pax_global_header00006660000000000000000000000064127027722760014526gustar00rootroot0000000000000052 comment=9d4818a437ce8bef56b265c7b80c9530db82734d lxd-2.0.0/000077500000000000000000000000001270277227600123145ustar00rootroot00000000000000lxd-2.0.0/.github/000077500000000000000000000000001270277227600136545ustar00rootroot00000000000000lxd-2.0.0/.github/ISSUE_TEMPLATE.md000066400000000000000000000013751270277227600163670ustar00rootroot00000000000000The template below is mostly useful for bug reports and support questions. Feel free to remove anything which doesn't apply to you and add more information where it makes sense. # Required information * Distribution: * Distribution version: * The output of "lxc info" or if that fails: * Kernel version: * LXC version: * LXD version: * Storage backend in use: # Issue description A brief description of what failed or what could be improved. # Steps to reproduce 1. Step one 2. Step two 3. Step three # Information to attach - [ ] any relevant kernel output (dmesg) - [ ] container log (lxc info NAME --show-log) - [ ] main daemon log (/var/log/lxd.log) - [ ] output of the client with --debug - [ ] output of the daemon with --debug lxd-2.0.0/.gitignore000066400000000000000000000001541270277227600143040ustar00rootroot00000000000000*.swp po/*.mo po/*.po~ lxd-*.tar.gz .vagrant test/deps/devlxd-client *~ tags # For Atom ctags .tags .tags1 lxd-2.0.0/.travis.yml000066400000000000000000000005211270277227600144230ustar00rootroot00000000000000language: go os: - osx go: - 1.5 - 1.6 - tip matrix: fast_finish: true allow_failures: - go: tip install: - "mkdir -p $GOPATH/github.com/lxc" - "rsync -az ${TRAVIS_BUILD_DIR}/ $HOME/gopath/src/github.com/lxc/lxd/" script: - "make client" notifications: webhooks: https://linuxcontainers.org/webhook-lxcbot/ lxd-2.0.0/AUTHORS000066400000000000000000000003631270277227600133660ustar00rootroot00000000000000Unless mentioned otherwise in a specific file's header, all code in this project is released under the Apache 2.0 license. The list of authors and contributors can be retrieved from the git commit history and in some cases, the file headers. lxd-2.0.0/CONTRIBUTING.md000066400000000000000000000051051270277227600145460ustar00rootroot00000000000000# Pull requests: Changes to this project should be proposed as pull requests on Github at: https://github.com/lxc/lxd Proposed changes will then go through code review there and once acked, be merged in the main branch. # License and copyright: By default, any contribution to this project is made under the Apache 2.0 license. The author of a change remains the copyright holder of their code (no copyright assignment). # Developer Certificate of Origin: To improve tracking of contributions to this project we use the DCO 1.1 and use a "sign-off" procedure for all changes going into the branch. The sign-off is a simple line at the end of the explanation for the commit which certifies that you wrote it or otherwise have the right to pass it on as an open-source contribution. > Developer Certificate of Origin > Version 1.1 > > Copyright (C) 2004, 2006 The Linux Foundation and its contributors. > 660 York Street, Suite 102, > San Francisco, CA 94110 USA > > Everyone is permitted to copy and distribute verbatim copies of this > license document, but changing it is not allowed. > > Developer's Certificate of Origin 1.1 > > By making a contribution to this project, I certify that: > > (a) The contribution was created in whole or in part by me and I > have the right to submit it under the open source license > indicated in the file; or > > (b) The contribution is based upon previous work that, to the best > of my knowledge, is covered under an appropriate open source > license and I have the right under that license to submit that > work with modifications, whether created in whole or in part > by me, under the same open source license (unless I am > permitted to submit under a different license), as indicated > in the file; or > > (c) The contribution was provided directly to me by some other > person who certified (a), (b) or (c) and I have not modified > it. > > (d) I understand and agree that this project and the contribution > are public and that a record of the contribution (including all > personal information I submit with it, including my sign-off) is > maintained indefinitely and may be redistributed consistent with > this project or the open source license(s) involved. An example of a valid sign-off line is: Signed-off-by: Random J Developer Use your real name and a valid e-mail address. Sorry, no pseudonyms or anonymous contributions are allowed. We also require each commit be individually signed-off by their author, even when part of a larger set. You may find `git commit -s` useful. lxd-2.0.0/COPYING000066400000000000000000000261361270277227600133570ustar00rootroot00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. lxd-2.0.0/Makefile000066400000000000000000000052511270277227600137570ustar00rootroot00000000000000DOMAIN=lxd POFILES=$(wildcard po/*.po) MOFILES=$(patsubst %.po,%.mo,$(POFILES)) LINGUAS=$(basename $(POFILES)) POTFILE=po/$(DOMAIN).pot # dist is primarily for use when packaging; for development we still manage # dependencies via `go get` explicitly. # TODO: use git describe for versioning VERSION=$(shell grep "var Version" shared/flex.go | cut -d'"' -f2) ARCHIVE=lxd-$(VERSION).tar .PHONY: default default: # Must run twice due to go get race -go get -t -v -d ./... -go get -t -v -d ./... go install -v $(DEBUG) ./... @echo "LXD built successfully" .PHONY: client client: # Must run twice due to go get race -go get -t -v -d ./... -go get -t -v -d ./... go install -v $(DEBUG) ./lxc @echo "LXD client built successfully" .PHONY: update update: # Must run twice due to go get race -go get -t -v -d -u ./... go get -t -v -d -u ./... @echo "Dependencies updated" # This only needs to be done when migrate.proto is actually changed; since we # commit the .pb.go in the tree and it's not expected to change very often, # it's not a default build step. .PHONY: protobuf protobuf: protoc --go_out=. ./lxd/migrate.proto .PHONY: check check: default go get -v -x github.com/remyoudompheng/go-misc/deadcode go test -v ./... cd test && ./main.sh gccgo: go build -compiler gccgo ./... @echo "LXD built successfully with gccgo" .PHONY: dist dist: rm -Rf lxd-$(VERSION) $(ARCHIVE) $(ARCHIVE).gz mkdir -p lxd-$(VERSION)/dist -GOPATH=$(shell pwd)/lxd-$(VERSION)/dist go get -t -v -d ./... GOPATH=$(shell pwd)/lxd-$(VERSION)/dist go get -t -v -d ./... rm -rf $(shell pwd)/lxd-$(VERSION)/dist/src/github.com/lxc/lxd ln -s ../../../.. ./lxd-$(VERSION)/dist/src/github.com/lxc/lxd git archive --prefix=lxd-$(VERSION)/ --output=$(ARCHIVE) HEAD tar -uf $(ARCHIVE) --exclude-vcs lxd-$(VERSION)/ gzip -9 $(ARCHIVE) rm -Rf dist lxd-$(VERSION) $(ARCHIVE) .PHONY: i18n update-po update-pot build-mo static-analysis i18n: update-pot po/%.mo: po/%.po msgfmt --statistics -o $@ $< po/%.po: po/$(DOMAIN).pot msgmerge -U po/$*.po po/$(DOMAIN).pot update-po: -for lang in $(LINGUAS); do\ msgmerge -U $$lang.po po/$(DOMAIN).pot; \ rm -f $$lang.po~; \ done update-pot: go get -v -x github.com/ubuntu-core/snappy/i18n/xgettext-go/ xgettext-go -o po/$(DOMAIN).pot --add-comments-tag=TRANSLATORS: --sort-output --package-name=$(DOMAIN) --msgid-bugs-address=lxc-devel@lists.linuxcontainers.org --keyword=i18n.G --keyword-plural=i18n.NG *.go shared/*.go lxc/*.go lxd/*.go build-mo: $(MOFILES) static-analysis: /bin/bash -x -c ". test/static_analysis.sh; static_analysis" tags: *.go lxd/*.go shared/*.go lxc/*.go find . | grep \.go | grep -v git | grep -v .swp | grep -v vagrant | xargs gotags > tags lxd-2.0.0/README.md000066400000000000000000000225421270277227600136000ustar00rootroot00000000000000# LXD REST API, command line tool and OpenStack integration plugin for LXC. LXD is pronounced lex-dee. To easily see what LXD is about, you can [try it online](https://linuxcontainers.org/lxd/try-it). ## CI status * Travis: [![Build Status](https://travis-ci.org/lxc/lxd.svg?branch=master)](https://travis-ci.org/lxc/lxd) * Jenkins: [![Build Status](https://jenkins.linuxcontainers.org/job/lxd-github-commit/badge/icon)](https://jenkins.linuxcontainers.org/job/lxd-github-commit/) ## Getting started with LXD Since LXD development is happening at such a rapid pace, we only provide daily builds right now. They're available via: sudo add-apt-repository ppa:ubuntu-lxc/lxd-git-master && sudo apt-get update sudo apt-get install lxd Because group membership is only applied at login, you then either need to close and re-open your user session or use the "newgrp lxd" command in the shell you're going to interact with lxd from. newgrp lxd After you've got LXD installed and a session with the right permissions, you can take your [first steps](#first-steps). ## Building from source We recommend having the latest versions of liblxc (>= 1.1 required) and CRIU (>= 1.7 recommended) available for LXD development. Additionally, LXD requires Golang 1.5 or later to work. All the right versions dependencies are available via the LXD PPA: sudo apt-get install software-properties-common sudo add-apt-repository ppa:ubuntu-lxc/lxd-git-master sudo apt-get update sudo apt-get install golang lxc lxc-dev mercurial git pkg-config protobuf-compiler golang-goprotobuf-dev xz-utils tar acl make There are a few storage backends for LXD besides the default "directory" backend. Installing these tools adds a bit to initramfs and may slow down your host boot, but are needed if you'd like to use a particular backend: sudo apt-get install lvm2 thin-provisioning-tools sudo apt-get install btrfs-tools To run the testsuite, you'll also need: sudo apt-get install curl gettext jq sqlite3 uuid-runtime pyflakes pep8 shellcheck bzr ### Building the tools LXD consists of two binaries, a client called `lxc` and a server called `lxd`. These live in the source tree in the `lxc/` and `lxd/` dirs, respectively. To get the code, set up your go environment: mkdir -p ~/go export GOPATH=~/go And then download it as usual: go get github.com/lxc/lxd cd $GOPATH/src/github.com/lxc/lxd make ...which will give you two binaries in $GOPATH/bin, `lxd` the daemon binary, and `lxc` a command line client to that daemon. ### Machine Setup You'll need sub{u,g}ids for root, so that LXD can create the unprivileged containers: echo "root:1000000:65536" | sudo tee -a /etc/subuid /etc/subgid Now you can run the daemon (the --group sudo bit allows everyone in the sudo group to talk to LXD; you can create your own group if you want): sudo -E $GOPATH/bin/lxd --group sudo ## First steps LXD has two parts, the daemon (the `lxd` binary), and the client (the `lxc` binary). Now that the daemon is all configured and running (either via the packaging or via the from-source instructions above), you can create a container: $GOPATH/bin/lxc launch ubuntu:14.04 Alternatively, you can also use a remote LXD host as a source of images. One comes pre-configured in LXD, called "images" (images.linuxcontainers.org) $GOPATH/bin/lxc launch images:centos/7/amd64 centos ## Bug reports Bug reports can be filed at https://github.com/lxc/lxd/issues/new ## Contributing Fixes and new features are greatly appreciated but please read our [contributing guidelines](CONTRIBUTING.md) first. Contributions to this project should be sent as pull requests on github. ## Hacking Sometimes it is useful to view the raw response that LXD sends; you can do this by: lxc config set core.trust_password foo lxc remote add local 127.0.0.1:8443 wget --no-check-certificate https://127.0.0.1:8443/1.0 --certificate=$HOME/.config/lxc/client.crt --private-key=$HOME/.config/lxc/client.key -O - -q ## Upgrading The `lxd` and `lxc` (`lxd-client`) binaries should be upgraded at the same time with: apt-get update apt-get install lxd lxd-client ## Support and discussions We use the LXC mailing-lists for developer and user discussions, you can find and subscribe to those at: https://lists.linuxcontainers.org If you prefer live discussions, some of us also hang out in [#lxcontainers](http://webchat.freenode.net/?channels=#lxcontainers) on irc.freenode.net. ## FAQ #### How to enable LXD server for remote access? By default LXD server is not accessible from the networks as it only listens on a local unix socket. You can make LXD available from the network by specifying additional addresses to listen to. This is done with the `core.https_address` config variable. To see the current server configuration, run: lxc config show To set the address to listen to, find out what addresses are available and use the `config set` command on the server: ip addr lxc config set core.https_address 192.168.1.15 #### When I do a `lxc remote add` over https, it asks for a password? By default, LXD has no password for security reasons, so you can't do a remote add this way. In order to set a password, do: lxc config set core.trust_password SECRET on the host LXD is running on. This will set the remote password that you can then use to do `lxc remote add`. You can also access the server without setting a password by copying the client certificate from `.config/lxc/client.crt` to the server and adding it with: lxc config trust add client.crt #### How do I configure alternative storage backends for LXD? LXD supports various storage backends; below are instructions on how to configure some of them. By default, we use a simple directory backed storage mechanism, but we recommend using ZFS for best results. ###### ZFS First, you need to install the ZFS tooling. On Wily and above this is just: sudo apt-get install zfsutils-linux ZFS has many different ways to procure a zpool, which is what you need to feed LXD. For example, if you have an extra block device laying around, you can just: sudo zpool create lxd /dev/sdc6 -m none However, if you want to test things out on a laptop or don't have an extra disk laying around, ZFS has its own loopback driver and can be used directly on a (sparse) file. To do this, first create the sparse file: sudo truncate -s 100G /var/lib/lxd.img then, sudo zpool create lxd /var/lib/lxd.img -m none Finally, whichever method you used to create your zpool, you need to tell LXD to use it: lxc config set storage.zfs_pool_name lxd ###### BTRFS The setup for btrfs is fairly simple, just mount /var/lib/lxd (or whatever your chosen `LXD_DIR` is) as a btrfs filesystem before you start LXD, and you're good to go. First install the btrfs userspace tools, sudo apt-get install btrfs-tools Now, you need to create a btrfs filesystem. If you don't have an extra disk laying around, you'll have to create your own loopback device manually: sudo truncate -s 100G /var/lib/lxd.img sudo losetup /dev/loop0 /var/lib/lxd.img Once you've got a loopback device (or an actual device), you can create the btrfs filesystem and mount it: sudo mkfs.btrfs /dev/loop0 # or your real device sudo mount /dev/loop0 /var/lib/lxd ###### LVM To set up LVM, the instructions are similar to the above. First, install the userspace tools: sudo apt-get install lvm2 thin-provisioning-tools Then, if you have a block device laying around: sudo pvcreate /dev/sdc6 sudo vgcreate lxd /dev/sdc6 lxc config set storage.lvm_vg_name lxd Alternatively, if you want to try it via a loopback device, there is a script provided in [/scripts/lxd-setup-lvm-storage](https://raw.githubusercontent.com/lxc/lxd/master/scripts/lxd-setup-lvm-storage) which will do it for you. It can be run via: sudo apt-get install lvm2 ./scripts/lxd-setup-lvm-storage -s 10G And it has a --destroy argument to clean up the bits as well: ./scripts/lxd-setup-lvm-storage --destroy #### How can I live migrate a container using LXD? Live migration requires a tool installed on both hosts called [CRIU](http://criu.org), which is available in Ubuntu via: sudo apt-get install criu Then, launch your container with the following, lxc launch ubuntu $somename sleep 5s # let the container get to an interesting state lxc move host1:$somename host2:$somename And with luck you'll have migrated the container :). Migration is still in experimental stages and may not work for all workloads. Please report bugs on lxc-devel, and we can escalate to CRIU lists as necessary. #### Can I bind mount my home directory in a container? Yes. The easiest way to do that is using a privileged container: lxc launch ubuntu priv -c security.privileged=true lxc config device add priv homedir disk source=/home/$USER path=/home/ubuntu #### How can I run docker inside a LXD container? To run docker inside a lxd container, you must be running a kernel with cgroup namespaces (Ubuntu 4.4 kernel or newer, or upstream 4.6 or newer), and must apply the docker profile to your container. lxc launch ubuntu:xenial my-docker-host -p default -p docker Note that the docker profile does not provide a network interface, so the common case will want to compose the default and docker profiles. The container must be using the Ubuntu 1.10.2-0ubuntu4 or newer docker package. lxd-2.0.0/Vagrantfile000066400000000000000000000011651270277227600145040ustar00rootroot00000000000000Vagrant.configure('2') do |config| # grab Ubuntu 14.04 boxcutter image: https://atlas.hashicorp.com/boxcutter config.vm.box = "boxcutter/ubuntu1404" # Ubuntu 14.04 # fix issues with slow dns https://www.virtualbox.org/ticket/13002 config.vm.provider :virtualbox do |vb, override| vb.customize ["modifyvm", :id, "--natdnsproxy1", "off"] end config.vm.network "forwarded_port", guest: 443, host: 8443 config.vm.provision :shell, :privileged => false, :path => "scripts/vagrant/install-go.sh" config.vm.provision :shell, :privileged => false, :path => "scripts/vagrant/install-lxd.sh" end lxd-2.0.0/client.go000066400000000000000000001504061270277227600141270ustar00rootroot00000000000000package lxd import ( "bytes" "crypto/x509" "encoding/base64" "encoding/json" "encoding/pem" "fmt" "io" "io/ioutil" "mime" "mime/multipart" "net" "net/http" "net/url" "os" "path" "path/filepath" "strconv" "strings" "github.com/gorilla/websocket" "github.com/lxc/lxd/shared" ) // Client can talk to a LXD daemon. type Client struct { BaseURL string BaseWSURL string Config Config Name string Remote *RemoteConfig Transport string Certificate string Http http.Client websocketDialer websocket.Dialer simplestreams *shared.SimpleStreams } type ResponseType string const ( Sync ResponseType = "sync" Async ResponseType = "async" Error ResponseType = "error" ) var ( // LXDErrors are special errors; the client library hoists error codes // to these errors internally so that user code can compare against // them. We probably shouldn't hoist BadRequest or InternalError, since // LXD passes an error string along which is more informative than // whatever static error message we would put here. LXDErrors = map[int]error{ http.StatusNotFound: fmt.Errorf("not found"), } ) type Response struct { Type ResponseType `json:"type"` /* Valid only for Sync responses */ Status string `json:"status"` StatusCode int `json:"status_code"` /* Valid only for Async responses */ Operation string `json:"operation"` /* Valid only for Error responses */ Code int `json:"error_code"` Error string `json:"error"` /* Valid for Sync and Error responses */ Metadata json.RawMessage `json:"metadata"` } func (r *Response) MetadataAsMap() (*shared.Jmap, error) { ret := shared.Jmap{} if err := json.Unmarshal(r.Metadata, &ret); err != nil { return nil, err } return &ret, nil } func (r *Response) MetadataAsOperation() (*shared.Operation, error) { op := shared.Operation{} if err := json.Unmarshal(r.Metadata, &op); err != nil { return nil, err } return &op, nil } // ParseResponse parses a lxd style response out of an http.Response. Note that // this does _not_ automatically convert error responses to golang errors. To // do that, use ParseError. Internal client library uses should probably use // HoistResponse, unless they are interested in accessing the underlying Error // response (e.g. to inspect the error code). func ParseResponse(r *http.Response) (*Response, error) { if r == nil { return nil, fmt.Errorf("no response!") } defer r.Body.Close() ret := Response{} s, err := ioutil.ReadAll(r.Body) if err != nil { return nil, err } shared.Debugf("Raw response: %s", string(s)) if err := json.Unmarshal(s, &ret); err != nil { return nil, err } return &ret, nil } // HoistResponse hoists a regular http response into a response of type rtype // or returns a golang error. func HoistResponse(r *http.Response, rtype ResponseType) (*Response, error) { resp, err := ParseResponse(r) if err != nil { return nil, err } if resp.Type == Error { // Try and use a known error if we have one for this code. err, ok := LXDErrors[resp.Code] if !ok { return nil, fmt.Errorf(resp.Error) } return nil, err } if resp.Type != rtype { return nil, fmt.Errorf("got bad response type, expected %s got %s", rtype, resp.Type) } return resp, nil } // NewClient returns a new LXD client. func NewClient(config *Config, remote string) (*Client, error) { if remote == "" { return nil, fmt.Errorf("A remote name must be provided.") } r, ok := config.Remotes[remote] if !ok { return nil, fmt.Errorf("unknown remote name: %q", remote) } info := ConnectInfo{ Name: remote, RemoteConfig: r, } if strings.HasPrefix(r.Addr, "unix:") { // replace "unix://" with the official "unix:/var/lib/lxd/unix.socket" if info.RemoteConfig.Addr == "unix://" { info.RemoteConfig.Addr = fmt.Sprintf("unix:%s", shared.VarPath("unix.socket")) } } else { // Read the client certificate (if it exists) clientCertPath := path.Join(config.ConfigDir, "client.crt") if shared.PathExists(clientCertPath) { certBytes, err := ioutil.ReadFile(clientCertPath) if err != nil { return nil, err } info.ClientPEMCert = string(certBytes) } // Read the client key (if it exists) clientKeyPath := path.Join(config.ConfigDir, "client.key") if shared.PathExists(clientKeyPath) { keyBytes, err := ioutil.ReadFile(clientKeyPath) if err != nil { return nil, err } info.ClientPEMKey = string(keyBytes) } // Read the server certificate (if it exists) serverCertPath := config.ServerCertPath(remote) if shared.PathExists(serverCertPath) { cert, err := shared.ReadCert(serverCertPath) if err != nil { return nil, err } info.ServerPEMCert = string(pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: cert.Raw})) } } c, err := NewClientFromInfo(info) if err != nil { return nil, err } c.Config = *config return c, nil } // ConnectInfo contains the information we need to connect to a specific LXD server type ConnectInfo struct { // Name is a simple identifier for the remote server. In 'lxc' it is // the name used to lookup the address and other information in the // config.yml file. Name string // RemoteConfig is the information about the Remote that we are // connecting to. This includes information like if the remote is // Public and/or Static. RemoteConfig RemoteConfig // ClientPEMCert is the PEM encoded bytes of the client's certificate. // If Addr indicates a Unix socket, the certificate and key bytes will // not be used. ClientPEMCert string // ClientPEMKey is the PEM encoded private bytes of the client's key associated with its certificate ClientPEMKey string // ServerPEMCert is the PEM encoded server certificate that we are // connecting to. It can be the empty string if we do not know the // server's certificate yet. ServerPEMCert string } func connectViaUnix(c *Client, remote *RemoteConfig) error { c.BaseURL = "http://unix.socket" c.BaseWSURL = "ws://unix.socket" c.Transport = "unix" uDial := func(network, addr string) (net.Conn, error) { // The arguments 'network' and 'addr' are ignored because // they are the wrong information. // addr is generated from BaseURL which becomes // 'unix.socket:80' which is certainly not what we want. // handle: // unix:///path/to/socket // unix:/path/to/socket // unix:path/to/socket path := strings.TrimPrefix(remote.Addr, "unix:") if strings.HasPrefix(path, "///") { // translate unix:///path/to, to just "/path/to" path = path[2:] } raddr, err := net.ResolveUnixAddr("unix", path) if err != nil { return nil, err } return net.DialUnix("unix", nil, raddr) } c.Http.Transport = &http.Transport{Dial: uDial} c.websocketDialer.NetDial = uDial c.Remote = remote st, err := c.ServerStatus() if err != nil { return err } c.Certificate = st.Environment.Certificate return nil } func connectViaHttp(c *Client, remote *RemoteConfig, clientCert, clientKey, serverCert string) error { tlsconfig, err := shared.GetTLSConfigMem(clientCert, clientKey, serverCert) if err != nil { return err } tr := &http.Transport{ TLSClientConfig: tlsconfig, Dial: shared.RFC3493Dialer, Proxy: shared.ProxyFromEnvironment, } c.websocketDialer.NetDial = shared.RFC3493Dialer c.websocketDialer.TLSClientConfig = tlsconfig justAddr := strings.TrimPrefix(remote.Addr, "https://") c.BaseURL = "https://" + justAddr c.BaseWSURL = "wss://" + justAddr c.Transport = "https" c.Http.Transport = tr c.Remote = remote c.Certificate = serverCert // We don't actually need to connect yet, defer that until someone // needs something from the server. return nil } // NewClientFromInfo returns a new LXD client. func NewClientFromInfo(info ConnectInfo) (*Client, error) { c := &Client{ // Config: *config, Http: http.Client{}, Config: Config{ Remotes: DefaultRemotes, Aliases: map[string]string{}, }, } c.Name = info.Name var err error if strings.HasPrefix(info.RemoteConfig.Addr, "unix:") { err = connectViaUnix(c, &info.RemoteConfig) } else { err = connectViaHttp(c, &info.RemoteConfig, info.ClientPEMCert, info.ClientPEMKey, info.ServerPEMCert) } if err != nil { return nil, err } if info.RemoteConfig.Protocol == "simplestreams" { ss, err := shared.SimpleStreamsClient(c.Remote.Addr, shared.ProxyFromEnvironment) if err != nil { return nil, err } c.simplestreams = ss } return c, nil } func (c *Client) Addresses() ([]string, error) { addresses := make([]string, 0) if c.Transport == "unix" { serverStatus, err := c.ServerStatus() if err != nil { return nil, err } addresses = serverStatus.Environment.Addresses } else if c.Transport == "https" { addresses = append(addresses, c.BaseURL[8:]) } else { return nil, fmt.Errorf("unknown transport type: %s", c.Transport) } if len(addresses) == 0 { return nil, fmt.Errorf("The source remote isn't available over the network") } return addresses, nil } func (c *Client) get(base string) (*Response, error) { uri := c.url(shared.APIVersion, base) return c.baseGet(uri) } func (c *Client) baseGet(getUrl string) (*Response, error) { req, err := http.NewRequest("GET", getUrl, nil) if err != nil { return nil, err } req.Header.Set("User-Agent", shared.UserAgent) resp, err := c.Http.Do(req) if err != nil { return nil, err } return HoistResponse(resp, Sync) } func (c *Client) put(base string, args interface{}, rtype ResponseType) (*Response, error) { uri := c.url(shared.APIVersion, base) buf := bytes.Buffer{} err := json.NewEncoder(&buf).Encode(args) if err != nil { return nil, err } shared.Debugf("Putting %s to %s", buf.String(), uri) req, err := http.NewRequest("PUT", uri, &buf) if err != nil { return nil, err } req.Header.Set("User-Agent", shared.UserAgent) req.Header.Set("Content-Type", "application/json") resp, err := c.Http.Do(req) if err != nil { return nil, err } return HoistResponse(resp, rtype) } func (c *Client) post(base string, args interface{}, rtype ResponseType) (*Response, error) { uri := c.url(shared.APIVersion, base) buf := bytes.Buffer{} err := json.NewEncoder(&buf).Encode(args) if err != nil { return nil, err } shared.Debugf("Posting %s to %s", buf.String(), uri) req, err := http.NewRequest("POST", uri, &buf) if err != nil { return nil, err } req.Header.Set("User-Agent", shared.UserAgent) req.Header.Set("Content-Type", "application/json") resp, err := c.Http.Do(req) if err != nil { return nil, err } return HoistResponse(resp, rtype) } func (c *Client) getRaw(uri string) (*http.Response, error) { req, err := http.NewRequest("GET", uri, nil) if err != nil { return nil, err } req.Header.Set("User-Agent", shared.UserAgent) raw, err := c.Http.Do(req) if err != nil { return nil, err } // because it is raw data, we need to check for http status if raw.StatusCode != 200 { resp, err := HoistResponse(raw, Sync) if err != nil { return nil, err } return nil, fmt.Errorf("expected error, got %v", *resp) } return raw, nil } func (c *Client) delete(base string, args interface{}, rtype ResponseType) (*Response, error) { uri := c.url(shared.APIVersion, base) buf := bytes.Buffer{} err := json.NewEncoder(&buf).Encode(args) if err != nil { return nil, err } shared.Debugf("Deleting %s to %s", buf.String(), uri) req, err := http.NewRequest("DELETE", uri, &buf) if err != nil { return nil, err } req.Header.Set("User-Agent", shared.UserAgent) req.Header.Set("Content-Type", "application/json") resp, err := c.Http.Do(req) if err != nil { return nil, err } return HoistResponse(resp, rtype) } func (c *Client) websocket(operation string, secret string) (*websocket.Conn, error) { query := url.Values{"secret": []string{secret}} url := c.BaseWSURL + path.Join(operation, "websocket") + "?" + query.Encode() return WebsocketDial(c.websocketDialer, url) } func (c *Client) url(elem ...string) string { path := strings.Join(elem, "/") uri := c.BaseURL + "/" + path if strings.HasPrefix(path, "1.0/images/aliases") { return uri } if strings.Contains(path, "?") { return uri } return strings.TrimSuffix(uri, "/") } func (c *Client) GetServerConfig() (*Response, error) { if c.Remote.Protocol == "simplestreams" { return nil, fmt.Errorf("This function isn't supported by simplestreams remote.") } return c.baseGet(c.url(shared.APIVersion)) } func (c *Client) AmTrusted() bool { resp, err := c.GetServerConfig() if err != nil { return false } shared.Debugf("%s", resp) jmap, err := resp.MetadataAsMap() if err != nil { return false } auth, err := jmap.GetString("auth") if err != nil { return false } return auth == "trusted" } func (c *Client) IsPublic() bool { resp, err := c.GetServerConfig() if err != nil { return false } shared.Debugf("%s", resp) jmap, err := resp.MetadataAsMap() if err != nil { return false } public, err := jmap.GetBool("public") if err != nil { return false } return public } func (c *Client) ListContainers() ([]shared.ContainerInfo, error) { if c.Remote.Public { return nil, fmt.Errorf("This function isn't supported by public remotes.") } resp, err := c.get("containers?recursion=1") if err != nil { return nil, err } var result []shared.ContainerInfo if err := json.Unmarshal(resp.Metadata, &result); err != nil { return nil, err } return result, nil } func (c *Client) CopyImage(image string, dest *Client, copy_aliases bool, aliases []string, public bool, autoUpdate bool, progressHandler func(progress string)) error { source := shared.Jmap{ "type": "image", "mode": "pull", "server": c.BaseURL, "protocol": c.Remote.Protocol, "certificate": c.Certificate, "fingerprint": image} target := c.GetAlias(image) if target != "" { image = target } info, err := c.GetImageInfo(image) if err != nil { return err } if c.Remote.Protocol != "simplestreams" { if !info.Public { var secret string resp, err := c.post("images/"+image+"/secret", nil, Async) if err != nil { return err } op, err := resp.MetadataAsOperation() if err != nil { return err } secret, err = op.Metadata.GetString("secret") if err != nil { return err } source["secret"] = secret } source["fingerprint"] = image } addresses, err := c.Addresses() if err != nil { return err } operation := "" handler := func(msg interface{}) { if msg == nil { return } event := msg.(map[string]interface{}) if event["type"].(string) != "operation" { return } if event["metadata"] == nil { return } md := event["metadata"].(map[string]interface{}) if !strings.HasSuffix(operation, md["id"].(string)) { return } if md["metadata"] == nil { return } opMd := md["metadata"].(map[string]interface{}) _, ok := opMd["download_progress"] if ok { progressHandler(opMd["download_progress"].(string)) } } if progressHandler != nil { go dest.Monitor([]string{"operation"}, handler) } for _, addr := range addresses { sourceUrl := "https://" + addr source["server"] = sourceUrl body := shared.Jmap{"public": public, "auto_update": autoUpdate, "source": source} resp, err := dest.post("images", body, Async) if err != nil { continue } operation = resp.Operation err = dest.WaitForSuccess(resp.Operation) if err != nil { return err } break } if err != nil { return err } /* copy aliases from source image */ if copy_aliases { for _, alias := range info.Aliases { dest.DeleteAlias(alias.Name) err = dest.PostAlias(alias.Name, alias.Description, info.Fingerprint) if err != nil { return fmt.Errorf("Error adding alias %s: %s", alias.Name, err) } } } /* add new aliases */ for _, alias := range aliases { dest.DeleteAlias(alias) err = dest.PostAlias(alias, alias, info.Fingerprint) if err != nil { return fmt.Errorf("Error adding alias %s: %s\n", alias, err) } } return err } func (c *Client) ExportImage(image string, target string) (string, error) { if c.Remote.Protocol == "simplestreams" && c.simplestreams != nil { return c.simplestreams.ExportImage(image, target) } uri := c.url(shared.APIVersion, "images", image, "export") raw, err := c.getRaw(uri) if err != nil { return "", err } ctype, ctypeParams, err := mime.ParseMediaType(raw.Header.Get("Content-Type")) if err != nil { ctype = "application/octet-stream" } // Deal with split images if ctype == "multipart/form-data" { if !shared.IsDir(target) { return "", fmt.Errorf("Split images can only be written to a directory.") } // Parse the POST data mr := multipart.NewReader(raw.Body, ctypeParams["boundary"]) // Get the metadata tarball part, err := mr.NextPart() if err != nil { return "", err } if part.FormName() != "metadata" { return "", fmt.Errorf("Invalid multipart image") } imageTarf, err := os.OpenFile(filepath.Join(target, part.FileName()), os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600) if err != nil { return "", err } _, err = io.Copy(imageTarf, part) imageTarf.Close() if err != nil { return "", err } // Get the rootfs tarball part, err = mr.NextPart() if err != nil { return "", err } if part.FormName() != "rootfs" { return "", fmt.Errorf("Invalid multipart image") } rootfsTarf, err := os.OpenFile(filepath.Join(part.FileName()), os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600) if err != nil { return "", err } _, err = io.Copy(rootfsTarf, part) rootfsTarf.Close() if err != nil { return "", err } return target, nil } // Deal with unified images var wr io.Writer var destpath string if target == "-" { wr = os.Stdout destpath = "stdout" } else if fi, err := os.Stat(target); err == nil { // file exists, so check if folder switch mode := fi.Mode(); { case mode.IsDir(): // save in directory, header content-disposition can not be null // and will have a filename cd := strings.Split(raw.Header["Content-Disposition"][0], "=") // write filename from header destpath = filepath.Join(target, cd[1]) f, err := os.Create(destpath) defer f.Close() if err != nil { return "", err } wr = f default: // overwrite file destpath = target f, err := os.OpenFile(destpath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600) defer f.Close() if err != nil { return "", err } wr = f } } else { // write as simple file destpath = target f, err := os.Create(destpath) defer f.Close() wr = f if err != nil { return "", err } } _, err = io.Copy(wr, raw.Body) if err != nil { return "", err } // it streams to stdout or file, so no response returned return destpath, nil } func (c *Client) PostImageURL(imageFile string, public bool, aliases []string) (string, error) { if c.Remote.Public { return "", fmt.Errorf("This function isn't supported by public remotes.") } source := shared.Jmap{ "type": "url", "mode": "pull", "url": imageFile} body := shared.Jmap{"public": public, "source": source} resp, err := c.post("images", body, Async) if err != nil { return "", err } op, err := c.WaitFor(resp.Operation) if err != nil { return "", err } if op.Metadata == nil { return "", fmt.Errorf("Missing operation metadata") } fingerprint, err := op.Metadata.GetString("fingerprint") if err != nil { return "", err } /* add new aliases */ for _, alias := range aliases { c.DeleteAlias(alias) err = c.PostAlias(alias, alias, fingerprint) if err != nil { return "", fmt.Errorf("Error adding alias %s: %s", alias, err) } } return fingerprint, nil } func (c *Client) PostImage(imageFile string, rootfsFile string, properties []string, public bool, aliases []string, progressHandler func(percent int)) (string, error) { if c.Remote.Public { return "", fmt.Errorf("This function isn't supported by public remotes.") } uri := c.url(shared.APIVersion, "images") var err error var fImage *os.File var fRootfs *os.File var req *http.Request if rootfsFile != "" { fImage, err = os.Open(imageFile) if err != nil { return "", err } defer fImage.Close() fRootfs, err = os.Open(rootfsFile) if err != nil { return "", err } defer fRootfs.Close() body, err := ioutil.TempFile("", "lxc_image_") if err != nil { return "", err } defer os.Remove(body.Name()) w := multipart.NewWriter(body) // Metadata file fw, err := w.CreateFormFile("metadata", path.Base(imageFile)) if err != nil { return "", err } _, err = io.Copy(fw, fImage) if err != nil { return "", err } // Rootfs file fw, err = w.CreateFormFile("rootfs", path.Base(rootfsFile)) if err != nil { return "", err } _, err = io.Copy(fw, fRootfs) if err != nil { return "", err } w.Close() size, err := body.Seek(0, 2) if err != nil { return "", err } _, err = body.Seek(0, 0) if err != nil { return "", err } progress := &shared.TransferProgress{Reader: body, Length: size, Handler: progressHandler} req, err = http.NewRequest("POST", uri, progress) req.Header.Set("Content-Type", w.FormDataContentType()) } else { fImage, err = os.Open(imageFile) if err != nil { return "", err } defer fImage.Close() stat, err := fImage.Stat() if err != nil { return "", err } progress := &shared.TransferProgress{Reader: fImage, Length: stat.Size(), Handler: progressHandler} req, err = http.NewRequest("POST", uri, progress) req.Header.Set("X-LXD-filename", filepath.Base(imageFile)) req.Header.Set("Content-Type", "application/octet-stream") } if err != nil { return "", err } req.Header.Set("User-Agent", shared.UserAgent) if public { req.Header.Set("X-LXD-public", "1") } else { req.Header.Set("X-LXD-public", "0") } if len(properties) != 0 { imgProps := url.Values{} for _, value := range properties { eqIndex := strings.Index(value, "=") // props must be in key=value format // if not, request will not be accepted if eqIndex > -1 { imgProps.Set(value[:eqIndex], value[eqIndex+1:]) } else { return "", fmt.Errorf("Bad image property: %s", value) } } req.Header.Set("X-LXD-properties", imgProps.Encode()) } raw, err := c.Http.Do(req) if err != nil { return "", err } resp, err := HoistResponse(raw, Async) if err != nil { return "", err } jmap, err := c.AsyncWaitMeta(resp) if err != nil { return "", err } fingerprint, err := jmap.GetString("fingerprint") if err != nil { return "", err } /* add new aliases */ for _, alias := range aliases { c.DeleteAlias(alias) err = c.PostAlias(alias, alias, fingerprint) if err != nil { return "", fmt.Errorf("Error adding alias %s: %s", alias, err) } } return fingerprint, nil } func (c *Client) GetImageInfo(image string) (*shared.ImageInfo, error) { if c.Remote.Protocol == "simplestreams" && c.simplestreams != nil { return c.simplestreams.GetImageInfo(image) } resp, err := c.get(fmt.Sprintf("images/%s", image)) if err != nil { return nil, err } info := shared.ImageInfo{} if err := json.Unmarshal(resp.Metadata, &info); err != nil { return nil, err } return &info, nil } func (c *Client) PutImageInfo(name string, p shared.BriefImageInfo) error { if c.Remote.Public { return fmt.Errorf("This function isn't supported by public remotes.") } _, err := c.put(fmt.Sprintf("images/%s", name), p, Sync) return err } func (c *Client) ListImages() ([]shared.ImageInfo, error) { if c.Remote.Protocol == "simplestreams" && c.simplestreams != nil { return c.simplestreams.ListImages() } resp, err := c.get("images?recursion=1") if err != nil { return nil, err } var result []shared.ImageInfo if err := json.Unmarshal(resp.Metadata, &result); err != nil { return nil, err } return result, nil } func (c *Client) DeleteImage(image string) error { if c.Remote.Public { return fmt.Errorf("This function isn't supported by public remotes.") } resp, err := c.delete(fmt.Sprintf("images/%s", image), nil, Async) if err != nil { return err } return c.WaitForSuccess(resp.Operation) } func (c *Client) PostAlias(alias string, desc string, target string) error { if c.Remote.Public { return fmt.Errorf("This function isn't supported by public remotes.") } body := shared.Jmap{"description": desc, "target": target, "name": alias} _, err := c.post("images/aliases", body, Sync) return err } func (c *Client) DeleteAlias(alias string) error { if c.Remote.Public { return fmt.Errorf("This function isn't supported by public remotes.") } _, err := c.delete(fmt.Sprintf("images/aliases/%s", alias), nil, Sync) return err } func (c *Client) ListAliases() (shared.ImageAliases, error) { if c.Remote.Protocol == "simplestreams" && c.simplestreams != nil { return c.simplestreams.ListAliases() } resp, err := c.get("images/aliases?recursion=1") if err != nil { return nil, err } var result shared.ImageAliases if err := json.Unmarshal(resp.Metadata, &result); err != nil { return nil, err } return result, nil } func (c *Client) CertificateList() ([]shared.CertInfo, error) { if c.Remote.Public { return nil, fmt.Errorf("This function isn't supported by public remotes.") } resp, err := c.get("certificates?recursion=1") if err != nil { return nil, err } var result []shared.CertInfo if err := json.Unmarshal(resp.Metadata, &result); err != nil { return nil, err } return result, nil } func (c *Client) AddMyCertToServer(pwd string) error { if c.Remote.Public { return fmt.Errorf("This function isn't supported by public remotes.") } body := shared.Jmap{"type": "client", "password": pwd} _, err := c.post("certificates", body, Sync) return err } func (c *Client) CertificateAdd(cert *x509.Certificate, name string) error { if c.Remote.Public { return fmt.Errorf("This function isn't supported by public remotes.") } b64 := base64.StdEncoding.EncodeToString(cert.Raw) _, err := c.post("certificates", shared.Jmap{"type": "client", "certificate": b64, "name": name}, Sync) return err } func (c *Client) CertificateRemove(fingerprint string) error { if c.Remote.Public { return fmt.Errorf("This function isn't supported by public remotes.") } _, err := c.delete(fmt.Sprintf("certificates/%s", fingerprint), nil, Sync) return err } func (c *Client) IsAlias(alias string) (bool, error) { _, err := c.get(fmt.Sprintf("images/aliases/%s", alias)) if err != nil { if err == LXDErrors[http.StatusNotFound] { return false, nil } return false, err } return true, nil } func (c *Client) GetAlias(alias string) string { if c.Remote.Protocol == "simplestreams" && c.simplestreams != nil { return c.simplestreams.GetAlias(alias) } resp, err := c.get(fmt.Sprintf("images/aliases/%s", alias)) if err != nil { return "" } if resp.Type == Error { return "" } var result shared.ImageAliasesEntry if err := json.Unmarshal(resp.Metadata, &result); err != nil { return "" } return result.Target } // Init creates a container from either a fingerprint or an alias; you must // provide at least one. func (c *Client) Init(name string, imgremote string, image string, profiles *[]string, config map[string]string, ephem bool) (*Response, error) { if c.Remote.Public { return nil, fmt.Errorf("This function isn't supported by public remotes.") } var tmpremote *Client var err error serverStatus, err := c.ServerStatus() if err != nil { return nil, err } architectures := serverStatus.Environment.Architectures source := shared.Jmap{"type": "image"} if image == "" { image = "default" } if imgremote != c.Name { source["type"] = "image" source["mode"] = "pull" tmpremote, err = NewClient(&c.Config, imgremote) if err != nil { return nil, err } if tmpremote.Remote.Protocol != "simplestreams" { target := tmpremote.GetAlias(image) if target == "" { target = image } imageinfo, err := tmpremote.GetImageInfo(target) if err != nil { return nil, err } if len(architectures) != 0 && !shared.StringInSlice(imageinfo.Architecture, architectures) { return nil, fmt.Errorf("The image architecture is incompatible with the target server") } if !imageinfo.Public { var secret string image = target resp, err := tmpremote.post("images/"+image+"/secret", nil, Async) if err != nil { return nil, err } op, err := resp.MetadataAsOperation() if err != nil { return nil, err } secret, err = op.Metadata.GetString("secret") if err != nil { return nil, err } source["secret"] = secret } } source["server"] = tmpremote.BaseURL source["protocol"] = tmpremote.Remote.Protocol source["certificate"] = tmpremote.Certificate source["fingerprint"] = image } else { fingerprint := c.GetAlias(image) if fingerprint == "" { fingerprint = image } imageinfo, err := c.GetImageInfo(fingerprint) if err != nil { return nil, fmt.Errorf("can't get info for image '%s': %s", image, err) } if len(architectures) != 0 && !shared.StringInSlice(imageinfo.Architecture, architectures) { return nil, fmt.Errorf("The image architecture is incompatible with the target server") } source["fingerprint"] = fingerprint } body := shared.Jmap{"source": source} if name != "" { body["name"] = name } if profiles != nil { body["profiles"] = *profiles } if config != nil { body["config"] = config } if ephem { body["ephemeral"] = ephem } var resp *Response if imgremote != c.Name { var addresses []string addresses, err = tmpremote.Addresses() if err != nil { return nil, err } for _, addr := range addresses { body["source"].(shared.Jmap)["server"] = "https://" + addr resp, err = c.post("containers", body, Async) if err != nil { continue } break } } else { resp, err = c.post("containers", body, Async) } if err != nil { if LXDErrors[http.StatusNotFound] == err { return nil, fmt.Errorf("image doesn't exist") } return nil, err } return resp, nil } func (c *Client) LocalCopy(source string, name string, config map[string]string, profiles []string, ephemeral bool) (*Response, error) { if c.Remote.Public { return nil, fmt.Errorf("This function isn't supported by public remotes.") } body := shared.Jmap{ "source": shared.Jmap{ "type": "copy", "source": source, }, "name": name, "config": config, "profiles": profiles, "ephemeral": ephemeral, } return c.post("containers", body, Async) } func (c *Client) Monitor(types []string, handler func(interface{})) error { if c.Remote.Public { return fmt.Errorf("This function isn't supported by public remotes.") } url := c.BaseWSURL + path.Join("/", "1.0", "events") if len(types) != 0 { url += "?type=" + strings.Join(types, ",") } conn, err := WebsocketDial(c.websocketDialer, url) if err != nil { return err } defer conn.Close() for { message := make(map[string]interface{}) _, data, err := conn.ReadMessage() if err != nil { return err } err = json.Unmarshal(data, &message) if err != nil { return err } handler(message) } } // Exec runs a command inside the LXD container. For "interactive" use such as // `lxc exec ...`, one should pass a controlHandler that talks over the control // socket and handles things like SIGWINCH. If running non-interactive, passing // a nil controlHandler will cause Exec to return when all of the command // output is sent to the output buffers. func (c *Client) Exec(name string, cmd []string, env map[string]string, stdin io.ReadCloser, stdout io.WriteCloser, stderr io.WriteCloser, controlHandler func(*Client, *websocket.Conn), width int, height int) (int, error) { if c.Remote.Public { return -1, fmt.Errorf("This function isn't supported by public remotes.") } body := shared.Jmap{ "command": cmd, "wait-for-websocket": true, "interactive": controlHandler != nil, "environment": env, } if width > 0 && height > 0 { body["width"] = width body["height"] = height } resp, err := c.post(fmt.Sprintf("containers/%s/exec", name), body, Async) if err != nil { return -1, err } var fds shared.Jmap op, err := resp.MetadataAsOperation() if err != nil { return -1, err } fds, err = op.Metadata.GetMap("fds") if err != nil { return -1, err } if controlHandler != nil { var control *websocket.Conn if wsControl, ok := fds["control"]; ok { control, err = c.websocket(resp.Operation, wsControl.(string)) if err != nil { return -1, err } defer control.Close() go controlHandler(c, control) } conn, err := c.websocket(resp.Operation, fds["0"].(string)) if err != nil { return -1, err } shared.WebsocketSendStream(conn, stdin) <-shared.WebsocketRecvStream(stdout, conn) conn.Close() } else { conns := make([]*websocket.Conn, 3) dones := make([]chan bool, 3) conns[0], err = c.websocket(resp.Operation, fds[strconv.Itoa(0)].(string)) if err != nil { return -1, err } defer conns[0].Close() dones[0] = shared.WebsocketSendStream(conns[0], stdin) outputs := []io.WriteCloser{stdout, stderr} for i := 1; i < 3; i++ { conns[i], err = c.websocket(resp.Operation, fds[strconv.Itoa(i)].(string)) if err != nil { return -1, err } defer conns[i].Close() dones[i] = shared.WebsocketRecvStream(outputs[i-1], conns[i]) } /* * We'll get a read signal from each of stdout, stderr when they've * both died. We need to wait for these in addition to the operation, * because the server may indicate that the operation is done before we * can actually read the last bits of data off these sockets and print * it to the screen. * * We don't wait for stdin here, because if we're interactive, the user * may not have closed it (e.g. if the command exits but the user * didn't ^D). */ for i := 1; i < 3; i++ { <-dones[i] } // Once we're done, we explicitly close stdin, to signal the websockets // we're done. stdin.Close() } // Now, get the operation's status too. op, err = c.WaitFor(resp.Operation) if err != nil { return -1, err } if op.StatusCode == shared.Failure { return -1, fmt.Errorf(op.Err) } if op.StatusCode != shared.Success { return -1, fmt.Errorf("got bad op status %s", op.Status) } if op.Metadata == nil { return -1, fmt.Errorf("no metadata received") } return op.Metadata.GetInt("return") } func (c *Client) Action(name string, action shared.ContainerAction, timeout int, force bool, stateful bool) (*Response, error) { if c.Remote.Public { return nil, fmt.Errorf("This function isn't supported by public remotes.") } body := shared.Jmap{ "action": action, "timeout": timeout, "force": force} if shared.StringInSlice(string(action), []string{"start", "stop"}) { body["stateful"] = stateful } return c.put(fmt.Sprintf("containers/%s/state", name), body, Async) } func (c *Client) Delete(name string) (*Response, error) { if c.Remote.Public { return nil, fmt.Errorf("This function isn't supported by public remotes.") } var url string s := strings.SplitN(name, "/", 2) if len(s) == 2 { url = fmt.Sprintf("containers/%s/snapshots/%s", s[0], s[1]) } else { url = fmt.Sprintf("containers/%s", name) } return c.delete(url, nil, Async) } func (c *Client) ServerStatus() (*shared.ServerState, error) { ss := shared.ServerState{} resp, err := c.GetServerConfig() if err != nil { return nil, err } if err := json.Unmarshal(resp.Metadata, &ss); err != nil { return nil, err } return &ss, nil } func (c *Client) ContainerInfo(name string) (*shared.ContainerInfo, error) { if c.Remote.Public { return nil, fmt.Errorf("This function isn't supported by public remotes.") } ct := shared.ContainerInfo{} resp, err := c.get(fmt.Sprintf("containers/%s", name)) if err != nil { return nil, err } if err := json.Unmarshal(resp.Metadata, &ct); err != nil { return nil, err } return &ct, nil } func (c *Client) ContainerState(name string) (*shared.ContainerState, error) { if c.Remote.Public { return nil, fmt.Errorf("This function isn't supported by public remotes.") } ct := shared.ContainerState{} resp, err := c.get(fmt.Sprintf("containers/%s/state", name)) if err != nil { return nil, err } if err := json.Unmarshal(resp.Metadata, &ct); err != nil { return nil, err } return &ct, nil } func (c *Client) GetLog(container string, log string) (io.Reader, error) { if c.Remote.Public { return nil, fmt.Errorf("This function isn't supported by public remotes.") } uri := c.url(shared.APIVersion, "containers", container, "logs", log) resp, err := c.getRaw(uri) if err != nil { return nil, err } return resp.Body, nil } func (c *Client) ProfileConfig(name string) (*shared.ProfileConfig, error) { if c.Remote.Public { return nil, fmt.Errorf("This function isn't supported by public remotes.") } ct := shared.ProfileConfig{} resp, err := c.get(fmt.Sprintf("profiles/%s", name)) if err != nil { return nil, err } if err := json.Unmarshal(resp.Metadata, &ct); err != nil { return nil, err } return &ct, nil } func (c *Client) PushFile(container string, p string, gid int, uid int, mode os.FileMode, buf io.ReadSeeker) error { if c.Remote.Public { return fmt.Errorf("This function isn't supported by public remotes.") } query := url.Values{"path": []string{p}} uri := c.url(shared.APIVersion, "containers", container, "files") + "?" + query.Encode() req, err := http.NewRequest("POST", uri, buf) if err != nil { return err } req.Header.Set("User-Agent", shared.UserAgent) req.Header.Set("X-LXD-mode", fmt.Sprintf("%04o", mode.Perm())) req.Header.Set("X-LXD-uid", strconv.FormatUint(uint64(uid), 10)) req.Header.Set("X-LXD-gid", strconv.FormatUint(uint64(gid), 10)) raw, err := c.Http.Do(req) if err != nil { return err } _, err = HoistResponse(raw, Sync) return err } func (c *Client) PullFile(container string, p string) (int, int, os.FileMode, io.ReadCloser, error) { if c.Remote.Public { return 0, 0, 0, nil, fmt.Errorf("This function isn't supported by public remotes.") } uri := c.url(shared.APIVersion, "containers", container, "files") query := url.Values{"path": []string{p}} r, err := c.getRaw(uri + "?" + query.Encode()) if err != nil { return 0, 0, 0, nil, err } uid, gid, mode := shared.ParseLXDFileHeaders(r.Header) return uid, gid, mode, r.Body, nil } func (c *Client) GetMigrationSourceWS(container string) (*Response, error) { if c.Remote.Public { return nil, fmt.Errorf("This function isn't supported by public remotes.") } body := shared.Jmap{"migration": true} url := fmt.Sprintf("containers/%s", container) if shared.IsSnapshot(container) { pieces := strings.SplitN(container, shared.SnapshotDelimiter, 2) if len(pieces) != 2 { return nil, fmt.Errorf("invalid snapshot name %s", container) } url = fmt.Sprintf("containers/%s/snapshots/%s", pieces[0], pieces[1]) } return c.post(url, body, Async) } func (c *Client) MigrateFrom(name string, operation string, certificate string, secrets map[string]string, architecture string, config map[string]string, devices shared.Devices, profiles []string, baseImage string, ephemeral bool) (*Response, error) { if c.Remote.Public { return nil, fmt.Errorf("This function isn't supported by public remotes.") } source := shared.Jmap{ "type": "migration", "mode": "pull", "operation": operation, "certificate": certificate, "secrets": secrets, "base-image": baseImage, } body := shared.Jmap{ "architecture": architecture, "config": config, "devices": devices, "ephemeral": ephemeral, "name": name, "profiles": profiles, "source": source, } return c.post("containers", body, Async) } func (c *Client) Rename(name string, newName string) (*Response, error) { if c.Remote.Public { return nil, fmt.Errorf("This function isn't supported by public remotes.") } oldNameParts := strings.SplitN(name, "/", 2) newNameParts := strings.SplitN(newName, "/", 2) if len(oldNameParts) != len(newNameParts) { return nil, fmt.Errorf("Attempting to rename container to snapshot or vice versa.") } if len(oldNameParts) == 1 { body := shared.Jmap{"name": newName} return c.post(fmt.Sprintf("containers/%s", name), body, Async) } if oldNameParts[0] != newNameParts[0] { return nil, fmt.Errorf("Attempting to rename snapshot of one container into a snapshot of another container.") } body := shared.Jmap{"name": newNameParts[1]} return c.post(fmt.Sprintf("containers/%s/snapshots/%s", oldNameParts[0], oldNameParts[1]), body, Async) } /* Wait for an operation */ func (c *Client) WaitFor(waitURL string) (*shared.Operation, error) { if len(waitURL) < 1 { return nil, fmt.Errorf("invalid wait url %s", waitURL) } /* For convenience, waitURL is expected to be in the form of a * Response.Operation string, i.e. it already has * "//operations/" in it; we chop off the leading / and pass * it to url directly. */ shared.Debugf(path.Join(waitURL[1:], "wait")) resp, err := c.baseGet(c.url(waitURL, "wait")) if err != nil { return nil, err } return resp.MetadataAsOperation() } func (c *Client) WaitForSuccess(waitURL string) error { op, err := c.WaitFor(waitURL) if err != nil { return err } if op.StatusCode == shared.Success { return nil } return fmt.Errorf(op.Err) } func (c *Client) RestoreSnapshot(container string, snapshotName string, stateful bool) (*Response, error) { if c.Remote.Public { return nil, fmt.Errorf("This function isn't supported by public remotes.") } body := shared.Jmap{"restore": snapshotName, "stateful": stateful} return c.put(fmt.Sprintf("containers/%s", container), body, Async) } func (c *Client) Snapshot(container string, snapshotName string, stateful bool) (*Response, error) { if c.Remote.Public { return nil, fmt.Errorf("This function isn't supported by public remotes.") } body := shared.Jmap{"name": snapshotName, "stateful": stateful} return c.post(fmt.Sprintf("containers/%s/snapshots", container), body, Async) } func (c *Client) ListSnapshots(container string) ([]shared.SnapshotInfo, error) { if c.Remote.Public { return nil, fmt.Errorf("This function isn't supported by public remotes.") } qUrl := fmt.Sprintf("containers/%s/snapshots?recursion=1", container) resp, err := c.get(qUrl) if err != nil { return nil, err } var result []shared.SnapshotInfo if err := json.Unmarshal(resp.Metadata, &result); err != nil { return nil, err } return result, nil } func (c *Client) GetServerConfigString() ([]string, error) { var resp []string ss, err := c.ServerStatus() if err != nil { return resp, err } if ss.Auth == "untrusted" { return resp, nil } if len(ss.Config) == 0 { resp = append(resp, "No config variables set.") } for k, v := range ss.Config { resp = append(resp, fmt.Sprintf("%s = %v", k, v)) } return resp, nil } func (c *Client) SetServerConfig(key string, value string) (*Response, error) { if c.Remote.Public { return nil, fmt.Errorf("This function isn't supported by public remotes.") } ss, err := c.ServerStatus() if err != nil { return nil, err } ss.Config[key] = value return c.put("", ss, Sync) } func (c *Client) UpdateServerConfig(ss shared.BriefServerState) (*Response, error) { if c.Remote.Public { return nil, fmt.Errorf("This function isn't supported by public remotes.") } return c.put("", ss, Sync) } /* * return string array representing a container's full configuration */ func (c *Client) GetContainerConfig(container string) ([]string, error) { if c.Remote.Public { return nil, fmt.Errorf("This function isn't supported by public remotes.") } var resp []string st, err := c.ContainerInfo(container) if err != nil { return resp, err } profiles := strings.Join(st.Profiles, ",") pstr := fmt.Sprintf("Profiles: %s", profiles) resp = append(resp, pstr) for k, v := range st.Config { str := fmt.Sprintf("%s = %s", k, v) resp = append(resp, str) } return resp, nil } func (c *Client) SetContainerConfig(container, key, value string) error { if c.Remote.Public { return fmt.Errorf("This function isn't supported by public remotes.") } st, err := c.ContainerInfo(container) if err != nil { return err } if value == "" { delete(st.Config, key) } else { st.Config[key] = value } /* * Although container config is an async operation (we PUT to restore a * snapshot), we expect config to be a sync operation, so let's just * handle it here. */ resp, err := c.put(fmt.Sprintf("containers/%s", container), st, Async) if err != nil { return err } return c.WaitForSuccess(resp.Operation) } func (c *Client) UpdateContainerConfig(container string, st shared.BriefContainerInfo) error { if c.Remote.Public { return fmt.Errorf("This function isn't supported by public remotes.") } resp, err := c.put(fmt.Sprintf("containers/%s", container), st, Async) if err != nil { return err } return c.WaitForSuccess(resp.Operation) } func (c *Client) ProfileCreate(p string) error { if c.Remote.Public { return fmt.Errorf("This function isn't supported by public remotes.") } body := shared.Jmap{"name": p} _, err := c.post("profiles", body, Sync) return err } func (c *Client) ProfileDelete(p string) error { if c.Remote.Public { return fmt.Errorf("This function isn't supported by public remotes.") } _, err := c.delete(fmt.Sprintf("profiles/%s", p), nil, Sync) return err } func (c *Client) GetProfileConfig(profile string) (map[string]string, error) { if c.Remote.Public { return nil, fmt.Errorf("This function isn't supported by public remotes.") } st, err := c.ProfileConfig(profile) if err != nil { return nil, err } return st.Config, nil } func (c *Client) SetProfileConfigItem(profile, key, value string) error { if c.Remote.Public { return fmt.Errorf("This function isn't supported by public remotes.") } st, err := c.ProfileConfig(profile) if err != nil { shared.Debugf("Error getting profile %s to update", profile) return err } if value == "" { delete(st.Config, key) } else { st.Config[key] = value } _, err = c.put(fmt.Sprintf("profiles/%s", profile), st, Sync) return err } func (c *Client) PutProfile(name string, profile shared.ProfileConfig) error { if c.Remote.Public { return fmt.Errorf("This function isn't supported by public remotes.") } if profile.Name != name { return fmt.Errorf("Cannot change profile name") } _, err := c.put(fmt.Sprintf("profiles/%s", name), profile, Sync) return err } func (c *Client) ListProfiles() ([]string, error) { if c.Remote.Public { return nil, fmt.Errorf("This function isn't supported by public remotes.") } resp, err := c.get("profiles") if err != nil { return nil, err } var result []string if err := json.Unmarshal(resp.Metadata, &result); err != nil { return nil, err } names := []string{} for _, url := range result { toScan := strings.Replace(url, "/", " ", -1) version := "" name := "" count, err := fmt.Sscanf(toScan, " %s profiles %s", &version, &name) if err != nil { return nil, err } if count != 2 { return nil, fmt.Errorf("bad profile url %s", url) } if version != shared.APIVersion { return nil, fmt.Errorf("bad version in profile url") } names = append(names, name) } return names, nil } func (c *Client) ApplyProfile(container, profile string) (*Response, error) { if c.Remote.Public { return nil, fmt.Errorf("This function isn't supported by public remotes.") } st, err := c.ContainerInfo(container) if err != nil { return nil, err } st.Profiles = strings.Split(profile, ",") return c.put(fmt.Sprintf("containers/%s", container), st, Async) } func (c *Client) ContainerDeviceDelete(container, devname string) (*Response, error) { if c.Remote.Public { return nil, fmt.Errorf("This function isn't supported by public remotes.") } st, err := c.ContainerInfo(container) if err != nil { return nil, err } delete(st.Devices, devname) return c.put(fmt.Sprintf("containers/%s", container), st, Async) } func (c *Client) ContainerDeviceAdd(container, devname, devtype string, props []string) (*Response, error) { if c.Remote.Public { return nil, fmt.Errorf("This function isn't supported by public remotes.") } st, err := c.ContainerInfo(container) if err != nil { return nil, err } newdev := shared.Device{} for _, p := range props { results := strings.SplitN(p, "=", 2) if len(results) != 2 { return nil, fmt.Errorf("no value found in %q", p) } k := results[0] v := results[1] newdev[k] = v } if st.Devices != nil && st.Devices.ContainsName(devname) { return nil, fmt.Errorf("device already exists") } newdev["type"] = devtype if st.Devices == nil { st.Devices = shared.Devices{} } st.Devices[devname] = newdev return c.put(fmt.Sprintf("containers/%s", container), st, Async) } func (c *Client) ContainerListDevices(container string) ([]string, error) { if c.Remote.Public { return nil, fmt.Errorf("This function isn't supported by public remotes.") } st, err := c.ContainerInfo(container) if err != nil { return nil, err } devs := []string{} for n, d := range st.Devices { devs = append(devs, fmt.Sprintf("%s: %s", n, d["type"])) } return devs, nil } func (c *Client) ProfileDeviceDelete(profile, devname string) (*Response, error) { if c.Remote.Public { return nil, fmt.Errorf("This function isn't supported by public remotes.") } st, err := c.ProfileConfig(profile) if err != nil { return nil, err } for n, _ := range st.Devices { if n == devname { delete(st.Devices, n) } } return c.put(fmt.Sprintf("profiles/%s", profile), st, Sync) } func (c *Client) ProfileDeviceAdd(profile, devname, devtype string, props []string) (*Response, error) { if c.Remote.Public { return nil, fmt.Errorf("This function isn't supported by public remotes.") } st, err := c.ProfileConfig(profile) if err != nil { return nil, err } newdev := shared.Device{} for _, p := range props { results := strings.SplitN(p, "=", 2) if len(results) != 2 { return nil, fmt.Errorf("no value found in %q", p) } k := results[0] v := results[1] newdev[k] = v } if st.Devices != nil && st.Devices.ContainsName(devname) { return nil, fmt.Errorf("device already exists") } newdev["type"] = devtype if st.Devices == nil { st.Devices = shared.Devices{} } st.Devices[devname] = newdev return c.put(fmt.Sprintf("profiles/%s", profile), st, Sync) } func (c *Client) ProfileListDevices(profile string) ([]string, error) { if c.Remote.Public { return nil, fmt.Errorf("This function isn't supported by public remotes.") } st, err := c.ProfileConfig(profile) if err != nil { return nil, err } devs := []string{} for n, d := range st.Devices { devs = append(devs, fmt.Sprintf("%s: %s", n, d["type"])) } return devs, nil } // WebsocketDial attempts to dial a websocket to a LXD instance, parsing // LXD-style errors and returning them as go errors. func WebsocketDial(dialer websocket.Dialer, url string) (*websocket.Conn, error) { conn, raw, err := dialer.Dial(url, http.Header{}) if err != nil { _, err2 := HoistResponse(raw, Error) if err2 != nil { /* The response isn't one we understand, so return * whatever the original error was. */ return nil, err } return nil, err } return conn, err } func (c *Client) ProfileCopy(name, newname string, dest *Client) error { if c.Remote.Public { return fmt.Errorf("This function isn't supported by public remotes.") } st, err := c.ProfileConfig(name) if err != nil { return err } body := shared.Jmap{"config": st.Config, "name": newname, "devices": st.Devices} _, err = dest.post("profiles", body, Sync) return err } func (c *Client) AsyncWaitMeta(resp *Response) (*shared.Jmap, error) { op, err := c.WaitFor(resp.Operation) if err != nil { return nil, err } if op.StatusCode == shared.Failure { return nil, fmt.Errorf(op.Err) } if op.StatusCode != shared.Success { return nil, fmt.Errorf("got bad op status %s", op.Status) } return op.Metadata, nil } func (c *Client) ImageFromContainer(cname string, public bool, aliases []string, properties map[string]string) (string, error) { if c.Remote.Public { return "", fmt.Errorf("This function isn't supported by public remotes.") } source := shared.Jmap{"type": "container", "name": cname} if shared.IsSnapshot(cname) { source["type"] = "snapshot" } body := shared.Jmap{"public": public, "source": source, "properties": properties} resp, err := c.post("images", body, Async) if err != nil { return "", err } jmap, err := c.AsyncWaitMeta(resp) if err != nil { return "", err } fingerprint, err := jmap.GetString("fingerprint") if err != nil { return "", err } /* add new aliases */ for _, alias := range aliases { c.DeleteAlias(alias) err = c.PostAlias(alias, alias, fingerprint) if err != nil { return "", fmt.Errorf("Error adding alias %s: %s", alias, err) } } return fingerprint, nil } lxd-2.0.0/config.go000066400000000000000000000104601270277227600141110ustar00rootroot00000000000000package lxd import ( "fmt" "io/ioutil" "os" "path" "path/filepath" "strings" "gopkg.in/yaml.v2" "github.com/lxc/lxd/shared" ) // Config holds settings to be used by a client or daemon. type Config struct { // DefaultRemote holds the remote daemon name from the Remotes map // that the client should communicate with by default. // If empty it defaults to "local". DefaultRemote string `yaml:"default-remote"` // Remotes defines a map of remote daemon names to the details for // communication with the named daemon. // The implicit "local" remote is always available and communicates // with the local daemon over a unix socket. Remotes map[string]RemoteConfig `yaml:"remotes"` // Command line aliases for `lxc` Aliases map[string]string `yaml:"aliases"` // This is the path to the config directory, so the client can find // previously stored server certs, give good error messages, and save // new server certs, etc. // // We don't need to store it, because of course once we've loaded this // structure we already know where it is :) ConfigDir string `yaml:"-"` } // RemoteConfig holds details for communication with a remote daemon. type RemoteConfig struct { Addr string `yaml:"addr"` Public bool `yaml:"public"` Protocol string `yaml:"protocol,omitempty"` Static bool `yaml:"-"` } var LocalRemote = RemoteConfig{ Addr: "unix://", Static: true, Public: false} var ImagesRemote = RemoteConfig{ Addr: "https://images.linuxcontainers.org", Public: true} var UbuntuRemote = RemoteConfig{ Addr: "https://cloud-images.ubuntu.com/releases", Static: true, Public: true, Protocol: "simplestreams"} var UbuntuDailyRemote = RemoteConfig{ Addr: "https://cloud-images.ubuntu.com/daily", Static: true, Public: true, Protocol: "simplestreams"} var StaticRemotes = map[string]RemoteConfig{ "local": LocalRemote, "ubuntu": UbuntuRemote, "ubuntu-daily": UbuntuDailyRemote} var DefaultRemotes = map[string]RemoteConfig{ "images": ImagesRemote, "local": LocalRemote, "ubuntu": UbuntuRemote, "ubuntu-daily": UbuntuDailyRemote} var DefaultConfig = Config{ Remotes: DefaultRemotes, DefaultRemote: "local", Aliases: map[string]string{}, } // LoadConfig reads the configuration from the config path; if the path does // not exist, it returns a default configuration. func LoadConfig(path string) (*Config, error) { data, err := ioutil.ReadFile(path) if os.IsNotExist(err) { // A missing file is equivalent to the default configuration. withPath := DefaultConfig withPath.ConfigDir = filepath.Dir(path) return &withPath, nil } if err != nil { return nil, fmt.Errorf("cannot read config file: %v", err) } var c Config err = yaml.Unmarshal(data, &c) if err != nil { return nil, fmt.Errorf("cannot parse configuration: %v", err) } if c.Remotes == nil { c.Remotes = make(map[string]RemoteConfig) } c.ConfigDir = filepath.Dir(path) for k, v := range StaticRemotes { c.Remotes[k] = v } return &c, nil } // SaveConfig writes the provided configuration to the config file. func SaveConfig(c *Config, fname string) error { for k, _ := range StaticRemotes { delete(c.Remotes, k) } // Ignore errors on these two calls. Create will report any problems. os.Remove(fname + ".new") os.Mkdir(filepath.Dir(fname), 0700) f, err := os.Create(fname + ".new") if err != nil { return fmt.Errorf("cannot create config file: %v", err) } // If there are any errors, do not leave it around. defer f.Close() defer os.Remove(fname + ".new") data, err := yaml.Marshal(c) _, err = f.Write(data) if err != nil { return fmt.Errorf("cannot write configuration: %v", err) } f.Close() err = shared.FileMove(fname+".new", fname) if err != nil { return fmt.Errorf("cannot rename temporary config file: %v", err) } return nil } func (c *Config) ParseRemoteAndContainer(raw string) (string, string) { result := strings.SplitN(raw, ":", 2) if len(result) == 1 { return c.DefaultRemote, result[0] } return result[0], result[1] } func (c *Config) ParseRemote(raw string) string { return strings.SplitN(raw, ":", 2)[0] } func (c *Config) ConfigPath(file string) string { return path.Join(c.ConfigDir, file) } func (c *Config) ServerCertPath(name string) string { return path.Join(c.ConfigDir, "servercerts", fmt.Sprintf("%s.crt", name)) } lxd-2.0.0/config/000077500000000000000000000000001270277227600135615ustar00rootroot00000000000000lxd-2.0.0/config/bash/000077500000000000000000000000001270277227600144765ustar00rootroot00000000000000lxd-2.0.0/config/bash/lxd-client000066400000000000000000000045211270277227600164660ustar00rootroot00000000000000_have lxc && { _lxd_complete() { _lxd_names() { COMPREPLY=( $( compgen -W \ "$( lxc list --fast | tail -n +4 | awk '{print $2}' | egrep -v '^(\||^$)' )" "$cur" ) ) } _lxd_images() { COMPREPLY=( $( compgen -W \ "$( lxc image list | tail -n +4 | awk '{print $2}' | egrep -v '^(\||^$)' )" "$cur" ) ) } local cur prev COMPREPLY=() cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} lxc_cmds="config copy delete exec file help image info init launch \ list move profile publish remote restart restore snapshot start stop \ version" if [ $COMP_CWORD -eq 1 ]; then COMPREPLY=( $(compgen -W "$lxc_cmds" -- $cur) ) elif [ $COMP_CWORD -eq 2 ]; then case "$prev" in "config") COMPREPLY=( $(compgen -W "device edit get set show trust" -- $cur) ) ;; "copy") _lxd_names ;; "delete") _lxd_names ;; "exec") _lxd_names ;; "file") COMPREPLY=( $(compgen -W "pull push edit" -- $cur) ) ;; "help") COMPREPLY=( $(compgen -W "$lxc_cmds" -- $cur) ) ;; "image") COMPREPLY=( $(compgen -W "import copy delete edit export info list show alias" -- $cur) ) ;; "info") _lxd_names ;; "init") _lxd_images ;; "launch") _lxd_images ;; "move") _lxd_names ;; "profile") COMPREPLY=( $(compgen -W \ "list show create edit copy get set delete apply device" -- $cur) ) ;; "publish") _lxd_names ;; "remote") COMPREPLY=( $(compgen -W \ "add remove list rename set-url set-default get-default" -- $cur) ) ;; "restart") _lxd_names ;; "restore") _lxd_names ;; "snapshot") _lxd_names ;; "start") # should check if containers are stopped _lxd_names ;; "stop") # should check if containers are started _lxd_names ;; *) ;; esac fi return 0 } complete -o default -F _lxd_complete lxc } lxd-2.0.0/doc/000077500000000000000000000000001270277227600130615ustar00rootroot00000000000000lxd-2.0.0/doc/architectures.md000066400000000000000000000027071270277227600162560ustar00rootroot00000000000000# Introduction LXD just like LXC can run on just about any architecture that's supported by the Linux kernel and by Go. Some objects in LXD are tied to an architecture, like the container, container snapshots and images. This document lists all the supported architectures, their unique identifier (used in the database), how they should be named and some notes. Please note that what LXD cares about is the kernel architecture, not the particular userspace flavor as determined by the toolchain. That means that LXD considers armv7 hard-float to be the same as armv7 soft-float and refers to both as "armv7". If useful to the user, the exact userspace ABI may be set as an image and container property, allowing easy query. # Architectures ID | Name | Notes | Personalities :--- | :--- | :---- | :------------ 1 | i686 | 32bit Intel x86 | 2 | x86\_64 | 64bit Intel x86 | x86 3 | armv7l | 32bit ARMv7 little-endian | 4 | aarch64 | 64bit ARMv8 little-endian | armv7 (optional) 5 | ppc | 32bit PowerPC big-endian | 6 | ppc64 | 64bit PowerPC big-endian | powerpc 7 | ppc64le | 64bit PowerPC little-endian | 8 | s390x | 64bit ESA/390 big-endian | The architecture names above are typically aligned with the Linux kernel architecture names. lxd-2.0.0/doc/configuration.md000066400000000000000000000450431270277227600162600ustar00rootroot00000000000000# Introduction Current LXD stores the following kind of configurations: - Server configuration (the LXD daemon itself) - Container configuration The server configuration is a simple set of key and values. The container configuration is a bit more complex as it uses both key/value configuration and some more complex configuration structures for devices, network interfaces and storage volumes. # Server configuration ## Key/value configuration The key/value configuration is namespaced with the following namespaces currently supported: - core (core daemon configuration) - images (image configuration) - storage (storage configuration) Key | Type | Default | Description :-- | :--- | :------ | :---------- core.https\_address | string | - | Address to bind for the remote API core.https\_allowed\_origin | string | - | Access-Control-Allow-Origin http header value core.https\_allowed\_methods | string | - | Access-Control-Allow-Methods http header value core.https\_allowed\_headers | string | - | Access-Control-Allow-Headers http header value core.proxy\_https | string | - | https proxy to use, if any (falls back to HTTPS\_PROXY environment variable) core.proxy\_http | string | - | http proxy to use, if any (falls back to HTTP\_PROXY environment variable) core.proxy\_ignore\_hosts | string | - | hosts which don't need the proxy for use (similar format to NO\_PROXY, e.g. 1.2.3.4,1.2.3.5, falls back to NO\_PROXY environment variable) core.trust\_password | string | - | Password to be provided by clients to setup a trust storage.lvm\_vg\_name | string | - | LVM Volume Group name to be used for container and image storage. A default Thin Pool is created using 100% of the free space in the Volume Group, unless `storage.lvm_thinpool_name` is set. storage.lvm\_thinpool\_name | string | "LXDPool" | LVM Thin Pool to use within the Volume Group specified in `storage.lvm_vg_name`, if the default pool parameters are undesirable. storage.lvm\_fstype | string | ext4 | Format LV with filesystem, for now it's value can be only ext4 (default) or xfs. storage.lvm\_volume\_size | string | 10GiB | Size of the logical volume storage.zfs\_pool\_name | string | - | ZFS pool name images.compression\_algorithm | string | gzip | Compression algorithm to use for new images (bzip2, gzip, lzma, xz or none) images.remote\_cache\_expiry | integer | 10 | Number of days after which an unused cached remote image will be flushed images.auto\_update\_interval | integer | 6 | Interval in hours at which to look for update to cached images (0 disables it) images.auto\_update\_cached | boolean | true | Whether to automatically update any image that LXD caches Those keys can be set using the lxc tool with: lxc config set # Container configuration ## Properties The following are direct container properties and can't be part of a profile: - name - architecture Name is the container name and can only be changed by renaming the container. ## Key/value configuration The key/value configuration is namespaced with the following namespaces currently supported: - boot (boot related options, timing, dependencies, ...) - environment (environment variables) - limits (resource limits) - raw (raw container configuration overrides) - security (security policies) - user (storage for user properties, searchable) - volatile (used internally by LXD to store settings that are specific to a specific container instance) The currently supported keys are: Key | Type | Default | Live update | Description :-- | :--- | :------ | :---------- | :---------- boot.autostart | boolean | false | n/a | Always start the container when LXD starts boot.autostart.delay | integer | 0 | n/a | Number of seconds to wait after the container started before starting the next one boot.autostart.priority | integer | 0 | n/a | What order to start the containers in (starting with highest) environment.\* | string | - | yes (exec) | key/value environment variables to export to the container and set on exec limits.cpu | string | - (all) | yes | Number or range of CPUs to expose to the container limits.cpu.allowance | string | 100% | yes | How much of the CPU can be used. Can be a percentage (e.g. 50%) for a soft limit or hard a chunk of time (25ms/100ms) limits.cpu.priority | integer | 10 (maximum) | yes | CPU scheduling priority compared to other containers sharing the same CPUs (overcommit) limits.disk.priority | integer | 5 (medium) | yes | When under load, how much priority to give to the container's I/O requests limits.memory | string | - (all) | yes | Percentage of the host's memory or fixed value in bytes (supports kB, MB, GB, TB, PB and EB suffixes) limits.memory.enforce | string | hard | yes | If hard, container can't exceed its memory limit. If soft, the container can exceed its memory limit when extra host memory is available. limits.memory.swap | boolean | true | yes | Whether to allow some of the container's memory to be swapped out to disk limits.memory.swap.priority | integer | 10 (maximum) | yes | The higher this is set, the least likely the container is to be swapped to disk limits.network.priority | integer | 0 (minimum) | yes | When under load, how much priority to give to the container's network requests limits.processes | integer | - (max) | yes | Maximum number of processes that can run in the container linux.kernel\_modules | string | - | yes | Comma separated list of kernel modules to load before starting the container raw.apparmor | blob | - | yes | Apparmor profile entries to be appended to the generated profile raw.lxc | blob | - | no | Raw LXC configuration to be appended to the generated one security.nesting | boolean | false | yes | Support running lxd (nested) inside the container security.privileged | boolean | false | no | Runs the container in privileged mode user.\* | string | - | n/a | Free form user key/value storage (can be used in search) The following volatile keys are currently internally used by LXD: Key | Type | Default | Description :-- | :--- | :------ | :---------- volatile.\.hwaddr | string | - | Network device MAC address (when no hwaddr property is set on the device itself) volatile.\.name | string | - | Network device name (when no name propery is set on the device itself) volatile.apply\_template | string | - | The name of a template hook which should be triggered upon next startup volatile.base\_image | string | - | The hash of the image the container was created from, if any. volatile.last\_state.idmap | string | - | Serialized container uid/gid map volatile.last\_state.power | string | - | Container state as of last host shutdown Additionally, those user keys have become common with images (support isn't guaranteed): Key | Type | Default | Description :-- | :--- | :------ | :---------- user.network\_mode | string | dhcp | One of "dhcp" or "link-local". Used to configure network in supported images. user.meta-data | string | - | Cloud-init meta-data, content is appended to seed value. user.user-data | string | #!cloud-config | Cloud-init user-data, content is used as seed value. user.vendor-data | string | #!cloud-config | Cloud-init vendor-data, content is used as seed value. Note that while a type is defined above as a convenience, all values are stored as strings and should be exported over the REST API as strings (which makes it possible to support any extra values without breaking backward compatibility). Those keys can be set using the lxc tool with: lxc config set Volatile keys can't be set by the user and can only be set directly against a container. The raw keys allow direct interaction with the backend features that LXD itself uses, setting those may very well break LXD in non-obvious ways and should whenever possible be avoided. ## Devices configuration LXD will always provide the container with the basic devices which are required for a standard POSIX system to work. These aren't visible in container or profile configuration and may not be overriden. Those includes: - /dev/null (character device) - /dev/zero (character device) - /dev/full (character device) - /dev/console (character device) - /dev/tty (character device) - /dev/random (character device) - /dev/urandom (character device) - lo (network interface) Anything else has to be defined in the container configuration or in one of its profiles. The default profile will typically contain a network interface to become eth0 in the container. To add extra devices to a container, device entries can be added directly to a container, or to a profile. Devices may be added or removed while the container is running. Every device entry is identified by a unique name. If the same name is used in a subsequent profile or in the container's own configuration, the whole entry is overriden by the new definition. Device entries are added through: lxc config device add [key=value]... lxc profile device add [key=value]... ### Device types LXD supports the following device types: ID (database) | Name | Description :-- | :-- | :-- 0 | none | Inheritance blocker 1 | nic | Network interface 2 | disk | Mountpoint inside the container 3 | unix-char | Unix character device 4 | unix-block | Unix block device ### Type: none A none type device doesn't have any property and doesn't create anything inside the container. It's only purpose it to stop inheritance of devices coming from profiles. To do so, just add a none type device with the same name of the one you wish to skip inheriting. It can be added in a profile being applied after the profile it originated from or directly on the container. ### Type: nic LXD supports different kind of network devices: - physical: Straight physical device passthrough from the host. The targeted device will vanish from the host and appear in the container. - bridged: Uses an existing bridge on the host and creates a virtual device pair to connect the host bridge to the container. - macvlan: Sets up a new network device based on an existing one but using a different MAC address. - p2p: Creates a virtual device pair, putting one side in the container and leaving the other side on the host. Different network interface types have different additional properties, the current list is: Key | Type | Default | Required | Used by | Description :-- | :-- | :-- | :-- | :-- | :-- nictype | string | - | yes | all | The device type, one of "physical", "bridged", "macvlan" or "p2p" limits.ingress | string | - | no | bridged, p2p | I/O limit in bit/s (supports kbit, Mbit, Gbit suffixes) limits.egress | string | - | no | bridged, p2p | I/O limit in bit/s (supports kbit, Mbit, Gbit suffixes) limits.max | string | - | no | bridged, p2p | Same as modifying both limits.read and limits.write name | string | kernel assigned | no | all | The name of the interface inside the container host\_name | string | randomly assigned | no | bridged, p2p, macvlan | The name of the interface inside the host hwaddr | string | randomly assigned | no | all | The MAC address of the new interface mtu | integer | parent MTU | no | all | The MTU of the new interface parent | string | - | yes | physical, bridged, macvlan | The name of the host device or bridge ### Type: disk Disk entries are essentially mountpoints inside the container. They can either be a bind-mount of an existing file or directory on the host, or if the source is a block device, a regular mount. The following properties exist: Key | Type | Default | Required | Description :-- | :-- | :-- | :-- | :-- limits.read | string | - | no | I/O limit in byte/s (supports kB, MB, GB, TB, PB and EB suffixes) or in iops (must be suffixed with "iops") limits.write | string | - | no | I/O limit in byte/s (supports kB, MB, GB, TB, PB and EB suffixes) or in iops (must be suffixed with "iops") limits.max | string | - | no | Same as modifying both limits.read and limits.write path | string | - | yes | Path inside the container where the disk will be mounted source | string | - | yes | Path on the host, either to a file/directory or to a block device optional | boolean | false | no | Controls whether to fail if the source doesn't exist readonly | boolean | false | no | Controls whether to make the mount read-only size | string | - | no | Disk size in bytes (supports kB, MB, GB, TB, PB and EB suffixes). This is only supported for the rootfs (/). recursive | boolean | false | no | Whether or not to recursively mount the source path If multiple disks, backed by the same block device, have I/O limits set, the average of the limits will be used. ### Type: unix-char Unix character device entries simply make the requested character device appear in the container's /dev and allow read/write operations to it. The following properties exist: Key | Type | Default | Required | Description :-- | :-- | :-- | :-- | :-- path | string | - | yes | Path inside the container major | int | device on host | no | Device major number minor | int | device on host | no | Device minor number uid | int | 0 | no | UID of the device owner in the container gid | int | 0 | no | GID of the device owner in the container mode | int | 0660 | no | Mode of the device in the container ### Type: unix-block Unix block device entries simply make the requested character device appear in the container's /dev and allow read/write operations to it. The following properties exist: Key | Type | Default | Required | Description :-- | :-- | :-- | :-- | :-- path | string | - | yes | Path inside the container major | int | device on host | no | Device major number minor | int | device on host | no | Device minor number uid | int | 0 | no | UID of the device owner in the container gid | int | 0 | no | GID of the device owner in the container mode | int | 0660 | no | Mode of the device in the container ## Profiles Profiles can store any configuration that a container can (key/value or devices) and any number of profiles can be applied to a container. Profiles are applied in the order they are specified so the last profile to specify a specific key wins. In any case, resource-specific configuration always overrides that coming from the profiles. If not present, LXD will create a "default" profile which comes with a network interface connected to LXD's default bridge (lxdbr0). The "default" profile is set for any new container created which doesn't specify a different profiles list. ## JSON representation A representation of a container using all the different types of configurations would look like: { 'name': "my-container", 'profiles': ["default"], 'architecture': 'x86_64', 'config': { 'limits.cpu': '3', 'security.privileged': 'true' }, 'devices': { 'nic-lxdbr0': { 'type': 'none' }, 'nic-mybr0': { 'type': 'nic', 'mtu': '9000', 'parent': 'mybr0' }, 'rootfs': { 'type': 'disk', 'path': '/', 'source': 'UUID=8f7fdf5e-dc60-4524-b9fe-634f82ac2fb6' }, }, 'status': { 'status': "Running", 'status_code': 103, 'ips': [{'interface': "eth0", 'protocol': "INET6", 'address': "2001:470:b368:1020:1::2"}, {'interface': "eth0", 'protocol': "INET", 'address': "172.16.15.30"}]} } lxd-2.0.0/doc/daemon-behavior.md000066400000000000000000000023221270277227600164420ustar00rootroot00000000000000# Introduction This specification covers some of the daemon's behavior, such as reaction to given signals, crashes, ... # Startup On every start, LXD checks that its directory structure exists. If it doesn't, it'll create the required directories, generate a keypair and initialize the database. Once the daemon is ready for work, LXD will scan the containers table for any container for which the stored power state differs from the current one. If a container's power state was recorded as running and the container isn't running, LXD will start it. # Signal handling ## SIGINT, SIGQUIT, SIGTERM For those signals, LXD assumes that it's being temporarily stopped and will be restarted at a later time to continue handling the containers. The containers will keep running and LXD will close all connections and exit cleanly. ## SIGPWR Indicates to LXD that the host is going down. LXD will attempt a clean shutdown of all the containers. After 30s, it will kill any remaining container. The container power\_state in the containers table is kept as it was so that LXD after the host is done rebooting can restore the containers as they were. ## SIGUSR1 Write a memory profile dump to the file specified with \-\-memprofile. lxd-2.0.0/doc/database.md000066400000000000000000000337561270277227600151650ustar00rootroot00000000000000# Introduction So first of all, why a database? Rather than keeping the configuration and state within each container's directory as is traditionally done by LXC, LXD has an internal database which stores all of that information. This allows very quick queries against all containers configuration. An example is the rather obvious question "what containers are using br0?". To answer that question without a database, LXD would have to iterate through every single container, load and parse its configuration and then look at what network devices are defined in there. While that may be quick with a few containers, imagine how many filesystem access would be required for 2000 containers. Instead with a database, it's only a matter of accessing the already cached database with a pretty simple query. # Database engine As this is a purely internal database with a single client and very little data, we'll be using sqlite3. We have no interest in replication or other HA features offered by the bigger database engines as LXD runs on each compute nodes and having the database accessible when the compute node itself isn't, wouldn't be terribly useful. # Design The design of the database is made to be as close as possible to the REST API. The main table and field names are exact match for the REST API. However this database isn't an exact match of the API, mostly because any runtime or external piece of information will not be stored in the database (as this would require constent polling and wouldn't gain us anything). We make no guarantee of stability for the database schema. This is a purely internal database which only LXD should ever use. Updating LXD may cause a schema update and data being shuffled. In those cases, LXD will make a copy of the old database as ".old" to allow for a revert. # Tables The list of tables is: * certificates * config * containers * containers\_config * containers\_devices * containers\_devices\_config * containers\_profiles * images * images\_properties * images\_aliases * images\_source * profiles * profiles\_config * profiles\_devices * profiles\_devices\_config * schema You'll notice that compared to the REST API, there are three main differences: 1. The extra "\*\_config" tables which are there for key/value config storage. 2. The extra "images\_properties" table which is there for key/value property storage. 3. The extra "schema" table whish is used for database schema version tracking. 4. There is no "snapshots" table. That's because snapshots are a copy of a container at a given point in time, including its configuration and on-disk state. So having snapshots in a separate table would only be needless duplication. # Notes on sqlite3 sqlite3 only supports 5 storage classes: NULL, INTEGER, REAL, TEXT and BLOB There are then a set of aliases for each of those storage classes which is what we use below. # Schema ## certificates Column | Type | Default | Constraint | Description :----- | :--- | :------ | :--------- | :---------- id | INTEGER | SERIAL | NOT NULL | SERIAL fingerprint | VARCHAR(255) | - | NOT NULL | HEX encoded certificate fingerprint type | INTEGER | - | NOT NULL | Certificate type (0 = client) name | VARCHAR(255) | - | NOT NULL | Certificate name (defaults to CN) certificate | TEXT | - | NOT NULL | PEM encoded certificate Index: UNIQUE ON id AND fingerprint ## config (server configuration) Column | Type | Default | Constraint | Description :----- | :--- | :------ | :--------- | :---------- id | INTEGER | SERIAL | NOT NULL | SERIAL key | VARCHAR(255) | - | NOT NULL | Configuration key value | TEXT | - | | Configuration value (NULL for unset) Index: UNIQUE ON id AND key ## containers Column | Type | Default | Constraint | Description :----- | :--- | :------ | :--------- | :---------- id | INTEGER | SERIAL | NOT NULL | SERIAL name | VARCHAR(255) | - | NOT NULL | Container name architecture | INTEGER | - | NOT NULL | Container architecture type | INTEGER | 0 | NOT NULL | Container type (0 = container, 1 = container snapshot) ephemeral | INTEGER | 0 | NOT NULL | Whether the container is ephemeral (0 = persistent, 1 = ephemeral) stateful | INTEGER | 0 | NOT NULL | Whether the snapshot contains state (snapshot only) creation\_date | DATETIME | - | | Image creation date (user supplied, 0 = unknown) Index: UNIQUE ON id AND name ## containers\_config Column | Type | Default | Constraint | Description :----- | :--- | :------ | :--------- | :---------- id | INTEGER | SERIAL | NOT NULL | SERIAL container\_id | INTEGER | - | NOT NULL | containers.id FK key | VARCHAR(255) | - | NOT NULL | Configuration key value | TEXT | - | | Configuration value (NULL for unset) Index: UNIQUE ON id AND container\_id + key Foreign keys: container\_id REFERENCES containers(id) ## containers\_devices Column | Type | Default | Constraint | Description :----- | :--- | :------ | :--------- | :---------- id | INTEGER | SERIAL | NOT NULL | SERIAL container\_id | INTEGER | - | NOT NULL | containers.id FK name | VARCHAR(255) | - | NOT NULL | Container name type | INTEGER | 0 | NOT NULL | Device type (see configuration.md) Index: UNIQUE ON id AND container\_id + name Foreign keys: container\_id REFERENCES containers(id) ## containers\_devices\_config Column | Type | Default | Constraint | Description :----- | :--- | :------ | :--------- | :---------- id | INTEGER | SERIAL | NOT NULL | SERIAL container\_device\_id | INTEGER | - | NOT NULL | containers\_devices.id FK key | VARCHAR(255) | - | NOT NULL | Configuration key value | TEXT | - | | Configuration value (NULL for unset) Index: UNIQUE ON id AND container\_device\_id + key Foreign keys: container\_device\_id REFERENCES containers\_devices(id) ## containers\_profiles Column | Type | Default | Constraint | Description :----- | :--- | :------ | :--------- | :---------- id | INTEGER | SERIAL | NOT NULL | SERIAL container\_id | INTEGER | - | NOT NULL | containers.id FK profile\_id | INTEGER | - | NOT NULL | profiles.id FK apply\_order | INTEGER | 0 | NOT NULL | Profile ordering Index: UNIQUE ON id AND container\_id + profile\_id Foreign keys: container\_id REFERENCES containers(id) and profile\_id REFERENCES profiles(id) ## images Column | Type | Default | Constraint | Description :----- | :--- | :------ | :--------- | :---------- id | INTEGER | SERIAL | NOT NULL | SERIAL cached | INTEGER | 0 | NOT NULL | Whether this is a cached image fingerprint | VARCHAR(255) | - | NOT NULL | Tarball fingerprint filename | VARCHAR(255) | - | NOT NULL | Tarball filename size | INTEGER | - | NOT NULL | Tarball size public | INTEGER | 0 | NOT NULL | Whether the image is public or not auto\_update | INTEGER | 0 | NOT NULL | Whether to update from the source of this image architecture | INTEGER | - | NOT NULL | Image architecture creation\_date | DATETIME | - | | Image creation date (user supplied, 0 = unknown) expiry\_date | DATETIME | - | | Image expiry (user supplied, 0 = never) upload\_date | DATETIME | - | NOT NULL | Image entry creation date last\_use\_date | DATETIME | - | | Last time the image was used to spawn a container Index: UNIQUE ON id AND fingerprint ## images\_aliases Column | Type | Default | Constraint | Description :----- | :--- | :------ | :--------- | :---------- id | INTEGER | SERIAL | NOT NULL | SERIAL name | VARCHAR(255) | - | NOT NULL | Alias name image\_id | INTEGER | - | NOT NULL | images.id FK description | VARCHAR(255) | - | | Description of the alias Index: UNIQUE ON id AND name Foreign keys: image\_id REFERENCES images(id) ## images\_properties Column | Type | Default | Constraint | Description :----- | :--- | :------ | :--------- | :---------- id | INTEGER | SERIAL | NOT NULL | SERIAL image\_id | INTEGER | - | NOT NULL | images.id FK type | INTEGER | 0 | NOT NULL | Property type (0 = string, 1 = text) key | VARCHAR(255) | - | NOT NULL | Property name value | TEXT | - | | Property value (NULL for unset) Index: UNIQUE ON id Foreign keys: image\_id REFERENCES images(id) ## images\_source Column | Type | Default | Constraint | Description :----- | :--- | :------ | :--------- | :---------- id | INTEGER | SERIAL | NOT NULL | SERIAL image\_id | INTEGER | - | NOT NULL | images.id FK server | TEXT | - | NOT NULL | Server URL protocol | INTEGER | 0 | NOT NULL | Protocol to access the remote (0 = lxd, 1 = direct, 2 = simplestreams) alias | VARCHAR(255) | - | NOT NULL | What remote alias to use as the source certificate | TEXT | - | | PEM encoded certificate of the server Index: UNIQUE ON id Foreign keys: image\_id REFERENCES images(id) ## profiles Column | Type | Default | Constraint | Description :----- | :--- | :------ | :--------- | :---------- id | INTEGER | SERIAL | NOT NULL | SERIAL name | VARCHAR(255) | - | NOT NULL | Profile name description | TEXT | - | | Description of the profile Index: UNIQUE on id AND name ## profiles\_config Column | Type | Default | Constraint | Description :----- | :--- | :------ | :--------- | :---------- id | INTEGER | SERIAL | NOT NULL | SERIAL profile\_id | INTEGER | - | NOT NULL | profiles.id FK key | VARCHAR(255) | - | NOT NULL | Configuration key value | VARCHAR(255) | - | | Configuration value (NULL for unset) Index: UNIQUE ON id AND profile\_id + key Foreign keys: profile\_id REFERENCES profiles(id) ## profiles\_devices Column | Type | Default | Constraint | Description :----- | :--- | :------ | :--------- | :---------- id | INTEGER | SERIAL | NOT NULL | SERIAL profile\_id | INTEGER | - | NOT NULL | profiles.id FK name | VARCHAR(255) | - | NOT NULL | Container name type | INTEGER | 0 | NOT NULL | Device type (see configuration.md) Index: UNIQUE ON id AND profile\_id + name Foreign keys: profile\_id REFERENCES profiles(id) ## profiles\_devices\_config Column | Type | Default | Constraint | Description :----- | :--- | :------ | :--------- | :---------- id | INTEGER | SERIAL | NOT NULL | SERIAL profile\_device\_id | INTEGER | - | NOT NULL | profiles\_devices.id FK key | VARCHAR(255) | - | NOT NULL | Configuration key value | TEXT | - | | Configuration value (NULL for unset) Index: UNIQUE ON id AND profile\_device\_id + key Foreign keys: profile\_device\_id REFERENCES profiles\_devices(id) ## schema Column | Type | Default | Constraint | Description :----- | :--- | :------ | :--------- | :---------- id | INTEGER | SERIAL | NOT NULL | SERIAL version | INTEGER | - | NOT NULL | Schema version updated\_at | DATETIME | - | NOT NULL | When the schema update was done Index: UNIQUE ON id AND version lxd-2.0.0/doc/dev-lxd.md000066400000000000000000000047021270277227600147510ustar00rootroot00000000000000# Introduction Communication between the hosted workload (container) and its host while not strictly needed is a pretty useful feature. In LXD, this feature is implemented through a /dev/lxd/sock node which is created and setup for all LXD containers. This file is a Unix socket which processes inside the container can connect to. It's multi-threaded so multiple clients can be connected at the same time. # Implementation details LXD on the host binds /var/lib/lxd/devlxd and starts listening for new connections on it. This socket is then bind-mounted into every single container started by LXD at /dev/lxd/sock. The bind-mount is required so we can exceed 4096 containers, otherwise, LXD would have to bind a different socket for every container, quickly reaching the FD limit. # Authentication Queries on /dev/lxd/sock will only return information related to the requesting container. To figure out where a request comes from, LXD will extract the initial socket ucred and compare that to the list of containers it manages. # Protocol The protocol on /dev/lxd/sock is plain-text HTTP with JSON messaging, so very similar to the local version of the LXD protocol. Unlike the main LXD API, there is no background operation and no authentication support in the /dev/lxd/sock API. # REST-API ## API structure * / * /1.0 * /1.0/config * /1.0/config/{key} * /1.0/meta-data ## API details ### / #### GET * Description: List of supported APIs * Return: list of supported API endpoint URLs (by default ['/1.0']) Return value: [ "/1.0" ] ### /1.0 #### GET * Description: Information about the 1.0 API * Return: dict Return value: { "api_version": "1.0" } ### /1.0/config #### GET * Description: List of configuration keys * Return: list of configuration keys URL Note that the configuration key names match those in the container config, however not all configuration namespaces will be exported to /dev/lxd/sock. Currently only the user.\* keys are accessible to the container. At this time, there also aren't any container-writable namespace. Return value: [ "/1.0/config/user.a" ] ### /1.0/config/\ #### GET * Description: Value of that key * Return: Plain-text value Return value: blah ### /1.0/meta-data #### GET * Description: Container meta-data compatible with cloud-init * Return: cloud-init meta-data Return value: #cloud-config instance-id: abc local-hostname: abc lxd-2.0.0/doc/environment.md000066400000000000000000000020271270277227600157500ustar00rootroot00000000000000# Introduction The LXD client and daemon respect some environment variables to adapt to the user's environment and to turn some advanced features on and off. # Common LXD\_DIR | The LXD data directory PATH | List of paths to look into when resolving binaries http\_proxy | Proxy server URL for HTTP https\_proxy | Proxy server URL for HTTPs no\_proxy | List of domains that don't require the use of a proxy # Client environment variable Name | Description :--- | :---- EDITOR | What text editor to use VISUAL | What text editor to use (if EDITOR isn't set) # Server environment variable Name | Description :--- | :---- LXD\_SECURITY\_APPARMOR | If set to "false", forces AppArmor off LXD\_LXC\_TEMPLATE\_CONFIG | Path to the LXC template configuration directory lxd-2.0.0/doc/image-handling.md000066400000000000000000000113361270277227600162530ustar00rootroot00000000000000# Introduction LXD uses an image based workflow. It comes with a built-in image store where the user or external tools can import images. Containers are then started from those images. It's possible to spawn remote containers using local images or local containers using remote images. In such cases, the image may be cached on the target LXD. # Caching When spawning a container from a remote image, the remote image is downloaded into the local image store with the cached bit set. The image will be kept locally as a private image until either it's been unused (no new container spawned) for the number of days set in images.remote\_cache\_expiry or until the image's expiry is reached whichever comes first. LXD keeps track of image usage by updating the last\_used\_at image property every time a new container is spawned from the image. # Auto-update LXD can keep images up to date. By default, any image which comes from a remote server and was requested through an alias will be automatically updated by LXD. This can be changed with images.auto\_update\_cached. On startup and then every 6 hours (unless images.auto\_update\_interval is set), the LXD daemon will go look for more recent version of all the images in the store which are marked as auto-update and have a recorded source server. When a new image is found, it is downloaded into the image store, the aliases pointing to the old image are moved to the new one and the old image is removed from the store. The user can also request a particular image be kept up to date when manually copying an image from a remote server. # Image format LXD currently supports two LXD-specific image formats. The first is a unified tarball, where a single tarball contains both the container rootfs and the needed metadata. The second is a split model, using two tarballs instead, one containing the rootfs, the other containing the metadata. The former is what's produced by LXD itself and what people should be using for LXD-specific images. The latter is designed to allow for easy image building from existing non-LXD rootfs tarballs already available today. ## Unified tarball Tarball, can be compressed and contains: - rootfs/ - metadata.yaml - templates/ (optional) In this mode, the image identifier is the SHA-256 of the tarball. ## Split tarballs Two (possibly compressed) tarballs. One for metadata, one for the rootfs. metadata.tar contains: - metadata.yaml - templates/ (optional) rootfs.tar contains a Linux root filesystem at its root. In this mode the image identifier is the SHA-256 of the concatenation of the metadata and rootfs tarball (in that order). ## Content The rootfs directory (or tarball) contains a full file system tree of what will become the container's /. The templates directory contains pongo2-formatted templates of files inside the container. metadata.yaml contains information relevant to running the image under LXD, at the moment, this contains: architecture: x86_64 creation_date: 1424284563 properties: description: Ubuntu 14.04 LTS Intel 64bit os: Ubuntu release: - trusty - 14.04 templates: /etc/hosts: when: - create - rename template: hosts.tpl properties: foo: bar /etc/hostname: when: - start template: hostname.tpl /etc/network/interfaces: when: - create template: interfaces.tpl create_only: true The architecture and creation\_date fields are mandatory, the properties are just a set of default properties for the image. The os, release, name and description fields while not mandatory in any way, should be pretty common. For templates, the "when" key can be one or more of: - create (run at the time a new container is created from the image) - copy (run when a container is created from an existing one) - start (run every time the container is started) The templates will always receive the following context: - trigger: name of the event which triggered the template (string) - path: path of the file being templated (string) - container: key/value map of container properties (name, architecture, privileged and ephemeral) (map[string]string) - config: key/value map of the container's configuration (map[string]string) - devices: key/value map of the devices assigned to this container (map[string]map[string]string) - properties: key/value map of the template properties specified in metadata.yaml (map[string]string) The "create\_only" key can be set to have LXD only only create missing files but not overwrite an existing file. As a general rule, you should never template a file which is owned by a package or is otherwise expected to be overwritten by normal operation of the container. lxd-2.0.0/doc/lxd-ssl-authentication.md000066400000000000000000000106441270277227600200130ustar00rootroot00000000000000# Introduction Local communications over the UNIX socket happen over a cleartext HTTP socket and access is restricted by socket ownership and mode. Remote communications with the LXD daemon happen using JSON over HTTPS. The supported protocol must be TLS1.2 or better. All communications must use perfect forward secrecy and ciphers must be limited to strong elliptic curve ones (such as ECDHE-RSA or ECDHE-ECDSA). Any generated key should be at least 4096bit RSA and when using signatures, only SHA-2 signatures should be trusted. Since we control both client and server, there is no reason to support any backward compatibility to broken protocol or ciphers. Both the client and the server will generate a keypair the first time they're launched. The server will use that for all https connections to the LXD socket and the client will use its certificate as a client certificate for any client-server communication. # Adding a remote with a default setup In the default setup, when the user adds a new server with "lxc remote add", the server will be contacted over HTTPs, its certificate downloaded and the fingerprint will be shown to the user. The user will then be asked to confirm that this is indeed the server's fingerprint which they can manually check by connecting to or asking someone with access to the server to run the status command and compare the fingerprints. After that, the user must enter the trust password for that server, if it matches, the client certificate is added to the server's trust store and the client can now connect to the server without having to provide any additional credentials. This is a workflow that's very similar to that of ssh where an initial connection to an unknown server triggers a prompt. A possible extension to that is to support something similar to ssh's fingerprint in DNS feature where the certificate fingerprint is added as a TXT record, then if the domain is signed by DNSSEC, the client will automatically accept the fingerprint if it matches that in the DNS record. # Adding a remote with a PKI based setup In the PKI setup, a system administrator is managing a central PKI, that PKI then issues client certificates for all the lxc clients and server certificates for all the LXD daemons. Those certificates and keys are manually put in place on the various machines, replacing the automatically generated ones. The CA certificate is also added to all machines. A CRL may also accompany the CA certificate. In that mode, any connection to a LXD daemon will be done using the preseeded CA certificate. If the server certificate isn't signed by the CA, or if it has been revoked, the connection will simply go through the normal authentication mechanism. If the server certificate is valid and signed by the CA, then the connection continues without prompting the user for the certificate. After that, the user must enter the trust password for that server, if it matches, the client certificate is added to the server's trust store and the client can now connect to the server without having to provide any additional credentials. # Password prompt To establish a new trust relationship, a password must be set on the server and send by the client when adding itself. A remote add operation should therefore go like this: 1. Call GET /1.0 2. If we're not in a PKI setup ask the user to confirm the fingerprint. 3. Look at the dict we received back from the server. If "auth" is "untrusted", ask the user for the server's password and do a POST to /1.0/certificates, then call /1.0 again to check that we're indeed trusted. 4. Remote is now ready # Failure scenarios ## Server certificate changes This will typically happen in two cases: * The server was fully reinstalled and so changed certificate * The connection is being intercepted (MITM) In such cases the client will refuse to connect to the server since the certificate fringerprint will not match that in the config for this remote. It is then up to the user to contact the server administrator to check if the certificate did in fact change. If it did, then the certificate can be replaced by the new one or the remote be removed altogether and re-added. ## Server trust relationship revoked In this case, the server still uses the same certificate but all API calls return a 403 with an error indicating that the client isn't trusted. This happens if another trusted client or the local server administrator removed the trust entry on the server. lxd-2.0.0/doc/migration.md000066400000000000000000000043221270277227600153750ustar00rootroot00000000000000# Live Migration in LXD ## Overview Migration has two pieces, a "source", that is, the host that already has the container, and a "sink", the host that's getting the container. Currently, in the 'pull' mode, the source sets up an operation, and the sink connects to the source and pulls the container. There are three websockets (channels) used in migration: 1. the control stream 2. the criu images stream 3. the filesystem stream When a migration is initiated, information about the container, its configuration, etc. are sent over the control channel (a full description of this process is below), the criu images and container filesystem are synced over their respective channels, and the result of the restore operation is sent from the sink to the source over the control channel. In particular, the protocol that is spoken over the criu channel and filesystem channel can vary, depending on what is negotiated over the control socket. For example, both the source and the sink's LXD directory is on btrfs, the filesystem socket can speak btrfs-send/receive. Additionally, although we do a "stop the world" type migration right now, support for criu's p.haul protocol will happen over the criu socket at some later time. ## Control Socket Once all three websockets are connected between the two endpoints, the source sends a MigrationHeader (protobuf description found in `/lxd/migration/migrate.proto`). This header contains the container configuration which will be added to the new container. There are also two fields indicating the filesystem and criu protocol to speak. For example, if a server is hosted on a btrfs filesystem, it can indicate that it wants to do a `btrfs send` instead of a simple rsync (similarly, it could indicate that it wants to speak the p.haul protocol, instead of just rsyncing the images over slowly). The sink then examines this message and responds with whatever it supports. Continuing our example, if the sink is not on a btrfs filesystem, it responds with the lowest common denominator (rsync, in this case), and the source is to send the root filesystem using rsync. Similarly with the criu connection; if the sink doesn't have support for the p.haul protocol (or whatever), we fall back to rsync. lxd-2.0.0/doc/requirements.md000066400000000000000000000015321270277227600161270ustar00rootroot00000000000000# Requirements ## Go LXD requires Go 1.5 or higher. Both the golang and gccgo compilers are supported. ## Kernel requirements The minimum supported kernel version is 3.13. LXD requires a kernel with support for: * Namespaces (pid, net, uts, ipc and mount) * Seccomp The following optional features also require extra kernel options: * Namespaces (user and cgroup) * AppArmor (including Ubuntu patch for mount mediation) * Control Groups (blkio, cpuset, devices, memory, pids and net\_prio) * CRIU (exact details to be found with CRIU upstream) As well as any other kernel feature required by the LXC version in use. ## LXC LXD requires LXC 1.1.5 or higher with the following build options: * apparmor (if using LXD's apparmor support) * seccomp To run recent version of various distributions, including Ubuntu, LXCFS should also be installed. lxd-2.0.0/doc/rest-api.md000066400000000000000000001473011270277227600151350ustar00rootroot00000000000000# Introduction All the communications between LXD and its clients happen using a RESTful API over http which is then encapsulated over either SSL for remote operations or a unix socket for local operations. Not all of the REST interface requires authentication: * GET to / is allowed for everyone (lists the API endpoints) * GET to /1.0 is allowed for everyone (but result varies) * POST to /1.0/certificates is allowed for everyone with a client certificate * GET to /1.0/images/\* is allowed for everyone but only returns public images for unauthenticated users Unauthenticated endpoints are clearly identified as such below. # API versioning The list of supported major API versions can be retrieved using GET /. The reason for a major API bump is if the API breaks backward compatibility. Feature additions done without breaking backward compatibility only result in addition to api\_extensions which can be used by the client to check if a given feature is supported by the server. # Return values There are three standard return types: * Standard return value * Background operation * Error ### Standard return value For a standard synchronous operation, the following dict is returned: { "type": "sync", "status": "Success", "status_code": 200, "metadata": {} # Extra resource/action specific metadata } HTTP code must be 200. ### Background operation When a request results in a background operation, the HTTP code is set to 202 (Accepted) and the Location HTTP header is set to the operation URL. The body is a dict with the following structure: { "type": "async", "status": "OK", "status_code": 100, "operation": "/1.0/containers/", # URL to the background operation "metadata": {} # Operation metadata (see below) } The operation metadata structure looks like: { "id": "a40f5541-5e98-454f-b3b6-8a51ef5dbd3c", # UUID of the operation "class": "websocket", # Class of the operation (task, websocket or token) "created_at": "2015-11-17T22:32:02.226176091-05:00", # When the operation was created "updated_at": "2015-11-17T22:32:02.226176091-05:00", # Last time the operation was updated "status": "Running", # String version of the operation's status "status_code": 103, # Integer version of the operation's status (use this rather than status) "resources": { # Dictionary of resource types (container, snapshots, images) and affected resources "containers": [ "/1.0/containers/test" ] }, "metadata": { # Metadata specific to the operation in question (in this case, exec) "fds": { "0": "2a4a97af81529f6608dca31f03a7b7e47acc0b8dc6514496eb25e325f9e4fa6a", "control": "5b64c661ef313b423b5317ba9cb6410e40b705806c28255f601c0ef603f079a7" } }, "may_cancel": false, # Whether the operation can be canceled (DELETE over REST) "err": "" # The error string should the operation have failed } The body is mostly provided as a user friendly way of seeing what's going on without having to pull the target operation, all information in the body can also be retrieved from the background operation URL. ### Error There are various situations in which something may immediately go wrong, in those cases, the following return value is used: { "type": "error", "error": "Failure", "error_code": 400, "metadata": {} # More details about the error } HTTP code must be one of of 400, 401, 403, 404, 409, 412 or 500. # Status codes The LXD REST API often has to return status information, be that the reason for an error, the current state of an operation or the state of the various resources it exports. To make it simple to debug, all of those are always doubled. There is a numeric representation of the state which is guaranteed never to change and can be relied on by API clients. Then there is a text version meant to make it easier for people manually using the API to figure out what's happening. In most cases, those will be called status and status\_code, the former being the user-friendly string representation and the latter the fixed numeric value. The codes are always 3 digits, with the following ranges: * 100 to 199: resource state (started, stopped, ready, ...) * 200 to 399: positive action result * 400 to 599: negative action result * 600 to 999: future use ## List of current status codes Code | Meaning :--- | :------ 100 | Operation created 101 | Started 102 | Stopped 103 | Running 104 | Cancelling 105 | Pending 106 | Starting 107 | Stopping 108 | Aborting 109 | Freezing 110 | Frozen 111 | Thawed 200 | Success 400 | Failure 401 | Cancelled # Recursion To optimize queries of large lists, recursion is implemented for collections. A "recursion" argument can be passed to a GET query against a collection. The default value is 0 which means that collection member URLs are returned. Setting it to 1 will have those URLs be replaced by the object they point to (typically a dict). Recursion is implemented by simply replacing any pointer to an job (URL) by the object itself. # Async operations Any operation which may take more than a second to be done must be done in the background, returning a background operation ID to the client. The client will then be able to either poll for a status update or wait for a notification using the long-poll API. # Notifications A websocket based API is available for notifications, different notification types exist to limit the traffic going to the client. It's recommended that the client always subscribes to the operations notification type before triggering remote operations so that it doesn't have to then poll for their status. # API structure * / * /1.0 * /1.0/certificates * /1.0/certificates/\ * /1.0/containers * /1.0/containers/\ * /1.0/containers/\/exec * /1.0/containers/\/files * /1.0/containers/\/snapshots * /1.0/containers/\/snapshots/\ * /1.0/containers/\/state * /1.0/containers/\/logs * /1.0/containers/\/logs/\ * /1.0/events * /1.0/images * /1.0/images/\ * /1.0/images/\/export * /1.0/images/aliases * /1.0/images/aliases/\ * /1.0/networks * /1.0/networks/\ * /1.0/operations * /1.0/operations/\ * /1.0/operations/\/wait * /1.0/operations/\/websocket * /1.0/profiles * /1.0/profiles/\ # API details ## / ### GET * Description: List of supported APIs * Authentication: guest * Operation: sync * Return: list of supported API endpoint URLs Return value: [ "/1.0" ] ## /1.0/ ### GET * Description: Server configuration and environment information * Authentication: guest, untrusted or trusted * Operation: sync * Return: Dict representing server state Return value (if trusted): { "api_extensions": [], # List of API extensions added after the API was marked stable "api_status": "stable", # API implementation status (one of, development, stable or deprecated) "api_version": "1.0", # The API version as a string "auth": "trusted", # Authentication state, one of "guest", "untrusted" or "trusted" "config": { # Host configuration "core.trust_password": true, "core.https_address": "[::]:8443" }, "environment": { # Various information about the host (OS, kernel, ...) "addresses": [ "1.2.3.4:8443", "[1234::1234]:8443" ], "architectures": [ "x86_64", "i686" ], "certificate": "PEM certificate", "driver": "lxc", "driver_version": "1.0.6", "kernel": "Linux", "kernel_architecture": "x86_64", "kernel_version": "3.16", "server": "lxd", "server_pid": 10224, "server_version": "0.8.1"} "storage": "btrfs", "storage_version": "3.19", }, "public": false, # Whether the server should be treated as a public (read-only) remote by the client } Return value (if guest or untrusted): { "api_extensions": [], # List of API extensions added after the API was marked stable "api_status": "stable", # API implementation status (one of, development, stable or deprecated) "api_version": "1.0", # The API version as a string "auth": "guest", # Authentication state, one of "guest", "untrusted" or "trusted" "public": false, # Whether the server should be treated as a public (read-only) remote by the client } ### PUT * Description: Updates the server configuration or other properties * Authentication: trusted * Operation: sync * Return: standard return value or standard error Input (replaces any existing config with the provided one): { "config": { "core.trust_password": "my-new-password", "storage.zfs_pool_name": "lxd" } } ## /1.0/certificates ### GET * Description: list of trusted certificates * Authentication: trusted * Operation: sync * Return: list of URLs for trusted certificates Return: [ "/1.0/certificates/3ee64be3c3c7d617a7470e14f2d847081ad467c8c26e1caad841c8f67f7c7b09" ] ### POST * Description: add a new trusted certificate * Authentication: trusted or untrusted * Operation: sync * Return: standard return value or standard error Input: { "type": "client", # Certificate type (keyring), currently only client "certificate": "PEM certificate", # If provided, a valid x509 certificate. If not, the client certificate of the connection will be used "name": "foo" # An optional name for the certificate. If nothing is provided, the host in the TLS header for the request is used. "password": "server-trust-password" # The trust password for that server (only required if untrusted) } ## /1.0/certificates/\ ### GET * Description: trusted certificate information * Authentication: trusted * Operation: sync * Return: dict representing a trusted certificate Output: { "type": "client", "certificate": "PEM certificate" "fingerprint": "SHA256 Hash of the raw certificate" } ### DELETE * Description: Remove a trusted certificate * Authentication: trusted * Operation: sync * Return: standard return value or standard error Input (none at present): { } HTTP code for this should be 202 (Accepted). ## /1.0/containers ### GET * Description: List of containers * Authentication: trusted * Operation: sync * Return: list of URLs for containers this server publishes Return value: [ "/1.0/containers/blah", "/1.0/containers/blah1" ] ### POST * Description: Create a new container * Authentication: trusted * Operation: async * Return: background operation or standard error Input (container based on a local image with the "ubuntu/devel" alias): { "name": "my-new-container", # 64 chars max, ASCII, no slash, no colon and no comma "architecture": "x86_64", "profiles": ["default"], # List of profiles "ephemeral": true, # Whether to destroy the container on shutdown "config": {"limits.cpu": "2"}, # Config override. "source": {"type": "image", # Can be: "image", "migration", "copy" or "none" "alias": "ubuntu/devel"}, # Name of the alias } Input (container based on a local image identified by its fingerprint): { "name": "my-new-container", # 64 chars max, ASCII, no slash, no colon and no comma "architecture": "x86_64", "profiles": ["default"], # List of profiles "ephemeral": true, # Whether to destroy the container on shutdown "config": {"limits.cpu": "2"}, # Config override. "source": {"type": "image", # Can be: "image", "migration", "copy" or "none" "fingerprint": "SHA-256"}, # Fingerprint } Input (container based on most recent match based on image properties): { "name": "my-new-container", # 64 chars max, ASCII, no slash, no colon and no comma "architecture": "x86_64", "profiles": ["default"], # List of profiles "ephemeral": true, # Whether to destroy the container on shutdown "config": {"limits.cpu": "2"}, # Config override. "source": {"type": "image", # Can be: "image", "migration", "copy" or "none" "properties": { # Properties "os": "ubuntu", "release": "14.04", "architecture": "x86_64" }}, } Input (container without a pre-populated rootfs, useful when attaching to an existing one): { "name": "my-new-container", # 64 chars max, ASCII, no slash, no colon and no comma "architecture": "x86_64", "profiles": ["default"], # List of profiles "ephemeral": true, # Whether to destroy the container on shutdown "config": {"limits.cpu": "2"}, # Config override. "source": {"type": "none"}, # Can be: "image", "migration", "copy" or "none" } Input (using a public remote image): { "name": "my-new-container", # 64 chars max, ASCII, no slash, no colon and no comma "architecture": "x86_64", "profiles": ["default"], # List of profiles "ephemeral": true, # Whether to destroy the container on shutdown "config": {"limits.cpu": "2"}, # Config override. "source": {"type": "image", # Can be: "image", "migration", "copy" or "none" "mode": "pull", # One of "local" (default) or "pull" "server": "https://10.0.2.3:8443", # Remote server (pull mode only) "protocol": "lxd", # Protocol (one of lxd or simplestreams, defaults to lxd) "certificate": "PEM certificate", # Optional PEM certificate. If not mentioned, system CA is used. "alias": "ubuntu/devel"}, # Name of the alias } Input (using a private remote image after having obtained a secret for that image): { "name": "my-new-container", # 64 chars max, ASCII, no slash, no colon and no comma "architecture": "x86_64", "profiles": ["default"], # List of profiles "ephemeral": true, # Whether to destroy the container on shutdown "config": {"limits.cpu": "2"}, # Config override. "source": {"type": "image", # Can be: "image", "migration", "copy" or "none" "mode": "pull", # One of "local" (default) or "pull" "server": "https://10.0.2.3:8443", # Remote server (pull mode only) "secret": "my-secret-string", # Secret to use to retrieve the image (pull mode only) "certificate": "PEM certificate", # Optional PEM certificate. If not mentioned, system CA is used. "alias": "ubuntu/devel"}, # Name of the alias } Input (using a remote container, sent over the migration websocket): { "name": "my-new-container", # 64 chars max, ASCII, no slash, no colon and no comma "architecture": "x86_64", "profiles": ["default"], # List of profiles "ephemeral": true, # Whether to destroy the container on shutdown "config": {"limits.cpu": "2"}, # Config override. "source": {"type": "migration", # Can be: "image", "migration", "copy" or "none" "mode": "pull", # Only "pull" is supported for now "operation": "https://10.0.2.3:8443/1.0/operations/", # Full URL to the remote operation (pull mode only) "certificate": "PEM certificate", # Optional PEM certificate. If not mentioned, system CA is used. "base-image": "", # Optional, the base image the container was created from "secrets": {"control": "my-secret-string", # Secrets to use when talking to the migration source "criu": "my-other-secret", "fs": "my third secret"}, } Input (using a local container): { "name": "my-new-container", # 64 chars max, ASCII, no slash, no colon and no comma "architecture": "x86_64", "profiles": ["default"], # List of profiles "ephemeral": true, # Whether to destroy the container on shutdown "config": {"limits.cpu": "2"}, # Config override. "source": {"type": "copy", # Can be: "image", "migration", "copy" or "none" "source": "my-old-container"} # Name of the source container } ## /1.0/containers/\ ### GET * Description: Container information * Authentication: trusted * Operation: sync * Return: dict of the container configuration and current state. Output: { "architecture": "x86_64", "config": { "limits.cpu": "3", "volatile.base_image": "97d97a3d1d053840ca19c86cdd0596cf1be060c5157d31407f2a4f9f350c78cc", "volatile.eth0.hwaddr": "00:16:3e:1c:94:38" }, "created_at": "2016-02-16T01:05:05Z", "devices": { "rootfs": { "path": "/", "type": "disk" } }, "ephemeral": false, "expanded_config": { # the result of expanding profiles and adding the container's local config "limits.cpu": "3", "volatile.base_image": "97d97a3d1d053840ca19c86cdd0596cf1be060c5157d31407f2a4f9f350c78cc", "volatile.eth0.hwaddr": "00:16:3e:1c:94:38" }, "expanded_devices": { # the result of expanding profiles and adding the container's local devices "eth0": { "name": "eth0", "nictype": "bridged", "parent": "lxdbr0", "type": "nic" }, "root": { "path": "/", "type": "disk" } }, "name": "my-container", "profiles": [ "default" ], "stateful": false, # If true, indicates that the container has some stored state that can be restored on startup "status": "Running", "status_code": 103 } ### PUT * Description: update container configuration or restore snapshot * Authentication: trusted * Operation: async * Return: background operation or standard error Input (update container configuration): { "architecture": "x86_64", "config": { "limits.cpu": "4", "volatile.base_image": "97d97a3d1d053840ca19c86cdd0596cf1be060c5157d31407f2a4f9f350c78cc", "volatile.eth0.hwaddr": "00:16:3e:1c:94:38" }, "devices": { "rootfs": { "path": "/", "type": "disk" } }, "ephemeral": true, "profiles": [ "default" ] } Takes the same structure as that returned by GET but doesn't allow name changes (see POST below) or changes to the status sub-dict (since that's read-only). Input (restore snapshot): { "restore": "snapshot-name" } ### POST * Description: used to rename/migrate the container * Authentication: trusted * Operation: async * Return: background operation or standard error Renaming to an existing name must return the 409 (Conflict) HTTP code. Input (simple rename): { "name": "new-name" } Input (migration across lxd instances): { "migration": true } The migration does not actually start until someone (i.e. another lxd instance) connects to all the websockets and begins negotiation with the source. Output in metadata section (for migration): { "control": "secret1", # Migration control socket "criu": "secret2", # State transfer socket (only if live migrating) "fs": "secret3" # Filesystem transfer socket } These are the secrets that should be passed to the create call. ### DELETE * Description: remove the container * Authentication: trusted * Operation: async * Return: background operation or standard error Input (none at present): { } HTTP code for this should be 202 (Accepted). ## /1.0/containers/\/state ### GET * Description: current state * Authentication: trusted * Operation: sync * Return: dict representing current state { "type": "sync", "status": "Success", "status_code": 200, "metadata": { "status": "Running", "status_code": 103, "disk": { "root": { "usage": 422330368 } }, "memory": { "usage": 51126272, "usage_peak": 70246400, "swap_usage": 0, "swap_usage_peak": 0 }, "network": { "eth0": { "addresses": [ { "family": "inet", "address": "10.0.3.27", "netmask": "24", "scope": "global" }, { "family": "inet6", "address": "fe80::216:3eff:feec:65a8", "netmask": "64", "scope": "link" } ], "counters": { "bytes_received": 33942, "bytes_sent": 30810, "packets_received": 402, "packets_sent": 178 }, "hwaddr": "00:16:3e:ec:65:a8", "host_name": "vethBWTSU5", "mtu": 1500, "state": "up", "type": "broadcast" }, "lo": { "addresses": [ { "family": "inet", "address": "127.0.0.1", "netmask": "8", "scope": "local" }, { "family": "inet6", "address": "::1", "netmask": "128", "scope": "local" } ], "counters": { "bytes_received": 86816, "bytes_sent": 86816, "packets_received": 1226, "packets_sent": 1226 }, "hwaddr": "", "host_name": "", "mtu": 65536, "state": "up", "type": "loopback" }, "lxdbr0": { "addresses": [ { "family": "inet", "address": "10.0.3.1", "netmask": "24", "scope": "global" }, { "family": "inet6", "address": "fe80::68d4:87ff:fe40:7769", "netmask": "64", "scope": "link" } ], "counters": { "bytes_received": 0, "bytes_sent": 570, "packets_received": 0, "packets_sent": 7 }, "hwaddr": "6a:d4:87:40:77:69", "host_name": "", "mtu": 1500, "state": "up", "type": "broadcast" }, "zt0": { "addresses": [ { "family": "inet", "address": "29.17.181.59", "netmask": "7", "scope": "global" }, { "family": "inet6", "address": "fd80:56c2:e21c:0:199:9379:e711:b3e1", "netmask": "88", "scope": "global" }, { "family": "inet6", "address": "fe80::79:e7ff:fe0d:5123", "netmask": "64", "scope": "link" } ], "counters": { "bytes_received": 0, "bytes_sent": 806, "packets_received": 0, "packets_sent": 9 }, "hwaddr": "02:79:e7:0d:51:23", "host_name": "", "mtu": 2800, "state": "up", "type": "broadcast" } }, "pid": 13663, "processes": 32 } } ### PUT * Description: change the container state * Authentication: trusted * Operation: async * Return: background operation or standard error Input: { "action": "stop", # State change action (stop, start, restart, freeze or unfreeze) "timeout": 30, # A timeout after which the state change is considered as failed "force": true, # Force the state change (currently only valid for stop and restart where it means killing the container) "stateful": true # Whether to store or restore runtime state before stopping or startiong (only valid for stop and start, defaults to false) } ## /1.0/containers/\/files ### GET (?path=/path/inside/the/container) * Description: download a file from the container * Authentication: trusted * Operation: sync * Return: Raw file or standard error The following headers will be set (on top of standard size and mimetype headers): * X-LXD-uid: 0 * X-LXD-gid: 0 * X-LXD-mode: 0700 This is designed to be easily usable from the command line or even a web browser. ### POST (?path=/path/inside/the/container) * Description: upload a file to the container * Authentication: trusted * Operation: sync * Return: standard return value or standard error Input: * Standard http file upload The following headers may be set by the client: * X-LXD-uid: 0 * X-LXD-gid: 0 * X-LXD-mode: 0700 This is designed to be easily usable from the command line or even a web browser. ## /1.0/containers/\/snapshots ### GET * Description: List of snapshots * Authentication: trusted * Operation: sync * Return: list of URLs for snapshots for this container Return value: [ "/1.0/containers/blah/snapshots/snap0" ] ### POST * Description: create a new snapshot * Authentication: trusted * Operation: async * Return: background operation or standard error Input: { "name": "my-snapshot", # Name of the snapshot "stateful": true # Whether to include state too } ## /1.0/containers/\/snapshots/\ ### GET * Description: Snapshot information * Authentication: trusted * Operation: sync * Return: dict representing the snapshot Return: { "architecture": "x86_64", "config": { "security.nesting": "true", "volatile.base_image": "a49d26ce5808075f5175bf31f5cb90561f5023dcd408da8ac5e834096d46b2d8", "volatile.eth0.hwaddr": "00:16:3e:ec:65:a8", "volatile.last_state.idmap": "[{\"Isuid\":true,\"Isgid\":false,\"Hostid\":100000,\"Nsid\":0,\"Maprange\":65536},{\"Isuid\":false,\"Isgid\":true,\"Hostid\":100000,\"Nsid\":0,\"Maprange\":65536}]", }, "created_at": "2016-03-08T23:55:08Z", "devices": { "eth0": { "name": "eth0", "nictype": "bridged", "parent": "lxdbr0", "type": "nic" }, "root": { "path": "/", "type": "disk" }, }, "ephemeral": false, "expanded_config": { "security.nesting": "true", "volatile.base_image": "a49d26ce5808075f5175bf31f5cb90561f5023dcd408da8ac5e834096d46b2d8", "volatile.eth0.hwaddr": "00:16:3e:ec:65:a8", "volatile.last_state.idmap": "[{\"Isuid\":true,\"Isgid\":false,\"Hostid\":100000,\"Nsid\":0,\"Maprange\":65536},{\"Isuid\":false,\"Isgid\":true,\"Hostid\":100000,\"Nsid\":0,\"Maprange\":65536}]", }, "expanded_devices": { "eth0": { "name": "eth0", "nictype": "bridged", "parent": "lxdbr0", "type": "nic" }, "root": { "path": "/", "type": "disk" }, }, "name": "zerotier/blah", "profiles": [ "default" ], "stateful": false } ### POST * Description: used to rename/migrate the snapshot * Authentication: trusted * Operation: async * Return: background operation or standard error Input (rename the snapshot): { "name": "new-name" } Input (setup the migration source): { "migration": true, } Return (with migration=true): { "control": "secret1", # Migration control socket "fs": "secret3" # Filesystem transfer socket } Renaming to an existing name must return the 409 (Conflict) HTTP code. ### DELETE * Description: remove the snapshot * Authentication: trusted * Operation: async * Return: background operation or standard error Input (none at present): { } HTTP code for this should be 202 (Accepted). ## /1.0/containers/\/exec ### POST * Description: run a remote command * Authentication: trusted * Operation: async * Return: background operation + optional websocket information or standard error Input (run bash): { "command": ["/bin/bash"], # Command and arguments "environment": {}, # Optional extra environment variables to set "wait-for-websocket": false, # Whether to wait for a connection before starting the process "interactive": true, # Whether to allocate a pts device instead of PIPEs "width": 80, # Initial width of the terminal (optional) "height": 25, # Initial height of the terminal (optional) } `wait-for-websocket` indicates whether the operation should block and wait for a websocket connection to start (so that users can pass stdin and read stdout), or simply run to completion with /dev/null as stdin and stdout. If interactive is set to true, a single websocket is returned and is mapped to a pts device for stdin, stdout and stderr of the execed process. If interactive is set to false (default), three pipes will be setup, one for each of stdin, stdout and stderr. Depending on the state of the interactive flag, one or three different websocket/secret pairs will be returned, which are valid for connecting to this operations /websocket endpoint. Return (with wait-for-websocket=true and interactive=false): { "fds": { "0": "f5b6c760c0aa37a6430dd2a00c456430282d89f6e1661a077a926ed1bf3d1c21", "1": "464dcf9f8fdce29d0d6478284523a9f26f4a31ae365d94cd38bac41558b797cf", "2": "25b70415b686360e3b03131e33d6d94ee85a7f19b0f8d141d6dca5a1fc7b00eb", "control": "20c479d9532ab6d6c3060f6cdca07c1f177647c9d96f0c143ab61874160bd8a5" } } Return (with wait-for-websocket=true and interactive=true): { "fds": { "0": "f5b6c760c0aa37a6430dd2a00c456430282d89f6e1661a077a926ed1bf3d1c21", "control": "20c479d9532ab6d6c3060f6cdca07c1f177647c9d96f0c143ab61874160bd8a5" } } When the exec command finishes, its exit status is available from the operation's metadata: { "return": 0 } ## /1.0/containers/\/logs ### GET * Description: Returns a list of the log files available for this container. Note that this works on containers that have been deleted (or were never created) to enable people to get logs for failed creations. * Authentication: trusted * Operation: Sync * Return: a list of the available log files Return: [ "/1.0/containers/blah/logs/forkstart.log", "/1.0/containers/blah/logs/lxc.conf", "/1.0/containers/blah/logs/lxc.log" ] ## /1.0/containers/\/logs/\ ### GET * Description: returns the contents of a particular log file. * Authentication: trusted * Operation: N/A * Return: the contents of the log file ### DELETE * Description: delete a particular log file. * Authentication: trusted * Operation: Sync * Return: empty response or standard error ## /1.0/events This URL isn't a real REST API endpoint, instead doing a GET query on it will upgrade the connection to a websocket on which notifications will be sent. ### GET (?type=operation,logging) * Description: websocket upgrade * Authentication: trusted * Operation: sync * Return: none (never ending flow of events) Supported arguments are: * type: comma separated list of notifications to subscribe to (defaults to all) The notification types are: * operation (notification about creation, updates and termination of all background operations) * logging (every log entry from the server) This never returns. Each notification is sent as a separate JSON dict: { "timestamp": "2015-06-09T19:07:24.379615253-06:00", # Current timestamp "type": "operation", # Notification type "metadata": {} # Extra resource or type specific metadata } { "timestamp": "2016-02-17T11:44:28.572721913-05:00", "type": "logging", "metadata": { "context": { "ip": "@", "method": "GET" "url": "/1.0/containers/xen/snapshots", }, "level": "info", "message": "handling" } } ## /1.0/images ### GET * Description: list of images (public or private) * Authentication: guest or trusted * Operation: sync * Return: list of URLs for images this server publishes Return: [ "/1.0/images/54c8caac1f61901ed86c68f24af5f5d3672bdc62c71d04f06df3a59e95684473", "/1.0/images/97d97a3d1d053840ca19c86cdd0596cf1be060c5157d31407f2a4f9f350c78cc", "/1.0/images/a49d26ce5808075f5175bf31f5cb90561f5023dcd408da8ac5e834096d46b2d8", "/1.0/images/c9b6e738fae75286d52f497415463a8ecc61bbcb046536f220d797b0e500a41f" ] ### POST * Description: create and publish a new image * Authentication: trusted * Operation: async * Return: background operation or standard error Input (one of): * Standard http file upload * Source image dictionary (transfers a remote image) * Source container dictionary (makes an image out of a local container) * Remote image URL dictionary (downloads a remote image) In the http file upload case, The following headers may be set by the client: * X-LXD-fingerprint: SHA-256 (if set, uploaded file must match) * X-LXD-filename: FILENAME (used for export) * X-LXD-public: true/false (defaults to false) * X-LXD-properties: URL-encoded key value pairs without duplicate keys (optional properties) In the source image case, the following dict must be used: { "filename": filename, # Used for export (optional) "public": true, # Whether the image can be downloaded by untrusted users (defaults to false) "auto_update": true, # Whether the image should be auto-updated (optional; defaults to false) "properties": { # Image properties (optional, applied on top of source properties) "os": "Ubuntu" }, "source": { "type": "image", "mode": "pull", # Only pull is supported for now "server": "https://10.0.2.3:8443", # Remote server (pull mode only) "protocol": "lxd", # Protocol (one of lxd or simplestreams, defaults to lxd) "secret": "my-secret-string", # Secret (pull mode only, private images only) "certificate": "PEM certificate", # Optional PEM certificate. If not mentioned, system CA is used. "fingerprint": "SHA256", # Fingerprint of the image (must be set if alias isn't) "alias": "ubuntu/devel", # Name of the alias (must be set if fingerprint isn't) } } In the source container case, the following dict must be used: { "filename": filename, # Used for export (optional) "public": true, # Whether the image can be downloaded by untrusted users (defaults to false) "properties": { # Image properties (optional) "os": "Ubuntu" }, "source": { "type": "container", # One of "container" or "snapshot" "name": "abc" } } In the remote image URL case, the following dict must be used: { "filename": filename, # Used for export (optional) "public": true, # Whether the image can be downloaded by untrusted users (defaults to false) "properties": { # Image properties (optional) "os": "Ubuntu" }, "source": { "type": "url", "url": "https://www.some-server.com/image" # URL for the image } } After the input is received by LXD, a background operation is started which will add the image to the store and possibly do some backend filesystem-specific optimizations. ## /1.0/images/\ ### GET (optional ?secret=SECRET) * Description: Image description and metadata * Authentication: guest or trusted * Operation: sync * Return: dict representing an image properties Output: { "aliases": [ { "name": "trusty", "description": "", } ], "architecture": "x86_64", "auto_update": true, "cached": false, "fingerprint": "54c8caac1f61901ed86c68f24af5f5d3672bdc62c71d04f06df3a59e95684473", "filename": "ubuntu-trusty-14.04-amd64-server-20160201.tar.xz", "properties": { "architecture": "x86_64", "description": "Ubuntu 14.04 LTS server (20160201)", "os": "ubuntu", "release": "trusty" }, "update_source": { "server": "https://10.1.2.4:8443", "protocol": "lxd", "certificate": "PEM certificate", "alias": "ubuntu/trusty/amd64" }, "public": false, "size": 123792592, "created_at": "2016-02-01T21:07:41Z", "expires_at": "1970-01-01T00:00:00Z", "last_used_at": "1970-01-01T00:00:00Z", "uploaded_at": "2016-02-16T00:44:47Z" } ### DELETE * Description: Remove an image * Authentication: trusted * Operation: async * Return: background operaton or standard error Input (none at present): { } HTTP code for this should be 202 (Accepted). ### PUT * Description: Updates the image properties * Authentication: trusted * Operation: sync * Return: standard return value or standard error Input: { "auto_update": true, "properties": { "architecture": "x86_64", "description": "Ubuntu 14.04 LTS server (20160201)", "os": "ubuntu", "release": "trusty" }, "public": true, } ## /1.0/images/\/export ### GET (optional ?secret=SECRET) * Description: Download the image tarball * Authentication: guest or trusted * Operation: sync * Return: Raw file or standard error The secret string is required when an untrusted LXD is spawning a new container from a private image stored on a different LXD. Rather than require a trust relationship between the two LXDs, the client will POST to /1.0/images/\/export to get a secret token which it'll then pass to the target LXD. That target LXD will then GET the image as a guest, passing the secret token. ## /1.0/images/\/secret ### POST * Description: Generate a random token and tell LXD to expect it be used by a guest * Authentication: guest or trusted * Operation: async * Return: background operation or standard error Input: { } Return: { "secret": "52e9ec5885562aa24d05d7b4846ebb8b5f1f7bf5cd6e285639b569d9eaf54c9b" } Standard backround operation with "secret" set to the generated secret string in metadata. The secret is automatically invalidated 5s after an image URL using it has been accessed. This allows to both retried the image information and then hit /export with the same secret. ## /1.0/images/aliases ### GET * Description: list of aliases (public or private based on image visibility) * Authentication: guest or trusted * Operation: sync * Return: list of URLs for aliases this server knows about Return: [ "/1.0/images/aliases/sl6", "/1.0/images/aliases/trusty", "/1.0/images/aliases/xenial" ] ### POST * Description: create a new alias * Authentication: trusted * Operation: sync * Return: standard return value or standard error Input: { "description": "The alias description", "target": "SHA-256", "name": "alias-name" } ## /1.0/images/aliases/\ ### GET * Description: Alias description and target * Authentication: guest or trusted * Operation: sync * Return: dict representing an alias description and target Output: { "name": "test", "description": "my description", "target": "c9b6e738fae75286d52f497415463a8ecc61bbcb046536f220d797b0e500a41f" } ### PUT * Description: Updates the alias target or description * Authentication: trusted * Operation: sync * Return: standard return value or standard error Input: { "description": "New description", "target": "54c8caac1f61901ed86c68f24af5f5d3672bdc62c71d04f06df3a59e95684473" } ### POST * Description: rename an alias * Authentication: trusted * Operation: sync * Return: standard return value or standard error Input: { "name": "new-name" } Renaming to an existing name must return the 409 (Conflict) HTTP code. ### DELETE * Description: Remove an alias * Authentication: trusted * Operation: sync * Return: standard return value or standard error Input (none at present): { } ## /1.0/networks ### GET * Description: list of networks * Authentication: trusted * Operation: sync * Return: list of URLs for networks that are current defined on the host [ "/1.0/networks/eth0",, "/1.0/networks/lxdbr0" ] ## /1.0/networks/\ ### GET * Description: information about a network * Authentication: trusted * Operation: sync * Return: dict representing a network { "name": "lxdbr0", "type": "bridge", "used_by": [ "/1.0/containers/blah" ] } ## /1.0/operations ### GET * Description: list of operations * Authentication: trusted * Operation: sync * Return: list of URLs for operations that are currently going on/queued [ "/1.0/operations/c0fc0d0d-a997-462b-842b-f8bd0df82507", "/1.0/operations/092a8755-fd90-4ce4-bf91-9f87d03fd5bc" ] ## /1.0/operations/\ ### GET * Description: background operation * Authentication: trusted * Operation: sync * Return: dict representing a background operation Return: { "id": "b8d84888-1dc2-44fd-b386-7f679e171ba5", "class": "token", # One of "task" (background task), "websocket" (set of websockets and crendentials) or "token" (temporary credentials) "created_at": "2016-02-17T16:59:27.237628195-05:00", # Creation timestamp "updated_at": "2016-02-17T16:59:27.237628195-05:00", # Last update timestamp "status": "Running", "status_code": 103, "resources": { # List of affected resources "images": [ "/1.0/images/54c8caac1f61901ed86c68f24af5f5d3672bdc62c71d04f06df3a59e95684473" ] }, "metadata": { # Extra information about the operation (action, target, ...) "secret": "c9209bee6df99315be1660dd215acde4aec89b8e5336039712fc11008d918b0d" }, "may_cancel": true, # Whether it's possible to cancel the operation (DELETE) "err": "" } ### DELETE * Description: cancel an operation. Calling this will change the state to "cancelling" rather than actually removing the entry. * Authentication: trusted * Operation: sync * Return: standard return value or standard error Input (none at present): { } HTTP code for this should be 202 (Accepted). ## /1.0/operations/\/wait ### GET (optional ?timeout=30) * Description: Wait for an operation to finish * Authentication: trusted * Operation: sync * Return: dict of the operation after it's reached its final state Input (wait indefinitely for a final state): no argument Input (similar but times out after 30s): ?timeout=30 ## /1.0/operations/\/websocket ### GET (?secret=SECRET) * Description: This connection is upgraded into a websocket connection speaking the protocol defined by the operation type. For example, in the case of an exec operation, the websocket is the bidirectional pipe for stdin/stdout/stderr to flow to and from the process inside the container. In the case of migration, it will be the primary interface over which the migration information is communicated. The secret here is the one that was provided when the operation was created. Guests are allowed to connect provided they have the right secret. * Authentication: guest or trusted * Operation: sync * Return: websocket stream or standard error ## /1.0/profiles ### GET * Description: List of configuration profiles * Authentication: trusted * Operation: sync * Return: list of URLs to defined profiles Return: [ "/1.0/profiles/default" ] ### POST * Description: define a new profile * Authentication: trusted * Operation: sync * Return: standard return value or standard error Input: { "name": "my-profilename", "description": "Some description string", "config": { "limits.memory": "2GB" }, "devices": { "kvm": { "type": "unix-char", "path": "/dev/kvm" } } } ## /1.0/profiles/\ ### GET * Description: profile configuration * Authentication: trusted * Operation: sync * Return: dict representing the profile content Output: { "name": "test", "description": "Some description string", "config": { "limits.memory": "2GB" }, "devices": { "kvm": { "path": "/dev/kvm", "type": "unix-char" } } } ### PUT * Description: update the profile * Authentication: trusted * Operation: sync * Return: standard return value or standard error Input: { "config": { "limits.memory": "4GB" }, "description": "Some description string", "devices": { "kvm": { "path": "/dev/kvm", "type": "unix-char" } } } Same dict as used for initial creation and coming from GET. The name property can't be changed (see POST for that). ### POST * Description: rename a profile * Authentication: trusted * Operation: sync * Return: standard return value or standard error Input (rename a profile): { "name": "new-name" } HTTP return value must be 204 (No content) and Location must point to the renamed resource. Renaming to an existing name must return the 409 (Conflict) HTTP code. ### DELETE * Description: remove a profile * Authentication: trusted * Operation: sync * Return: standard return value or standard error Input (none at present): { } HTTP code for this should be 202 (Accepted). lxd-2.0.0/doc/storage-backends.md000066400000000000000000000070411270277227600166210ustar00rootroot00000000000000# Storage Backends and supported functions ## Feature comparison LXD supports using plain dirs, Btrfs, LVM, and ZFS for storage of images and containers. Where possible, LXD tries to use the advanced features of each system to optimize operations. Feature | Directory | Btrfs | LVM | ZFS :--- | :--- | :--- | :--- | :--- Optimized image storage | no | yes | yes | yes Optimized container creation | no | yes | yes | yes Optimized snapshot creation | no | yes | yes | yes Optimized image transfer | no | yes | no | yes Optimized container transfer | no | yes | no | yes Copy on write | no | yes | yes | yes Block based | no | no | yes | no Instant cloning | no | yes | yes | yes Nesting support | yes | yes | no | no Restore from older snapshots (not latest) | yes | yes | yes | no Storage quotas | no | yes | no | yes ## Mixed storage When switching storage backend after some containers or images already exist, LXD will create any new container using the new backend and converting older images to the new backend as needed. ## Non-optimized container transfer When the filesystem on the source and target hosts differs or when there is no faster way, rsync is used to transfer the container content across. ## Notes ### Directory - The directory backend is the fallback backend when nothing else is configured or detected. - While this backend is fully functional, it's also much slower than all the others due to it having to unpack images or do instant copies of containers, snapshots and images. ### Btrfs - The btrfs backend is automatically used if /var/lib/lxd is on a btrfs filesystem. - Uses a subvolume per container, image and snapshot, creating btrfs snapshots when creating a new object. ### LVM - A LVM VG must be created and then storage.lvm\_vg\_name set to point to it. - If a thinpool doesn't already exist, one will be created, the name of the thinpool can be set with storage.lvm\_thinpool\_name . - Uses LVs for images, then LV snapshots for containers and container snapshots. - The filesystem used for the LVs is ext4 (can be configured to use xfs instead). - LVs are created with a default size of 10GiB (can be configured through). ### ZFS - LXD can use any zpool or part of a zpool. storage.zfs\_pool\_name must be set to the path to be used. - ZFS doesn't have to (and shouldn't be) mounted on /var/lib/lxd - Uses ZFS filesystems for images, then snapshots and clones to create containers and snapshots. - Due to the way copy-on-write works in ZFS, parent filesystems can't be removed until all children are gone. As a result, LXD will automatically rename any removed but still referenced object to a random deleted/ path and keep it until such time the references are gone and it can safely be removed. - ZFS as it is today doesn't support delegating part of a pool to a container user. Upstream is actively working on this. - ZFS doesn't support restoring from snapshots other than the latest one. You can however create new containers from older snapshots which makes it possible to confirm the snapshots is indeed what you want to restore before you remove the newer snapshots. lxd-2.0.0/doc/userns-idmap.md000066400000000000000000000036441270277227600160210ustar00rootroot00000000000000# Introduction LXD runs safe containers. This is achieved mostly through the use of user namespaces which make it possible to run containers unprivileged, greatly limiting the attack surface. User namespaces work by mapping a set of uids and gids on the host to a set of uids and gids in the container. For example, we can define that the host uids and gids from 100000 to 165535 may be used by LXD and should be mapped to uid/gid 0 through 65535 in the container. As a result a process running as uid 0 in the container will actually be running as uid 100000. Allocations should always be of at least 65536 uids and gids to cover the POSIX range including root (0) and nobody (65534). To simplify things, at this point, we will only deal with identical allocations for uids and gids and only support a single contiguous range per container. # Kernel support User namespaces require a kernel >= 3.12, LXD will start even on older kernels but will refuse to start containers. # Allowed ranges On most hosts, LXD will check /etc/subuid and /etc/subgid for allocations for the "lxd" user and on first start, set the default profile to use the first 65536 uids and gids from that range. If the range is shorter than 65536 (which includes no range at all), then LXD will fail to create or start any container until this is corrected. If some but not all of /etc/subuid, /etc/subgid, newuidmap (path lookup) and newgidmap (path lookup) can't be found on the system, LXD will fail the startup of any container until this is corrected as this shows a broken shadow setup. If none of those 4 files can be found, then LXD will assume it's running on a host using an old version of shadow. In this mode, LXD will assume it can use any uids and gids above 65535 and will take the first 65536 as its default map. # Varying ranges between hosts The source map is sent when moving containers between hosts so that they can be remapped on the receiving host. lxd-2.0.0/fuidshift/000077500000000000000000000000001270277227600143015ustar00rootroot00000000000000lxd-2.0.0/fuidshift/Makefile000066400000000000000000000001511270277227600157360ustar00rootroot00000000000000# we let go build figure out dependency changes .PHONY: fuidmap lxc: go build clean: -rm -f fuidshift lxd-2.0.0/fuidshift/main.go000066400000000000000000000031301270277227600155510ustar00rootroot00000000000000package main import ( "fmt" "os" "github.com/lxc/lxd/shared" ) func help(me string, status int) { fmt.Printf("Usage: %s directory [-t] [-r] [ ...]\n", me) fmt.Printf(" -t implies test mode. No file ownerships will be changed.\n") fmt.Printf(" -r means reverse, that is shift the uids out of the container.\n") fmt.Printf("\n") fmt.Printf(" A range is [u|b|g]:.\n") fmt.Printf(" where u means shift uids, g means shift gids, b means shift both.\n") fmt.Printf(" For example: %s directory b:0:100000:65536 u:10000:1000:1\n", me) os.Exit(status) } func main() { if err := run(); err != nil { fmt.Printf("Error: %q\n", err) help(os.Args[0], 1) } } func run() error { if len(os.Args) < 3 { if len(os.Args) > 1 && (os.Args[1] == "-h" || os.Args[1] == "--help" || os.Args[1] == "help") { help(os.Args[0], 0) } else { help(os.Args[0], 1) } } directory := os.Args[1] idmap := shared.IdmapSet{} testmode := false reverse := false for pos := 2; pos < len(os.Args); pos++ { switch os.Args[pos] { case "-r", "--reverse": reverse = true case "t", "-t", "--test", "test": testmode = true default: var err error idmap, err = idmap.Append(os.Args[pos]) if err != nil { return err } } } if idmap.Len() == 0 { fmt.Printf("No idmaps given\n") help(os.Args[0], 1) } if !testmode && os.Geteuid() != 0 { fmt.Printf("This must be run as root\n") os.Exit(1) } if reverse { return idmap.UidshiftFromContainer(directory, testmode) } return idmap.UidshiftIntoContainer(directory, testmode) } lxd-2.0.0/lxc/000077500000000000000000000000001270277227600131025ustar00rootroot00000000000000lxd-2.0.0/lxc/action.go000066400000000000000000000044201270277227600147060ustar00rootroot00000000000000package main import ( "fmt" "github.com/lxc/lxd" "github.com/lxc/lxd/shared" "github.com/lxc/lxd/shared/gnuflag" "github.com/lxc/lxd/shared/i18n" ) type actionCmd struct { action shared.ContainerAction hasTimeout bool visible bool name string timeout int force bool stateful bool stateless bool } func (c *actionCmd) showByDefault() bool { return c.visible } func (c *actionCmd) usage() string { return fmt.Sprintf(i18n.G( `Changes state of one or more containers to %s. lxc %s [...]`), c.name, c.name) } func (c *actionCmd) flags() { if c.hasTimeout { gnuflag.IntVar(&c.timeout, "timeout", -1, i18n.G("Time to wait for the container before killing it.")) gnuflag.BoolVar(&c.force, "force", false, i18n.G("Force the container to shutdown.")) gnuflag.BoolVar(&c.stateful, "stateful", false, i18n.G("Store the container state (only for stop).")) gnuflag.BoolVar(&c.stateless, "stateless", false, i18n.G("Ignore the container state (only forstart).")) } } func (c *actionCmd) run(config *lxd.Config, args []string) error { if len(args) == 0 { return errArgs } state := false // Only store state if asked to if c.action == "stop" && c.stateful { state = true } for _, nameArg := range args { remote, name := config.ParseRemoteAndContainer(nameArg) d, err := lxd.NewClient(config, remote) if err != nil { return err } if name == "" { return fmt.Errorf(i18n.G("Must supply container name for: ")+"\"%s\"", nameArg) } if c.action == shared.Start || c.action == shared.Stop { current, err := d.ContainerInfo(name) if err != nil { return err } // "start" for a frozen container means "unfreeze" if current.StatusCode == shared.Frozen { c.action = shared.Unfreeze } // Always restore state (if present) unless asked not to if c.action == shared.Start && current.Stateful && !c.stateless { state = true } } resp, err := d.Action(name, c.action, c.timeout, c.force, state) if err != nil { return err } if resp.Type != lxd.Async { return fmt.Errorf(i18n.G("bad result type from action")) } if err := d.WaitForSuccess(resp.Operation); err != nil { return fmt.Errorf("%s\n"+i18n.G("Try `lxc info --show-log %s` for more info"), err, name) } } return nil } lxd-2.0.0/lxc/config.go000066400000000000000000000447261270277227600147130ustar00rootroot00000000000000package main import ( "crypto/x509" "encoding/pem" "fmt" "io/ioutil" "os" "sort" "strings" "syscall" "github.com/olekukonko/tablewriter" "gopkg.in/yaml.v2" "github.com/lxc/lxd" "github.com/lxc/lxd/shared" "github.com/lxc/lxd/shared/gnuflag" "github.com/lxc/lxd/shared/i18n" "github.com/lxc/lxd/shared/termios" ) type configCmd struct { httpAddr string expanded bool } func (c *configCmd) showByDefault() bool { return true } func (c *configCmd) flags() { gnuflag.BoolVar(&c.expanded, "expanded", false, i18n.G("Whether to show the expanded configuration")) } func (c *configCmd) configEditHelp() string { return i18n.G( `### This is a yaml representation of the configuration. ### Any line starting with a '# will be ignored. ### ### A sample configuration looks like: ### name: container1 ### profiles: ### - default ### config: ### volatile.eth0.hwaddr: 00:16:3e:e9:f8:7f ### devices: ### homedir: ### path: /extra ### source: /home/user ### type: disk ### ephemeral: false ### ### Note that the name is shown but cannot be changed`) } func (c *configCmd) usage() string { return i18n.G( `Manage configuration. lxc config device add <[remote:]container> [key=value]... Add a device to a container. lxc config device get <[remote:]container> Get a device property. lxc config device set <[remote:]container> Set a device property. lxc config device unset <[remote:]container> Unset a device property. lxc config device list <[remote:]container> List devices for container. lxc config device show <[remote:]container> Show full device details for container. lxc config device remove <[remote:]container> Remove device from container. lxc config get [remote:][container] Get container or server configuration key. lxc config set [remote:][container] Set container or server configuration key. lxc config unset [remote:][container] Unset container or server configuration key. lxc config show [remote:][container] [--expanded] Show container or server configuration. lxc config edit [remote:][container] Edit container or server configuration in external editor. Edit configuration, either by launching external editor or reading STDIN. Example: lxc config edit # launch editor cat config.yml | lxc config edit # read from config.yml lxc config trust list [remote] List all trusted certs. lxc config trust add [remote] Add certfile.crt to trusted hosts. lxc config trust remove [remote] [hostname|fingerprint] Remove the cert from trusted hosts. Examples: To mount host's /share/c1 onto /opt in the container: lxc config device add [remote:]container1 disk source=/share/c1 path=opt To set an lxc config value: lxc config set [remote:] raw.lxc 'lxc.aa_allow_incomplete = 1' To listen on IPv4 and IPv6 port 8443 (you can omit the 8443 its the default): lxc config set core.https_address [::]:8443 To set the server trust password: lxc config set core.trust_password blah`) } func (c *configCmd) doSet(config *lxd.Config, args []string, unset bool) error { if len(args) != 4 { return errArgs } // [[lxc config]] set dakara:c1 limits.memory 200000 remote, container := config.ParseRemoteAndContainer(args[1]) d, err := lxd.NewClient(config, remote) if err != nil { return err } key := args[2] value := args[3] if !termios.IsTerminal(int(syscall.Stdin)) && value == "-" { buf, err := ioutil.ReadAll(os.Stdin) if err != nil { return fmt.Errorf(i18n.G("Can't read from stdin: %s"), err) } value = string(buf[:]) } if unset { st, err := d.ContainerInfo(container) if err != nil { return err } _, ok := st.Config[key] if !ok { return fmt.Errorf(i18n.G("Can't unset key '%s', it's not currently set."), key) } } return d.SetContainerConfig(container, key, value) } func (c *configCmd) run(config *lxd.Config, args []string) error { if len(args) < 1 { return errArgs } switch args[0] { case "unset": if len(args) < 2 { return errArgs } // Deal with local server if len(args) == 2 { c, err := lxd.NewClient(config, config.DefaultRemote) if err != nil { return err } ss, err := c.ServerStatus() if err != nil { return err } _, ok := ss.Config[args[1]] if !ok { return fmt.Errorf(i18n.G("Can't unset key '%s', it's not currently set."), args[1]) } _, err = c.SetServerConfig(args[1], "") return err } // Deal with remote server remote, container := config.ParseRemoteAndContainer(args[1]) if container == "" { c, err := lxd.NewClient(config, remote) if err != nil { return err } ss, err := c.ServerStatus() if err != nil { return err } _, ok := ss.Config[args[1]] if !ok { return fmt.Errorf(i18n.G("Can't unset key '%s', it's not currently set."), args[1]) } _, err = c.SetServerConfig(args[2], "") return err } // Deal with container args = append(args, "") return c.doSet(config, args, true) case "set": if len(args) < 3 { return errArgs } // Deal with local server if len(args) == 3 { c, err := lxd.NewClient(config, config.DefaultRemote) if err != nil { return err } _, err = c.SetServerConfig(args[1], args[2]) return err } // Deal with remote server remote, container := config.ParseRemoteAndContainer(args[1]) if container == "" { c, err := lxd.NewClient(config, remote) if err != nil { return err } _, err = c.SetServerConfig(args[2], args[3]) return err } // Deal with container return c.doSet(config, args, false) case "trust": if len(args) < 2 { return errArgs } switch args[1] { case "list": var remote string if len(args) == 3 { remote = config.ParseRemote(args[2]) } else { remote = config.DefaultRemote } d, err := lxd.NewClient(config, remote) if err != nil { return err } trust, err := d.CertificateList() if err != nil { return err } data := [][]string{} for _, cert := range trust { fp := cert.Fingerprint[0:12] certBlock, _ := pem.Decode([]byte(cert.Certificate)) cert, err := x509.ParseCertificate(certBlock.Bytes) if err != nil { return err } const layout = "Jan 2, 2006 at 3:04pm (MST)" issue := cert.NotBefore.Format(layout) expiry := cert.NotAfter.Format(layout) data = append(data, []string{fp, cert.Subject.CommonName, issue, expiry}) } table := tablewriter.NewWriter(os.Stdout) table.SetAutoWrapText(false) table.SetAlignment(tablewriter.ALIGN_LEFT) table.SetRowLine(true) table.SetHeader([]string{ i18n.G("FINGERPRINT"), i18n.G("COMMON NAME"), i18n.G("ISSUE DATE"), i18n.G("EXPIRY DATE")}) sort.Sort(SortImage(data)) table.AppendBulk(data) table.Render() return nil case "add": var remote string if len(args) < 3 { return fmt.Errorf(i18n.G("No certificate provided to add")) } else if len(args) == 4 { remote = config.ParseRemote(args[2]) } else { remote = config.DefaultRemote } d, err := lxd.NewClient(config, remote) if err != nil { return err } fname := args[len(args)-1] cert, err := shared.ReadCert(fname) if err != nil { return err } name, _ := shared.SplitExt(fname) return d.CertificateAdd(cert, name) case "remove": var remote string if len(args) < 3 { return fmt.Errorf(i18n.G("No fingerprint specified.")) } else if len(args) == 4 { remote = config.ParseRemote(args[2]) } else { remote = config.DefaultRemote } d, err := lxd.NewClient(config, remote) if err != nil { return err } return d.CertificateRemove(args[len(args)-1]) default: return errArgs } case "show": remote := config.DefaultRemote container := "" if len(args) > 1 { remote, container = config.ParseRemoteAndContainer(args[1]) } d, err := lxd.NewClient(config, remote) if err != nil { return err } var data []byte if len(args) == 1 || container == "" { config, err := d.ServerStatus() if err != nil { return err } brief := config.Brief() data, err = yaml.Marshal(&brief) } else { config, err := d.ContainerInfo(container) if err != nil { return err } brief := config.Brief() if c.expanded { brief = config.BriefExpanded() } data, err = yaml.Marshal(&brief) } fmt.Printf("%s", data) return nil case "get": if len(args) > 3 || len(args) < 2 { return errArgs } remote := config.DefaultRemote container := "" key := args[1] if len(args) > 2 { remote, container = config.ParseRemoteAndContainer(args[1]) key = args[2] } d, err := lxd.NewClient(config, remote) if err != nil { return err } if container != "" { resp, err := d.ContainerInfo(container) if err != nil { return err } fmt.Println(resp.Config[key]) } else { resp, err := d.ServerStatus() if err != nil { return err } value := resp.Config[key] if value == nil { value = "" } else if value == true { value = "true" } else if value == false { value = "false" } fmt.Println(value) } return nil case "profile": case "device": if len(args) < 2 { return errArgs } switch args[1] { case "list": return c.deviceList(config, "container", args) case "add": return c.deviceAdd(config, "container", args) case "remove": return c.deviceRm(config, "container", args) case "get": return c.deviceGet(config, "container", args) case "set": return c.deviceSet(config, "container", args) case "unset": return c.deviceUnset(config, "container", args) case "show": return c.deviceShow(config, "container", args) default: return errArgs } case "edit": if len(args) < 1 { return errArgs } remote := config.DefaultRemote container := "" if len(args) > 1 { remote, container = config.ParseRemoteAndContainer(args[1]) } d, err := lxd.NewClient(config, remote) if err != nil { return err } if len(args) == 1 || container == "" { return c.doDaemonConfigEdit(d) } return c.doContainerConfigEdit(d, container) default: return errArgs } return errArgs } func (c *configCmd) doContainerConfigEdit(client *lxd.Client, cont string) error { // If stdin isn't a terminal, read text from it if !termios.IsTerminal(int(syscall.Stdin)) { contents, err := ioutil.ReadAll(os.Stdin) if err != nil { return err } newdata := shared.BriefContainerInfo{} err = yaml.Unmarshal(contents, &newdata) if err != nil { return err } return client.UpdateContainerConfig(cont, newdata) } // Extract the current value config, err := client.ContainerInfo(cont) if err != nil { return err } brief := config.Brief() data, err := yaml.Marshal(&brief) if err != nil { return err } // Spawn the editor content, err := shared.TextEditor("", []byte(c.configEditHelp()+"\n\n"+string(data))) if err != nil { return err } for { // Parse the text received from the editor newdata := shared.BriefContainerInfo{} err = yaml.Unmarshal(content, &newdata) if err == nil { err = client.UpdateContainerConfig(cont, newdata) } // Respawn the editor if err != nil { fmt.Fprintf(os.Stderr, i18n.G("Config parsing error: %s")+"\n", err) fmt.Println(i18n.G("Press enter to start the editor again")) _, err := os.Stdin.Read(make([]byte, 1)) if err != nil { return err } content, err = shared.TextEditor("", content) if err != nil { return err } continue } break } return nil } func (c *configCmd) doDaemonConfigEdit(client *lxd.Client) error { // If stdin isn't a terminal, read text from it if !termios.IsTerminal(int(syscall.Stdin)) { contents, err := ioutil.ReadAll(os.Stdin) if err != nil { return err } newdata := shared.BriefServerState{} err = yaml.Unmarshal(contents, &newdata) if err != nil { return err } _, err = client.UpdateServerConfig(newdata) return err } // Extract the current value config, err := client.ServerStatus() if err != nil { return err } brief := config.Brief() data, err := yaml.Marshal(&brief) if err != nil { return err } // Spawn the editor content, err := shared.TextEditor("", []byte(c.configEditHelp()+"\n\n"+string(data))) if err != nil { return err } for { // Parse the text received from the editor newdata := shared.BriefServerState{} err = yaml.Unmarshal(content, &newdata) if err == nil { _, err = client.UpdateServerConfig(newdata) } // Respawn the editor if err != nil { fmt.Fprintf(os.Stderr, i18n.G("Config parsing error: %s")+"\n", err) fmt.Println(i18n.G("Press enter to start the editor again")) _, err := os.Stdin.Read(make([]byte, 1)) if err != nil { return err } content, err = shared.TextEditor("", content) if err != nil { return err } continue } break } return nil } func (c *configCmd) deviceAdd(config *lxd.Config, which string, args []string) error { if len(args) < 5 { return errArgs } remote, name := config.ParseRemoteAndContainer(args[2]) client, err := lxd.NewClient(config, remote) if err != nil { return err } devname := args[3] devtype := args[4] var props []string if len(args) > 5 { props = args[5:] } else { props = []string{} } var resp *lxd.Response if which == "profile" { resp, err = client.ProfileDeviceAdd(name, devname, devtype, props) } else { resp, err = client.ContainerDeviceAdd(name, devname, devtype, props) } if err != nil { return err } if which != "profile" { err = client.WaitForSuccess(resp.Operation) } if err == nil { fmt.Printf(i18n.G("Device %s added to %s")+"\n", devname, name) } return err } func (c *configCmd) deviceGet(config *lxd.Config, which string, args []string) error { if len(args) < 5 { return errArgs } remote, name := config.ParseRemoteAndContainer(args[2]) client, err := lxd.NewClient(config, remote) if err != nil { return err } devname := args[3] key := args[4] if which == "profile" { st, err := client.ProfileConfig(name) if err != nil { return err } dev, ok := st.Devices[devname] if !ok { return fmt.Errorf(i18n.G("The device doesn't exist")) } fmt.Println(dev[key]) } else { st, err := client.ContainerInfo(name) if err != nil { return err } dev, ok := st.Devices[devname] if !ok { return fmt.Errorf(i18n.G("The device doesn't exist")) } fmt.Println(dev[key]) } return nil } func (c *configCmd) deviceSet(config *lxd.Config, which string, args []string) error { if len(args) < 6 { return errArgs } remote, name := config.ParseRemoteAndContainer(args[2]) client, err := lxd.NewClient(config, remote) if err != nil { return err } devname := args[3] key := args[4] value := args[5] if which == "profile" { st, err := client.ProfileConfig(name) if err != nil { return err } dev, ok := st.Devices[devname] if !ok { return fmt.Errorf(i18n.G("The device doesn't exist")) } dev[key] = value st.Devices[devname] = dev err = client.PutProfile(name, *st) if err != nil { return err } } else { st, err := client.ContainerInfo(name) if err != nil { return err } dev, ok := st.Devices[devname] if !ok { return fmt.Errorf(i18n.G("The device doesn't exist")) } dev[key] = value st.Devices[devname] = dev err = client.UpdateContainerConfig(name, st.Brief()) if err != nil { return err } } return err } func (c *configCmd) deviceUnset(config *lxd.Config, which string, args []string) error { if len(args) < 5 { return errArgs } remote, name := config.ParseRemoteAndContainer(args[2]) client, err := lxd.NewClient(config, remote) if err != nil { return err } devname := args[3] key := args[4] if which == "profile" { st, err := client.ProfileConfig(name) if err != nil { return err } dev, ok := st.Devices[devname] if !ok { return fmt.Errorf(i18n.G("The device doesn't exist")) } delete(dev, key) st.Devices[devname] = dev err = client.PutProfile(name, *st) if err != nil { return err } } else { st, err := client.ContainerInfo(name) if err != nil { return err } dev, ok := st.Devices[devname] if !ok { return fmt.Errorf(i18n.G("The device doesn't exist")) } delete(dev, key) st.Devices[devname] = dev err = client.UpdateContainerConfig(name, st.Brief()) if err != nil { return err } } return err } func (c *configCmd) deviceRm(config *lxd.Config, which string, args []string) error { if len(args) < 4 { return errArgs } remote, name := config.ParseRemoteAndContainer(args[2]) client, err := lxd.NewClient(config, remote) if err != nil { return err } devname := args[3] var resp *lxd.Response if which == "profile" { resp, err = client.ProfileDeviceDelete(name, devname) } else { resp, err = client.ContainerDeviceDelete(name, devname) } if err != nil { return err } if which != "profile" { err = client.WaitForSuccess(resp.Operation) } if err == nil { fmt.Printf(i18n.G("Device %s removed from %s")+"\n", devname, name) } return err } func (c *configCmd) deviceList(config *lxd.Config, which string, args []string) error { if len(args) < 3 { return errArgs } remote, name := config.ParseRemoteAndContainer(args[2]) client, err := lxd.NewClient(config, remote) if err != nil { return err } var resp []string if which == "profile" { resp, err = client.ProfileListDevices(name) } else { resp, err = client.ContainerListDevices(name) } if err != nil { return err } fmt.Printf("%s\n", strings.Join(resp, "\n")) return nil } func (c *configCmd) deviceShow(config *lxd.Config, which string, args []string) error { if len(args) < 3 { return errArgs } remote, name := config.ParseRemoteAndContainer(args[2]) client, err := lxd.NewClient(config, remote) if err != nil { return err } var devices map[string]shared.Device if which == "profile" { resp, err := client.ProfileConfig(name) if err != nil { return err } devices = resp.Devices } else { resp, err := client.ContainerInfo(name) if err != nil { return err } devices = resp.Devices } data, err := yaml.Marshal(&devices) if err != nil { return err } fmt.Printf(string(data)) return nil } lxd-2.0.0/lxc/copy.go000066400000000000000000000100521270277227600144010ustar00rootroot00000000000000package main import ( "fmt" "strings" "github.com/lxc/lxd" "github.com/lxc/lxd/shared" "github.com/lxc/lxd/shared/gnuflag" "github.com/lxc/lxd/shared/i18n" ) type copyCmd struct { ephem bool } func (c *copyCmd) showByDefault() bool { return true } func (c *copyCmd) usage() string { return i18n.G( `Copy containers within or in between lxd instances. lxc copy [remote:] [remote:] [--ephemeral|e]`) } func (c *copyCmd) flags() { gnuflag.BoolVar(&c.ephem, "ephemeral", false, i18n.G("Ephemeral container")) gnuflag.BoolVar(&c.ephem, "e", false, i18n.G("Ephemeral container")) } func (c *copyCmd) copyContainer(config *lxd.Config, sourceResource string, destResource string, keepVolatile bool, ephemeral int) error { sourceRemote, sourceName := config.ParseRemoteAndContainer(sourceResource) destRemote, destName := config.ParseRemoteAndContainer(destResource) if sourceName == "" { return fmt.Errorf(i18n.G("you must specify a source container name")) } if destName == "" { destName = sourceName } source, err := lxd.NewClient(config, sourceRemote) if err != nil { return err } status := &shared.ContainerInfo{} // TODO: presumably we want to do this for copying snapshots too? We // need to think a bit more about how we track the baseImage in the // face of LVM and snapshots in general; this will probably make more // sense once that work is done. baseImage := "" if !shared.IsSnapshot(sourceName) { status, err = source.ContainerInfo(sourceName) if err != nil { return err } baseImage = status.Config["volatile.base_image"] if !keepVolatile { for k := range status.Config { if strings.HasPrefix(k, "volatile") { delete(status.Config, k) } } } } // Do a local copy if the remotes are the same, otherwise do a migration if sourceRemote == destRemote { if sourceName == destName { return fmt.Errorf(i18n.G("can't copy to the same container name")) } cp, err := source.LocalCopy(sourceName, destName, status.Config, status.Profiles, ephemeral == 1) if err != nil { return err } return source.WaitForSuccess(cp.Operation) } dest, err := lxd.NewClient(config, destRemote) if err != nil { return err } sourceProfs := shared.NewStringSet(status.Profiles) destProfs, err := dest.ListProfiles() if err != nil { return err } if !sourceProfs.IsSubset(shared.NewStringSet(destProfs)) { return fmt.Errorf(i18n.G("not all the profiles from the source exist on the target")) } if ephemeral == -1 { ct, err := source.ContainerInfo(sourceName) if err != nil { return err } if ct.Ephemeral { ephemeral = 1 } else { ephemeral = 0 } } sourceWSResponse, err := source.GetMigrationSourceWS(sourceName) if err != nil { return err } secrets := map[string]string{} op, err := sourceWSResponse.MetadataAsOperation() if err != nil { return err } for k, v := range *op.Metadata { secrets[k] = v.(string) } addresses, err := source.Addresses() if err != nil { return err } /* Since we're trying a bunch of different network ports that * may be invalid, we can get "bad handshake" errors when the * websocket code tries to connect. If the first error is a * real error, but the subsequent errors are only network * errors, we should try to report the first real error. Of * course, if all the errors are websocket errors, let's just * report that. */ for _, addr := range addresses { var migration *lxd.Response sourceWSUrl := "https://" + addr + sourceWSResponse.Operation migration, err = dest.MigrateFrom(destName, sourceWSUrl, source.Certificate, secrets, status.Architecture, status.Config, status.Devices, status.Profiles, baseImage, ephemeral == 1) if err != nil { continue } if err = dest.WaitForSuccess(migration.Operation); err != nil { return err } return nil } return err } func (c *copyCmd) run(config *lxd.Config, args []string) error { if len(args) != 2 { return errArgs } ephem := 0 if c.ephem { ephem = 1 } return c.copyContainer(config, args[0], args[1], false, ephem) } lxd-2.0.0/lxc/delete.go000066400000000000000000000051241270277227600146750ustar00rootroot00000000000000package main import ( "bufio" "fmt" "os" "strings" "github.com/lxc/lxd" "github.com/lxc/lxd/shared" "github.com/lxc/lxd/shared/gnuflag" "github.com/lxc/lxd/shared/i18n" ) type deleteCmd struct { force bool interactive bool } func (c *deleteCmd) showByDefault() bool { return true } func (c *deleteCmd) usage() string { return i18n.G( `Delete containers or container snapshots. lxc delete [remote:][/] [remote:][[/]...] Destroy containers or snapshots with any attached data (configuration, snapshots, ...).`) } func (c *deleteCmd) flags() { gnuflag.BoolVar(&c.force, "f", false, i18n.G("Force the removal of stopped containers.")) gnuflag.BoolVar(&c.force, "force", false, i18n.G("Force the removal of stopped containers.")) gnuflag.BoolVar(&c.interactive, "i", false, i18n.G("Require user confirmation.")) gnuflag.BoolVar(&c.interactive, "interactive", false, i18n.G("Require user confirmation.")) } func (c *deleteCmd) promptDelete(name string) error { reader := bufio.NewReader(os.Stdin) fmt.Printf(i18n.G("Remove %s (yes/no): "), name) input, _ := reader.ReadString('\n') input = strings.TrimSuffix(input, "\n") if !shared.StringInSlice(strings.ToLower(input), []string{i18n.G("yes")}) { return fmt.Errorf(i18n.G("User aborted delete operation.")) } return nil } func (c *deleteCmd) doDelete(d *lxd.Client, name string) error { resp, err := d.Delete(name) if err != nil { return err } return d.WaitForSuccess(resp.Operation) } func (c *deleteCmd) run(config *lxd.Config, args []string) error { if len(args) == 0 { return errArgs } for _, nameArg := range args { remote, name := config.ParseRemoteAndContainer(nameArg) d, err := lxd.NewClient(config, remote) if err != nil { return err } if c.interactive { err := c.promptDelete(name) if err != nil { return err } } if shared.IsSnapshot(name) { return c.doDelete(d, name) } ct, err := d.ContainerInfo(name) if err != nil { return err } if ct.StatusCode != 0 && ct.StatusCode != shared.Stopped { if !c.force { return fmt.Errorf(i18n.G("The container is currently running, stop it first or pass --force.")) } resp, err := d.Action(name, shared.Stop, -1, true, false) if err != nil { return err } op, err := d.WaitFor(resp.Operation) if err != nil { return err } if op.StatusCode == shared.Failure { return fmt.Errorf(i18n.G("Stopping container failed!")) } if ct.Ephemeral == true { return nil } } if err := c.doDelete(d, name); err != nil { return err } } return nil } lxd-2.0.0/lxc/exec.go000066400000000000000000000071251270277227600143620ustar00rootroot00000000000000package main import ( "encoding/json" "fmt" "os" "strconv" "strings" "syscall" "github.com/gorilla/websocket" "github.com/lxc/lxd" "github.com/lxc/lxd/shared" "github.com/lxc/lxd/shared/gnuflag" "github.com/lxc/lxd/shared/i18n" "github.com/lxc/lxd/shared/termios" ) type envFlag []string func (f *envFlag) String() string { return fmt.Sprint(*f) } func (f *envFlag) Set(value string) error { if f == nil { *f = make(envFlag, 1) } else { *f = append(*f, value) } return nil } type execCmd struct { modeFlag string envArgs envFlag } func (c *execCmd) showByDefault() bool { return true } func (c *execCmd) usage() string { return i18n.G( `Execute the specified command in a container. lxc exec [remote:]container [--mode=auto|interactive|non-interactive] [--env EDITOR=/usr/bin/vim]... Mode defaults to non-interactive, interactive mode is selected if both stdin AND stdout are terminals (stderr is ignored).`) } func (c *execCmd) flags() { gnuflag.Var(&c.envArgs, "env", i18n.G("An environment variable of the form HOME=/home/foo")) gnuflag.StringVar(&c.modeFlag, "mode", "auto", i18n.G("Override the terminal mode (auto, interactive or non-interactive)")) } func (c *execCmd) sendTermSize(control *websocket.Conn) error { width, height, err := termios.GetSize(int(syscall.Stdout)) if err != nil { return err } shared.Debugf("Window size is now: %dx%d", width, height) w, err := control.NextWriter(websocket.TextMessage) if err != nil { return err } msg := shared.ContainerExecControl{} msg.Command = "window-resize" msg.Args = make(map[string]string) msg.Args["width"] = strconv.Itoa(width) msg.Args["height"] = strconv.Itoa(height) buf, err := json.Marshal(msg) if err != nil { return err } _, err = w.Write(buf) w.Close() return err } func (c *execCmd) run(config *lxd.Config, args []string) error { if len(args) < 2 { return errArgs } remote, name := config.ParseRemoteAndContainer(args[0]) d, err := lxd.NewClient(config, remote) if err != nil { return err } env := map[string]string{"HOME": "/root", "USER": "root"} myEnv := os.Environ() for _, ent := range myEnv { if strings.HasPrefix(ent, "TERM=") { env["TERM"] = ent[len("TERM="):] } } for _, arg := range c.envArgs { pieces := strings.SplitN(arg, "=", 2) value := "" if len(pieces) > 1 { value = pieces[1] } env[pieces[0]] = value } cfd := int(syscall.Stdin) var interactive bool if c.modeFlag == "interactive" { interactive = true } else if c.modeFlag == "non-interactive" { interactive = false } else { interactive = termios.IsTerminal(cfd) && termios.IsTerminal(int(syscall.Stdout)) } var oldttystate *termios.State if interactive { oldttystate, err = termios.MakeRaw(cfd) if err != nil { return err } defer termios.Restore(cfd, oldttystate) } handler := c.controlSocketHandler if !interactive { handler = nil } var width, height int if interactive { width, height, err = termios.GetSize(int(syscall.Stdout)) if err != nil { return err } } stdout := c.getStdout() ret, err := d.Exec(name, args[1:], env, os.Stdin, stdout, os.Stderr, handler, width, height) if err != nil { return err } if oldttystate != nil { /* A bit of a special case here: we want to exit with the same code as * the process inside the container, so we explicitly exit here * instead of returning an error. * * Additionally, since os.Exit() exits without running deferred * functions, we restore the terminal explicitly. */ termios.Restore(cfd, oldttystate) } os.Exit(ret) return fmt.Errorf(i18n.G("unreachable return reached")) } lxd-2.0.0/lxc/exec_unix.go000066400000000000000000000013331270277227600154200ustar00rootroot00000000000000// +build !windows package main import ( "io" "os" "os/signal" "syscall" "github.com/gorilla/websocket" "github.com/lxc/lxd" "github.com/lxc/lxd/shared" ) func (c *execCmd) getStdout() io.WriteCloser { return os.Stdout } func (c *execCmd) controlSocketHandler(d *lxd.Client, control *websocket.Conn) { ch := make(chan os.Signal) signal.Notify(ch, syscall.SIGWINCH) for { sig := <-ch shared.Debugf("Received '%s signal', updating window geometry.", sig) err := c.sendTermSize(control) if err != nil { shared.Debugf("error setting term size %s", err) break } } closeMsg := websocket.FormatCloseMessage(websocket.CloseNormalClosure, "") control.WriteMessage(websocket.CloseMessage, closeMsg) } lxd-2.0.0/lxc/exec_windows.go000066400000000000000000000016461270277227600161360ustar00rootroot00000000000000// +build windows package main import ( "io" "os" "github.com/gorilla/websocket" "github.com/mattn/go-colorable" "github.com/lxc/lxd" "github.com/lxc/lxd/shared" ) // Windows doesn't process ANSI sequences natively, so we wrap // os.Stdout for improved user experience for Windows client type WrappedWriteCloser struct { io.Closer wrapper io.Writer } func (wwc *WrappedWriteCloser) Write(p []byte) (int, error) { return wwc.wrapper.Write(p) } func (c *execCmd) getStdout() io.WriteCloser { return &WrappedWriteCloser{os.Stdout, colorable.NewColorableStdout()} } func (c *execCmd) controlSocketHandler(d *lxd.Client, control *websocket.Conn) { // TODO: figure out what the equivalent of signal.SIGWINCH is on // windows and use that; for now if you resize your terminal it just // won't work quite correctly. err := c.sendTermSize(control) if err != nil { shared.Debugf("error setting term size %s", err) } } lxd-2.0.0/lxc/file.go000066400000000000000000000127531270277227600143600ustar00rootroot00000000000000package main import ( "fmt" "io" "io/ioutil" "os" "path" "path/filepath" "strconv" "strings" "syscall" "github.com/lxc/lxd" "github.com/lxc/lxd/shared" "github.com/lxc/lxd/shared/gnuflag" "github.com/lxc/lxd/shared/i18n" "github.com/lxc/lxd/shared/termios" ) type fileCmd struct { uid int gid int mode string } func (c *fileCmd) showByDefault() bool { return true } func (c *fileCmd) usage() string { return i18n.G( `Manage files on a container. lxc file pull [...] lxc file push [--uid=UID] [--gid=GID] [--mode=MODE] [...] lxc file edit in the case of pull, in the case of push and in the case of edit are /`) } func (c *fileCmd) flags() { gnuflag.IntVar(&c.uid, "uid", -1, i18n.G("Set the file's uid on push")) gnuflag.IntVar(&c.gid, "gid", -1, i18n.G("Set the file's gid on push")) gnuflag.StringVar(&c.mode, "mode", "", i18n.G("Set the file's perms on push")) } func (c *fileCmd) push(config *lxd.Config, args []string) error { if len(args) < 2 { return errArgs } target := args[len(args)-1] pathSpec := strings.SplitN(target, "/", 2) if len(pathSpec) != 2 { return fmt.Errorf(i18n.G("Invalid target %s"), target) } targetPath := pathSpec[1] remote, container := config.ParseRemoteAndContainer(pathSpec[0]) d, err := lxd.NewClient(config, remote) if err != nil { return err } mode := os.FileMode(0755) if c.mode != "" { if len(c.mode) == 3 { c.mode = "0" + c.mode } m, err := strconv.ParseInt(c.mode, 0, 0) if err != nil { return err } mode = os.FileMode(m) } uid := 0 if c.uid >= 0 { uid = c.uid } gid := 0 if c.gid >= 0 { gid = c.gid } _, targetfilename := filepath.Split(targetPath) var sourcefilenames []string for _, fname := range args[:len(args)-1] { if !strings.HasPrefix(fname, "--") { sourcefilenames = append(sourcefilenames, fname) } } if (targetfilename != "") && (len(sourcefilenames) > 1) { return errArgs } /* Make sure all of the files are accessible by us before trying to * push any of them. */ var files []*os.File for _, f := range sourcefilenames { var file *os.File if f == "-" { file = os.Stdin } else { file, err = os.Open(f) if err != nil { return err } } defer file.Close() files = append(files, file) } for _, f := range files { fpath := targetPath if targetfilename == "" { fpath = path.Join(fpath, path.Base(f.Name())) } if c.mode == "" || c.uid == -1 || c.gid == -1 { fMode, fUid, fGid, err := c.getOwner(f) if err != nil { return err } if c.mode == "" { mode = fMode } if c.uid == -1 { uid = fUid } if c.gid == -1 { gid = fGid } } err = d.PushFile(container, fpath, gid, uid, mode, f) if err != nil { return err } } return nil } func (c *fileCmd) pull(config *lxd.Config, args []string) error { if len(args) < 2 { return errArgs } target := args[len(args)-1] targetIsDir := false sb, err := os.Stat(target) if err != nil && !os.IsNotExist(err) { return err } /* * If the path exists, just use it. If it doesn't exist, it might be a * directory in one of two cases: * 1. Someone explicitly put "/" at the end * 2. Someone provided more than one source. In this case the target * should be a directory so we can save all the files into it. */ if err == nil { targetIsDir = sb.IsDir() if !targetIsDir && len(args)-1 > 1 { return fmt.Errorf(i18n.G("More than one file to download, but target is not a directory")) } } else if strings.HasSuffix(target, string(os.PathSeparator)) || len(args)-1 > 1 { if err := os.MkdirAll(target, 0755); err != nil { return err } targetIsDir = true } for _, f := range args[:len(args)-1] { pathSpec := strings.SplitN(f, "/", 2) if len(pathSpec) != 2 { return fmt.Errorf(i18n.G("Invalid source %s"), f) } remote, container := config.ParseRemoteAndContainer(pathSpec[0]) d, err := lxd.NewClient(config, remote) if err != nil { return err } _, _, _, buf, err := d.PullFile(container, pathSpec[1]) if err != nil { return err } var targetPath string if targetIsDir { targetPath = path.Join(target, path.Base(pathSpec[1])) } else { targetPath = target } var f *os.File if targetPath == "-" { f = os.Stdout } else { f, err = os.Create(targetPath) if err != nil { return err } defer f.Close() } _, err = io.Copy(f, buf) if err != nil { return err } } return nil } func (c *fileCmd) edit(config *lxd.Config, args []string) error { if len(args) != 1 { return errArgs } // If stdin isn't a terminal, read text from it if !termios.IsTerminal(int(syscall.Stdin)) { return c.push(config, append([]string{os.Stdin.Name()}, args[0])) } // Create temp file f, err := ioutil.TempFile("", "lxd_file_edit_") fname := f.Name() f.Close() os.Remove(fname) defer os.Remove(fname) // Extract current value err = c.pull(config, append([]string{args[0]}, fname)) if err != nil { return err } _, err = shared.TextEditor(fname, []byte{}) if err != nil { return err } err = c.push(config, append([]string{fname}, args[0])) if err != nil { return err } return nil } func (c *fileCmd) run(config *lxd.Config, args []string) error { if len(args) < 1 { return errArgs } switch args[0] { case "push": return c.push(config, args[1:]) case "pull": return c.pull(config, args[1:]) case "edit": return c.edit(config, args[1:]) default: return errArgs } } lxd-2.0.0/lxc/file_unix.go000066400000000000000000000005541270277227600154170ustar00rootroot00000000000000// +build !windows package main import ( "os" "syscall" ) func (c *fileCmd) getOwner(f *os.File) (os.FileMode, int, int, error) { fInfo, err := f.Stat() if err != nil { return os.FileMode(0), -1, -1, err } mode := fInfo.Mode() uid := int(fInfo.Sys().(*syscall.Stat_t).Uid) gid := int(fInfo.Sys().(*syscall.Stat_t).Gid) return mode, uid, gid, nil } lxd-2.0.0/lxc/file_windows.go000066400000000000000000000002411270277227600161170ustar00rootroot00000000000000// +build windows package main import ( "os" ) func (c *fileCmd) getOwner(f *os.File) (os.FileMode, int, int, error) { return os.FileMode(0), -1, -1, nil } lxd-2.0.0/lxc/finger.go000066400000000000000000000015541270277227600147100ustar00rootroot00000000000000package main import ( "github.com/lxc/lxd" "github.com/lxc/lxd/shared/i18n" ) type fingerCmd struct { httpAddr string } func (c *fingerCmd) showByDefault() bool { return false } func (c *fingerCmd) usage() string { return i18n.G( `Fingers the LXD instance to check if it is up and working. lxc finger `) } func (c *fingerCmd) flags() {} func (c *fingerCmd) run(config *lxd.Config, args []string) error { if len(args) > 1 { return errArgs } var remote string if len(args) == 1 { remote = config.ParseRemote(args[0]) } else { remote = config.DefaultRemote } // New client may or may not need to connect to the remote host, but // client.ServerStatus will at least request the basic information from // the server. client, err := lxd.NewClient(config, remote) if err != nil { return err } _, err = client.ServerStatus() return err } lxd-2.0.0/lxc/help.go000066400000000000000000000041711270277227600143640ustar00rootroot00000000000000package main import ( "bufio" "bytes" "fmt" "os" "sort" "strings" "github.com/lxc/lxd" "github.com/lxc/lxd/shared/gnuflag" "github.com/lxc/lxd/shared/i18n" ) type helpCmd struct { showAll bool } func (c *helpCmd) showByDefault() bool { return true } func (c *helpCmd) usage() string { return i18n.G( `Presents details on how to use LXD. lxd help [--all]`) } func (c *helpCmd) flags() { gnuflag.BoolVar(&c.showAll, "all", false, i18n.G("Show all commands (not just interesting ones)")) } func (c *helpCmd) run(_ *lxd.Config, args []string) error { if len(args) > 0 { for _, name := range args { cmd, ok := commands[name] if !ok { fmt.Fprintf(os.Stderr, i18n.G("error: unknown command: %s")+"\n", name) } else { fmt.Fprintf(os.Stderr, cmd.usage()+"\n") } } return nil } fmt.Println(i18n.G("Usage: lxc [subcommand] [options]")) fmt.Println(i18n.G("Available commands:")) var names []string for name := range commands { names = append(names, name) } sort.Strings(names) for _, name := range names { cmd := commands[name] if c.showAll || cmd.showByDefault() { fmt.Printf("\t%-10s - %s\n", name, c.summaryLine(cmd.usage())) } } if !c.showAll { fmt.Println() fmt.Println(i18n.G("Options:")) fmt.Println(" --all " + i18n.G("Print less common commands.")) fmt.Println(" --debug " + i18n.G("Print debug information.")) fmt.Println(" --verbose " + i18n.G("Print verbose information.")) fmt.Println() fmt.Println(i18n.G("Environment:")) fmt.Println(" LXD_CONF " + i18n.G("Path to an alternate client configuration directory.")) fmt.Println(" LXD_DIR " + i18n.G("Path to an alternate server directory.")) } return nil } // summaryLine returns the first line of the help text. Conventionally, this // should be a one-line command summary, potentially followed by a longer // explanation. func (c *helpCmd) summaryLine(usage string) string { usage = strings.TrimSpace(usage) s := bufio.NewScanner(bytes.NewBufferString(usage)) if s.Scan() { if len(s.Text()) > 1 { return s.Text() } } return i18n.G("Missing summary.") } lxd-2.0.0/lxc/image.go000066400000000000000000000421251270277227600145170ustar00rootroot00000000000000package main import ( "fmt" "io/ioutil" "os" "regexp" "sort" "strings" "syscall" "github.com/olekukonko/tablewriter" "gopkg.in/yaml.v2" "github.com/lxc/lxd" "github.com/lxc/lxd/shared" "github.com/lxc/lxd/shared/gnuflag" "github.com/lxc/lxd/shared/i18n" "github.com/lxc/lxd/shared/termios" ) type SortImage [][]string func (a SortImage) Len() int { return len(a) } func (a SortImage) Swap(i, j int) { a[i], a[j] = a[j], a[i] } func (a SortImage) Less(i, j int) bool { if a[i][0] == a[j][0] { if a[i][3] == "" { return false } if a[j][3] == "" { return true } return a[i][3] < a[j][3] } if a[i][0] == "" { return false } if a[j][0] == "" { return true } return a[i][0] < a[j][0] } type aliasList []string func (f *aliasList) String() string { return fmt.Sprint(*f) } func (f *aliasList) Set(value string) error { if f == nil { *f = make(aliasList, 1) } else { *f = append(*f, value) } return nil } type imageCmd struct { addAliases aliasList publicImage bool copyAliases bool autoUpdate bool } func (c *imageCmd) showByDefault() bool { return true } func (c *imageCmd) imageEditHelp() string { return i18n.G( `### This is a yaml representation of the image properties. ### Any line starting with a '# will be ignored. ### ### Each property is represented by a single line: ### An example would be: ### description: My custom image`) } func (c *imageCmd) usage() string { return i18n.G( `Manipulate container images. In LXD containers are created from images. Those images were themselves either generated from an existing container or downloaded from an image server. When using remote images, LXD will automatically cache images for you and remove them upon expiration. The image unique identifier is the hash (sha-256) of its representation as a compressed tarball (or for split images, the concatenation of the metadata and rootfs tarballs). Images can be referenced by their full hash, shortest unique partial hash or alias name (if one is set). lxc image import [rootfs tarball|URL] [remote:] [--public] [--created-at=ISO-8601] [--expires-at=ISO-8601] [--fingerprint=FINGERPRINT] [prop=value] Import an image tarball (or tarballs) into the LXD image store. lxc image copy [remote:] : [--alias=ALIAS].. [--copy-aliases] [--public] [--auto-update] Copy an image from one LXD daemon to another over the network. The auto-update flag instructs the server to keep this image up to date. It requires the source to be an alias and for it to be public. lxc image delete [remote:] Delete an image from the LXD image store. lxc image export [remote:] Export an image from the LXD image store into a distributable tarball. lxc image info [remote:] Print everything LXD knows about a given image. lxc image list [remote:] [filter] List images in the LXD image store. Filters may be of the = form for property based filtering, or part of the image hash or part of the image alias name. lxc image show [remote:] Yaml output of the user modifiable properties of an image. lxc image edit [remote:] Edit image, either by launching external editor or reading STDIN. Example: lxc image edit # launch editor cat image.yml | lxc image edit # read from image.yml lxc image alias create [remote:] Create a new alias for an existing image. lxc image alias delete [remote:] Delete an alias. lxc image alias list [remote:] [filter] List the aliases. Filters may be part of the image hash or part of the image alias name. `) } func (c *imageCmd) flags() { gnuflag.BoolVar(&c.publicImage, "public", false, i18n.G("Make image public")) gnuflag.BoolVar(&c.copyAliases, "copy-aliases", false, i18n.G("Copy aliases from source")) gnuflag.BoolVar(&c.autoUpdate, "auto-update", false, i18n.G("Keep the image up to date after initial copy")) gnuflag.Var(&c.addAliases, "alias", i18n.G("New alias to define at target")) } func (c *imageCmd) doImageAlias(config *lxd.Config, args []string) error { var remote string switch args[1] { case "list": filters := []string{} if len(args) > 2 { result := strings.SplitN(args[2], ":", 2) if len(result) == 1 { filters = append(filters, args[2]) remote, _ = config.ParseRemoteAndContainer("") } else { remote, _ = config.ParseRemoteAndContainer(args[2]) } } else { remote, _ = config.ParseRemoteAndContainer("") } if len(args) > 3 { for _, filter := range args[3:] { filters = append(filters, filter) } } d, err := lxd.NewClient(config, remote) if err != nil { return err } resp, err := d.ListAliases() if err != nil { return err } c.showAliases(resp, filters) return nil case "create": /* alias create [:] */ if len(args) < 4 { return errArgs } remote, alias := config.ParseRemoteAndContainer(args[2]) target := args[3] d, err := lxd.NewClient(config, remote) if err != nil { return err } /* TODO - what about description? */ err = d.PostAlias(alias, alias, target) return err case "delete": /* alias delete [:] */ if len(args) < 3 { return errArgs } remote, alias := config.ParseRemoteAndContainer(args[2]) d, err := lxd.NewClient(config, remote) if err != nil { return err } err = d.DeleteAlias(alias) return err } return errArgs } func (c *imageCmd) run(config *lxd.Config, args []string) error { var remote string if len(args) < 1 { return errArgs } switch args[0] { case "alias": if len(args) < 2 { return errArgs } return c.doImageAlias(config, args) case "copy": /* copy [:] [:] */ if len(args) != 3 { return errArgs } remote, inName := config.ParseRemoteAndContainer(args[1]) if inName == "" { inName = "default" } destRemote, outName := config.ParseRemoteAndContainer(args[2]) if outName != "" { return errArgs } d, err := lxd.NewClient(config, remote) if err != nil { return err } dest, err := lxd.NewClient(config, destRemote) if err != nil { return err } progressHandler := func(progress string) { fmt.Printf(i18n.G("Copying the image: %s")+"\r", progress) } err = d.CopyImage(inName, dest, c.copyAliases, c.addAliases, c.publicImage, c.autoUpdate, progressHandler) if err == nil { fmt.Println(i18n.G("Image copied successfully!")) } return err case "delete": /* delete [:] */ if len(args) < 2 { return errArgs } remote, inName := config.ParseRemoteAndContainer(args[1]) if inName == "" { inName = "default" } d, err := lxd.NewClient(config, remote) if err != nil { return err } image := c.dereferenceAlias(d, inName) err = d.DeleteImage(image) return err case "info": if len(args) < 2 { return errArgs } remote, inName := config.ParseRemoteAndContainer(args[1]) if inName == "" { inName = "default" } d, err := lxd.NewClient(config, remote) if err != nil { return err } image := c.dereferenceAlias(d, inName) info, err := d.GetImageInfo(image) if err != nil { return err } public := i18n.G("no") if info.Public { public = i18n.G("yes") } autoUpdate := i18n.G("disabled") if info.AutoUpdate { autoUpdate = i18n.G("enabled") } fmt.Printf(i18n.G("Fingerprint: %s")+"\n", info.Fingerprint) fmt.Printf(i18n.G("Size: %.2fMB")+"\n", float64(info.Size)/1024.0/1024.0) fmt.Printf(i18n.G("Architecture: %s")+"\n", info.Architecture) fmt.Printf(i18n.G("Public: %s")+"\n", public) fmt.Printf(i18n.G("Timestamps:") + "\n") const layout = "2006/01/02 15:04 UTC" if info.CreationDate.UTC().Unix() != 0 { fmt.Printf(" "+i18n.G("Created: %s")+"\n", info.CreationDate.UTC().Format(layout)) } fmt.Printf(" "+i18n.G("Uploaded: %s")+"\n", info.UploadDate.UTC().Format(layout)) if info.ExpiryDate.UTC().Unix() != 0 { fmt.Printf(" "+i18n.G("Expires: %s")+"\n", info.ExpiryDate.UTC().Format(layout)) } else { fmt.Printf(" " + i18n.G("Expires: never") + "\n") } fmt.Println(i18n.G("Properties:")) for key, value := range info.Properties { fmt.Printf(" %s: %s\n", key, value) } fmt.Println(i18n.G("Aliases:")) for _, alias := range info.Aliases { fmt.Printf(" - %s\n", alias.Name) } fmt.Printf(i18n.G("Auto update: %s")+"\n", autoUpdate) if info.Source != nil { fmt.Println(i18n.G("Source:")) fmt.Printf(" Server: %s\n", info.Source.Server) fmt.Printf(" Protocol: %s\n", info.Source.Protocol) fmt.Printf(" Alias: %s\n", info.Source.Alias) } return nil case "import": if len(args) < 2 { return errArgs } var fingerprint string var imageFile string var rootfsFile string var properties []string var remote string for _, arg := range args[1:] { split := strings.Split(arg, "=") if len(split) == 1 || shared.PathExists(arg) { if strings.HasSuffix(arg, ":") { remote = config.ParseRemote(arg) } else { if imageFile == "" { imageFile = args[1] } else { rootfsFile = arg } } } else { properties = append(properties, arg) } } if remote == "" { remote = config.DefaultRemote } if imageFile == "" { return errArgs } d, err := lxd.NewClient(config, remote) if err != nil { return err } handler := func(percent int) { fmt.Printf(i18n.G("Transferring image: %d%%")+"\r", percent) if percent == 100 { fmt.Printf("\n") } } if strings.HasPrefix(imageFile, "https://") { fingerprint, err = d.PostImageURL(imageFile, c.publicImage, c.addAliases) } else if strings.HasPrefix(imageFile, "http://") { return fmt.Errorf(i18n.G("Only https:// is supported for remote image import.")) } else { fingerprint, err = d.PostImage(imageFile, rootfsFile, properties, c.publicImage, c.addAliases, handler) } if err != nil { return err } fmt.Printf(i18n.G("Image imported with fingerprint: %s")+"\n", fingerprint) return nil case "list": filters := []string{} if len(args) > 1 { result := strings.SplitN(args[1], ":", 2) if len(result) == 1 { filters = append(filters, args[1]) remote, _ = config.ParseRemoteAndContainer("") } else { remote, _ = config.ParseRemoteAndContainer(args[1]) } } else { remote, _ = config.ParseRemoteAndContainer("") } if len(args) > 2 { for _, filter := range args[2:] { filters = append(filters, filter) } } d, err := lxd.NewClient(config, remote) if err != nil { return err } images, err := d.ListImages() if err != nil { return err } return c.showImages(images, filters) case "edit": if len(args) < 2 { return errArgs } remote, inName := config.ParseRemoteAndContainer(args[1]) if inName == "" { inName = "default" } d, err := lxd.NewClient(config, remote) if err != nil { return err } image := c.dereferenceAlias(d, inName) if image == "" { image = inName } return c.doImageEdit(d, image) case "export": if len(args) < 2 { return errArgs } remote, inName := config.ParseRemoteAndContainer(args[1]) if inName == "" { inName = "default" } d, err := lxd.NewClient(config, remote) if err != nil { return err } image := c.dereferenceAlias(d, inName) target := "." if len(args) > 2 { target = args[2] } outfile, err := d.ExportImage(image, target) if err != nil { return err } if target != "-" { fmt.Printf(i18n.G("Output is in %s")+"\n", outfile) } return nil case "show": if len(args) < 2 { return errArgs } remote, inName := config.ParseRemoteAndContainer(args[1]) if inName == "" { inName = "default" } d, err := lxd.NewClient(config, remote) if err != nil { return err } image := c.dereferenceAlias(d, inName) info, err := d.GetImageInfo(image) if err != nil { return err } properties := info.Brief() data, err := yaml.Marshal(&properties) fmt.Printf("%s", data) return err default: return errArgs } } func (c *imageCmd) dereferenceAlias(d *lxd.Client, inName string) string { result := d.GetAlias(inName) if result == "" { return inName } return result } func (c *imageCmd) shortestAlias(list []shared.ImageAlias) string { shortest := "" for _, l := range list { if shortest == "" { shortest = l.Name continue } if len(l.Name) != 0 && len(l.Name) < len(shortest) { shortest = l.Name } } return shortest } func (c *imageCmd) findDescription(props map[string]string) string { for k, v := range props { if k == "description" { return v } } return "" } func (c *imageCmd) showImages(images []shared.ImageInfo, filters []string) error { data := [][]string{} for _, image := range images { if !c.imageShouldShow(filters, &image) { continue } shortest := c.shortestAlias(image.Aliases) if len(image.Aliases) > 1 { shortest = fmt.Sprintf(i18n.G("%s (%d more)"), shortest, len(image.Aliases)-1) } fp := image.Fingerprint[0:12] public := i18n.G("no") description := c.findDescription(image.Properties) if image.Public { public = i18n.G("yes") } const layout = "Jan 2, 2006 at 3:04pm (MST)" uploaded := image.UploadDate.UTC().Format(layout) size := fmt.Sprintf("%.2fMB", float64(image.Size)/1024.0/1024.0) data = append(data, []string{shortest, fp, public, description, image.Architecture, size, uploaded}) } table := tablewriter.NewWriter(os.Stdout) table.SetAutoWrapText(false) table.SetAlignment(tablewriter.ALIGN_LEFT) table.SetRowLine(true) table.SetHeader([]string{ i18n.G("ALIAS"), i18n.G("FINGERPRINT"), i18n.G("PUBLIC"), i18n.G("DESCRIPTION"), i18n.G("ARCH"), i18n.G("SIZE"), i18n.G("UPLOAD DATE")}) sort.Sort(SortImage(data)) table.AppendBulk(data) table.Render() return nil } func (c *imageCmd) showAliases(aliases shared.ImageAliases, filters []string) error { data := [][]string{} for _, alias := range aliases { if !c.aliasShouldShow(filters, &alias) { continue } data = append(data, []string{alias.Name, alias.Target[0:12], alias.Description}) } table := tablewriter.NewWriter(os.Stdout) table.SetAutoWrapText(false) table.SetAlignment(tablewriter.ALIGN_LEFT) table.SetRowLine(true) table.SetHeader([]string{ i18n.G("ALIAS"), i18n.G("FINGERPRINT"), i18n.G("DESCRIPTION")}) sort.Sort(SortImage(data)) table.AppendBulk(data) table.Render() return nil } func (c *imageCmd) doImageEdit(client *lxd.Client, image string) error { // If stdin isn't a terminal, read text from it if !termios.IsTerminal(int(syscall.Stdin)) { contents, err := ioutil.ReadAll(os.Stdin) if err != nil { return err } newdata := shared.BriefImageInfo{} err = yaml.Unmarshal(contents, &newdata) if err != nil { return err } return client.PutImageInfo(image, newdata) } // Extract the current value config, err := client.GetImageInfo(image) if err != nil { return err } brief := config.Brief() data, err := yaml.Marshal(&brief) if err != nil { return err } // Spawn the editor content, err := shared.TextEditor("", []byte(c.imageEditHelp()+"\n\n"+string(data))) if err != nil { return err } for { // Parse the text received from the editor newdata := shared.BriefImageInfo{} err = yaml.Unmarshal(content, &newdata) if err == nil { err = client.PutImageInfo(image, newdata) } // Respawn the editor if err != nil { fmt.Fprintf(os.Stderr, i18n.G("Config parsing error: %s")+"\n", err) fmt.Println(i18n.G("Press enter to start the editor again")) _, err := os.Stdin.Read(make([]byte, 1)) if err != nil { return err } content, err = shared.TextEditor("", content) if err != nil { return err } continue } break } return nil } func (c *imageCmd) imageShouldShow(filters []string, state *shared.ImageInfo) bool { if len(filters) == 0 { return true } for _, filter := range filters { found := false if strings.Contains(filter, "=") { membs := strings.SplitN(filter, "=", 2) key := membs[0] var value string if len(membs) < 2 { value = "" } else { value = membs[1] } for configKey, configValue := range state.Properties { list := listCmd{} if list.dotPrefixMatch(key, configKey) { //try to test filter value as a regexp regexpValue := value if !(strings.Contains(value, "^") || strings.Contains(value, "$")) { regexpValue = "^" + regexpValue + "$" } r, err := regexp.Compile(regexpValue) //if not regexp compatible use original value if err != nil { if value == configValue { found = true break } } else if r.MatchString(configValue) == true { found = true break } } } } else { for _, alias := range state.Aliases { if strings.Contains(alias.Name, filter) { found = true break } } if strings.Contains(state.Fingerprint, filter) { found = true } } if !found { return false } } return true } func (c *imageCmd) aliasShouldShow(filters []string, state *shared.ImageAliasesEntry) bool { if len(filters) == 0 { return true } for _, filter := range filters { if strings.Contains(state.Name, filter) || strings.Contains(state.Target, filter) { return true } } return false } lxd-2.0.0/lxc/info.go000066400000000000000000000123071270277227600143670ustar00rootroot00000000000000package main import ( "fmt" "io/ioutil" "strings" "gopkg.in/yaml.v2" "github.com/lxc/lxd" "github.com/lxc/lxd/shared" "github.com/lxc/lxd/shared/gnuflag" "github.com/lxc/lxd/shared/i18n" ) type infoCmd struct { showLog bool } func (c *infoCmd) showByDefault() bool { return true } func (c *infoCmd) usage() string { return i18n.G( `List information on LXD servers and containers. For a container: lxc info [:]container [--show-log] For a server: lxc info [:]`) } func (c *infoCmd) flags() { gnuflag.BoolVar(&c.showLog, "show-log", false, i18n.G("Show the container's last 100 log lines?")) } func (c *infoCmd) run(config *lxd.Config, args []string) error { var remote string var cName string if len(args) == 1 { remote, cName = config.ParseRemoteAndContainer(args[0]) } else { remote, cName = config.ParseRemoteAndContainer("") } d, err := lxd.NewClient(config, remote) if err != nil { return err } if cName == "" { return c.remoteInfo(d) } else { return c.containerInfo(d, cName, c.showLog) } } func (c *infoCmd) remoteInfo(d *lxd.Client) error { serverStatus, err := d.ServerStatus() if err != nil { return err } data, err := yaml.Marshal(&serverStatus) if err != nil { return err } fmt.Printf("%s", data) return nil } func (c *infoCmd) containerInfo(d *lxd.Client, name string, showLog bool) error { ct, err := d.ContainerInfo(name) if err != nil { return err } cs, err := d.ContainerState(name) if err != nil { return err } const layout = "2006/01/02 15:04 UTC" fmt.Printf(i18n.G("Name: %s")+"\n", ct.Name) fmt.Printf(i18n.G("Architecture: %s")+"\n", ct.Architecture) if ct.CreationDate.UTC().Unix() != 0 { fmt.Printf(i18n.G("Created: %s")+"\n", ct.CreationDate.UTC().Format(layout)) } fmt.Printf(i18n.G("Status: %s")+"\n", ct.Status) if ct.Ephemeral { fmt.Printf(i18n.G("Type: ephemeral") + "\n") } else { fmt.Printf(i18n.G("Type: persistent") + "\n") } fmt.Printf(i18n.G("Profiles: %s")+"\n", strings.Join(ct.Profiles, ", ")) if cs.Pid != 0 { fmt.Printf(i18n.G("Pid: %d")+"\n", cs.Pid) // IP addresses ipInfo := "" if cs.Network != nil { for netName, net := range cs.Network { vethStr := "" if net.HostName != "" { vethStr = fmt.Sprintf("\t%s", net.HostName) } for _, addr := range net.Addresses { ipInfo += fmt.Sprintf(" %s:\t%s\t%s%s\n", netName, addr.Family, addr.Address, vethStr) } } } if ipInfo != "" { fmt.Println(i18n.G("Ips:")) fmt.Printf(ipInfo) } fmt.Println(i18n.G("Resources:")) // Processes fmt.Printf(" "+i18n.G("Processes: %d")+"\n", cs.Processes) // Disk usage diskInfo := "" if cs.Disk != nil { for entry, disk := range cs.Disk { if disk.Usage != 0 { diskInfo += fmt.Sprintf(" %s: %s\n", entry, shared.GetByteSizeString(disk.Usage)) } } } if diskInfo != "" { fmt.Println(i18n.G(" Disk usage:")) fmt.Printf(diskInfo) } // Memory usage memoryInfo := "" if cs.Memory.Usage != 0 { memoryInfo += fmt.Sprintf(" %s: %s\n", i18n.G("Memory (current)"), shared.GetByteSizeString(cs.Memory.Usage)) } if cs.Memory.UsagePeak != 0 { memoryInfo += fmt.Sprintf(" %s: %s\n", i18n.G("Memory (peak)"), shared.GetByteSizeString(cs.Memory.UsagePeak)) } if cs.Memory.SwapUsage != 0 { memoryInfo += fmt.Sprintf(" %s: %s\n", i18n.G("Swap (current)"), shared.GetByteSizeString(cs.Memory.SwapUsage)) } if cs.Memory.SwapUsagePeak != 0 { memoryInfo += fmt.Sprintf(" %s: %s\n", i18n.G("Swap (peak)"), shared.GetByteSizeString(cs.Memory.SwapUsagePeak)) } if memoryInfo != "" { fmt.Println(i18n.G(" Memory usage:")) fmt.Printf(memoryInfo) } // Network usage networkInfo := "" if cs.Network != nil { for netName, net := range cs.Network { networkInfo += fmt.Sprintf(" %s:\n", netName) networkInfo += fmt.Sprintf(" %s: %s\n", i18n.G("Bytes received"), shared.GetByteSizeString(net.Counters.BytesReceived)) networkInfo += fmt.Sprintf(" %s: %s\n", i18n.G("Bytes sent"), shared.GetByteSizeString(net.Counters.BytesSent)) networkInfo += fmt.Sprintf(" %s: %d\n", i18n.G("Packets received"), net.Counters.PacketsReceived) networkInfo += fmt.Sprintf(" %s: %d\n", i18n.G("Packets sent"), net.Counters.PacketsSent) } } if networkInfo != "" { fmt.Println(i18n.G(" Network usage:")) fmt.Printf(networkInfo) } } // List snapshots first_snapshot := true snaps, err := d.ListSnapshots(name) if err != nil { return nil } for _, snap := range snaps { if first_snapshot { fmt.Println(i18n.G("Snapshots:")) } fields := strings.Split(snap.Name, shared.SnapshotDelimiter) fmt.Printf(" %s", fields[len(fields)-1]) if snap.CreationDate.UTC().Unix() != 0 { fmt.Printf(" ("+i18n.G("taken at %s")+")", snap.CreationDate.UTC().Format(layout)) } if snap.Stateful { fmt.Printf(" (" + i18n.G("stateful") + ")") } else { fmt.Printf(" (" + i18n.G("stateless") + ")") } fmt.Printf("\n") first_snapshot = false } if showLog { log, err := d.GetLog(name, "lxc.log") if err != nil { return err } stuff, err := ioutil.ReadAll(log) if err != nil { return err } fmt.Printf("\n"+i18n.G("Log:")+"\n\n%s\n", string(stuff)) } return nil } lxd-2.0.0/lxc/init.go000066400000000000000000000125621270277227600144020ustar00rootroot00000000000000package main import ( "fmt" "os" "strings" "github.com/lxc/lxd" "github.com/lxc/lxd/shared" "github.com/lxc/lxd/shared/gnuflag" "github.com/lxc/lxd/shared/i18n" ) type profileList []string var configMap map[string]string func (f *profileList) String() string { return fmt.Sprint(*f) } type configList []string func (f *configList) String() string { return fmt.Sprint(configMap) } func (f *configList) Set(value string) error { if value == "" { return fmt.Errorf(i18n.G("Invalid configuration key")) } items := strings.SplitN(value, "=", 2) if len(items) < 2 { return fmt.Errorf(i18n.G("Invalid configuration key")) } if configMap == nil { configMap = map[string]string{} } configMap[items[0]] = items[1] return nil } func (f *profileList) Set(value string) error { if value == "" { initRequestedEmptyProfiles = true return nil } if f == nil { *f = make(profileList, 1) } else { *f = append(*f, value) } return nil } var initRequestedEmptyProfiles bool type initCmd struct { profArgs profileList confArgs configList ephem bool } func (c *initCmd) showByDefault() bool { return false } func (c *initCmd) usage() string { return i18n.G( `Initialize a container from a particular image. lxc init [remote:] [remote:][] [--ephemeral|-e] [--profile|-p ...] [--config|-c ...] Initializes a container using the specified image and name. Not specifying -p will result in the default profile. Specifying "-p" with no argument will result in no profile. Example: lxc init ubuntu u1`) } func (c *initCmd) is_ephem(s string) bool { switch s { case "-e": return true case "--ephemeral": return true } return false } func (c *initCmd) is_profile(s string) bool { switch s { case "-p": return true case "--profile": return true } return false } func (c *initCmd) massage_args() { l := len(os.Args) if l < 2 { return } if c.is_profile(os.Args[l-1]) { initRequestedEmptyProfiles = true os.Args = os.Args[0 : l-1] return } if l < 3 { return } /* catch "lxc init ubuntu -p -e */ if c.is_ephem(os.Args[l-1]) && c.is_profile(os.Args[l-2]) { initRequestedEmptyProfiles = true newargs := os.Args[0 : l-2] newargs = append(newargs, os.Args[l-1]) return } } func (c *initCmd) flags() { c.massage_args() gnuflag.Var(&c.confArgs, "config", i18n.G("Config key/value to apply to the new container")) gnuflag.Var(&c.confArgs, "c", i18n.G("Config key/value to apply to the new container")) gnuflag.Var(&c.profArgs, "profile", i18n.G("Profile to apply to the new container")) gnuflag.Var(&c.profArgs, "p", i18n.G("Profile to apply to the new container")) gnuflag.BoolVar(&c.ephem, "ephemeral", false, i18n.G("Ephemeral container")) gnuflag.BoolVar(&c.ephem, "e", false, i18n.G("Ephemeral container")) } func (c *initCmd) run(config *lxd.Config, args []string) error { if len(args) > 2 || len(args) < 1 { return errArgs } iremote, image := config.ParseRemoteAndContainer(args[0]) var name string var remote string if len(args) == 2 { remote, name = config.ParseRemoteAndContainer(args[1]) } else { remote, name = config.ParseRemoteAndContainer("") } d, err := lxd.NewClient(config, remote) if err != nil { return err } // TODO: implement the syntax for supporting other image types/remotes /* * initRequestedEmptyProfiles means user requested empty * !initRequestedEmptyProfiles but len(profArgs) == 0 means use profile default */ profiles := []string{} for _, p := range c.profArgs { profiles = append(profiles, p) } var resp *lxd.Response if name == "" { fmt.Printf(i18n.G("Creating the container") + "\n") } else { fmt.Printf(i18n.G("Creating %s")+"\n", name) } if !initRequestedEmptyProfiles && len(profiles) == 0 { resp, err = d.Init(name, iremote, image, nil, configMap, c.ephem) } else { resp, err = d.Init(name, iremote, image, &profiles, configMap, c.ephem) } if err != nil { return err } c.initProgressTracker(d, resp.Operation) err = d.WaitForSuccess(resp.Operation) if err != nil { return err } else { op, err := resp.MetadataAsOperation() if err != nil { return fmt.Errorf(i18n.G("didn't get any affected image, container or snapshot from server")) } containers, ok := op.Resources["containers"] if !ok || len(containers) == 0 { return fmt.Errorf(i18n.G("didn't get any affected image, container or snapshot from server")) } if len(containers) == 1 && name == "" { fields := strings.Split(containers[0], "/") fmt.Printf(i18n.G("Container name is: %s")+"\n", fields[len(fields)-1]) } } return nil } func (c *initCmd) initProgressTracker(d *lxd.Client, operation string) { handler := func(msg interface{}) { if msg == nil { return } event := msg.(map[string]interface{}) if event["type"].(string) != "operation" { return } if event["metadata"] == nil { return } md := event["metadata"].(map[string]interface{}) if !strings.HasSuffix(operation, md["id"].(string)) { return } if md["metadata"] == nil { return } if shared.StatusCode(md["status_code"].(float64)).IsFinal() { return } opMd := md["metadata"].(map[string]interface{}) _, ok := opMd["download_progress"] if ok { fmt.Printf(i18n.G("Retrieving image: %s")+"\r", opMd["download_progress"].(string)) } if opMd["download_progress"].(string) == "100%" { fmt.Printf("\n") } } go d.Monitor([]string{"operation"}, handler) } lxd-2.0.0/lxc/launch.go000066400000000000000000000066551270277227600147170ustar00rootroot00000000000000package main import ( "fmt" "strings" "github.com/lxc/lxd" "github.com/lxc/lxd/shared" "github.com/lxc/lxd/shared/gnuflag" "github.com/lxc/lxd/shared/i18n" ) type launchCmd struct { init initCmd } func (c *launchCmd) showByDefault() bool { return true } func (c *launchCmd) usage() string { return i18n.G( `Launch a container from a particular image. lxc launch [remote:] [remote:][] [--ephemeral|-e] [--profile|-p ...] [--config|-c ...] Launches a container using the specified image and name. Not specifying -p will result in the default profile. Specifying "-p" with no argument will result in no profile. Example: lxc launch ubuntu u1`) } func (c *launchCmd) flags() { c.init = initCmd{} c.init.massage_args() gnuflag.Var(&c.init.confArgs, "config", i18n.G("Config key/value to apply to the new container")) gnuflag.Var(&c.init.confArgs, "c", i18n.G("Config key/value to apply to the new container")) gnuflag.Var(&c.init.profArgs, "profile", i18n.G("Profile to apply to the new container")) gnuflag.Var(&c.init.profArgs, "p", i18n.G("Profile to apply to the new container")) gnuflag.BoolVar(&c.init.ephem, "ephemeral", false, i18n.G("Ephemeral container")) gnuflag.BoolVar(&c.init.ephem, "e", false, i18n.G("Ephemeral container")) } func (c *launchCmd) run(config *lxd.Config, args []string) error { if len(args) > 2 || len(args) < 1 { return errArgs } iremote, image := config.ParseRemoteAndContainer(args[0]) var name string var remote string if len(args) == 2 { remote, name = config.ParseRemoteAndContainer(args[1]) } else { remote, name = config.ParseRemoteAndContainer("") } d, err := lxd.NewClient(config, remote) if err != nil { return err } /* * initRequestedEmptyProfiles means user requested empty * !initRequestedEmptyProfiles but len(profArgs) == 0 means use profile default */ var resp *lxd.Response profiles := []string{} for _, p := range c.init.profArgs { profiles = append(profiles, p) } if !initRequestedEmptyProfiles && len(profiles) == 0 { resp, err = d.Init(name, iremote, image, nil, configMap, c.init.ephem) } else { resp, err = d.Init(name, iremote, image, &profiles, configMap, c.init.ephem) } if err != nil { return err } c.init.initProgressTracker(d, resp.Operation) if name == "" { op, err := resp.MetadataAsOperation() if err != nil { return fmt.Errorf(i18n.G("didn't get any affected image, container or snapshot from server")) } containers, ok := op.Resources["containers"] if !ok || len(containers) == 0 { return fmt.Errorf(i18n.G("didn't get any affected image, container or snapshot from server")) } var version string toScan := strings.Replace(containers[0], "/", " ", -1) count, err := fmt.Sscanf(toScan, " %s containers %s", &version, &name) if err != nil { return err } if count != 2 { return fmt.Errorf(i18n.G("bad number of things scanned from image, container or snapshot")) } if version != shared.APIVersion { return fmt.Errorf(i18n.G("got bad version")) } } fmt.Printf(i18n.G("Creating %s")+"\n", name) if err = d.WaitForSuccess(resp.Operation); err != nil { return err } fmt.Printf(i18n.G("Starting %s")+"\n", name) resp, err = d.Action(name, shared.Start, -1, false, false) if err != nil { return err } err = d.WaitForSuccess(resp.Operation) if err != nil { return fmt.Errorf("%s\n"+i18n.G("Try `lxc info --show-log %s` for more info"), err, name) } return nil } lxd-2.0.0/lxc/list.go000066400000000000000000000263601270277227600144130ustar00rootroot00000000000000package main import ( "encoding/json" "fmt" "os" "regexp" "sort" "strings" "sync" "github.com/olekukonko/tablewriter" "github.com/lxc/lxd" "github.com/lxc/lxd/shared" "github.com/lxc/lxd/shared/gnuflag" "github.com/lxc/lxd/shared/i18n" ) type column struct { Name string Data columnData NeedsState bool NeedsSnapshots bool } type columnData func(shared.ContainerInfo, *shared.ContainerState, []shared.SnapshotInfo) string type byName [][]string func (a byName) Len() int { return len(a) } func (a byName) Swap(i, j int) { a[i], a[j] = a[j], a[i] } func (a byName) Less(i, j int) bool { if a[i][0] == "" { return false } if a[j][0] == "" { return true } return a[i][0] < a[j][0] } const ( listFormatTable = "table" listFormatJSON = "json" ) type listCmd struct { chosenColumnRunes string fast bool format string } func (c *listCmd) showByDefault() bool { return true } func (c *listCmd) usage() string { return i18n.G( `Lists the available resources. lxc list [resource] [filters] [--format table|json] [-c columns] [--fast] The filters are: * A single keyword like "web" which will list any container with "web" in its name. * A key/value pair referring to a configuration item. For those, the namespace can be abreviated to the smallest unambiguous identifier: * "user.blah=abc" will list all containers with the "blah" user property set to "abc" * "u.blah=abc" will do the same * "security.privileged=1" will list all privileged containers * "s.privileged=1" will do the same Columns for table format are: * 4 - IPv4 address * 6 - IPv6 address * a - architecture * c - creation date * n - name * p - pid of container init process * P - profiles * s - state * S - number of snapshots * t - type (persistent or ephemeral) Default column layout: ns46tS Fast column layout: nsacPt`) } func (c *listCmd) flags() { gnuflag.StringVar(&c.chosenColumnRunes, "c", "ns46tS", i18n.G("Columns")) gnuflag.StringVar(&c.chosenColumnRunes, "columns", "ns46tS", i18n.G("Columns")) gnuflag.StringVar(&c.format, "format", "table", i18n.G("Format")) gnuflag.BoolVar(&c.fast, "fast", false, i18n.G("Fast mode (same as --columns=nsacPt")) } // This seems a little excessive. func (c *listCmd) dotPrefixMatch(short string, full string) bool { fullMembs := strings.Split(full, ".") shortMembs := strings.Split(short, ".") if len(fullMembs) != len(shortMembs) { return false } for i, _ := range fullMembs { if !strings.HasPrefix(fullMembs[i], shortMembs[i]) { return false } } return true } func (c *listCmd) shouldShow(filters []string, state *shared.ContainerInfo) bool { for _, filter := range filters { if strings.Contains(filter, "=") { membs := strings.SplitN(filter, "=", 2) key := membs[0] var value string if len(membs) < 2 { value = "" } else { value = membs[1] } found := false for configKey, configValue := range state.ExpandedConfig { if c.dotPrefixMatch(key, configKey) { //try to test filter value as a regexp regexpValue := value if !(strings.Contains(value, "^") || strings.Contains(value, "$")) { regexpValue = "^" + regexpValue + "$" } r, err := regexp.Compile(regexpValue) //if not regexp compatible use original value if err != nil { if value == configValue { found = true break } else { // the property was found but didn't match return false } } else if r.MatchString(configValue) == true { found = true break } } } if !found { return false } } else { if !strings.Contains(state.Name, filter) { return false } } } return true } func (c *listCmd) listContainers(d *lxd.Client, cinfos []shared.ContainerInfo, filters []string, columns []column) error { headers := []string{} for _, column := range columns { headers = append(headers, column.Name) } threads := 10 if len(cinfos) < threads { threads = len(cinfos) } cStates := map[string]*shared.ContainerState{} cStatesLock := sync.Mutex{} cStatesQueue := make(chan string, threads) cStatesWg := sync.WaitGroup{} cSnapshots := map[string][]shared.SnapshotInfo{} cSnapshotsLock := sync.Mutex{} cSnapshotsQueue := make(chan string, threads) cSnapshotsWg := sync.WaitGroup{} for i := 0; i < threads; i++ { cStatesWg.Add(1) go func() { for { cName, more := <-cStatesQueue if !more { break } state, err := d.ContainerState(cName) if err != nil { continue } cStatesLock.Lock() cStates[cName] = state cStatesLock.Unlock() } cStatesWg.Done() }() cSnapshotsWg.Add(1) go func() { for { cName, more := <-cSnapshotsQueue if !more { break } snaps, err := d.ListSnapshots(cName) if err != nil { continue } cSnapshotsLock.Lock() cSnapshots[cName] = snaps cSnapshotsLock.Unlock() } cSnapshotsWg.Done() }() } for _, cInfo := range cinfos { if !c.shouldShow(filters, &cInfo) { continue } for _, column := range columns { if column.NeedsState && cInfo.IsActive() { _, ok := cStates[cInfo.Name] if ok { continue } cStatesLock.Lock() cStates[cInfo.Name] = nil cStatesLock.Unlock() cStatesQueue <- cInfo.Name } if column.NeedsSnapshots { _, ok := cSnapshots[cInfo.Name] if ok { continue } cSnapshotsLock.Lock() cSnapshots[cInfo.Name] = nil cSnapshotsLock.Unlock() cSnapshotsQueue <- cInfo.Name } } } close(cStatesQueue) close(cSnapshotsQueue) cStatesWg.Wait() cSnapshotsWg.Wait() switch c.format { case listFormatTable: data := [][]string{} for _, cInfo := range cinfos { if !c.shouldShow(filters, &cInfo) { continue } col := []string{} for _, column := range columns { col = append(col, column.Data(cInfo, cStates[cInfo.Name], cSnapshots[cInfo.Name])) } data = append(data, col) } table := tablewriter.NewWriter(os.Stdout) table.SetAutoWrapText(false) table.SetAlignment(tablewriter.ALIGN_LEFT) table.SetRowLine(true) table.SetHeader(headers) sort.Sort(byName(data)) table.AppendBulk(data) table.Render() case listFormatJSON: data := make([]listContainerItem, len(cinfos)) for i := range cinfos { data[i].ContainerInfo = &cinfos[i] data[i].State = cStates[cinfos[i].Name] data[i].Snapshots = cSnapshots[cinfos[i].Name] } enc := json.NewEncoder(os.Stdout) err := enc.Encode(data) if err != nil { return err } default: return fmt.Errorf("invalid format %q", c.format) } return nil } type listContainerItem struct { *shared.ContainerInfo State *shared.ContainerState `json:"state"` Snapshots []shared.SnapshotInfo `json:"snapshots"` } func (c *listCmd) run(config *lxd.Config, args []string) error { var remote string name := "" filters := []string{} if len(args) != 0 { filters = args if strings.Contains(args[0], ":") { remote, name = config.ParseRemoteAndContainer(args[0]) filters = args[1:] } else if !strings.Contains(args[0], "=") { remote = config.DefaultRemote name = args[0] } } if remote == "" { remote = config.DefaultRemote } d, err := lxd.NewClient(config, remote) if err != nil { return err } var cts []shared.ContainerInfo ctslist, err := d.ListContainers() if err != nil { return err } if name == "" { cts = ctslist } else { for _, cinfo := range ctslist { if len(cinfo.Name) >= len(name) && cinfo.Name[0:len(name)] == name { cts = append(cts, cinfo) } } } columns_map := map[rune]column{ '4': column{i18n.G("IPV4"), c.IP4ColumnData, true, false}, '6': column{i18n.G("IPV6"), c.IP6ColumnData, true, false}, 'a': column{i18n.G("ARCHITECTURE"), c.ArchitectureColumnData, false, false}, 'c': column{i18n.G("CREATED AT"), c.CreatedColumnData, false, false}, 'n': column{i18n.G("NAME"), c.nameColumnData, false, false}, 'p': column{i18n.G("PID"), c.PIDColumnData, true, false}, 'P': column{i18n.G("PROFILES"), c.ProfilesColumnData, false, false}, 'S': column{i18n.G("SNAPSHOTS"), c.numberSnapshotsColumnData, false, true}, 's': column{i18n.G("STATE"), c.statusColumnData, false, false}, 't': column{i18n.G("TYPE"), c.typeColumnData, false, false}, } if c.fast { c.chosenColumnRunes = "nsacPt" } columns := []column{} for _, columnRune := range c.chosenColumnRunes { if column, ok := columns_map[columnRune]; ok { columns = append(columns, column) } else { return fmt.Errorf("%s does contain invalid column characters\n", c.chosenColumnRunes) } } return c.listContainers(d, cts, filters, columns) } func (c *listCmd) nameColumnData(cInfo shared.ContainerInfo, cState *shared.ContainerState, cSnaps []shared.SnapshotInfo) string { return cInfo.Name } func (c *listCmd) statusColumnData(cInfo shared.ContainerInfo, cState *shared.ContainerState, cSnaps []shared.SnapshotInfo) string { return strings.ToUpper(cInfo.Status) } func (c *listCmd) IP4ColumnData(cInfo shared.ContainerInfo, cState *shared.ContainerState, cSnaps []shared.SnapshotInfo) string { if cInfo.IsActive() && cState.Network != nil { ipv4s := []string{} for netName, net := range cState.Network { if net.Type == "loopback" { continue } for _, addr := range net.Addresses { if shared.StringInSlice(addr.Scope, []string{"link", "local"}) { continue } if addr.Family == "inet" { ipv4s = append(ipv4s, fmt.Sprintf("%s (%s)", addr.Address, netName)) } } } return strings.Join(ipv4s, "\n") } else { return "" } } func (c *listCmd) IP6ColumnData(cInfo shared.ContainerInfo, cState *shared.ContainerState, cSnaps []shared.SnapshotInfo) string { if cInfo.IsActive() && cState.Network != nil { ipv6s := []string{} for netName, net := range cState.Network { if net.Type == "loopback" { continue } for _, addr := range net.Addresses { if shared.StringInSlice(addr.Scope, []string{"link", "local"}) { continue } if addr.Family == "inet6" { ipv6s = append(ipv6s, fmt.Sprintf("%s (%s)", addr.Address, netName)) } } } return strings.Join(ipv6s, "\n") } else { return "" } } func (c *listCmd) typeColumnData(cInfo shared.ContainerInfo, cState *shared.ContainerState, cSnaps []shared.SnapshotInfo) string { if cInfo.Ephemeral { return i18n.G("EPHEMERAL") } else { return i18n.G("PERSISTENT") } } func (c *listCmd) numberSnapshotsColumnData(cInfo shared.ContainerInfo, cState *shared.ContainerState, cSnaps []shared.SnapshotInfo) string { return fmt.Sprintf("%d", len(cSnaps)) } func (c *listCmd) PIDColumnData(cInfo shared.ContainerInfo, cState *shared.ContainerState, cSnaps []shared.SnapshotInfo) string { if cInfo.IsActive() { return fmt.Sprintf("%d", cState.Pid) } return "" } func (c *listCmd) ArchitectureColumnData(cInfo shared.ContainerInfo, cState *shared.ContainerState, cSnaps []shared.SnapshotInfo) string { return cInfo.Architecture } func (c *listCmd) ProfilesColumnData(cInfo shared.ContainerInfo, cState *shared.ContainerState, cSnaps []shared.SnapshotInfo) string { return strings.Join(cInfo.Profiles, "\n") } func (c *listCmd) CreatedColumnData(cInfo shared.ContainerInfo, cState *shared.ContainerState, cSnaps []shared.SnapshotInfo) string { layout := "2006/01/02 15:04 UTC" if cInfo.CreationDate.UTC().Unix() != 0 { return cInfo.CreationDate.UTC().Format(layout) } return "" } lxd-2.0.0/lxc/list_test.go000066400000000000000000000016641270277227600154520ustar00rootroot00000000000000package main import ( "testing" "github.com/lxc/lxd/shared" ) func TestDotPrefixMatch(t *testing.T) { list := listCmd{} pass := true pass = pass && list.dotPrefixMatch("s.privileged", "security.privileged") pass = pass && list.dotPrefixMatch("u.blah", "user.blah") if !pass { t.Error("failed prefix matching") } } func TestShouldShow(t *testing.T) { list := listCmd{} state := &shared.ContainerInfo{ Name: "foo", ExpandedConfig: map[string]string{ "security.privileged": "1", "user.blah": "abc", }, } if !list.shouldShow([]string{"u.blah=abc"}, state) { t.Error("u.blah=abc didn't match") } if !list.shouldShow([]string{"user.blah=abc"}, state) { t.Error("user.blah=abc didn't match") } if list.shouldShow([]string{"bar", "u.blah=abc"}, state) { t.Errorf("name filter didn't work") } if list.shouldShow([]string{"bar", "u.blah=other"}, state) { t.Errorf("value filter didn't work") } } lxd-2.0.0/lxc/main.go000066400000000000000000000157001270277227600143600ustar00rootroot00000000000000package main import ( "fmt" "net" "net/url" "os" "os/exec" "path" "strings" "syscall" "github.com/lxc/lxd" "github.com/lxc/lxd/shared" "github.com/lxc/lxd/shared/gnuflag" "github.com/lxc/lxd/shared/i18n" "github.com/lxc/lxd/shared/logging" ) var configPath string func main() { if err := run(); err != nil { // The action we take depends on the error we get. msg := fmt.Sprintf(i18n.G("error: %v"), err) switch t := err.(type) { case *url.Error: switch u := t.Err.(type) { case *net.OpError: if u.Op == "dial" && u.Net == "unix" { switch errno := u.Err.(type) { case syscall.Errno: switch errno { case syscall.ENOENT: msg = i18n.G("LXD socket not found; is LXD running?") case syscall.ECONNREFUSED: msg = i18n.G("Connection refused; is LXD running?") case syscall.EACCES: msg = i18n.G("Permisson denied, are you in the lxd group?") default: msg = fmt.Sprintf("%d %s", uintptr(errno), errno.Error()) } } } } } fmt.Fprintln(os.Stderr, fmt.Sprintf("%s", msg)) os.Exit(1) } } func run() error { verbose := gnuflag.Bool("verbose", false, i18n.G("Enables verbose mode.")) debug := gnuflag.Bool("debug", false, i18n.G("Enables debug mode.")) forceLocal := gnuflag.Bool("force-local", false, i18n.G("Force using the local unix socket.")) noAlias := gnuflag.Bool("no-alias", false, i18n.G("Ignore aliases when determining what command to run.")) configDir := "$HOME/.config/lxc" if os.Getenv("LXD_CONF") != "" { configDir = os.Getenv("LXD_CONF") } configPath = os.ExpandEnv(path.Join(configDir, "config.yml")) if len(os.Args) >= 3 && os.Args[1] == "config" && os.Args[2] == "profile" { fmt.Fprintf(os.Stderr, i18n.G("`lxc config profile` is deprecated, please use `lxc profile`")+"\n") os.Args = append(os.Args[:1], os.Args[2:]...) } if len(os.Args) >= 2 && (os.Args[1] == "-h" || os.Args[1] == "--help") { os.Args[1] = "help" } if len(os.Args) >= 2 && (os.Args[1] == "--all") { os.Args[1] = "help" os.Args = append(os.Args, "--all") } if len(os.Args) == 2 && os.Args[1] == "--version" { os.Args[1] = "version" } if len(os.Args) < 2 { commands["help"].run(nil, nil) os.Exit(1) } var config *lxd.Config var err error if *forceLocal { config = &lxd.DefaultConfig } else { config, err = lxd.LoadConfig(configPath) if err != nil { return err } } // This is quite impolite, but it seems gnuflag needs us to shift our // own exename out of the arguments before parsing them. However, this // is useful for execIfAlias, which wants to know exactly the command // line we received, and in some cases is called before this shift, and // in others after. So, let's save the original args. origArgs := os.Args name := os.Args[1] /* at this point we haven't parsed the args, so we have to look for * --no-alias by hand. */ if !shared.StringInSlice("--no-alias", origArgs) { execIfAliases(config, origArgs) } cmd, ok := commands[name] if !ok { commands["help"].run(nil, nil) fmt.Fprintf(os.Stderr, "\n"+i18n.G("error: unknown command: %s")+"\n", name) os.Exit(1) } cmd.flags() gnuflag.Usage = func() { fmt.Fprintf(os.Stderr, i18n.G("Usage: %s")+"\n\n"+i18n.G("Options:")+"\n\n", strings.TrimSpace(cmd.usage())) gnuflag.PrintDefaults() } os.Args = os.Args[1:] gnuflag.Parse(true) shared.Log, err = logging.GetLogger("", "", *verbose, *debug, nil) if err != nil { return err } certf := config.ConfigPath("client.crt") keyf := config.ConfigPath("client.key") if !*forceLocal && os.Args[0] != "help" && os.Args[0] != "version" && (!shared.PathExists(certf) || !shared.PathExists(keyf)) { fmt.Fprintf(os.Stderr, i18n.G("Generating a client certificate. This may take a minute...")+"\n") err = shared.FindOrGenCert(certf, keyf) if err != nil { return err } if shared.PathExists("/var/lib/lxd/") { fmt.Fprintf(os.Stderr, i18n.G("If this is your first time using LXD, you should also run: sudo lxd init")+"\n\n") } } err = cmd.run(config, gnuflag.Args()) if err == errArgs { /* If we got an error about invalid arguments, let's try to * expand this as an alias */ if !*noAlias { execIfAliases(config, origArgs) } fmt.Fprintf(os.Stderr, "%s\n\n"+i18n.G("error: %v")+"\n", cmd.usage(), err) os.Exit(1) } return err } type command interface { usage() string flags() showByDefault() bool run(config *lxd.Config, args []string) error } var commands = map[string]command{ "config": &configCmd{}, "copy": ©Cmd{}, "delete": &deleteCmd{}, "exec": &execCmd{}, "file": &fileCmd{}, "finger": &fingerCmd{}, "help": &helpCmd{}, "image": &imageCmd{}, "info": &infoCmd{}, "init": &initCmd{}, "launch": &launchCmd{}, "list": &listCmd{}, "monitor": &monitorCmd{}, "move": &moveCmd{}, "pause": &actionCmd{shared.Freeze, false, false, "pause", -1, false, false, false}, "profile": &profileCmd{}, "publish": &publishCmd{}, "remote": &remoteCmd{}, "restart": &actionCmd{shared.Restart, true, true, "restart", -1, false, false, false}, "restore": &restoreCmd{}, "snapshot": &snapshotCmd{}, "start": &actionCmd{shared.Start, false, true, "start", -1, false, false, false}, "stop": &actionCmd{shared.Stop, true, true, "stop", -1, false, false, false}, "version": &versionCmd{}, } var errArgs = fmt.Errorf(i18n.G("wrong number of subcommand arguments")) func expandAlias(config *lxd.Config, origArgs []string) ([]string, bool) { foundAlias := false aliasKey := []string{} aliasValue := []string{} for k, v := range config.Aliases { matches := false for i, key := range strings.Split(k, " ") { if len(origArgs) <= i+1 { break } if origArgs[i+1] == key { matches = true aliasKey = strings.Split(k, " ") aliasValue = strings.Split(v, " ") break } } if !matches { continue } foundAlias = true break } if !foundAlias { return []string{}, false } newArgs := []string{origArgs[0]} hasReplacedArgsVar := false for i, aliasArg := range aliasValue { if aliasArg == "@ARGS@" && len(origArgs) > i { newArgs = append(newArgs, origArgs[i+1:]...) hasReplacedArgsVar = true } else { newArgs = append(newArgs, aliasArg) } } if !hasReplacedArgsVar { /* add the rest of the arguments */ newArgs = append(newArgs, origArgs[len(aliasKey)+1:]...) } /* don't re-do aliases the next time; this allows us to have recursive * aliases, e.g. `lxc list` to `lxc list -c n` */ newArgs = append(newArgs[:2], append([]string{"--no-alias"}, newArgs[2:]...)...) return newArgs, true } func execIfAliases(config *lxd.Config, origArgs []string) { newArgs, expanded := expandAlias(config, origArgs) if !expanded { return } path, err := exec.LookPath(origArgs[0]) if err != nil { fmt.Fprintf(os.Stderr, i18n.G("processing aliases failed %s\n"), err) os.Exit(5) } ret := syscall.Exec(path, newArgs, syscall.Environ()) fmt.Fprintf(os.Stderr, i18n.G("processing aliases failed %s\n"), ret) os.Exit(5) } lxd-2.0.0/lxc/main_test.go000066400000000000000000000023731270277227600154210ustar00rootroot00000000000000package main import ( "testing" "github.com/lxc/lxd" ) type aliasTestcase struct { input []string expected []string } func slicesEqual(a, b []string) bool { if a == nil && b == nil { return true } if a == nil || b == nil { return false } if len(a) != len(b) { return false } for i := range a { if a[i] != b[i] { return false } } return true } func TestExpandAliases(t *testing.T) { aliases := map[string]string{ "tester 12": "list", "foo": "list @ARGS@ -c n", } testcases := []aliasTestcase{ aliasTestcase{ input: []string{"lxc", "list"}, expected: []string{"lxc", "list"}, }, aliasTestcase{ input: []string{"lxc", "tester", "12"}, expected: []string{"lxc", "list", "--no-alias"}, }, aliasTestcase{ input: []string{"lxc", "foo", "asdf"}, expected: []string{"lxc", "list", "--no-alias", "asdf", "-c", "n"}, }, } conf := &lxd.Config{Aliases: aliases} for _, tc := range testcases { result, expanded := expandAlias(conf, tc.input) if !expanded { if !slicesEqual(tc.input, tc.expected) { t.Errorf("didn't expand when expected to: %s", tc.input) } continue } if !slicesEqual(result, tc.expected) { t.Errorf("%s didn't match %s", result, tc.expected) } } } lxd-2.0.0/lxc/monitor.go000066400000000000000000000030351270277227600151210ustar00rootroot00000000000000package main import ( "fmt" "gopkg.in/yaml.v2" "github.com/lxc/lxd" "github.com/lxc/lxd/shared/gnuflag" "github.com/lxc/lxd/shared/i18n" ) type typeList []string func (f *typeList) String() string { return fmt.Sprint(*f) } func (f *typeList) Set(value string) error { if value == "" { return fmt.Errorf("Invalid type: %s", value) } if f == nil { *f = make(typeList, 1) } else { *f = append(*f, value) } return nil } type monitorCmd struct { typeArgs typeList } func (c *monitorCmd) showByDefault() bool { return false } func (c *monitorCmd) usage() string { return i18n.G( `Monitor activity on the LXD server. lxc monitor [remote:] [--type=TYPE...] Connects to the monitoring interface of the specified LXD server. By default will listen to all message types. Specific types to listen to can be specified with --type. Example: lxc monitor --type=logging`) } func (c *monitorCmd) flags() { gnuflag.Var(&c.typeArgs, "type", i18n.G("Event type to listen for")) } func (c *monitorCmd) run(config *lxd.Config, args []string) error { var remote string if len(args) > 1 { return errArgs } if len(args) == 0 { remote, _ = config.ParseRemoteAndContainer("") } else { remote, _ = config.ParseRemoteAndContainer(args[0]) } d, err := lxd.NewClient(config, remote) if err != nil { return err } handler := func(message interface{}) { render, err := yaml.Marshal(&message) if err != nil { fmt.Printf("error: %s\n", err) return } fmt.Printf("%s\n\n", render) } return d.Monitor(c.typeArgs, handler) } lxd-2.0.0/lxc/move.go000066400000000000000000000031741270277227600144040ustar00rootroot00000000000000package main import ( "github.com/lxc/lxd" "github.com/lxc/lxd/shared/i18n" ) type moveCmd struct { httpAddr string } func (c *moveCmd) showByDefault() bool { return true } func (c *moveCmd) usage() string { return i18n.G( `Move containers within or in between lxd instances. lxc move [remote:] [remote:] Move a container between two hosts, renaming it if destination name differs. lxc move Rename a local container. `) } func (c *moveCmd) flags() {} func (c *moveCmd) run(config *lxd.Config, args []string) error { if len(args) != 2 { return errArgs } sourceRemote, sourceName := config.ParseRemoteAndContainer(args[0]) destRemote, destName := config.ParseRemoteAndContainer(args[1]) // As an optimization, if the source an destination are the same, do // this via a simple rename. This only works for containers that aren't // running, containers that are running should be live migrated (of // course, this changing of hostname isn't supported right now, so this // simply won't work). if sourceRemote == destRemote { source, err := lxd.NewClient(config, sourceRemote) if err != nil { return err } rename, err := source.Rename(sourceName, destName) if err != nil { return err } return source.WaitForSuccess(rename.Operation) } cpy := copyCmd{} // A move is just a copy followed by a delete; however, we want to // keep the volatile entries around since we are moving the container. if err := cpy.copyContainer(config, args[0], args[1], true, -1); err != nil { return err } return commands["delete"].run(config, args[:1]) } lxd-2.0.0/lxc/profile.go000066400000000000000000000214101270277227600150670ustar00rootroot00000000000000package main import ( "fmt" "io/ioutil" "os" "strings" "syscall" "gopkg.in/yaml.v2" "github.com/lxc/lxd" "github.com/lxc/lxd/shared" "github.com/lxc/lxd/shared/i18n" "github.com/lxc/lxd/shared/termios" ) type profileCmd struct { httpAddr string } func (c *profileCmd) showByDefault() bool { return true } func (c *profileCmd) profileEditHelp() string { return i18n.G( `### This is a yaml representation of the profile. ### Any line starting with a '# will be ignored. ### ### A profile consists of a set of configuration items followed by a set of ### devices. ### ### An example would look like: ### name: onenic ### config: ### raw.lxc: lxc.aa_profile=unconfined ### devices: ### eth0: ### nictype: bridged ### parent: lxdbr0 ### type: nic ### ### Note that the name is shown but cannot be changed`) } func (c *profileCmd) usage() string { return i18n.G( `Manage configuration profiles. lxc profile list [filters] List available profiles. lxc profile show Show details of a profile. lxc profile create Create a profile. lxc profile copy Copy the profile to the specified remote. lxc profile get Get profile configuration. lxc profile set Set profile configuration. lxc profile delete Delete a profile. lxc profile edit Edit profile, either by launching external editor or reading STDIN. Example: lxc profile edit # launch editor cat profile.yml | lxc profile edit # read from profile.yml lxc profile apply Apply a comma-separated list of profiles to a container, in order. All profiles passed in this call (and only those) will be applied to the specified container. Example: lxc profile apply foo default,bar # Apply default and bar lxc profile apply foo default # Only default is active lxc profile apply '' # no profiles are applied anymore lxc profile apply bar,default # Apply default second now Devices: lxc profile device list List devices in the given profile. lxc profile device show Show full device details in the given profile. lxc profile device remove Remove a device from a profile. lxc profile device get <[remote:]profile> Get a device property. lxc profile device set <[remote:]profile> Set a device property. lxc profile device unset <[remote:]profile> Unset a device property. lxc profile device add [key=value]... Add a profile device, such as a disk or a nic, to the containers using the specified profile.`) } func (c *profileCmd) flags() {} func (c *profileCmd) run(config *lxd.Config, args []string) error { if len(args) < 1 { return errArgs } if args[0] == "list" { return c.doProfileList(config, args) } if len(args) < 2 { return errArgs } remote, profile := config.ParseRemoteAndContainer(args[1]) client, err := lxd.NewClient(config, remote) if err != nil { return err } switch args[0] { case "create": return c.doProfileCreate(client, profile) case "delete": return c.doProfileDelete(client, profile) case "device": return c.doProfileDevice(config, args) case "edit": return c.doProfileEdit(client, profile) case "apply": container := profile switch len(args) { case 2: profile = "" case 3: profile = args[2] default: return errArgs } return c.doProfileApply(client, container, profile) case "get": return c.doProfileGet(client, profile, args[2:]) case "set": return c.doProfileSet(client, profile, args[2:]) case "unset": return c.doProfileSet(client, profile, args[2:]) case "copy": return c.doProfileCopy(config, client, profile, args[2:]) case "show": return c.doProfileShow(client, profile) default: return errArgs } } func (c *profileCmd) doProfileCreate(client *lxd.Client, p string) error { err := client.ProfileCreate(p) if err == nil { fmt.Printf(i18n.G("Profile %s created")+"\n", p) } return err } func (c *profileCmd) doProfileEdit(client *lxd.Client, p string) error { // If stdin isn't a terminal, read text from it if !termios.IsTerminal(int(syscall.Stdin)) { contents, err := ioutil.ReadAll(os.Stdin) if err != nil { return err } newdata := shared.ProfileConfig{} err = yaml.Unmarshal(contents, &newdata) if err != nil { return err } return client.PutProfile(p, newdata) } // Extract the current value profile, err := client.ProfileConfig(p) if err != nil { return err } data, err := yaml.Marshal(&profile) if err != nil { return err } // Spawn the editor content, err := shared.TextEditor("", []byte(c.profileEditHelp()+"\n\n"+string(data))) if err != nil { return err } for { // Parse the text received from the editor newdata := shared.ProfileConfig{} err = yaml.Unmarshal(content, &newdata) if err == nil { err = client.PutProfile(p, newdata) } // Respawn the editor if err != nil { fmt.Fprintf(os.Stderr, i18n.G("Config parsing error: %s")+"\n", err) fmt.Println(i18n.G("Press enter to open the editor again")) _, err := os.Stdin.Read(make([]byte, 1)) if err != nil { return err } content, err = shared.TextEditor("", content) if err != nil { return err } continue } break } return nil } func (c *profileCmd) doProfileDelete(client *lxd.Client, p string) error { err := client.ProfileDelete(p) if err == nil { fmt.Printf(i18n.G("Profile %s deleted")+"\n", p) } return err } func (c *profileCmd) doProfileApply(client *lxd.Client, d string, p string) error { resp, err := client.ApplyProfile(d, p) if err != nil { return err } err = client.WaitForSuccess(resp.Operation) if err == nil { if p == "" { p = i18n.G("(none)") } fmt.Printf(i18n.G("Profile %s applied to %s")+"\n", p, d) } return err } func (c *profileCmd) doProfileShow(client *lxd.Client, p string) error { profile, err := client.ProfileConfig(p) if err != nil { return err } data, err := yaml.Marshal(&profile) fmt.Printf("%s", data) return nil } func (c *profileCmd) doProfileCopy(config *lxd.Config, client *lxd.Client, p string, args []string) error { if len(args) != 1 { return errArgs } remote, newname := config.ParseRemoteAndContainer(args[0]) if newname == "" { newname = p } dest, err := lxd.NewClient(config, remote) if err != nil { return err } return client.ProfileCopy(p, newname, dest) } func (c *profileCmd) doProfileDevice(config *lxd.Config, args []string) error { // device add b1 eth0 nic type=bridged // device list b1 // device remove b1 eth0 if len(args) < 3 { return errArgs } cfg := configCmd{} switch args[1] { case "add": return cfg.deviceAdd(config, "profile", args) case "remove": return cfg.deviceRm(config, "profile", args) case "list": return cfg.deviceList(config, "profile", args) case "show": return cfg.deviceShow(config, "profile", args) case "get": return cfg.deviceGet(config, "profile", args) case "set": return cfg.deviceSet(config, "profile", args) case "unset": return cfg.deviceUnset(config, "profile", args) default: return errArgs } } func (c *profileCmd) doProfileGet(client *lxd.Client, p string, args []string) error { // we shifted @args so so it should read "" if len(args) != 1 { return errArgs } resp, err := client.GetProfileConfig(p) if err != nil { return err } for k, v := range resp { if k == args[0] { fmt.Printf("%s\n", v) } } return nil } func (c *profileCmd) doProfileSet(client *lxd.Client, p string, args []string) error { // we shifted @args so so it should read " []" if len(args) < 1 { return errArgs } key := args[0] var value string if len(args) < 2 { value = "" } else { value = args[1] } if !termios.IsTerminal(int(syscall.Stdin)) && value == "-" { buf, err := ioutil.ReadAll(os.Stdin) if err != nil { return fmt.Errorf("Can't read from stdin: %s", err) } value = string(buf[:]) } err := client.SetProfileConfigItem(p, key, value) return err } func (c *profileCmd) doProfileList(config *lxd.Config, args []string) error { var remote string if len(args) > 1 { var name string remote, name = config.ParseRemoteAndContainer(args[1]) if name != "" { return fmt.Errorf(i18n.G("Cannot provide container name to list")) } } else { remote = config.DefaultRemote } client, err := lxd.NewClient(config, remote) if err != nil { return err } profiles, err := client.ListProfiles() if err != nil { return err } fmt.Printf("%s\n", strings.Join(profiles, "\n")) return nil } lxd-2.0.0/lxc/publish.go000066400000000000000000000070131270277227600151000ustar00rootroot00000000000000package main import ( "fmt" "strings" "github.com/lxc/lxd" "github.com/lxc/lxd/shared/gnuflag" "github.com/lxc/lxd/shared/i18n" "github.com/lxc/lxd/shared" ) type publishCmd struct { pAliases aliasList // aliasList defined in lxc/image.go makePublic bool Force bool } func (c *publishCmd) showByDefault() bool { return true } func (c *publishCmd) usage() string { return i18n.G( `Publish containers as images. lxc publish [remote:]container [remote:] [--alias=ALIAS]... [prop-key=prop-value]...`) } func (c *publishCmd) flags() { gnuflag.BoolVar(&c.makePublic, "public", false, i18n.G("Make the image public")) gnuflag.Var(&c.pAliases, "alias", i18n.G("New alias to define at target")) gnuflag.BoolVar(&c.Force, "force", false, i18n.G("Stop the container if currently running")) gnuflag.BoolVar(&c.Force, "f", false, i18n.G("Stop the container if currently running")) } func (c *publishCmd) run(config *lxd.Config, args []string) error { var cRemote string var cName string iName := "" iRemote := "" properties := map[string]string{} firstprop := 1 // first property is arg[2] if arg[1] is image remote, else arg[1] if len(args) < 1 { return errArgs } cRemote, cName = config.ParseRemoteAndContainer(args[0]) if len(args) >= 2 && !strings.Contains(args[1], "=") { firstprop = 2 iRemote, iName = config.ParseRemoteAndContainer(args[1]) } else { iRemote, iName = config.ParseRemoteAndContainer("") } if cName == "" { return fmt.Errorf(i18n.G("Container name is mandatory")) } if iName != "" { return fmt.Errorf(i18n.G("There is no \"image name\". Did you want an alias?")) } d, err := lxd.NewClient(config, iRemote) if err != nil { return err } s := d if cRemote != iRemote { s, err = lxd.NewClient(config, cRemote) if err != nil { return err } } if !shared.IsSnapshot(cName) { ct, err := s.ContainerInfo(cName) if err != nil { return err } wasRunning := ct.StatusCode != 0 && ct.StatusCode != shared.Stopped wasEphemeral := ct.Ephemeral if wasRunning { if !c.Force { return fmt.Errorf(i18n.G("The container is currently running. Use --force to have it stopped and restarted.")) } if ct.Ephemeral { ct.Ephemeral = false err := s.UpdateContainerConfig(cName, ct.Brief()) if err != nil { return err } } resp, err := s.Action(cName, shared.Stop, -1, true, false) if err != nil { return err } op, err := s.WaitFor(resp.Operation) if err != nil { return err } if op.StatusCode == shared.Failure { return fmt.Errorf(i18n.G("Stopping container failed!")) } defer s.Action(cName, shared.Start, -1, true, false) if wasEphemeral { ct.Ephemeral = true err := s.UpdateContainerConfig(cName, ct.Brief()) if err != nil { return err } } } } for i := firstprop; i < len(args); i++ { entry := strings.SplitN(args[i], "=", 2) if len(entry) < 2 { return errArgs } properties[entry[0]] = entry[1] } var fp string // Optimized local publish if cRemote == iRemote { fp, err = d.ImageFromContainer(cName, c.makePublic, c.pAliases, properties) if err != nil { return err } fmt.Printf(i18n.G("Container published with fingerprint: %s")+"\n", fp) return nil } fp, err = s.ImageFromContainer(cName, false, nil, properties) if err != nil { return err } defer s.DeleteImage(fp) err = s.CopyImage(fp, d, false, c.pAliases, c.makePublic, false, nil) if err != nil { return err } fmt.Printf(i18n.G("Container published with fingerprint: %s")+"\n", fp) return nil } lxd-2.0.0/lxc/remote.go000066400000000000000000000245571270277227600147410ustar00rootroot00000000000000package main import ( "crypto/sha256" "crypto/x509" "encoding/pem" "fmt" "net" "net/http" "net/url" "os" "path/filepath" "sort" "strings" "github.com/olekukonko/tablewriter" "golang.org/x/crypto/ssh/terminal" "github.com/lxc/lxd" "github.com/lxc/lxd/shared" "github.com/lxc/lxd/shared/gnuflag" "github.com/lxc/lxd/shared/i18n" ) type remoteCmd struct { httpAddr string acceptCert bool password string public bool protocol string } func (c *remoteCmd) showByDefault() bool { return true } func (c *remoteCmd) usage() string { return i18n.G( `Manage remote LXD servers. lxc remote add [--accept-certificate] [--password=PASSWORD] [--public] [--protocol=PROTOCOL] Add the remote at . lxc remote remove Remove the remote . lxc remote list List all remotes. lxc remote rename Rename remote to . lxc remote set-url Update 's url to . lxc remote set-default Set the default remote. lxc remote get-default Print the default remote.`) } func (c *remoteCmd) flags() { gnuflag.BoolVar(&c.acceptCert, "accept-certificate", false, i18n.G("Accept certificate")) gnuflag.StringVar(&c.password, "password", "", i18n.G("Remote admin password")) gnuflag.StringVar(&c.protocol, "protocol", "", i18n.G("Server protocol (lxd or simplestreams)")) gnuflag.BoolVar(&c.public, "public", false, i18n.G("Public image server")) } func getRemoteCertificate(address string) (*x509.Certificate, error) { // Setup a permissive TLS config tlsConfig, err := shared.GetTLSConfig("", "", nil) if err != nil { return nil, err } tlsConfig.InsecureSkipVerify = true tr := &http.Transport{ TLSClientConfig: tlsConfig, Dial: shared.RFC3493Dialer, Proxy: shared.ProxyFromEnvironment, } // Connect client := &http.Client{Transport: tr} resp, err := client.Get(address) if err != nil { return nil, err } // Retrieve the certificate if resp.TLS == nil || len(resp.TLS.PeerCertificates) == 0 { return nil, fmt.Errorf(i18n.G("Unable to read remote TLS certificate")) } return resp.TLS.PeerCertificates[0], nil } func (c *remoteCmd) addServer(config *lxd.Config, server string, addr string, acceptCert bool, password string, public bool, protocol string) error { var rScheme string var rHost string var rPort string // Setup the remotes list if config.Remotes == nil { config.Remotes = make(map[string]lxd.RemoteConfig) } /* Complex remote URL parsing */ remoteURL, err := url.Parse(addr) if err != nil { return err } // Fast track simplestreams if protocol == "simplestreams" { if remoteURL.Scheme != "https" { return fmt.Errorf(i18n.G("Only https URLs are supported for simplestreams")) } config.Remotes[server] = lxd.RemoteConfig{Addr: addr, Public: true, Protocol: protocol} return nil } // Fix broken URL parser if !strings.Contains(addr, "://") && remoteURL.Scheme != "" && remoteURL.Scheme != "unix" && remoteURL.Host == "" { remoteURL.Host = remoteURL.Scheme remoteURL.Scheme = "" } if remoteURL.Scheme != "" { if remoteURL.Scheme != "unix" && remoteURL.Scheme != "https" { return fmt.Errorf(i18n.G("Invalid URL scheme \"%s\" in \"%s\""), remoteURL.Scheme, addr) } rScheme = remoteURL.Scheme } else if addr[0] == '/' { rScheme = "unix" } else { if !shared.PathExists(addr) { rScheme = "https" } else { rScheme = "unix" } } if remoteURL.Host != "" { rHost = remoteURL.Host } else { rHost = addr } host, port, err := net.SplitHostPort(rHost) if err == nil { rHost = host rPort = port } else { rPort = shared.DefaultPort } if rScheme == "unix" { if addr[0:5] == "unix:" { if addr[0:7] == "unix://" { if len(addr) > 8 { rHost = addr[8:] } else { rHost = "" } } else { rHost = addr[6:] } } rPort = "" } if strings.Contains(rHost, ":") && !strings.HasPrefix(rHost, "[") { rHost = fmt.Sprintf("[%s]", rHost) } if rPort != "" { addr = rScheme + "://" + rHost + ":" + rPort } else { addr = rScheme + "://" + rHost } /* Actually add the remote */ config.Remotes[server] = lxd.RemoteConfig{Addr: addr, Protocol: protocol} remote := config.ParseRemote(server) d, err := lxd.NewClient(config, remote) if err != nil { return err } if len(addr) > 5 && addr[0:5] == "unix:" { // NewClient succeeded so there was a lxd there (we fingered // it) so just accept it return nil } var certificate *x509.Certificate /* Attempt to connect using the system root CA */ _, err = d.GetServerConfig() if err != nil { // Failed to connect using the system CA, so retrieve the remote certificate certificate, err = getRemoteCertificate(addr) if err != nil { return err } } if certificate != nil { if !acceptCert { digest := sha256.Sum256(certificate.Raw) fmt.Printf(i18n.G("Certificate fingerprint: %x")+"\n", digest) fmt.Printf(i18n.G("ok (y/n)?") + " ") line, err := shared.ReadStdin() if err != nil { return err } if len(line) < 1 || line[0] != 'y' && line[0] != 'Y' { return fmt.Errorf(i18n.G("Server certificate NACKed by user")) } } dnam := d.Config.ConfigPath("servercerts") err := os.MkdirAll(dnam, 0750) if err != nil { return fmt.Errorf(i18n.G("Could not create server cert dir")) } certf := fmt.Sprintf("%s/%s.crt", dnam, d.Name) certOut, err := os.Create(certf) if err != nil { return err } pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: certificate.Raw}) certOut.Close() // Setup a new connection, this time with the remote certificate d, err = lxd.NewClient(config, remote) if err != nil { return err } } if d.IsPublic() || public { config.Remotes[server] = lxd.RemoteConfig{Addr: addr, Public: true} if _, err := d.GetServerConfig(); err != nil { return err } return nil } if d.AmTrusted() { // server already has our cert, so we're done return nil } if password == "" { fmt.Printf(i18n.G("Admin password for %s: "), server) pwd, err := terminal.ReadPassword(0) if err != nil { /* We got an error, maybe this isn't a terminal, let's try to * read it as a file */ pwd, err = shared.ReadStdin() if err != nil { return err } } fmt.Println("") password = string(pwd) } err = d.AddMyCertToServer(password) if err != nil { return err } if !d.AmTrusted() { return fmt.Errorf(i18n.G("Server doesn't trust us after adding our cert")) } fmt.Println(i18n.G("Client certificate stored at server: "), server) return nil } func (c *remoteCmd) removeCertificate(config *lxd.Config, remote string) { certf := config.ServerCertPath(remote) shared.Debugf("Trying to remove %s", certf) os.Remove(certf) } func (c *remoteCmd) run(config *lxd.Config, args []string) error { if len(args) < 1 { return errArgs } switch args[0] { case "add": if len(args) < 3 { return errArgs } if rc, ok := config.Remotes[args[1]]; ok { return fmt.Errorf(i18n.G("remote %s exists as <%s>"), args[1], rc.Addr) } err := c.addServer(config, args[1], args[2], c.acceptCert, c.password, c.public, c.protocol) if err != nil { delete(config.Remotes, args[1]) c.removeCertificate(config, args[1]) return err } case "remove": if len(args) != 2 { return errArgs } rc, ok := config.Remotes[args[1]] if !ok { return fmt.Errorf(i18n.G("remote %s doesn't exist"), args[1]) } if rc.Static { return fmt.Errorf(i18n.G("remote %s is static and cannot be modified"), args[1]) } if config.DefaultRemote == args[1] { return fmt.Errorf(i18n.G("can't remove the default remote")) } delete(config.Remotes, args[1]) c.removeCertificate(config, args[1]) case "list": data := [][]string{} for name, rc := range config.Remotes { strPublic := i18n.G("NO") if rc.Public { strPublic = i18n.G("YES") } strStatic := i18n.G("NO") if rc.Static { strStatic = i18n.G("YES") } if rc.Protocol == "" { rc.Protocol = "lxd" } strName := name if name == config.DefaultRemote { strName = fmt.Sprintf("%s (%s)", name, i18n.G("default")) } data = append(data, []string{strName, rc.Addr, rc.Protocol, strPublic, strStatic}) } table := tablewriter.NewWriter(os.Stdout) table.SetAutoWrapText(false) table.SetAlignment(tablewriter.ALIGN_LEFT) table.SetRowLine(true) table.SetHeader([]string{ i18n.G("NAME"), i18n.G("URL"), i18n.G("PROTOCOL"), i18n.G("PUBLIC"), i18n.G("STATIC")}) sort.Sort(byName(data)) table.AppendBulk(data) table.Render() return nil case "rename": if len(args) != 3 { return errArgs } rc, ok := config.Remotes[args[1]] if !ok { return fmt.Errorf(i18n.G("remote %s doesn't exist"), args[1]) } if rc.Static { return fmt.Errorf(i18n.G("remote %s is static and cannot be modified"), args[1]) } if _, ok := config.Remotes[args[2]]; ok { return fmt.Errorf(i18n.G("remote %s already exists"), args[2]) } // Rename the certificate file oldPath := filepath.Join(config.ConfigPath("servercerts"), fmt.Sprintf("%s.crt", args[1])) newPath := filepath.Join(config.ConfigPath("servercerts"), fmt.Sprintf("%s.crt", args[2])) if shared.PathExists(oldPath) { err := os.Rename(oldPath, newPath) if err != nil { return err } } config.Remotes[args[2]] = rc delete(config.Remotes, args[1]) if config.DefaultRemote == args[1] { config.DefaultRemote = args[2] } case "set-url": if len(args) != 3 { return errArgs } rc, ok := config.Remotes[args[1]] if !ok { return fmt.Errorf(i18n.G("remote %s doesn't exist"), args[1]) } if rc.Static { return fmt.Errorf(i18n.G("remote %s is static and cannot be modified"), args[1]) } config.Remotes[args[1]] = lxd.RemoteConfig{Addr: args[2]} case "set-default": if len(args) != 2 { return errArgs } _, ok := config.Remotes[args[1]] if !ok { return fmt.Errorf(i18n.G("remote %s doesn't exist"), args[1]) } config.DefaultRemote = args[1] case "get-default": if len(args) != 1 { return errArgs } fmt.Println(config.DefaultRemote) return nil default: return errArgs } return lxd.SaveConfig(config, configPath) } lxd-2.0.0/lxc/restore.go000066400000000000000000000024431270277227600151170ustar00rootroot00000000000000package main import ( "fmt" "github.com/lxc/lxd" "github.com/lxc/lxd/shared" "github.com/lxc/lxd/shared/gnuflag" "github.com/lxc/lxd/shared/i18n" ) type restoreCmd struct { stateful bool } func (c *restoreCmd) showByDefault() bool { return true } func (c *restoreCmd) usage() string { return i18n.G( `Set the current state of a resource back to a snapshot. lxc restore [remote:] [--stateful] Restores a container from a snapshot (optionally with running state, see snapshot help for details). For example: lxc snapshot u1 snap0 # create the snapshot lxc restore u1 snap0 # restore the snapshot`) } func (c *restoreCmd) flags() { gnuflag.BoolVar(&c.stateful, "stateful", false, i18n.G("Whether or not to restore the container's running state from snapshot (if available)")) } func (c *restoreCmd) run(config *lxd.Config, args []string) error { if len(args) < 2 { return errArgs } var snapname = args[1] remote, name := config.ParseRemoteAndContainer(args[0]) d, err := lxd.NewClient(config, remote) if err != nil { return err } if !shared.IsSnapshot(snapname) { snapname = fmt.Sprintf("%s/%s", name, snapname) } resp, err := d.RestoreSnapshot(name, snapname, c.stateful) if err != nil { return err } return d.WaitForSuccess(resp.Operation) } lxd-2.0.0/lxc/snapshot.go000066400000000000000000000031301270277227600152650ustar00rootroot00000000000000package main import ( "fmt" "github.com/lxc/lxd" "github.com/lxc/lxd/shared" "github.com/lxc/lxd/shared/gnuflag" "github.com/lxc/lxd/shared/i18n" ) type snapshotCmd struct { stateful bool } func (c *snapshotCmd) showByDefault() bool { return true } func (c *snapshotCmd) usage() string { return i18n.G( `Create a read-only snapshot of a container. lxc snapshot [remote:] [--stateful] Creates a snapshot of the container (optionally with the container's memory state). When --stateful is used, LXD attempts to checkpoint the container's running state, including process memory state, TCP connections, etc. so that it can be restored (via lxc restore) at a later time (although some things, e.g. TCP connections after the TCP timeout window has expired, may not be restored successfully). Example: lxc snapshot u1 snap0`) } func (c *snapshotCmd) flags() { gnuflag.BoolVar(&c.stateful, "stateful", false, i18n.G("Whether or not to snapshot the container's running state")) } func (c *snapshotCmd) run(config *lxd.Config, args []string) error { if len(args) < 1 { return errArgs } var snapname string if len(args) < 2 { snapname = "" } else { snapname = args[1] } remote, name := config.ParseRemoteAndContainer(args[0]) d, err := lxd.NewClient(config, remote) if err != nil { return err } // we don't allow '/' in snapshot names if shared.IsSnapshot(snapname) { return fmt.Errorf(i18n.G("'/' not allowed in snapshot name")) } resp, err := d.Snapshot(name, snapname, c.stateful) if err != nil { return err } return d.WaitForSuccess(resp.Operation) } lxd-2.0.0/lxc/version.go000066400000000000000000000007731270277227600151250ustar00rootroot00000000000000package main import ( "fmt" "github.com/lxc/lxd" "github.com/lxc/lxd/shared" "github.com/lxc/lxd/shared/i18n" ) type versionCmd struct{} func (c *versionCmd) showByDefault() bool { return true } func (c *versionCmd) usage() string { return i18n.G( `Prints the version number of this client tool. lxc version`) } func (c *versionCmd) flags() { } func (c *versionCmd) run(_ *lxd.Config, args []string) error { if len(args) > 0 { return errArgs } fmt.Println(shared.Version) return nil } lxd-2.0.0/lxd-bridge/000077500000000000000000000000001270277227600143355ustar00rootroot00000000000000lxd-2.0.0/lxd-bridge/lxd-bridge000077500000000000000000000201641270277227600163070ustar00rootroot00000000000000#!/bin/sh config="/etc/default/lxd-bridge" varrun="/run/lxd-bridge/" varlib="/var/lib/lxd-bridge/" # lxdbr0 defaults to only setting up the standard IPv6 link-local network # to enable routable IPv4 and/or IPv6, please edit /etc/default/lxd # The values below are defaults USE_LXD_BRIDGE="true" LXD_BRIDGE="lxdbr0" LXD_CONFILE="" LXD_DOMAIN="" # IPv4 LXD_IPV4_ADDR="" LXD_IPV4_NETMASK="" LXD_IPV4_NETWORK="" LXD_IPV4_DHCP_RANGE="" LXD_IPV4_DHCP_MAX="" LXD_IPV4_NAT="false" # IPv6 LXD_IPV6_ADDR="" LXD_IPV6_MASK="" LXD_IPV6_NETWORK="" LXD_IPV6_NAT="false" LXD_IPV6_PROXY="true" [ ! -f "${config}" ] || . "${config}" use_iptables_lock="-w" iptables -w -L -n > /dev/null 2>&1 || use_iptables_lock="" HAS_IPV6=false [ -e "/proc/sys/net/ipv6/conf/default/disable_ipv6" ] && \ [ "$(cat /proc/sys/net/ipv6/conf/default/disable_ipv6)" = "0" ] && HAS_IPV6=true _netmask2cidr () { # Assumes there's no "255." after a non-255 byte in the mask local x=${1##*255.} set -- "0^^^128^192^224^240^248^252^254^" "$(( (${#1} - ${#x})*2 ))" "${x%%.*}" x=${1%%${3}*} echo $(( ${2} + (${#x}/4) )) } ifdown() { ip addr flush dev "${1}" ip link set dev "${1}" down } ifup() { [ "${HAS_IPV6}" = "true" ] && [ "${LXD_IPV6_PROXY}" = "true" ] && ip addr add fe80::1/64 dev "${1}" if [ -n "${LXD_IPV4_NETMASK}" ] && [ -n "${LXD_IPV4_ADDR}" ]; then MASK=$(_netmask2cidr ${LXD_IPV4_NETMASK}) CIDR_ADDR="${LXD_IPV4_ADDR}/${MASK}" ip addr add "${CIDR_ADDR}" dev "${1}" fi ip link set dev "${1}" up } start() { [ "x${USE_LXD_BRIDGE}" = "xtrue" ] || { exit 0; } [ ! -f "${varrun}/network_up" ] || { echo "lxd-bridge is already running"; exit 1; } if [ -d /sys/class/net/${LXD_BRIDGE} ]; then stop force 2>/dev/null || true fi FAILED=1 cleanup() { set +e if [ "${FAILED}" = "1" ]; then echo "Failed to setup lxd-bridge." >&2 stop force fi } trap cleanup EXIT HUP INT TERM set -e # set up the lxd network [ ! -d "/sys/class/net/${LXD_BRIDGE}" ] && ip link add dev "${LXD_BRIDGE}" type bridge if [ "${HAS_IPV6}" = "true" ]; then echo 0 > "/proc/sys/net/ipv6/conf/${LXD_BRIDGE}/autoconf" || true echo 0 > "/proc/sys/net/ipv6/conf/${LXD_BRIDGE}/accept_dad" || true fi # if we are run from systemd on a system with selinux enabled, # the mkdir will create /run/lxd as init_var_run_t which dnsmasq # can't write its pid into, so we restorecon it (to var_run_t) if [ ! -d "${varrun}" ]; then mkdir -p "${varrun}" if which restorecon >/dev/null 2>&1; then restorecon "${varrun}" fi fi if [ ! -d "${varlib}" ]; then mkdir -p "${varlib}" if which restorecon >/dev/null 2>&1; then restorecon "${varlib}" fi fi ifup "${LXD_BRIDGE}" "${LXD_IPV4_ADDR}" "${LXD_IPV4_NETMASK}" LXD_IPV4_ARG="" if [ -n "${LXD_IPV4_ADDR}" ] && [ -n "${LXD_IPV4_NETMASK}" ] && [ -n "${LXD_IPV4_NETWORK}" ]; then echo 1 > /proc/sys/net/ipv4/ip_forward if [ "${LXD_IPV4_NAT}" = "true" ]; then iptables "${use_iptables_lock}" -t nat -A POSTROUTING -s "${LXD_IPV4_NETWORK}" ! -d "${LXD_IPV4_NETWORK}" -j MASQUERADE fi LXD_IPV4_ARG="--listen-address ${LXD_IPV4_ADDR} --dhcp-range ${LXD_IPV4_DHCP_RANGE} --dhcp-lease-max=${LXD_IPV4_DHCP_MAX}" fi LXD_IPV6_ARG="" if [ "${HAS_IPV6}" = "true" ] && [ -n "${LXD_IPV6_ADDR}" ] && [ -n "${LXD_IPV6_MASK}" ] && [ -n "${LXD_IPV6_NETWORK}" ]; then # IPv6 sysctls don't respect the "all" path... for interface in /proc/sys/net/ipv6/conf/*; do echo 2 > "${interface}/accept_ra" done for interface in /proc/sys/net/ipv6/conf/*; do echo 1 > "${interface}/forwarding" done ip -6 addr add dev "${LXD_BRIDGE}" "${LXD_IPV6_ADDR}/${LXD_IPV6_MASK}" if [ "${LXD_IPV6_NAT}" = "true" ]; then ip6tables "${use_iptables_lock}" -t nat -A POSTROUTING -s "${LXD_IPV6_NETWORK}" ! -d "${LXD_IPV6_NETWORK}" -j MASQUERADE fi LXD_IPV6_ARG="--dhcp-range=${LXD_IPV6_ADDR},ra-only --listen-address ${LXD_IPV6_ADDR}" fi iptables "${use_iptables_lock}" -I INPUT -i "${LXD_BRIDGE}" -p udp --dport 67 -j ACCEPT iptables "${use_iptables_lock}" -I INPUT -i "${LXD_BRIDGE}" -p tcp --dport 67 -j ACCEPT iptables "${use_iptables_lock}" -I INPUT -i "${LXD_BRIDGE}" -p udp --dport 53 -j ACCEPT iptables "${use_iptables_lock}" -I INPUT -i "${LXD_BRIDGE}" -p tcp --dport 53 -j ACCEPT iptables "${use_iptables_lock}" -I FORWARD -i "${LXD_BRIDGE}" -j ACCEPT iptables "${use_iptables_lock}" -I FORWARD -o "${LXD_BRIDGE}" -j ACCEPT iptables "${use_iptables_lock}" -t mangle -A POSTROUTING -o "${LXD_BRIDGE}" -p udp -m udp --dport 68 -j CHECKSUM --checksum-fill LXD_DOMAIN_ARG="" if [ -n "${LXD_DOMAIN}" ]; then LXD_DOMAIN_ARG="-s ${LXD_DOMAIN} -S /${LXD_DOMAIN}/" fi LXD_CONFILE_ARG="" if [ -n "${LXD_CONFILE}" ]; then LXD_CONFILE_ARG="--conf-file=${LXD_CONFILE}" fi # https://lists.linuxcontainers.org/pipermail/lxc-devel/2014-October/010561.html for DNSMASQ_USER in lxd dnsmasq nobody do if getent passwd "${DNSMASQ_USER}" >/dev/null; then break fi done if [ -n "${LXD_IPV4_ADDR}" ] || [ -n "${LXD_IPV6_ADDR}" ]; then # shellcheck disable=SC2086 dnsmasq ${LXD_CONFILE_ARG} ${LXD_DOMAIN_ARG} -u "${DNSMASQ_USER}" --strict-order --bind-interfaces --pid-file="${varrun}/dnsmasq.pid" --dhcp-no-override --except-interface=lo --interface="${LXD_BRIDGE}" --dhcp-leasefile="${varlib}/dnsmasq.${LXD_BRIDGE}.leases" --dhcp-authoritative ${LXD_IPV4_ARG} ${LXD_IPV6_ARG} || cleanup fi if [ "${HAS_IPV6}" = "true" ] && [ "${LXD_IPV6_PROXY}" = "true" ]; then PATH="${PATH}:$(dirname "${0}")" lxd-bridge-proxy --addr="[fe80::1%${LXD_BRIDGE}]:13128" & PID=$! echo "${PID}" > "${varrun}/proxy.pid" fi touch "${varrun}/network_up" FAILED=0 } stop() { [ -f "${varrun}/network_up" ] || [ "${1}" = "force" ] || { echo "lxd-bridge isn't running"; exit 1; } if [ -d /sys/class/net/${LXD_BRIDGE} ]; then ifdown ${LXD_BRIDGE} iptables ${use_iptables_lock} -D INPUT -i ${LXD_BRIDGE} -p udp --dport 67 -j ACCEPT iptables ${use_iptables_lock} -D INPUT -i ${LXD_BRIDGE} -p tcp --dport 67 -j ACCEPT iptables ${use_iptables_lock} -D INPUT -i ${LXD_BRIDGE} -p udp --dport 53 -j ACCEPT iptables ${use_iptables_lock} -D INPUT -i ${LXD_BRIDGE} -p tcp --dport 53 -j ACCEPT iptables ${use_iptables_lock} -D FORWARD -i ${LXD_BRIDGE} -j ACCEPT iptables ${use_iptables_lock} -D FORWARD -o ${LXD_BRIDGE} -j ACCEPT iptables ${use_iptables_lock} -t mangle -D POSTROUTING -o ${LXD_BRIDGE} -p udp -m udp --dport 68 -j CHECKSUM --checksum-fill if [ -n "${LXD_IPV4_NETWORK}" ] && [ "${LXD_IPV4_NAT}" = "true" ]; then iptables ${use_iptables_lock} -t nat -D POSTROUTING -s ${LXD_IPV4_NETWORK} ! -d ${LXD_IPV4_NETWORK} -j MASQUERADE fi if [ "${HAS_IPV6}" = "true" ] && [ -n "${LXD_IPV6_NETWORK}" ] && [ "${LXD_IPV6_NAT}" = "true" ]; then ip6tables ${use_iptables_lock} -t nat -D POSTROUTING -s ${LXD_IPV6_NETWORK} ! -d ${LXD_IPV6_NETWORK} -j MASQUERADE fi if [ -e "${varrun}/dnsmasq.pid" ]; then pid=$(cat "${varrun}/dnsmasq.pid" 2>/dev/null) && kill -9 "${pid}" rm -f "${varrun}/dnsmasq.pid" fi if [ -e "${varrun}/proxy.pid" ]; then pid=$(cat "${varrun}/proxy.pid" 2>/dev/null) && kill -9 "${pid}" rm -f "${varrun}/proxy.pid" fi # if ${LXD_BRIDGE} has attached interfaces, don't destroy the bridge ls /sys/class/net/${LXD_BRIDGE}/brif/* > /dev/null 2>&1 || ip link delete "${LXD_BRIDGE}" fi rm -f "${varrun}/network_up" } # See how we were called. case "${1}" in start) start ;; stop) stop ;; restart|reload|force-reload) ${0} stop ${0} start ;; *) echo "Usage: ${0} {start|stop|restart|reload|force-reload}" exit 2 esac exit $? lxd-2.0.0/lxd-bridge/lxd-bridge-proxy/000077500000000000000000000000001270277227600175355ustar00rootroot00000000000000lxd-2.0.0/lxd-bridge/lxd-bridge-proxy/main.go000066400000000000000000000007071270277227600210140ustar00rootroot00000000000000package main import ( "flag" "fmt" "log" "net/http" "net/http/httputil" ) func NewProxy() *httputil.ReverseProxy { director := func(req *http.Request) { if req.Method == "CONNECT" { fmt.Printf("CONNECT: %s\n", req.Host) } } return &httputil.ReverseProxy{Director: director} } func main() { addr := flag.String("addr", "[fe80::1%lxdbr0]:13128", "proxy listen address") flag.Parse() log.Fatal(http.ListenAndServe(*addr, NewProxy())) } lxd-2.0.0/lxd/000077500000000000000000000000001270277227600131035ustar00rootroot00000000000000lxd-2.0.0/lxd/api_1.0.go000066400000000000000000000131451270277227600145650ustar00rootroot00000000000000package main import ( "encoding/pem" "fmt" "net/http" "os" "syscall" "gopkg.in/lxc/go-lxc.v2" "github.com/lxc/lxd/shared" ) var api10 = []Command{ containersCmd, containerCmd, containerStateCmd, containerFileCmd, containerLogsCmd, containerLogCmd, containerSnapshotsCmd, containerSnapshotCmd, containerExecCmd, aliasCmd, aliasesCmd, eventsCmd, imageCmd, imagesCmd, imagesExportCmd, imagesSecretCmd, operationsCmd, operationCmd, operationWait, operationWebsocket, networksCmd, networkCmd, api10Cmd, certificatesCmd, certificateFingerprintCmd, profilesCmd, profileCmd, } func api10Get(d *Daemon, r *http.Request) Response { body := shared.Jmap{ "api_extensions": []string{}, "api_status": "stable", "api_version": shared.APIVersion, } if d.isTrustedClient(r) { body["auth"] = "trusted" /* * Based on: https://groups.google.com/forum/#!topic/golang-nuts/Jel8Bb-YwX8 * there is really no better way to do this, which is * unfortunate. Also, we ditch the more accepted CharsToString * version in that thread, since it doesn't seem as portable, * viz. github issue #206. */ uname := syscall.Utsname{} if err := syscall.Uname(&uname); err != nil { return InternalError(err) } kernel := "" for _, c := range uname.Sysname { if c == 0 { break } kernel += string(byte(c)) } kernelVersion := "" for _, c := range uname.Release { if c == 0 { break } kernelVersion += string(byte(c)) } kernelArchitecture := "" for _, c := range uname.Machine { if c == 0 { break } kernelArchitecture += string(byte(c)) } addresses, err := d.ListenAddresses() if err != nil { return InternalError(err) } var certificate string if len(d.tlsConfig.Certificates) != 0 { certificate = string(pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: d.tlsConfig.Certificates[0].Certificate[0]})) } architectures := []string{} for _, architecture := range d.architectures { architectureName, err := shared.ArchitectureName(architecture) if err != nil { return InternalError(err) } architectures = append(architectures, architectureName) } env := shared.Jmap{ "addresses": addresses, "architectures": architectures, "certificate": certificate, "driver": "lxc", "driver_version": lxc.Version(), "kernel": kernel, "kernel_architecture": kernelArchitecture, "kernel_version": kernelVersion, "storage": d.Storage.GetStorageTypeName(), "storage_version": d.Storage.GetStorageTypeVersion(), "server": "lxd", "server_pid": os.Getpid(), "server_version": shared.Version} body["environment"] = env body["public"] = false serverConfig, err := d.ConfigValuesGet() if err != nil { return InternalError(err) } config := shared.Jmap{} for key, value := range serverConfig { if key == "core.trust_password" { config[key] = true } else { config[key] = value } } body["config"] = config } else { body["auth"] = "untrusted" body["public"] = false } return SyncResponse(true, body) } type apiPut struct { Config shared.Jmap `json:"config"` } func api10Put(d *Daemon, r *http.Request) Response { oldConfig, err := dbConfigValuesGet(d.db) if err != nil { return InternalError(err) } req := apiPut{} if err := shared.ReadToJSON(r.Body, &req); err != nil { return BadRequest(err) } // Diff the configs changedConfig := map[string]interface{}{} for key, value := range oldConfig { if req.Config[key] != value { changedConfig[key] = req.Config[key] } } for key, value := range req.Config { if oldConfig[key] != value { changedConfig[key] = req.Config[key] } } for key, value := range changedConfig { if value == nil { value = "" } if !d.ConfigKeyIsValid(key) { return BadRequest(fmt.Errorf("Bad server config key: '%s'", key)) } if key == "core.trust_password" { if value == true { continue } err := d.PasswordSet(value.(string)) if err != nil { return InternalError(err) } } else if key == "storage.lvm_vg_name" { err := storageLVMSetVolumeGroupNameConfig(d, value.(string)) if err != nil { return InternalError(err) } if err = d.SetupStorageDriver(); err != nil { return InternalError(err) } } else if key == "storage.lvm_thinpool_name" { err := storageLVMSetThinPoolNameConfig(d, value.(string)) if err != nil { return InternalError(err) } } else if key == "storage.zfs_pool_name" { err := storageZFSSetPoolNameConfig(d, value.(string)) if err != nil { return InternalError(err) } if err = d.SetupStorageDriver(); err != nil { return InternalError(err) } } else if key == "core.https_address" { old_address, err := d.ConfigValueGet("core.https_address") if err != nil { return InternalError(err) } err = d.UpdateHTTPsPort(old_address, value.(string)) if err != nil { return InternalError(err) } err = d.ConfigValueSet(key, value.(string)) if err != nil { return InternalError(err) } } else if key == "core.proxy_https" || key == "core.proxy_http" || key == "core.proxy_ignore_hosts" { err = d.ConfigValueSet(key, value.(string)) if err != nil { return InternalError(err) } d.updateProxy() } else { err := d.ConfigValueSet(key, value.(string)) if err != nil { return InternalError(err) } if key == "images.remote_cache_expiry" { d.pruneChan <- true } } } return EmptySyncResponse } var api10Cmd = Command{name: "", untrustedGet: true, get: api10Get, put: api10Put} lxd-2.0.0/lxd/api_internal.go000066400000000000000000000034601270277227600161020ustar00rootroot00000000000000package main import ( "fmt" "net/http" "strconv" "github.com/gorilla/mux" ) var apiInternal = []Command{ internalReadyCmd, internalShutdownCmd, internalContainerOnStartCmd, internalContainerOnStopCmd, } func internalReady(d *Daemon, r *http.Request) Response { if !d.SetupMode { return InternalError(fmt.Errorf("The server isn't currently in setup mode")) } err := d.Ready() if err != nil { return InternalError(err) } d.SetupMode = false return EmptySyncResponse } func internalWaitReady(d *Daemon, r *http.Request) Response { <-d.readyChan return EmptySyncResponse } func internalShutdown(d *Daemon, r *http.Request) Response { d.shutdownChan <- true return EmptySyncResponse } func internalContainerOnStart(d *Daemon, r *http.Request) Response { id, err := strconv.Atoi(mux.Vars(r)["id"]) if err != nil { return SmartError(err) } c, err := containerLoadById(d, id) if err != nil { return SmartError(err) } err = c.OnStart() if err != nil { return SmartError(err) } return EmptySyncResponse } func internalContainerOnStop(d *Daemon, r *http.Request) Response { id, err := strconv.Atoi(mux.Vars(r)["id"]) if err != nil { return SmartError(err) } target := r.FormValue("target") if target == "" { target = "unknown" } c, err := containerLoadById(d, id) if err != nil { return SmartError(err) } err = c.OnStop(target) if err != nil { return SmartError(err) } return EmptySyncResponse } var internalShutdownCmd = Command{name: "shutdown", put: internalShutdown} var internalReadyCmd = Command{name: "ready", put: internalReady, get: internalWaitReady} var internalContainerOnStartCmd = Command{name: "containers/{id}/onstart", get: internalContainerOnStart} var internalContainerOnStopCmd = Command{name: "containers/{id}/onstop", get: internalContainerOnStop} lxd-2.0.0/lxd/apparmor.go000066400000000000000000000120421270277227600152520ustar00rootroot00000000000000package main import ( "crypto/sha256" "fmt" "io" "io/ioutil" "os" "os/exec" "path" "strings" "github.com/lxc/lxd/shared" log "gopkg.in/inconshreveable/log15.v2" ) const ( APPARMOR_CMD_LOAD = "r" APPARMOR_CMD_UNLOAD = "R" APPARMOR_CMD_PARSE = "Q" ) var aaPath = shared.VarPath("security", "apparmor") const NESTING_AA_PROFILE = ` pivot_root, mount /var/lib/lxd/shmounts/ -> /var/lib/lxd/shmounts/, mount none -> /var/lib/lxd/shmounts/, mount fstype=proc -> /usr/lib/*/lxc/**, mount fstype=sysfs -> /usr/lib/*/lxc/**, mount options=(rw,bind), mount options=(rw,rbind), deny /dev/.lxd/proc/** rw, deny /dev/.lxd/sys/** rw, mount options=(rw,make-rshared), # there doesn't seem to be a way to ask for: # mount options=(ro,nosuid,nodev,noexec,remount,bind), # as we always get mount to $cdir/proc/sys with those flags denied # So allow all mounts until that is straightened out: mount, mount options=bind /var/lib/lxd/shmounts/** -> /var/lib/lxd/**, # lxc-container-default-with-nesting also inherited these # from start-container, and seems to need them. ptrace, signal, ` const DEFAULT_AA_PROFILE = ` #include profile "%s" flags=(attach_disconnected,mediate_deleted) { #include # Special exception for cgroup namespaces %s # user input raw.apparmor below here %s # nesting support goes here if needed %s change_profile -> "%s", }` func AAProfileFull(c container) string { lxddir := shared.VarPath("") if len(c.Name())+len(lxddir)+7 >= 253 { hash := sha256.New() io.WriteString(hash, lxddir) lxddir = fmt.Sprintf("%x", hash.Sum(nil)) } return fmt.Sprintf("lxd-%s_<%s>", c.Name(), lxddir) } func AAProfileShort(c container) string { return fmt.Sprintf("lxd-%s", c.Name()) } func AAProfileCgns() string { if shared.PathExists("/proc/self/ns/cgroup") { return " mount fstype=cgroup -> /sys/fs/cgroup/**," } return "" } // getProfileContent generates the apparmor profile template from the given // container. This includes the stock lxc includes as well as stuff from // raw.apparmor. func getAAProfileContent(c container) string { rawApparmor, ok := c.ExpandedConfig()["raw.apparmor"] if !ok { rawApparmor = "" } nesting := "" if c.IsNesting() { nesting = NESTING_AA_PROFILE } return fmt.Sprintf(DEFAULT_AA_PROFILE, AAProfileFull(c), AAProfileCgns(), rawApparmor, nesting, AAProfileFull(c)) } func runApparmor(command string, c container) error { if !aaAvailable { return nil } cmd := exec.Command("apparmor_parser", []string{ fmt.Sprintf("-%sWL", command), path.Join(aaPath, "cache"), path.Join(aaPath, "profiles", AAProfileShort(c)), }...) output, err := cmd.CombinedOutput() if err != nil { shared.Log.Error("Running apparmor", log.Ctx{"action": command, "output": string(output), "err": err}) } return err } // Ensure that the container's policy is loaded into the kernel so the // container can boot. func AALoadProfile(c container) error { if !aaAdmin { return nil } /* In order to avoid forcing a profile parse (potentially slow) on * every container start, let's use apparmor's binary policy cache, * which checks mtime of the files to figure out if the policy needs to * be regenerated. * * Since it uses mtimes, we shouldn't just always write out our local * apparmor template; instead we should check to see whether the * template is the same as ours. If it isn't we should write our * version out so that the new changes are reflected and we definitely * force a recompile. */ profile := path.Join(aaPath, "profiles", AAProfileShort(c)) content, err := ioutil.ReadFile(profile) if err != nil && !os.IsNotExist(err) { return err } updated := getAAProfileContent(c) if string(content) != string(updated) { if err := os.MkdirAll(path.Join(aaPath, "cache"), 0700); err != nil { return err } if err := os.MkdirAll(path.Join(aaPath, "profiles"), 0700); err != nil { return err } if err := ioutil.WriteFile(profile, []byte(updated), 0600); err != nil { return err } } return runApparmor(APPARMOR_CMD_LOAD, c) } // Ensure that the container's policy is unloaded to free kernel memory. This // does not delete the policy from disk or cache. func AAUnloadProfile(c container) error { if !aaAdmin { return nil } return runApparmor(APPARMOR_CMD_UNLOAD, c) } // Parse the profile without loading it into the kernel. func AAParseProfile(c container) error { if !aaAvailable { } return runApparmor(APPARMOR_CMD_PARSE, c) } // Delete the policy from cache/disk. func AADeleteProfile(c container) { if !aaAdmin { return } /* It's ok if these deletes fail: if the container was never started, * we'll have never written a profile or cached it. */ os.Remove(path.Join(aaPath, "cache", AAProfileShort(c))) os.Remove(path.Join(aaPath, "profiles", AAProfileShort(c))) } // What's current apparmor profile func aaProfile() string { contents, err := ioutil.ReadFile("/proc/self/attr/current") if err == nil { return strings.TrimSpace(string(contents)) } return "" } lxd-2.0.0/lxd/certificates.go000066400000000000000000000113421270277227600161000ustar00rootroot00000000000000package main import ( "crypto/sha256" "crypto/x509" "encoding/base64" "encoding/pem" "fmt" "net" "net/http" "github.com/gorilla/mux" "github.com/lxc/lxd/shared" ) func certGenerateFingerprint(cert *x509.Certificate) string { return fmt.Sprintf("%x", sha256.Sum256(cert.Raw)) } func certificatesGet(d *Daemon, r *http.Request) Response { recursion := d.isRecursionRequest(r) if recursion { certResponses := []shared.CertInfo{} baseCerts, err := dbCertsGet(d.db) if err != nil { return SmartError(err) } for _, baseCert := range baseCerts { resp := shared.CertInfo{} resp.Fingerprint = baseCert.Fingerprint resp.Certificate = baseCert.Certificate if baseCert.Type == 1 { resp.Type = "client" } else { resp.Type = "unknown" } certResponses = append(certResponses, resp) } return SyncResponse(true, certResponses) } body := []string{} for _, cert := range d.clientCerts { fingerprint := fmt.Sprintf("/%s/certificates/%s", shared.APIVersion, certGenerateFingerprint(&cert)) body = append(body, fingerprint) } return SyncResponse(true, body) } type certificatesPostBody struct { Type string `json:"type"` Certificate string `json:"certificate"` Name string `json:"name"` Password string `json:"password"` } func readSavedClientCAList(d *Daemon) { d.clientCerts = []x509.Certificate{} dbCerts, err := dbCertsGet(d.db) if err != nil { shared.Logf("Error reading certificates from database: %s", err) return } for _, dbCert := range dbCerts { certBlock, _ := pem.Decode([]byte(dbCert.Certificate)) cert, err := x509.ParseCertificate(certBlock.Bytes) if err != nil { shared.Logf("Error reading certificate for %s: %s", dbCert.Name, err) continue } d.clientCerts = append(d.clientCerts, *cert) } } func saveCert(d *Daemon, host string, cert *x509.Certificate) error { baseCert := new(dbCertInfo) baseCert.Fingerprint = certGenerateFingerprint(cert) baseCert.Type = 1 baseCert.Name = host baseCert.Certificate = string( pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: cert.Raw}), ) return dbCertSave(d.db, baseCert) } func certificatesPost(d *Daemon, r *http.Request) Response { req := certificatesPostBody{} if err := shared.ReadToJSON(r.Body, &req); err != nil { return BadRequest(err) } if req.Type != "client" { return BadRequest(fmt.Errorf("Unknown request type %s", req.Type)) } var cert *x509.Certificate var name string if req.Certificate != "" { data, err := base64.StdEncoding.DecodeString(req.Certificate) if err != nil { return BadRequest(err) } cert, err = x509.ParseCertificate(data) if err != nil { return BadRequest(err) } name = req.Name } else if r.TLS != nil { if len(r.TLS.PeerCertificates) < 1 { return BadRequest(fmt.Errorf("No client certificate provided")) } cert = r.TLS.PeerCertificates[len(r.TLS.PeerCertificates)-1] remoteHost, _, err := net.SplitHostPort(r.RemoteAddr) if err != nil { return InternalError(err) } name = remoteHost } else { return BadRequest(fmt.Errorf("Can't use TLS data on non-TLS link")) } fingerprint := certGenerateFingerprint(cert) for _, existingCert := range d.clientCerts { if fingerprint == certGenerateFingerprint(&existingCert) { return EmptySyncResponse } } if !d.isTrustedClient(r) && !d.PasswordCheck(req.Password) { return Forbidden } err := saveCert(d, name, cert) if err != nil { return SmartError(err) } d.clientCerts = append(d.clientCerts, *cert) return EmptySyncResponse } var certificatesCmd = Command{ "certificates", false, true, certificatesGet, nil, certificatesPost, nil, } func certificateFingerprintGet(d *Daemon, r *http.Request) Response { fingerprint := mux.Vars(r)["fingerprint"] cert, err := doCertificateGet(d, fingerprint) if err != nil { return SmartError(err) } return SyncResponse(true, cert) } func doCertificateGet(d *Daemon, fingerprint string) (shared.CertInfo, error) { resp := shared.CertInfo{} dbCertInfo, err := dbCertGet(d.db, fingerprint) if err != nil { return resp, err } resp.Fingerprint = dbCertInfo.Fingerprint resp.Certificate = dbCertInfo.Certificate if dbCertInfo.Type == 1 { resp.Type = "client" } else { resp.Type = "unknown" } return resp, nil } func certificateFingerprintDelete(d *Daemon, r *http.Request) Response { fingerprint := mux.Vars(r)["fingerprint"] certInfo, err := dbCertGet(d.db, fingerprint) if err != nil { return NotFound } err = dbCertDelete(d.db, certInfo.Fingerprint) if err != nil { return SmartError(err) } readSavedClientCAList(d) return EmptySyncResponse } var certificateFingerprintCmd = Command{ "certificates/{fingerprint}", false, false, certificateFingerprintGet, nil, nil, certificateFingerprintDelete, } lxd-2.0.0/lxd/cgroup.go000066400000000000000000000022311270277227600147270ustar00rootroot00000000000000package main import ( "bufio" "io/ioutil" "os" "path" "strings" ) func getInitCgroupPath(controller string) string { f, err := os.Open("/proc/1/cgroup") if err != nil { return "/" } defer f.Close() scan := bufio.NewScanner(f) for scan.Scan() { line := scan.Text() fields := strings.Split(line, ":") if len(fields) != 3 { return "/" } if fields[2] != controller { continue } initPath := string(fields[3]) // ignore trailing /init.scope if it is there dir, file := path.Split(initPath) if file == "init.scope" { return dir } else { return initPath } } return "/" } func cGroupGet(controller, cgroup, file string) (string, error) { initPath := getInitCgroupPath(controller) path := path.Join("/sys/fs/cgroup", controller, initPath, cgroup, file) contents, err := ioutil.ReadFile(path) if err != nil { return "", err } return strings.Trim(string(contents), "\n"), nil } func cGroupSet(controller, cgroup, file string, value string) error { initPath := getInitCgroupPath(controller) path := path.Join("/sys/fs/cgroup", controller, initPath, cgroup, file) return ioutil.WriteFile(path, []byte(value), 0755) } lxd-2.0.0/lxd/container.go000066400000000000000000000344211270277227600154200ustar00rootroot00000000000000package main import ( "fmt" "io" "os" "strings" "time" "gopkg.in/lxc/go-lxc.v2" "github.com/lxc/lxd/shared" log "gopkg.in/inconshreveable/log15.v2" ) // Helper functions func containerPath(name string, isSnapshot bool) string { if isSnapshot { return shared.VarPath("snapshots", name) } return shared.VarPath("containers", name) } func containerValidName(name string) error { if strings.Contains(name, shared.SnapshotDelimiter) { return fmt.Errorf( "The character '%s' is reserved for snapshots.", shared.SnapshotDelimiter) } if !shared.ValidHostname(name) { return fmt.Errorf("Container name isn't a valid hostname.") } return nil } func containerValidConfigKey(k string) bool { switch k { case "boot.autostart": return true case "boot.autostart.delay": return true case "boot.autostart.priority": return true case "limits.cpu": return true case "limits.cpu.allowance": return true case "limits.cpu.priority": return true case "limits.disk.priority": return true case "limits.memory": return true case "limits.memory.enforce": return true case "limits.memory.swap": return true case "limits.memory.swap.priority": return true case "limits.network.priority": return true case "limits.processes": return true case "linux.kernel_modules": return true case "security.privileged": return true case "security.nesting": return true case "raw.apparmor": return true case "raw.lxc": return true case "volatile.apply_template": return true case "volatile.base_image": return true case "volatile.last_state.idmap": return true case "volatile.last_state.power": return true } if strings.HasPrefix(k, "volatile.") { if strings.HasSuffix(k, ".hwaddr") { return true } if strings.HasSuffix(k, ".name") { return true } } if strings.HasPrefix(k, "environment.") { return true } if strings.HasPrefix(k, "user.") { return true } return false } func containerValidDeviceConfigKey(t, k string) bool { if k == "type" { return true } switch t { case "unix-char": switch k { case "gid": return true case "major": return true case "minor": return true case "mode": return true case "path": return true case "uid": return true default: return false } case "unix-block": switch k { case "gid": return true case "major": return true case "minor": return true case "mode": return true case "path": return true case "uid": return true default: return false } case "nic": switch k { case "limits.max": return true case "limits.ingress": return true case "limits.egress": return true case "host_name": return true case "hwaddr": return true case "mtu": return true case "name": return true case "nictype": return true case "parent": return true default: return false } case "disk": switch k { case "limits.max": return true case "limits.read": return true case "limits.write": return true case "optional": return true case "path": return true case "readonly": return true case "size": return true case "source": return true case "recursive": return true default: return false } case "none": return false default: return false } } func containerValidConfig(config map[string]string, profile bool, expanded bool) error { if config == nil { return nil } for k, _ := range config { if profile && strings.HasPrefix(k, "volatile.") { return fmt.Errorf("Volatile keys can only be set on containers.") } if k == "raw.lxc" { err := lxcValidConfig(config["raw.lxc"]) if err != nil { return err } } if !containerValidConfigKey(k) { return fmt.Errorf("Bad key: %s", k) } } return nil } func containerValidDevices(devices shared.Devices, profile bool, expanded bool) error { // Empty device list if devices == nil { return nil } // Check each device individually for _, m := range devices { for k, _ := range m { if !containerValidDeviceConfigKey(m["type"], k) { return fmt.Errorf("Invalid device configuration key for %s: %s", m["type"], k) } } if m["type"] == "nic" { if m["nictype"] == "" { return fmt.Errorf("Missing nic type") } if !shared.StringInSlice(m["nictype"], []string{"bridged", "physical", "p2p", "macvlan"}) { return fmt.Errorf("Bad nic type: %s", m["nictype"]) } if shared.StringInSlice(m["nictype"], []string{"bridged", "physical", "macvlan"}) && m["parent"] == "" { return fmt.Errorf("Missing parent for %s type nic.", m["nictype"]) } } else if m["type"] == "disk" { if m["path"] == "" { return fmt.Errorf("Disk entry is missing the required \"path\" property.") } if m["source"] == "" && m["path"] != "/" { return fmt.Errorf("Disk entry is missing the required \"source\" property.") } if m["path"] == "/" && m["source"] != "" { return fmt.Errorf("Root disk entry may not have a \"source\" property set.") } if m["size"] != "" && m["path"] != "/" { return fmt.Errorf("Only the root disk may have a size quota.") } if (m["path"] == "/" || !shared.IsDir(m["source"])) && m["recursive"] != "" { return fmt.Errorf("The recursive option is only supported for additional bind-mounted paths.") } } else if shared.StringInSlice(m["type"], []string{"unix-char", "unix-block"}) { if m["path"] == "" { return fmt.Errorf("Unix device entry is missing the required \"path\" property.") } } else if m["type"] == "none" { continue } else { return fmt.Errorf("Invalid device type: %s", m["type"]) } } // Checks on the expanded config if expanded { foundRootfs := false for _, m := range devices { if m["type"] == "disk" && m["path"] == "/" { foundRootfs = true } } if !foundRootfs { return fmt.Errorf("Container is lacking rootfs entry") } } return nil } // The container arguments type containerArgs struct { // Don't set manually Id int Architecture int BaseImage string Config map[string]string CreationDate time.Time Ctype containerType Devices shared.Devices Ephemeral bool Name string Profiles []string Stateful bool } // The container interface type container interface { // Container actions Freeze() error Shutdown(timeout time.Duration) error Start(stateful bool) error Stop(stateful bool) error Unfreeze() error // Snapshots & migration Restore(sourceContainer container) error Checkpoint(opts lxc.CheckpointOptions) error StartFromMigration(imagesDir string) error Snapshots() ([]container, error) // Config handling Rename(newName string) error Update(newConfig containerArgs, userRequested bool) error Delete() error Export(w io.Writer) error // Live configuration CGroupGet(key string) (string, error) CGroupSet(key string, value string) error ConfigKeySet(key string, value string) error // File handling FilePull(srcpath string, dstpath string) (int, int, os.FileMode, error) FilePush(srcpath string, dstpath string, uid int, gid int, mode os.FileMode) error // Command execution Exec(command []string, env map[string]string, stdin *os.File, stdout *os.File, stderr *os.File) (int, error) // Status Render() (interface{}, error) RenderState() (*shared.ContainerState, error) IsPrivileged() bool IsRunning() bool IsFrozen() bool IsEphemeral() bool IsSnapshot() bool IsStateful() bool IsNesting() bool // Hooks OnStart() error OnStop(target string) error // Properties Id() int Name() string Architecture() int CreationDate() time.Time ExpandedConfig() map[string]string ExpandedDevices() shared.Devices LocalConfig() map[string]string LocalDevices() shared.Devices Profiles() []string InitPID() int State() string // Paths Path() string RootfsPath() string TemplatesPath() string StatePath() string LogFilePath() string LogPath() string // FIXME: Those should be internal functions StorageStart() error StorageStop() error Storage() storage IdmapSet() *shared.IdmapSet LastIdmapSet() (*shared.IdmapSet, error) TemplateApply(trigger string) error Daemon() *Daemon } // Loader functions func containerCreateAsEmpty(d *Daemon, args containerArgs) (container, error) { // Create the container c, err := containerCreateInternal(d, args) if err != nil { return nil, err } // Now create the empty storage if err := c.Storage().ContainerCreate(c); err != nil { c.Delete() return nil, err } // Apply any post-storage configuration err = containerConfigureInternal(c) if err != nil { c.Delete() return nil, err } return c, nil } func containerCreateEmptySnapshot(d *Daemon, args containerArgs) (container, error) { // Create the snapshot c, err := containerCreateInternal(d, args) if err != nil { return nil, err } // Now create the empty snapshot if err := c.Storage().ContainerSnapshotCreateEmpty(c); err != nil { c.Delete() return nil, err } return c, nil } func containerCreateFromImage(d *Daemon, args containerArgs, hash string) (container, error) { // Create the container c, err := containerCreateInternal(d, args) if err != nil { return nil, err } if err := dbImageLastAccessUpdate(d.db, hash, time.Now().UTC()); err != nil { return nil, fmt.Errorf("Error updating image last use date: %s", err) } // Now create the storage from an image if err := c.Storage().ContainerCreateFromImage(c, hash); err != nil { c.Delete() return nil, err } // Apply any post-storage configuration err = containerConfigureInternal(c) if err != nil { c.Delete() return nil, err } return c, nil } func containerCreateAsCopy(d *Daemon, args containerArgs, sourceContainer container) (container, error) { // Create the container c, err := containerCreateInternal(d, args) if err != nil { return nil, err } // Now clone the storage if err := c.Storage().ContainerCopy(c, sourceContainer); err != nil { c.Delete() return nil, err } // Apply any post-storage configuration err = containerConfigureInternal(c) if err != nil { c.Delete() return nil, err } return c, nil } func containerCreateAsSnapshot(d *Daemon, args containerArgs, sourceContainer container) (container, error) { // Deal with state if args.Stateful { if !sourceContainer.IsRunning() { return nil, fmt.Errorf("Container not running, cannot do stateful snapshot") } stateDir := sourceContainer.StatePath() err := os.MkdirAll(stateDir, 0700) if err != nil { return nil, err } /* TODO: ideally we would freeze here and unfreeze below after * we've copied the filesystem, to make sure there are no * changes by the container while snapshotting. Unfortunately * there is abug in CRIU where it doesn't leave the container * in the same state it found it w.r.t. freezing, i.e. CRIU * freezes too, and then /always/ thaws, even if the container * was frozen. Until that's fixed, all calls to Unfreeze() * after snapshotting will fail. */ opts := lxc.CheckpointOptions{Directory: stateDir, Stop: false, Verbose: true} err = sourceContainer.Checkpoint(opts) err2 := CollectCRIULogFile(sourceContainer, stateDir, "snapshot", "dump") if err2 != nil { shared.Log.Warn("failed to collect criu log file", log.Ctx{"error": err2}) } if err != nil { os.RemoveAll(sourceContainer.StatePath()) return nil, err } } // Create the snapshot c, err := containerCreateInternal(d, args) if err != nil { return nil, err } // Clone the container if err := sourceContainer.Storage().ContainerSnapshotCreate(c, sourceContainer); err != nil { c.Delete() return nil, err } // Once we're done, remove the state directory if args.Stateful { os.RemoveAll(sourceContainer.StatePath()) } return c, nil } func containerCreateInternal(d *Daemon, args containerArgs) (container, error) { // Set default values if args.Profiles == nil { args.Profiles = []string{"default"} } if args.Config == nil { args.Config = map[string]string{} } if args.BaseImage != "" { args.Config["volatile.base_image"] = args.BaseImage } if args.Devices == nil { args.Devices = shared.Devices{} } if args.Architecture == 0 { args.Architecture = d.architectures[0] } // Validate container name if args.Ctype == cTypeRegular { err := containerValidName(args.Name) if err != nil { return nil, err } } // Validate container config err := containerValidConfig(args.Config, false, false) if err != nil { return nil, err } // Validate container devices err = containerValidDevices(args.Devices, false, false) if err != nil { return nil, err } // Validate architecture _, err = shared.ArchitectureName(args.Architecture) if err != nil { return nil, err } // Validate profiles profiles, err := dbProfiles(d.db) if err != nil { return nil, err } for _, profile := range args.Profiles { if !shared.StringInSlice(profile, profiles) { return nil, fmt.Errorf("Requested profile '%s' doesn't exist", profile) } } path := containerPath(args.Name, args.Ctype == cTypeSnapshot) if shared.PathExists(path) { if shared.IsSnapshot(args.Name) { return nil, fmt.Errorf("Snapshot '%s' already exists", args.Name) } return nil, fmt.Errorf("The container already exists") } // Wipe any existing log for this container name os.RemoveAll(shared.LogPath(args.Name)) // Create the container entry id, err := dbContainerCreate(d.db, args) if err != nil { return nil, err } args.Id = id // Read the timestamp from the database dbArgs, err := dbContainerGet(d.db, args.Name) if err != nil { return nil, err } args.CreationDate = dbArgs.CreationDate return containerLXCCreate(d, args) } func containerConfigureInternal(c container) error { // Find the root device for _, m := range c.ExpandedDevices() { if m["type"] != "disk" || m["path"] != "/" || m["size"] == "" { continue } size, err := shared.ParseByteSizeString(m["size"]) if err != nil { return err } err = c.Storage().ContainerSetQuota(c, size) if err != nil { return err } break } return nil } func containerLoadById(d *Daemon, id int) (container, error) { // Get the DB record name, err := dbContainerName(d.db, id) if err != nil { return nil, err } return containerLoadByName(d, name) } func containerLoadByName(d *Daemon, name string) (container, error) { // Get the DB record args, err := dbContainerGet(d.db, name) if err != nil { return nil, err } return containerLXCLoad(d, args) } lxd-2.0.0/lxd/container_delete.go000066400000000000000000000011641270277227600167400ustar00rootroot00000000000000package main import ( "fmt" "net/http" "github.com/gorilla/mux" ) func containerDelete(d *Daemon, r *http.Request) Response { name := mux.Vars(r)["name"] c, err := containerLoadByName(d, name) if err != nil { return SmartError(err) } if c.IsRunning() { return BadRequest(fmt.Errorf("container is running")) } rmct := func(op *operation) error { return c.Delete() } resources := map[string][]string{} resources["containers"] = []string{name} op, err := operationCreate(operationClassTask, resources, nil, rmct, nil, nil) if err != nil { return InternalError(err) } return OperationResponse(op) } lxd-2.0.0/lxd/container_exec.go000066400000000000000000000157361270277227600164340ustar00rootroot00000000000000package main import ( "encoding/json" "fmt" "io/ioutil" "net/http" "os" "strconv" "strings" "sync" "github.com/gorilla/mux" "github.com/gorilla/websocket" "github.com/lxc/lxd/shared" ) type commandPostContent struct { Command []string `json:"command"` WaitForWS bool `json:"wait-for-websocket"` Interactive bool `json:"interactive"` Environment map[string]string `json:"environment"` Width int `json:"width"` Height int `json:"height"` } type execWs struct { command []string container container env map[string]string rootUid int rootGid int conns map[int]*websocket.Conn connsLock sync.Mutex allConnected chan bool controlConnected chan bool interactive bool fds map[int]string width int height int } func (s *execWs) Metadata() interface{} { fds := shared.Jmap{} for fd, secret := range s.fds { if fd == -1 { fds["control"] = secret } else { fds[strconv.Itoa(fd)] = secret } } return shared.Jmap{"fds": fds} } func (s *execWs) Connect(op *operation, r *http.Request, w http.ResponseWriter) error { secret := r.FormValue("secret") if secret == "" { return fmt.Errorf("missing secret") } for fd, fdSecret := range s.fds { if secret == fdSecret { conn, err := shared.WebsocketUpgrader.Upgrade(w, r, nil) if err != nil { return err } s.connsLock.Lock() s.conns[fd] = conn s.connsLock.Unlock() if fd == -1 { s.controlConnected <- true return nil } for i, c := range s.conns { if i != -1 && c == nil { return nil } } s.allConnected <- true return nil } } /* If we didn't find the right secret, the user provided a bad one, * which 403, not 404, since this operation actually exists */ return os.ErrPermission } func (s *execWs) Do(op *operation) error { <-s.allConnected var err error var ttys []*os.File var ptys []*os.File var stdin *os.File var stdout *os.File var stderr *os.File if s.interactive { ttys = make([]*os.File, 1) ptys = make([]*os.File, 1) ptys[0], ttys[0], err = shared.OpenPty(s.rootUid, s.rootGid) stdin = ttys[0] stdout = ttys[0] stderr = ttys[0] if s.width > 0 && s.height > 0 { shared.SetSize(int(ptys[0].Fd()), s.width, s.height) } } else { ttys = make([]*os.File, 3) ptys = make([]*os.File, 3) for i := 0; i < len(ttys); i++ { ptys[i], ttys[i], err = shared.Pipe() if err != nil { return err } } stdin = ptys[0] stdout = ttys[1] stderr = ttys[2] } controlExit := make(chan bool) var wgEOF sync.WaitGroup if s.interactive { wgEOF.Add(1) go func() { select { case <-s.controlConnected: break case <-controlExit: return } for { mt, r, err := s.conns[-1].NextReader() if mt == websocket.CloseMessage { break } if err != nil { shared.Debugf("Got error getting next reader %s", err) break } buf, err := ioutil.ReadAll(r) if err != nil { shared.Debugf("Failed to read message %s", err) break } command := shared.ContainerExecControl{} if err := json.Unmarshal(buf, &command); err != nil { shared.Debugf("Failed to unmarshal control socket command: %s", err) continue } if command.Command == "window-resize" { winchWidth, err := strconv.Atoi(command.Args["width"]) if err != nil { shared.Debugf("Unable to extract window width: %s", err) continue } winchHeight, err := strconv.Atoi(command.Args["height"]) if err != nil { shared.Debugf("Unable to extract window height: %s", err) continue } err = shared.SetSize(int(ptys[0].Fd()), winchWidth, winchHeight) if err != nil { shared.Debugf("Failed to set window size to: %dx%d", winchWidth, winchHeight) continue } } } }() go func() { readDone, writeDone := shared.WebsocketMirror(s.conns[0], ptys[0], ptys[0]) <-readDone <-writeDone s.conns[0].Close() wgEOF.Done() }() } else { wgEOF.Add(len(ttys) - 1) for i := 0; i < len(ttys); i++ { go func(i int) { if i == 0 { <-shared.WebsocketRecvStream(ttys[i], s.conns[i]) ttys[i].Close() } else { <-shared.WebsocketSendStream(s.conns[i], ptys[i]) ptys[i].Close() wgEOF.Done() } }(i) } } cmdResult, cmdErr := s.container.Exec(s.command, s.env, stdin, stdout, stderr) for _, tty := range ttys { tty.Close() } if s.conns[-1] == nil { if s.interactive { controlExit <- true } } else { s.conns[-1].Close() } wgEOF.Wait() for _, pty := range ptys { pty.Close() } metadata := shared.Jmap{"return": cmdResult} err = op.UpdateMetadata(metadata) if err != nil { return err } return cmdErr } func containerExecPost(d *Daemon, r *http.Request) Response { name := mux.Vars(r)["name"] c, err := containerLoadByName(d, name) if err != nil { return SmartError(err) } if !c.IsRunning() { return BadRequest(fmt.Errorf("Container is not running.")) } if c.IsFrozen() { return BadRequest(fmt.Errorf("Container is frozen.")) } post := commandPostContent{} buf, err := ioutil.ReadAll(r.Body) if err != nil { return BadRequest(err) } if err := json.Unmarshal(buf, &post); err != nil { return BadRequest(err) } env := map[string]string{} for k, v := range c.ExpandedConfig() { if strings.HasPrefix(k, "environment.") { env[strings.TrimPrefix(k, "environment.")] = v } } if post.Environment != nil { for k, v := range post.Environment { env[k] = v } } if post.WaitForWS { ws := &execWs{} ws.fds = map[int]string{} idmapset := c.IdmapSet() if idmapset != nil { ws.rootUid, ws.rootGid = idmapset.ShiftIntoNs(0, 0) } ws.conns = map[int]*websocket.Conn{} ws.conns[-1] = nil ws.conns[0] = nil if !post.Interactive { ws.conns[1] = nil ws.conns[2] = nil } ws.allConnected = make(chan bool, 1) ws.controlConnected = make(chan bool, 1) ws.interactive = post.Interactive for i := -1; i < len(ws.conns)-1; i++ { ws.fds[i], err = shared.RandomCryptoString() if err != nil { return InternalError(err) } } ws.command = post.Command ws.container = c ws.env = env ws.width = post.Width ws.height = post.Height resources := map[string][]string{} resources["containers"] = []string{ws.container.Name()} op, err := operationCreate(operationClassWebsocket, resources, ws.Metadata(), ws.Do, nil, ws.Connect) if err != nil { return InternalError(err) } return OperationResponse(op) } run := func(op *operation) error { nullDev, err := os.OpenFile(os.DevNull, os.O_RDWR, 0666) if err != nil { return err } defer nullDev.Close() _, cmdErr := c.Exec(post.Command, env, nil, nil, nil) return cmdErr } resources := map[string][]string{} resources["containers"] = []string{name} op, err := operationCreate(operationClassTask, resources, nil, run, nil, nil) if err != nil { return InternalError(err) } return OperationResponse(op) } lxd-2.0.0/lxd/container_file.go000066400000000000000000000043251270277227600164170ustar00rootroot00000000000000package main import ( "fmt" "io" "io/ioutil" "net/http" "os" "path/filepath" "github.com/gorilla/mux" "github.com/lxc/lxd/shared" ) func containerFileHandler(d *Daemon, r *http.Request) Response { name := mux.Vars(r)["name"] c, err := containerLoadByName(d, name) if err != nil { return SmartError(err) } path := r.FormValue("path") if path == "" { return BadRequest(fmt.Errorf("missing path argument")) } switch r.Method { case "GET": return containerFileGet(c, path, r) case "POST": return containerFilePut(c, path, r) default: return NotFound } } func containerFileGet(c container, path string, r *http.Request) Response { /* * Copy out of the ns to a temporary file, and then use that to serve * the request from. This prevents us from having to worry about stuff * like people breaking out of the container root by symlinks or * ../../../s etc. in the path, since we can just rely on the kernel * for correctness. */ temp, err := ioutil.TempFile("", "lxd_forkgetfile_") if err != nil { return InternalError(err) } defer temp.Close() // Pul the file from the container uid, gid, mode, err := c.FilePull(path, temp.Name()) if err != nil { return InternalError(err) } headers := map[string]string{ "X-LXD-uid": fmt.Sprintf("%d", uid), "X-LXD-gid": fmt.Sprintf("%d", gid), "X-LXD-mode": fmt.Sprintf("%04o", mode), } // Make a file response struct files := make([]fileResponseEntry, 1) files[0].identifier = filepath.Base(path) files[0].path = temp.Name() files[0].filename = filepath.Base(path) return FileResponse(r, files, headers, true) } func containerFilePut(c container, path string, r *http.Request) Response { // Extract file ownership and mode from headers uid, gid, mode := shared.ParseLXDFileHeaders(r.Header) // Write file content to a tempfile temp, err := ioutil.TempFile("", "lxd_forkputfile_") if err != nil { return InternalError(err) } defer func() { temp.Close() os.Remove(temp.Name()) }() _, err = io.Copy(temp, r.Body) if err != nil { return InternalError(err) } // Transfer the file into the container err = c.FilePush(temp.Name(), path, uid, gid, mode) if err != nil { return InternalError(err) } return EmptySyncResponse } lxd-2.0.0/lxd/container_get.go000066400000000000000000000005341270277227600162550ustar00rootroot00000000000000package main import ( "net/http" "github.com/gorilla/mux" ) func containerGet(d *Daemon, r *http.Request) Response { name := mux.Vars(r)["name"] c, err := containerLoadByName(d, name) if err != nil { return SmartError(err) } state, err := c.Render() if err != nil { return InternalError(err) } return SyncResponse(true, state) } lxd-2.0.0/lxd/container_logs.go000066400000000000000000000043621270277227600164450ustar00rootroot00000000000000package main import ( "fmt" "io/ioutil" "net/http" "os" "strings" "github.com/gorilla/mux" "github.com/lxc/lxd/shared" ) func containerLogsGet(d *Daemon, r *http.Request) Response { /* Let's explicitly *not* try to do a containerLoadByName here. In some * cases (e.g. when container creation failed), the container won't * exist in the DB but it does have some log files on disk. * * However, we should check this name and ensure it's a valid container * name just so that people can't list arbitrary directories. */ name := mux.Vars(r)["name"] if err := containerValidName(name); err != nil { return BadRequest(err) } result := []string{} dents, err := ioutil.ReadDir(shared.LogPath(name)) if err != nil { return SmartError(err) } for _, f := range dents { result = append(result, fmt.Sprintf("/%s/containers/%s/logs/%s", shared.APIVersion, name, f.Name())) } return SyncResponse(true, result) } var containerLogsCmd = Command{ name: "containers/{name}/logs", get: containerLogsGet, } func validLogFileName(fname string) bool { /* Let's just require that the paths be relative, so that we don't have * to deal with any escaping or whatever. */ return fname == "lxc.log" || fname == "lxc.conf" || strings.HasPrefix(fname, "migration_") || strings.HasPrefix(fname, "snapshot_") } func containerLogGet(d *Daemon, r *http.Request) Response { name := mux.Vars(r)["name"] file := mux.Vars(r)["file"] if err := containerValidName(name); err != nil { return BadRequest(err) } if !validLogFileName(file) { return BadRequest(fmt.Errorf("log file name %s not valid", file)) } ent := fileResponseEntry{ path: shared.LogPath(name, file), filename: file, } return FileResponse(r, []fileResponseEntry{ent}, nil, false) } func containerLogDelete(d *Daemon, r *http.Request) Response { name := mux.Vars(r)["name"] file := mux.Vars(r)["file"] if err := containerValidName(name); err != nil { return BadRequest(err) } if !validLogFileName(file) { return BadRequest(fmt.Errorf("log file name %s not valid", file)) } return SmartError(os.Remove(shared.LogPath(name, file))) } var containerLogCmd = Command{ name: "containers/{name}/logs/{file}", get: containerLogGet, delete: containerLogDelete, } lxd-2.0.0/lxd/container_lxc.go000066400000000000000000003074011270277227600162670ustar00rootroot00000000000000package main import ( "archive/tar" "encoding/json" "fmt" "io" "io/ioutil" "net" "os" "os/exec" "path" "path/filepath" "reflect" "strconv" "strings" "sync" "syscall" "time" "gopkg.in/flosch/pongo2.v3" "gopkg.in/lxc/go-lxc.v2" "gopkg.in/yaml.v2" "github.com/lxc/lxd/shared" log "gopkg.in/inconshreveable/log15.v2" ) // Global variables var lxcStoppingContainersLock sync.Mutex var lxcStoppingContainers map[int]*sync.WaitGroup = make(map[int]*sync.WaitGroup) // Helper functions func lxcSetConfigItem(c *lxc.Container, key string, value string) error { if c == nil { return fmt.Errorf("Uninitialized go-lxc struct") } err := c.SetConfigItem(key, value) if err != nil { return fmt.Errorf("Failed to set LXC config: %s=%s", key, value) } return nil } func lxcValidConfig(rawLxc string) error { for _, line := range strings.Split(rawLxc, "\n") { // Ignore empty lines if len(line) == 0 { continue } // Ignore comments if strings.HasPrefix(line, "#") { continue } // Ensure the format is valid membs := strings.SplitN(line, "=", 2) if len(membs) != 2 { return fmt.Errorf("Invalid raw.lxc line: %s", line) } key := strings.ToLower(strings.Trim(membs[0], " \t")) // Blacklist some keys if key == "lxc.logfile" { return fmt.Errorf("Setting lxc.logfile is not allowed") } if strings.HasPrefix(key, "lxc.network.") { fields := strings.Split(key, ".") if len(fields) == 4 && shared.StringInSlice(fields[3], []string{"ipv4", "ipv6"}) { continue } if len(fields) == 5 && shared.StringInSlice(fields[3], []string{"ipv4", "ipv6"}) && fields[4] == "gateway" { continue } return fmt.Errorf("Only interface-specific ipv4/ipv6 lxc.network keys are allowed") } } return nil } // Loader functions func containerLXCCreate(d *Daemon, args containerArgs) (container, error) { // Create the container struct c := &containerLXC{ daemon: d, id: args.Id, name: args.Name, ephemeral: args.Ephemeral, architecture: args.Architecture, cType: args.Ctype, stateful: args.Stateful, creationDate: args.CreationDate, profiles: args.Profiles, localConfig: args.Config, localDevices: args.Devices, } // No need to detect storage here, its a new container. c.storage = d.Storage // Load the config err := c.init() if err != nil { c.Delete() return nil, err } // Look for a rootfs entry rootfs := false for _, m := range c.expandedDevices { if m["type"] == "disk" && m["path"] == "/" { rootfs = true break } } if !rootfs { deviceName := "root" for { if c.expandedDevices[deviceName] == nil { break } deviceName += "_" } c.localDevices[deviceName] = shared.Device{"type": "disk", "path": "/"} updateArgs := containerArgs{ Architecture: c.architecture, Config: c.localConfig, Devices: c.localDevices, Ephemeral: c.ephemeral, Profiles: c.profiles, } err = c.Update(updateArgs, false) if err != nil { c.Delete() return nil, err } } // Validate expanded config err = containerValidConfig(c.expandedConfig, false, true) if err != nil { c.Delete() return nil, err } err = containerValidDevices(c.expandedDevices, false, true) if err != nil { c.Delete() return nil, err } // Setup initial idmap config idmap := c.IdmapSet() var jsonIdmap string if idmap != nil { idmapBytes, err := json.Marshal(idmap.Idmap) if err != nil { c.Delete() return nil, err } jsonIdmap = string(idmapBytes) } else { jsonIdmap = "[]" } err = c.ConfigKeySet("volatile.last_state.idmap", jsonIdmap) if err != nil { c.Delete() return nil, err } return c, nil } func containerLXCLoad(d *Daemon, args containerArgs) (container, error) { // Create the container struct c := &containerLXC{ daemon: d, id: args.Id, name: args.Name, ephemeral: args.Ephemeral, architecture: args.Architecture, cType: args.Ctype, creationDate: args.CreationDate, profiles: args.Profiles, localConfig: args.Config, localDevices: args.Devices, stateful: args.Stateful} // Detect the storage backend s, err := storageForFilename(d, shared.VarPath("containers", strings.Split(c.name, "/")[0])) if err != nil { return nil, err } c.storage = s // Load the config err = c.init() if err != nil { return nil, err } return c, nil } // The LXC container driver type containerLXC struct { // Properties architecture int cType containerType creationDate time.Time ephemeral bool id int name string stateful bool // Config expandedConfig map[string]string expandedDevices shared.Devices fromHook bool localConfig map[string]string localDevices shared.Devices profiles []string // Cache c *lxc.Container daemon *Daemon idmapset *shared.IdmapSet storage storage } func (c *containerLXC) init() error { // Compute the expanded config and device list err := c.expandConfig() if err != nil { return err } err = c.expandDevices() if err != nil { return err } // Setup the Idmap if !c.IsPrivileged() { if c.daemon.IdmapSet == nil { return fmt.Errorf("LXD doesn't have a uid/gid allocation. In this mode, only privileged containers are supported.") } c.idmapset = c.daemon.IdmapSet } return nil } func (c *containerLXC) initLXC() error { // Check if being called from a hook if c.fromHook { return fmt.Errorf("You can't use go-lxc from inside a LXC hook.") } // Check if already initialized if c.c != nil { return nil } // Load the go-lxc struct cc, err := lxc.NewContainer(c.Name(), c.daemon.lxcpath) if err != nil { return err } // Base config err = lxcSetConfigItem(cc, "lxc.cap.drop", "mac_admin mac_override sys_time sys_module sys_rawio") if err != nil { return err } // Set an appropriate /proc, /sys/ and /sys/fs/cgroup mounts := []string{} if c.IsPrivileged() && !runningInUserns { mounts = append(mounts, "proc:mixed") mounts = append(mounts, "sys:mixed") } else { mounts = append(mounts, "proc:rw") mounts = append(mounts, "sys:rw") } if !shared.PathExists("/proc/self/ns/cgroup") { mounts = append(mounts, "cgroup:mixed") } err = lxcSetConfigItem(cc, "lxc.mount.auto", strings.Join(mounts, " ")) if err != nil { return err } err = lxcSetConfigItem(cc, "lxc.autodev", "1") if err != nil { return err } err = lxcSetConfigItem(cc, "lxc.pts", "1024") if err != nil { return err } bindMounts := []string{ "/proc/sys/fs/binfmt_misc", "/sys/firmware/efi/efivars", "/sys/fs/fuse/connections", "/sys/fs/pstore", "/sys/kernel/debug", "/sys/kernel/security"} if c.IsPrivileged() && !runningInUserns { err = lxcSetConfigItem(cc, "lxc.mount.entry", "mqueue dev/mqueue mqueue rw,relatime,create=dir,optional") if err != nil { return err } } else { bindMounts = append(bindMounts, "/dev/mqueue") } for _, mnt := range bindMounts { err = lxcSetConfigItem(cc, "lxc.mount.entry", fmt.Sprintf("%s %s none rbind,create=dir,optional", mnt, strings.TrimPrefix(mnt, "/"))) if err != nil { return err } } // For lxcfs templateConfDir := os.Getenv("LXD_LXC_TEMPLATE_CONFIG") if templateConfDir == "" { templateConfDir = "/usr/share/lxc/config" } if shared.PathExists(fmt.Sprintf("%s/common.conf.d/", templateConfDir)) { err = lxcSetConfigItem(cc, "lxc.include", fmt.Sprintf("%s/common.conf.d/", templateConfDir)) if err != nil { return err } } // Configure devices cgroup if c.IsPrivileged() && !runningInUserns && cgDevicesController { err = lxcSetConfigItem(cc, "lxc.cgroup.devices.deny", "a") if err != nil { return err } for _, dev := range []string{"c *:* m", "b *:* m", "c 5:0 rwm", "c 5:1 rwm", "c 1:5 rwm", "c 1:7 rwm", "c 1:3 rwm", "c 1:8 rwm", "c 1:9 rwm", "c 5:2 rwm", "c 136:* rwm"} { err = lxcSetConfigItem(cc, "lxc.cgroup.devices.allow", dev) if err != nil { return err } } } if c.IsNesting() { /* * mount extra /proc and /sys to work around kernel * restrictions on remounting them when covered */ err = lxcSetConfigItem(cc, "lxc.mount.entry", "proc dev/.lxc/proc proc create=dir,optional") if err != nil { return err } err = lxcSetConfigItem(cc, "lxc.mount.entry", "sys dev/.lxc/sys sysfs create=dir,optional") if err != nil { return err } } // Setup logging logfile := c.LogFilePath() err = cc.SetLogFile(logfile) if err != nil { return err } err = lxcSetConfigItem(cc, "lxc.loglevel", "0") if err != nil { return err } // Setup architecture personality, err := shared.ArchitecturePersonality(c.architecture) if err != nil { personality, err = shared.ArchitecturePersonality(c.daemon.architectures[0]) if err != nil { return err } } err = lxcSetConfigItem(cc, "lxc.arch", personality) if err != nil { return err } // Setup the hooks err = lxcSetConfigItem(cc, "lxc.hook.pre-start", fmt.Sprintf("%s callhook %s %d start", c.daemon.execPath, shared.VarPath(""), c.id)) if err != nil { return err } err = lxcSetConfigItem(cc, "lxc.hook.post-stop", fmt.Sprintf("%s callhook %s %d stop", c.daemon.execPath, shared.VarPath(""), c.id)) if err != nil { return err } // Setup the console err = lxcSetConfigItem(cc, "lxc.tty", "0") if err != nil { return err } // Setup the hostname err = lxcSetConfigItem(cc, "lxc.utsname", c.Name()) if err != nil { return err } // Setup devlxd err = lxcSetConfigItem(cc, "lxc.mount.entry", fmt.Sprintf("%s dev/lxd none bind,create=dir 0 0", shared.VarPath("devlxd"))) if err != nil { return err } // Setup AppArmor if aaAvailable { if aaConfined || !aaAdmin { // If confined but otherwise able to use AppArmor, use our own profile curProfile := aaProfile() curProfile = strings.TrimSuffix(curProfile, " (enforce)") err = lxcSetConfigItem(cc, "lxc.aa_profile", curProfile) if err != nil { return err } } else { // If not currently confined, use the container's profile err := lxcSetConfigItem(cc, "lxc.aa_profile", AAProfileFull(c)) if err != nil { return err } } } // Setup Seccomp err = lxcSetConfigItem(cc, "lxc.seccomp", SeccompProfilePath(c)) if err != nil { return err } // Setup idmap if c.idmapset != nil { lines := c.idmapset.ToLxcString() for _, line := range lines { err := lxcSetConfigItem(cc, "lxc.id_map", strings.TrimSuffix(line, "\n")) if err != nil { return err } } } // Setup environment for k, v := range c.expandedConfig { if strings.HasPrefix(k, "environment.") { err = lxcSetConfigItem(cc, "lxc.environment", fmt.Sprintf("%s=%s", strings.TrimPrefix(k, "environment."), v)) if err != nil { return err } } } // Memory limits if cgMemoryController { memory := c.expandedConfig["limits.memory"] memoryEnforce := c.expandedConfig["limits.memory.enforce"] memorySwap := c.expandedConfig["limits.memory.swap"] memorySwapPriority := c.expandedConfig["limits.memory.swap.priority"] // Configure the memory limits if memory != "" { var valueInt int64 if strings.HasSuffix(memory, "%") { percent, err := strconv.ParseInt(strings.TrimSuffix(memory, "%"), 10, 64) if err != nil { return err } memoryTotal, err := deviceTotalMemory() if err != nil { return err } valueInt = int64((memoryTotal / 100) * percent) } else { valueInt, err = shared.ParseByteSizeString(memory) if err != nil { return err } } if memoryEnforce == "soft" { err = lxcSetConfigItem(cc, "lxc.cgroup.memory.soft_limit_in_bytes", fmt.Sprintf("%d", valueInt)) if err != nil { return err } } else { if memorySwap != "false" && cgSwapAccounting { err = lxcSetConfigItem(cc, "lxc.cgroup.memory.limit_in_bytes", fmt.Sprintf("%d", valueInt)) if err != nil { return err } err = lxcSetConfigItem(cc, "lxc.cgroup.memory.memsw.limit_in_bytes", fmt.Sprintf("%d", valueInt)) if err != nil { return err } } else { err = lxcSetConfigItem(cc, "lxc.cgroup.memory.limit_in_bytes", fmt.Sprintf("%d", valueInt)) if err != nil { return err } } } } // Configure the swappiness if memorySwap == "false" { err = lxcSetConfigItem(cc, "lxc.cgroup.memory.swappiness", "0") if err != nil { return err } } else if memorySwapPriority != "" { priority, err := strconv.Atoi(memorySwapPriority) if err != nil { return err } err = lxcSetConfigItem(cc, "lxc.cgroup.memory.swappiness", fmt.Sprintf("%d", 60-10+priority)) if err != nil { return err } } } // CPU limits cpuPriority := c.expandedConfig["limits.cpu.priority"] cpuAllowance := c.expandedConfig["limits.cpu.allowance"] if (cpuPriority != "" || cpuAllowance != "") && cgCpuController { cpuShares, cpuCfsQuota, cpuCfsPeriod, err := deviceParseCPU(cpuAllowance, cpuPriority) if err != nil { return err } if cpuShares != "1024" { err = lxcSetConfigItem(cc, "lxc.cgroup.cpu.shares", cpuShares) if err != nil { return err } } if cpuCfsPeriod != "-1" { err = lxcSetConfigItem(cc, "lxc.cgroup.cpu.cfs_period_us", cpuCfsPeriod) if err != nil { return err } } if cpuCfsQuota != "-1" { err = lxcSetConfigItem(cc, "lxc.cgroup.cpu.cfs_quota_us", cpuCfsQuota) if err != nil { return err } } } // Disk limits if cgBlkioController { diskPriority := c.expandedConfig["limits.disk.priority"] if diskPriority != "" { priorityInt, err := strconv.Atoi(diskPriority) if err != nil { return err } err = lxcSetConfigItem(cc, "lxc.cgroup.blkio.weight", fmt.Sprintf("%d", priorityInt*100)) if err != nil { return err } } hasDiskLimits := false for _, m := range c.expandedDevices { if m["type"] != "disk" { continue } if m["limits.read"] != "" || m["limits.write"] != "" || m["limits.max"] != "" { hasDiskLimits = true break } } if hasDiskLimits { diskLimits, err := c.getDiskLimits() if err != nil { return err } for block, limit := range diskLimits { if limit.readBps > 0 { err = lxcSetConfigItem(cc, "lxc.cgroup.blkio.throttle.read_bps_device", fmt.Sprintf("%s %d", block, limit.readBps)) if err != nil { return err } } if limit.readIops > 0 { err = lxcSetConfigItem(cc, "lxc.cgroup.blkio.throttle.read_iops_device", fmt.Sprintf("%s %d", block, limit.readIops)) if err != nil { return err } } if limit.writeBps > 0 { err = lxcSetConfigItem(cc, "lxc.cgroup.blkio.throttle.write_bps_device", fmt.Sprintf("%s %d", block, limit.writeBps)) if err != nil { return err } } if limit.writeIops > 0 { err = lxcSetConfigItem(cc, "lxc.cgroup.blkio.throttle.write_iops_device", fmt.Sprintf("%s %d", block, limit.writeIops)) if err != nil { return err } } } } } // Processes if cgPidsController { processes := c.expandedConfig["limits.processes"] if processes != "" { valueInt, err := strconv.ParseInt(processes, 10, 64) if err != nil { return err } err = lxcSetConfigItem(cc, "lxc.cgroup.pids.max", fmt.Sprintf("%d", valueInt)) if err != nil { return err } } } // Setup devices for k, m := range c.expandedDevices { if shared.StringInSlice(m["type"], []string{"unix-char", "unix-block"}) { // Prepare all the paths srcPath := m["path"] tgtPath := strings.TrimPrefix(srcPath, "/") devName := fmt.Sprintf("unix.%s", strings.Replace(tgtPath, "/", "-", -1)) devPath := filepath.Join(c.DevicesPath(), devName) // Set the bind-mount entry err = lxcSetConfigItem(cc, "lxc.mount.entry", fmt.Sprintf("%s %s none bind,create=file", devPath, tgtPath)) if err != nil { return err } } else if m["type"] == "nic" { // Fill in some fields from volatile m, err = c.fillNetworkDevice(k, m) if err != nil { return err } // Interface type specific configuration if shared.StringInSlice(m["nictype"], []string{"bridged", "p2p"}) { err = lxcSetConfigItem(cc, "lxc.network.type", "veth") if err != nil { return err } } else if m["nictype"] == "physical" { err = lxcSetConfigItem(cc, "lxc.network.type", "phys") if err != nil { return err } } else if m["nictype"] == "macvlan" { err = lxcSetConfigItem(cc, "lxc.network.type", "macvlan") if err != nil { return err } err = lxcSetConfigItem(cc, "lxc.network.macvlan.mode", "bridge") if err != nil { return err } } err = lxcSetConfigItem(cc, "lxc.network.flags", "up") if err != nil { return err } if shared.StringInSlice(m["nictype"], []string{"bridged", "physical", "macvlan"}) { err = lxcSetConfigItem(cc, "lxc.network.link", m["parent"]) if err != nil { return err } } // Host Virtual NIC name if m["host_name"] != "" { err = lxcSetConfigItem(cc, "lxc.network.veth.pair", m["host_name"]) if err != nil { return err } } // MAC address if m["hwaddr"] != "" { err = lxcSetConfigItem(cc, "lxc.network.hwaddr", m["hwaddr"]) if err != nil { return err } } // MTU if m["mtu"] != "" { err = lxcSetConfigItem(cc, "lxc.network.mtu", m["mtu"]) if err != nil { return err } } // Name if m["name"] != "" { err = lxcSetConfigItem(cc, "lxc.network.name", m["name"]) if err != nil { return err } } } else if m["type"] == "disk" { // Prepare all the paths srcPath := m["source"] tgtPath := strings.TrimPrefix(m["path"], "/") devName := fmt.Sprintf("disk.%s", strings.Replace(tgtPath, "/", "-", -1)) devPath := filepath.Join(c.DevicesPath(), devName) // Various option checks isOptional := m["optional"] == "1" || m["optional"] == "true" isReadOnly := m["readonly"] == "1" || m["readonly"] == "true" isRecursive := m["recursive"] == "1" || m["recursive"] == "true" isFile := !shared.IsDir(srcPath) && !deviceIsBlockdev(srcPath) // Deal with a rootfs if tgtPath == "" { // Set the rootfs backend type if supported (must happen before any other lxc.rootfs) err := lxcSetConfigItem(cc, "lxc.rootfs.backend", "dir") if err == nil { value := cc.ConfigItem("lxc.rootfs.backend") if len(value) == 0 || value[0] != "dir" { lxcSetConfigItem(cc, "lxc.rootfs.backend", "") } } // Set the rootfs path err = lxcSetConfigItem(cc, "lxc.rootfs", c.RootfsPath()) if err != nil { return err } // Read-only rootfs (unlikely to work very well) if isReadOnly { err = lxcSetConfigItem(cc, "lxc.rootfs.options", "ro") if err != nil { return err } } } else { rbind := "" options := []string{} if isReadOnly { options = append(options, "ro") } if isOptional { options = append(options, "optional") } if isRecursive { rbind = "r" } if isFile { options = append(options, "create=file") } else { options = append(options, "create=dir") } err = lxcSetConfigItem(cc, "lxc.mount.entry", fmt.Sprintf("%s %s none %sbind,%s", devPath, tgtPath, rbind, strings.Join(options, ","))) if err != nil { return err } } } } // Setup shmounts err = lxcSetConfigItem(cc, "lxc.mount.entry", fmt.Sprintf("%s dev/.lxd-mounts none bind,create=dir 0 0", shared.VarPath("shmounts", c.Name()))) if err != nil { return err } // Apply raw.lxc if lxcConfig, ok := c.expandedConfig["raw.lxc"]; ok { f, err := ioutil.TempFile("", "lxd_config_") if err != nil { return err } err = shared.WriteAll(f, []byte(lxcConfig)) f.Close() defer os.Remove(f.Name()) if err != nil { return err } if err := cc.LoadConfigFile(f.Name()); err != nil { return fmt.Errorf("Failed to load raw.lxc") } } c.c = cc return nil } // Config handling func (c *containerLXC) expandConfig() error { config := map[string]string{} // Apply all the profiles for _, name := range c.profiles { profileConfig, err := dbProfileConfig(c.daemon.db, name) if err != nil { return err } for k, v := range profileConfig { config[k] = v } } // Stick the local config on top for k, v := range c.localConfig { config[k] = v } c.expandedConfig = config return nil } func (c *containerLXC) expandDevices() error { devices := shared.Devices{} // Apply all the profiles for _, p := range c.profiles { profileDevices, err := dbDevices(c.daemon.db, p, true) if err != nil { return err } for k, v := range profileDevices { devices[k] = v } } // Stick local devices on top for k, v := range c.localDevices { devices[k] = v } c.expandedDevices = devices return nil } // Start functions func (c *containerLXC) startCommon() (string, error) { // Load the go-lxc struct err := c.initLXC() if err != nil { return "", err } // Check that we're not already running if c.IsRunning() { return "", fmt.Errorf("The container is already running") } // Load any required kernel modules kernelModules := c.expandedConfig["linux.kernel_modules"] if kernelModules != "" { for _, module := range strings.Split(kernelModules, ",") { module = strings.TrimPrefix(module, " ") out, err := exec.Command("modprobe", module).CombinedOutput() if err != nil { return "", fmt.Errorf("Failed to load kernel module '%s': %s", module, out) } } } /* Deal with idmap changes */ idmap := c.IdmapSet() lastIdmap, err := c.LastIdmapSet() if err != nil { return "", err } var jsonIdmap string if idmap != nil { idmapBytes, err := json.Marshal(idmap.Idmap) if err != nil { return "", err } jsonIdmap = string(idmapBytes) } else { jsonIdmap = "[]" } if !reflect.DeepEqual(idmap, lastIdmap) { shared.Debugf("Container idmap changed, remapping") err := c.StorageStart() if err != nil { return "", err } if lastIdmap != nil { err = lastIdmap.UnshiftRootfs(c.RootfsPath()) if err != nil { c.StorageStop() return "", err } } if idmap != nil { err = idmap.ShiftRootfs(c.RootfsPath()) if err != nil { c.StorageStop() return "", err } } err = c.StorageStop() if err != nil { return "", err } } err = c.ConfigKeySet("volatile.last_state.idmap", jsonIdmap) if err != nil { return "", err } // Generate the Seccomp profile if err := SeccompCreateProfile(c); err != nil { return "", err } // Cleanup any existing leftover devices c.removeUnixDevices() c.removeDiskDevices() // Create the devices for k, m := range c.expandedDevices { if shared.StringInSlice(m["type"], []string{"unix-char", "unix-block"}) { // Unix device devPath, err := c.createUnixDevice(k, m) if err != nil { return "", err } // Add the new device cgroup rule dType, dMajor, dMinor, err := deviceGetAttributes(devPath) if err != nil { return "", err } err = lxcSetConfigItem(c.c, "lxc.cgroup.devices.allow", fmt.Sprintf("%s %d:%d rwm", dType, dMajor, dMinor)) if err != nil { return "", fmt.Errorf("Failed to add cgroup rule for device") } } else if m["type"] == "disk" { // Disk device if m["path"] != "/" { _, err := c.createDiskDevice(k, m) if err != nil { return "", err } } } } // Create any missing directory err = os.MkdirAll(c.LogPath(), 0700) if err != nil { return "", err } err = os.MkdirAll(shared.VarPath("devices", c.Name()), 0711) if err != nil { return "", err } err = os.MkdirAll(shared.VarPath("shmounts", c.Name()), 0711) if err != nil { return "", err } // Cleanup any leftover volatile entries netNames := []string{} for k, v := range c.expandedDevices { if v["type"] == "nic" { netNames = append(netNames, k) } } for k, _ := range c.localConfig { // We only care about volatile if !strings.HasPrefix(k, "volatile.") { continue } // Confirm it's a key of format volatile.. fields := strings.SplitN(k, ".", 3) if len(fields) != 3 { continue } // The only device keys we care about are name and hwaddr if !shared.StringInSlice(fields[2], []string{"name", "hwaddr"}) { continue } // Check if the device still exists if shared.StringInSlice(fields[1], netNames) { // Don't remove the volatile entry if the device doesn't have the matching field set if c.expandedDevices[fields[1]][fields[2]] == "" { continue } } // Remove the volatile key from the DB err := dbContainerConfigRemove(c.daemon.db, c.id, k) if err != nil { return "", err } // Remove the volatile key from the in-memory configs delete(c.localConfig, k) delete(c.expandedConfig, k) } // Generate the LXC config f, err := ioutil.TempFile("", "lxd_lxc_startconfig_") if err != nil { return "", err } configPath := f.Name() if err = f.Chmod(0600); err != nil { f.Close() os.Remove(configPath) return "", err } f.Close() err = c.c.SaveConfigFile(configPath) if err != nil { os.Remove(configPath) return "", err } return configPath, nil } func (c *containerLXC) Start(stateful bool) error { // Wait for container tear down to finish lxcStoppingContainersLock.Lock() wgStopping, stopping := lxcStoppingContainers[c.id] lxcStoppingContainersLock.Unlock() if stopping { wgStopping.Wait() } // Run the shared start code configPath, err := c.startCommon() if err != nil { return err } // If stateful, restore now if stateful { if !c.stateful { return fmt.Errorf("Container has no existing state to restore.") } if !c.IsPrivileged() { if err := c.IdmapSet().ShiftRootfs(c.StatePath()); err != nil { return err } } out, err := exec.Command( c.daemon.execPath, "forkmigrate", c.name, c.daemon.lxcpath, configPath, c.StatePath()).CombinedOutput() if string(out) != "" { for _, line := range strings.Split(strings.TrimRight(string(out), "\n"), "\n") { shared.Debugf("forkmigrate: %s", line) } } CollectCRIULogFile(c, c.StatePath(), "snapshot", "restore") if err != nil && !c.IsRunning() { return err } os.RemoveAll(c.StatePath()) c.stateful = false return dbContainerSetStateful(c.daemon.db, c.id, false) } else if c.stateful { /* stateless start required when we have state, let's delete it */ err := os.RemoveAll(c.StatePath()) if err != nil { return err } c.stateful = false err = dbContainerSetStateful(c.daemon.db, c.id, false) if err != nil { return err } } // Start the LXC container out, err := exec.Command( c.daemon.execPath, "forkstart", c.name, c.daemon.lxcpath, configPath).CombinedOutput() if string(out) != "" { for _, line := range strings.Split(strings.TrimRight(string(out), "\n"), "\n") { shared.Debugf("forkstart: %s", line) } } if err != nil && !c.IsRunning() { return fmt.Errorf( "Error calling 'lxd forkstart %s %s %s': err='%v'", c.name, c.daemon.lxcpath, filepath.Join(c.LogPath(), "lxc.conf"), err) } return nil } func (c *containerLXC) StartFromMigration(imagesDir string) error { // Run the shared start code configPath, err := c.startCommon() if err != nil { return err } // Start the LXC container out, err := exec.Command( c.daemon.execPath, "forkmigrate", c.name, c.daemon.lxcpath, configPath, imagesDir).CombinedOutput() if string(out) != "" { for _, line := range strings.Split(strings.TrimRight(string(out), "\n"), "\n") { shared.Debugf("forkmigrate: %s", line) } } if err != nil && !c.IsRunning() { return fmt.Errorf( "Error calling 'lxd forkmigrate %s %s %s %s': err='%v'", c.name, c.daemon.lxcpath, filepath.Join(c.LogPath(), "lxc.conf"), imagesDir, err) } return nil } func (c *containerLXC) OnStart() error { // Make sure we can't call go-lxc functions by mistake c.fromHook = true // Start the storage for this container err := c.StorageStart() if err != nil { return err } // Load the container AppArmor profile err = AALoadProfile(c) if err != nil { c.StorageStop() return err } // Template anything that needs templating key := "volatile.apply_template" if c.localConfig[key] != "" { // Run any template that needs running err = c.templateApplyNow(c.localConfig[key]) if err != nil { c.StorageStop() return err } // Remove the volatile key from the DB err := dbContainerConfigRemove(c.daemon.db, c.id, key) if err != nil { c.StorageStop() return err } } err = c.templateApplyNow("start") if err != nil { c.StorageStop() return err } // Trigger a rebalance deviceTaskSchedulerTrigger("container", c.name, "started") // Apply network priority if c.expandedConfig["limits.network.priority"] != "" { go func(c *containerLXC) { c.fromHook = false err := c.setNetworkPriority() if err != nil { shared.Log.Error("Failed to apply network priority", log.Ctx{"container": c.name, "err": err}) } }(c) } // Apply network limits for name, m := range c.expandedDevices { if m["type"] != "nic" { continue } if m["limits.max"] == "" && m["limits.ingress"] == "" && m["limits.egress"] == "" { continue } go func(c *containerLXC, name string, m shared.Device) { c.fromHook = false err = c.setNetworkLimits(name, m) if err != nil { shared.Log.Error("Failed to apply network limits", log.Ctx{"container": c.name, "err": err}) } }(c, name, m) } return nil } // Container shutdown locking func (c *containerLXC) setupStopping() *sync.WaitGroup { // Handle locking lxcStoppingContainersLock.Lock() defer lxcStoppingContainersLock.Unlock() // Existing entry wg, stopping := lxcStoppingContainers[c.id] if stopping { return wg } // Setup new entry lxcStoppingContainers[c.id] = &sync.WaitGroup{} go func(wg *sync.WaitGroup, id int) { wg.Wait() lxcStoppingContainersLock.Lock() defer lxcStoppingContainersLock.Unlock() delete(lxcStoppingContainers, id) }(lxcStoppingContainers[c.id], c.id) return lxcStoppingContainers[c.id] } // Stop functions func (c *containerLXC) Stop(stateful bool) error { // Handle stateful stop if stateful { // Cleanup any existing state stateDir := c.StatePath() os.RemoveAll(stateDir) err := os.MkdirAll(stateDir, 0700) if err != nil { return err } // Checkpoint opts := lxc.CheckpointOptions{Directory: stateDir, Stop: true, Verbose: true} err = c.Checkpoint(opts) err2 := CollectCRIULogFile(c, stateDir, "snapshot", "dump") if err2 != nil { shared.Log.Warn("failed to collect criu log file", log.Ctx{"error": err2}) } if err != nil { return err } c.stateful = true err = dbContainerSetStateful(c.daemon.db, c.id, true) if err != nil { return err } return nil } // Load the go-lxc struct err := c.initLXC() if err != nil { return err } // Attempt to freeze the container first, helps massively with fork bombs c.Freeze() // Handle locking wg := c.setupStopping() // Stop the container wg.Add(1) if err := c.c.Stop(); err != nil { wg.Done() return err } // Mark ourselves as done wg.Done() // Wait for any other teardown routines to finish wg.Wait() return nil } func (c *containerLXC) Shutdown(timeout time.Duration) error { // Load the go-lxc struct err := c.initLXC() if err != nil { return err } // Handle locking wg := c.setupStopping() // Shutdown the container wg.Add(1) if err := c.c.Shutdown(timeout); err != nil { wg.Done() return err } // Mark ourselves as done wg.Done() // Wait for any other teardown routines to finish wg.Wait() return nil } func (c *containerLXC) OnStop(target string) error { // Get locking lxcStoppingContainersLock.Lock() wg, stopping := lxcStoppingContainers[c.id] lxcStoppingContainersLock.Unlock() if wg != nil { wg.Add(1) } // Make sure we can't call go-lxc functions by mistake c.fromHook = true // Stop the storage for this container err := c.StorageStop() if err != nil { wg.Done() return err } // Unload the apparmor profile AAUnloadProfile(c) // FIXME: The go routine can go away once we can rely on LXC_TARGET go func(c *containerLXC, target string, wg *sync.WaitGroup) { c.fromHook = false // Unlock on return if wg != nil { defer wg.Done() } if target == "unknown" && stopping { target = "stop" } if target == "unknown" { time.Sleep(5 * time.Second) newContainer, err := containerLoadByName(c.daemon, c.Name()) if err != nil { return } if newContainer.Id() != c.id { return } if newContainer.IsRunning() { return } } // Clean all the unix devices err = c.removeUnixDevices() if err != nil { shared.Log.Error("Unable to remove unix devices", log.Ctx{"err": err}) } // Clean all the disk devices err = c.removeDiskDevices() if err != nil { shared.Log.Error("Unable to remove disk devices", log.Ctx{"err": err}) } // Reboot the container if target == "reboot" { /* This part is a hack to workaround a LXC bug where a failure from a post-stop script doesn't prevent the container to restart. */ ephemeral := c.ephemeral args := containerArgs{ Architecture: c.Architecture(), Config: c.LocalConfig(), Devices: c.LocalDevices(), Ephemeral: false, Profiles: c.Profiles(), } c.Update(args, false) c.Stop(false) args.Ephemeral = ephemeral c.Update(args, true) // Start the container again c.Start(false) return } // Trigger a rebalance deviceTaskSchedulerTrigger("container", c.name, "stopped") // Destroy ephemeral containers if c.ephemeral { c.Delete() } }(c, target, wg) return nil } // Freezer functions func (c *containerLXC) Freeze() error { // Load the go-lxc struct err := c.initLXC() if err != nil { return err } return c.c.Freeze() } func (c *containerLXC) Unfreeze() error { // Load the go-lxc struct err := c.initLXC() if err != nil { return err } return c.c.Unfreeze() } var LxcMonitorStateError = fmt.Errorf("Monitor is hung") // Get lxc container state, with 1 second timeout // If we don't get a reply, assume the lxc monitor is hung func (c *containerLXC) getLxcState() (lxc.State, error) { monitor := make(chan lxc.State, 1) go func(c *lxc.Container) { monitor <- c.State() }(c.c) select { case state := <-monitor: return state, nil case <-time.After(5 * time.Second): return lxc.StateMap["FROZEN"], LxcMonitorStateError } } func (c *containerLXC) Render() (interface{}, error) { // Load the go-lxc struct err := c.initLXC() if err != nil { return nil, err } // Ignore err as the arch string on error is correct (unknown) architectureName, _ := shared.ArchitectureName(c.architecture) if c.IsSnapshot() { return &shared.SnapshotInfo{ Architecture: architectureName, Config: c.localConfig, CreationDate: c.creationDate, Devices: c.localDevices, Ephemeral: c.ephemeral, ExpandedConfig: c.expandedConfig, ExpandedDevices: c.expandedDevices, Name: c.name, Profiles: c.profiles, Stateful: c.stateful, }, nil } else { // FIXME: Render shouldn't directly access the go-lxc struct cState, err := c.getLxcState() if err != nil { return nil, err } statusCode := shared.FromLXCState(int(cState)) return &shared.ContainerInfo{ Architecture: architectureName, Config: c.localConfig, CreationDate: c.creationDate, Devices: c.localDevices, Ephemeral: c.ephemeral, ExpandedConfig: c.expandedConfig, ExpandedDevices: c.expandedDevices, Name: c.name, Profiles: c.profiles, Status: statusCode.String(), StatusCode: statusCode, Stateful: c.stateful, }, nil } } func (c *containerLXC) RenderState() (*shared.ContainerState, error) { // Load the go-lxc struct err := c.initLXC() if err != nil { return nil, err } cState, err := c.getLxcState() if err != nil { return nil, err } statusCode := shared.FromLXCState(int(cState)) status := shared.ContainerState{ Status: statusCode.String(), StatusCode: statusCode, } if c.IsRunning() { pid := c.InitPID() status.Disk = c.diskState() status.Memory = c.memoryState() status.Network = c.networkState() status.Pid = int64(pid) status.Processes = c.processesState() } return &status, nil } func (c *containerLXC) Snapshots() ([]container, error) { // Get all the snapshots snaps, err := dbContainerGetSnapshots(c.daemon.db, c.name) if err != nil { return nil, err } // Build the snapshot list containers := []container{} for _, snapName := range snaps { snap, err := containerLoadByName(c.daemon, snapName) if err != nil { return nil, err } containers = append(containers, snap) } return containers, nil } func (c *containerLXC) Restore(sourceContainer container) error { // Check if we can restore the container err := c.storage.ContainerCanRestore(c, sourceContainer) if err != nil { return err } // Stop the container wasRunning := false if c.IsRunning() { wasRunning = true if err := c.Stop(false); err != nil { shared.Log.Error( "Could not stop container", log.Ctx{ "container": c.Name(), "err": err}) return err } } // Restore the rootfs err = c.storage.ContainerRestore(c, sourceContainer) if err != nil { shared.Log.Error("Restoring the filesystem failed", log.Ctx{ "source": sourceContainer.Name(), "destination": c.Name()}) return err } // Restore the configuration args := containerArgs{ Architecture: sourceContainer.Architecture(), Config: sourceContainer.LocalConfig(), Devices: sourceContainer.LocalDevices(), Ephemeral: sourceContainer.IsEphemeral(), Profiles: sourceContainer.Profiles(), } err = c.Update(args, false) if err != nil { shared.Log.Error("Restoring the configuration failed", log.Ctx{ "source": sourceContainer.Name(), "destination": c.Name()}) return err } // If the container wasn't running but was stateful, should we restore // it as running? if shared.PathExists(c.StatePath()) { configPath, err := c.startCommon() if err != nil { return err } if !c.IsPrivileged() { if err := c.IdmapSet().ShiftRootfs(c.StatePath()); err != nil { return err } } out, err := exec.Command( c.daemon.execPath, "forkmigrate", c.name, c.daemon.lxcpath, configPath, c.StatePath()).CombinedOutput() if string(out) != "" { for _, line := range strings.Split(strings.TrimRight(string(out), "\n"), "\n") { shared.Debugf("forkmigrate: %s", line) } } CollectCRIULogFile(c, c.StatePath(), "snapshot", "restore") if err != nil { return err } // Remove the state from the parent container; we only keep // this in snapshots. err2 := os.RemoveAll(c.StatePath()) if err2 != nil { shared.Log.Error("failed to delete snapshot state", "path", c.StatePath(), "err", err2) } if err != nil { return err } return nil } // Restart the container if wasRunning { return c.Start(false) } return nil } func (c *containerLXC) cleanup() { // Unmount any leftovers c.removeUnixDevices() c.removeDiskDevices() // Remove the security profiles AADeleteProfile(c) SeccompDeleteProfile(c) // Remove the devices path os.RemoveAll(c.DevicesPath()) // Remove the shmounts path os.RemoveAll(shared.VarPath("shmounts", c.Name())) } func (c *containerLXC) Delete() error { if c.IsSnapshot() { // Remove the snapshot if err := c.storage.ContainerSnapshotDelete(c); err != nil { shared.Log.Warn("failed to delete snapshot", "name", c.Name(), "err", err) } } else { // Remove all snapshot if err := containerDeleteSnapshots(c.daemon, c.Name()); err != nil { shared.Log.Warn("failed to delete snapshots", "name", c.Name(), "err", err) } // Clean things up c.cleanup() // Delete the container from disk if shared.PathExists(c.Path()) { if err := c.storage.ContainerDelete(c); err != nil { return err } } } // Remove the database record if err := dbContainerRemove(c.daemon.db, c.Name()); err != nil { return err } return nil } func (c *containerLXC) Rename(newName string) error { oldName := c.Name() // Sanity checks if !c.IsSnapshot() && !shared.ValidHostname(newName) { return fmt.Errorf("Invalid container name") } if c.IsRunning() { return fmt.Errorf("renaming of running container not allowed") } // Clean things up c.cleanup() // Rename the logging path os.RemoveAll(shared.LogPath(newName)) err := os.Rename(c.LogPath(), shared.LogPath(newName)) if err != nil { return err } // Rename the storage entry if c.IsSnapshot() { if err := c.storage.ContainerSnapshotRename(c, newName); err != nil { return err } } else { if err := c.storage.ContainerRename(c, newName); err != nil { return err } } // Rename the database entry if err := dbContainerRename(c.daemon.db, oldName, newName); err != nil { return err } if !c.IsSnapshot() { // Rename all the snapshots results, err := dbContainerGetSnapshots(c.daemon.db, oldName) if err != nil { return err } for _, sname := range results { // Rename the snapshot baseSnapName := filepath.Base(sname) newSnapshotName := newName + shared.SnapshotDelimiter + baseSnapName if err := dbContainerRename(c.daemon.db, sname, newSnapshotName); err != nil { return err } } } // Set the new name in the struct c.name = newName // Invalidate the go-lxc cache c.c = nil return nil } func (c *containerLXC) CGroupGet(key string) (string, error) { // Load the go-lxc struct err := c.initLXC() if err != nil { return "", err } // Make sure the container is running if !c.IsRunning() { return "", fmt.Errorf("Can't get cgroups on a stopped container") } value := c.c.CgroupItem(key) return strings.Join(value, "\n"), nil } func (c *containerLXC) CGroupSet(key string, value string) error { // Load the go-lxc struct err := c.initLXC() if err != nil { return err } // Make sure the container is running if !c.IsRunning() { return fmt.Errorf("Can't set cgroups on a stopped container") } err = c.c.SetCgroupItem(key, value) if err != nil { return fmt.Errorf("Failed to set cgroup %s=\"%s\": %s", key, value, err) } return nil } func (c *containerLXC) ConfigKeySet(key string, value string) error { c.localConfig[key] = value args := containerArgs{ Architecture: c.architecture, Config: c.localConfig, Devices: c.localDevices, Ephemeral: c.ephemeral, Profiles: c.profiles, } return c.Update(args, false) } func (c *containerLXC) Update(args containerArgs, userRequested bool) error { // Set sane defaults for unset keys if args.Architecture == 0 { args.Architecture = c.architecture } if args.Config == nil { args.Config = map[string]string{} } if args.Devices == nil { args.Devices = shared.Devices{} } if args.Profiles == nil { args.Profiles = []string{} } // Validate the new config err := containerValidConfig(args.Config, false, false) if err != nil { return err } // Validate the new devices err = containerValidDevices(args.Devices, false, false) if err != nil { return err } // Validate the new profiles profiles, err := dbProfiles(c.daemon.db) if err != nil { return err } for _, name := range args.Profiles { if !shared.StringInSlice(name, profiles) { return fmt.Errorf("Profile doesn't exist: %s", name) } } // Validate the new architecture if args.Architecture != 0 { _, err = shared.ArchitectureName(args.Architecture) if err != nil { return fmt.Errorf("Invalid architecture id: %s", err) } } // Check that volatile wasn't modified if userRequested { for k, v := range args.Config { if strings.HasPrefix(k, "volatile.") && c.localConfig[k] != v { return fmt.Errorf("Volatile keys are read-only.") } } for k, v := range c.localConfig { if strings.HasPrefix(k, "volatile.") && args.Config[k] != v { return fmt.Errorf("Volatile keys are read-only.") } } } // Get a copy of the old configuration oldArchitecture := 0 err = shared.DeepCopy(&c.architecture, &oldArchitecture) if err != nil { return err } oldEphemeral := false err = shared.DeepCopy(&c.ephemeral, &oldEphemeral) if err != nil { return err } oldExpandedDevices := shared.Devices{} err = shared.DeepCopy(&c.expandedDevices, &oldExpandedDevices) if err != nil { return err } oldExpandedConfig := map[string]string{} err = shared.DeepCopy(&c.expandedConfig, &oldExpandedConfig) if err != nil { return err } oldLocalDevices := shared.Devices{} err = shared.DeepCopy(&c.localDevices, &oldLocalDevices) if err != nil { return err } oldLocalConfig := map[string]string{} err = shared.DeepCopy(&c.localConfig, &oldLocalConfig) if err != nil { return err } oldProfiles := []string{} err = shared.DeepCopy(&c.profiles, &oldProfiles) if err != nil { return err } // Define a function which reverts everything undoChanges := func() { c.architecture = oldArchitecture c.ephemeral = oldEphemeral c.expandedConfig = oldExpandedConfig c.expandedDevices = oldExpandedDevices c.localConfig = oldLocalConfig c.localDevices = oldLocalDevices c.profiles = oldProfiles c.initLXC() deviceTaskSchedulerTrigger("container", c.name, "changed") } // Apply the various changes c.architecture = args.Architecture c.ephemeral = args.Ephemeral c.localConfig = args.Config c.localDevices = args.Devices c.profiles = args.Profiles // Expand the config and refresh the LXC config err = c.expandConfig() if err != nil { undoChanges() return err } err = c.expandDevices() if err != nil { undoChanges() return err } err = c.initLXC() if err != nil { undoChanges() return err } // Diff the configurations changedConfig := []string{} for key, _ := range oldExpandedConfig { if oldExpandedConfig[key] != c.expandedConfig[key] { if !shared.StringInSlice(key, changedConfig) { changedConfig = append(changedConfig, key) } } } for key, _ := range c.expandedConfig { if oldExpandedConfig[key] != c.expandedConfig[key] { if !shared.StringInSlice(key, changedConfig) { changedConfig = append(changedConfig, key) } } } // Diff the devices removeDevices, addDevices, updateDevices := oldExpandedDevices.Update(c.expandedDevices) // Do some validation of the config diff err = containerValidConfig(c.expandedConfig, false, true) if err != nil { undoChanges() return err } // Do some validation of the devices diff err = containerValidDevices(c.expandedDevices, false, true) if err != nil { undoChanges() return err } // If apparmor changed, re-validate the apparmor profile for _, key := range changedConfig { if key == "raw.apparmor" || key == "security.nesting" { err = AAParseProfile(c) if err != nil { undoChanges() return err } } } // Apply disk quota changes for _, m := range addDevices { var oldRootfsSize string for _, m := range oldExpandedDevices { if m["type"] == "disk" && m["path"] == "/" { oldRootfsSize = m["size"] break } } if m["size"] != oldRootfsSize { size, err := shared.ParseByteSizeString(m["size"]) if err != nil { undoChanges() return err } err = c.storage.ContainerSetQuota(c, size) if err != nil { undoChanges() return err } } } // Apply the live changes if c.IsRunning() { // Confirm that the rootfs source didn't change var oldRootfs shared.Device for _, m := range oldExpandedDevices { if m["type"] == "disk" && m["path"] == "/" { oldRootfs = m break } } var newRootfs shared.Device for _, m := range c.expandedDevices { if m["type"] == "disk" && m["path"] == "/" { newRootfs = m break } } if oldRootfs["source"] != newRootfs["source"] { undoChanges() return fmt.Errorf("Cannot change the rootfs path of a running container") } // Live update the container config for _, key := range changedConfig { value := c.expandedConfig[key] if key == "raw.apparmor" || key == "security.nesting" { // Update the AppArmor profile err = AALoadProfile(c) if err != nil { undoChanges() return err } } else if key == "linux.kernel_modules" && value != "" { for _, module := range strings.Split(value, ",") { module = strings.TrimPrefix(module, " ") out, err := exec.Command("modprobe", module).CombinedOutput() if err != nil { undoChanges() return fmt.Errorf("Failed to load kernel module '%s': %s", module, out) } } } else if key == "limits.disk.priority" { if !cgBlkioController { continue } priorityInt := 5 diskPriority := c.expandedConfig["limits.disk.priority"] if diskPriority != "" { priorityInt, err = strconv.Atoi(diskPriority) if err != nil { return err } } err = c.CGroupSet("blkio.weight", fmt.Sprintf("%d", priorityInt*100)) if err != nil { return err } } else if key == "limits.memory" || strings.HasPrefix(key, "limits.memory.") { // Skip if no memory CGroup if !cgMemoryController { continue } // Set the new memory limit memory := c.expandedConfig["limits.memory"] memoryEnforce := c.expandedConfig["limits.memory.enforce"] memorySwap := c.expandedConfig["limits.memory.swap"] // Parse memory if memory == "" { memory = "-1" } else if strings.HasSuffix(memory, "%") { percent, err := strconv.ParseInt(strings.TrimSuffix(memory, "%"), 10, 64) if err != nil { return err } memoryTotal, err := deviceTotalMemory() if err != nil { return err } memory = fmt.Sprintf("%d", int64((memoryTotal/100)*percent)) } else { valueInt, err := shared.ParseByteSizeString(memory) if err != nil { undoChanges() return err } memory = fmt.Sprintf("%d", valueInt) } // Reset everything if cgSwapAccounting { err = c.CGroupSet("memory.memsw.limit_in_bytes", "-1") if err != nil { undoChanges() return err } } err = c.CGroupSet("memory.limit_in_bytes", "-1") if err != nil { undoChanges() return err } err = c.CGroupSet("memory.soft_limit_in_bytes", "-1") if err != nil { undoChanges() return err } // Set the new values if memoryEnforce == "soft" { // Set new limit err = c.CGroupSet("memory.soft_limit_in_bytes", memory) if err != nil { undoChanges() return err } } else { if memorySwap != "false" && cgSwapAccounting { err = c.CGroupSet("memory.limit_in_bytes", memory) if err != nil { undoChanges() return err } err = c.CGroupSet("memory.memsw.limit_in_bytes", memory) if err != nil { undoChanges() return err } } else { err = c.CGroupSet("memory.limit_in_bytes", memory) if err != nil { undoChanges() return err } } } // Configure the swappiness if key == "limits.memory.swap" || key == "limits.memory.swap.priority" { memorySwap := c.expandedConfig["limits.memory.swap"] memorySwapPriority := c.expandedConfig["limits.memory.swap.priority"] if memorySwap == "false" { err = c.CGroupSet("memory.swappiness", "0") if err != nil { undoChanges() return err } } else { priority := 0 if memorySwapPriority != "" { priority, err = strconv.Atoi(memorySwapPriority) if err != nil { undoChanges() return err } } err = c.CGroupSet("memory.swappiness", fmt.Sprintf("%d", 60-10+priority)) if err != nil { undoChanges() return err } } } } else if key == "limits.network.priority" { err := c.setNetworkPriority() if err != nil { return err } } else if key == "limits.cpu" { // Trigger a scheduler re-run deviceTaskSchedulerTrigger("container", c.name, "changed") } else if key == "limits.cpu.priority" || key == "limits.cpu.allowance" { // Skip if no cpu CGroup if !cgCpuController { continue } // Apply new CPU limits cpuShares, cpuCfsQuota, cpuCfsPeriod, err := deviceParseCPU(c.expandedConfig["limits.cpu.allowance"], c.expandedConfig["limits.cpu.priority"]) if err != nil { undoChanges() return err } err = c.CGroupSet("cpu.shares", cpuShares) if err != nil { undoChanges() return err } err = c.CGroupSet("cpu.cfs_period_us", cpuCfsPeriod) if err != nil { undoChanges() return err } err = c.CGroupSet("cpu.cfs_quota_us", cpuCfsQuota) if err != nil { undoChanges() return err } } else if key == "limits.processes" { if !cgPidsController { continue } if value == "" { err = c.CGroupSet("pids.max", "max") if err != nil { undoChanges() return err } } else { valueInt, err := strconv.ParseInt(value, 10, 64) if err != nil { undoChanges() return err } err = c.CGroupSet("pids.max", fmt.Sprintf("%d", valueInt)) if err != nil { undoChanges() return err } } } } // Live update the devices for k, m := range removeDevices { if shared.StringInSlice(m["type"], []string{"unix-char", "unix-block"}) { err = c.removeUnixDevice(k, m) if err != nil { undoChanges() return err } } else if m["type"] == "disk" && m["path"] != "/" { err = c.removeDiskDevice(k, m) if err != nil { undoChanges() return err } } else if m["type"] == "nic" { err = c.removeNetworkDevice(k, m) if err != nil { undoChanges() return err } } } for k, m := range addDevices { if shared.StringInSlice(m["type"], []string{"unix-char", "unix-block"}) { err = c.insertUnixDevice(k, m) if err != nil { undoChanges() return err } } else if m["type"] == "disk" && m["path"] != "/" { err = c.insertDiskDevice(k, m) if err != nil { undoChanges() return err } } else if m["type"] == "nic" { err = c.insertNetworkDevice(k, m) if err != nil { undoChanges() return err } } } updateDiskLimit := false for k, m := range updateDevices { if m["type"] == "disk" { updateDiskLimit = true } else if m["type"] == "nic" { err = c.setNetworkLimits(k, m) if err != nil { undoChanges() return err } } } // Disk limits parse all devices, so just apply them once if updateDiskLimit && cgBlkioController { diskLimits, err := c.getDiskLimits() if err != nil { undoChanges() return err } for block, limit := range diskLimits { err = c.CGroupSet("blkio.throttle.read_bps_device", fmt.Sprintf("%s %d", block, limit.readBps)) if err != nil { undoChanges() return err } err = c.CGroupSet("blkio.throttle.read_iops_device", fmt.Sprintf("%s %d", block, limit.readIops)) if err != nil { undoChanges() return err } err = c.CGroupSet("blkio.throttle.write_bps_device", fmt.Sprintf("%s %d", block, limit.writeBps)) if err != nil { undoChanges() return err } err = c.CGroupSet("blkio.throttle.write_iops_device", fmt.Sprintf("%s %d", block, limit.writeIops)) if err != nil { undoChanges() return err } } } } // Finally, apply the changes to the database tx, err := dbBegin(c.daemon.db) if err != nil { undoChanges() return err } err = dbContainerConfigClear(tx, c.id) if err != nil { tx.Rollback() undoChanges() return err } err = dbContainerConfigInsert(tx, c.id, args.Config) if err != nil { tx.Rollback() undoChanges() return err } err = dbContainerProfilesInsert(tx, c.id, args.Profiles) if err != nil { tx.Rollback() undoChanges() return err } err = dbDevicesAdd(tx, "container", int64(c.id), args.Devices) if err != nil { tx.Rollback() undoChanges() return err } err = dbContainerUpdate(tx, c.id, c.architecture, c.ephemeral) if err != nil { tx.Rollback() undoChanges() return err } if err := txCommit(tx); err != nil { undoChanges() return err } return nil } func (c *containerLXC) Export(w io.Writer) error { if c.IsRunning() { return fmt.Errorf("Cannot export a running container as an image") } // Start the storage err := c.StorageStart() if err != nil { return err } defer c.StorageStop() // Unshift the container idmap, err := c.LastIdmapSet() if err != nil { return err } if idmap != nil { if err := idmap.UnshiftRootfs(c.RootfsPath()); err != nil { return err } defer idmap.ShiftRootfs(c.RootfsPath()) } // Create the tarball tw := tar.NewWriter(w) // Keep track of the first path we saw for each path with nlink>1 linkmap := map[uint64]string{} cDir := c.Path() // Path inside the tar image is the pathname starting after cDir offset := len(cDir) + 1 writeToTar := func(path string, fi os.FileInfo, err error) error { if err := c.tarStoreFile(linkmap, offset, tw, path, fi); err != nil { shared.Debugf("Error tarring up %s: %s", path, err) return err } return nil } // Look for metadata.yaml fnam := filepath.Join(cDir, "metadata.yaml") if !shared.PathExists(fnam) { // Generate a new metadata.yaml f, err := ioutil.TempFile("", "lxd_lxd_metadata_") if err != nil { tw.Close() return err } defer os.Remove(f.Name()) // Get the container's architecture var arch string if c.IsSnapshot() { parentName := strings.SplitN(c.name, shared.SnapshotDelimiter, 2)[0] parent, err := containerLoadByName(c.daemon, parentName) if err != nil { tw.Close() return err } arch, _ = shared.ArchitectureName(parent.Architecture()) } else { arch, _ = shared.ArchitectureName(c.architecture) } if arch == "" { arch, err = shared.ArchitectureName(c.daemon.architectures[0]) if err != nil { return err } } // Fill in the metadata meta := imageMetadata{} meta.Architecture = arch meta.CreationDate = time.Now().UTC().Unix() data, err := yaml.Marshal(&meta) if err != nil { tw.Close() return err } // Write the actual file f.Write(data) f.Close() fi, err := os.Lstat(f.Name()) if err != nil { tw.Close() return err } tmpOffset := len(path.Dir(f.Name())) + 1 if err := c.tarStoreFile(linkmap, tmpOffset, tw, f.Name(), fi); err != nil { shared.Debugf("Error writing to tarfile: %s", err) tw.Close() return err } fnam = f.Name() } else { // Include metadata.yaml in the tarball fi, err := os.Lstat(fnam) if err != nil { shared.Debugf("Error statting %s during export", fnam) tw.Close() return err } if err := c.tarStoreFile(linkmap, offset, tw, fnam, fi); err != nil { shared.Debugf("Error writing to tarfile: %s", err) tw.Close() return err } } // Include all the rootfs files fnam = c.RootfsPath() filepath.Walk(fnam, writeToTar) // Include all the templates fnam = c.TemplatesPath() if shared.PathExists(fnam) { filepath.Walk(fnam, writeToTar) } return tw.Close() } func (c *containerLXC) Checkpoint(opts lxc.CheckpointOptions) error { // Load the go-lxc struct err := c.initLXC() if err != nil { return err } return c.c.Checkpoint(opts) } func (c *containerLXC) TemplateApply(trigger string) error { // "create" and "copy" are deferred until next start if shared.StringInSlice(trigger, []string{"create", "copy"}) { // The two events are mutually exclusive so only keep the last one err := c.ConfigKeySet("volatile.apply_template", trigger) if err != nil { return err } } return c.templateApplyNow(trigger) } func (c *containerLXC) templateApplyNow(trigger string) error { // If there's no metadata, just return fname := filepath.Join(c.Path(), "metadata.yaml") if !shared.PathExists(fname) { return nil } // Parse the metadata content, err := ioutil.ReadFile(fname) if err != nil { return err } metadata := new(imageMetadata) err = yaml.Unmarshal(content, &metadata) if err != nil { return fmt.Errorf("Could not parse %s: %v", fname, err) } // Go through the templates for templatePath, template := range metadata.Templates { var w *os.File // Check if the template should be applied now found := false for _, tplTrigger := range template.When { if tplTrigger == trigger { found = true break } } if !found { continue } // Open the file to template, create if needed fullpath := filepath.Join(c.RootfsPath(), strings.TrimLeft(templatePath, "/")) if shared.PathExists(fullpath) { if template.CreateOnly { continue } // Open the existing file w, err = os.Create(fullpath) if err != nil { return err } } else { // Create a new one uid := 0 gid := 0 // Get the right uid and gid for the container if !c.IsPrivileged() { uid, gid = c.idmapset.ShiftIntoNs(0, 0) } // Create the directories leading to the file shared.MkdirAllOwner(path.Dir(fullpath), 0755, uid, gid) // Create the file itself w, err = os.Create(fullpath) if err != nil { return err } // Fix ownership and mode if !c.IsPrivileged() { w.Chown(uid, gid) } w.Chmod(0644) } defer w.Close() // Read the template tplString, err := ioutil.ReadFile(filepath.Join(c.TemplatesPath(), template.Template)) if err != nil { return err } tpl, err := pongo2.FromString("{% autoescape off %}" + string(tplString) + "{% endautoescape %}") if err != nil { return err } // Figure out the architecture arch, err := shared.ArchitectureName(c.architecture) if err != nil { arch, err = shared.ArchitectureName(c.daemon.architectures[0]) if err != nil { return err } } // Generate the metadata containerMeta := make(map[string]string) containerMeta["name"] = c.name containerMeta["architecture"] = arch if c.ephemeral { containerMeta["ephemeral"] = "true" } else { containerMeta["ephemeral"] = "false" } if c.IsPrivileged() { containerMeta["privileged"] = "true" } else { containerMeta["privileged"] = "false" } configGet := func(confKey, confDefault *pongo2.Value) *pongo2.Value { val, ok := c.expandedConfig[confKey.String()] if !ok { return confDefault } return pongo2.AsValue(strings.TrimRight(val, "\r\n")) } // Render the template tpl.ExecuteWriter(pongo2.Context{"trigger": trigger, "path": templatePath, "container": containerMeta, "config": c.expandedConfig, "devices": c.expandedDevices, "properties": template.Properties, "config_get": configGet}, w) } return nil } func (c *containerLXC) FilePull(srcpath string, dstpath string) (int, int, os.FileMode, error) { // Setup container storage if needed if !c.IsRunning() { err := c.StorageStart() if err != nil { return -1, -1, 0, err } } // Get the file from the container out, err := exec.Command( c.daemon.execPath, "forkgetfile", c.RootfsPath(), fmt.Sprintf("%d", c.InitPID()), dstpath, srcpath, ).CombinedOutput() // Tear down container storage if needed if !c.IsRunning() { err := c.StorageStop() if err != nil { return -1, -1, 0, err } } uid := -1 gid := -1 mode := -1 // Process forkgetfile response for _, line := range strings.Split(strings.TrimRight(string(out), "\n"), "\n") { if line == "" { continue } // Extract errors if strings.HasPrefix(line, "error: ") { return -1, -1, 0, fmt.Errorf(strings.TrimPrefix(line, "error: ")) } // Extract the uid if strings.HasPrefix(line, "uid: ") { uid, err = strconv.Atoi(strings.TrimPrefix(line, "uid: ")) if err != nil { return -1, -1, 0, err } continue } // Extract the gid if strings.HasPrefix(line, "gid: ") { gid, err = strconv.Atoi(strings.TrimPrefix(line, "gid: ")) if err != nil { return -1, -1, 0, err } continue } // Extract the mode if strings.HasPrefix(line, "mode: ") { mode, err = strconv.Atoi(strings.TrimPrefix(line, "mode: ")) if err != nil { return -1, -1, 0, err } continue } shared.Debugf("forkgetfile: %s", line) } if err != nil { return -1, -1, 0, fmt.Errorf( "Error calling 'lxd forkgetfile %s %d %s': err='%v'", dstpath, c.InitPID(), srcpath, err) } // Unmap uid and gid if needed idmapset, err := c.LastIdmapSet() if err != nil { return -1, -1, 0, err } if idmapset != nil { uid, gid = idmapset.ShiftFromNs(uid, gid) } return uid, gid, os.FileMode(mode), nil } func (c *containerLXC) FilePush(srcpath string, dstpath string, uid int, gid int, mode os.FileMode) error { // Map uid and gid if needed idmapset, err := c.LastIdmapSet() if err != nil { return err } if idmapset != nil { uid, gid = idmapset.ShiftIntoNs(uid, gid) } // Setup container storage if needed if !c.IsRunning() { err := c.StorageStart() if err != nil { return err } } // Push the file to the container out, err := exec.Command( c.daemon.execPath, "forkputfile", c.RootfsPath(), fmt.Sprintf("%d", c.InitPID()), srcpath, dstpath, fmt.Sprintf("%d", uid), fmt.Sprintf("%d", gid), fmt.Sprintf("%d", mode&os.ModePerm), ).CombinedOutput() // Tear down container storage if needed if !c.IsRunning() { err := c.StorageStop() if err != nil { return err } } // Process forkputfile response if string(out) != "" { if strings.HasPrefix(string(out), "error:") { return fmt.Errorf(strings.TrimPrefix(strings.TrimSuffix(string(out), "\n"), "error: ")) } for _, line := range strings.Split(strings.TrimRight(string(out), "\n"), "\n") { shared.Debugf("forkgetfile: %s", line) } } if err != nil { return fmt.Errorf( "Error calling 'lxd forkputfile %s %d %s %d %d %d': err='%v'", srcpath, c.InitPID(), dstpath, uid, gid, mode, err) } return nil } func (c *containerLXC) Exec(command []string, env map[string]string, stdin *os.File, stdout *os.File, stderr *os.File) (int, error) { envSlice := []string{} for k, v := range env { envSlice = append(envSlice, fmt.Sprintf("%s=%s", k, v)) } args := []string{c.daemon.execPath, "forkexec", c.name, c.daemon.lxcpath, filepath.Join(c.LogPath(), "lxc.conf")} args = append(args, "--") args = append(args, "env") args = append(args, envSlice...) args = append(args, "--") args = append(args, "cmd") args = append(args, command...) cmd := exec.Cmd{} cmd.Path = c.daemon.execPath cmd.Args = args cmd.Stdin = stdin cmd.Stdout = stdout cmd.Stderr = stderr err := cmd.Run() if err != nil { exitErr, ok := err.(*exec.ExitError) if ok { status, ok := exitErr.Sys().(syscall.WaitStatus) if ok { return status.ExitStatus(), nil } } return -1, err } return 0, nil } func (c *containerLXC) diskState() map[string]shared.ContainerStateDisk { disk := map[string]shared.ContainerStateDisk{} for name, d := range c.expandedDevices { if d["type"] != "disk" { continue } if d["path"] != "/" { continue } usage, err := c.storage.ContainerGetUsage(c) if err != nil { continue } disk[name] = shared.ContainerStateDisk{Usage: usage} } return disk } func (c *containerLXC) memoryState() shared.ContainerStateMemory { memory := shared.ContainerStateMemory{} if !cgMemoryController { return memory } // Memory in bytes value, err := c.CGroupGet("memory.usage_in_bytes") valueInt, err := strconv.ParseInt(value, 10, 64) if err != nil { valueInt = -1 } memory.Usage = valueInt // Memory peak in bytes value, err = c.CGroupGet("memory.max_usage_in_bytes") valueInt, err = strconv.ParseInt(value, 10, 64) if err != nil { valueInt = -1 } memory.UsagePeak = valueInt if cgSwapAccounting { // Swap in bytes value, err := c.CGroupGet("memory.memsw.usage_in_bytes") valueInt, err := strconv.ParseInt(value, 10, 64) if err != nil { valueInt = -1 } memory.SwapUsage = valueInt - memory.Usage // Swap peak in bytes value, err = c.CGroupGet("memory.memsw.max_usage_in_bytes") valueInt, err = strconv.ParseInt(value, 10, 64) if err != nil { valueInt = -1 } memory.SwapUsagePeak = valueInt - memory.UsagePeak } return memory } func (c *containerLXC) networkState() map[string]shared.ContainerStateNetwork { result := map[string]shared.ContainerStateNetwork{} pid := c.InitPID() if pid < 1 { return result } // Get the network state from the container out, err := exec.Command( c.daemon.execPath, "forkgetnet", fmt.Sprintf("%d", pid)).CombinedOutput() // Process forkgetnet response if err != nil { shared.Log.Error("Error calling 'lxd forkgetnet", log.Ctx{"container": c.name, "output": string(out), "pid": pid}) return result } networks := map[string]shared.ContainerStateNetwork{} err = json.Unmarshal(out, &networks) if err != nil { shared.Log.Error("Failure to read forkgetnet json", log.Ctx{"container": c.name, "err": err}) return result } // Add HostName field for netName, net := range networks { net.HostName = c.getHostInterface(netName) result[netName] = net } return result } func (c *containerLXC) processesState() int64 { // Return 0 if not running pid := c.InitPID() if pid == -1 { return 0 } if cgPidsController { value, err := c.CGroupGet("pids.current") valueInt, err := strconv.ParseInt(value, 10, 64) if err != nil { return -1 } return valueInt } pids := []int64{int64(pid)} // Go through the pid list, adding new pids at the end so we go through them all for i := 0; i < len(pids); i++ { fname := fmt.Sprintf("/proc/%d/task/%d/children", pids[i], pids[i]) fcont, err := ioutil.ReadFile(fname) if err != nil { // the process terminated during execution of this loop continue } content := strings.Split(string(fcont), " ") for j := 0; j < len(content); j++ { pid, err := strconv.ParseInt(content[j], 10, 64) if err == nil { pids = append(pids, pid) } } } return int64(len(pids)) } func (c *containerLXC) tarStoreFile(linkmap map[uint64]string, offset int, tw *tar.Writer, path string, fi os.FileInfo) error { var err error var major, minor, nlink int var ino uint64 link := "" if fi.Mode()&os.ModeSymlink == os.ModeSymlink { link, err = os.Readlink(path) if err != nil { return err } } hdr, err := tar.FileInfoHeader(fi, link) if err != nil { return err } hdr.Name = path[offset:] if fi.IsDir() || fi.Mode()&os.ModeSymlink == os.ModeSymlink { hdr.Size = 0 } else { hdr.Size = fi.Size() } hdr.Uid, hdr.Gid, major, minor, ino, nlink, err = shared.GetFileStat(path) if err != nil { return fmt.Errorf("error getting file info: %s", err) } // Unshift the id under /rootfs/ for unpriv containers if !c.IsPrivileged() && strings.HasPrefix(hdr.Name, "/rootfs") { hdr.Uid, hdr.Gid = c.idmapset.ShiftFromNs(hdr.Uid, hdr.Gid) if hdr.Uid == -1 || hdr.Gid == -1 { return nil } } if major != -1 { hdr.Devmajor = int64(major) hdr.Devminor = int64(minor) } // If it's a hardlink we've already seen use the old name if fi.Mode().IsRegular() && nlink > 1 { if firstpath, found := linkmap[ino]; found { hdr.Typeflag = tar.TypeLink hdr.Linkname = firstpath hdr.Size = 0 } else { linkmap[ino] = hdr.Name } } // TODO: handle xattrs if err := tw.WriteHeader(hdr); err != nil { return fmt.Errorf("error writing header: %s", err) } if hdr.Typeflag == tar.TypeReg { f, err := os.Open(path) if err != nil { return fmt.Errorf("tarStoreFile: error opening file: %s", err) } defer f.Close() if _, err := io.Copy(tw, f); err != nil { return fmt.Errorf("error copying file %s", err) } } return nil } // Storage functions func (c *containerLXC) Storage() storage { return c.storage } func (c *containerLXC) StorageStart() error { if c.IsSnapshot() { return c.storage.ContainerSnapshotStart(c) } return c.storage.ContainerStart(c) } func (c *containerLXC) StorageStop() error { if c.IsSnapshot() { return c.storage.ContainerSnapshotStop(c) } return c.storage.ContainerStop(c) } // Mount handling func (c *containerLXC) insertMount(source, target, fstype string, flags int) error { var err error // Get the init PID pid := c.InitPID() if pid == -1 { // Container isn't running return fmt.Errorf("Can't insert mount into stopped container") } // Create the temporary mount target var tmpMount string if shared.IsDir(source) { tmpMount, err = ioutil.TempDir(shared.VarPath("shmounts", c.name), "lxdmount_") if err != nil { return fmt.Errorf("Failed to create shmounts path: %s", err) } } else { f, err := ioutil.TempFile(shared.VarPath("shmounts", c.name), "lxdmount_") if err != nil { return fmt.Errorf("Failed to create shmounts path: %s", err) } tmpMount = f.Name() f.Close() } defer os.Remove(tmpMount) // Mount the filesystem err = syscall.Mount(source, tmpMount, fstype, uintptr(flags), "") if err != nil { return fmt.Errorf("Failed to setup temporary mount: %s", err) } defer syscall.Unmount(tmpMount, syscall.MNT_DETACH) // Move the mount inside the container mntsrc := filepath.Join("/dev/.lxd-mounts", filepath.Base(tmpMount)) pidStr := fmt.Sprintf("%d", pid) out, err := exec.Command(c.daemon.execPath, "forkmount", pidStr, mntsrc, target).CombinedOutput() if string(out) != "" { for _, line := range strings.Split(strings.TrimRight(string(out), "\n"), "\n") { shared.Debugf("forkmount: %s", line) } } if err != nil { return fmt.Errorf( "Error calling 'lxd forkmount %s %s %s': err='%v'", pidStr, mntsrc, target, err) } return nil } func (c *containerLXC) removeMount(mount string) error { // Get the init PID pid := c.InitPID() if pid == -1 { // Container isn't running return fmt.Errorf("Can't remove mount from stopped container") } // Remove the mount from the container pidStr := fmt.Sprintf("%d", pid) out, err := exec.Command(c.daemon.execPath, "forkumount", pidStr, mount).CombinedOutput() if string(out) != "" { for _, line := range strings.Split(strings.TrimRight(string(out), "\n"), "\n") { shared.Debugf("forkumount: %s", line) } } if err != nil { return fmt.Errorf( "Error calling 'lxd forkumount %s %s': err='%v'", pidStr, mount, err) } return nil } // Unix devices handling func (c *containerLXC) createUnixDevice(name string, m shared.Device) (string, error) { var err error var major, minor int // Our device paths srcPath := m["path"] tgtPath := strings.TrimPrefix(srcPath, "/") devName := fmt.Sprintf("unix.%s", strings.Replace(tgtPath, "/", "-", -1)) devPath := filepath.Join(c.DevicesPath(), devName) // Get the major/minor of the device we want to create if m["major"] == "" && m["minor"] == "" { // If no major and minor are set, use those from the device on the host _, major, minor, err = deviceGetAttributes(srcPath) if err != nil { return "", fmt.Errorf("Failed to get device attributes: %s", err) } } else if m["major"] == "" || m["minor"] == "" { return "", fmt.Errorf("Both major and minor must be supplied for devices") } else { major, err = strconv.Atoi(m["major"]) if err != nil { return "", fmt.Errorf("Bad major %s in device %s", m["major"], m["path"]) } minor, err = strconv.Atoi(m["minor"]) if err != nil { return "", fmt.Errorf("Bad minor %s in device %s", m["minor"], m["path"]) } } // Get the device mode mode := os.FileMode(0660) if m["mode"] != "" { tmp, err := deviceModeOct(m["mode"]) if err != nil { return "", fmt.Errorf("Bad mode %s in device %s", m["mode"], m["path"]) } mode = os.FileMode(tmp) } if m["type"] == "unix-block" { mode |= syscall.S_IFBLK } else { mode |= syscall.S_IFCHR } // Get the device owner uid := 0 gid := 0 if m["uid"] != "" { uid, err = strconv.Atoi(m["uid"]) if err != nil { return "", fmt.Errorf("Invalid uid %s in device %s", m["uid"], m["path"]) } } if m["gid"] != "" { gid, err = strconv.Atoi(m["gid"]) if err != nil { return "", fmt.Errorf("Invalid gid %s in device %s", m["gid"], m["path"]) } } // Create the devices directory if missing if !shared.PathExists(c.DevicesPath()) { os.Mkdir(c.DevicesPath(), 0711) if err != nil { return "", fmt.Errorf("Failed to create devices path: %s", err) } } // Clean any existing entry if shared.PathExists(devPath) { err = os.Remove(devPath) if err != nil { return "", fmt.Errorf("Failed to remove existing entry: %s", err) } } // Create the new entry if err := syscall.Mknod(devPath, uint32(mode), minor|(major<<8)); err != nil { return "", fmt.Errorf("Failed to create device %s for %s: %s", devPath, m["path"], err) } if err := os.Chown(devPath, uid, gid); err != nil { return "", fmt.Errorf("Failed to chown device %s: %s", devPath, err) } // Needed as mknod respects the umask if err := os.Chmod(devPath, mode); err != nil { return "", fmt.Errorf("Failed to chmod device %s: %s", devPath, err) } if c.idmapset != nil { if err := c.idmapset.ShiftFile(devPath); err != nil { // uidshift failing is weird, but not a big problem. Log and proceed shared.Debugf("Failed to uidshift device %s: %s\n", m["path"], err) } } return devPath, nil } func (c *containerLXC) insertUnixDevice(name string, m shared.Device) error { // Check that the container is running if !c.IsRunning() { return fmt.Errorf("Can't insert device into stopped container") } // Create the device on the host devPath, err := c.createUnixDevice(name, m) if err != nil { return fmt.Errorf("Failed to setup device: %s", err) } // Bind-mount it into the container tgtPath := strings.TrimSuffix(m["path"], "/") err = c.insertMount(devPath, tgtPath, "none", syscall.MS_BIND) if err != nil { return fmt.Errorf("Failed to add mount for device: %s", err) } // Add the new device cgroup rule dType, dMajor, dMinor, err := deviceGetAttributes(devPath) if err != nil { return fmt.Errorf("Failed to get device attributes: %s", err) } if err := c.CGroupSet("devices.allow", fmt.Sprintf("%s %d:%d rwm", dType, dMajor, dMinor)); err != nil { return fmt.Errorf("Failed to add cgroup rule for device") } return nil } func (c *containerLXC) removeUnixDevice(name string, m shared.Device) error { // Check that the container is running pid := c.InitPID() if pid == -1 { return fmt.Errorf("Can't remove device from stopped container") } // Figure out the paths srcPath := m["path"] tgtPath := strings.TrimPrefix(srcPath, "/") devName := fmt.Sprintf("unix.%s", strings.Replace(tgtPath, "/", "-", -1)) devPath := filepath.Join(c.DevicesPath(), devName) // Remove the device cgroup rule dType, dMajor, dMinor, err := deviceGetAttributes(devPath) if err != nil { return err } err = c.CGroupSet("devices.deny", fmt.Sprintf("%s %d:%d rwm", dType, dMajor, dMinor)) if err != nil { return err } // Remove the bind-mount from the container ctnPath := fmt.Sprintf("/proc/%d/root/%s", pid, tgtPath) if shared.PathExists(ctnPath) { err = c.removeMount(m["path"]) if err != nil { return fmt.Errorf("Error unmounting the device: %s", err) } err = os.Remove(ctnPath) if err != nil { return fmt.Errorf("Error removing the device: %s", err) } } // Remove the host side err = os.Remove(devPath) if err != nil { return err } return nil } func (c *containerLXC) removeUnixDevices() error { // Check that we indeed have devices to remove if !shared.PathExists(c.DevicesPath()) { return nil } // Load the directory listing dents, err := ioutil.ReadDir(c.DevicesPath()) if err != nil { return err } // Go through all the unix devices for _, f := range dents { // Skip non-Unix devices if !strings.HasPrefix(f.Name(), "unix.") { continue } // Remove the entry err := os.Remove(filepath.Join(c.DevicesPath(), f.Name())) if err != nil { return err } } return nil } // Network device handling func (c *containerLXC) createNetworkDevice(name string, m shared.Device) (string, error) { var dev, n1 string if shared.StringInSlice(m["nictype"], []string{"bridged", "p2p", "macvlan"}) { // Host Virtual NIC name if m["host_name"] != "" { n1 = m["host_name"] } else { n1 = deviceNextVeth() } } // Handle bridged and p2p if shared.StringInSlice(m["nictype"], []string{"bridged", "p2p"}) { n2 := deviceNextVeth() err := exec.Command("ip", "link", "add", n1, "type", "veth", "peer", "name", n2).Run() if err != nil { return "", fmt.Errorf("Failed to create the veth interface: %s", err) } err = exec.Command("ip", "link", "set", n1, "up").Run() if err != nil { return "", fmt.Errorf("Failed to bring up the veth interface %s: %s", n1, err) } if m["nictype"] == "bridged" { err = exec.Command("ip", "link", "set", n1, "master", m["parent"]).Run() if err != nil { deviceRemoveInterface(n2) return "", fmt.Errorf("Failed to add interface to bridge: %s", err) } } dev = n2 } // Handle physical if m["nictype"] == "physical" { dev = m["parent"] } // Handle macvlan if m["nictype"] == "macvlan" { err := exec.Command("ip", "link", "add", n1, "link", m["parent"], "type", "macvlan", "mode", "bridge").Run() if err != nil { return "", fmt.Errorf("Failed to create the new macvlan interface: %s", err) } dev = n1 } // Set the MAC address if m["hwaddr"] != "" { err := exec.Command("ip", "link", "set", "dev", dev, "address", m["hwaddr"]).Run() if err != nil { deviceRemoveInterface(dev) return "", fmt.Errorf("Failed to set the MAC address: %s", err) } } // Bring the interface up err := exec.Command("ip", "link", "set", "dev", dev, "up").Run() if err != nil { deviceRemoveInterface(dev) return "", fmt.Errorf("Failed to bring up the interface: %s", err) } return dev, nil } func (c *containerLXC) fillNetworkDevice(name string, m shared.Device) (shared.Device, error) { newDevice := shared.Device{} err := shared.DeepCopy(&m, &newDevice) if err != nil { return nil, err } // Function to try and guess an available name nextInterfaceName := func() (string, error) { devNames := []string{} // Include all static interface names for _, v := range c.expandedDevices { if v["name"] != "" && !shared.StringInSlice(v["name"], devNames) { devNames = append(devNames, v["name"]) } } // Include all currently allocated interface names for k, v := range c.expandedConfig { if !strings.HasPrefix(k, "volatile.") { continue } fields := strings.SplitN(k, ".", 3) if len(fields) != 3 { continue } if fields[2] != "name" || shared.StringInSlice(v, devNames) { continue } devNames = append(devNames, v) } // Attempt to include all existing interfaces cc, err := lxc.NewContainer(c.Name(), c.daemon.lxcpath) if err == nil { interfaces, err := cc.Interfaces() if err == nil { for _, name := range interfaces { if shared.StringInSlice(name, devNames) { continue } devNames = append(devNames, name) } } } // Find a free ethX device i := 0 for { name := fmt.Sprintf("eth%d", i) if !shared.StringInSlice(name, devNames) { return name, nil } i += 1 } } // Fill in the MAC address if m["nictype"] != "physical" && m["hwaddr"] == "" { configKey := fmt.Sprintf("volatile.%s.hwaddr", name) volatileHwaddr := c.localConfig[configKey] if volatileHwaddr == "" { // Generate a new MAC address volatileHwaddr, err = deviceNextInterfaceHWAddr() if err != nil { return nil, err } c.localConfig[configKey] = volatileHwaddr c.expandedConfig[configKey] = volatileHwaddr // Update the database tx, err := dbBegin(c.daemon.db) if err != nil { return nil, err } err = dbContainerConfigInsert(tx, c.id, map[string]string{configKey: volatileHwaddr}) if err != nil { tx.Rollback() return nil, err } err = txCommit(tx) if err != nil { return nil, err } } newDevice["hwaddr"] = volatileHwaddr } // File in the name if m["name"] == "" { configKey := fmt.Sprintf("volatile.%s.name", name) volatileName := c.localConfig[configKey] if volatileName == "" { // Generate a new interface name volatileName, err = nextInterfaceName() if err != nil { return nil, err } c.localConfig[configKey] = volatileName c.expandedConfig[configKey] = volatileName // Update the database tx, err := dbBegin(c.daemon.db) if err != nil { return nil, err } err = dbContainerConfigInsert(tx, c.id, map[string]string{configKey: volatileName}) if err != nil { tx.Rollback() return nil, err } err = txCommit(tx) if err != nil { return nil, err } } newDevice["name"] = volatileName } return newDevice, nil } func (c *containerLXC) insertNetworkDevice(name string, m shared.Device) error { // Load the go-lxc struct err := c.initLXC() if err != nil { return nil } // Fill in some fields from volatile m, err = c.fillNetworkDevice(name, m) if err != nil { return nil } if m["hwaddr"] == "" || m["name"] == "" { return fmt.Errorf("wtf? hwaddr=%s name=%s", m["hwaddr"], m["name"]) } // Return empty list if not running if !c.IsRunning() { return fmt.Errorf("Can't insert device into stopped container") } // Create the interface devName, err := c.createNetworkDevice(name, m) if err != nil { return err } // Add the interface to the container err = c.c.AttachInterface(devName, m["name"]) if err != nil { return fmt.Errorf("Failed to attach interface: %s: %s", devName, err) } return nil } func (c *containerLXC) removeNetworkDevice(name string, m shared.Device) error { // Load the go-lxc struct err := c.initLXC() if err != nil { return nil } // Fill in some fields from volatile m, err = c.fillNetworkDevice(name, m) if err != nil { return nil } // Return empty list if not running if !c.IsRunning() { return fmt.Errorf("Can't insert device into stopped container") } // Get a temporary device name var hostName string if m["nictype"] == "physical" { hostName = m["parent"] } else { hostName = deviceNextVeth() } // For some reason, having network config confuses detach, so get our own go-lxc struct cc, err := lxc.NewContainer(c.Name(), c.daemon.lxcpath) if err != nil { return err } // Remove the interface from the container err = cc.DetachInterfaceRename(m["name"], hostName) if err != nil { return fmt.Errorf("Failed to detach interface: %s: %s", m["name"], err) } // If a veth, destroy it if m["nictype"] != "physical" { deviceRemoveInterface(hostName) } return nil } // Disk device handling func (c *containerLXC) createDiskDevice(name string, m shared.Device) (string, error) { // Prepare all the paths srcPath := m["source"] tgtPath := strings.TrimPrefix(m["path"], "/") devName := fmt.Sprintf("disk.%s", strings.Replace(tgtPath, "/", "-", -1)) devPath := filepath.Join(c.DevicesPath(), devName) // Check if read-only isOptional := m["optional"] == "1" || m["optional"] == "true" isReadOnly := m["readonly"] == "1" || m["readonly"] == "true" isRecursive := m["recursive"] == "1" || m["recursive"] == "true" isFile := !shared.IsDir(srcPath) && !deviceIsBlockdev(srcPath) // Check if the source exists if !shared.PathExists(srcPath) { if isOptional { return "", nil } return "", fmt.Errorf("Source path doesn't exist") } // Create the devices directory if missing if !shared.PathExists(c.DevicesPath()) { err := os.Mkdir(c.DevicesPath(), 0711) if err != nil { return "", err } } // Clean any existing entry if shared.PathExists(devPath) { err := os.Remove(devPath) if err != nil { return "", err } } // Create the mount point if isFile { f, err := os.Create(devPath) if err != nil { return "", err } f.Close() } else { err := os.Mkdir(devPath, 0700) if err != nil { return "", err } } // Mount the fs err := deviceMountDisk(srcPath, devPath, isReadOnly, isRecursive) if err != nil { return "", err } return devPath, nil } func (c *containerLXC) insertDiskDevice(name string, m shared.Device) error { // Check that the container is running if !c.IsRunning() { return fmt.Errorf("Can't insert device into stopped container") } isRecursive := m["recursive"] == "1" || m["recursive"] == "true" // Create the device on the host devPath, err := c.createDiskDevice(name, m) if err != nil { return fmt.Errorf("Failed to setup device: %s", err) } flags := syscall.MS_BIND if isRecursive { flags |= syscall.MS_REC } // Bind-mount it into the container tgtPath := strings.TrimSuffix(m["path"], "/") err = c.insertMount(devPath, tgtPath, "none", flags) if err != nil { return fmt.Errorf("Failed to add mount for device: %s", err) } return nil } func (c *containerLXC) removeDiskDevice(name string, m shared.Device) error { // Check that the container is running pid := c.InitPID() if pid == -1 { return fmt.Errorf("Can't remove device from stopped container") } // Figure out the paths tgtPath := strings.TrimPrefix(m["path"], "/") devName := fmt.Sprintf("disk.%s", strings.Replace(tgtPath, "/", "-", -1)) devPath := filepath.Join(c.DevicesPath(), devName) // Remove the bind-mount from the container ctnPath := fmt.Sprintf("/proc/%d/root/%s", pid, tgtPath) if shared.PathExists(ctnPath) { err := c.removeMount(m["path"]) if err != nil { return fmt.Errorf("Error unmounting the device: %s", err) } } // Unmount the host side err := syscall.Unmount(devPath, syscall.MNT_DETACH) if err != nil { return err } // Remove the host side err = os.Remove(devPath) if err != nil { return err } return nil } func (c *containerLXC) removeDiskDevices() error { // Check that we indeed have devices to remove if !shared.PathExists(c.DevicesPath()) { return nil } // Load the directory listing dents, err := ioutil.ReadDir(c.DevicesPath()) if err != nil { return err } // Go through all the unix devices for _, f := range dents { // Skip non-Unix devices if !strings.HasPrefix(f.Name(), "disk.") { continue } // Always try to unmount the host side _ = syscall.Unmount(filepath.Join(c.DevicesPath(), f.Name()), syscall.MNT_DETACH) // Remove the entry err := os.Remove(filepath.Join(c.DevicesPath(), f.Name())) if err != nil { return err } } return nil } // Block I/O limits func (c *containerLXC) getDiskLimits() (map[string]deviceBlockLimit, error) { result := map[string]deviceBlockLimit{} // Build a list of all valid block devices validBlocks := []string{} dents, err := ioutil.ReadDir("/sys/class/block/") if err != nil { return nil, err } for _, f := range dents { fPath := filepath.Join("/sys/class/block/", f.Name()) if shared.PathExists(fmt.Sprintf("%s/partition", fPath)) { continue } if !shared.PathExists(fmt.Sprintf("%s/dev", fPath)) { continue } block, err := ioutil.ReadFile(fmt.Sprintf("%s/dev", fPath)) if err != nil { return nil, err } validBlocks = append(validBlocks, strings.TrimSuffix(string(block), "\n")) } // Process all the limits blockLimits := map[string][]deviceBlockLimit{} for _, m := range c.expandedDevices { if m["type"] != "disk" { continue } // Apply max limit if m["limits.max"] != "" { m["limits.read"] = m["limits.max"] m["limits.write"] = m["limits.max"] } // Parse the user input readBps, readIops, writeBps, writeIops, err := deviceParseDiskLimit(m["limits.read"], m["limits.write"]) if err != nil { return nil, err } // Set the source path source := m["source"] if source == "" { source = c.RootfsPath() } // Get the backing block devices (major:minor) blocks, err := deviceGetParentBlocks(source) if err != nil { if readBps == 0 && readIops == 0 && writeBps == 0 && writeIops == 0 { // If the device doesn't exist, there is no limit to clear so ignore the failure continue } else { return nil, err } } device := deviceBlockLimit{readBps: readBps, readIops: readIops, writeBps: writeBps, writeIops: writeIops} for _, block := range blocks { blockStr := "" if shared.StringInSlice(block, validBlocks) { // Straightforward entry (full block device) blockStr = block } else { // Attempt to deal with a partition (guess its parent) fields := strings.SplitN(block, ":", 2) fields[1] = "0" if shared.StringInSlice(fmt.Sprintf("%s:%s", fields[0], fields[1]), validBlocks) { blockStr = fmt.Sprintf("%s:%s", fields[0], fields[1]) } } if blockStr == "" { return nil, fmt.Errorf("Block device doesn't support quotas: %s", block) } if blockLimits[blockStr] == nil { blockLimits[blockStr] = []deviceBlockLimit{} } blockLimits[blockStr] = append(blockLimits[blockStr], device) } } // Average duplicate limits for block, limits := range blockLimits { var readBpsCount, readBpsTotal, readIopsCount, readIopsTotal, writeBpsCount, writeBpsTotal, writeIopsCount, writeIopsTotal int64 for _, limit := range limits { if limit.readBps > 0 { readBpsCount += 1 readBpsTotal += limit.readBps } if limit.readIops > 0 { readIopsCount += 1 readIopsTotal += limit.readIops } if limit.writeBps > 0 { writeBpsCount += 1 writeBpsTotal += limit.writeBps } if limit.writeIops > 0 { writeIopsCount += 1 writeIopsTotal += limit.writeIops } } device := deviceBlockLimit{} if readBpsCount > 0 { device.readBps = readBpsTotal / readBpsCount } if readIopsCount > 0 { device.readIops = readIopsTotal / readIopsCount } if writeBpsCount > 0 { device.writeBps = writeBpsTotal / writeBpsCount } if writeIopsCount > 0 { device.writeIops = writeIopsTotal / writeIopsCount } result[block] = device } return result, nil } // Network I/O limits func (c *containerLXC) setNetworkPriority() error { // Check that the container is running if !c.IsRunning() { return fmt.Errorf("Can't set network priority on stopped container") } // Don't bother if the cgroup controller doesn't exist if !cgNetPrioController { return nil } // Extract the current priority networkPriority := c.expandedConfig["limits.network.priority"] if networkPriority == "" { networkPriority = "0" } networkInt, err := strconv.Atoi(networkPriority) if err != nil { return err } // Get all the interfaces netifs, err := net.Interfaces() if err != nil { return err } // Check that we at least succeeded to set an entry success := false var last_error error for _, netif := range netifs { err = c.CGroupSet("net_prio.ifpriomap", fmt.Sprintf("%s %d", netif.Name, networkInt)) if err == nil { success = true } else { last_error = err } } if !success { return fmt.Errorf("Failed to set network device priority: %s", last_error) } return nil } func (c *containerLXC) getHostInterface(name string) string { if c.IsRunning() { for i := 0; i < len(c.c.ConfigItem("lxc.network")); i++ { nicName := c.c.RunningConfigItem(fmt.Sprintf("lxc.network.%d.name", i))[0] if nicName != name { continue } veth := c.c.RunningConfigItem(fmt.Sprintf("lxc.network.%d.veth.pair", i))[0] if veth != "" { return veth } } } for k, dev := range c.expandedDevices { if dev["type"] != "nic" { continue } m, err := c.fillNetworkDevice(k, dev) if err != nil { m = dev } if m["name"] != name { continue } return m["host_name"] } return "" } func (c *containerLXC) setNetworkLimits(name string, m shared.Device) error { // We can only do limits on some network type if m["nictype"] != "bridged" && m["nictype"] != "p2p" { return fmt.Errorf("Network limits are only supported on bridged and p2p interfaces") } // Load the go-lxc struct err := c.initLXC() if err != nil { return err } // Check that the container is running if !c.IsRunning() { return fmt.Errorf("Can't set network limits on stopped container") } // Fill in some fields from volatile m, err = c.fillNetworkDevice(name, m) if err != nil { return nil } // Look for the host side interface name veth := c.getHostInterface(m["name"]) if veth == "" { return fmt.Errorf("LXC doesn't now about this device and the host_name property isn't set, can't find host side veth name") } // Apply max limit if m["limits.max"] != "" { m["limits.ingress"] = m["limits.max"] m["limits.egress"] = m["limits.max"] } // Parse the values var ingressInt int64 if m["limits.ingress"] != "" { ingressInt, err = shared.ParseBitSizeString(m["limits.ingress"]) if err != nil { return err } } var egressInt int64 if m["limits.egress"] != "" { egressInt, err = shared.ParseBitSizeString(m["limits.egress"]) if err != nil { return err } } // Clean any existing entry _ = exec.Command("tc", "qdisc", "del", "dev", veth, "root").Run() _ = exec.Command("tc", "qdisc", "del", "dev", veth, "ingress").Run() // Apply new limits if m["limits.ingress"] != "" { out, err := exec.Command("tc", "qdisc", "add", "dev", veth, "root", "handle", "1:0", "htb", "default", "10").CombinedOutput() if err != nil { return fmt.Errorf("Failed to create root tc qdisc: %s", out) } out, err = exec.Command("tc", "class", "add", "dev", veth, "parent", "1:0", "classid", "1:10", "htb", "rate", fmt.Sprintf("%dbit", ingressInt)).CombinedOutput() if err != nil { return fmt.Errorf("Failed to create limit tc class: %s", out) } out, err = exec.Command("tc", "filter", "add", "dev", veth, "parent", "1:0", "protocol", "all", "u32", "match", "u32", "0", "0", "flowid", "1:1").CombinedOutput() if err != nil { return fmt.Errorf("Failed to create tc filter: %s", out) } } if m["limits.egress"] != "" { out, err := exec.Command("tc", "qdisc", "add", "dev", veth, "handle", "ffff:0", "ingress").CombinedOutput() if err != nil { return fmt.Errorf("Failed to create ingress tc qdisc: %s", out) } out, err = exec.Command("tc", "filter", "add", "dev", veth, "parent", "ffff:0", "protocol", "all", "u32", "match", "u32", "0", "0", "police", "rate", fmt.Sprintf("%dbit", egressInt), "burst", "1024k", "mtu", "64kb", "drop", "flowid", ":1").CombinedOutput() if err != nil { return fmt.Errorf("Failed to create ingress tc qdisc: %s", out) } } return nil } // Various state query functions func (c *containerLXC) IsStateful() bool { return c.stateful } func (c *containerLXC) IsEphemeral() bool { return c.ephemeral } func (c *containerLXC) IsFrozen() bool { return c.State() == "FROZEN" } func (c *containerLXC) IsNesting() bool { switch strings.ToLower(c.expandedConfig["security.nesting"]) { case "1": return true case "true": return true } return false } func (c *containerLXC) IsPrivileged() bool { switch strings.ToLower(c.expandedConfig["security.privileged"]) { case "1": return true case "true": return true } return false } func (c *containerLXC) IsRunning() bool { state := c.State() return state != "BROKEN" && state != "STOPPED" } func (c *containerLXC) IsSnapshot() bool { return c.cType == cTypeSnapshot } // Various property query functions func (c *containerLXC) Architecture() int { return c.architecture } func (c *containerLXC) CreationDate() time.Time { return c.creationDate } func (c *containerLXC) ExpandedConfig() map[string]string { return c.expandedConfig } func (c *containerLXC) ExpandedDevices() shared.Devices { return c.expandedDevices } func (c *containerLXC) Id() int { return c.id } func (c *containerLXC) IdmapSet() *shared.IdmapSet { return c.idmapset } func (c *containerLXC) InitPID() int { // Load the go-lxc struct err := c.initLXC() if err != nil { return -1 } return c.c.InitPid() } func (c *containerLXC) LocalConfig() map[string]string { return c.localConfig } func (c *containerLXC) LocalDevices() shared.Devices { return c.localDevices } func (c *containerLXC) LastIdmapSet() (*shared.IdmapSet, error) { lastJsonIdmap := c.LocalConfig()["volatile.last_state.idmap"] if lastJsonIdmap == "" { return c.IdmapSet(), nil } lastIdmap := new(shared.IdmapSet) err := json.Unmarshal([]byte(lastJsonIdmap), &lastIdmap.Idmap) if err != nil { return nil, err } if len(lastIdmap.Idmap) == 0 { return nil, nil } return lastIdmap, nil } func (c *containerLXC) Daemon() *Daemon { // FIXME: This function should go away return c.daemon } func (c *containerLXC) Name() string { return c.name } func (c *containerLXC) Profiles() []string { return c.profiles } func (c *containerLXC) State() string { // Load the go-lxc struct err := c.initLXC() if err != nil { return "BROKEN" } state, err := c.getLxcState() if err != nil { return shared.Error.String() } return state.String() } // Various container paths func (c *containerLXC) Path() string { return containerPath(c.Name(), c.IsSnapshot()) } func (c *containerLXC) DevicesPath() string { return shared.VarPath("devices", c.Name()) } func (c *containerLXC) LogPath() string { return shared.LogPath(c.Name()) } func (c *containerLXC) LogFilePath() string { return filepath.Join(c.LogPath(), "lxc.log") } func (c *containerLXC) RootfsPath() string { return filepath.Join(c.Path(), "rootfs") } func (c *containerLXC) TemplatesPath() string { return filepath.Join(c.Path(), "templates") } func (c *containerLXC) StatePath() string { return filepath.Join(c.RootfsPath(), "state") } lxd-2.0.0/lxd/container_post.go000066400000000000000000000023441270277227600164640ustar00rootroot00000000000000package main import ( "encoding/json" "io/ioutil" "net/http" "github.com/gorilla/mux" ) type containerPostBody struct { Migration bool `json:"migration"` Name string `json:"name"` } func containerPost(d *Daemon, r *http.Request) Response { name := mux.Vars(r)["name"] c, err := containerLoadByName(d, name) if err != nil { return SmartError(err) } buf, err := ioutil.ReadAll(r.Body) if err != nil { return InternalError(err) } body := containerPostBody{} if err := json.Unmarshal(buf, &body); err != nil { return BadRequest(err) } if body.Migration { ws, err := NewMigrationSource(c) if err != nil { return InternalError(err) } resources := map[string][]string{} resources["containers"] = []string{name} op, err := operationCreate(operationClassWebsocket, resources, ws.Metadata(), ws.Do, nil, ws.Connect) if err != nil { return InternalError(err) } return OperationResponse(op) } run := func(*operation) error { return c.Rename(body.Name) } resources := map[string][]string{} resources["containers"] = []string{name} op, err := operationCreate(operationClassTask, resources, nil, run, nil, nil) if err != nil { return InternalError(err) } return OperationResponse(op) } lxd-2.0.0/lxd/container_put.go000066400000000000000000000051171270277227600163100ustar00rootroot00000000000000package main import ( "database/sql" "encoding/json" "fmt" "net/http" "github.com/gorilla/mux" "github.com/lxc/lxd/shared" log "gopkg.in/inconshreveable/log15.v2" ) type containerPutReq struct { Architecture string `json:"architecture"` Config map[string]string `json:"config"` Devices shared.Devices `json:"devices"` Ephemeral bool `json:"ephemeral"` Profiles []string `json:"profiles"` Restore string `json:"restore"` } /* * Update configuration, or, if 'restore:snapshot-name' is present, restore * the named snapshot */ func containerPut(d *Daemon, r *http.Request) Response { name := mux.Vars(r)["name"] c, err := containerLoadByName(d, name) if err != nil { return NotFound } configRaw := containerPutReq{} if err := json.NewDecoder(r.Body).Decode(&configRaw); err != nil { return BadRequest(err) } architecture, err := shared.ArchitectureId(configRaw.Architecture) if err != nil { architecture = 0 } var do = func(*operation) error { return nil } if configRaw.Restore == "" { // Update container configuration do = func(op *operation) error { args := containerArgs{ Architecture: architecture, Config: configRaw.Config, Devices: configRaw.Devices, Ephemeral: configRaw.Ephemeral, Profiles: configRaw.Profiles} // FIXME: should set to true when not migrating err = c.Update(args, false) if err != nil { return err } return nil } } else { // Snapshot Restore do = func(op *operation) error { return containerSnapRestore(d, name, configRaw.Restore) } } resources := map[string][]string{} resources["containers"] = []string{name} op, err := operationCreate(operationClassTask, resources, nil, do, nil, nil) if err != nil { return InternalError(err) } return OperationResponse(op) } func containerSnapRestore(d *Daemon, name string, snap string) error { // normalize snapshot name if !shared.IsSnapshot(snap) { snap = name + shared.SnapshotDelimiter + snap } shared.Log.Info( "RESTORE => Restoring snapshot", log.Ctx{ "snapshot": snap, "container": name}) c, err := containerLoadByName(d, name) if err != nil { shared.Log.Error( "RESTORE => loadcontainerLXD() failed", log.Ctx{ "container": name, "err": err}) return err } source, err := containerLoadByName(d, snap) if err != nil { switch err { case sql.ErrNoRows: return fmt.Errorf("snapshot %s does not exist", snap) default: return err } } if err := c.Restore(source); err != nil { return err } return nil } lxd-2.0.0/lxd/container_snapshot.go000066400000000000000000000127231270277227600173400ustar00rootroot00000000000000package main import ( "encoding/json" "fmt" "net/http" "strconv" "strings" "github.com/gorilla/mux" "github.com/lxc/lxd/shared" ) type containerSnapshotPostReq struct { Name string `json:"name"` Stateful bool `json:"stateful"` } func containerSnapshotsGet(d *Daemon, r *http.Request) Response { recursionStr := r.FormValue("recursion") recursion, err := strconv.Atoi(recursionStr) if err != nil { recursion = 0 } cname := mux.Vars(r)["name"] c, err := containerLoadByName(d, cname) if err != nil { return SmartError(err) } snaps, err := c.Snapshots() if err != nil { return SmartError(err) } resultString := []string{} resultMap := []*shared.SnapshotInfo{} for _, snap := range snaps { snapName := strings.SplitN(snap.Name(), shared.SnapshotDelimiter, 2)[1] if recursion == 0 { url := fmt.Sprintf("/%s/containers/%s/snapshots/%s", shared.APIVersion, cname, snapName) resultString = append(resultString, url) } else { render, err := snap.Render() if err != nil { continue } resultMap = append(resultMap, render.(*shared.SnapshotInfo)) } } if recursion == 0 { return SyncResponse(true, resultString) } return SyncResponse(true, resultMap) } /* * Note, the code below doesn't deal with snapshots of snapshots. * To do that, we'll need to weed out based on # slashes in names */ func nextSnapshot(d *Daemon, name string) int { base := name + shared.SnapshotDelimiter + "snap" length := len(base) q := fmt.Sprintf("SELECT MAX(name) FROM containers WHERE type=? AND SUBSTR(name,1,?)=?") var numstr string inargs := []interface{}{cTypeSnapshot, length, base} outfmt := []interface{}{numstr} results, err := dbQueryScan(d.db, q, inargs, outfmt) if err != nil { return 0 } max := 0 for _, r := range results { numstr = r[0].(string) if len(numstr) <= length { continue } substr := numstr[length:] var num int count, err := fmt.Sscanf(substr, "%d", &num) if err != nil || count != 1 { continue } if num >= max { max = num + 1 } } return max } func containerSnapshotsPost(d *Daemon, r *http.Request) Response { name := mux.Vars(r)["name"] /* * snapshot is a three step operation: * 1. choose a new name * 2. copy the database info over * 3. copy over the rootfs */ c, err := containerLoadByName(d, name) if err != nil { return SmartError(err) } req := containerSnapshotPostReq{} if err := json.NewDecoder(r.Body).Decode(&req); err != nil { return BadRequest(err) } if req.Name == "" { // come up with a name i := nextSnapshot(d, name) req.Name = fmt.Sprintf("snap%d", i) } fullName := name + shared.SnapshotDelimiter + req.Name snapshot := func(op *operation) error { args := containerArgs{ Name: fullName, Ctype: cTypeSnapshot, Config: c.LocalConfig(), Profiles: c.Profiles(), Ephemeral: c.IsEphemeral(), BaseImage: c.ExpandedConfig()["volatile.base_image"], Architecture: c.Architecture(), Devices: c.LocalDevices(), Stateful: req.Stateful, } _, err := containerCreateAsSnapshot(d, args, c) if err != nil { return err } return nil } resources := map[string][]string{} resources["containers"] = []string{name} op, err := operationCreate(operationClassTask, resources, nil, snapshot, nil, nil) if err != nil { return InternalError(err) } return OperationResponse(op) } func snapshotHandler(d *Daemon, r *http.Request) Response { containerName := mux.Vars(r)["name"] snapshotName := mux.Vars(r)["snapshotName"] sc, err := containerLoadByName( d, containerName+ shared.SnapshotDelimiter+ snapshotName) if err != nil { return SmartError(err) } switch r.Method { case "GET": return snapshotGet(sc, snapshotName) case "POST": return snapshotPost(r, sc, containerName) case "DELETE": return snapshotDelete(sc, snapshotName) default: return NotFound } } func snapshotGet(sc container, name string) Response { render, err := sc.Render() if err != nil { return SmartError(err) } return SyncResponse(true, render.(*shared.SnapshotInfo)) } func snapshotPost(r *http.Request, sc container, containerName string) Response { raw := shared.Jmap{} if err := json.NewDecoder(r.Body).Decode(&raw); err != nil { return BadRequest(err) } migration, err := raw.GetBool("migration") if err == nil && migration { ws, err := NewMigrationSource(sc) if err != nil { return SmartError(err) } resources := map[string][]string{} resources["containers"] = []string{containerName} op, err := operationCreate(operationClassWebsocket, resources, ws.Metadata(), ws.Do, nil, ws.Connect) if err != nil { return InternalError(err) } return OperationResponse(op) } newName, err := raw.GetString("name") if err != nil { return BadRequest(err) } rename := func(op *operation) error { return sc.Rename(containerName + shared.SnapshotDelimiter + newName) } resources := map[string][]string{} resources["containers"] = []string{containerName} op, err := operationCreate(operationClassTask, resources, nil, rename, nil, nil) if err != nil { return InternalError(err) } return OperationResponse(op) } func snapshotDelete(sc container, name string) Response { remove := func(op *operation) error { return sc.Delete() } resources := map[string][]string{} resources["containers"] = []string{sc.Name()} op, err := operationCreate(operationClassTask, resources, nil, remove, nil, nil) if err != nil { return InternalError(err) } return OperationResponse(op) } lxd-2.0.0/lxd/container_state.go000066400000000000000000000052541270277227600166220ustar00rootroot00000000000000package main import ( "encoding/json" "fmt" "net/http" "time" "github.com/gorilla/mux" "github.com/lxc/lxd/shared" ) type containerStatePutReq struct { Action string `json:"action"` Timeout int `json:"timeout"` Force bool `json:"force"` Stateful bool `json:"stateful"` } func containerState(d *Daemon, r *http.Request) Response { name := mux.Vars(r)["name"] c, err := containerLoadByName(d, name) if err != nil { return SmartError(err) } state, err := c.RenderState() if err != nil { return InternalError(err) } return SyncResponse(true, state) } func containerStatePut(d *Daemon, r *http.Request) Response { name := mux.Vars(r)["name"] raw := containerStatePutReq{} // We default to -1 (i.e. no timeout) here instead of 0 (instant // timeout). raw.Timeout = -1 if err := json.NewDecoder(r.Body).Decode(&raw); err != nil { return BadRequest(err) } // Don't mess with containers while in setup mode <-d.readyChan c, err := containerLoadByName(d, name) if err != nil { return SmartError(err) } var do func(*operation) error switch shared.ContainerAction(raw.Action) { case shared.Start: do = func(op *operation) error { if err = c.Start(raw.Stateful); err != nil { return err } return nil } case shared.Stop: if raw.Stateful { do = func(op *operation) error { err := c.Stop(raw.Stateful) if err != nil { return err } return nil } } else if raw.Timeout == 0 || raw.Force { do = func(op *operation) error { err = c.Stop(false) if err != nil { return err } if c.IsEphemeral() { c.Delete() } return nil } } else { do = func(op *operation) error { err = c.Shutdown(time.Duration(raw.Timeout) * time.Second) if err != nil { return err } if c.IsEphemeral() { c.Delete() } return nil } } case shared.Restart: do = func(op *operation) error { if raw.Timeout == 0 || raw.Force { err = c.Stop(false) if err != nil { return err } } else { err = c.Shutdown(time.Duration(raw.Timeout) * time.Second) if err != nil { return err } } err = c.Start(false) if err != nil { return err } return nil } case shared.Freeze: do = func(op *operation) error { return c.Freeze() } case shared.Unfreeze: do = func(op *operation) error { return c.Unfreeze() } default: return BadRequest(fmt.Errorf("unknown action %s", raw.Action)) } resources := map[string][]string{} resources["containers"] = []string{name} op, err := operationCreate(operationClassTask, resources, nil, do, nil, nil) if err != nil { return InternalError(err) } return OperationResponse(op) } lxd-2.0.0/lxd/container_test.go000066400000000000000000000124141270277227600164550ustar00rootroot00000000000000package main import ( "github.com/lxc/lxd/shared" ) func (suite *lxdTestSuite) TestContainer_ProfilesDefault() { args := containerArgs{ Ctype: cTypeRegular, Ephemeral: false, Name: "testFoo", } c, err := containerCreateInternal(suite.d, args) suite.Req.Nil(err) defer c.Delete() profiles := c.Profiles() suite.Len( profiles, 1, "No default profile created on containerCreateInternal.") suite.Equal( "default", profiles[0], "First profile should be the default profile.") } func (suite *lxdTestSuite) TestContainer_ProfilesMulti() { // Create an unprivileged profile _, err := dbProfileCreate( suite.d.db, "unprivileged", "unprivileged", map[string]string{"security.privileged": "true"}, shared.Devices{}) suite.Req.Nil(err, "Failed to create the unprivileged profile.") defer func() { dbProfileDelete(suite.d.db, "unprivileged") }() args := containerArgs{ Ctype: cTypeRegular, Ephemeral: false, Profiles: []string{"default", "unprivileged"}, Name: "testFoo", } c, err := containerCreateInternal(suite.d, args) suite.Req.Nil(err) defer c.Delete() profiles := c.Profiles() suite.Len( profiles, 2, "Didn't get both profiles in containerCreateInternal.") suite.True( c.IsPrivileged(), "The container is not privileged (didn't apply the unprivileged profile?).") } func (suite *lxdTestSuite) TestContainer_ProfilesOverwriteDefaultNic() { args := containerArgs{ Ctype: cTypeRegular, Ephemeral: false, Config: map[string]string{"security.privileged": "true"}, Devices: shared.Devices{ "eth0": shared.Device{ "type": "nic", "nictype": "bridged", "parent": "unknownbr0"}}, Name: "testFoo", } c, err := containerCreateInternal(suite.d, args) suite.Req.Nil(err) suite.True(c.IsPrivileged(), "This container should be privileged.") out, err := c.Render() suite.Req.Nil(err) state := out.(*shared.ContainerInfo) defer c.Delete() suite.Equal( "unknownbr0", state.Devices["eth0"]["parent"], "Container config doesn't overwrite profile config.") } func (suite *lxdTestSuite) TestContainer_LoadFromDB() { args := containerArgs{ Ctype: cTypeRegular, Ephemeral: false, Config: map[string]string{"security.privileged": "true"}, Devices: shared.Devices{ "eth0": shared.Device{ "type": "nic", "nictype": "bridged", "parent": "unknownbr0"}}, Name: "testFoo", } // Create the container c, err := containerCreateInternal(suite.d, args) suite.Req.Nil(err) defer c.Delete() // Load the container and trigger initLXC() c2, err := containerLoadByName(suite.d, "testFoo") c2.IsRunning() suite.Req.Nil(err) suite.Exactly( c, c2, "The loaded container isn't excactly the same as the created one.") } func (suite *lxdTestSuite) TestContainer_Path_Regular() { // Regular args := containerArgs{ Ctype: cTypeRegular, Ephemeral: false, Name: "testFoo", } c, err := containerCreateInternal(suite.d, args) suite.Req.Nil(err) defer c.Delete() suite.Req.False(c.IsSnapshot(), "Shouldn't be a snapshot.") suite.Req.Equal(shared.VarPath("containers", "testFoo"), c.Path()) suite.Req.Equal(shared.VarPath("containers", "testFoo2"), containerPath("testFoo2", false)) } func (suite *lxdTestSuite) TestContainer_Path_Snapshot() { // Snapshot args := containerArgs{ Ctype: cTypeSnapshot, Ephemeral: false, Name: "test/snap0", } c, err := containerCreateInternal(suite.d, args) suite.Req.Nil(err) defer c.Delete() suite.Req.True(c.IsSnapshot(), "Should be a snapshot.") suite.Req.Equal( shared.VarPath("snapshots", "test", "snap0"), c.Path()) suite.Req.Equal( shared.VarPath("snapshots", "test", "snap1"), containerPath("test/snap1", true)) } func (suite *lxdTestSuite) TestContainer_LogPath() { args := containerArgs{ Ctype: cTypeRegular, Ephemeral: false, Name: "testFoo", } c, err := containerCreateInternal(suite.d, args) suite.Req.Nil(err) defer c.Delete() suite.Req.Equal(shared.VarPath("logs", "testFoo"), c.LogPath()) } func (suite *lxdTestSuite) TestContainer_IsPrivileged_Privileged() { args := containerArgs{ Ctype: cTypeRegular, Ephemeral: false, Config: map[string]string{"security.privileged": "true"}, Name: "testFoo", } c, err := containerCreateInternal(suite.d, args) suite.Req.Nil(err) defer c.Delete() suite.Req.True(c.IsPrivileged(), "This container should be privileged.") suite.Req.Nil(c.Delete(), "Failed to delete the container.") } func (suite *lxdTestSuite) TestContainer_IsPrivileged_Unprivileged() { args := containerArgs{ Ctype: cTypeRegular, Ephemeral: false, Config: map[string]string{"security.privileged": "false"}, Name: "testFoo", } c, err := containerCreateInternal(suite.d, args) suite.Req.Nil(err) defer c.Delete() suite.Req.False(c.IsPrivileged(), "This container should be unprivileged.") suite.Req.Nil(c.Delete(), "Failed to delete the container.") } func (suite *lxdTestSuite) TestContainer_Rename() { args := containerArgs{ Ctype: cTypeRegular, Ephemeral: false, Name: "testFoo", } c, err := containerCreateInternal(suite.d, args) suite.Req.Nil(err) defer c.Delete() suite.Req.Nil(c.Rename("testFoo2"), "Failed to rename the container.") suite.Req.Equal(shared.VarPath("containers", "testFoo2"), c.Path()) } lxd-2.0.0/lxd/containers.go000066400000000000000000000160561270277227600156070ustar00rootroot00000000000000package main import ( "fmt" "os" "sort" "strconv" "strings" "sync" "syscall" "time" "gopkg.in/lxc/go-lxc.v2" "github.com/lxc/lxd/shared" log "gopkg.in/inconshreveable/log15.v2" ) var containersCmd = Command{ name: "containers", get: containersGet, post: containersPost, } var containerCmd = Command{ name: "containers/{name}", get: containerGet, put: containerPut, delete: containerDelete, post: containerPost, } var containerStateCmd = Command{ name: "containers/{name}/state", get: containerState, put: containerStatePut, } var containerFileCmd = Command{ name: "containers/{name}/files", get: containerFileHandler, post: containerFileHandler, } var containerSnapshotsCmd = Command{ name: "containers/{name}/snapshots", get: containerSnapshotsGet, post: containerSnapshotsPost, } var containerSnapshotCmd = Command{ name: "containers/{name}/snapshots/{snapshotName}", get: snapshotHandler, post: snapshotHandler, delete: snapshotHandler, } var containerExecCmd = Command{ name: "containers/{name}/exec", post: containerExecPost, } type containerAutostartList []container func (slice containerAutostartList) Len() int { return len(slice) } func (slice containerAutostartList) Less(i, j int) bool { iOrder := slice[i].ExpandedConfig()["boot.autostart.priority"] jOrder := slice[j].ExpandedConfig()["boot.autostart.priority"] if iOrder != jOrder { iOrderInt, _ := strconv.Atoi(iOrder) jOrderInt, _ := strconv.Atoi(jOrder) return iOrderInt > jOrderInt } return slice[i].Name() < slice[j].Name() } func (slice containerAutostartList) Swap(i, j int) { slice[i], slice[j] = slice[j], slice[i] } func containersRestart(d *Daemon) error { result, err := dbContainersList(d.db, cTypeRegular) if err != nil { return err } containers := []container{} for _, name := range result { c, err := containerLoadByName(d, name) if err != nil { return err } containers = append(containers, c) } sort.Sort(containerAutostartList(containers)) for _, c := range containers { config := c.ExpandedConfig() lastState := config["volatile.last_state.power"] autoStart := config["boot.autostart"] autoStartDelay := config["boot.autostart.delay"] if lastState == "RUNNING" || autoStart == "true" { if c.IsRunning() { continue } c.Start(false) autoStartDelayInt, err := strconv.Atoi(autoStartDelay) if err == nil { time.Sleep(time.Duration(autoStartDelayInt) * time.Second) } } } _, err = dbExec(d.db, "DELETE FROM containers_config WHERE key='volatile.last_state.power'") if err != nil { return err } return nil } func containersShutdown(d *Daemon) error { results, err := dbContainersList(d.db, cTypeRegular) if err != nil { return err } var wg sync.WaitGroup for _, r := range results { c, err := containerLoadByName(d, r) if err != nil { return err } err = c.ConfigKeySet("volatile.last_state.power", c.State()) if err != nil { return err } if c.IsRunning() { wg.Add(1) go func() { c.Shutdown(time.Second * 30) c.Stop(false) wg.Done() }() } } wg.Wait() return nil } func containerDeleteSnapshots(d *Daemon, cname string) error { shared.Log.Debug("containerDeleteSnapshots", log.Ctx{"container": cname}) results, err := dbContainerGetSnapshots(d.db, cname) if err != nil { return err } for _, sname := range results { sc, err := containerLoadByName(d, sname) if err != nil { shared.Log.Error( "containerDeleteSnapshots: Failed to load the snapshotcontainer", log.Ctx{"container": cname, "snapshot": sname}) continue } if err := sc.Delete(); err != nil { shared.Log.Error( "containerDeleteSnapshots: Failed to delete a snapshotcontainer", log.Ctx{"container": cname, "snapshot": sname, "err": err}) } } return nil } /* * This is called by lxd when called as "lxd forkstart " * 'forkstart' is used instead of just 'start' in the hopes that people * do not accidentally type 'lxd start' instead of 'lxc start' */ func startContainer(args []string) error { if len(args) != 4 { return fmt.Errorf("Bad arguments: %q", args) } name := args[1] lxcpath := args[2] configPath := args[3] c, err := lxc.NewContainer(name, lxcpath) if err != nil { return fmt.Errorf("Error initializing container for start: %q", err) } err = c.LoadConfigFile(configPath) if err != nil { return fmt.Errorf("Error opening startup config file: %q", err) } /* due to https://github.com/golang/go/issues/13155 and the * CollectOutput call we make for the forkstart process, we need to * close our stdin/stdout/stderr here. Collecting some of the logs is * better than collecting no logs, though. */ os.Stdin.Close() os.Stderr.Close() os.Stdout.Close() // Redirect stdout and stderr to a log file logPath := shared.LogPath(name, "forkstart.log") if shared.PathExists(logPath) { os.Remove(logPath) } logFile, err := os.OpenFile(logPath, os.O_WRONLY|os.O_CREATE|os.O_SYNC, 0644) if err == nil { syscall.Dup3(int(logFile.Fd()), 1, 0) syscall.Dup3(int(logFile.Fd()), 2, 0) } // Move the config so we can inspect it on failure shared.FileMove(configPath, shared.LogPath(name, "lxc.conf")) return c.Start() } /* * This is called by lxd when called as "lxd forkexec " */ func execContainer(args []string) (int, error) { if len(args) < 6 { return -1, fmt.Errorf("Bad arguments: %q", args) } name := args[1] lxcpath := args[2] configPath := args[3] c, err := lxc.NewContainer(name, lxcpath) if err != nil { return -1, fmt.Errorf("Error initializing container for start: %q", err) } err = c.LoadConfigFile(configPath) if err != nil { return -1, fmt.Errorf("Error opening startup config file: %q", err) } syscall.Dup3(int(os.Stdin.Fd()), 200, 0) syscall.Dup3(int(os.Stdout.Fd()), 201, 0) syscall.Dup3(int(os.Stderr.Fd()), 202, 0) syscall.Close(int(os.Stdin.Fd())) syscall.Close(int(os.Stdout.Fd())) syscall.Close(int(os.Stderr.Fd())) opts := lxc.DefaultAttachOptions opts.ClearEnv = true opts.StdinFd = 200 opts.StdoutFd = 201 opts.StderrFd = 202 logPath := shared.LogPath(name, "forkexec.log") if shared.PathExists(logPath) { os.Remove(logPath) } logFile, err := os.OpenFile(logPath, os.O_WRONLY|os.O_CREATE|os.O_SYNC, 0644) if err == nil { syscall.Dup3(int(logFile.Fd()), 1, 0) syscall.Dup3(int(logFile.Fd()), 2, 0) } env := []string{} cmd := []string{} section := "" for _, arg := range args[5:len(args)] { // The "cmd" section must come last as it may contain a -- if arg == "--" && section != "cmd" { section = "" continue } if section == "" { section = arg continue } if section == "env" { fields := strings.SplitN(arg, "=", 2) if len(fields) == 2 && fields[0] == "HOME" { opts.Cwd = fields[1] } env = append(env, arg) } else if section == "cmd" { cmd = append(cmd, arg) } else { return -1, fmt.Errorf("Invalid exec section: %s", section) } } opts.Env = env status, err := c.RunCommandStatus(cmd, opts) if err != nil { return -1, fmt.Errorf("Failed running command: %q", err) } return status >> 8, nil } lxd-2.0.0/lxd/containers_get.go000066400000000000000000000032711270277227600164410ustar00rootroot00000000000000package main import ( "fmt" "net/http" "time" "github.com/lxc/lxd/shared" ) func containersGet(d *Daemon, r *http.Request) Response { for i := 0; i < 100; i++ { result, err := doContainersGet(d, d.isRecursionRequest(r)) if err == nil { return SyncResponse(true, result) } if !isDbLockedError(err) { shared.Debugf("DBERR: containersGet: error %q", err) return InternalError(err) } // 1 s may seem drastic, but we really don't want to thrash // perhaps we should use a random amount time.Sleep(100 * time.Millisecond) } shared.Debugf("DBERR: containersGet, db is locked") shared.PrintStack() return InternalError(fmt.Errorf("DB is locked")) } func doContainersGet(d *Daemon, recursion bool) (interface{}, error) { result, err := dbContainersList(d.db, cTypeRegular) if err != nil { return nil, err } resultString := []string{} resultList := []*shared.ContainerInfo{} if err != nil { return []string{}, err } for _, container := range result { if !recursion { url := fmt.Sprintf("/%s/containers/%s", shared.APIVersion, container) resultString = append(resultString, url) } else { c, err := doContainerGet(d, container) if err != nil { c = &shared.ContainerInfo{ Name: container, Status: shared.Error.String(), StatusCode: shared.Error} } resultList = append(resultList, c) } } if !recursion { return resultString, nil } return resultList, nil } func doContainerGet(d *Daemon, cname string) (*shared.ContainerInfo, error) { c, err := containerLoadByName(d, cname) if err != nil { return nil, err } cts, err := c.Render() if err != nil { return nil, err } return cts.(*shared.ContainerInfo), nil } lxd-2.0.0/lxd/containers_post.go000066400000000000000000000241431270277227600166500ustar00rootroot00000000000000package main import ( "crypto/x509" "encoding/json" "encoding/pem" "fmt" "net/http" "strings" "github.com/dustinkirkland/golang-petname" "github.com/gorilla/websocket" "github.com/lxc/lxd/shared" log "gopkg.in/inconshreveable/log15.v2" ) type containerImageSource struct { Type string `json:"type"` Certificate string `json:"certificate"` /* for "image" type */ Alias string `json:"alias"` Fingerprint string `json:"fingerprint"` Properties map[string]string `json:"properties"` Server string `json:"server"` Secret string `json:"secret"` Protocol string `json:"protocol"` /* * for "migration" and "copy" types, as an optimization users can * provide an image hash to extract before the filesystem is rsync'd, * potentially cutting down filesystem transfer time. LXD will not go * and fetch this image, it will simply use it if it exists in the * image store. */ BaseImage string `json:"base-image"` /* for "migration" type */ Mode string `json:"mode"` Operation string `json:"operation"` Websockets map[string]string `json:"secrets"` /* for "copy" type */ Source string `json:"source"` } type containerPostReq struct { Architecture string `json:"architecture"` Config map[string]string `json:"config"` Devices shared.Devices `json:"devices"` Ephemeral bool `json:"ephemeral"` Name string `json:"name"` Profiles []string `json:"profiles"` Source containerImageSource `json:"source"` } func createFromImage(d *Daemon, req *containerPostReq) Response { var hash string var err error if req.Source.Fingerprint != "" { hash = req.Source.Fingerprint } else if req.Source.Alias != "" { if req.Source.Server != "" { hash = req.Source.Alias } else { _, alias, err := dbImageAliasGet(d.db, req.Source.Alias, true) if err != nil { return InternalError(err) } hash = alias.Target } } else if req.Source.Fingerprint != "" { hash = req.Source.Fingerprint } else if req.Source.Properties != nil { if req.Source.Server != "" { return BadRequest(fmt.Errorf("Property match is only supported for local images")) } hashes, err := dbImagesGet(d.db, false) if err != nil { return InternalError(err) } var image *shared.ImageInfo for _, hash := range hashes { _, img, err := dbImageGet(d.db, hash, false, true) if err != nil { continue } if image != nil && img.CreationDate.Before(image.CreationDate) { continue } match := true for key, value := range req.Source.Properties { if img.Properties[key] != value { match = false break } } if !match { continue } image = img } if image == nil { return BadRequest(fmt.Errorf("No matching image could be found")) } hash = image.Fingerprint } else { return BadRequest(fmt.Errorf("Must specify one of alias, fingerprint or properties for init from image")) } run := func(op *operation) error { if req.Source.Server != "" { updateCached, _ := d.ConfigValueGet("images.auto_update_cached") hash, err = d.ImageDownload(op, req.Source.Server, req.Source.Protocol, req.Source.Certificate, req.Source.Secret, hash, true, updateCached != "false") if err != nil { return err } } _, imgInfo, err := dbImageGet(d.db, hash, false, false) if err != nil { return err } hash = imgInfo.Fingerprint architecture, err := shared.ArchitectureId(imgInfo.Architecture) if err != nil { architecture = 0 } args := containerArgs{ Architecture: architecture, BaseImage: hash, Config: req.Config, Ctype: cTypeRegular, Devices: req.Devices, Ephemeral: req.Ephemeral, Name: req.Name, Profiles: req.Profiles, } _, err = containerCreateFromImage(d, args, hash) return err } resources := map[string][]string{} resources["containers"] = []string{req.Name} op, err := operationCreate(operationClassTask, resources, nil, run, nil, nil) if err != nil { return InternalError(err) } return OperationResponse(op) } func createFromNone(d *Daemon, req *containerPostReq) Response { architecture, err := shared.ArchitectureId(req.Architecture) if err != nil { architecture = 0 } args := containerArgs{ Architecture: architecture, Config: req.Config, Ctype: cTypeRegular, Devices: req.Devices, Ephemeral: req.Ephemeral, Name: req.Name, Profiles: req.Profiles, } run := func(op *operation) error { _, err := containerCreateAsEmpty(d, args) return err } resources := map[string][]string{} resources["containers"] = []string{req.Name} op, err := operationCreate(operationClassTask, resources, nil, run, nil, nil) if err != nil { return InternalError(err) } return OperationResponse(op) } func createFromMigration(d *Daemon, req *containerPostReq) Response { if req.Source.Mode != "pull" { return NotImplemented } architecture, err := shared.ArchitectureId(req.Architecture) if err != nil { architecture = 0 } run := func(op *operation) error { args := containerArgs{ Architecture: architecture, BaseImage: req.Source.BaseImage, Config: req.Config, Ctype: cTypeRegular, Devices: req.Devices, Ephemeral: req.Ephemeral, Name: req.Name, Profiles: req.Profiles, } var c container _, _, err := dbImageGet(d.db, req.Source.BaseImage, false, true) /* Only create a container from an image if we're going to * rsync over the top of it. In the case of a better file * transfer mechanism, let's just use that. * * TODO: we could invent some negotiation here, where if the * source and sink both have the same image, we can clone from * it, but we have to know before sending the snapshot that * we're sending the whole thing or just a delta from the * image, so one extra negotiation round trip is needed. An * alternative is to move actual container object to a later * point and just negotiate it over the migration control * socket. Anyway, it'll happen later :) */ if err == nil && d.Storage.MigrationType() == MigrationFSType_RSYNC { c, err = containerCreateFromImage(d, args, req.Source.BaseImage) if err != nil { return err } } else { c, err = containerCreateAsEmpty(d, args) if err != nil { return err } } var cert *x509.Certificate if req.Source.Certificate != "" { certBlock, _ := pem.Decode([]byte(req.Source.Certificate)) cert, err = x509.ParseCertificate(certBlock.Bytes) if err != nil { return err } } config, err := shared.GetTLSConfig("", "", cert) if err != nil { c.Delete() return err } migrationArgs := MigrationSinkArgs{ Url: req.Source.Operation, Dialer: websocket.Dialer{ TLSClientConfig: config, NetDial: shared.RFC3493Dialer}, Container: c, Secrets: req.Source.Websockets, } sink, err := NewMigrationSink(&migrationArgs) if err != nil { c.Delete() return err } // Start the storage for this container (LVM mount/umount) c.StorageStart() // And finaly run the migration. err = sink() if err != nil { c.StorageStop() shared.Log.Error("Error during migration sink", "err", err) c.Delete() return fmt.Errorf("Error transferring container data: %s", err) } defer c.StorageStop() err = c.TemplateApply("copy") if err != nil { return err } return nil } resources := map[string][]string{} resources["containers"] = []string{req.Name} op, err := operationCreate(operationClassTask, resources, nil, run, nil, nil) if err != nil { return InternalError(err) } return OperationResponse(op) } func createFromCopy(d *Daemon, req *containerPostReq) Response { if req.Source.Source == "" { return BadRequest(fmt.Errorf("must specify a source container")) } source, err := containerLoadByName(d, req.Source.Source) if err != nil { return SmartError(err) } // Config override sourceConfig := source.LocalConfig() if req.Config == nil { req.Config = make(map[string]string) } for key, value := range sourceConfig { if len(key) > 8 && key[0:8] == "volatile" && key[9:] != "base_image" { shared.Log.Debug("Skipping volatile key from copy source", log.Ctx{"key": key}) continue } _, exists := req.Config[key] if exists { continue } req.Config[key] = value } // Profiles override if req.Profiles == nil { req.Profiles = source.Profiles() } args := containerArgs{ Architecture: source.Architecture(), BaseImage: req.Source.BaseImage, Config: req.Config, Ctype: cTypeRegular, Devices: source.LocalDevices(), Ephemeral: req.Ephemeral, Name: req.Name, Profiles: req.Profiles, } run := func(op *operation) error { _, err := containerCreateAsCopy(d, args, source) if err != nil { return err } return nil } resources := map[string][]string{} resources["containers"] = []string{req.Name, req.Source.Source} op, err := operationCreate(operationClassTask, resources, nil, run, nil, nil) if err != nil { return InternalError(err) } return OperationResponse(op) } func containersPost(d *Daemon, r *http.Request) Response { shared.Debugf("Responding to container create") req := containerPostReq{} if err := json.NewDecoder(r.Body).Decode(&req); err != nil { return BadRequest(err) } if req.Name == "" { req.Name = strings.ToLower(petname.Generate(2, "-")) shared.Debugf("No name provided, creating %s", req.Name) } if req.Devices == nil { req.Devices = shared.Devices{} } if req.Config == nil { req.Config = map[string]string{} } if strings.Contains(req.Name, shared.SnapshotDelimiter) { return BadRequest(fmt.Errorf("Invalid container name: '%s' is reserved for snapshots", shared.SnapshotDelimiter)) } switch req.Source.Type { case "image": return createFromImage(d, &req) case "none": return createFromNone(d, &req) case "migration": return createFromMigration(d, &req) case "copy": return createFromCopy(d, &req) default: return BadRequest(fmt.Errorf("unknown source type %s", req.Source.Type)) } } lxd-2.0.0/lxd/daemon.go000066400000000000000000000725341270277227600147100ustar00rootroot00000000000000package main import ( "bytes" "crypto/rand" "crypto/tls" "crypto/x509" "database/sql" "encoding/hex" "encoding/pem" "fmt" "io" "net" "net/http" "net/url" "os" "os/exec" "runtime" "strconv" "strings" "sync" "syscall" "time" "golang.org/x/crypto/scrypt" "github.com/coreos/go-systemd/activation" "github.com/gorilla/mux" _ "github.com/mattn/go-sqlite3" "github.com/syndtr/gocapability/capability" "gopkg.in/tomb.v2" "github.com/lxc/lxd" "github.com/lxc/lxd/shared" "github.com/lxc/lxd/shared/logging" log "gopkg.in/inconshreveable/log15.v2" ) // AppArmor var aaAdmin = true var aaAvailable = true var aaConfined = false // CGroup var cgBlkioController = false var cgCpuController = false var cgCpusetController = false var cgDevicesController = false var cgMemoryController = false var cgNetPrioController = false var cgPidsController = false var cgSwapAccounting = false // UserNS var runningInUserns = false const ( pwSaltBytes = 32 pwHashBytes = 64 ) type Socket struct { Socket net.Listener CloseOnExit bool } // A Daemon can respond to requests from a shared client. type Daemon struct { architectures []int BackingFs string clientCerts []x509.Certificate db *sql.DB group string IdmapSet *shared.IdmapSet lxcpath string mux *mux.Router tomb tomb.Tomb readyChan chan bool pruneChan chan bool shutdownChan chan bool resetAutoUpdateChan chan bool execPath string Storage storage TCPSocket *Socket UnixSocket *Socket devlxd *net.UnixListener configValues map[string]string MockMode bool SetupMode bool imagesDownloading map[string]chan bool imagesDownloadingLock sync.RWMutex tlsConfig *tls.Config proxy func(req *http.Request) (*url.URL, error) } // Command is the basic structure for every API call. type Command struct { name string untrustedGet bool untrustedPost bool get func(d *Daemon, r *http.Request) Response put func(d *Daemon, r *http.Request) Response post func(d *Daemon, r *http.Request) Response delete func(d *Daemon, r *http.Request) Response } func (d *Daemon) updateProxy() { d.proxy = shared.ProxyFromConfig( d.configValues["core.proxy_https"], d.configValues["core.proxy_http"], d.configValues["core.proxy_ignore_hosts"], ) } func (d *Daemon) httpGetSync(url string, certificate string) (*lxd.Response, error) { var err error var cert *x509.Certificate if certificate != "" { certBlock, _ := pem.Decode([]byte(certificate)) cert, err = x509.ParseCertificate(certBlock.Bytes) if err != nil { return nil, err } } tlsConfig, err := shared.GetTLSConfig("", "", cert) if err != nil { return nil, err } tr := &http.Transport{ TLSClientConfig: tlsConfig, Dial: shared.RFC3493Dialer, Proxy: d.proxy, } myhttp := http.Client{ Transport: tr, } req, err := http.NewRequest("GET", url, nil) if err != nil { return nil, err } req.Header.Set("User-Agent", shared.UserAgent) r, err := myhttp.Do(req) if err != nil { return nil, err } resp, err := lxd.ParseResponse(r) if err != nil { return nil, err } if resp.Type != lxd.Sync { return nil, fmt.Errorf("unexpected non-sync response") } return resp, nil } func (d *Daemon) httpGetFile(url string, certificate string) (*http.Response, error) { var err error var cert *x509.Certificate if certificate != "" { certBlock, _ := pem.Decode([]byte(certificate)) cert, err = x509.ParseCertificate(certBlock.Bytes) if err != nil { return nil, err } } tlsConfig, err := shared.GetTLSConfig("", "", cert) if err != nil { return nil, err } tr := &http.Transport{ TLSClientConfig: tlsConfig, Dial: shared.RFC3493Dialer, Proxy: d.proxy, } myhttp := http.Client{ Transport: tr, } req, err := http.NewRequest("GET", url, nil) if err != nil { return nil, err } req.Header.Set("User-Agent", shared.UserAgent) raw, err := myhttp.Do(req) if err != nil { return nil, err } if raw.StatusCode != 200 { _, err := lxd.HoistResponse(raw, lxd.Error) if err != nil { return nil, err } return nil, fmt.Errorf("non-200 status with no error response?") } return raw, nil } func readMyCert() (string, string, error) { certf := shared.VarPath("server.crt") keyf := shared.VarPath("server.key") shared.Log.Info("Looking for existing certificates", log.Ctx{"cert": certf, "key": keyf}) err := shared.FindOrGenCert(certf, keyf) return certf, keyf, err } func (d *Daemon) isTrustedClient(r *http.Request) bool { if r.RemoteAddr == "@" { // Unix socket return true } if r.TLS == nil { return false } for i := range r.TLS.PeerCertificates { if d.CheckTrustState(*r.TLS.PeerCertificates[i]) { return true } } return false } func isJSONRequest(r *http.Request) bool { for k, vs := range r.Header { if strings.ToLower(k) == "content-type" && len(vs) == 1 && strings.ToLower(vs[0]) == "application/json" { return true } } return false } func (d *Daemon) isRecursionRequest(r *http.Request) bool { recursionStr := r.FormValue("recursion") recursion, err := strconv.Atoi(recursionStr) if err != nil { return false } return recursion == 1 } func (d *Daemon) createCmd(version string, c Command) { var uri string if c.name == "" { uri = fmt.Sprintf("/%s", version) } else { uri = fmt.Sprintf("/%s/%s", version, c.name) } d.mux.HandleFunc(uri, func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") if d.isTrustedClient(r) { shared.Log.Info( "handling", log.Ctx{"method": r.Method, "url": r.URL.RequestURI(), "ip": r.RemoteAddr}) } else if r.Method == "GET" && c.untrustedGet { shared.Log.Info( "allowing untrusted GET", log.Ctx{"url": r.URL.RequestURI(), "ip": r.RemoteAddr}) } else if r.Method == "POST" && c.untrustedPost { shared.Log.Info( "allowing untrusted POST", log.Ctx{"url": r.URL.RequestURI(), "ip": r.RemoteAddr}) } else { shared.Log.Warn( "rejecting request from untrusted client", log.Ctx{"ip": r.RemoteAddr}) Forbidden.Render(w) return } if debug && r.Method != "GET" && isJSONRequest(r) { newBody := &bytes.Buffer{} captured := &bytes.Buffer{} multiW := io.MultiWriter(newBody, captured) if _, err := io.Copy(multiW, r.Body); err != nil { InternalError(err).Render(w) return } r.Body = shared.BytesReadCloser{Buf: newBody} shared.DebugJson(captured) } var resp Response resp = NotImplemented switch r.Method { case "GET": if c.get != nil { resp = c.get(d, r) } case "PUT": if c.put != nil { resp = c.put(d, r) } case "POST": if c.post != nil { resp = c.post(d, r) } case "DELETE": if c.delete != nil { resp = c.delete(d, r) } default: resp = NotFound } if err := resp.Render(w); err != nil { err := InternalError(err).Render(w) if err != nil { shared.Log.Error("Failed writing error for error, giving up") } } /* * When we create a new lxc.Container, it adds a finalizer (via * SetFinalizer) that frees the struct. However, it sometimes * takes the go GC a while to actually free the struct, * presumably since it is a small amount of memory. * Unfortunately, the struct also keeps the log fd open, so if * we leave too many of these around, we end up running out of * fds. So, let's explicitly do a GC to collect these at the * end of each request. */ runtime.GC() }) } func (d *Daemon) SetupStorageDriver() error { lvmVgName, err := d.ConfigValueGet("storage.lvm_vg_name") if err != nil { return fmt.Errorf("Couldn't read config: %s", err) } zfsPoolName, err := d.ConfigValueGet("storage.zfs_pool_name") if err != nil { return fmt.Errorf("Couldn't read config: %s", err) } if lvmVgName != "" { d.Storage, err = newStorage(d, storageTypeLvm) if err != nil { shared.Logf("Could not initialize storage type LVM: %s - falling back to dir", err) } else { return nil } } else if zfsPoolName != "" { d.Storage, err = newStorage(d, storageTypeZfs) if err != nil { shared.Logf("Could not initialize storage type ZFS: %s - falling back to dir", err) } else { return nil } } else if d.BackingFs == "btrfs" { d.Storage, err = newStorage(d, storageTypeBtrfs) if err != nil { shared.Logf("Could not initialize storage type btrfs: %s - falling back to dir", err) } else { return nil } } d.Storage, err = newStorage(d, storageTypeDir) return err } func setupSharedMounts() error { path := shared.VarPath("shmounts") isShared, err := shared.IsOnSharedMount(path) if err != nil { return err } if isShared { // / may already be ms-shared, or shmounts may have // been mounted by a previous lxd run return nil } if err := syscall.Mount(path, path, "none", syscall.MS_BIND, ""); err != nil { return err } var flags uintptr = syscall.MS_SHARED | syscall.MS_REC if err := syscall.Mount(path, path, "none", flags, ""); err != nil { return err } return nil } func (d *Daemon) ListenAddresses() ([]string, error) { addresses := make([]string, 0) value, err := d.ConfigValueGet("core.https_address") if err != nil || value == "" { return addresses, err } localHost, localPort, err := net.SplitHostPort(value) if err != nil { localHost = value localPort = shared.DefaultPort } if localHost == "0.0.0.0" || localHost == "::" || localHost == "[::]" { ifaces, err := net.Interfaces() if err != nil { return addresses, err } for _, i := range ifaces { addrs, err := i.Addrs() if err != nil { continue } for _, addr := range addrs { var ip net.IP switch v := addr.(type) { case *net.IPNet: ip = v.IP case *net.IPAddr: ip = v.IP } if !ip.IsGlobalUnicast() { continue } if ip.To4() == nil { if localHost == "0.0.0.0" { continue } addresses = append(addresses, fmt.Sprintf("[%s]:%s", ip, localPort)) } else { addresses = append(addresses, fmt.Sprintf("%s:%s", ip, localPort)) } } } } else { if strings.Contains(localHost, ":") { addresses = append(addresses, fmt.Sprintf("[%s]:%s", localHost, localPort)) } else { addresses = append(addresses, fmt.Sprintf("%s:%s", localHost, localPort)) } } return addresses, nil } func (d *Daemon) UpdateHTTPsPort(oldAddress string, newAddress string) error { if oldAddress == newAddress { return nil } if d.TCPSocket != nil { d.TCPSocket.Socket.Close() } if newAddress != "" { _, _, err := net.SplitHostPort(newAddress) if err != nil { ip := net.ParseIP(newAddress) if ip != nil && ip.To4() == nil { newAddress = fmt.Sprintf("[%s]:%s", newAddress, shared.DefaultPort) } else { newAddress = fmt.Sprintf("%s:%s", newAddress, shared.DefaultPort) } } var tcpl net.Listener for i := 0; i < 10; i++ { tcpl, err = tls.Listen("tcp", newAddress, d.tlsConfig) if err == nil { break } time.Sleep(100 * time.Millisecond) } if err != nil { return fmt.Errorf("cannot listen on https socket: %v", err) } d.tomb.Go(func() error { return http.Serve(tcpl, d.mux) }) d.TCPSocket = &Socket{Socket: tcpl, CloseOnExit: true} } return nil } func haveMacAdmin() bool { c, err := capability.NewPid(0) if err != nil { return false } if c.Get(capability.EFFECTIVE, capability.CAP_MAC_ADMIN) { return true } return false } func (d *Daemon) Init() error { /* Initialize some variables */ d.imagesDownloading = map[string]chan bool{} d.readyChan = make(chan bool) d.shutdownChan = make(chan bool) /* Set the executable path */ absPath, err := os.Readlink("/proc/self/exe") if err != nil { return err } d.execPath = absPath /* Set the LVM environment */ err = os.Setenv("LVM_SUPPRESS_FD_WARNINGS", "1") if err != nil { return err } /* Setup logging if that wasn't done before */ if shared.Log == nil { shared.Log, err = logging.GetLogger("", "", true, true, nil) if err != nil { return err } } /* Print welcome message */ if d.MockMode { shared.Log.Info("LXD is starting in mock mode", log.Ctx{"path": shared.VarPath("")}) } else if d.SetupMode { shared.Log.Info("LXD is starting in setup mode", log.Ctx{"path": shared.VarPath("")}) } else { shared.Log.Info("LXD is starting in normal mode", log.Ctx{"path": shared.VarPath("")}) } /* Detect user namespaces */ runningInUserns = shared.RunningInUserNS() /* Detect AppArmor support */ if aaAvailable && os.Getenv("LXD_SECURITY_APPARMOR") == "false" { aaAvailable = false aaAdmin = false shared.Log.Warn("AppArmor support has been manually disabled") } if aaAvailable && !shared.IsDir("/sys/kernel/security/apparmor") { aaAvailable = false aaAdmin = false shared.Log.Warn("AppArmor support has been disabled because of lack of kernel support") } _, err = exec.LookPath("apparmor_parser") if aaAvailable && err != nil { aaAvailable = false aaAdmin = false shared.Log.Warn("AppArmor support has been disabled because 'apparmor_parser' couldn't be found") } /* Detect AppArmor admin support */ if aaAdmin && !haveMacAdmin() { aaAdmin = false shared.Log.Warn("Per-container AppArmor profiles are disabled because the mac_admin capability is missing.") } if aaAdmin && runningInUserns { aaAdmin = false shared.Log.Warn("Per-container AppArmor profiles are disabled because LXD is running in an unprivileged container.") } /* Detect AppArmor confinment */ if !aaConfined { profile := aaProfile() if profile != "unconfined" && profile != "" { aaConfined = true shared.Log.Warn("Per-container AppArmor profiles are disabled because LXD is already protected by AppArmor.") } } /* Detect CGroup support */ cgBlkioController = shared.PathExists("/sys/fs/cgroup/blkio/") if !cgBlkioController { shared.Log.Warn("Couldn't find the CGroup blkio controller, I/O limits will be ignored.") } cgCpuController = shared.PathExists("/sys/fs/cgroup/cpu/") if !cgCpuController { shared.Log.Warn("Couldn't find the CGroup CPU controller, CPU time limits will be ignored.") } cgCpusetController = shared.PathExists("/sys/fs/cgroup/cpuset/") if !cgCpusetController { shared.Log.Warn("Couldn't find the CGroup CPUset controller, CPU pinning will be ignored.") } cgDevicesController = shared.PathExists("/sys/fs/cgroup/devices/") if !cgDevicesController { shared.Log.Warn("Couldn't find the CGroup devices controller, device access control won't work.") } cgMemoryController = shared.PathExists("/sys/fs/cgroup/memory/") if !cgMemoryController { shared.Log.Warn("Couldn't find the CGroup memory controller, memory limits will be ignored.") } cgNetPrioController = shared.PathExists("/sys/fs/cgroup/net_prio/") if !cgNetPrioController { shared.Log.Warn("Couldn't find the CGroup network class controller, network limits will be ignored.") } cgPidsController = shared.PathExists("/sys/fs/cgroup/pids/") if !cgPidsController { shared.Log.Warn("Couldn't find the CGroup pids controller, process limits will be ignored.") } cgSwapAccounting = shared.PathExists("/sys/fs/cgroup/memory/memory.memsw.limit_in_bytes") if !cgSwapAccounting { shared.Log.Warn("CGroup memory swap accounting is disabled, swap limits will be ignored.") } /* Get the list of supported architectures */ var architectures = []int{} architectureName, err := shared.ArchitectureGetLocal() if err != nil { return err } architecture, err := shared.ArchitectureId(architectureName) if err != nil { return err } architectures = append(architectures, architecture) personalities, err := shared.ArchitecturePersonalities(architecture) if err != nil { return err } for _, personality := range personalities { architectures = append(architectures, personality) } d.architectures = architectures /* Set container path */ d.lxcpath = shared.VarPath("containers") /* Make sure all our directories are available */ if err := os.MkdirAll(shared.VarPath("containers"), 0711); err != nil { return err } if err := os.MkdirAll(shared.VarPath("devices"), 0711); err != nil { return err } if err := os.MkdirAll(shared.VarPath("devlxd"), 0755); err != nil { return err } if err := os.MkdirAll(shared.VarPath("images"), 0700); err != nil { return err } if err := os.MkdirAll(shared.LogPath(), 0700); err != nil { return err } if err := os.MkdirAll(shared.VarPath("security"), 0700); err != nil { return err } if err := os.MkdirAll(shared.VarPath("shmounts"), 0711); err != nil { return err } if err := os.MkdirAll(shared.VarPath("snapshots"), 0700); err != nil { return err } /* Detect the filesystem */ d.BackingFs, err = filesystemDetect(d.lxcpath) if err != nil { shared.Log.Error("Error detecting backing fs", log.Ctx{"err": err}) } /* Read the uid/gid allocation */ d.IdmapSet, err = shared.DefaultIdmapSet() if err != nil { shared.Log.Warn("Error reading idmap", log.Ctx{"err": err.Error()}) shared.Log.Warn("Only privileged containers will be able to run") } else { shared.Log.Info("Default uid/gid map:") for _, lxcmap := range d.IdmapSet.ToLxcString() { shared.Log.Info(strings.TrimRight(" - "+lxcmap, "\n")) } } /* Initialize the database */ err = initializeDbObject(d, shared.VarPath("lxd.db")) if err != nil { return err } /* Setup the storage driver */ if !d.MockMode { err = d.SetupStorageDriver() if err != nil { return fmt.Errorf("Failed to setup storage: %s", err) } } /* Load all config values from the database */ _, err = d.ConfigValuesGet() if err != nil { return err } /* set the initial proxy function based on config values in the DB */ d.updateProxy() /* Setup /dev/lxd */ d.devlxd, err = createAndBindDevLxd() if err != nil { return err } if err := setupSharedMounts(); err != nil { return err } if !d.MockMode { /* Start the scheduler */ go deviceEventListener(d) /* Setup the TLS authentication */ certf, keyf, err := readMyCert() if err != nil { return err } cert, err := tls.LoadX509KeyPair(certf, keyf) if err != nil { return err } tlsConfig := &tls.Config{ InsecureSkipVerify: true, ClientAuth: tls.RequestClientCert, Certificates: []tls.Certificate{cert}, MinVersion: tls.VersionTLS12, MaxVersion: tls.VersionTLS12, CipherSuites: []uint16{ tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256}, PreferServerCipherSuites: true, } tlsConfig.BuildNameToCertificate() d.tlsConfig = tlsConfig readSavedClientCAList(d) } /* Setup the web server */ d.mux = mux.NewRouter() d.mux.StrictSlash(false) d.mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") SyncResponse(true, []string{"/1.0"}).Render(w) }) for _, c := range api10 { d.createCmd("1.0", c) } for _, c := range apiInternal { d.createCmd("internal", c) } d.mux.NotFoundHandler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { shared.Log.Debug("Sending top level 404", log.Ctx{"url": r.URL}) w.Header().Set("Content-Type", "application/json") NotFound.Render(w) }) listeners, err := activation.Listeners(false) if err != nil { return err } if len(listeners) > 0 { shared.Log.Info("LXD is socket activated") for _, listener := range listeners { if shared.PathExists(listener.Addr().String()) { d.UnixSocket = &Socket{Socket: listener, CloseOnExit: false} } else { tlsListener := tls.NewListener(listener, d.tlsConfig) d.TCPSocket = &Socket{Socket: tlsListener, CloseOnExit: false} } } } else { shared.Log.Info("LXD isn't socket activated") localSocketPath := shared.VarPath("unix.socket") // If the socket exists, let's try to connect to it and see if there's // a lxd running. if shared.PathExists(localSocketPath) { _, err := lxd.NewClient(&lxd.DefaultConfig, "local") if err != nil { shared.Log.Debug("Detected stale unix socket, deleting") // Connecting failed, so let's delete the socket and // listen on it ourselves. err = os.Remove(localSocketPath) if err != nil { return err } } else { return fmt.Errorf("LXD is already running.") } } unixAddr, err := net.ResolveUnixAddr("unix", localSocketPath) if err != nil { return fmt.Errorf("cannot resolve unix socket address: %v", err) } unixl, err := net.ListenUnix("unix", unixAddr) if err != nil { return fmt.Errorf("cannot listen on unix socket: %v", err) } if err := os.Chmod(localSocketPath, 0660); err != nil { return err } var gid int if d.group != "" { gid, err = shared.GroupId(d.group) if err != nil { return err } } else { gid = os.Getgid() } if err := os.Chown(localSocketPath, os.Getuid(), gid); err != nil { return err } d.UnixSocket = &Socket{Socket: unixl, CloseOnExit: true} } listenAddr, err := d.ConfigValueGet("core.https_address") if err != nil { return err } if listenAddr != "" { _, _, err := net.SplitHostPort(listenAddr) if err != nil { listenAddr = fmt.Sprintf("%s:%s", listenAddr, shared.DefaultPort) } tcpl, err := tls.Listen("tcp", listenAddr, d.tlsConfig) if err != nil { shared.Log.Error("cannot listen on https socket, skipping...", log.Ctx{"err": err}) } else { if d.TCPSocket != nil { shared.Log.Info("Replacing systemd TCP socket by configure one") d.TCPSocket.Socket.Close() } d.TCPSocket = &Socket{Socket: tcpl, CloseOnExit: true} } } d.tomb.Go(func() error { shared.Log.Info("REST API daemon:") if d.UnixSocket != nil { shared.Log.Info(" - binding Unix socket", log.Ctx{"socket": d.UnixSocket.Socket.Addr()}) d.tomb.Go(func() error { return http.Serve(d.UnixSocket.Socket, &lxdHttpServer{d.mux, d}) }) } if d.TCPSocket != nil { shared.Log.Info(" - binding TCP socket", log.Ctx{"socket": d.TCPSocket.Socket.Addr()}) d.tomb.Go(func() error { return http.Serve(d.TCPSocket.Socket, &lxdHttpServer{d.mux, d}) }) } d.tomb.Go(func() error { server := devLxdServer(d) return server.Serve(d.devlxd) }) return nil }) if !d.MockMode && !d.SetupMode { err := d.Ready() if err != nil { return err } } return nil } func (d *Daemon) Ready() error { /* Prune images */ d.pruneChan = make(chan bool) go func() { pruneExpiredImages(d) for { timer := time.NewTimer(24 * time.Hour) timeChan := timer.C select { case <-timeChan: /* run once per day */ pruneExpiredImages(d) case <-d.pruneChan: /* run when image.remote_cache_expiry is changed */ pruneExpiredImages(d) timer.Stop() } } }() /* Auto-update images */ d.resetAutoUpdateChan = make(chan bool) go func() { autoUpdateImages(d) for { interval, _ := d.ConfigValueGet("images.auto_update_interval") if interval == "" { interval = "6" } intervalInt, err := strconv.Atoi(interval) if err != nil { intervalInt = 0 } if intervalInt > 0 { timer := time.NewTimer(time.Duration(intervalInt) * time.Hour) timeChan := timer.C select { case <-timeChan: autoUpdateImages(d) case <-d.resetAutoUpdateChan: timer.Stop() } } else { select { case <-d.resetAutoUpdateChan: continue } } } }() /* Restore containers */ go containersRestart(d) /* Re-balance in case things changed while LXD was down */ deviceTaskBalance(d) close(d.readyChan) return nil } // CheckTrustState returns True if the client is trusted else false. func (d *Daemon) CheckTrustState(cert x509.Certificate) bool { for k, v := range d.clientCerts { if bytes.Compare(cert.Raw, v.Raw) == 0 { shared.Log.Debug("Found cert", log.Ctx{"k": k}) return true } shared.Log.Debug("Client cert != key", log.Ctx{"k": k}) } return false } func (d *Daemon) numRunningContainers() (int, error) { results, err := dbContainersList(d.db, cTypeRegular) if err != nil { return 0, err } count := 0 for _, r := range results { container, err := containerLoadByName(d, r) if err != nil { continue } if container.IsRunning() { count = count + 1 } } return count, nil } var errStop = fmt.Errorf("requested stop") // Stop stops the shared daemon. func (d *Daemon) Stop() error { forceStop := false d.tomb.Kill(errStop) shared.Log.Info("Stopping REST API handler:") for _, socket := range []*Socket{d.TCPSocket, d.UnixSocket} { if socket == nil { continue } if socket.CloseOnExit { shared.Log.Info(" - closing socket", log.Ctx{"socket": socket.Socket.Addr()}) socket.Socket.Close() } else { shared.Log.Info(" - skipping socket-activated socket", log.Ctx{"socket": socket.Socket.Addr()}) forceStop = true } } if n, err := d.numRunningContainers(); err != nil || n == 0 { shared.Log.Debug("Unmounting shmounts") syscall.Unmount(shared.VarPath("shmounts"), syscall.MNT_DETACH) } else { shared.Debugf("Not unmounting shmounts (containers are still running)") } shared.Log.Debug("Closing the database") d.db.Close() shared.Log.Debug("Stopping /dev/lxd handler") d.devlxd.Close() if d.MockMode || forceStop { return nil } err := d.tomb.Wait() if err == errStop { return nil } return err } // ConfigKeyIsValid returns if the given key is a known config value. func (d *Daemon) ConfigKeyIsValid(key string) bool { switch key { case "core.https_address": return true case "core.https_allowed_origin": return true case "core.https_allowed_methods": return true case "core.https_allowed_headers": return true case "core.proxy_https": return true case "core.proxy_http": return true case "core.proxy_ignore_hosts": return true case "core.trust_password": return true case "storage.lvm_vg_name": return true case "storage.lvm_thinpool_name": return true case "storage.lvm_fstype": return true case "storage.lvm_volume_size": return true case "storage.zfs_pool_name": return true case "images.remote_cache_expiry": return true case "images.compression_algorithm": return true case "images.auto_update_interval": return true case "images.auto_update_cached": return true } return false } // ConfigValueGet returns a config value from the memory, // calls ConfigValuesGet if required. // It returns a empty result if the config key isn't given. func (d *Daemon) ConfigValueGet(key string) (string, error) { if d.configValues == nil { if _, err := d.ConfigValuesGet(); err != nil { return "", err } } if val, ok := d.configValues[key]; ok { return val, nil } return "", nil } // ConfigValuesGet fetches all config values and stores them in memory. func (d *Daemon) ConfigValuesGet() (map[string]string, error) { if d.configValues == nil { var err error d.configValues, err = dbConfigValuesGet(d.db) if err != nil { return d.configValues, err } } return d.configValues, nil } // ConfigValueSet sets a new or updates a config value, // it updates the value in the DB and in memory. func (d *Daemon) ConfigValueSet(key string, value string) error { if err := dbConfigValueSet(d.db, key, value); err != nil { return err } if d.configValues == nil { if _, err := d.ConfigValuesGet(); err != nil { return err } } if value == "" { delete(d.configValues, key) } else { d.configValues[key] = value } return nil } // PasswordSet sets the password to the new value. func (d *Daemon) PasswordSet(password string) error { shared.Log.Info("Setting new https password") var value = password if password != "" { buf := make([]byte, pwSaltBytes) _, err := io.ReadFull(rand.Reader, buf) if err != nil { return err } hash, err := scrypt.Key([]byte(password), buf, 1<<14, 8, 1, pwHashBytes) if err != nil { return err } buf = append(buf, hash...) value = hex.EncodeToString(buf) } err := d.ConfigValueSet("core.trust_password", value) if err != nil { return err } return nil } // PasswordCheck checks if the given password is the same // as we have in the DB. func (d *Daemon) PasswordCheck(password string) bool { value, err := d.ConfigValueGet("core.trust_password") if err != nil { shared.Log.Error("verifyAdminPwd", log.Ctx{"err": err}) return false } // No password set if value == "" { return false } buff, err := hex.DecodeString(value) if err != nil { shared.Log.Error("hex decode failed", log.Ctx{"err": err}) return false } salt := buff[0:pwSaltBytes] hash, err := scrypt.Key([]byte(password), salt, 1<<14, 8, 1, pwHashBytes) if err != nil { shared.Log.Error("Failed to create hash to check", log.Ctx{"err": err}) return false } if !bytes.Equal(hash, buff[pwSaltBytes:]) { shared.Log.Error("Bad password received", log.Ctx{"err": err}) return false } shared.Log.Debug("Verified the admin password") return true } type lxdHttpServer struct { r *mux.Router d *Daemon } func (s *lxdHttpServer) ServeHTTP(rw http.ResponseWriter, req *http.Request) { allowedOrigin, _ := s.d.ConfigValueGet("core.https_allowed_origin") origin := req.Header.Get("Origin") if allowedOrigin != "" && origin != "" { rw.Header().Set("Access-Control-Allow-Origin", allowedOrigin) } allowedMethods, _ := s.d.ConfigValueGet("core.https_allowed_methods") if allowedMethods != "" && origin != "" { rw.Header().Set("Access-Control-Allow-Methods", allowedMethods) } allowedHeaders, _ := s.d.ConfigValueGet("core.https_allowed_headers") if allowedHeaders != "" && origin != "" { rw.Header().Set("Access-Control-Allow-Headers", allowedHeaders) } // OPTIONS request don't need any further processing if req.Method == "OPTIONS" { return } // Call the original server s.r.ServeHTTP(rw, req) } lxd-2.0.0/lxd/daemon_images.go000066400000000000000000000213641270277227600162300ustar00rootroot00000000000000package main import ( "encoding/json" "fmt" "io" "mime" "mime/multipart" "os" "path/filepath" "sync" "time" "github.com/lxc/lxd/shared" log "gopkg.in/inconshreveable/log15.v2" ) type imageStreamCacheEntry struct { ss *shared.SimpleStreams expiry time.Time } var imageStreamCache = map[string]*imageStreamCacheEntry{} var imageStreamCacheLock sync.Mutex // ImageDownload checks if we have that Image Fingerprint else // downloads the image from a remote server. func (d *Daemon) ImageDownload(op *operation, server string, protocol string, certificate string, secret string, alias string, forContainer bool, autoUpdate bool) (string, error) { var err error var ss *shared.SimpleStreams if protocol == "" { protocol = "lxd" } fp := alias // Expand aliases if protocol == "simplestreams" { imageStreamCacheLock.Lock() entry, _ := imageStreamCache[server] if entry == nil || entry.expiry.Before(time.Now()) { ss, err = shared.SimpleStreamsClient(server, d.proxy) if err != nil { imageStreamCacheLock.Unlock() return "", err } entry = &imageStreamCacheEntry{ss: ss, expiry: time.Now().Add(time.Hour)} imageStreamCache[server] = entry } else { shared.Debugf("Using SimpleStreams cache entry for %s, expires at %s", server, entry.expiry) ss = entry.ss } imageStreamCacheLock.Unlock() target := ss.GetAlias(fp) if target != "" { fp = target } image, err := ss.GetImageInfo(fp) if err != nil { return "", err } if fp == alias { alias = image.Fingerprint } fp = image.Fingerprint } else if protocol == "lxd" { target, err := remoteGetImageFingerprint(d, server, certificate, fp) if err == nil && target != "" { fp = target } } if _, _, err := dbImageGet(d.db, fp, false, false); err == nil { shared.Log.Debug("Image already exists in the db", log.Ctx{"image": fp}) // already have it return fp, nil } shared.Log.Info( "Image not in the db, downloading it", log.Ctx{"image": fp, "server": server}) // Now check if we already downloading the image d.imagesDownloadingLock.RLock() if waitChannel, ok := d.imagesDownloading[fp]; ok { // We already download the image d.imagesDownloadingLock.RUnlock() shared.Log.Info( "Already downloading the image, waiting for it to succeed", log.Ctx{"image": fp}) // Wait until the download finishes (channel closes) if _, ok := <-waitChannel; ok { shared.Log.Warn("Value transmitted over image lock semaphore?") } if _, _, err := dbImageGet(d.db, fp, false, true); err != nil { shared.Log.Error( "Previous download didn't succeed", log.Ctx{"image": fp}) return "", fmt.Errorf("Previous download didn't succeed") } shared.Log.Info( "Previous download succeeded", log.Ctx{"image": fp}) return fp, nil } d.imagesDownloadingLock.RUnlock() shared.Log.Info( "Downloading the image", log.Ctx{"image": fp}) // Add the download to the queue d.imagesDownloadingLock.Lock() d.imagesDownloading[fp] = make(chan bool) d.imagesDownloadingLock.Unlock() // Unlock once this func ends. defer func() { d.imagesDownloadingLock.Lock() if waitChannel, ok := d.imagesDownloading[fp]; ok { close(waitChannel) delete(d.imagesDownloading, fp) } d.imagesDownloadingLock.Unlock() }() exporturl := server var info shared.ImageInfo info.Fingerprint = fp destDir := shared.VarPath("images") destName := filepath.Join(destDir, fp) if shared.PathExists(destName) { d.Storage.ImageDelete(fp) } progress := func(progressInt int) { if op == nil { return } meta := op.metadata if meta == nil { meta = make(map[string]interface{}) } progress := fmt.Sprintf("%d%%", progressInt) if meta["download_progress"] != progress { meta["download_progress"] = progress op.UpdateMetadata(meta) } } if protocol == "lxd" { /* grab the metadata from /1.0/images/%s */ var url string if secret != "" { url = fmt.Sprintf( "%s/%s/images/%s?secret=%s", server, shared.APIVersion, fp, secret) } else { url = fmt.Sprintf("%s/%s/images/%s", server, shared.APIVersion, fp) } resp, err := d.httpGetSync(url, certificate) if err != nil { shared.Log.Error( "Failed to download image metadata", log.Ctx{"image": fp, "err": err}) return "", err } if err := json.Unmarshal(resp.Metadata, &info); err != nil { return "", err } /* now grab the actual file from /1.0/images/%s/export */ if secret != "" { exporturl = fmt.Sprintf( "%s/%s/images/%s/export?secret=%s", server, shared.APIVersion, fp, secret) } else { exporturl = fmt.Sprintf( "%s/%s/images/%s/export", server, shared.APIVersion, fp) } } else if protocol == "simplestreams" { err := ss.Download(fp, "meta", destName, nil) if err != nil { return "", err } err = ss.Download(fp, "root", destName+".rootfs", progress) if err != nil { return "", err } info, err := ss.GetImageInfo(fp) if err != nil { return "", err } info.Public = false info.AutoUpdate = autoUpdate _, err = imageBuildFromInfo(d, *info) if err != nil { return "", err } if alias != fp { id, _, err := dbImageGet(d.db, fp, false, true) if err != nil { return "", err } err = dbImageSourceInsert(d.db, id, server, protocol, "", alias) if err != nil { return "", err } } if forContainer { return fp, dbImageLastAccessInit(d.db, fp) } return fp, nil } raw, err := d.httpGetFile(exporturl, certificate) if err != nil { shared.Log.Error( "Failed to download image", log.Ctx{"image": fp, "err": err}) return "", err } info.Size = raw.ContentLength ctype, ctypeParams, err := mime.ParseMediaType(raw.Header.Get("Content-Type")) if err != nil { ctype = "application/octet-stream" } body := &shared.TransferProgress{Reader: raw.Body, Length: raw.ContentLength, Handler: progress} if ctype == "multipart/form-data" { // Parse the POST data mr := multipart.NewReader(body, ctypeParams["boundary"]) // Get the metadata tarball part, err := mr.NextPart() if err != nil { shared.Log.Error( "Invalid multipart image", log.Ctx{"image": fp, "err": err}) return "", err } if part.FormName() != "metadata" { shared.Log.Error( "Invalid multipart image", log.Ctx{"image": fp, "err": err}) return "", fmt.Errorf("Invalid multipart image") } destName = filepath.Join(destDir, info.Fingerprint) f, err := os.Create(destName) if err != nil { shared.Log.Error( "Failed to save image", log.Ctx{"image": fp, "err": err}) return "", err } _, err = io.Copy(f, part) f.Close() if err != nil { shared.Log.Error( "Failed to save image", log.Ctx{"image": fp, "err": err}) return "", err } // Get the rootfs tarball part, err = mr.NextPart() if err != nil { shared.Log.Error( "Invalid multipart image", log.Ctx{"image": fp, "err": err}) return "", err } if part.FormName() != "rootfs" { shared.Log.Error( "Invalid multipart image", log.Ctx{"image": fp}) return "", fmt.Errorf("Invalid multipart image") } destName = filepath.Join(destDir, info.Fingerprint+".rootfs") f, err = os.Create(destName) if err != nil { shared.Log.Error( "Failed to save image", log.Ctx{"image": fp, "err": err}) return "", err } _, err = io.Copy(f, part) f.Close() if err != nil { shared.Log.Error( "Failed to save image", log.Ctx{"image": fp, "err": err}) return "", err } } else { destName = filepath.Join(destDir, info.Fingerprint) f, err := os.Create(destName) if err != nil { shared.Log.Error( "Failed to save image", log.Ctx{"image": fp, "err": err}) return "", err } _, err = io.Copy(f, body) f.Close() if err != nil { shared.Log.Error( "Failed to save image", log.Ctx{"image": fp, "err": err}) return "", err } } if protocol == "direct" { imageMeta, err := getImageMetadata(destName) if err != nil { return "", err } info.Architecture = imageMeta.Architecture info.CreationDate = time.Unix(imageMeta.CreationDate, 0) info.ExpiryDate = time.Unix(imageMeta.ExpiryDate, 0) info.Properties = imageMeta.Properties } // By default, make all downloaded images private info.Public = false if alias != fp && secret == "" { info.AutoUpdate = autoUpdate } _, err = imageBuildFromInfo(d, info) if err != nil { shared.Log.Error( "Failed to create image", log.Ctx{"image": fp, "err": err}) return "", err } if alias != fp { id, _, err := dbImageGet(d.db, fp, false, true) if err != nil { return "", err } err = dbImageSourceInsert(d.db, id, server, protocol, "", alias) if err != nil { return "", err } } shared.Log.Info( "Download succeeded", log.Ctx{"image": fp}) if forContainer { return fp, dbImageLastAccessInit(d.db, fp) } return fp, nil } lxd-2.0.0/lxd/daemon_test.go000066400000000000000000000011221270277227600157300ustar00rootroot00000000000000package main func (suite *lxdTestSuite) Test_config_value_set_empty_removes_val() { var err error d := suite.d err = d.ConfigValueSet("storage.lvm_vg_name", "foo") suite.Req.Nil(err) val, err := d.ConfigValueGet("storage.lvm_vg_name") suite.Req.Nil(err) suite.Req.Equal(val, "foo") err = d.ConfigValueSet("storage.lvm_vg_name", "") suite.Req.Nil(err) val, err = d.ConfigValueGet("storage.lvm_vg_name") suite.Req.Nil(err) suite.Req.Equal(val, "") valMap, err := d.ConfigValuesGet() suite.Req.Nil(err) _, present := valMap["storage.lvm_vg_name"] suite.Req.False(present) } lxd-2.0.0/lxd/db.go000066400000000000000000000274751270277227600140360ustar00rootroot00000000000000package main import ( "database/sql" "fmt" "time" "github.com/mattn/go-sqlite3" "github.com/lxc/lxd/shared" ) var ( // DbErrAlreadyDefined hapens when the given entry already exists, // for example a container. DbErrAlreadyDefined = fmt.Errorf("The container/snapshot already exists") /* NoSuchObjectError is in the case of joins (and probably other) queries, * we don't get back sql.ErrNoRows when no rows are returned, even though we do * on selects without joins. Instead, you can use this error to * propagate up and generate proper 404s to the client when something * isn't found so we don't abuse sql.ErrNoRows any more than we * already do. */ NoSuchObjectError = fmt.Errorf("No such object") ) // Profile is here to order Profiles. type Profile struct { name string order int } // Profiles will contain a list of all Profiles. type Profiles []Profile const DB_CURRENT_VERSION int = 29 // CURRENT_SCHEMA contains the current SQLite SQL Schema. const CURRENT_SCHEMA string = ` CREATE TABLE IF NOT EXISTS certificates ( id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, fingerprint VARCHAR(255) NOT NULL, type INTEGER NOT NULL, name VARCHAR(255) NOT NULL, certificate TEXT NOT NULL, UNIQUE (fingerprint) ); CREATE TABLE IF NOT EXISTS config ( id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, key VARCHAR(255) NOT NULL, value TEXT, UNIQUE (key) ); CREATE TABLE IF NOT EXISTS containers ( id INTEGER primary key AUTOINCREMENT NOT NULL, name VARCHAR(255) NOT NULL, architecture INTEGER NOT NULL, type INTEGER NOT NULL, ephemeral INTEGER NOT NULL DEFAULT 0, stateful INTEGER NOT NULL DEFAULT 0, creation_date DATETIME, UNIQUE (name) ); CREATE TABLE IF NOT EXISTS containers_config ( id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, container_id INTEGER NOT NULL, key VARCHAR(255) NOT NULL, value TEXT, FOREIGN KEY (container_id) REFERENCES containers (id) ON DELETE CASCADE, UNIQUE (container_id, key) ); CREATE TABLE IF NOT EXISTS containers_devices ( id INTEGER primary key AUTOINCREMENT NOT NULL, container_id INTEGER NOT NULL, name VARCHAR(255) NOT NULL, type INTEGER NOT NULL default 0, FOREIGN KEY (container_id) REFERENCES containers (id) ON DELETE CASCADE, UNIQUE (container_id, name) ); CREATE TABLE IF NOT EXISTS containers_devices_config ( id INTEGER primary key AUTOINCREMENT NOT NULL, container_device_id INTEGER NOT NULL, key VARCHAR(255) NOT NULL, value TEXT, FOREIGN KEY (container_device_id) REFERENCES containers_devices (id) ON DELETE CASCADE, UNIQUE (container_device_id, key) ); CREATE TABLE IF NOT EXISTS containers_profiles ( id INTEGER primary key AUTOINCREMENT NOT NULL, container_id INTEGER NOT NULL, profile_id INTEGER NOT NULL, apply_order INTEGER NOT NULL default 0, UNIQUE (container_id, profile_id), FOREIGN KEY (container_id) REFERENCES containers(id) ON DELETE CASCADE, FOREIGN KEY (profile_id) REFERENCES profiles(id) ON DELETE CASCADE ); CREATE TABLE IF NOT EXISTS images ( id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, cached INTEGER NOT NULL DEFAULT 0, fingerprint VARCHAR(255) NOT NULL, filename VARCHAR(255) NOT NULL, size INTEGER NOT NULL, public INTEGER NOT NULL DEFAULT 0, auto_update INTEGER NOT NULL DEFAULT 0, architecture INTEGER NOT NULL, creation_date DATETIME, expiry_date DATETIME, upload_date DATETIME NOT NULL, last_use_date DATETIME, UNIQUE (fingerprint) ); CREATE TABLE IF NOT EXISTS images_aliases ( id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, name VARCHAR(255) NOT NULL, image_id INTEGER NOT NULL, description VARCHAR(255), FOREIGN KEY (image_id) REFERENCES images (id) ON DELETE CASCADE, UNIQUE (name) ); CREATE TABLE IF NOT EXISTS images_properties ( id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, image_id INTEGER NOT NULL, type INTEGER NOT NULL, key VARCHAR(255) NOT NULL, value TEXT, FOREIGN KEY (image_id) REFERENCES images (id) ON DELETE CASCADE ); CREATE TABLE IF NOT EXISTS images_source ( id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, image_id INTEGER NOT NULL, server TEXT NOT NULL, protocol INTEGER NOT NULL, certificate TEXT NOT NULL, alias VARCHAR(255) NOT NULL, FOREIGN KEY (image_id) REFERENCES images (id) ON DELETE CASCADE ); CREATE TABLE IF NOT EXISTS profiles ( id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, name VARCHAR(255) NOT NULL, description TEXT, UNIQUE (name) ); CREATE TABLE IF NOT EXISTS profiles_config ( id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, profile_id INTEGER NOT NULL, key VARCHAR(255) NOT NULL, value VARCHAR(255), UNIQUE (profile_id, key), FOREIGN KEY (profile_id) REFERENCES profiles(id) ON DELETE CASCADE ); CREATE TABLE IF NOT EXISTS profiles_devices ( id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, profile_id INTEGER NOT NULL, name VARCHAR(255) NOT NULL, type INTEGER NOT NULL default 0, UNIQUE (profile_id, name), FOREIGN KEY (profile_id) REFERENCES profiles (id) ON DELETE CASCADE ); CREATE TABLE IF NOT EXISTS profiles_devices_config ( id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, profile_device_id INTEGER NOT NULL, key VARCHAR(255) NOT NULL, value TEXT, UNIQUE (profile_device_id, key), FOREIGN KEY (profile_device_id) REFERENCES profiles_devices (id) ON DELETE CASCADE ); CREATE TABLE IF NOT EXISTS schema ( id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, version INTEGER NOT NULL, updated_at DATETIME NOT NULL, UNIQUE (version) );` // Create the initial (current) schema for a given SQLite DB connection. func createDb(db *sql.DB) (err error) { latestVersion := dbGetSchema(db) if latestVersion != 0 { return nil } _, err = db.Exec(CURRENT_SCHEMA) if err != nil { return err } // There isn't an entry for schema version, let's put it in. insertStmt := `INSERT INTO schema (version, updated_at) values (?, strftime("%s"));` _, err = db.Exec(insertStmt, DB_CURRENT_VERSION) if err != nil { return err } err = dbProfileCreateDefault(db) if err != nil { return err } return dbProfileCreateDocker(db) } func dbGetSchema(db *sql.DB) (v int) { arg1 := []interface{}{} arg2 := []interface{}{&v} q := "SELECT max(version) FROM schema" err := dbQueryRowScan(db, q, arg1, arg2) if err != nil { return 0 } return v } // Create a database connection object and return it. func initializeDbObject(d *Daemon, path string) (err error) { var openPath string timeout := 5 // TODO - make this command-line configurable? // These are used to tune the transaction BEGIN behavior instead of using the // similar "locking_mode" pragma (locking for the whole database connection). openPath = fmt.Sprintf("%s?_busy_timeout=%d&_txlock=exclusive", path, timeout*1000) // Open the database. If the file doesn't exist it is created. d.db, err = sql.Open("sqlite3", openPath) if err != nil { return err } // Create the DB if it doesn't exist. err = createDb(d.db) if err != nil { return fmt.Errorf("Error creating database: %s", err) } // Run PRAGMA statements now since they are *per-connection*. d.db.Exec("PRAGMA foreign_keys=ON;") // This allows us to use ON DELETE CASCADE v := dbGetSchema(d.db) if v != DB_CURRENT_VERSION { err = dbUpdate(d, v) if err != nil { return err } } return nil } func isDbLockedError(err error) bool { if err == nil { return false } if err == sqlite3.ErrLocked || err == sqlite3.ErrBusy { return true } if err.Error() == "database is locked" { return true } return false } func isNoMatchError(err error) bool { if err == nil { return false } if err.Error() == "sql: no rows in result set" { return true } return false } func dbBegin(db *sql.DB) (*sql.Tx, error) { for i := 0; i < 100; i++ { tx, err := db.Begin() if err == nil { return tx, nil } if !isDbLockedError(err) { shared.Debugf("DbBegin: error %q", err) return nil, err } time.Sleep(100 * time.Millisecond) } shared.Debugf("DbBegin: DB still locked") shared.PrintStack() return nil, fmt.Errorf("DB is locked") } func txCommit(tx *sql.Tx) error { for i := 0; i < 100; i++ { err := tx.Commit() if err == nil { return nil } if !isDbLockedError(err) { shared.Debugf("Txcommit: error %q", err) return err } time.Sleep(100 * time.Millisecond) } shared.Debugf("Txcommit: db still locked") shared.PrintStack() return fmt.Errorf("DB is locked") } func dbQueryRowScan(db *sql.DB, q string, args []interface{}, outargs []interface{}) error { for i := 0; i < 100; i++ { err := db.QueryRow(q, args...).Scan(outargs...) if err == nil { return nil } if isNoMatchError(err) { return err } if !isDbLockedError(err) { return err } time.Sleep(100 * time.Millisecond) } shared.Debugf("DbQueryRowScan: query %q args %q, DB still locked", q, args) shared.PrintStack() return fmt.Errorf("DB is locked") } func dbQuery(db *sql.DB, q string, args ...interface{}) (*sql.Rows, error) { for i := 0; i < 100; i++ { result, err := db.Query(q, args...) if err == nil { return result, nil } if !isDbLockedError(err) { shared.Debugf("DbQuery: query %q error %q", q, err) return nil, err } time.Sleep(100 * time.Millisecond) } shared.Debugf("DbQuery: query %q args %q, DB still locked", q, args) shared.PrintStack() return nil, fmt.Errorf("DB is locked") } func doDbQueryScan(db *sql.DB, q string, args []interface{}, outargs []interface{}) ([][]interface{}, error) { rows, err := db.Query(q, args...) if err != nil { return [][]interface{}{}, err } defer rows.Close() result := [][]interface{}{} for rows.Next() { ptrargs := make([]interface{}, len(outargs)) for i := range outargs { switch t := outargs[i].(type) { case string: str := "" ptrargs[i] = &str case int: integer := 0 ptrargs[i] = &integer default: return [][]interface{}{}, fmt.Errorf("Bad interface type: %s", t) } } err = rows.Scan(ptrargs...) if err != nil { return [][]interface{}{}, err } newargs := make([]interface{}, len(outargs)) for i := range ptrargs { switch t := outargs[i].(type) { case string: newargs[i] = *ptrargs[i].(*string) case int: newargs[i] = *ptrargs[i].(*int) default: return [][]interface{}{}, fmt.Errorf("Bad interface type: %s", t) } } result = append(result, newargs) } err = rows.Err() if err != nil { return [][]interface{}{}, err } return result, nil } /* * . q is the database query * . inargs is an array of interfaces containing the query arguments * . outfmt is an array of interfaces containing the right types of output * arguments, i.e. * var arg1 string * var arg2 int * outfmt := {}interface{}{arg1, arg2} * * The result will be an array (one per output row) of arrays (one per output argument) * of interfaces, containing pointers to the actual output arguments. */ func dbQueryScan(db *sql.DB, q string, inargs []interface{}, outfmt []interface{}) ([][]interface{}, error) { for i := 0; i < 100; i++ { result, err := doDbQueryScan(db, q, inargs, outfmt) if err == nil { return result, nil } if !isDbLockedError(err) { shared.Debugf("DbQuery: query %q error %q", q, err) return nil, err } time.Sleep(100 * time.Millisecond) } shared.Debugf("DbQueryscan: query %q inargs %q, DB still locked", q, inargs) shared.PrintStack() return nil, fmt.Errorf("DB is locked") } func dbExec(db *sql.DB, q string, args ...interface{}) (sql.Result, error) { for i := 0; i < 100; i++ { result, err := db.Exec(q, args...) if err == nil { return result, nil } if !isDbLockedError(err) { shared.Debugf("DbExec: query %q error %q", q, err) return nil, err } time.Sleep(100 * time.Millisecond) } shared.Debugf("DbExec: query %q args %q, DB still locked", q, args) shared.PrintStack() return nil, fmt.Errorf("DB is locked") } lxd-2.0.0/lxd/db_certificates.go000066400000000000000000000045421270277227600165510ustar00rootroot00000000000000package main import ( "database/sql" _ "github.com/mattn/go-sqlite3" ) // dbCertInfo is here to pass the certificates content // from the database around type dbCertInfo struct { ID int Fingerprint string Type int Name string Certificate string } // dbCertsGet returns all certificates from the DB as CertBaseInfo objects. func dbCertsGet(db *sql.DB) (certs []*dbCertInfo, err error) { rows, err := dbQuery( db, "SELECT id, fingerprint, type, name, certificate FROM certificates", ) if err != nil { return certs, err } defer rows.Close() for rows.Next() { cert := new(dbCertInfo) rows.Scan( &cert.ID, &cert.Fingerprint, &cert.Type, &cert.Name, &cert.Certificate, ) certs = append(certs, cert) } return certs, nil } // dbCertGet gets an CertBaseInfo object from the database. // The argument fingerprint will be queried with a LIKE query, means you can // pass a shortform and will get the full fingerprint. // There can never be more than one image with a given fingerprint, as it is // enforced by a UNIQUE constraint in the schema. func dbCertGet(db *sql.DB, fingerprint string) (cert *dbCertInfo, err error) { cert = new(dbCertInfo) inargs := []interface{}{fingerprint + "%"} outfmt := []interface{}{ &cert.ID, &cert.Fingerprint, &cert.Type, &cert.Name, &cert.Certificate, } query := ` SELECT id, fingerprint, type, name, certificate FROM certificates WHERE fingerprint LIKE ?` if err = dbQueryRowScan(db, query, inargs, outfmt); err != nil { return nil, err } return cert, err } // dbCertSave stores a CertBaseInfo object in the db, // it will ignore the ID field from the dbCertInfo. func dbCertSave(db *sql.DB, cert *dbCertInfo) error { tx, err := dbBegin(db) if err != nil { return err } stmt, err := tx.Prepare(` INSERT INTO certificates ( fingerprint, type, name, certificate ) VALUES (?, ?, ?, ?)`, ) if err != nil { tx.Rollback() return err } defer stmt.Close() _, err = stmt.Exec( cert.Fingerprint, cert.Type, cert.Name, cert.Certificate, ) if err != nil { tx.Rollback() return err } return txCommit(tx) } // dbCertDelete deletes a certificate from the db. func dbCertDelete(db *sql.DB, fingerprint string) error { _, err := dbExec( db, "DELETE FROM certificates WHERE fingerprint=?", fingerprint, ) return err } lxd-2.0.0/lxd/db_config.go000066400000000000000000000017571270277227600153560ustar00rootroot00000000000000package main import ( "database/sql" _ "github.com/mattn/go-sqlite3" ) func dbConfigValuesGet(db *sql.DB) (map[string]string, error) { q := "SELECT key, value FROM config" rows, err := dbQuery(db, q) if err != nil { return map[string]string{}, err } defer rows.Close() results := map[string]string{} for rows.Next() { var key, value string rows.Scan(&key, &value) results[key] = value } return results, nil } func dbConfigValueSet(db *sql.DB, key string, value string) error { tx, err := dbBegin(db) if err != nil { return err } _, err = tx.Exec("DELETE FROM config WHERE key=?", key) if err != nil { tx.Rollback() return err } if value != "" { str := `INSERT INTO config (key, value) VALUES (?, ?);` stmt, err := tx.Prepare(str) if err != nil { tx.Rollback() return err } defer stmt.Close() _, err = stmt.Exec(key, value) if err != nil { tx.Rollback() return err } } err = txCommit(tx) if err != nil { return err } return nil } lxd-2.0.0/lxd/db_containers.go000066400000000000000000000214261270277227600162510ustar00rootroot00000000000000package main import ( "database/sql" "fmt" "time" "github.com/lxc/lxd/shared" log "gopkg.in/inconshreveable/log15.v2" ) type containerType int const ( cTypeRegular containerType = 0 cTypeSnapshot containerType = 1 ) func dbContainerRemove(db *sql.DB, name string) error { id, err := dbContainerId(db, name) if err != nil { return err } tx, err := dbBegin(db) if err != nil { return err } err = dbContainerConfigClear(tx, id) if err != nil { tx.Rollback() return err } _, err = tx.Exec("DELETE FROM containers WHERE id=?", id) if err != nil { tx.Rollback() return err } return txCommit(tx) } func dbContainerName(db *sql.DB, id int) (string, error) { q := "SELECT name FROM containers WHERE id=?" name := "" arg1 := []interface{}{id} arg2 := []interface{}{&name} err := dbQueryRowScan(db, q, arg1, arg2) return name, err } func dbContainerId(db *sql.DB, name string) (int, error) { q := "SELECT id FROM containers WHERE name=?" id := -1 arg1 := []interface{}{name} arg2 := []interface{}{&id} err := dbQueryRowScan(db, q, arg1, arg2) return id, err } func dbContainerGet(db *sql.DB, name string) (containerArgs, error) { args := containerArgs{} args.Name = name ephemInt := -1 statefulInt := -1 q := "SELECT id, architecture, type, ephemeral, stateful, creation_date FROM containers WHERE name=?" arg1 := []interface{}{name} arg2 := []interface{}{&args.Id, &args.Architecture, &args.Ctype, &ephemInt, &statefulInt, &args.CreationDate} err := dbQueryRowScan(db, q, arg1, arg2) if err != nil { return args, err } if args.Id == -1 { return args, fmt.Errorf("Unknown container") } if ephemInt == 1 { args.Ephemeral = true } if statefulInt == 1 { args.Stateful = true } config, err := dbContainerConfig(db, args.Id) if err != nil { return args, err } args.Config = config profiles, err := dbContainerProfiles(db, args.Id) if err != nil { return args, err } args.Profiles = profiles /* get container_devices */ args.Devices = shared.Devices{} newdevs, err := dbDevices(db, name, false) if err != nil { return args, err } for k, v := range newdevs { args.Devices[k] = v } return args, nil } func dbContainerCreate(db *sql.DB, args containerArgs) (int, error) { id, err := dbContainerId(db, args.Name) if err == nil { return 0, DbErrAlreadyDefined } tx, err := dbBegin(db) if err != nil { return 0, err } ephemInt := 0 if args.Ephemeral == true { ephemInt = 1 } statefulInt := 0 if args.Stateful == true { statefulInt = 1 } args.CreationDate = time.Now().UTC() str := fmt.Sprintf("INSERT INTO containers (name, architecture, type, ephemeral, creation_date, stateful) VALUES (?, ?, ?, ?, ?, ?)") stmt, err := tx.Prepare(str) if err != nil { tx.Rollback() return 0, err } defer stmt.Close() result, err := stmt.Exec(args.Name, args.Architecture, args.Ctype, ephemInt, args.CreationDate.Unix(), statefulInt) if err != nil { tx.Rollback() return 0, err } id64, err := result.LastInsertId() if err != nil { tx.Rollback() return 0, fmt.Errorf("Error inserting %s into database", args.Name) } // TODO: is this really int64? we should fix it everywhere if so id = int(id64) if err := dbContainerConfigInsert(tx, id, args.Config); err != nil { tx.Rollback() return 0, err } if err := dbContainerProfilesInsert(tx, id, args.Profiles); err != nil { tx.Rollback() return 0, err } if err := dbDevicesAdd(tx, "container", int64(id), args.Devices); err != nil { tx.Rollback() return 0, err } return id, txCommit(tx) } func dbContainerConfigClear(tx *sql.Tx, id int) error { _, err := tx.Exec("DELETE FROM containers_config WHERE container_id=?", id) if err != nil { return err } _, err = tx.Exec("DELETE FROM containers_profiles WHERE container_id=?", id) if err != nil { return err } _, err = tx.Exec(`DELETE FROM containers_devices_config WHERE id IN (SELECT containers_devices_config.id FROM containers_devices_config JOIN containers_devices ON containers_devices_config.container_device_id=containers_devices.id WHERE containers_devices.container_id=?)`, id) if err != nil { return err } _, err = tx.Exec("DELETE FROM containers_devices WHERE container_id=?", id) return err } func dbContainerConfigInsert(tx *sql.Tx, id int, config map[string]string) error { str := "INSERT INTO containers_config (container_id, key, value) values (?, ?, ?)" stmt, err := tx.Prepare(str) if err != nil { return err } defer stmt.Close() for k, v := range config { _, err := stmt.Exec(id, k, v) if err != nil { shared.Debugf("Error adding configuration item %s = %s to container %d", k, v, id) return err } } return nil } func dbContainerConfigRemove(db *sql.DB, id int, name string) error { _, err := dbExec(db, "DELETE FROM containers_config WHERE key=? AND container_id=?", name, id) return err } func dbContainerSetStateful(db *sql.DB, id int, stateful bool) error { statefulInt := 0 if stateful { statefulInt = 1 } _, err := dbExec(db, "UPDATE containers SET stateful=? WHERE id=?", statefulInt, id) return err } func dbContainerProfilesInsert(tx *sql.Tx, id int, profiles []string) error { applyOrder := 1 str := `INSERT INTO containers_profiles (container_id, profile_id, apply_order) VALUES (?, (SELECT id FROM profiles WHERE name=?), ?);` stmt, err := tx.Prepare(str) if err != nil { return err } defer stmt.Close() for _, p := range profiles { _, err = stmt.Exec(id, p, applyOrder) if err != nil { shared.Debugf("Error adding profile %s to container: %s", p, err) return err } applyOrder = applyOrder + 1 } return nil } // Get a list of profiles for a given container id. func dbContainerProfiles(db *sql.DB, containerId int) ([]string, error) { var name string var profiles []string query := ` SELECT name FROM containers_profiles JOIN profiles ON containers_profiles.profile_id=profiles.id WHERE container_id=? ORDER BY containers_profiles.apply_order` inargs := []interface{}{containerId} outfmt := []interface{}{name} results, err := dbQueryScan(db, query, inargs, outfmt) if err != nil { return nil, err } for _, r := range results { name = r[0].(string) profiles = append(profiles, name) } return profiles, nil } // dbContainerConfig gets the container configuration map from the DB func dbContainerConfig(db *sql.DB, containerId int) (map[string]string, error) { var key, value string q := `SELECT key, value FROM containers_config WHERE container_id=?` inargs := []interface{}{containerId} outfmt := []interface{}{key, value} // Results is already a slice here, not db Rows anymore. results, err := dbQueryScan(db, q, inargs, outfmt) if err != nil { return nil, err //SmartError will wrap this and make "not found" errors pretty } config := map[string]string{} for _, r := range results { key = r[0].(string) value = r[1].(string) config[key] = value } return config, nil } func dbContainersList(db *sql.DB, cType containerType) ([]string, error) { q := fmt.Sprintf("SELECT name FROM containers WHERE type=? ORDER BY name") inargs := []interface{}{cType} var container string outfmt := []interface{}{container} result, err := dbQueryScan(db, q, inargs, outfmt) if err != nil { return nil, err } var ret []string for _, container := range result { ret = append(ret, container[0].(string)) } return ret, nil } func dbContainerRename(db *sql.DB, oldName string, newName string) error { tx, err := dbBegin(db) if err != nil { return err } str := fmt.Sprintf("UPDATE containers SET name = ? WHERE name = ?") stmt, err := tx.Prepare(str) if err != nil { tx.Rollback() return err } defer stmt.Close() shared.Log.Debug( "Calling SQL Query", log.Ctx{ "query": "UPDATE containers SET name = ? WHERE name = ?", "oldName": oldName, "newName": newName}) if _, err := stmt.Exec(newName, oldName); err != nil { tx.Rollback() return err } return txCommit(tx) } func dbContainerUpdate(tx *sql.Tx, id int, architecture int, ephemeral bool) error { str := fmt.Sprintf("UPDATE containers SET architecture=?, ephemeral=? WHERE id=?") stmt, err := tx.Prepare(str) if err != nil { return err } defer stmt.Close() ephemeralInt := 0 if ephemeral { ephemeralInt = 1 } if _, err := stmt.Exec(architecture, ephemeralInt, id); err != nil { return err } return nil } func dbContainerGetSnapshots(db *sql.DB, name string) ([]string, error) { result := []string{} regexp := name + shared.SnapshotDelimiter length := len(regexp) q := "SELECT name FROM containers WHERE type=? AND SUBSTR(name,1,?)=?" inargs := []interface{}{cTypeSnapshot, length, regexp} outfmt := []interface{}{name} dbResults, err := dbQueryScan(db, q, inargs, outfmt) if err != nil { return result, err } for _, r := range dbResults { result = append(result, r[0].(string)) } return result, nil } lxd-2.0.0/lxd/db_devices.go000066400000000000000000000067521270277227600155330ustar00rootroot00000000000000package main import ( "database/sql" "fmt" _ "github.com/mattn/go-sqlite3" "github.com/lxc/lxd/shared" ) func dbDeviceTypeToString(t int) (string, error) { switch t { case 0: return "none", nil case 1: return "nic", nil case 2: return "disk", nil case 3: return "unix-char", nil case 4: return "unix-block", nil default: return "", fmt.Errorf("Invalid device type %d", t) } } func dbDeviceTypeToInt(t string) (int, error) { switch t { case "none": return 0, nil case "nic": return 1, nil case "disk": return 2, nil case "unix-char": return 3, nil case "unix-block": return 4, nil default: return -1, fmt.Errorf("Invalid device type %s", t) } } func dbDevicesAdd(tx *sql.Tx, w string, cID int64, devices shared.Devices) error { // Prepare the devices entry SQL str1 := fmt.Sprintf("INSERT INTO %ss_devices (%s_id, name, type) VALUES (?, ?, ?)", w, w) stmt1, err := tx.Prepare(str1) if err != nil { return err } defer stmt1.Close() // Prepare the devices config entry SQL str2 := fmt.Sprintf("INSERT INTO %ss_devices_config (%s_device_id, key, value) VALUES (?, ?, ?)", w, w) stmt2, err := tx.Prepare(str2) if err != nil { return err } defer stmt2.Close() // Insert all the devices for k, v := range devices { t, err := dbDeviceTypeToInt(v["type"]) if err != nil { return err } result, err := stmt1.Exec(cID, k, t) if err != nil { return err } id64, err := result.LastInsertId() if err != nil { return fmt.Errorf("Error inserting device %s into database", k) } id := int(id64) for ck, cv := range v { // The type is stored as int in the parent entry if ck == "type" { continue } _, err = stmt2.Exec(id, ck, cv) if err != nil { return err } } } return nil } func dbDeviceConfig(db *sql.DB, id int, isprofile bool) (shared.Device, error) { var query string var key, value string newdev := shared.Device{} // That's a map[string]string inargs := []interface{}{id} outfmt := []interface{}{key, value} if isprofile { query = `SELECT key, value FROM profiles_devices_config WHERE profile_device_id=?` } else { query = `SELECT key, value FROM containers_devices_config WHERE container_device_id=?` } results, err := dbQueryScan(db, query, inargs, outfmt) if err != nil { return newdev, err } for _, r := range results { key = r[0].(string) value = r[1].(string) newdev[key] = value } return newdev, nil } func dbDevices(db *sql.DB, qName string, isprofile bool) (shared.Devices, error) { var q string if isprofile { q = `SELECT profiles_devices.id, profiles_devices.name, profiles_devices.type FROM profiles_devices JOIN profiles ON profiles_devices.profile_id = profiles.id WHERE profiles.name=?` } else { q = `SELECT containers_devices.id, containers_devices.name, containers_devices.type FROM containers_devices JOIN containers ON containers_devices.container_id = containers.id WHERE containers.name=?` } var id, dtype int var name, stype string inargs := []interface{}{qName} outfmt := []interface{}{id, name, dtype} results, err := dbQueryScan(db, q, inargs, outfmt) if err != nil { return nil, err } devices := shared.Devices{} for _, r := range results { id = r[0].(int) name = r[1].(string) stype, err = dbDeviceTypeToString(r[2].(int)) if err != nil { return nil, err } newdev, err := dbDeviceConfig(db, id, isprofile) if err != nil { return nil, err } newdev["type"] = stype devices[name] = newdev } return devices, nil } lxd-2.0.0/lxd/db_images.go000066400000000000000000000256041270277227600153530ustar00rootroot00000000000000package main import ( "database/sql" "fmt" "time" _ "github.com/mattn/go-sqlite3" "github.com/lxc/lxd/shared" ) var dbImageSourceProtocol = map[int]string{ 0: "lxd", 1: "direct", 2: "simplestreams", } func dbImagesGet(db *sql.DB, public bool) ([]string, error) { q := "SELECT fingerprint FROM images" if public == true { q = "SELECT fingerprint FROM images WHERE public=1" } var fp string inargs := []interface{}{} outfmt := []interface{}{fp} dbResults, err := dbQueryScan(db, q, inargs, outfmt) if err != nil { return []string{}, err } results := []string{} for _, r := range dbResults { results = append(results, r[0].(string)) } return results, nil } func dbImagesGetExpired(db *sql.DB, expiry int) ([]string, error) { q := `SELECT fingerprint FROM images WHERE cached=1 AND creation_date<=strftime('%s', date('now', '-` + fmt.Sprintf("%d", expiry) + ` day'))` var fp string inargs := []interface{}{} outfmt := []interface{}{fp} dbResults, err := dbQueryScan(db, q, inargs, outfmt) if err != nil { return []string{}, err } results := []string{} for _, r := range dbResults { results = append(results, r[0].(string)) } return results, nil } func dbImageSourceInsert(db *sql.DB, imageId int, server string, protocol string, certificate string, alias string) error { stmt := `INSERT INTO images_source (image_id, server, protocol, certificate, alias) values (?, ?, ?, ?, ?)` protocolInt := -1 for protoInt, protoString := range dbImageSourceProtocol { if protoString == protocol { protocolInt = protoInt } } if protocolInt == -1 { return fmt.Errorf("Invalid protocol: %s", protocol) } _, err := dbExec(db, stmt, imageId, server, protocolInt, certificate, alias) return err } func dbImageSourceGet(db *sql.DB, imageId int) (int, shared.ImageSource, error) { q := `SELECT id, server, protocol, certificate, alias FROM images_source WHERE image_id=?` id := 0 protocolInt := -1 result := shared.ImageSource{} arg1 := []interface{}{imageId} arg2 := []interface{}{&id, &result.Server, &protocolInt, &result.Certificate, &result.Alias} err := dbQueryRowScan(db, q, arg1, arg2) if err != nil { if err == sql.ErrNoRows { return -1, shared.ImageSource{}, NoSuchObjectError } return -1, shared.ImageSource{}, err } protocol, found := dbImageSourceProtocol[protocolInt] if !found { return -1, shared.ImageSource{}, fmt.Errorf("Invalid protocol: %d", protocolInt) } result.Protocol = protocol return id, result, nil } // dbImageGet gets an ImageBaseInfo object from the database. // The argument fingerprint will be queried with a LIKE query, means you can // pass a shortform and will get the full fingerprint. // There can never be more than one image with a given fingerprint, as it is // enforced by a UNIQUE constraint in the schema. func dbImageGet(db *sql.DB, fingerprint string, public bool, strictMatching bool) (int, *shared.ImageInfo, error) { var err error var create, expire, used, upload *time.Time // These hold the db-returned times // The object we'll actually return image := shared.ImageInfo{} id := -1 arch := -1 // These two humongous things will be filled by the call to DbQueryRowScan outfmt := []interface{}{&id, &image.Fingerprint, &image.Filename, &image.Size, &image.Cached, &image.Public, &image.AutoUpdate, &arch, &create, &expire, &used, &upload} var query string var inargs []interface{} if strictMatching { inargs = []interface{}{fingerprint} query = ` SELECT id, fingerprint, filename, size, cached, public, auto_update, architecture, creation_date, expiry_date, last_use_date, upload_date FROM images WHERE fingerprint = ?` } else { inargs = []interface{}{fingerprint + "%"} query = ` SELECT id, fingerprint, filename, size, cached, public, auto_update, architecture, creation_date, expiry_date, last_use_date, upload_date FROM images WHERE fingerprint LIKE ?` } if public { query = query + " AND public=1" } err = dbQueryRowScan(db, query, inargs, outfmt) if err != nil { return -1, nil, err // Likely: there are no rows for this fingerprint } // Some of the dates can be nil in the DB, let's process them. if create != nil { image.CreationDate = *create } else { image.CreationDate = time.Time{} } if expire != nil { image.ExpiryDate = *expire } else { image.ExpiryDate = time.Time{} } if used != nil { image.LastUsedDate = *used } else { image.LastUsedDate = time.Time{} } image.Architecture, _ = shared.ArchitectureName(arch) // The upload date is enforced by NOT NULL in the schema, so it can never be nil. image.UploadDate = *upload // Get the properties q := "SELECT key, value FROM images_properties where image_id=?" var key, value, name, desc string inargs = []interface{}{id} outfmt = []interface{}{key, value} results, err := dbQueryScan(db, q, inargs, outfmt) if err != nil { return -1, nil, err } properties := map[string]string{} for _, r := range results { key = r[0].(string) value = r[1].(string) properties[key] = value } image.Properties = properties // Get the aliases q = "SELECT name, description FROM images_aliases WHERE image_id=?" inargs = []interface{}{id} outfmt = []interface{}{name, desc} results, err = dbQueryScan(db, q, inargs, outfmt) if err != nil { return -1, nil, err } aliases := []shared.ImageAlias{} for _, r := range results { name = r[0].(string) desc = r[0].(string) a := shared.ImageAlias{Name: name, Description: desc} aliases = append(aliases, a) } image.Aliases = aliases _, source, err := dbImageSourceGet(db, id) if err == nil { image.Source = &source } return id, &image, nil } func dbImageDelete(db *sql.DB, id int) error { tx, err := dbBegin(db) if err != nil { return err } _, _ = tx.Exec("DELETE FROM images_aliases WHERE image_id=?", id) _, _ = tx.Exec("DELETE FROM images_properties WHERE image_id=?", id) _, _ = tx.Exec("DELETE FROM images_source WHERE image_id=?", id) _, _ = tx.Exec("DELETE FROM images WHERE id=?", id) if err := txCommit(tx); err != nil { return err } return nil } func dbImageAliasGet(db *sql.DB, name string, isTrustedClient bool) (int, shared.ImageAliasesEntry, error) { q := `SELECT images_aliases.id, images.fingerprint, images_aliases.description FROM images_aliases INNER JOIN images ON images_aliases.image_id=images.id WHERE images_aliases.name=?` if !isTrustedClient { q = q + ` AND images.public=1` } var fingerprint, description string id := -1 arg1 := []interface{}{name} arg2 := []interface{}{&id, &fingerprint, &description} err := dbQueryRowScan(db, q, arg1, arg2) if err != nil { if err == sql.ErrNoRows { return -1, shared.ImageAliasesEntry{}, NoSuchObjectError } return -1, shared.ImageAliasesEntry{}, err } return id, shared.ImageAliasesEntry{Name: name, Target: fingerprint, Description: description}, nil } func dbImageAliasRename(db *sql.DB, id int, name string) error { _, err := dbExec(db, "UPDATE images_aliases SET name=? WHERE id=?", name, id) return err } func dbImageAliasDelete(db *sql.DB, name string) error { _, err := dbExec(db, "DELETE FROM images_aliases WHERE name=?", name) return err } func dbImageAliasesMove(db *sql.DB, source int, destination int) error { _, err := dbExec(db, "UPDATE images_aliases SET image_id=? WHERE image_id=?", destination, source) return err } // Insert an alias ento the database. func dbImageAliasAdd(db *sql.DB, name string, imageID int, desc string) error { stmt := `INSERT INTO images_aliases (name, image_id, description) values (?, ?, ?)` _, err := dbExec(db, stmt, name, imageID, desc) return err } func dbImageAliasUpdate(db *sql.DB, id int, imageID int, desc string) error { stmt := `UPDATE images_aliases SET image_id=?, description=? WHERE id=?` _, err := dbExec(db, stmt, imageID, desc, id) return err } func dbImageLastAccessUpdate(db *sql.DB, fingerprint string, date time.Time) error { stmt := `UPDATE images SET last_use_date=? WHERE fingerprint=?` _, err := dbExec(db, stmt, date, fingerprint) return err } func dbImageLastAccessInit(db *sql.DB, fingerprint string) error { stmt := `UPDATE images SET cached=1, last_use_date=strftime("%s") WHERE fingerprint=?` _, err := dbExec(db, stmt, fingerprint) return err } func dbImageUpdate(db *sql.DB, id int, fname string, sz int64, public bool, autoUpdate bool, architecture string, creationDate time.Time, expiryDate time.Time, properties map[string]string) error { arch, err := shared.ArchitectureId(architecture) if err != nil { arch = 0 } tx, err := dbBegin(db) if err != nil { return err } publicInt := 0 if public { publicInt = 1 } autoUpdateInt := 0 if autoUpdate { autoUpdateInt = 1 } stmt, err := tx.Prepare(`UPDATE images SET filename=?, size=?, public=?, auto_update=?, architecture=?, creation_date=?, expiry_date=? WHERE id=?`) if err != nil { tx.Rollback() return err } defer stmt.Close() _, err = stmt.Exec(fname, sz, publicInt, autoUpdateInt, arch, creationDate, expiryDate, id) if err != nil { tx.Rollback() return err } _, err = tx.Exec(`DELETE FROM images_properties WHERE image_id=?`, id) stmt, err = tx.Prepare(`INSERT INTO images_properties (image_id, type, key, value) VALUES (?, ?, ?, ?)`) if err != nil { tx.Rollback() return err } for key, value := range properties { _, err = stmt.Exec(id, 0, key, value) if err != nil { tx.Rollback() return err } } if err := txCommit(tx); err != nil { return err } return nil } func dbImageInsert(db *sql.DB, fp string, fname string, sz int64, public bool, autoUpdate bool, architecture string, creationDate time.Time, expiryDate time.Time, properties map[string]string) error { arch, err := shared.ArchitectureId(architecture) if err != nil { arch = 0 } tx, err := dbBegin(db) if err != nil { return err } publicInt := 0 if public { publicInt = 1 } autoUpdateInt := 0 if autoUpdate { autoUpdateInt = 1 } stmt, err := tx.Prepare(`INSERT INTO images (fingerprint, filename, size, public, auto_update, architecture, creation_date, expiry_date, upload_date) VALUES (?, ?, ?, ?, ?, ?, ?, ?, strftime("%s"))`) if err != nil { tx.Rollback() return err } defer stmt.Close() result, err := stmt.Exec(fp, fname, sz, publicInt, autoUpdateInt, arch, creationDate, expiryDate) if err != nil { tx.Rollback() return err } if len(properties) > 0 { id64, err := result.LastInsertId() if err != nil { tx.Rollback() return err } id := int(id64) pstmt, err := tx.Prepare(`INSERT INTO images_properties (image_id, type, key, value) VALUES (?, 0, ?, ?)`) if err != nil { tx.Rollback() return err } defer pstmt.Close() for k, v := range properties { // we can assume, that there is just one // value per key _, err = pstmt.Exec(id, k, v) if err != nil { tx.Rollback() return err } } } if err := txCommit(tx); err != nil { return err } return nil } lxd-2.0.0/lxd/db_profiles.go000066400000000000000000000145371270277227600157340ustar00rootroot00000000000000package main import ( "database/sql" "fmt" _ "github.com/mattn/go-sqlite3" "github.com/lxc/lxd/shared" ) // dbProfiles returns a string list of profiles. func dbProfiles(db *sql.DB) ([]string, error) { q := fmt.Sprintf("SELECT name FROM profiles") inargs := []interface{}{} var name string outfmt := []interface{}{name} result, err := dbQueryScan(db, q, inargs, outfmt) if err != nil { return []string{}, err } response := []string{} for _, r := range result { response = append(response, r[0].(string)) } return response, nil } func dbProfileGet(db *sql.DB, profile string) (int64, *shared.ProfileConfig, error) { id := int64(-1) description := sql.NullString{} q := "SELECT id, description FROM profiles WHERE name=?" arg1 := []interface{}{profile} arg2 := []interface{}{&id, &description} err := dbQueryRowScan(db, q, arg1, arg2) if err != nil { return -1, nil, err } config, err := dbProfileConfig(db, profile) if err != nil { return -1, nil, err } devices, err := dbDevices(db, profile, true) if err != nil { return -1, nil, err } return id, &shared.ProfileConfig{ Name: profile, Config: config, Description: description.String, Devices: devices, }, nil } func dbProfileCreate(db *sql.DB, profile string, description string, config map[string]string, devices shared.Devices) (int64, error) { tx, err := dbBegin(db) if err != nil { return -1, err } result, err := tx.Exec("INSERT INTO profiles (name, description) VALUES (?, ?)", profile, description) if err != nil { tx.Rollback() return -1, err } id, err := result.LastInsertId() if err != nil { tx.Rollback() return -1, err } err = dbProfileConfigAdd(tx, id, config) if err != nil { tx.Rollback() return -1, err } err = dbDevicesAdd(tx, "profile", id, devices) if err != nil { tx.Rollback() return -1, err } err = txCommit(tx) if err != nil { return -1, err } return id, nil } func dbProfileCreateDefault(db *sql.DB) error { id, _, _ := dbProfileGet(db, "default") if id != -1 { // default profile already exists return nil } // TODO: We should scan for bridges and use the best available as default. devices := shared.Devices{ "eth0": shared.Device{ "name": "eth0", "type": "nic", "nictype": "bridged", "parent": "lxdbr0"}} id, err := dbProfileCreate(db, "default", "Default LXD profile", map[string]string{}, devices) if err != nil { return err } return nil } func dbProfileCreateDocker(db *sql.DB) error { id, _, err := dbProfileGet(db, "docker") if id != -1 { // docker profile already exists return nil } config := map[string]string{ "security.nesting": "true", "linux.kernel_modules": "overlay, nf_nat"} fusedev := map[string]string{ "path": "/dev/fuse", "type": "unix-char", } aadisable := map[string]string{ "path": "/sys/module/apparmor/parameters/enabled", "type": "disk", "source": "/dev/null", } devices := map[string]shared.Device{"fuse": fusedev, "aadisable": aadisable} _, err = dbProfileCreate(db, "docker", "Profile supporting docker in containers", config, devices) return err } // Get the profile configuration map from the DB func dbProfileConfig(db *sql.DB, name string) (map[string]string, error) { var key, value string query := ` SELECT key, value FROM profiles_config JOIN profiles ON profiles_config.profile_id=profiles.id WHERE name=?` inargs := []interface{}{name} outfmt := []interface{}{key, value} results, err := dbQueryScan(db, query, inargs, outfmt) if err != nil { return nil, fmt.Errorf("Failed to get profile '%s'", name) } if len(results) == 0 { /* * If we didn't get any rows here, let's check to make sure the * profile really exists; if it doesn't, let's send back a 404. */ query := "SELECT id FROM profiles WHERE name=?" var id int results, err := dbQueryScan(db, query, []interface{}{name}, []interface{}{id}) if err != nil { return nil, err } if len(results) == 0 { return nil, NoSuchObjectError } } config := map[string]string{} for _, r := range results { key = r[0].(string) value = r[1].(string) config[key] = value } return config, nil } func dbProfileDelete(db *sql.DB, name string) error { tx, err := dbBegin(db) if err != nil { return err } _, err = tx.Exec("DELETE FROM profiles WHERE name=?", name) if err != nil { tx.Rollback() return err } err = txCommit(tx) return err } func dbProfileUpdate(db *sql.DB, name string, newName string) error { tx, err := dbBegin(db) if err != nil { return err } _, err = tx.Exec("UPDATE profiles SET name=? WHERE name=?", newName, name) if err != nil { tx.Rollback() return err } err = txCommit(tx) return err } func dbProfileDescriptionUpdate(tx *sql.Tx, id int64, description string) error { _, err := tx.Exec("UPDATE profiles SET description=? WHERE id=?", description, id) return err } func dbProfileConfigClear(tx *sql.Tx, id int64) error { _, err := tx.Exec("DELETE FROM profiles_config WHERE profile_id=?", id) if err != nil { return err } _, err = tx.Exec(`DELETE FROM profiles_devices_config WHERE id IN (SELECT profiles_devices_config.id FROM profiles_devices_config JOIN profiles_devices ON profiles_devices_config.profile_device_id=profiles_devices.id WHERE profiles_devices.profile_id=?)`, id) if err != nil { return err } _, err = tx.Exec("DELETE FROM profiles_devices WHERE profile_id=?", id) if err != nil { return err } return nil } func dbProfileConfigAdd(tx *sql.Tx, id int64, config map[string]string) error { str := fmt.Sprintf("INSERT INTO profiles_config (profile_id, key, value) VALUES(?, ?, ?)") stmt, err := tx.Prepare(str) defer stmt.Close() for k, v := range config { _, err = stmt.Exec(id, k, v) if err != nil { return err } } return nil } func dbProfileContainersGet(db *sql.DB, profile string) ([]string, error) { q := `SELECT containers.name FROM containers JOIN containers_profiles ON containers.id == containers_profiles.container_id JOIN profiles ON containers_profiles.profile_id == profiles.id WHERE profiles.name == ?` results := []string{} inargs := []interface{}{profile} var name string outfmt := []interface{}{name} output, err := dbQueryScan(db, q, inargs, outfmt) if err != nil { return results, err } for _, r := range output { results = append(results, r[0].(string)) } return results, nil } lxd-2.0.0/lxd/db_test.go000066400000000000000000000406371270277227600150700ustar00rootroot00000000000000package main import ( "database/sql" "fmt" "testing" "time" "github.com/lxc/lxd/shared" "github.com/lxc/lxd/shared/logging" ) const DB_FIXTURES string = ` INSERT INTO containers (name, architecture, type) VALUES ('thename', 1, 1); INSERT INTO profiles (name) VALUES ('theprofile'); INSERT INTO containers_profiles (container_id, profile_id) VALUES (1, 3); INSERT INTO containers_config (container_id, key, value) VALUES (1, 'thekey', 'thevalue'); INSERT INTO containers_devices (container_id, name, type) VALUES (1, 'somename', 1); INSERT INTO containers_devices_config (key, value, container_device_id) VALUES ('configkey', 'configvalue', 1); INSERT INTO images (fingerprint, filename, size, architecture, creation_date, expiry_date, upload_date) VALUES ('fingerprint', 'filename', 1024, 0, 1431547174, 1431547175, 1431547176); INSERT INTO images_aliases (name, image_id, description) VALUES ('somealias', 1, 'some description'); INSERT INTO images_properties (image_id, type, key, value) VALUES (1, 0, 'thekey', 'some value'); INSERT INTO profiles_config (profile_id, key, value) VALUES (3, 'thekey', 'thevalue'); INSERT INTO profiles_devices (profile_id, name, type) VALUES (3, 'devicename', 1); INSERT INTO profiles_devices_config (profile_device_id, key, value) VALUES (4, 'devicekey', 'devicevalue'); ` // This Helper will initialize a test in-memory DB. func createTestDb(t *testing.T) (db *sql.DB) { // Setup logging if main() hasn't been called/when testing if shared.Log == nil { var err error shared.Log, err = logging.GetLogger("", "", true, true, nil) if err != nil { t.Fatal(err) } } var err error d := &Daemon{MockMode: true} err = initializeDbObject(d, ":memory:") db = d.db if err != nil { t.Fatal(err) } _, err = db.Exec(DB_FIXTURES) if err != nil { t.Fatal(err) } return // db is a named output param } func Test_deleting_a_container_cascades_on_related_tables(t *testing.T) { var db *sql.DB var err error var count int var statements string // Insert a container and a related profile. db = createTestDb(t) defer db.Close() // Drop the container we just created. statements = `DELETE FROM containers WHERE name = 'thename';` _, err = db.Exec(statements) if err != nil { t.Errorf("Error deleting container! %s", err) } // Make sure there are 0 container_profiles entries left. statements = `SELECT count(*) FROM containers_profiles;` err = db.QueryRow(statements).Scan(&count) if count != 0 { t.Errorf("Deleting a container didn't delete the profile association! There are %d left", count) } // Make sure there are 0 containers_config entries left. statements = `SELECT count(*) FROM containers_config;` err = db.QueryRow(statements).Scan(&count) if count != 0 { t.Errorf("Deleting a container didn't delete the associated container_config! There are %d left", count) } // Make sure there are 0 containers_devices entries left. statements = `SELECT count(*) FROM containers_devices;` err = db.QueryRow(statements).Scan(&count) if count != 0 { t.Errorf("Deleting a container didn't delete the associated container_devices! There are %d left", count) } // Make sure there are 0 containers_devices_config entries left. statements = `SELECT count(*) FROM containers_devices_config;` err = db.QueryRow(statements).Scan(&count) if count != 0 { t.Errorf("Deleting a container didn't delete the associated container_devices_config! There are %d left", count) } } func Test_deleting_a_profile_cascades_on_related_tables(t *testing.T) { var db *sql.DB var err error var count int var statements string // Insert a container and a related profile. db = createTestDb(t) defer db.Close() // Drop the profile we just created. statements = `DELETE FROM profiles WHERE name = 'theprofile';` _, err = db.Exec(statements) if err != nil { t.Errorf("Error deleting profile! %s", err) } // Make sure there are 0 container_profiles entries left. statements = `SELECT count(*) FROM containers_profiles WHERE profile_id = 3;` err = db.QueryRow(statements).Scan(&count) if count != 0 { t.Errorf("Deleting a profile didn't delete the container association! There are %d left", count) } // Make sure there are 0 profiles_devices entries left. statements = `SELECT count(*) FROM profiles_devices WHERE profile_id == 3;` err = db.QueryRow(statements).Scan(&count) if count != 0 { t.Errorf("Deleting a profile didn't delete the related profiles_devices! There are %d left", count) } // Make sure there are 0 profiles_config entries left. statements = `SELECT count(*) FROM profiles_config WHERE profile_id == 3;` err = db.QueryRow(statements).Scan(&count) if count != 0 { t.Errorf("Deleting a profile didn't delete the related profiles_config! There are %d left", count) } // Make sure there are 0 profiles_devices_config entries left. statements = `SELECT count(*) FROM profiles_devices_config WHERE profile_device_id == 4;` err = db.QueryRow(statements).Scan(&count) if count != 0 { t.Errorf("Deleting a profile didn't delete the related profiles_devices_config! There are %d left", count) } } func Test_deleting_an_image_cascades_on_related_tables(t *testing.T) { var db *sql.DB var err error var count int var statements string db = createTestDb(t) defer db.Close() // Drop the image we just created. statements = `DELETE FROM images;` _, err = db.Exec(statements) if err != nil { t.Errorf("Error deleting image! %s", err) } // Make sure there are 0 images_aliases entries left. statements = `SELECT count(*) FROM images_aliases;` err = db.QueryRow(statements).Scan(&count) if count != 0 { t.Errorf("Deleting an image didn't delete the image alias association! There are %d left", count) } // Make sure there are 0 images_properties entries left. statements = `SELECT count(*) FROM images_properties;` err = db.QueryRow(statements).Scan(&count) if count != 0 { t.Errorf("Deleting an image didn't delete the related images_properties! There are %d left", count) } } func Test_initializing_db_is_indempotent(t *testing.T) { var db *sql.DB var err error // This calls "createDb" once already. d := &Daemon{MockMode: true} err = initializeDbObject(d, ":memory:") db = d.db defer db.Close() // Let's call it a second time. err = createDb(db) if err != nil { t.Errorf("The database schema is not indempotent, err='%s'", err) } } func Test_get_schema_returns_0_on_uninitialized_db(t *testing.T) { var db *sql.DB var err error db, err = sql.Open("sqlite3", ":memory:") if err != nil { t.Error(err) } result := dbGetSchema(db) if result != 0 { t.Error("getSchema should return 0 on uninitialized db!") } } func Test_running_dbUpdateFromV6_adds_on_delete_cascade(t *testing.T) { // Upgrading the database schema with updateFromV6 adds ON DELETE CASCADE // to sqlite tables that require it, and conserve the data. var err error var count int d := &Daemon{MockMode: true} err = initializeDbObject(d, ":memory:") defer d.db.Close() statements := ` CREATE TABLE IF NOT EXISTS containers ( id INTEGER primary key AUTOINCREMENT NOT NULL, name VARCHAR(255) NOT NULL, architecture INTEGER NOT NULL, type INTEGER NOT NULL, power_state INTEGER NOT NULL DEFAULT 0, ephemeral INTEGER NOT NULL DEFAULT 0, UNIQUE (name) ); CREATE TABLE IF NOT EXISTS containers_config ( id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, container_id INTEGER NOT NULL, key VARCHAR(255) NOT NULL, value TEXT, FOREIGN KEY (container_id) REFERENCES containers (id), UNIQUE (container_id, key) ); INSERT INTO containers (name, architecture, type) VALUES ('thename', 1, 1); INSERT INTO containers_config (container_id, key, value) VALUES (1, 'thekey', 'thevalue');` _, err = d.db.Exec(statements) if err != nil { t.Error(err) } // Run the upgrade from V6 code err = dbUpdateFromV6(d.db) // Make sure the inserted data is still there. statements = `SELECT count(*) FROM containers_config;` err = d.db.QueryRow(statements).Scan(&count) if count != 1 { t.Fatalf("There should be exactly one entry in containers_config! There are %d.", count) } // Drop the container. statements = `DELETE FROM containers WHERE name = 'thename';` _, err = d.db.Exec(statements) if err != nil { t.Errorf("Error deleting container! %s", err) } // Make sure there are 0 container_profiles entries left. statements = `SELECT count(*) FROM containers_profiles;` err = d.db.QueryRow(statements).Scan(&count) if count != 0 { t.Errorf("Deleting a container didn't delete the profile association! There are %d left", count) } } func Test_run_database_upgrades_with_some_foreign_keys_inconsistencies(t *testing.T) { var db *sql.DB var err error var count int var statements string db, err = sql.Open("sqlite3", ":memory:") defer db.Close() if err != nil { t.Fatal(err) } // This schema is a part of schema rev 1. statements = ` CREATE TABLE containers ( id INTEGER primary key AUTOINCREMENT NOT NULL, name VARCHAR(255) NOT NULL, architecture INTEGER NOT NULL, type INTEGER NOT NULL, UNIQUE (name) ); CREATE TABLE containers_config ( id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, container_id INTEGER NOT NULL, key VARCHAR(255) NOT NULL, value TEXT, FOREIGN KEY (container_id) REFERENCES containers (id), UNIQUE (container_id, key) ); CREATE TABLE schema ( id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, version INTEGER NOT NULL, updated_at DATETIME NOT NULL, UNIQUE (version) ); CREATE TABLE images ( id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, fingerprint VARCHAR(255) NOT NULL, filename VARCHAR(255) NOT NULL, size INTEGER NOT NULL, public INTEGER NOT NULL DEFAULT 0, architecture INTEGER NOT NULL, creation_date DATETIME, expiry_date DATETIME, upload_date DATETIME NOT NULL, UNIQUE (fingerprint) ); CREATE TABLE images_properties ( id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, image_id INTEGER NOT NULL, type INTEGER NOT NULL, key VARCHAR(255) NOT NULL, value TEXT, FOREIGN KEY (image_id) REFERENCES images (id) ); CREATE TABLE certificates ( id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, fingerprint VARCHAR(255) NOT NULL, type INTEGER NOT NULL, name VARCHAR(255) NOT NULL, certificate TEXT NOT NULL, UNIQUE (fingerprint) ); INSERT INTO schema (version, updated_at) values (1, "now"); INSERT INTO containers (name, architecture, type) VALUES ('thename', 1, 1); INSERT INTO containers_config (container_id, key, value) VALUES (1, 'thekey', 'thevalue');` _, err = db.Exec(statements) if err != nil { t.Fatal("Error creating schema!") } // Now that we have a consistent schema, let's remove the container entry // *without* the ON DELETE CASCADE in place. statements = `DELETE FROM containers;` _, err = db.Exec(statements) if err != nil { t.Fatal("Error truncating the container table!") } // The "foreign key" on containers_config now points to nothing. // Let's run the schema upgrades. d := &Daemon{MockMode: true} d.db = db err = dbUpdate(d, 1) if err != nil { t.Error("Error upgrading database schema!") t.Fatal(err) } result := dbGetSchema(db) if result != DB_CURRENT_VERSION { t.Fatal(fmt.Sprintf("The schema is not at the latest version after update! Found: %d, should be: %d", result, DB_CURRENT_VERSION)) } // Make sure there are 0 containers_config entries left. statements = `SELECT count(*) FROM containers_config;` err = db.QueryRow(statements).Scan(&count) if count != 0 { t.Fatal("updateDb did not delete orphaned child entries after adding ON DELETE CASCADE!") } } func Test_dbImageGet_finds_image_for_fingerprint(t *testing.T) { var db *sql.DB var err error var result *shared.ImageInfo db = createTestDb(t) defer db.Close() _, result, err = dbImageGet(db, "fingerprint", false, false) if err != nil { t.Fatal(err) } if result == nil { t.Fatal("No image returned!") } if result.Filename != "filename" { t.Fatal("Filename should be set.") } if result.CreationDate.UTC() != time.Unix(1431547174, 0).UTC() { t.Fatal(fmt.Sprintf("%s != %s", result.CreationDate, time.Unix(1431547174, 0))) } if result.ExpiryDate.UTC() != time.Unix(1431547175, 0).UTC() { // It was short lived t.Fatal(fmt.Sprintf("%s != %s", result.ExpiryDate, time.Unix(1431547175, 0))) } if result.UploadDate.UTC() != time.Unix(1431547176, 0).UTC() { t.Fatal(fmt.Sprintf("%s != %s", result.UploadDate, time.Unix(1431547176, 0))) } } func Test_dbImageGet_for_missing_fingerprint(t *testing.T) { var db *sql.DB var err error db = createTestDb(t) defer db.Close() _, _, err = dbImageGet(db, "unknown", false, false) if err != sql.ErrNoRows { t.Fatal("Wrong err type returned") } } func Test_dbImageAliasGet_alias_exists(t *testing.T) { var db *sql.DB var err error var result string db = createTestDb(t) defer db.Close() _, alias, err := dbImageAliasGet(db, "somealias", true) result = alias.Target if err != nil { t.Fatal(err) } if result != "fingerprint" { t.Fatal("Fingerprint is not the expected fingerprint!") } } func Test_dbImageAliasGet_alias_does_not_exists(t *testing.T) { var db *sql.DB var err error db = createTestDb(t) defer db.Close() _, _, err = dbImageAliasGet(db, "whatever", true) if err != NoSuchObjectError { t.Fatal("Error should be NoSuchObjectError") } } func Test_dbImageAliasAdd(t *testing.T) { var db *sql.DB var err error var result string db = createTestDb(t) defer db.Close() err = dbImageAliasAdd(db, "Chaosphere", 1, "Someone will like the name") if err != nil { t.Fatal("Error inserting Image alias.") } _, alias, err := dbImageAliasGet(db, "Chaosphere", true) if err != nil { t.Fatal(err) } result = alias.Target if result != "fingerprint" { t.Fatal("Couldn't retrieve newly created alias.") } } func Test_dbContainerConfig(t *testing.T) { var db *sql.DB var err error var result map[string]string var expected map[string]string db = createTestDb(t) defer db.Close() _, err = db.Exec("INSERT INTO containers_config (container_id, key, value) VALUES (1, 'something', 'something else');") result, err = dbContainerConfig(db, 1) if err != nil { t.Fatal(err) } expected = map[string]string{"thekey": "thevalue", "something": "something else"} for key, value := range expected { if result[key] != value { t.Errorf("Mismatching value for key %s: %s != %s", key, result[key], value) } } } func Test_dbProfileConfig(t *testing.T) { var db *sql.DB var err error var result map[string]string var expected map[string]string db = createTestDb(t) defer db.Close() _, err = db.Exec("INSERT INTO profiles_config (profile_id, key, value) VALUES (3, 'something', 'something else');") result, err = dbProfileConfig(db, "theprofile") if err != nil { t.Fatal(err) } expected = map[string]string{"thekey": "thevalue", "something": "something else"} for key, value := range expected { if result[key] != value { t.Errorf("Mismatching value for key %s: %s != %s", key, result[key], value) } } } func Test_dbContainerProfiles(t *testing.T) { var db *sql.DB var err error var result []string var expected []string db = createTestDb(t) defer db.Close() expected = []string{"theprofile"} result, err = dbContainerProfiles(db, 1) if err != nil { t.Fatal(err) } for i := range expected { if expected[i] != result[i] { t.Fatal(fmt.Sprintf("Mismatching contents for profile list: %s != %s", result[i], expected[i])) } } } func Test_dbDevices_profiles(t *testing.T) { var db *sql.DB var err error var result shared.Devices var subresult shared.Device var expected shared.Device db = createTestDb(t) defer db.Close() result, err = dbDevices(db, "theprofile", true) if err != nil { t.Fatal(err) } expected = shared.Device{"type": "nic", "devicekey": "devicevalue"} subresult = result["devicename"] for key, value := range expected { if subresult[key] != value { t.Errorf("Mismatching value for key %s: %v != %v", key, subresult[key], value) } } } func Test_dbDevices_containers(t *testing.T) { var db *sql.DB var err error var result shared.Devices var subresult shared.Device var expected shared.Device db = createTestDb(t) defer db.Close() result, err = dbDevices(db, "thename", false) if err != nil { t.Fatal(err) } expected = shared.Device{"type": "nic", "configkey": "configvalue"} subresult = result["somename"] for key, value := range expected { if subresult[key] != value { t.Errorf("Mismatching value for key %s: %s != %s", key, subresult[key], value) } } } lxd-2.0.0/lxd/db_update.go000066400000000000000000000716351270277227600153750ustar00rootroot00000000000000package main import ( "database/sql" "encoding/hex" "fmt" "os" "os/exec" "path/filepath" "strconv" "strings" "github.com/lxc/lxd/shared" log "gopkg.in/inconshreveable/log15.v2" ) func dbUpdateFromV28(db *sql.DB) error { stmt := ` INSERT INTO profiles_devices (profile_id, name, type) SELECT id, "aadisable", 2 FROM profiles WHERE name="docker"; INSERT INTO profiles_devices_config (profile_device_id, key, value) SELECT profiles_devices.id, "source", "/dev/null" FROM profiles_devices LEFT JOIN profiles WHERE profiles_devices.profile_id = profiles.id AND profiles.name = "docker" AND profiles_devices.name = "aadisable"; INSERT INTO profiles_devices_config (profile_device_id, key, value) SELECT profiles_devices.id, "path", "/sys/module/apparmor/parameters/enabled" FROM profiles_devices LEFT JOIN profiles WHERE profiles_devices.profile_id = profiles.id AND profiles.name = "docker" AND profiles_devices.name = "aadisable";` db.Exec(stmt) stmt = `INSERT INTO schema (version, updated_at) VALUES (?, strftime("%s"));` _, err := db.Exec(stmt, 29) return err } func dbUpdateFromV27(db *sql.DB) error { stmt := ` UPDATE profiles_devices SET type=3 WHERE type='unix-char'; INSERT INTO schema (version, updated_at) VALUES (?, strftime("%s"));` _, err := db.Exec(stmt, 28) return err } func dbUpdateFromV26(db *sql.DB) error { stmt := ` ALTER TABLE images ADD COLUMN auto_update INTEGER NOT NULL DEFAULT 0; CREATE TABLE IF NOT EXISTS images_source ( id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, image_id INTEGER NOT NULL, server TEXT NOT NULL, protocol INTEGER NOT NULL, certificate TEXT NOT NULL, alias VARCHAR(255) NOT NULL, FOREIGN KEY (image_id) REFERENCES images (id) ON DELETE CASCADE ); INSERT INTO schema (version, updated_at) VALUES (?, strftime("%s"));` _, err := db.Exec(stmt, 27) return err } func dbUpdateFromV25(db *sql.DB) error { stmt := ` INSERT INTO profiles (name, description) VALUES ("docker", "Profile supporting docker in containers"); INSERT INTO profiles_config (profile_id, key, value) SELECT id, "security.nesting", "true" FROM profiles WHERE name="docker"; INSERT INTO profiles_config (profile_id, key, value) SELECT id, "linux.kernel_modules", "overlay, nf_nat" FROM profiles WHERE name="docker"; INSERT INTO profiles_devices (profile_id, name, type) SELECT id, "fuse", "unix-char" FROM profiles WHERE name="docker"; INSERT INTO profiles_devices_config (profile_device_id, key, value) SELECT profiles_devices.id, "path", "/dev/fuse" FROM profiles_devices LEFT JOIN profiles WHERE profiles_devices.profile_id = profiles.id AND profiles.name = "docker";` db.Exec(stmt) stmt = `INSERT INTO schema (version, updated_at) VALUES (?, strftime("%s"));` _, err := db.Exec(stmt, 26) return err } func dbUpdateFromV24(db *sql.DB) error { stmt := ` ALTER TABLE containers ADD COLUMN stateful INTEGER NOT NULL DEFAULT 0; INSERT INTO schema (version, updated_at) VALUES (?, strftime("%s"));` _, err := db.Exec(stmt, 25) return err } func dbUpdateFromV23(db *sql.DB) error { stmt := ` ALTER TABLE profiles ADD COLUMN description TEXT; INSERT INTO schema (version, updated_at) VALUES (?, strftime("%s"));` _, err := db.Exec(stmt, 24) return err } func dbUpdateFromV22(db *sql.DB) error { stmt := ` DELETE FROM containers_devices_config WHERE key='type'; DELETE FROM profiles_devices_config WHERE key='type'; INSERT INTO schema (version, updated_at) VALUES (?, strftime("%s"));` _, err := db.Exec(stmt, 23) return err } func dbUpdateFromV21(db *sql.DB) error { stmt := ` ALTER TABLE containers ADD COLUMN creation_date DATETIME NOT NULL DEFAULT 0; INSERT INTO schema (version, updated_at) VALUES (?, strftime("%s"));` _, err := db.Exec(stmt, 22) return err } func dbUpdateFromV20(db *sql.DB) error { stmt := ` UPDATE containers_devices SET name='__lxd_upgrade_root' WHERE name='root'; UPDATE profiles_devices SET name='__lxd_upgrade_root' WHERE name='root'; INSERT INTO containers_devices (container_id, name, type) SELECT id, "root", 2 FROM containers; INSERT INTO containers_devices_config (container_device_id, key, value) SELECT id, "path", "/" FROM containers_devices WHERE name='root'; INSERT INTO schema (version, updated_at) VALUES (?, strftime("%s"));` _, err := db.Exec(stmt, 21) return err } func dbUpdateFromV19(db *sql.DB) error { stmt := ` DELETE FROM containers_config WHERE container_id NOT IN (SELECT id FROM containers); DELETE FROM containers_devices_config WHERE container_device_id NOT IN (SELECT id FROM containers_devices WHERE container_id IN (SELECT id FROM containers)); DELETE FROM containers_devices WHERE container_id NOT IN (SELECT id FROM containers); DELETE FROM containers_profiles WHERE container_id NOT IN (SELECT id FROM containers); DELETE FROM images_aliases WHERE image_id NOT IN (SELECT id FROM images); DELETE FROM images_properties WHERE image_id NOT IN (SELECT id FROM images); INSERT INTO schema (version, updated_at) VALUES (?, strftime("%s"));` _, err := db.Exec(stmt, 20) return err } func dbUpdateFromV18(db *sql.DB) error { var id int var value string // Update container config rows, err := dbQueryScan(db, "SELECT id, value FROM containers_config WHERE key='limits.memory'", nil, []interface{}{id, value}) if err != nil { return err } for _, row := range rows { id = row[0].(int) value = row[1].(string) // If already an integer, don't touch _, err := strconv.Atoi(value) if err == nil { continue } // Generate the new value value = strings.ToUpper(value) value += "B" // Deal with completely broken values _, err = shared.ParseByteSizeString(value) if err != nil { shared.Debugf("Invalid container memory limit, id=%d value=%s, removing.", id, value) _, err = db.Exec("DELETE FROM containers_config WHERE id=?;", id) if err != nil { return err } } // Set the new value _, err = db.Exec("UPDATE containers_config SET value=? WHERE id=?", value, id) if err != nil { return err } } // Update profiles config rows, err = dbQueryScan(db, "SELECT id, value FROM profiles_config WHERE key='limits.memory'", nil, []interface{}{id, value}) if err != nil { return err } for _, row := range rows { id = row[0].(int) value = row[1].(string) // If already an integer, don't touch _, err := strconv.Atoi(value) if err == nil { continue } // Generate the new value value = strings.ToUpper(value) value += "B" // Deal with completely broken values _, err = shared.ParseByteSizeString(value) if err != nil { shared.Debugf("Invalid profile memory limit, id=%d value=%s, removing.", id, value) _, err = db.Exec("DELETE FROM profiles_config WHERE id=?;", id) if err != nil { return err } } // Set the new value _, err = db.Exec("UPDATE profiles_config SET value=? WHERE id=?", value, id) if err != nil { return err } } _, err = db.Exec("INSERT INTO schema (version, updated_at) VALUES (?, strftime(\"%s\"));", 19) return err } func dbUpdateFromV17(db *sql.DB) error { stmt := ` DELETE FROM profiles_config WHERE key LIKE 'volatile.%'; UPDATE containers_config SET key='limits.cpu' WHERE key='limits.cpus'; UPDATE profiles_config SET key='limits.cpu' WHERE key='limits.cpus'; INSERT INTO schema (version, updated_at) VALUES (?, strftime("%s"));` _, err := db.Exec(stmt, 18) return err } func dbUpdateFromV16(db *sql.DB) error { stmt := ` UPDATE config SET key='storage.lvm_vg_name' WHERE key = 'core.lvm_vg_name'; UPDATE config SET key='storage.lvm_thinpool_name' WHERE key = 'core.lvm_thinpool_name'; INSERT INTO schema (version, updated_at) VALUES (?, strftime("%s"));` _, err := db.Exec(stmt, 17) return err } func dbUpdateFromV15(d *Daemon) error { // munge all LVM-backed containers' LV names to match what is // required for snapshot support cNames, err := dbContainersList(d.db, cTypeRegular) if err != nil { return err } vgName, err := d.ConfigValueGet("storage.lvm_vg_name") if err != nil { return fmt.Errorf("Error checking server config: %v", err) } for _, cName := range cNames { var lvLinkPath string if strings.Contains(cName, shared.SnapshotDelimiter) { lvLinkPath = shared.VarPath("snapshots", fmt.Sprintf("%s.lv", cName)) } else { lvLinkPath = shared.VarPath("containers", fmt.Sprintf("%s.lv", cName)) } if !shared.PathExists(lvLinkPath) { continue } newLVName := strings.Replace(cName, "-", "--", -1) newLVName = strings.Replace(newLVName, shared.SnapshotDelimiter, "-", -1) if cName == newLVName { shared.Log.Debug("No need to rename, skipping", log.Ctx{"cName": cName, "newLVName": newLVName}) continue } shared.Log.Debug("About to rename cName in lv upgrade", log.Ctx{"lvLinkPath": lvLinkPath, "cName": cName, "newLVName": newLVName}) output, err := exec.Command("lvrename", vgName, cName, newLVName).CombinedOutput() if err != nil { return fmt.Errorf("Could not rename LV '%s' to '%s': %v\noutput:%s", cName, newLVName, err, string(output)) } if err := os.Remove(lvLinkPath); err != nil { return fmt.Errorf("Couldn't remove lvLinkPath '%s'", lvLinkPath) } newLinkDest := fmt.Sprintf("/dev/%s/%s", vgName, newLVName) if err := os.Symlink(newLinkDest, lvLinkPath); err != nil { return fmt.Errorf("Couldn't recreate symlink '%s'->'%s'", lvLinkPath, newLinkDest) } } stmt := ` INSERT INTO schema (version, updated_at) VALUES (?, strftime("%s"));` _, err = d.db.Exec(stmt, 16) return err } func dbUpdateFromV14(db *sql.DB) error { stmt := ` PRAGMA foreign_keys=OFF; -- So that integrity doesn't get in the way for now DELETE FROM containers_config WHERE key="volatile.last_state.power"; INSERT INTO containers_config (container_id, key, value) SELECT id, "volatile.last_state.power", "RUNNING" FROM containers WHERE power_state=1; INSERT INTO containers_config (container_id, key, value) SELECT id, "volatile.last_state.power", "STOPPED" FROM containers WHERE power_state != 1; CREATE TABLE tmp ( id INTEGER primary key AUTOINCREMENT NOT NULL, name VARCHAR(255) NOT NULL, architecture INTEGER NOT NULL, type INTEGER NOT NULL, ephemeral INTEGER NOT NULL DEFAULT 0, UNIQUE (name) ); INSERT INTO tmp SELECT id, name, architecture, type, ephemeral FROM containers; DROP TABLE containers; ALTER TABLE tmp RENAME TO containers; PRAGMA foreign_keys=ON; -- Make sure we turn integrity checks back on. INSERT INTO schema (version, updated_at) VALUES (?, strftime("%s"));` _, err := db.Exec(stmt, 15) return err } func dbUpdateFromV13(db *sql.DB) error { stmt := ` UPDATE containers_config SET key='volatile.base_image' WHERE key = 'volatile.baseImage'; INSERT INTO schema (version, updated_at) VALUES (?, strftime("%s"));` _, err := db.Exec(stmt, 14) return err } func dbUpdateFromV12(db *sql.DB) error { stmt := ` ALTER TABLE images ADD COLUMN cached INTEGER NOT NULL DEFAULT 0; ALTER TABLE images ADD COLUMN last_use_date DATETIME; INSERT INTO schema (version, updated_at) VALUES (?, strftime("%s"));` _, err := db.Exec(stmt, 13) return err } func dbUpdateFromV11(d *Daemon) error { if d.MockMode { // No need to move snapshots no mock runs, // dbUpdateFromV12 will then set the db version to 13 return nil } cNames, err := dbContainersList(d.db, cTypeSnapshot) if err != nil { return err } errors := 0 for _, cName := range cNames { snappieces := strings.SplitN(cName, shared.SnapshotDelimiter, 2) oldPath := shared.VarPath("containers", snappieces[0], "snapshots", snappieces[1]) newPath := shared.VarPath("snapshots", snappieces[0], snappieces[1]) if shared.PathExists(oldPath) && !shared.PathExists(newPath) { shared.Log.Info( "Moving snapshot", log.Ctx{ "snapshot": cName, "oldPath": oldPath, "newPath": newPath}) // Rsync // containers//snapshots/ // to // snapshots// output, err := storageRsyncCopy(oldPath, newPath) if err != nil { shared.Log.Error( "Failed rsync snapshot", log.Ctx{ "snapshot": cName, "output": string(output), "err": err}) errors++ continue } // Remove containers//snapshots/ if err := os.RemoveAll(oldPath); err != nil { shared.Log.Error( "Failed to remove the old snapshot path", log.Ctx{ "snapshot": cName, "oldPath": oldPath, "err": err}) // Ignore this error. // errors++ // continue } // Remove /var/lib/lxd/containers//snapshots // if its empty. cPathParent := filepath.Dir(oldPath) if ok, _ := shared.PathIsEmpty(cPathParent); ok { os.Remove(cPathParent) } } // if shared.PathExists(oldPath) && !shared.PathExists(newPath) { } // for _, cName := range cNames { // Refuse to start lxd if a rsync failed. if errors > 0 { return fmt.Errorf("Got errors while moving snapshots, see the log output.") } stmt := ` INSERT INTO schema (version, updated_at) VALUES (?, strftime("%s"));` _, err = d.db.Exec(stmt, 12) return err } func dbUpdateFromV10(d *Daemon) error { if d.MockMode { // No need to move lxc to containers in mock runs, // dbUpdateFromV12 will then set the db version to 13 return nil } if shared.PathExists(shared.VarPath("lxc")) { err := os.Rename(shared.VarPath("lxc"), shared.VarPath("containers")) if err != nil { return err } shared.Debugf("Restarting all the containers following directory rename") containersShutdown(d) containersRestart(d) } stmt := ` INSERT INTO schema (version, updated_at) VALUES (?, strftime("%s"));` _, err := d.db.Exec(stmt, 11) return err } func dbUpdateFromV9(db *sql.DB) error { stmt := ` CREATE TABLE tmp ( id INTEGER primary key AUTOINCREMENT NOT NULL, container_id INTEGER NOT NULL, name VARCHAR(255) NOT NULL, type VARCHAR(255) NOT NULL default "none", FOREIGN KEY (container_id) REFERENCES containers (id) ON DELETE CASCADE, UNIQUE (container_id, name) ); INSERT INTO tmp SELECT * FROM containers_devices; UPDATE containers_devices SET type=0 WHERE id IN (SELECT id FROM tmp WHERE type="none"); UPDATE containers_devices SET type=1 WHERE id IN (SELECT id FROM tmp WHERE type="nic"); UPDATE containers_devices SET type=2 WHERE id IN (SELECT id FROM tmp WHERE type="disk"); UPDATE containers_devices SET type=3 WHERE id IN (SELECT id FROM tmp WHERE type="unix-char"); UPDATE containers_devices SET type=4 WHERE id IN (SELECT id FROM tmp WHERE type="unix-block"); DROP TABLE tmp; CREATE TABLE tmp ( id INTEGER primary key AUTOINCREMENT NOT NULL, profile_id INTEGER NOT NULL, name VARCHAR(255) NOT NULL, type VARCHAR(255) NOT NULL default "none", FOREIGN KEY (profile_id) REFERENCES profiles (id) ON DELETE CASCADE, UNIQUE (profile_id, name) ); INSERT INTO tmp SELECT * FROM profiles_devices; UPDATE profiles_devices SET type=0 WHERE id IN (SELECT id FROM tmp WHERE type="none"); UPDATE profiles_devices SET type=1 WHERE id IN (SELECT id FROM tmp WHERE type="nic"); UPDATE profiles_devices SET type=2 WHERE id IN (SELECT id FROM tmp WHERE type="disk"); UPDATE profiles_devices SET type=3 WHERE id IN (SELECT id FROM tmp WHERE type="unix-char"); UPDATE profiles_devices SET type=4 WHERE id IN (SELECT id FROM tmp WHERE type="unix-block"); DROP TABLE tmp; INSERT INTO schema (version, updated_at) VALUES (?, strftime("%s"));` _, err := db.Exec(stmt, 10) return err } func dbUpdateFromV8(db *sql.DB) error { stmt := ` UPDATE certificates SET fingerprint = replace(fingerprint, " ", ""); INSERT INTO schema (version, updated_at) VALUES (?, strftime("%s"));` _, err := db.Exec(stmt, 9) return err } func dbUpdateFromV7(db *sql.DB) error { stmt := ` UPDATE config SET key='core.trust_password' WHERE key IN ('password', 'trust_password', 'trust-password', 'core.trust-password'); DELETE FROM config WHERE key != 'core.trust_password'; INSERT INTO schema (version, updated_at) VALUES (?, strftime("%s"));` _, err := db.Exec(stmt, 8) return err } func dbUpdateFromV6(db *sql.DB) error { // This update recreates the schemas that need an ON DELETE CASCADE foreign // key. stmt := ` PRAGMA foreign_keys=OFF; -- So that integrity doesn't get in the way for now CREATE TEMP TABLE tmp AS SELECT * FROM containers_config; DROP TABLE containers_config; CREATE TABLE IF NOT EXISTS containers_config ( id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, container_id INTEGER NOT NULL, key VARCHAR(255) NOT NULL, value TEXT, FOREIGN KEY (container_id) REFERENCES containers (id) ON DELETE CASCADE, UNIQUE (container_id, key) ); INSERT INTO containers_config SELECT * FROM tmp; DROP TABLE tmp; CREATE TEMP TABLE tmp AS SELECT * FROM containers_devices; DROP TABLE containers_devices; CREATE TABLE IF NOT EXISTS containers_devices ( id INTEGER primary key AUTOINCREMENT NOT NULL, container_id INTEGER NOT NULL, name VARCHAR(255) NOT NULL, type INTEGER NOT NULL default 0, FOREIGN KEY (container_id) REFERENCES containers (id) ON DELETE CASCADE, UNIQUE (container_id, name) ); INSERT INTO containers_devices SELECT * FROM tmp; DROP TABLE tmp; CREATE TEMP TABLE tmp AS SELECT * FROM containers_devices_config; DROP TABLE containers_devices_config; CREATE TABLE IF NOT EXISTS containers_devices_config ( id INTEGER primary key AUTOINCREMENT NOT NULL, container_device_id INTEGER NOT NULL, key VARCHAR(255) NOT NULL, value TEXT, FOREIGN KEY (container_device_id) REFERENCES containers_devices (id) ON DELETE CASCADE, UNIQUE (container_device_id, key) ); INSERT INTO containers_devices_config SELECT * FROM tmp; DROP TABLE tmp; CREATE TEMP TABLE tmp AS SELECT * FROM containers_profiles; DROP TABLE containers_profiles; CREATE TABLE IF NOT EXISTS containers_profiles ( id INTEGER primary key AUTOINCREMENT NOT NULL, container_id INTEGER NOT NULL, profile_id INTEGER NOT NULL, apply_order INTEGER NOT NULL default 0, UNIQUE (container_id, profile_id), FOREIGN KEY (container_id) REFERENCES containers(id) ON DELETE CASCADE, FOREIGN KEY (profile_id) REFERENCES profiles(id) ON DELETE CASCADE ); INSERT INTO containers_profiles SELECT * FROM tmp; DROP TABLE tmp; CREATE TEMP TABLE tmp AS SELECT * FROM images_aliases; DROP TABLE images_aliases; CREATE TABLE IF NOT EXISTS images_aliases ( id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, name VARCHAR(255) NOT NULL, image_id INTEGER NOT NULL, description VARCHAR(255), FOREIGN KEY (image_id) REFERENCES images (id) ON DELETE CASCADE, UNIQUE (name) ); INSERT INTO images_aliases SELECT * FROM tmp; DROP TABLE tmp; CREATE TEMP TABLE tmp AS SELECT * FROM images_properties; DROP TABLE images_properties; CREATE TABLE IF NOT EXISTS images_properties ( id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, image_id INTEGER NOT NULL, type INTEGER NOT NULL, key VARCHAR(255) NOT NULL, value TEXT, FOREIGN KEY (image_id) REFERENCES images (id) ON DELETE CASCADE ); INSERT INTO images_properties SELECT * FROM tmp; DROP TABLE tmp; CREATE TEMP TABLE tmp AS SELECT * FROM profiles_config; DROP TABLE profiles_config; CREATE TABLE IF NOT EXISTS profiles_config ( id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, profile_id INTEGER NOT NULL, key VARCHAR(255) NOT NULL, value VARCHAR(255), UNIQUE (profile_id, key), FOREIGN KEY (profile_id) REFERENCES profiles(id) ON DELETE CASCADE ); INSERT INTO profiles_config SELECT * FROM tmp; DROP TABLE tmp; CREATE TEMP TABLE tmp AS SELECT * FROM profiles_devices; DROP TABLE profiles_devices; CREATE TABLE IF NOT EXISTS profiles_devices ( id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, profile_id INTEGER NOT NULL, name VARCHAR(255) NOT NULL, type INTEGER NOT NULL default 0, UNIQUE (profile_id, name), FOREIGN KEY (profile_id) REFERENCES profiles (id) ON DELETE CASCADE ); INSERT INTO profiles_devices SELECT * FROM tmp; DROP TABLE tmp; CREATE TEMP TABLE tmp AS SELECT * FROM profiles_devices_config; DROP TABLE profiles_devices_config; CREATE TABLE IF NOT EXISTS profiles_devices_config ( id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, profile_device_id INTEGER NOT NULL, key VARCHAR(255) NOT NULL, value TEXT, UNIQUE (profile_device_id, key), FOREIGN KEY (profile_device_id) REFERENCES profiles_devices (id) ON DELETE CASCADE ); INSERT INTO profiles_devices_config SELECT * FROM tmp; DROP TABLE tmp; PRAGMA foreign_keys=ON; -- Make sure we turn integrity checks back on. INSERT INTO schema (version, updated_at) VALUES (?, strftime("%s"));` _, err := db.Exec(stmt, 7) if err != nil { return err } // Get the rows with broken foreign keys an nuke them rows, err := db.Query("PRAGMA foreign_key_check;") if err != nil { return err } var tablestodelete []string var rowidtodelete []int defer rows.Close() for rows.Next() { var tablename string var rowid int var targetname string var keynumber int rows.Scan(&tablename, &rowid, &targetname, &keynumber) tablestodelete = append(tablestodelete, tablename) rowidtodelete = append(rowidtodelete, rowid) } rows.Close() for i := range tablestodelete { _, err = db.Exec(fmt.Sprintf("DELETE FROM %s WHERE rowid = %d;", tablestodelete[i], rowidtodelete[i])) if err != nil { return err } } return err } func dbUpdateFromV5(db *sql.DB) error { stmt := ` ALTER TABLE containers ADD COLUMN power_state INTEGER NOT NULL DEFAULT 0; ALTER TABLE containers ADD COLUMN ephemeral INTEGER NOT NULL DEFAULT 0; INSERT INTO schema (version, updated_at) VALUES (?, strftime("%s"));` _, err := db.Exec(stmt, 6) return err } func dbUpdateFromV4(db *sql.DB) error { stmt := ` CREATE TABLE IF NOT EXISTS config ( id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, key VARCHAR(255) NOT NULL, value TEXT, UNIQUE (key) ); INSERT INTO schema (version, updated_at) VALUES (?, strftime("%s"));` _, err := db.Exec(stmt, 5) if err != nil { return err } passfname := shared.VarPath("adminpwd") passOut, err := os.Open(passfname) oldPassword := "" if err == nil { defer passOut.Close() buff := make([]byte, 96) _, err = passOut.Read(buff) if err != nil { return err } oldPassword = hex.EncodeToString(buff) stmt := `INSERT INTO config (key, value) VALUES ("core.trust_password", ?);` _, err := db.Exec(stmt, oldPassword) if err != nil { return err } return os.Remove(passfname) } return nil } func dbUpdateFromV3(db *sql.DB) error { // Attempt to create a default profile (but don't fail if already there) stmt := `INSERT INTO profiles (name) VALUES ("default"); INSERT INTO profiles_devices (profile_id, name, type) SELECT id, "eth0", "nic" FROM profiles WHERE profiles.name="default"; INSERT INTO profiles_devices_config (profile_device_id, key, value) SELECT profiles_devices.id, "nictype", "bridged" FROM profiles_devices LEFT JOIN profiles ON profiles.id=profiles_devices.profile_id WHERE profiles.name == "default"; INSERT INTO profiles_devices_config (profile_device_id, key, value) SELECT profiles_devices.id, 'name', "eth0" FROM profiles_devices LEFT JOIN profiles ON profiles.id=profiles_devices.profile_id WHERE profiles.name == "default"; INSERT INTO profiles_devices_config (profile_device_id, key, value) SELECT profiles_devices.id, "parent", "lxdbr0" FROM profiles_devices LEFT JOIN profiles ON profiles.id=profiles_devices.profile_id WHERE profiles.name == "default";` db.Exec(stmt) stmt = `INSERT INTO schema (version, updated_at) VALUES (?, strftime("%s"));` _, err := db.Exec(stmt, 4) return err } func dbUpdateFromV2(db *sql.DB) error { stmt := ` CREATE TABLE IF NOT EXISTS containers_devices ( id INTEGER primary key AUTOINCREMENT NOT NULL, container_id INTEGER NOT NULL, name VARCHAR(255) NOT NULL, type INTEGER NOT NULL default 0, FOREIGN KEY (container_id) REFERENCES containers (id) ON DELETE CASCADE, UNIQUE (container_id, name) ); CREATE TABLE IF NOT EXISTS containers_devices_config ( id INTEGER primary key AUTOINCREMENT NOT NULL, container_device_id INTEGER NOT NULL, key VARCHAR(255) NOT NULL, value TEXT, FOREIGN KEY (container_device_id) REFERENCES containers_devices (id), UNIQUE (container_device_id, key) ); CREATE TABLE IF NOT EXISTS containers_profiles ( id INTEGER primary key AUTOINCREMENT NOT NULL, container_id INTEGER NOT NULL, profile_id INTEGER NOT NULL, apply_order INTEGER NOT NULL default 0, UNIQUE (container_id, profile_id), FOREIGN KEY (container_id) REFERENCES containers(id) ON DELETE CASCADE, FOREIGN KEY (profile_id) REFERENCES profiles(id) ON DELETE CASCADE ); CREATE TABLE IF NOT EXISTS profiles ( id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, name VARCHAR(255) NOT NULL, UNIQUE (name) ); CREATE TABLE IF NOT EXISTS profiles_config ( id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, profile_id INTEGER NOT NULL, key VARCHAR(255) NOT NULL, value VARCHAR(255), UNIQUE (profile_id, key), FOREIGN KEY (profile_id) REFERENCES profiles(id) ON DELETE CASCADE ); CREATE TABLE IF NOT EXISTS profiles_devices ( id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, profile_id INTEGER NOT NULL, name VARCHAR(255) NOT NULL, type INTEGER NOT NULL default 0, UNIQUE (profile_id, name), FOREIGN KEY (profile_id) REFERENCES profiles (id) ON DELETE CASCADE ); CREATE TABLE IF NOT EXISTS profiles_devices_config ( id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, profile_device_id INTEGER NOT NULL, key VARCHAR(255) NOT NULL, value TEXT, UNIQUE (profile_device_id, key), FOREIGN KEY (profile_device_id) REFERENCES profiles_devices (id) ); INSERT INTO schema (version, updated_at) VALUES (?, strftime("%s"));` _, err := db.Exec(stmt, 3) return err } /* Yeah we can do htis in a more clever way */ func dbUpdateFromV1(db *sql.DB) error { // v1..v2 adds images aliases stmt := ` CREATE TABLE IF NOT EXISTS images_aliases ( id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, name VARCHAR(255) NOT NULL, image_id INTEGER NOT NULL, description VARCHAR(255), FOREIGN KEY (image_id) REFERENCES images (id) ON DELETE CASCADE, UNIQUE (name) ); INSERT INTO schema (version, updated_at) VALUES (?, strftime("%s"));` _, err := db.Exec(stmt, 2) return err } func dbUpdateFromV0(db *sql.DB) error { // v0..v1 adds schema table stmt := ` CREATE TABLE IF NOT EXISTS schema ( id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, version INTEGER NOT NULL, updated_at DATETIME NOT NULL, UNIQUE (version) ); INSERT INTO schema (version, updated_at) VALUES (?, strftime("%s"));` _, err := db.Exec(stmt, 1) return err } func dbUpdate(d *Daemon, prevVersion int) error { db := d.db if prevVersion < 0 || prevVersion > DB_CURRENT_VERSION { return fmt.Errorf("Bad database version: %d", prevVersion) } if prevVersion == DB_CURRENT_VERSION { return nil } var err error if prevVersion < 1 { err = dbUpdateFromV0(db) if err != nil { return err } } if prevVersion < 2 { err = dbUpdateFromV1(db) if err != nil { return err } } if prevVersion < 3 { err = dbUpdateFromV2(db) if err != nil { return err } } if prevVersion < 4 { err = dbUpdateFromV3(db) if err != nil { return err } } if prevVersion < 5 { err = dbUpdateFromV4(db) if err != nil { return err } } if prevVersion < 6 { err = dbUpdateFromV5(db) if err != nil { return err } } if prevVersion < 7 { err = dbUpdateFromV6(db) if err != nil { return err } } if prevVersion < 8 { err = dbUpdateFromV7(db) if err != nil { return err } } if prevVersion < 9 { err = dbUpdateFromV8(db) if err != nil { return err } } if prevVersion < 10 { err = dbUpdateFromV9(db) if err != nil { return err } } if prevVersion < 11 { err = dbUpdateFromV10(d) if err != nil { return err } } if prevVersion < 12 { err = dbUpdateFromV11(d) if err != nil { return err } } if prevVersion < 13 { err = dbUpdateFromV12(db) if err != nil { return err } } if prevVersion < 14 { err = dbUpdateFromV13(db) if err != nil { return err } } if prevVersion < 15 { err = dbUpdateFromV14(db) if err != nil { return err } } if prevVersion < 16 { err = dbUpdateFromV15(d) if err != nil { return err } } if prevVersion < 17 { err = dbUpdateFromV16(db) if err != nil { return err } } if prevVersion < 18 { err = dbUpdateFromV17(db) if err != nil { return err } } if prevVersion < 19 { err = dbUpdateFromV18(db) if err != nil { return err } } if prevVersion < 20 { err = dbUpdateFromV19(db) if err != nil { return err } } if prevVersion < 21 { err = dbUpdateFromV20(db) if err != nil { return err } } if prevVersion < 22 { err = dbUpdateFromV21(db) if err != nil { return err } } if prevVersion < 23 { err = dbUpdateFromV22(db) if err != nil { return err } } if prevVersion < 24 { err = dbUpdateFromV23(db) if err != nil { return err } } if prevVersion < 25 { err = dbUpdateFromV24(db) if err != nil { return err } } if prevVersion < 26 { err = dbUpdateFromV25(db) if err != nil { return err } } if prevVersion < 27 { err = dbUpdateFromV26(db) if err != nil { return err } } if prevVersion < 28 { err = dbUpdateFromV27(db) if err != nil { return err } } if prevVersion < 29 { err = dbUpdateFromV28(db) if err != nil { return err } } return nil } lxd-2.0.0/lxd/debug.go000066400000000000000000000010131270277227600145130ustar00rootroot00000000000000package main import ( "os" "os/signal" "runtime/pprof" "syscall" "github.com/lxc/lxd/shared" ) func doMemDump(memProfile string) { f, err := os.Create(memProfile) if err != nil { shared.Debugf("Error opening memory profile file '%s': %s", err) return } pprof.WriteHeapProfile(f) f.Close() } func memProfiler(memProfile string) { ch := make(chan os.Signal) signal.Notify(ch, syscall.SIGUSR1) for { sig := <-ch shared.Debugf("Received '%s signal', dumping memory.", sig) doMemDump(memProfile) } } lxd-2.0.0/lxd/devices.go000066400000000000000000000437661270277227600150740ustar00rootroot00000000000000package main import ( "bufio" "bytes" "crypto/rand" "encoding/hex" "fmt" "math/big" "os" "os/exec" "path" "path/filepath" "sort" "strconv" "strings" "syscall" _ "github.com/mattn/go-sqlite3" "github.com/lxc/lxd/shared" log "gopkg.in/inconshreveable/log15.v2" ) var deviceSchedRebalance = make(chan []string, 2) type deviceBlockLimit struct { readBps int64 readIops int64 writeBps int64 writeIops int64 } type deviceTaskCPU struct { id int strId string count *int } type deviceTaskCPUs []deviceTaskCPU func (c deviceTaskCPUs) Len() int { return len(c) } func (c deviceTaskCPUs) Less(i, j int) bool { return *c[i].count < *c[j].count } func (c deviceTaskCPUs) Swap(i, j int) { c[i], c[j] = c[j], c[i] } func deviceNetlinkListener() (chan []string, chan []string, error) { NETLINK_KOBJECT_UEVENT := 15 UEVENT_BUFFER_SIZE := 2048 fd, err := syscall.Socket( syscall.AF_NETLINK, syscall.SOCK_RAW, NETLINK_KOBJECT_UEVENT, ) if err != nil { return nil, nil, err } nl := syscall.SockaddrNetlink{ Family: syscall.AF_NETLINK, Pid: uint32(os.Getpid()), Groups: 1, } err = syscall.Bind(fd, &nl) if err != nil { return nil, nil, err } chCPU := make(chan []string, 1) chNetwork := make(chan []string, 0) go func(chCPU chan []string, chNetwork chan []string) { b := make([]byte, UEVENT_BUFFER_SIZE*2) for { _, err := syscall.Read(fd, b) if err != nil { continue } props := map[string]string{} last := 0 for i, e := range b { if i == len(b) || e == 0 { msg := string(b[last+1 : i]) last = i if len(msg) == 0 || msg == "\x00" { continue } fields := strings.SplitN(msg, "=", 2) if len(fields) != 2 { continue } props[fields[0]] = fields[1] } } if props["SUBSYSTEM"] == "cpu" { if props["DRIVER"] != "processor" { continue } if props["ACTION"] != "offline" && props["ACTION"] != "online" { continue } // As CPU re-balancing affects all containers, no need to queue them select { case chCPU <- []string{path.Base(props["DEVPATH"]), props["ACTION"]}: default: // Channel is full, drop the event } } if props["SUBSYSTEM"] == "net" { if props["ACTION"] != "add" && props["ACTION"] != "removed" { continue } if !shared.PathExists(fmt.Sprintf("/sys/class/net/%s", props["INTERFACE"])) { continue } // Network balancing is interface specific, so queue everything chNetwork <- []string{props["INTERFACE"], props["ACTION"]} } } }(chCPU, chNetwork) return chCPU, chNetwork, nil } func parseCpuset(cpu string) ([]int, error) { cpus := []int{} chunks := strings.Split(cpu, ",") for _, chunk := range chunks { if strings.Contains(chunk, "-") { // Range fields := strings.SplitN(chunk, "-", 2) if len(fields) != 2 { return nil, fmt.Errorf("Invalid cpuset value: %s", cpu) } low, err := strconv.Atoi(fields[0]) if err != nil { return nil, fmt.Errorf("Invalid cpuset value: %s", cpu) } high, err := strconv.Atoi(fields[1]) if err != nil { return nil, fmt.Errorf("Invalid cpuset value: %s", cpu) } for i := low; i <= high; i++ { cpus = append(cpus, i) } } else { // Simple entry nr, err := strconv.Atoi(chunk) if err != nil { return nil, fmt.Errorf("Invalid cpuset value: %s", cpu) } cpus = append(cpus, nr) } } return cpus, nil } func deviceTaskBalance(d *Daemon) { min := func(x, y int) int { if x < y { return x } return y } // Don't bother running when CGroup support isn't there if !cgCpusetController { return } // Get effective cpus list - those are all guaranteed to be online effectiveCpus, err := cGroupGet("cpuset", "/", "cpuset.effective_cpus") if err != nil { shared.Log.Error("Error reading host's cpuset.effective_cpus") return } err = cGroupSet("cpuset", "/lxc", "cpuset.cpus", effectiveCpus) if err != nil && shared.PathExists("/sys/fs/cgroup/cpuset/lxc") { shared.Log.Warn("Error setting lxd's cpuset.cpus", log.Ctx{"err": err}) } cpus, err := parseCpuset(effectiveCpus) if err != nil { shared.Log.Error("Error parsing host's cpuset.effective_cpus", log.Ctx{"cpuset": effectiveCpus, "err": err}) return } // Iterate through the containers containers, err := dbContainersList(d.db, cTypeRegular) fixedContainers := map[int][]container{} balancedContainers := map[container]int{} for _, name := range containers { c, err := containerLoadByName(d, name) if err != nil { continue } conf := c.ExpandedConfig() cpulimit, ok := conf["limits.cpu"] if !ok || cpulimit == "" { cpulimit = effectiveCpus } if !c.IsRunning() { continue } count, err := strconv.Atoi(cpulimit) if err == nil { // Load-balance count = min(count, len(cpus)) balancedContainers[c] = count } else { // Pinned containerCpus, err := parseCpuset(cpulimit) if err != nil { return } for _, nr := range containerCpus { if !shared.IntInSlice(nr, cpus) { continue } _, ok := fixedContainers[nr] if ok { fixedContainers[nr] = append(fixedContainers[nr], c) } else { fixedContainers[nr] = []container{c} } } } } // Balance things pinning := map[container][]string{} usage := map[int]deviceTaskCPU{} for _, id := range cpus { cpu := deviceTaskCPU{} cpu.id = id cpu.strId = fmt.Sprintf("%d", id) count := 0 cpu.count = &count usage[id] = cpu } for cpu, ctns := range fixedContainers { c, ok := usage[cpu] if !ok { shared.Log.Error("Internal error: container using unavailable cpu") continue } id := c.strId for _, ctn := range ctns { _, ok := pinning[ctn] if ok { pinning[ctn] = append(pinning[ctn], id) } else { pinning[ctn] = []string{id} } *c.count += 1 } } sortedUsage := make(deviceTaskCPUs, 0) for _, value := range usage { sortedUsage = append(sortedUsage, value) } for ctn, count := range balancedContainers { sort.Sort(sortedUsage) for _, cpu := range sortedUsage { if count == 0 { break } count -= 1 id := cpu.strId _, ok := pinning[ctn] if ok { pinning[ctn] = append(pinning[ctn], id) } else { pinning[ctn] = []string{id} } *cpu.count += 1 } } // Set the new pinning for ctn, set := range pinning { // Confirm the container didn't just stop if !ctn.IsRunning() { continue } sort.Strings(set) err := ctn.CGroupSet("cpuset.cpus", strings.Join(set, ",")) if err != nil { shared.Log.Error("balance: Unable to set cpuset", log.Ctx{"name": ctn.Name(), "err": err, "value": strings.Join(set, ",")}) } } } func deviceNetworkPriority(d *Daemon, netif string) { // Don't bother running when CGroup support isn't there if !cgNetPrioController { return } containers, err := dbContainersList(d.db, cTypeRegular) if err != nil { return } for _, name := range containers { // Get the container struct c, err := containerLoadByName(d, name) if err != nil { continue } // Extract the current priority networkPriority := c.ExpandedConfig()["limits.network.priority"] if networkPriority == "" { continue } networkInt, err := strconv.Atoi(networkPriority) if err != nil { continue } // Set the value for the new interface c.CGroupSet("net_prio.ifpriomap", fmt.Sprintf("%s %d", netif, networkInt)) } return } func deviceEventListener(d *Daemon) { chNetlinkCPU, chNetlinkNetwork, err := deviceNetlinkListener() if err != nil { shared.Log.Error("scheduler: couldn't setup netlink listener") return } for { select { case e := <-chNetlinkCPU: if len(e) != 2 { shared.Log.Error("Scheduler: received an invalid cpu hotplug event") continue } if !cgCpusetController { continue } shared.Debugf("Scheduler: cpu: %s is now %s: re-balancing", e[0], e[1]) deviceTaskBalance(d) case e := <-chNetlinkNetwork: if len(e) != 2 { shared.Log.Error("Scheduler: received an invalid network hotplug event") continue } if !cgNetPrioController { continue } shared.Debugf("Scheduler: network: %s has been added: updating network priorities", e[0]) deviceNetworkPriority(d, e[0]) case e := <-deviceSchedRebalance: if len(e) != 3 { shared.Log.Error("Scheduler: received an invalid rebalance event") continue } if !cgCpusetController { continue } shared.Debugf("Scheduler: %s %s %s: re-balancing", e[0], e[1], e[2]) deviceTaskBalance(d) } } } func deviceTaskSchedulerTrigger(srcType string, srcName string, srcStatus string) { // Spawn a go routine which then triggers the scheduler select { case deviceSchedRebalance <- []string{srcType, srcName, srcStatus}: default: // Channel is full, drop the event } } func deviceIsBlockdev(path string) bool { // Get a stat struct from the provided path stat := syscall.Stat_t{} err := syscall.Stat(path, &stat) if err != nil { return false } // Check if it's a block device if stat.Mode&syscall.S_IFMT == syscall.S_IFBLK { return true } // Not a device return false } func deviceModeOct(strmode string) (int, error) { // Default mode if strmode == "" { return 0600, nil } // Converted mode i, err := strconv.ParseInt(strmode, 8, 32) if err != nil { return 0, fmt.Errorf("Bad device mode: %s", strmode) } return int(i), nil } func deviceGetAttributes(path string) (string, int, int, error) { // Get a stat struct from the provided path stat := syscall.Stat_t{} err := syscall.Stat(path, &stat) if err != nil { return "", 0, 0, err } // Check what kind of file it is dType := "" if stat.Mode&syscall.S_IFMT == syscall.S_IFBLK { dType = "b" } else if stat.Mode&syscall.S_IFMT == syscall.S_IFCHR { dType = "c" } else { return "", 0, 0, fmt.Errorf("Not a device") } // Return the device information major := int(stat.Rdev / 256) minor := int(stat.Rdev % 256) return dType, major, minor, nil } func deviceNextInterfaceHWAddr() (string, error) { // Generate a new random MAC address using the usual prefix ret := bytes.Buffer{} for _, c := range "00:16:3e:xx:xx:xx" { if c == 'x' { c, err := rand.Int(rand.Reader, big.NewInt(16)) if err != nil { return "", err } ret.WriteString(fmt.Sprintf("%x", c.Int64())) } else { ret.WriteString(string(c)) } } return ret.String(), nil } func deviceNextVeth() string { // Return a new random veth device name randBytes := make([]byte, 4) rand.Read(randBytes) return "veth" + hex.EncodeToString(randBytes) } func deviceRemoveInterface(nic string) error { return exec.Command("ip", "link", "del", nic).Run() } func deviceMountDisk(srcPath string, dstPath string, readonly bool, recursive bool) error { var err error // Prepare the mount flags flags := 0 if readonly { flags |= syscall.MS_RDONLY } // Detect the filesystem fstype := "none" if deviceIsBlockdev(srcPath) { fstype, err = shared.BlockFsDetect(srcPath) if err != nil { return err } } else { flags |= syscall.MS_BIND if recursive { flags |= syscall.MS_REC } } // Mount the filesystem if err = syscall.Mount(srcPath, dstPath, fstype, uintptr(flags), ""); err != nil { return fmt.Errorf("Unable to mount %s at %s: %s", srcPath, dstPath, err) } flags = syscall.MS_REC | syscall.MS_SLAVE if err = syscall.Mount("", dstPath, "", uintptr(flags), ""); err != nil { return fmt.Errorf("unable to make mount %s private: %s", dstPath, err) } return nil } func deviceParseCPU(cpuAllowance string, cpuPriority string) (string, string, string, error) { var err error // Parse priority cpuShares := 0 cpuPriorityInt := 10 if cpuPriority != "" { cpuPriorityInt, err = strconv.Atoi(cpuPriority) if err != nil { return "", "", "", err } } cpuShares -= 10 - cpuPriorityInt // Parse allowance cpuCfsQuota := "-1" cpuCfsPeriod := "100000" if cpuAllowance != "" { if strings.HasSuffix(cpuAllowance, "%") { // Percentage based allocation percent, err := strconv.Atoi(strings.TrimSuffix(cpuAllowance, "%")) if err != nil { return "", "", "", err } cpuShares += (10 * percent) + 24 } else { // Time based allocation fields := strings.SplitN(cpuAllowance, "/", 2) if len(fields) != 2 { return "", "", "", fmt.Errorf("Invalid allowance: %s", cpuAllowance) } quota, err := strconv.Atoi(strings.TrimSuffix(fields[0], "ms")) if err != nil { return "", "", "", err } period, err := strconv.Atoi(strings.TrimSuffix(fields[1], "ms")) if err != nil { return "", "", "", err } // Set limit in ms cpuCfsQuota = fmt.Sprintf("%d", quota*1000) cpuCfsPeriod = fmt.Sprintf("%d", period*1000) cpuShares += 1024 } } else { // Default is 100% cpuShares += 1024 } // Deal with a potential negative score if cpuShares < 0 { cpuShares = 0 } return fmt.Sprintf("%d", cpuShares), cpuCfsQuota, cpuCfsPeriod, nil } func deviceTotalMemory() (int64, error) { // Open /proc/meminfo f, err := os.Open("/proc/meminfo") if err != nil { return -1, err } defer f.Close() // Read it line by line scan := bufio.NewScanner(f) for scan.Scan() { line := scan.Text() // We only care about MemTotal if !strings.HasPrefix(line, "MemTotal:") { continue } // Extract the before last (value) and last (unit) fields fields := strings.Split(line, " ") value := fields[len(fields)-2] + fields[len(fields)-1] // Feed the result to shared.ParseByteSizeString to get an int value valueBytes, err := shared.ParseByteSizeString(value) if err != nil { return -1, err } return valueBytes, nil } return -1, fmt.Errorf("Couldn't find MemTotal") } func deviceGetParentBlocks(path string) ([]string, error) { var devices []string var device []string // Expand the mount path absPath, err := filepath.Abs(path) if err != nil { return nil, err } expPath, err := filepath.EvalSymlinks(absPath) if err != nil { expPath = absPath } // Find the source mount of the path file, err := os.Open("/proc/self/mountinfo") if err != nil { return nil, err } defer file.Close() scanner := bufio.NewScanner(file) match := "" for scanner.Scan() { line := scanner.Text() rows := strings.Fields(line) if len(rows[4]) <= len(match) { continue } if expPath != rows[4] && !strings.HasPrefix(expPath, rows[4]) { continue } match = rows[4] // Go backward to avoid problems with optional fields device = []string{rows[2], rows[len(rows)-2]} } if device == nil { return nil, fmt.Errorf("Couldn't find a match /proc/self/mountinfo entry") } // Handle the most simple case if !strings.HasPrefix(device[0], "0:") { return []string{device[0]}, nil } // Deal with per-filesystem oddities. We don't care about failures here // because any non-special filesystem => directory backend. fs, _ := filesystemDetect(expPath) if fs == "zfs" && shared.PathExists("/dev/zfs") { // Accessible zfs filesystems poolName := strings.Split(device[1], "/")[0] output, err := exec.Command("zpool", "status", poolName).CombinedOutput() if err != nil { return nil, fmt.Errorf("Failed to query zfs filesystem information for %s: %s", device[1], output) } header := true for _, line := range strings.Split(string(output), "\n") { fields := strings.Fields(line) if len(fields) < 5 { continue } if fields[1] != "ONLINE" { continue } if header { header = false continue } var path string if shared.PathExists(fields[0]) { if shared.IsBlockdevPath(fields[0]) { path = fields[0] } else { subDevices, err := deviceGetParentBlocks(fields[0]) if err != nil { return nil, err } for _, dev := range subDevices { devices = append(devices, dev) } } } else if shared.PathExists(fmt.Sprintf("/dev/%s", fields[0])) { path = fmt.Sprintf("/dev/%s", fields[0]) } else if shared.PathExists(fmt.Sprintf("/dev/disk/by-id/%s", fields[0])) { path = fmt.Sprintf("/dev/disk/by-id/%s", fields[0]) } else if shared.PathExists(fmt.Sprintf("/dev/mapper/%s", fields[0])) { path = fmt.Sprintf("/dev/mapper/%s", fields[0]) } else { continue } if path != "" { _, major, minor, err := deviceGetAttributes(path) if err != nil { continue } devices = append(devices, fmt.Sprintf("%d:%d", major, minor)) } } if len(devices) == 0 { return nil, fmt.Errorf("Unable to find backing block for zfs pool: %s", poolName) } } else if fs == "btrfs" && shared.PathExists(device[1]) { // Accessible btrfs filesystems output, err := exec.Command("btrfs", "filesystem", "show", device[1]).CombinedOutput() if err != nil { return nil, fmt.Errorf("Failed to query btrfs filesystem information for %s: %s", device[1], output) } for _, line := range strings.Split(string(output), "\n") { fields := strings.Fields(line) if len(fields) == 0 || fields[0] != "devid" { continue } _, major, minor, err := deviceGetAttributes(fields[len(fields)-1]) if err != nil { return nil, err } devices = append(devices, fmt.Sprintf("%d:%d", major, minor)) } } else if shared.PathExists(device[1]) { // Anything else with a valid path _, major, minor, err := deviceGetAttributes(device[1]) if err != nil { return nil, err } devices = append(devices, fmt.Sprintf("%d:%d", major, minor)) } else { return nil, fmt.Errorf("Invalid block device: %s", device[1]) } return devices, nil } func deviceParseDiskLimit(readSpeed string, writeSpeed string) (int64, int64, int64, int64, error) { parseValue := func(value string) (int64, int64, error) { var err error bps := int64(0) iops := int64(0) if readSpeed == "" { return bps, iops, nil } if strings.HasSuffix(value, "iops") { iops, err = strconv.ParseInt(strings.TrimSuffix(value, "iops"), 10, 64) if err != nil { return -1, -1, err } } else { bps, err = shared.ParseByteSizeString(value) if err != nil { return -1, -1, err } } return bps, iops, nil } readBps, readIops, err := parseValue(readSpeed) if err != nil { return -1, -1, -1, -1, err } writeBps, writeIops, err := parseValue(writeSpeed) if err != nil { return -1, -1, -1, -1, err } return readBps, readIops, writeBps, writeIops, nil } lxd-2.0.0/lxd/devlxd.go000066400000000000000000000240611270277227600147230ustar00rootroot00000000000000package main import ( "fmt" "io/ioutil" "net" "net/http" "os" "path" "reflect" "regexp" "strconv" "strings" "unsafe" "github.com/gorilla/mux" "github.com/lxc/lxd/shared" ) type devLxdResponse struct { content interface{} code int ctype string } func okResponse(ct interface{}, ctype string) *devLxdResponse { return &devLxdResponse{ct, http.StatusOK, ctype} } type devLxdHandler struct { path string /* * This API will have to be changed slightly when we decide to support * websocket events upgrading, but since we don't have events on the * server side right now either, I went the simple route to avoid * needless noise. */ f func(c container, r *http.Request) *devLxdResponse } var configGet = devLxdHandler{"/1.0/config", func(c container, r *http.Request) *devLxdResponse { filtered := []string{} for k, _ := range c.ExpandedConfig() { if strings.HasPrefix(k, "user.") { filtered = append(filtered, fmt.Sprintf("/1.0/config/%s", k)) } } return okResponse(filtered, "json") }} var configKeyGet = devLxdHandler{"/1.0/config/{key}", func(c container, r *http.Request) *devLxdResponse { key := mux.Vars(r)["key"] if !strings.HasPrefix(key, "user.") { return &devLxdResponse{"not authorized", http.StatusForbidden, "raw"} } value, ok := c.ExpandedConfig()[key] if !ok { return &devLxdResponse{"not found", http.StatusNotFound, "raw"} } return okResponse(value, "raw") }} var metadataGet = devLxdHandler{"/1.0/meta-data", func(c container, r *http.Request) *devLxdResponse { value := c.ExpandedConfig()["user.meta-data"] return okResponse(fmt.Sprintf("#cloud-config\ninstance-id: %s\nlocal-hostname: %s\n%s", c.Name(), c.Name(), value), "raw") }} var handlers = []devLxdHandler{ devLxdHandler{"/", func(c container, r *http.Request) *devLxdResponse { return okResponse([]string{"/1.0"}, "json") }}, devLxdHandler{"/1.0", func(c container, r *http.Request) *devLxdResponse { return okResponse(shared.Jmap{"api_version": shared.APIVersion}, "json") }}, configGet, configKeyGet, metadataGet, /* TODO: events */ } func hoistReq(f func(container, *http.Request) *devLxdResponse, d *Daemon) func(http.ResponseWriter, *http.Request) { return func(w http.ResponseWriter, r *http.Request) { conn := extractUnderlyingConn(w) cred, ok := pidMapper.m[conn] if !ok { http.Error(w, pidNotInContainerErr.Error(), 500) return } c, err := findContainerForPid(cred.pid, d) if err != nil { http.Error(w, err.Error(), 500) return } // Access control rootUid := int64(0) idmapset, err := c.LastIdmapSet() if err == nil && idmapset != nil { uid, _ := idmapset.ShiftIntoNs(0, 0) rootUid = int64(uid) } if rootUid != cred.uid { http.Error(w, "Access denied for non-root user", 401) return } resp := f(c, r) if resp.code != http.StatusOK { http.Error(w, fmt.Sprintf("%s", resp.content), resp.code) } else if resp.ctype == "json" { w.Header().Set("Content-Type", "application/json") WriteJSON(w, resp.content) } else { w.Header().Set("Content-Type", "application/octet-stream") fmt.Fprintf(w, resp.content.(string)) } } } func createAndBindDevLxd() (*net.UnixListener, error) { sockFile := path.Join(shared.VarPath("devlxd"), "sock") /* * If this socket exists, that means a previous lxd died and didn't * clean up after itself. We assume that the LXD is actually dead if we * get this far, since StartDaemon() tries to connect to the actual lxd * socket to make sure that it is actually dead. So, it is safe to * remove it here without any checks. * * Also, it would be nice to SO_REUSEADDR here so we don't have to * delete the socket, but we can't: * http://stackoverflow.com/questions/15716302/so-reuseaddr-and-af-unix * * Note that this will force clients to reconnect when LXD is restarted. */ if err := os.Remove(sockFile); err != nil && !os.IsNotExist(err) { return nil, err } unixAddr, err := net.ResolveUnixAddr("unix", sockFile) if err != nil { return nil, err } unixl, err := net.ListenUnix("unix", unixAddr) if err != nil { return nil, err } if err := os.Chmod(sockFile, 0666); err != nil { return nil, err } return unixl, nil } func devLxdServer(d *Daemon) *http.Server { m := mux.NewRouter() for _, handler := range handlers { m.HandleFunc(handler.path, hoistReq(handler.f, d)) } return &http.Server{ Handler: m, ConnState: pidMapper.ConnStateHandler, } } /* * Everything below here is the guts of the unix socket bits. Unfortunately, * golang's API does not make this easy. What happens is: * * 1. We install a ConnState listener on the http.Server, which does the * initial unix socket credential exchange. When we get a connection started * event, we use SO_PEERCRED to extract the creds for the socket. * * 2. We store a map from the connection pointer to the pid for that * connection, so that once the HTTP negotiation occurrs and we get a * ResponseWriter, we know (because we negotiated on the first byte) which * pid the connection belogs to. * * 3. Regular HTTP negotiation and dispatch occurs via net/http. * * 4. When rendering the response via ResponseWriter, we match its underlying * connection against what we stored in step (2) to figure out which container * it came from. */ /* * We keep this in a global so that we can reference it from the server and * from our http handlers, since there appears to be no way to pass information * around here. */ var pidMapper = ConnPidMapper{m: map[*net.UnixConn]*ucred{}} type ucred struct { pid int32 uid int64 gid int64 } type ConnPidMapper struct { m map[*net.UnixConn]*ucred } func (m *ConnPidMapper) ConnStateHandler(conn net.Conn, state http.ConnState) { unixConn := conn.(*net.UnixConn) switch state { case http.StateNew: cred, err := getCred(unixConn) if err != nil { shared.Debugf("Error getting ucred for conn %s", err) } else { m.m[unixConn] = cred } case http.StateActive: return case http.StateIdle: return case http.StateHijacked: /* * The "Hijacked" state indicates that the connection has been * taken over from net/http. This is useful for things like * developing websocket libraries, who want to upgrade the * connection to a websocket one, and not use net/http any * more. Whatever the case, we want to forget about it since we * won't see it either. */ delete(m.m, unixConn) case http.StateClosed: delete(m.m, unixConn) default: shared.Debugf("Unknown state for connection %s", state) } } /* * I also don't see that golang exports an API to get at the underlying FD, but * we need it to get at SO_PEERCRED, so let's grab it. */ func extractUnderlyingFd(unixConnPtr *net.UnixConn) int { conn := reflect.Indirect(reflect.ValueOf(unixConnPtr)) netFdPtr := conn.FieldByName("fd") netFd := reflect.Indirect(netFdPtr) fd := netFd.FieldByName("sysfd") return int(fd.Int()) } func getCred(conn *net.UnixConn) (*ucred, error) { fd := extractUnderlyingFd(conn) uid, gid, pid, err := getUcred(fd) if err != nil { return nil, err } return &ucred{pid, int64(uid), int64(gid)}, nil } /* * As near as I can tell, there is no nice way of extracting an underlying * net.Conn (or in our case, net.UnixConn) from an http.Request or * ResponseWriter without hijacking it [1]. Since we want to send and recieve * unix creds to figure out which container this request came from, we need to * do this. * * [1]: https://groups.google.com/forum/#!topic/golang-nuts/_FWdFXJa6QA */ func extractUnderlyingConn(w http.ResponseWriter) *net.UnixConn { v := reflect.Indirect(reflect.ValueOf(w)) connPtr := v.FieldByName("conn") conn := reflect.Indirect(connPtr) rwc := conn.FieldByName("rwc") netConnPtr := (*net.Conn)(unsafe.Pointer(rwc.UnsafeAddr())) unixConnPtr := (*netConnPtr).(*net.UnixConn) return unixConnPtr } var pidNotInContainerErr = fmt.Errorf("pid not in container?") func findContainerForPid(pid int32, d *Daemon) (container, error) { /* * Try and figure out which container a pid is in. There is probably a * better way to do this. Based on rharper's initial performance * metrics, looping over every container and calling newLxdContainer is * expensive, so I wanted to avoid that if possible, so this happens in * a two step process: * * 1. Walk up the process tree until you see something that looks like * an lxc monitor process and extract its name from there. * * 2. If this fails, it may be that someone did an `lxc exec foo bash`, * so the process isn't actually a decendant of the container's * init. In this case we just look through all the containers until * we find an init with a matching pid namespace. This is probably * uncommon, so hopefully the slowness won't hurt us. */ origpid := pid for pid > 1 { cmdline, err := ioutil.ReadFile(fmt.Sprintf("/proc/%d/cmdline", pid)) if err != nil { return nil, err } if strings.HasPrefix(string(cmdline), "[lxc monitor]") { // container names can't have spaces parts := strings.Split(string(cmdline), " ") name := strings.TrimSuffix(parts[len(parts)-1], "\x00") return containerLoadByName(d, name) } status, err := ioutil.ReadFile(fmt.Sprintf("/proc/%d/status", pid)) if err != nil { return nil, err } re := regexp.MustCompile("PPid:\\s*([0-9]*)") for _, line := range strings.Split(string(status), "\n") { m := re.FindStringSubmatch(line) if m != nil && len(m) > 1 { result, err := strconv.Atoi(m[1]) if err != nil { return nil, err } pid = int32(result) break } } } origPidNs, err := os.Readlink(fmt.Sprintf("/proc/%d/ns/pid", origpid)) if err != nil { return nil, err } containers, err := dbContainersList(d.db, cTypeRegular) if err != nil { return nil, err } for _, container := range containers { c, err := containerLoadByName(d, container) if err != nil { return nil, err } if !c.IsRunning() { continue } initpid := c.InitPID() pidNs, err := os.Readlink(fmt.Sprintf("/proc/%d/ns/pid", initpid)) if err != nil { return nil, err } if origPidNs == pidNs { return c, nil } } return nil, pidNotInContainerErr } lxd-2.0.0/lxd/devlxd_gc.go000066400000000000000000000004251270277227600153720ustar00rootroot00000000000000// +build gc package main import ( "syscall" ) func getUcred(fd int) (uint32, uint32, int32, error) { cred, err := syscall.GetsockoptUcred(fd, syscall.SOL_SOCKET, syscall.SO_PEERCRED) if err != nil { return 0, 0, -1, err } return cred.Uid, cred.Gid, cred.Pid, nil } lxd-2.0.0/lxd/devlxd_gccgo.go000066400000000000000000000016031270277227600160620ustar00rootroot00000000000000// +build gccgo // +build cgo package main import ( "errors" ) /* #define _GNU_SOURCE #include #include #include #include #include void getucred(int sock, uint *uid, uint *gid, int *pid) { struct ucred peercred; socklen_t len; len = sizeof(struct ucred); if (getsockopt(sock, SOL_SOCKET, SO_PEERCRED, &peercred, &len) != 0 || len != sizeof(peercred)) { fprintf(stderr, "getsockopt failed: %s\n", strerror(errno)); return; } *uid = peercred.uid; *gid = peercred.gid; *pid = peercred.pid; return; } */ import "C" func getUcred(fd int) (uint32, uint32, int32, error) { uid := C.uint(0) gid := C.uint(0) pid := C.int(-1) C.getucred(C.int(fd), &uid, &gid, &pid) if uid == 0 || gid == 0 || pid == -1 { return 0, 0, -1, errors.New("Failed to get the ucred") } return uint32(uid), uint32(gid), int32(pid), nil } lxd-2.0.0/lxd/devlxd_test.go000066400000000000000000000051651270277227600157660ustar00rootroot00000000000000package main import ( "fmt" "io/ioutil" "net" "net/http" "os" "strings" "testing" ) var testDir string type DevLxdDialer struct { Path string } func (d DevLxdDialer) DevLxdDial(network, path string) (net.Conn, error) { addr, err := net.ResolveUnixAddr("unix", d.Path) if err != nil { return nil, err } conn, err := net.DialUnix("unix", nil, addr) if err != nil { return nil, err } return conn, err } func setupDir() error { var err error testDir, err = ioutil.TempDir("", "lxd_test_devlxd_") if err != nil { return err } err = os.Chmod(testDir, 0700) if err != nil { return err } os.MkdirAll(fmt.Sprintf("%s/devlxd", testDir), 0755) return os.Setenv("LXD_DIR", testDir) } func setupSocket() (*net.UnixListener, error) { setupDir() return createAndBindDevLxd() } func connect(path string) (*net.UnixConn, error) { addr, err := net.ResolveUnixAddr("unix", path) if err != nil { return nil, err } conn, err := net.DialUnix("unix", nil, addr) if err != nil { return nil, err } return conn, nil } func TestCredsSendRecv(t *testing.T) { result := make(chan int32, 1) listener, err := setupSocket() if err != nil { t.Fatal(err) } defer listener.Close() defer os.RemoveAll(testDir) go func() { conn, err := listener.AcceptUnix() if err != nil { t.Log(err) result <- -1 return } defer conn.Close() cred, err := getCred(conn) if err != nil { t.Log(err) result <- -1 return } result <- cred.pid }() conn, err := connect(fmt.Sprintf("%s/devlxd/sock", testDir)) if err != nil { t.Fatal(err) } defer conn.Close() pid := <-result if pid != int32(os.Getpid()) { t.Fatal("pid mismatch: ", pid, os.Getpid()) } } /* * Here we're not really testing the API functionality (we can't, since it * expects us to be inside a container to work), but it is useful to test that * all the grotty connection extracting stuff works (that is, it gets to the * point where it realizes the pid isn't in a container without crashing). */ func TestHttpRequest(t *testing.T) { if err := setupDir(); err != nil { t.Fatal(err) } defer os.RemoveAll(testDir) d := &Daemon{} err := d.Init() if err != nil { t.Fatal(err) } defer d.Stop() c := http.Client{Transport: &http.Transport{Dial: DevLxdDialer{Path: fmt.Sprintf("%s/devlxd/sock", testDir)}.DevLxdDial}} raw, err := c.Get("http://1.0") if err != nil { t.Fatal(err) } if raw.StatusCode != 500 { t.Fatal(err) } resp, err := ioutil.ReadAll(raw.Body) if err != nil { t.Fatal(err) } if !strings.Contains(string(resp), pidNotInContainerErr.Error()) { t.Fatal("resp error not expected: ", string(resp)) } } lxd-2.0.0/lxd/events.go000066400000000000000000000053221270277227600147400ustar00rootroot00000000000000package main import ( "encoding/json" "fmt" "net/http" "strings" "sync" "time" "github.com/gorilla/websocket" "github.com/pborman/uuid" log "gopkg.in/inconshreveable/log15.v2" "github.com/lxc/lxd/shared" ) type eventsHandler struct { } func logContextMap(ctx []interface{}) map[string]string { var key string ctxMap := map[string]string{} for _, entry := range ctx { if key == "" { key = entry.(string) } else { ctxMap[key] = fmt.Sprintf("%s", entry) key = "" } } return ctxMap } func (h eventsHandler) Log(r *log.Record) error { eventSend("logging", shared.Jmap{ "message": r.Msg, "level": r.Lvl.String(), "context": logContextMap(r.Ctx)}) return nil } var eventsLock sync.Mutex var eventListeners map[string]*eventListener = make(map[string]*eventListener) type eventListener struct { connection *websocket.Conn messageTypes []string active chan bool id string msgLock sync.Mutex } type eventsServe struct { req *http.Request } func (r *eventsServe) Render(w http.ResponseWriter) error { return eventsSocket(r.req, w) } func eventsSocket(r *http.Request, w http.ResponseWriter) error { listener := eventListener{} typeStr := r.FormValue("type") if typeStr == "" { typeStr = "logging,operation" } c, err := shared.WebsocketUpgrader.Upgrade(w, r, nil) if err != nil { return err } listener.active = make(chan bool, 1) listener.connection = c listener.id = uuid.NewRandom().String() listener.messageTypes = strings.Split(typeStr, ",") eventsLock.Lock() eventListeners[listener.id] = &listener eventsLock.Unlock() shared.Debugf("New events listener: %s", listener.id) <-listener.active eventsLock.Lock() delete(eventListeners, listener.id) eventsLock.Unlock() listener.connection.Close() shared.Debugf("Disconnected events listener: %s", listener.id) return nil } func eventsGet(d *Daemon, r *http.Request) Response { return &eventsServe{r} } var eventsCmd = Command{name: "events", get: eventsGet} func eventSend(eventType string, eventMessage interface{}) error { event := shared.Jmap{} event["type"] = eventType event["timestamp"] = time.Now() event["metadata"] = eventMessage body, err := json.Marshal(event) if err != nil { return err } eventsLock.Lock() listeners := eventListeners for _, listener := range listeners { if !shared.StringInSlice(eventType, listener.messageTypes) { continue } go func(listener *eventListener, body []byte) { if listener == nil { return } listener.msgLock.Lock() err = listener.connection.WriteMessage(websocket.TextMessage, body) listener.msgLock.Unlock() if err != nil { listener.active <- false } }(listener, body) } eventsLock.Unlock() return nil } lxd-2.0.0/lxd/images.go000066400000000000000000000742741270277227600147150ustar00rootroot00000000000000package main import ( "bytes" "crypto/sha256" "encoding/json" "fmt" "io" "io/ioutil" "mime" "mime/multipart" "net/http" "net/url" "os" "os/exec" "strconv" "strings" "sync" "time" "github.com/gorilla/mux" "gopkg.in/yaml.v2" "github.com/lxc/lxd/shared" "github.com/lxc/lxd/shared/logging" log "gopkg.in/inconshreveable/log15.v2" ) /* We only want a single publish running at any one time. The CPU and I/O load of publish is such that running multiple ones in parallel takes longer than running them serially. Additionaly, publishing the same container or container snapshot twice would lead to storage problem, not to mention a conflict at the end for whichever finishes last. */ var imagePublishLock sync.Mutex func detectCompression(fname string) ([]string, string, error) { f, err := os.Open(fname) if err != nil { return []string{""}, "", err } defer f.Close() // read header parts to detect compression method // bz2 - 2 bytes, 'BZ' signature/magic number // gz - 2 bytes, 0x1f 0x8b // lzma - 6 bytes, { [0x000, 0xE0], '7', 'z', 'X', 'Z', 0x00 } - // xy - 6 bytes, header format { 0xFD, '7', 'z', 'X', 'Z', 0x00 } // tar - 263 bytes, trying to get ustar from 257 - 262 header := make([]byte, 263) _, err = f.Read(header) if err != nil { return []string{""}, "", err } switch { case bytes.Equal(header[0:2], []byte{'B', 'Z'}): return []string{"-jxf"}, ".tar.bz2", nil case bytes.Equal(header[0:2], []byte{0x1f, 0x8b}): return []string{"-zxf"}, ".tar.gz", nil case (bytes.Equal(header[1:5], []byte{'7', 'z', 'X', 'Z'}) && header[0] == 0xFD): return []string{"-Jxf"}, ".tar.xz", nil case (bytes.Equal(header[1:5], []byte{'7', 'z', 'X', 'Z'}) && header[0] != 0xFD): return []string{"--lzma", "-xf"}, ".tar.lzma", nil case bytes.Equal(header[257:262], []byte{'u', 's', 't', 'a', 'r'}): return []string{"-xf"}, ".tar", nil default: return []string{""}, "", fmt.Errorf("Unsupported compression.") } } func untar(tarball string, path string) error { extractArgs, _, err := detectCompression(tarball) if err != nil { return err } command := "tar" args := []string{} if runningInUserns { args = append(args, "--wildcards") args = append(args, "--exclude=dev/*") args = append(args, "--exclude=./dev/*") args = append(args, "--exclude=rootfs/dev/*") args = append(args, "--exclude=rootfs/./dev/*") } args = append(args, "-C", path, "--numeric-owner") args = append(args, extractArgs...) args = append(args, tarball) output, err := exec.Command(command, args...).CombinedOutput() if err != nil { shared.Debugf("Unpacking failed") shared.Debugf(string(output)) return err } return nil } func untarImage(imagefname string, destpath string) error { err := untar(imagefname, destpath) if err != nil { return err } if shared.PathExists(imagefname + ".rootfs") { rootfsPath := fmt.Sprintf("%s/rootfs", destpath) err = os.MkdirAll(rootfsPath, 0755) if err != nil { return fmt.Errorf("Error creating rootfs directory") } err = untar(imagefname+".rootfs", rootfsPath) if err != nil { return err } } return nil } func compressFile(path string, compress string) (string, error) { reproducible := []string{"gzip"} args := []string{path, "-c"} if shared.StringInSlice(compress, reproducible) { args = append(args, "-n") } cmd := exec.Command(compress, args...) outfile, err := os.Create(path + ".compressed") if err != nil { return "", err } defer outfile.Close() cmd.Stdout = outfile err = cmd.Run() if err != nil { os.Remove(outfile.Name()) return "", err } return outfile.Name(), nil } type templateEntry struct { When []string `yaml:"when"` CreateOnly bool `yaml:"create_only"` Template string `yaml:"template"` Properties map[string]string `yaml:"properties"` } type imagePostReq struct { Filename string `json:"filename"` Public bool `json:"public"` Source map[string]string `json:"source"` Properties map[string]string `json:"properties"` AutoUpdate bool `json:"auto_update"` } type imageMetadata struct { Architecture string `yaml:"architecture"` CreationDate int64 `yaml:"creation_date"` ExpiryDate int64 `yaml:"expiry_date"` Properties map[string]string `yaml:"properties"` Templates map[string]*templateEntry `yaml:"templates"` } /* * This function takes a container or snapshot from the local image server and * exports it as an image. */ func imgPostContInfo(d *Daemon, r *http.Request, req imagePostReq, builddir string) (info shared.ImageInfo, err error) { info.Properties = map[string]string{} name := req.Source["name"] ctype := req.Source["type"] if ctype == "" || name == "" { return info, fmt.Errorf("No source provided") } switch ctype { case "snapshot": if !shared.IsSnapshot(name) { return info, fmt.Errorf("Not a snapshot") } case "container": if shared.IsSnapshot(name) { return info, fmt.Errorf("This is a snapshot") } default: return info, fmt.Errorf("Bad type") } info.Filename = req.Filename switch req.Public { case true: info.Public = true case false: info.Public = false } c, err := containerLoadByName(d, name) if err != nil { return info, err } // Build the actual image file tarfile, err := ioutil.TempFile(builddir, "lxd_build_tar_") if err != nil { return info, err } defer os.Remove(tarfile.Name()) if err := c.Export(tarfile); err != nil { tarfile.Close() return info, err } tarfile.Close() compress, err := d.ConfigValueGet("images.compression_algorithm") if err != nil { return info, err } // Default to gzip for this if compress == "" { compress = "gzip" } var compressedPath string if compress != "none" { compressedPath, err = compressFile(tarfile.Name(), compress) if err != nil { return info, err } } else { compressedPath = tarfile.Name() } defer os.Remove(compressedPath) sha256 := sha256.New() tarf, err := os.Open(compressedPath) if err != nil { return info, err } info.Size, err = io.Copy(sha256, tarf) tarf.Close() if err != nil { return info, err } info.Fingerprint = fmt.Sprintf("%x", sha256.Sum(nil)) _, _, err = dbImageGet(d.db, info.Fingerprint, false, true) if err == nil { return info, fmt.Errorf("The image already exists: %s", info.Fingerprint) } /* rename the the file to the expected name so our caller can use it */ finalName := shared.VarPath("images", info.Fingerprint) err = shared.FileMove(compressedPath, finalName) if err != nil { return info, err } info.Architecture, _ = shared.ArchitectureName(c.Architecture()) info.Properties = req.Properties return info, nil } func imgPostRemoteInfo(d *Daemon, req imagePostReq, op *operation) error { var err error var hash string if req.Source["fingerprint"] != "" { hash = req.Source["fingerprint"] } else if req.Source["alias"] != "" { hash = req.Source["alias"] } else { return fmt.Errorf("must specify one of alias or fingerprint for init from image") } hash, err = d.ImageDownload(op, req.Source["server"], req.Source["protocol"], req.Source["certificate"], req.Source["secret"], hash, false, req.AutoUpdate) if err != nil { return err } id, info, err := dbImageGet(d.db, hash, false, false) if err != nil { return err } // Allow overriding or adding properties for k, v := range req.Properties { info.Properties[k] = v } // Update the DB record if needed if req.Public || req.AutoUpdate || req.Filename != "" || len(req.Properties) > 0 { err = dbImageUpdate(d.db, id, req.Filename, info.Size, req.Public, req.AutoUpdate, info.Architecture, info.CreationDate, info.ExpiryDate, info.Properties) if err != nil { return err } } metadata := make(map[string]string) metadata["fingerprint"] = info.Fingerprint metadata["size"] = strconv.FormatInt(info.Size, 10) op.UpdateMetadata(metadata) return nil } func imgPostURLInfo(d *Daemon, req imagePostReq, op *operation) error { var err error if req.Source["url"] == "" { return fmt.Errorf("Missing URL") } // Resolve the image URL tlsConfig, err := shared.GetTLSConfig("", "", nil) if err != nil { return err } tr := &http.Transport{ TLSClientConfig: tlsConfig, Dial: shared.RFC3493Dialer, Proxy: d.proxy, } myhttp := http.Client{ Transport: tr, } head, err := http.NewRequest("HEAD", req.Source["url"], nil) if err != nil { return err } architecturesStr := []string{} for _, arch := range d.architectures { architecturesStr = append(architecturesStr, fmt.Sprintf("%d", arch)) } head.Header.Set("User-Agent", shared.UserAgent) head.Header.Set("LXD-Server-Architectures", strings.Join(architecturesStr, ", ")) head.Header.Set("LXD-Server-Version", shared.Version) raw, err := myhttp.Do(head) if err != nil { return err } hash := raw.Header.Get("LXD-Image-Hash") if hash == "" { return fmt.Errorf("Missing LXD-Image-Hash header") } url := raw.Header.Get("LXD-Image-URL") if url == "" { return fmt.Errorf("Missing LXD-Image-URL header") } // Import the image hash, err = d.ImageDownload(op, url, "direct", "", "", hash, false, req.AutoUpdate) if err != nil { return err } id, info, err := dbImageGet(d.db, hash, false, false) if err != nil { return err } // Allow overriding or adding properties for k, v := range req.Properties { info.Properties[k] = v } if req.Public || req.AutoUpdate || req.Filename != "" || len(req.Properties) > 0 { err = dbImageUpdate(d.db, id, req.Filename, info.Size, req.Public, req.AutoUpdate, info.Architecture, info.CreationDate, info.ExpiryDate, info.Properties) if err != nil { return err } } metadata := make(map[string]string) metadata["fingerprint"] = info.Fingerprint metadata["size"] = strconv.FormatInt(info.Size, 10) op.UpdateMetadata(metadata) return nil } func getImgPostInfo(d *Daemon, r *http.Request, builddir string, post *os.File) (info shared.ImageInfo, err error) { var imageMeta *imageMetadata logger := logging.AddContext(shared.Log, log.Ctx{"function": "getImgPostInfo"}) public, _ := strconv.Atoi(r.Header.Get("X-LXD-public")) info.Public = public == 1 propHeaders := r.Header[http.CanonicalHeaderKey("X-LXD-properties")] ctype, ctypeParams, err := mime.ParseMediaType(r.Header.Get("Content-Type")) if err != nil { ctype = "application/octet-stream" } sha256 := sha256.New() var size int64 // Create a temporary file for the image tarball imageTarf, err := ioutil.TempFile(builddir, "lxd_tar_") if err != nil { return info, err } defer os.Remove(imageTarf.Name()) if ctype == "multipart/form-data" { // Parse the POST data post.Seek(0, 0) mr := multipart.NewReader(post, ctypeParams["boundary"]) // Get the metadata tarball part, err := mr.NextPart() if err != nil { return info, err } if part.FormName() != "metadata" { return info, fmt.Errorf("Invalid multipart image") } size, err = io.Copy(io.MultiWriter(imageTarf, sha256), part) info.Size += size imageTarf.Close() if err != nil { logger.Error( "Failed to copy the image tarfile", log.Ctx{"err": err}) return info, err } // Get the rootfs tarball part, err = mr.NextPart() if err != nil { logger.Error( "Failed to get the next part", log.Ctx{"err": err}) return info, err } if part.FormName() != "rootfs" { logger.Error( "Invalid multipart image") return info, fmt.Errorf("Invalid multipart image") } // Create a temporary file for the rootfs tarball rootfsTarf, err := ioutil.TempFile(builddir, "lxd_tar_") if err != nil { return info, err } defer os.Remove(rootfsTarf.Name()) size, err = io.Copy(io.MultiWriter(rootfsTarf, sha256), part) info.Size += size rootfsTarf.Close() if err != nil { logger.Error( "Failed to copy the rootfs tarfile", log.Ctx{"err": err}) return info, err } info.Filename = part.FileName() info.Fingerprint = fmt.Sprintf("%x", sha256.Sum(nil)) expectedFingerprint := r.Header.Get("X-LXD-fingerprint") if expectedFingerprint != "" && info.Fingerprint != expectedFingerprint { err = fmt.Errorf("fingerprints don't match, got %s expected %s", info.Fingerprint, expectedFingerprint) return info, err } imageMeta, err = getImageMetadata(imageTarf.Name()) if err != nil { logger.Error( "Failed to get image metadata", log.Ctx{"err": err}) return info, err } imgfname := shared.VarPath("images", info.Fingerprint) err = shared.FileMove(imageTarf.Name(), imgfname) if err != nil { logger.Error( "Failed to move the image tarfile", log.Ctx{ "err": err, "source": imageTarf.Name(), "dest": imgfname}) return info, err } rootfsfname := shared.VarPath("images", info.Fingerprint+".rootfs") err = shared.FileMove(rootfsTarf.Name(), rootfsfname) if err != nil { logger.Error( "Failed to move the rootfs tarfile", log.Ctx{ "err": err, "source": rootfsTarf.Name(), "dest": imgfname}) return info, err } } else { post.Seek(0, 0) size, err = io.Copy(io.MultiWriter(imageTarf, sha256), post) info.Size = size imageTarf.Close() logger.Debug("Tar size", log.Ctx{"size": size}) if err != nil { logger.Error( "Failed to copy the tarfile", log.Ctx{"err": err}) return info, err } info.Filename = r.Header.Get("X-LXD-filename") info.Fingerprint = fmt.Sprintf("%x", sha256.Sum(nil)) expectedFingerprint := r.Header.Get("X-LXD-fingerprint") if expectedFingerprint != "" && info.Fingerprint != expectedFingerprint { logger.Error( "Fingerprints don't match", log.Ctx{ "got": info.Fingerprint, "expected": expectedFingerprint}) err = fmt.Errorf( "fingerprints don't match, got %s expected %s", info.Fingerprint, expectedFingerprint) return info, err } imageMeta, err = getImageMetadata(imageTarf.Name()) if err != nil { logger.Error( "Failed to get image metadata", log.Ctx{"err": err}) return info, err } imgfname := shared.VarPath("images", info.Fingerprint) err = shared.FileMove(imageTarf.Name(), imgfname) if err != nil { logger.Error( "Failed to move the tarfile", log.Ctx{ "err": err, "source": imageTarf.Name(), "dest": imgfname}) return info, err } } info.Architecture = imageMeta.Architecture info.CreationDate = time.Unix(imageMeta.CreationDate, 0) info.ExpiryDate = time.Unix(imageMeta.ExpiryDate, 0) info.Properties = imageMeta.Properties if len(propHeaders) > 0 { for _, ph := range propHeaders { p, _ := url.ParseQuery(ph) for pkey, pval := range p { info.Properties[pkey] = pval[0] } } } return info, nil } func imageBuildFromInfo(d *Daemon, info shared.ImageInfo) (metadata map[string]string, err error) { err = d.Storage.ImageCreate(info.Fingerprint) if err != nil { return metadata, err } err = dbImageInsert( d.db, info.Fingerprint, info.Filename, info.Size, info.Public, info.AutoUpdate, info.Architecture, info.CreationDate, info.ExpiryDate, info.Properties) if err != nil { return metadata, err } metadata = make(map[string]string) metadata["fingerprint"] = info.Fingerprint metadata["size"] = strconv.FormatInt(info.Size, 10) return metadata, nil } func imagesPost(d *Daemon, r *http.Request) Response { var err error // create a directory under which we keep everything while building builddir, err := ioutil.TempDir(shared.VarPath("images"), "lxd_build_") if err != nil { return InternalError(err) } cleanup := func(path string, fd *os.File) { if fd != nil { fd.Close() } if err := os.RemoveAll(path); err != nil { shared.Debugf("Error deleting temporary directory \"%s\": %s", path, err) } } // Store the post data to disk post, err := ioutil.TempFile(builddir, "lxd_post_") if err != nil { cleanup(builddir, nil) return InternalError(err) } _, err = io.Copy(post, r.Body) if err != nil { cleanup(builddir, post) return InternalError(err) } // Is this a container request? post.Seek(0, 0) decoder := json.NewDecoder(post) imageUpload := false req := imagePostReq{} err = decoder.Decode(&req) if err != nil { if r.Header.Get("Content-Type") == "application/json" { return BadRequest(err) } imageUpload = true } if !imageUpload && !shared.StringInSlice(req.Source["type"], []string{"container", "snapshot", "image", "url"}) { cleanup(builddir, post) return InternalError(fmt.Errorf("Invalid images JSON")) } // Begin background operation run := func(op *operation) error { var info shared.ImageInfo // Setup the cleanup function defer cleanup(builddir, post) /* Processing image copy from remote */ if !imageUpload && req.Source["type"] == "image" { err := imgPostRemoteInfo(d, req, op) if err != nil { return err } return nil } /* Processing image copy from URL */ if !imageUpload && req.Source["type"] == "url" { err := imgPostURLInfo(d, req, op) if err != nil { return err } return nil } if imageUpload { /* Processing image upload */ info, err = getImgPostInfo(d, r, builddir, post) if err != nil { return err } } else { /* Processing image creation from container */ imagePublishLock.Lock() info, err = imgPostContInfo(d, r, req, builddir) if err != nil { imagePublishLock.Unlock() return err } imagePublishLock.Unlock() } metadata, err := imageBuildFromInfo(d, info) if err != nil { return err } op.UpdateMetadata(metadata) return nil } op, err := operationCreate(operationClassTask, nil, nil, run, nil, nil) if err != nil { return InternalError(err) } return OperationResponse(op) } func getImageMetadata(fname string) (*imageMetadata, error) { metadataName := "metadata.yaml" compressionArgs, _, err := detectCompression(fname) if err != nil { return nil, fmt.Errorf( "detectCompression failed, err='%v', tarfile='%s'", err, fname) } args := []string{"-O"} args = append(args, compressionArgs...) args = append(args, fname, metadataName) // read the metadata.yaml output, err := exec.Command("tar", args...).CombinedOutput() if err != nil { outputLines := strings.Split(string(output), "\n") return nil, fmt.Errorf("Could not extract image metadata %s from tar: %v (%s)", metadataName, err, outputLines[0]) } metadata := imageMetadata{} err = yaml.Unmarshal(output, &metadata) if err != nil { return nil, fmt.Errorf("Could not parse %s: %v", metadataName, err) } return &metadata, nil } func doImagesGet(d *Daemon, recursion bool, public bool) (interface{}, error) { results, err := dbImagesGet(d.db, public) if err != nil { return []string{}, err } resultString := make([]string, len(results)) resultMap := make([]*shared.ImageInfo, len(results)) i := 0 for _, name := range results { if !recursion { url := fmt.Sprintf("/%s/images/%s", shared.APIVersion, name) resultString[i] = url } else { image, response := doImageGet(d, name, public) if response != nil { continue } resultMap[i] = image } i++ } if !recursion { return resultString, nil } return resultMap, nil } func imagesGet(d *Daemon, r *http.Request) Response { public := !d.isTrustedClient(r) result, err := doImagesGet(d, d.isRecursionRequest(r), public) if err != nil { return SmartError(err) } return SyncResponse(true, result) } var imagesCmd = Command{name: "images", post: imagesPost, untrustedGet: true, get: imagesGet} func autoUpdateImages(d *Daemon) { shared.Debugf("Updating images") images, err := dbImagesGet(d.db, false) if err != nil { shared.Log.Error("Unable to retrieve the list of images", log.Ctx{"err": err}) return } for _, fp := range images { id, info, err := dbImageGet(d.db, fp, false, true) if err != nil { shared.Log.Error("Error loading image", log.Ctx{"err": err, "fp": fp}) continue } if !info.AutoUpdate { continue } _, source, err := dbImageSourceGet(d.db, id) if err != nil { continue } shared.Log.Debug("Processing image", log.Ctx{"fp": fp, "server": source.Server, "protocol": source.Protocol, "alias": source.Alias}) hash, err := d.ImageDownload(nil, source.Server, source.Protocol, "", "", source.Alias, false, true) if hash == fp { shared.Log.Debug("Already up to date", log.Ctx{"fp": fp}) continue } newId, _, err := dbImageGet(d.db, hash, false, true) if err != nil { shared.Log.Error("Error loading image", log.Ctx{"err": err, "fp": hash}) continue } err = dbImageLastAccessUpdate(d.db, hash, info.LastUsedDate) if err != nil { shared.Log.Error("Error setting last use date", log.Ctx{"err": err, "fp": hash}) continue } err = dbImageAliasesMove(d.db, id, newId) if err != nil { shared.Log.Error("Error moving aliases", log.Ctx{"err": err, "fp": hash}) continue } err = doDeleteImage(d, fp) if err != nil { shared.Log.Error("Error deleting image", log.Ctx{"err": err, "fp": fp}) } } } func pruneExpiredImages(d *Daemon) { shared.Debugf("Pruning expired images") expiry, err := d.ConfigValueGet("images.remote_cache_expiry") if err != nil { shared.Log.Error("Unable to read the images.remote_cache_expiry key") return } if expiry == "" { expiry = "10" } expiryInt, err := strconv.Atoi(expiry) if err != nil { shared.Log.Error("Invalid value for images.remote_cache_expiry", log.Ctx{"err": err}) return } images, err := dbImagesGetExpired(d.db, expiryInt) if err != nil { shared.Log.Error("Unable to retrieve the list of expired images", log.Ctx{"err": err}) return } for _, fp := range images { if err := doDeleteImage(d, fp); err != nil { shared.Log.Error("Error deleting image", log.Ctx{"err": err, "fp": fp}) } } shared.Debugf("Done pruning expired images") } func doDeleteImage(d *Daemon, fingerprint string) error { id, imgInfo, err := dbImageGet(d.db, fingerprint, false, false) if err != nil { return err } // get storage before deleting images/$fp because we need to // look at the path s, err := storageForImage(d, imgInfo) if err != nil { return err } // Remove the image from storage backend if err = s.ImageDelete(imgInfo.Fingerprint); err != nil { return err } // Remove main image file fname := shared.VarPath("images", imgInfo.Fingerprint) if shared.PathExists(fname) { err = os.Remove(fname) if err != nil { shared.Debugf("Error deleting image file %s: %s", fname, err) } } // Remote the rootfs file fname = shared.VarPath("images", imgInfo.Fingerprint) + ".rootfs" if shared.PathExists(fname) { err = os.Remove(fname) if err != nil { shared.Debugf("Error deleting image file %s: %s", fname, err) } } // Remove the DB entry if err = dbImageDelete(d.db, id); err != nil { return err } return nil } func imageDelete(d *Daemon, r *http.Request) Response { fingerprint := mux.Vars(r)["fingerprint"] rmimg := func(op *operation) error { return doDeleteImage(d, fingerprint) } resources := map[string][]string{} resources["images"] = []string{fingerprint} op, err := operationCreate(operationClassTask, resources, nil, rmimg, nil, nil) if err != nil { return InternalError(err) } return OperationResponse(op) } func doImageGet(d *Daemon, fingerprint string, public bool) (*shared.ImageInfo, Response) { _, imgInfo, err := dbImageGet(d.db, fingerprint, public, false) if err != nil { return nil, SmartError(err) } return imgInfo, nil } func imageValidSecret(fingerprint string, secret string) bool { for _, op := range operations { if op.resources == nil { continue } opImages, ok := op.resources["images"] if !ok { continue } if !shared.StringInSlice(fingerprint, opImages) { continue } opSecret, ok := op.metadata["secret"] if !ok { continue } if opSecret == secret { // Token is single-use, so cancel it now op.Cancel() return true } } return false } func imageGet(d *Daemon, r *http.Request) Response { fingerprint := mux.Vars(r)["fingerprint"] public := !d.isTrustedClient(r) secret := r.FormValue("secret") if public == true && imageValidSecret(fingerprint, secret) == true { public = false } info, response := doImageGet(d, fingerprint, public) if response != nil { return response } return SyncResponse(true, info) } type imagePutReq struct { Properties map[string]string `json:"properties"` Public bool `json:"public"` AutoUpdate bool `json:"auto_update"` } func imagePut(d *Daemon, r *http.Request) Response { fingerprint := mux.Vars(r)["fingerprint"] req := imagePutReq{} if err := json.NewDecoder(r.Body).Decode(&req); err != nil { return BadRequest(err) } id, info, err := dbImageGet(d.db, fingerprint, false, false) if err != nil { return SmartError(err) } err = dbImageUpdate(d.db, id, info.Filename, info.Size, req.Public, req.AutoUpdate, info.Architecture, info.CreationDate, info.ExpiryDate, req.Properties) if err != nil { return SmartError(err) } return EmptySyncResponse } var imageCmd = Command{name: "images/{fingerprint}", untrustedGet: true, get: imageGet, put: imagePut, delete: imageDelete} type aliasPostReq struct { Name string `json:"name"` Description string `json:"description"` Target string `json:"target"` } type aliasPutReq struct { Description string `json:"description"` Target string `json:"target"` } func aliasesPost(d *Daemon, r *http.Request) Response { req := aliasPostReq{} if err := json.NewDecoder(r.Body).Decode(&req); err != nil { return BadRequest(err) } if req.Name == "" || req.Target == "" { return BadRequest(fmt.Errorf("name and target are required")) } // This is just to see if the alias name already exists. _, _, err := dbImageAliasGet(d.db, req.Name, true) if err == nil { return Conflict } id, _, err := dbImageGet(d.db, req.Target, false, false) if err != nil { return SmartError(err) } err = dbImageAliasAdd(d.db, req.Name, id, req.Description) if err != nil { return InternalError(err) } return EmptySyncResponse } func aliasesGet(d *Daemon, r *http.Request) Response { recursion := d.isRecursionRequest(r) q := "SELECT name FROM images_aliases" var name string inargs := []interface{}{} outfmt := []interface{}{name} results, err := dbQueryScan(d.db, q, inargs, outfmt) if err != nil { return BadRequest(err) } responseStr := []string{} responseMap := shared.ImageAliases{} for _, res := range results { name = res[0].(string) if !recursion { url := fmt.Sprintf("/%s/images/aliases/%s", shared.APIVersion, name) responseStr = append(responseStr, url) } else { _, alias, err := dbImageAliasGet(d.db, name, d.isTrustedClient(r)) if err != nil { continue } responseMap = append(responseMap, alias) } } if !recursion { return SyncResponse(true, responseStr) } return SyncResponse(true, responseMap) } func aliasGet(d *Daemon, r *http.Request) Response { name := mux.Vars(r)["name"] _, alias, err := dbImageAliasGet(d.db, name, d.isTrustedClient(r)) if err != nil { return SmartError(err) } return SyncResponse(true, alias) } func aliasDelete(d *Daemon, r *http.Request) Response { name := mux.Vars(r)["name"] _, _, err := dbImageAliasGet(d.db, name, true) if err != nil { return SmartError(err) } err = dbImageAliasDelete(d.db, name) if err != nil { return SmartError(err) } return EmptySyncResponse } func aliasPut(d *Daemon, r *http.Request) Response { name := mux.Vars(r)["name"] req := aliasPutReq{} if err := json.NewDecoder(r.Body).Decode(&req); err != nil { return BadRequest(err) } if req.Target == "" { return BadRequest(fmt.Errorf("The target field is required")) } id, _, err := dbImageAliasGet(d.db, name, true) if err != nil { return SmartError(err) } imageId, _, err := dbImageGet(d.db, req.Target, false, false) if err != nil { return SmartError(err) } err = dbImageAliasUpdate(d.db, id, imageId, req.Description) if err != nil { return SmartError(err) } return EmptySyncResponse } func aliasPost(d *Daemon, r *http.Request) Response { name := mux.Vars(r)["name"] req := aliasPostReq{} if err := json.NewDecoder(r.Body).Decode(&req); err != nil { return BadRequest(err) } id, _, err := dbImageAliasGet(d.db, name, true) if err != nil { return SmartError(err) } err = dbImageAliasRename(d.db, id, req.Name) if err != nil { return SmartError(err) } return EmptySyncResponse } func imageExport(d *Daemon, r *http.Request) Response { fingerprint := mux.Vars(r)["fingerprint"] public := !d.isTrustedClient(r) secret := r.FormValue("secret") if public == true && imageValidSecret(fingerprint, secret) == true { public = false } _, imgInfo, err := dbImageGet(d.db, fingerprint, public, false) if err != nil { return SmartError(err) } filename := imgInfo.Filename imagePath := shared.VarPath("images", imgInfo.Fingerprint) rootfsPath := imagePath + ".rootfs" if filename == "" { _, ext, err := detectCompression(imagePath) if err != nil { ext = "" } filename = fmt.Sprintf("%s%s", fingerprint, ext) } if shared.PathExists(rootfsPath) { files := make([]fileResponseEntry, 2) files[0].identifier = "metadata" files[0].path = imagePath files[0].filename = "meta-" + filename files[1].identifier = "rootfs" files[1].path = rootfsPath files[1].filename = filename return FileResponse(r, files, nil, false) } files := make([]fileResponseEntry, 1) files[0].identifier = filename files[0].path = imagePath files[0].filename = filename return FileResponse(r, files, nil, false) } func imageSecret(d *Daemon, r *http.Request) Response { fingerprint := mux.Vars(r)["fingerprint"] _, _, err := dbImageGet(d.db, fingerprint, false, false) if err != nil { return SmartError(err) } secret, err := shared.RandomCryptoString() if err != nil { return InternalError(err) } meta := shared.Jmap{} meta["secret"] = secret resources := map[string][]string{} resources["images"] = []string{fingerprint} op, err := operationCreate(operationClassToken, resources, meta, nil, nil, nil) if err != nil { return InternalError(err) } return OperationResponse(op) } var imagesExportCmd = Command{name: "images/{fingerprint}/export", untrustedGet: true, get: imageExport} var imagesSecretCmd = Command{name: "images/{fingerprint}/secret", post: imageSecret} var aliasesCmd = Command{name: "images/aliases", post: aliasesPost, get: aliasesGet} var aliasCmd = Command{name: "images/aliases/{name:.*}", untrustedGet: true, get: aliasGet, delete: aliasDelete, put: aliasPut, post: aliasPost} lxd-2.0.0/lxd/main.go000066400000000000000000000632001270277227600143570ustar00rootroot00000000000000package main import ( "bufio" "encoding/json" "fmt" "io/ioutil" "math/rand" "net" "net/http" "os" "os/exec" "os/signal" "runtime/pprof" "strconv" "strings" "sync" "syscall" "time" "golang.org/x/crypto/ssh/terminal" "github.com/lxc/lxd" "github.com/lxc/lxd/shared" "github.com/lxc/lxd/shared/gnuflag" "github.com/lxc/lxd/shared/logging" ) // Global arguments var argAuto = gnuflag.Bool("auto", false, "") var argCPUProfile = gnuflag.String("cpuprofile", "", "") var argDebug = gnuflag.Bool("debug", false, "") var argGroup = gnuflag.String("group", "", "") var argHelp = gnuflag.Bool("help", false, "") var argLogfile = gnuflag.String("logfile", "", "") var argMemProfile = gnuflag.String("memprofile", "", "") var argNetworkAddress = gnuflag.String("network-address", "", "") var argNetworkPort = gnuflag.Int("network-port", -1, "") var argPrintGoroutinesEvery = gnuflag.Int("print-goroutines-every", -1, "") var argStorageBackend = gnuflag.String("storage-backend", "", "") var argStorageCreateDevice = gnuflag.String("storage-create-device", "", "") var argStorageCreateLoop = gnuflag.Int("storage-create-loop", -1, "") var argStoragePool = gnuflag.String("storage-pool", "", "") var argSyslog = gnuflag.Bool("syslog", false, "") var argTimeout = gnuflag.Int("timeout", -1, "") var argTrustPassword = gnuflag.String("trust-password", "", "") var argVerbose = gnuflag.Bool("verbose", false, "") var argVersion = gnuflag.Bool("version", false, "") // Global variables var debug bool var verbose bool func init() { rand.Seed(time.Now().UTC().UnixNano()) } func main() { if err := run(); err != nil { fmt.Fprintf(os.Stderr, "error: %v\n", err) os.Exit(1) } } func run() error { // Our massive custom usage gnuflag.Usage = func() { fmt.Printf("Usage: lxd [command] [options]\n") fmt.Printf("\nCommands:\n") fmt.Printf(" activateifneeded\n") fmt.Printf(" Check if LXD should be started (at boot) and if so, spawns it through socket activation\n") fmt.Printf(" daemon [--group=lxd] (default command)\n") fmt.Printf(" Start the main LXD daemon\n") fmt.Printf(" init [--auto] [--network-address=IP] [--network-port=8443] [--storage-backend=dir]\n") fmt.Printf(" [--storage-create-device=DEVICE] [--storage-create-loop=SIZE] [--storage-pool=POOL]\n") fmt.Printf(" [--trust-password=]\n") fmt.Printf(" Setup storage and networking\n") fmt.Printf(" ready\n") fmt.Printf(" Tells LXD that any setup-mode configuration has been done and that it can start containers.\n") fmt.Printf(" shutdown [--timeout=60]\n") fmt.Printf(" Perform a clean shutdown of LXD and all running containers\n") fmt.Printf(" waitready [--timeout=15]\n") fmt.Printf(" Wait until LXD is ready to handle requests\n") fmt.Printf("\n\nCommon options:\n") fmt.Printf(" --debug\n") fmt.Printf(" Enable debug mode\n") fmt.Printf(" --help\n") fmt.Printf(" Print this help message\n") fmt.Printf(" --logfile FILE\n") fmt.Printf(" Logfile to log to (e.g., /var/log/lxd/lxd.log)\n") fmt.Printf(" --syslog\n") fmt.Printf(" Enable syslog logging\n") fmt.Printf(" --verbose\n") fmt.Printf(" Enable verbose mode\n") fmt.Printf(" --version\n") fmt.Printf(" Print LXD's version number and exit\n") fmt.Printf("\nDaemon options:\n") fmt.Printf(" --group GROUP\n") fmt.Printf(" Group which owns the shared socket\n") fmt.Printf("\nDaemon debug options:\n") fmt.Printf(" --cpuprofile FILE\n") fmt.Printf(" Enable cpu profiling into the specified file\n") fmt.Printf(" --memprofile FILE\n") fmt.Printf(" Enable memory profiling into the specified file\n") fmt.Printf(" --print-goroutines-every SECONDS\n") fmt.Printf(" For debugging, print a complete stack trace every n seconds\n") fmt.Printf("\nInit options:\n") fmt.Printf(" --auto\n") fmt.Printf(" Automatic (non-interactive) mode\n") fmt.Printf("\nInit options for non-interactive mode (--auto):\n") fmt.Printf(" --network-address ADDRESS\n") fmt.Printf(" Address to bind LXD to (default: none)\n") fmt.Printf(" --network-port PORT\n") fmt.Printf(" Port to bind LXD to (default: 8443)\n") fmt.Printf(" --storage-backend NAME\n") fmt.Printf(" Storage backend to use (zfs or dir, default: dir)\n") fmt.Printf(" --storage-create-device DEVICE\n") fmt.Printf(" Setup device based storage using DEVICE\n") fmt.Printf(" --storage-create-loop SIZE\n") fmt.Printf(" Setup loop based storage with SIZE in GB\n") fmt.Printf(" --storage-pool NAME\n") fmt.Printf(" Storage pool to use or create\n") fmt.Printf(" --trust-password PASSWORD\n") fmt.Printf(" Password required to add new clients\n") fmt.Printf("\nShutdown options:\n") fmt.Printf(" --timeout SECONDS\n") fmt.Printf(" How long to wait before failing\n") fmt.Printf("\nWaitready options:\n") fmt.Printf(" --timeout SECONDS\n") fmt.Printf(" How long to wait before failing\n") fmt.Printf("\n\nInternal commands (don't call these directly):\n") fmt.Printf(" forkexec\n") fmt.Printf(" Execute a command in a container\n") fmt.Printf(" forkgetnet\n") fmt.Printf(" Get container network information\n") fmt.Printf(" forkgetfile\n") fmt.Printf(" Grab a file from a running container\n") fmt.Printf(" forkmigrate\n") fmt.Printf(" Restore a container after migration\n") fmt.Printf(" forkputfile\n") fmt.Printf(" Push a file to a running container\n") fmt.Printf(" forkstart\n") fmt.Printf(" Start a container\n") fmt.Printf(" callhook\n") fmt.Printf(" Call a container hook\n") } // Parse the arguments gnuflag.Parse(true) // Set the global variables debug = *argDebug verbose = *argVerbose if *argHelp { // The user asked for help via --help, so we shouldn't print to // stderr. gnuflag.SetOut(os.Stdout) gnuflag.Usage() return nil } // Deal with --version right here if *argVersion { fmt.Println(shared.Version) return nil } if len(shared.VarPath("unix.sock")) > 107 { return fmt.Errorf("LXD_DIR is too long, must be < %d", 107-len("unix.sock")) } // Configure logging syslog := "" if *argSyslog { syslog = "lxd" } handler := eventsHandler{} var err error shared.Log, err = logging.GetLogger(syslog, *argLogfile, *argVerbose, *argDebug, handler) if err != nil { fmt.Printf("%s", err) return nil } // Process sub-commands if len(os.Args) > 1 { // "forkputfile", "forkgetfile", "forkmount" and "forkumount" are handled specially in nsexec.go // "forkgetnet" is partially handled in nsexec.go (setns) switch os.Args[1] { // Main commands case "activateifneeded": return cmdActivateIfNeeded() case "daemon": return cmdDaemon() case "callhook": return cmdCallHook(os.Args[1:]) case "init": return cmdInit() case "ready": return cmdReady() case "shutdown": return cmdShutdown() case "waitready": return cmdWaitReady() // Internal commands case "forkgetnet": return printnet() case "forkmigrate": return MigrateContainer(os.Args[1:]) case "forkstart": return startContainer(os.Args[1:]) case "forkexec": ret, err := execContainer(os.Args[1:]) if err != nil { fmt.Fprintf(os.Stderr, "error: %v\n", err) } os.Exit(ret) } } // Fail if some other command is passed if gnuflag.NArg() > 0 { gnuflag.Usage() return fmt.Errorf("Unknown arguments") } return cmdDaemon() } func cmdCallHook(args []string) error { if len(args) < 4 { return fmt.Errorf("Invalid arguments") } path := args[1] id := args[2] state := args[3] target := "" err := os.Setenv("LXD_DIR", path) if err != nil { return err } c, err := lxd.NewClient(&lxd.DefaultConfig, "local") if err != nil { return err } url := fmt.Sprintf("%s/internal/containers/%s/on%s", c.BaseURL, id, state) if state == "stop" { target = os.Getenv("LXC_TARGET") if target == "" { target = "unknown" } url = fmt.Sprintf("%s?target=%s", url, target) } req, err := http.NewRequest("GET", url, nil) if err != nil { return err } hook := make(chan error, 1) go func() { raw, err := c.Http.Do(req) if err != nil { hook <- err return } _, err = lxd.HoistResponse(raw, lxd.Sync) if err != nil { hook <- err return } hook <- nil }() select { case err := <-hook: if err != nil { return err } break case <-time.After(30 * time.Second): return fmt.Errorf("Hook didn't finish within 30s") } if target == "reboot" { return fmt.Errorf("Reboot must be handled by LXD.") } return nil } func cmdDaemon() error { if *argCPUProfile != "" { f, err := os.Create(*argCPUProfile) if err != nil { fmt.Printf("Error opening cpu profile file: %s\n", err) return nil } pprof.StartCPUProfile(f) defer pprof.StopCPUProfile() } if *argMemProfile != "" { go memProfiler(*argMemProfile) } neededPrograms := []string{"setfacl", "rsync", "tar", "xz"} for _, p := range neededPrograms { _, err := exec.LookPath(p) if err != nil { return err } } if *argPrintGoroutinesEvery > 0 { go func() { for { time.Sleep(time.Duration(*argPrintGoroutinesEvery) * time.Second) shared.PrintStack() } }() } d := &Daemon{ group: *argGroup, SetupMode: shared.PathExists(shared.VarPath(".setup_mode"))} err := d.Init() if err != nil { if d != nil && d.db != nil { d.db.Close() } return err } var ret error var wg sync.WaitGroup wg.Add(1) go func() { ch := make(chan os.Signal) signal.Notify(ch, syscall.SIGPWR) sig := <-ch shared.Log.Info( fmt.Sprintf("Received '%s signal', shutting down containers.", sig)) containersShutdown(d) ret = d.Stop() wg.Done() }() go func() { <-d.shutdownChan shared.Log.Info( fmt.Sprintf("Asked to shutdown by API, shutting down containers.")) containersShutdown(d) ret = d.Stop() wg.Done() }() go func() { ch := make(chan os.Signal) signal.Notify(ch, syscall.SIGINT) signal.Notify(ch, syscall.SIGQUIT) signal.Notify(ch, syscall.SIGTERM) sig := <-ch shared.Log.Info(fmt.Sprintf("Received '%s signal', exiting.", sig)) ret = d.Stop() wg.Done() }() wg.Wait() return ret } func cmdReady() error { c, err := lxd.NewClient(&lxd.DefaultConfig, "local") if err != nil { return err } req, err := http.NewRequest("PUT", c.BaseURL+"/internal/ready", nil) if err != nil { return err } raw, err := c.Http.Do(req) if err != nil { return err } _, err = lxd.HoistResponse(raw, lxd.Sync) if err != nil { return err } return nil } func cmdShutdown() error { var timeout int if *argTimeout == -1 { timeout = 60 } else { timeout = *argTimeout } c, err := lxd.NewClient(&lxd.DefaultConfig, "local") if err != nil { return err } req, err := http.NewRequest("PUT", c.BaseURL+"/internal/shutdown", nil) if err != nil { return err } _, err = c.Http.Do(req) if err != nil { return err } monitor := make(chan error, 1) go func() { monitor <- c.Monitor(nil, func(m interface{}) {}) }() select { case <-monitor: break case <-time.After(time.Second * time.Duration(timeout)): return fmt.Errorf("LXD still running after %ds timeout.", timeout) } return nil } func cmdActivateIfNeeded() error { // Don't start a full daemon, we just need DB access d := &Daemon{ imagesDownloading: map[string]chan bool{}, imagesDownloadingLock: sync.RWMutex{}, lxcpath: shared.VarPath("containers"), } err := initializeDbObject(d, shared.VarPath("lxd.db")) if err != nil { return err } // Look for network socket value, err := d.ConfigValueGet("core.https_address") if err != nil { return err } if value != "" { shared.Debugf("Daemon has core.https_address set, activating...") _, err := lxd.NewClient(&lxd.DefaultConfig, "local") return err } // Look for auto-started or previously started containers d.IdmapSet, err = shared.DefaultIdmapSet() if err != nil { return err } result, err := dbContainersList(d.db, cTypeRegular) if err != nil { return err } for _, name := range result { c, err := containerLoadByName(d, name) if err != nil { return err } config := c.ExpandedConfig() lastState := config["volatile.last_state.power"] autoStart := config["boot.autostart"] if c.IsRunning() { shared.Debugf("Daemon has running containers, activating...") _, err := lxd.NewClient(&lxd.DefaultConfig, "local") return err } if lastState == "RUNNING" || lastState == "Running" || autoStart == "true" { shared.Debugf("Daemon has auto-started containers, activating...") _, err := lxd.NewClient(&lxd.DefaultConfig, "local") return err } } shared.Debugf("No need to start the daemon now.") return nil } func cmdWaitReady() error { var timeout int if *argTimeout == -1 { timeout = 15 } else { timeout = *argTimeout } finger := make(chan error, 1) go func() { for { c, err := lxd.NewClient(&lxd.DefaultConfig, "local") if err != nil { time.Sleep(500 * time.Millisecond) continue } req, err := http.NewRequest("GET", c.BaseURL+"/internal/ready", nil) if err != nil { time.Sleep(500 * time.Millisecond) continue } raw, err := c.Http.Do(req) if err != nil { time.Sleep(500 * time.Millisecond) continue } _, err = lxd.HoistResponse(raw, lxd.Sync) if err != nil { time.Sleep(500 * time.Millisecond) continue } finger <- nil return } }() select { case <-finger: break case <-time.After(time.Second * time.Duration(timeout)): return fmt.Errorf("LXD still not running after %ds timeout.", timeout) } return nil } func cmdInit() error { var defaultPrivileged int // controls whether we set security.privileged=true var storageBackend string // dir or zfs var storageMode string // existing, loop or device var storageLoopSize int // Size in GB var storageDevice string // Path var storagePool string // pool name var networkAddress string // Address var networkPort int // Port var trustPassword string // Trust password // Detect userns defaultPrivileged = -1 runningInUserns = shared.RunningInUserNS() // Only root should run this if os.Geteuid() != 0 { return fmt.Errorf("This must be run as root") } backendsAvailable := []string{"dir"} backendsSupported := []string{"dir", "zfs"} // Detect zfs out, err := exec.LookPath("zfs") if err == nil && len(out) != 0 { backendsAvailable = append(backendsAvailable, "zfs") } reader := bufio.NewReader(os.Stdin) askBool := func(question string) bool { for { fmt.Printf(question) input, _ := reader.ReadString('\n') input = strings.TrimSuffix(input, "\n") if shared.StringInSlice(strings.ToLower(input), []string{"yes", "y", "true"}) { return true } else if shared.StringInSlice(strings.ToLower(input), []string{"no", "n", "false"}) { return false } fmt.Printf("Invalid input, try again.\n\n") } } askChoice := func(question string, choices []string) string { for { fmt.Printf(question) input, _ := reader.ReadString('\n') input = strings.TrimSuffix(input, "\n") if shared.StringInSlice(input, choices) { return input } fmt.Printf("Invalid input, try again.\n\n") } } askInt := func(question string, min int, max int) int { for { fmt.Printf(question) input, _ := reader.ReadString('\n') input = strings.TrimSuffix(input, "\n") intInput, err := strconv.Atoi(input) if err == nil && (min == -1 || intInput >= min) && (max == -1 || intInput <= max) { return intInput } fmt.Printf("Invalid input, try again.\n\n") } } askString := func(question string) string { for { fmt.Printf(question) input, _ := reader.ReadString('\n') input = strings.TrimSuffix(input, "\n") if len(input) != 0 { return input } fmt.Printf("Invalid input, try again.\n\n") } } askPassword := func(question string) string { for { fmt.Printf(question) pwd, _ := terminal.ReadPassword(0) fmt.Printf("\n") inFirst := string(pwd) inFirst = strings.TrimSuffix(inFirst, "\n") fmt.Printf("Again: ") pwd, _ = terminal.ReadPassword(0) fmt.Printf("\n") inSecond := string(pwd) inSecond = strings.TrimSuffix(inSecond, "\n") if inFirst == inSecond { return inFirst } fmt.Printf("Invalid input, try again.\n\n") } } // Confirm that LXD is online c, err := lxd.NewClient(&lxd.DefaultConfig, "local") if err != nil { return fmt.Errorf("Unable to talk to LXD: %s", err) } // Check that we have no containers or images in the store containers, err := c.ListContainers() if err != nil { return fmt.Errorf("Unable to list the LXD containers: %s", err) } images, err := c.ListImages() if err != nil { return fmt.Errorf("Unable to list the LXD images: %s", err) } if len(containers) > 0 || len(images) > 0 { return fmt.Errorf("You have existing containers or images. lxd init requires an empty LXD.") } if *argAuto { if *argStorageBackend == "" { *argStorageBackend = "dir" } // Do a bunch of sanity checks if !shared.StringInSlice(*argStorageBackend, backendsSupported) { return fmt.Errorf("The requested backend '%s' isn't supported by lxd init.", *argStorageBackend) } if !shared.StringInSlice(*argStorageBackend, backendsAvailable) { return fmt.Errorf("The requested backend '%s' isn't available on your system (missing tools).", *argStorageBackend) } if *argStorageBackend == "dir" { if *argStorageCreateLoop != -1 || *argStorageCreateDevice != "" || *argStoragePool != "" { return fmt.Errorf("None of --storage-pool, --storage-create-device or --storage-create-pool may be used with the 'dir' backend.") } } if *argStorageBackend == "zfs" { if *argStorageCreateLoop != -1 && *argStorageCreateDevice != "" { return fmt.Errorf("Only one of --storage-create-device or --storage-create-pool can be specified with the 'zfs' backend.") } if *argStoragePool == "" { return fmt.Errorf("--storage-pool must be specified with the 'zfs' backend.") } } if *argNetworkAddress == "" { if *argNetworkPort != -1 { return fmt.Errorf("--network-port cannot be used without --network-address.") } if *argTrustPassword != "" { return fmt.Errorf("--trust-password cannot be used without --network-address.") } } // Set the local variables if *argStorageCreateDevice != "" { storageMode = "device" } else if *argStorageCreateLoop != -1 { storageMode = "loop" } else { storageMode = "existing" } storageBackend = *argStorageBackend storageLoopSize = *argStorageCreateLoop storageDevice = *argStorageCreateDevice storagePool = *argStoragePool networkAddress = *argNetworkAddress networkPort = *argNetworkPort trustPassword = *argTrustPassword } else { if *argStorageBackend != "" || *argStorageCreateDevice != "" || *argStorageCreateLoop != -1 || *argStoragePool != "" || *argNetworkAddress != "" || *argNetworkPort != -1 || *argTrustPassword != "" { return fmt.Errorf("Init configuration is only valid with --auto") } storageBackend = askChoice("Name of the storage backend to use (dir or zfs): ", backendsSupported) if !shared.StringInSlice(storageBackend, backendsSupported) { return fmt.Errorf("The requested backend '%s' isn't supported by lxd init.", storageBackend) } if !shared.StringInSlice(storageBackend, backendsAvailable) { return fmt.Errorf("The requested backend '%s' isn't available on your system (missing tools).", storageBackend) } if storageBackend == "zfs" { if askBool("Create a new ZFS pool (yes/no)? ") { storagePool = askString("Name of the new ZFS pool: ") if askBool("Would you like to use an existing block device (yes/no)? ") { storageDevice = askString("Path to the existing block device: ") storageMode = "device" } else { storageLoopSize = askInt("Size in GB of the new loop device (1GB minimum): ", 1, -1) storageMode = "loop" } } else { storagePool = askString("Name of the existing ZFS pool or dataset: ") storageMode = "existing" } } if runningInUserns { fmt.Printf(` We detected that you are running inside an unprivileged container. This means that unless you manually configured your host otherwise, you will not have enough uid and gid to allocate to your containers. LXD can re-use your container's own allocation to avoid the problem. Doing so makes your nested containers slightly less safe as they could in theory attack their parent container and gain more privileges than they otherwise would. `) if askBool("Would you like to have your containers share their parent's allocation (yes/no)? ") { defaultPrivileged = 1 } else { defaultPrivileged = 0 } } if askBool("Would you like LXD to be available over the network (yes/no)? ") { networkAddress = askString("Address to bind LXD to (not including port): ") networkPort = askInt("Port to bind LXD to (8443 recommended): ", 1, 65535) trustPassword = askPassword("Trust password for new clients: ") } } if !shared.StringInSlice(storageBackend, []string{"dir", "zfs"}) { return fmt.Errorf("Invalid storage backend: %s", storageBackend) } // Unset all storage keys, core.https_address and core.trust_password for _, key := range []string{"core.https_address", "core.trust_password"} { _, err = c.SetServerConfig(key, "") if err != nil { return err } } // Destroy any existing loop device for _, file := range []string{"zfs.img"} { os.Remove(shared.VarPath(file)) } if storageBackend == "zfs" { _ = exec.Command("modprobe", "zfs").Run() if storageMode == "loop" { storageDevice = shared.VarPath("zfs.img") f, err := os.Create(storageDevice) if err != nil { return fmt.Errorf("Failed to open %s: %s", storageDevice, err) } err = f.Truncate(int64(storageLoopSize * 1024 * 1024 * 1024)) if err != nil { return fmt.Errorf("Failed to create sparse file %s: %s", storageDevice, err) } err = f.Close() if err != nil { return fmt.Errorf("Failed to close %s: %s", storageDevice, err) } } if shared.StringInSlice(storageMode, []string{"loop", "device"}) { output, err := exec.Command( "zpool", "create", storagePool, storageDevice, "-f", "-m", "none").CombinedOutput() if err != nil { return fmt.Errorf("Failed to create the ZFS pool: %s", output) } } // Configure LXD to use the pool _, err = c.SetServerConfig("storage.zfs_pool_name", storagePool) if err != nil { return err } } if defaultPrivileged == 0 { err = c.SetProfileConfigItem("default", "security.privileged", "") if err != nil { return err } } else if defaultPrivileged == 1 { err = c.SetProfileConfigItem("default", "security.privileged", "true") if err != nil { } } if networkAddress != "" { _, err = c.SetServerConfig("core.https_address", fmt.Sprintf("%s:%d", networkAddress, networkPort)) if err != nil { return err } if trustPassword != "" { _, err = c.SetServerConfig("core.trust_password", trustPassword) if err != nil { return err } } } fmt.Printf("LXD has been successfully configured.\n") return nil } func printnet() error { networks := map[string]shared.ContainerStateNetwork{} interfaces, err := net.Interfaces() if err != nil { return err } stats := map[string][]int64{} content, err := ioutil.ReadFile("/proc/net/dev") if err == nil { for _, line := range strings.Split(string(content), "\n") { fields := strings.Fields(line) if len(fields) != 17 { continue } rxBytes, err := strconv.ParseInt(fields[1], 10, 64) if err != nil { continue } rxPackets, err := strconv.ParseInt(fields[2], 10, 64) if err != nil { continue } txBytes, err := strconv.ParseInt(fields[9], 10, 64) if err != nil { continue } txPackets, err := strconv.ParseInt(fields[10], 10, 64) if err != nil { continue } intName := strings.TrimSuffix(fields[0], ":") stats[intName] = []int64{rxBytes, rxPackets, txBytes, txPackets} } } for _, netIf := range interfaces { netState := "down" netType := "unknown" if netIf.Flags&net.FlagBroadcast > 0 { netType = "broadcast" } if netIf.Flags&net.FlagPointToPoint > 0 { netType = "point-to-point" } if netIf.Flags&net.FlagLoopback > 0 { netType = "loopback" } if netIf.Flags&net.FlagUp > 0 { netState = "up" } network := shared.ContainerStateNetwork{ Addresses: []shared.ContainerStateNetworkAddress{}, Counters: shared.ContainerStateNetworkCounters{}, Hwaddr: netIf.HardwareAddr.String(), Mtu: netIf.MTU, State: netState, Type: netType, } addrs, err := netIf.Addrs() if err == nil { for _, addr := range addrs { fields := strings.SplitN(addr.String(), "/", 2) if len(fields) != 2 { continue } family := "inet" if strings.Contains(fields[0], ":") { family = "inet6" } scope := "global" if strings.HasPrefix(fields[0], "127") { scope = "local" } if fields[0] == "::1" { scope = "local" } if strings.HasPrefix(fields[0], "169.254") { scope = "link" } if strings.HasPrefix(fields[0], "fe80:") { scope = "link" } address := shared.ContainerStateNetworkAddress{} address.Family = family address.Address = fields[0] address.Netmask = fields[1] address.Scope = scope network.Addresses = append(network.Addresses, address) } } counters, ok := stats[netIf.Name] if ok { network.Counters.BytesReceived = counters[0] network.Counters.PacketsReceived = counters[1] network.Counters.BytesSent = counters[2] network.Counters.PacketsSent = counters[3] } networks[netIf.Name] = network } buf, err := json.Marshal(networks) if err != nil { return err } fmt.Printf("%s\n", buf) return nil } lxd-2.0.0/lxd/main_test.go000066400000000000000000000024421270277227600154170ustar00rootroot00000000000000package main import ( "io/ioutil" "os" "sync" "testing" "github.com/stretchr/testify/require" "github.com/stretchr/testify/suite" ) func mockStartDaemon() (*Daemon, error) { d := &Daemon{ MockMode: true, imagesDownloading: map[string]chan bool{}, imagesDownloadingLock: sync.RWMutex{}, } if err := d.Init(); err != nil { return nil, err } // Call this after Init so we have a log object. storageConfig := make(map[string]interface{}) d.Storage = &storageLogWrapper{w: &storageMock{d: d}} if _, err := d.Storage.Init(storageConfig); err != nil { return nil, err } return d, nil } type lxdTestSuite struct { suite.Suite d *Daemon Req *require.Assertions tmpdir string } func (suite *lxdTestSuite) SetupSuite() { tmpdir, err := ioutil.TempDir("", "lxd_testrun_") if err != nil { os.Exit(1) } suite.tmpdir = tmpdir if err := os.Setenv("LXD_DIR", suite.tmpdir); err != nil { os.Exit(1) } suite.d, err = mockStartDaemon() if err != nil { os.Exit(1) } } func (suite *lxdTestSuite) TearDownSuite() { suite.d.Stop() err := os.RemoveAll(suite.tmpdir) if err != nil { os.Exit(1) } } func (suite *lxdTestSuite) SetupTest() { suite.Req = require.New(suite.T()) } func TestLxdTestSuite(t *testing.T) { suite.Run(t, new(lxdTestSuite)) } lxd-2.0.0/lxd/migrate.go000066400000000000000000000412321270277227600150640ustar00rootroot00000000000000// Package migration provides the primitives for migration in LXD. // // See https://github.com/lxc/lxd/blob/master/specs/migration.md for a complete // description. package main import ( "bufio" "fmt" "io/ioutil" "net/http" "net/url" "os" "os/exec" "path" "path/filepath" "strings" "sync" "time" "github.com/golang/protobuf/proto" "github.com/gorilla/websocket" "gopkg.in/lxc/go-lxc.v2" "github.com/lxc/lxd" "github.com/lxc/lxd/shared" ) type migrationFields struct { live bool controlSecret string controlConn *websocket.Conn controlLock sync.Mutex criuSecret string criuConn *websocket.Conn fsSecret string fsConn *websocket.Conn container container } func (c *migrationFields) send(m proto.Message) error { /* gorilla websocket doesn't allow concurrent writes, and * panic()s if it sees them (which is reasonable). If e.g. we * happen to fail, get scheduled, start our write, then get * unscheduled before the write is bit to a new thread which is * receiving an error from the other side (due to our previous * close), we can engage in these concurrent writes, which * casuses the whole daemon to panic. * * Instead, let's lock sends to the controlConn so that we only ever * write one message at the time. */ c.controlLock.Lock() defer c.controlLock.Unlock() w, err := c.controlConn.NextWriter(websocket.BinaryMessage) if err != nil { return err } defer w.Close() data, err := proto.Marshal(m) if err != nil { return err } return shared.WriteAll(w, data) } func findCriu(host string) error { _, err := exec.LookPath("criu") if err != nil { return fmt.Errorf("CRIU is required for live migration but its binary couldn't be found on the %s server. Is it installed in LXD's path?", host) } return nil } func (c *migrationFields) recv(m proto.Message) error { mt, r, err := c.controlConn.NextReader() if err != nil { return err } if mt != websocket.BinaryMessage { return fmt.Errorf("Only binary messages allowed") } buf, err := ioutil.ReadAll(r) if err != nil { return err } return proto.Unmarshal(buf, m) } func (c *migrationFields) disconnect() { closeMsg := websocket.FormatCloseMessage(websocket.CloseNormalClosure, "") c.controlLock.Lock() if c.controlConn != nil { c.controlConn.WriteMessage(websocket.CloseMessage, closeMsg) c.controlConn = nil /* don't close twice */ } c.controlLock.Unlock() /* Below we just Close(), which doesn't actually write to the * websocket, it just closes the underlying connection. If e.g. there * is still a filesystem transfer going on, but the other side has run * out of disk space, writing an actual CloseMessage here will cause * gorilla websocket to panic. Instead, we just force close this * connection, since we report the error over the control channel * anyway. */ if c.fsConn != nil { c.fsConn.Close() } if c.criuConn != nil { c.criuConn.Close() } } func (c *migrationFields) sendControl(err error) { message := "" if err != nil { message = err.Error() } msg := MigrationControl{ Success: proto.Bool(err == nil), Message: proto.String(message), } c.send(&msg) if err != nil { c.disconnect() } } func (c *migrationFields) controlChannel() <-chan MigrationControl { ch := make(chan MigrationControl) go func() { msg := MigrationControl{} err := c.recv(&msg) if err != nil { shared.Debugf("Got error reading migration control socket %s", err) close(ch) return } ch <- msg }() return ch } func CollectCRIULogFile(c container, imagesDir string, function string, method string) error { t := time.Now().Format(time.RFC3339) newPath := shared.LogPath(c.Name(), fmt.Sprintf("%s_%s_%s.log", function, method, t)) return shared.FileCopy(filepath.Join(imagesDir, fmt.Sprintf("%s.log", method)), newPath) } func GetCRIULogErrors(imagesDir string, method string) (string, error) { f, err := os.Open(path.Join(imagesDir, fmt.Sprintf("%s.log", method))) if err != nil { return "", err } defer f.Close() scanner := bufio.NewScanner(f) ret := []string{} for scanner.Scan() { line := scanner.Text() if strings.Contains(line, "Error") { ret = append(ret, scanner.Text()) } } return strings.Join(ret, "\n"), nil } type migrationSourceWs struct { migrationFields allConnected chan bool } func NewMigrationSource(c container) (*migrationSourceWs, error) { ret := migrationSourceWs{migrationFields{container: c}, make(chan bool, 1)} var err error ret.controlSecret, err = shared.RandomCryptoString() if err != nil { return nil, err } ret.fsSecret, err = shared.RandomCryptoString() if err != nil { return nil, err } if c.IsRunning() { if err := findCriu("source"); err != nil { return nil, err } ret.live = true ret.criuSecret, err = shared.RandomCryptoString() if err != nil { return nil, err } } return &ret, nil } func (s *migrationSourceWs) Metadata() interface{} { secrets := shared.Jmap{ "control": s.controlSecret, "fs": s.fsSecret, } if s.criuSecret != "" { secrets["criu"] = s.criuSecret } return secrets } func (s *migrationSourceWs) Connect(op *operation, r *http.Request, w http.ResponseWriter) error { secret := r.FormValue("secret") if secret == "" { return fmt.Errorf("missing secret") } var conn **websocket.Conn switch secret { case s.controlSecret: conn = &s.controlConn case s.criuSecret: conn = &s.criuConn case s.fsSecret: conn = &s.fsConn default: /* If we didn't find the right secret, the user provided a bad one, * which 403, not 404, since this operation actually exists */ return os.ErrPermission } c, err := shared.WebsocketUpgrader.Upgrade(w, r, nil) if err != nil { return err } *conn = c if s.controlConn != nil && (!s.live || s.criuConn != nil) && s.fsConn != nil { s.allConnected <- true } return nil } func (s *migrationSourceWs) Do(op *operation) error { <-s.allConnected criuType := CRIUType_CRIU_RSYNC.Enum() if !s.live { criuType = nil err := s.container.StorageStart() if err != nil { return err } defer s.container.StorageStop() } idmaps := make([]*IDMapType, 0) idmapset := s.container.IdmapSet() if idmapset != nil { for _, ctnIdmap := range idmapset.Idmap { idmap := IDMapType{ Isuid: proto.Bool(ctnIdmap.Isuid), Isgid: proto.Bool(ctnIdmap.Isgid), Hostid: proto.Int(ctnIdmap.Hostid), Nsid: proto.Int(ctnIdmap.Nsid), Maprange: proto.Int(ctnIdmap.Maprange), } idmaps = append(idmaps, &idmap) } } driver, fsErr := s.container.Storage().MigrationSource(s.container) /* the protocol says we have to send a header no matter what, so let's * do that, but then immediately send an error. */ snapshots := []string{} if fsErr == nil { fullSnaps := driver.Snapshots() for _, snap := range fullSnaps { snapshots = append(snapshots, shared.ExtractSnapshotName(snap.Name())) } } myType := s.container.Storage().MigrationType() header := MigrationHeader{ Fs: &myType, Criu: criuType, Idmap: idmaps, Snapshots: snapshots, } if err := s.send(&header); err != nil { s.sendControl(err) return err } if fsErr != nil { s.sendControl(fsErr) return fsErr } if err := s.recv(&header); err != nil { s.sendControl(err) return err } if *header.Fs != myType { myType = MigrationFSType_RSYNC header.Fs = &myType driver, _ = rsyncMigrationSource(s.container) } if err := driver.SendWhileRunning(s.fsConn); err != nil { driver.Cleanup() s.sendControl(err) return err } if s.live { if header.Criu == nil { driver.Cleanup() err := fmt.Errorf("Got no CRIU socket type for live migration") s.sendControl(err) return err } else if *header.Criu != CRIUType_CRIU_RSYNC { driver.Cleanup() err := fmt.Errorf("Formats other than criu rsync not understood") s.sendControl(err) return err } checkpointDir, err := ioutil.TempDir("", "lxd_checkpoint_") if err != nil { driver.Cleanup() s.sendControl(err) return err } defer os.RemoveAll(checkpointDir) opts := lxc.CheckpointOptions{Stop: true, Directory: checkpointDir, Verbose: true} err = s.container.Checkpoint(opts) if err2 := CollectCRIULogFile(s.container, checkpointDir, "migration", "dump"); err2 != nil { shared.Debugf("Error collecting checkpoint log file %s", err) } if err != nil { driver.Cleanup() log, err2 := GetCRIULogErrors(checkpointDir, "dump") /* couldn't find the CRIU log file which means we * didn't even get that far; give back the liblxc * error. */ if err2 != nil { log = err.Error() } err = fmt.Errorf("checkpoint failed:\n%s", log) s.sendControl(err) return err } /* * We do the serially right now, but there's really no reason for us * to; since we have separate websockets, we can do it in parallel if * we wanted to. However, assuming we're network bound, there's really * no reason to do these in parallel. In the future when we're using * p.haul's protocol, it will make sense to do these in parallel. */ if err := RsyncSend(shared.AddSlash(checkpointDir), s.criuConn); err != nil { driver.Cleanup() s.sendControl(err) return err } if err := driver.SendAfterCheckpoint(s.fsConn); err != nil { driver.Cleanup() s.sendControl(err) return err } } driver.Cleanup() msg := MigrationControl{} if err := s.recv(&msg); err != nil { s.disconnect() return err } // TODO: should we add some config here about automatically restarting // the container migrate failure? What about the failures above? if !*msg.Success { return fmt.Errorf(*msg.Message) } return nil } type migrationSink struct { migrationFields url string dialer websocket.Dialer } type MigrationSinkArgs struct { Url string Dialer websocket.Dialer Container container Secrets map[string]string } func NewMigrationSink(args *MigrationSinkArgs) (func() error, error) { sink := migrationSink{ migrationFields{container: args.Container}, args.Url, args.Dialer, } var ok bool sink.controlSecret, ok = args.Secrets["control"] if !ok { return nil, fmt.Errorf("Missing control secret") } sink.fsSecret, ok = args.Secrets["fs"] if !ok { return nil, fmt.Errorf("Missing fs secret") } sink.criuSecret, ok = args.Secrets["criu"] sink.live = ok if err := findCriu("destination"); sink.live && err != nil { return nil, err } return sink.do, nil } func (c *migrationSink) connectWithSecret(secret string) (*websocket.Conn, error) { query := url.Values{"secret": []string{secret}} // The URL is a https URL to the operation, mangle to be a wss URL to the secret wsUrl := fmt.Sprintf("wss://%s/websocket?%s", strings.TrimPrefix(c.url, "https://"), query.Encode()) return lxd.WebsocketDial(c.dialer, wsUrl) } func (c *migrationSink) do() error { var err error c.controlConn, err = c.connectWithSecret(c.controlSecret) if err != nil { return err } defer c.disconnect() c.fsConn, err = c.connectWithSecret(c.fsSecret) if err != nil { c.sendControl(err) return err } if c.live { c.criuConn, err = c.connectWithSecret(c.criuSecret) if err != nil { c.sendControl(err) return err } } header := MigrationHeader{} if err := c.recv(&header); err != nil { c.sendControl(err) return err } criuType := CRIUType_CRIU_RSYNC.Enum() if !c.live { criuType = nil } mySink := c.container.Storage().MigrationSink myType := c.container.Storage().MigrationType() resp := MigrationHeader{ Fs: &myType, Criu: criuType, } // If the storage type the source has doesn't match what we have, then // we have to use rsync. if *header.Fs != *resp.Fs { mySink = rsyncMigrationSink myType = MigrationFSType_RSYNC resp.Fs = &myType } if err := c.send(&resp); err != nil { c.sendControl(err) return err } restore := make(chan error) go func(c *migrationSink) { imagesDir := "" srcIdmap := new(shared.IdmapSet) snapshots := []container{} for _, snap := range header.Snapshots { // TODO: we need to propagate snapshot configurations // as well. Right now the container configuration is // done through the initial migration post. Should we // post the snapshots and their configs as well, or do // it some other way? name := c.container.Name() + shared.SnapshotDelimiter + snap args := containerArgs{ Ctype: cTypeSnapshot, Config: c.container.LocalConfig(), Profiles: c.container.Profiles(), Ephemeral: c.container.IsEphemeral(), Architecture: c.container.Architecture(), Devices: c.container.LocalDevices(), Name: name, } ct, err := containerCreateEmptySnapshot(c.container.Daemon(), args) if err != nil { restore <- err return } snapshots = append(snapshots, ct) } for _, idmap := range header.Idmap { e := shared.IdmapEntry{ Isuid: *idmap.Isuid, Isgid: *idmap.Isgid, Nsid: int(*idmap.Nsid), Hostid: int(*idmap.Hostid), Maprange: int(*idmap.Maprange)} srcIdmap.Idmap = shared.Extend(srcIdmap.Idmap, e) } /* We do the fs receive in parallel so we don't have to reason * about when to receive what. The sending side is smart enough * to send the filesystem bits that it can before it seizes the * container to start checkpointing, so the total transfer time * will be minimized even if we're dumb here. */ fsTransfer := make(chan error) go func() { if err := mySink(c.live, c.container, snapshots, c.fsConn); err != nil { fsTransfer <- err return } if err := ShiftIfNecessary(c.container, srcIdmap); err != nil { fsTransfer <- err return } fsTransfer <- nil }() if c.live { var err error imagesDir, err = ioutil.TempDir("", "lxd_restore_") if err != nil { os.RemoveAll(imagesDir) return } defer func() { err := CollectCRIULogFile(c.container, imagesDir, "migration", "restore") /* * If the checkpoint fails, we won't have any log to collect, * so don't warn about that. */ if err != nil && !os.IsNotExist(err) { shared.Debugf("Error collectiong migration log file %s", err) } os.RemoveAll(imagesDir) }() if err := RsyncRecv(shared.AddSlash(imagesDir), c.criuConn); err != nil { restore <- err return } /* * For unprivileged containers we need to shift the * perms on the images images so that they can be * opened by the process after it is in its user * namespace. */ if !c.container.IsPrivileged() { if err := c.container.IdmapSet().ShiftRootfs(imagesDir); err != nil { restore <- err return } } } err := <-fsTransfer if err != nil { restore <- err return } if c.live { err := c.container.StartFromMigration(imagesDir) if err != nil { log, err2 := GetCRIULogErrors(imagesDir, "restore") /* restore failed before CRIU was invoked, give * back the liblxc error */ if err2 != nil { log = err.Error() } err = fmt.Errorf("restore failed:\n%s", log) restore <- err return } } for _, snap := range snapshots { if err := ShiftIfNecessary(snap, srcIdmap); err != nil { restore <- err return } } restore <- nil }(c) source := c.controlChannel() for { select { case err = <-restore: c.sendControl(err) return err case msg, ok := <-source: if !ok { c.disconnect() return fmt.Errorf("Got error reading source") } if !*msg.Success { c.disconnect() return fmt.Errorf(*msg.Message) } else { // The source can only tell us it failed (e.g. if // checkpointing failed). We have to tell the source // whether or not the restore was successful. shared.Debugf("Unknown message %v from source", msg) } } } } /* * Similar to forkstart, this is called when lxd is invoked as: * * lxd forkmigrate * * liblxc's restore() sets up the processes in such a way that the monitor ends * up being a child of the process that calls it, in our case lxd. However, we * really want the monitor to be daemonized, so we fork again. Additionally, we * want to fork for the same reasons we do forkstart (i.e. reduced memory * footprint when we fork tasks that will never free golang's memory, etc.) */ func MigrateContainer(args []string) error { if len(args) != 5 { return fmt.Errorf("Bad arguments %q", args) } name := args[1] lxcpath := args[2] configPath := args[3] imagesDir := args[4] defer os.Remove(configPath) c, err := lxc.NewContainer(name, lxcpath) if err != nil { return err } if err := c.LoadConfigFile(configPath); err != nil { return err } /* see https://github.com/golang/go/issues/13155, startContainer, and dc3a229 */ os.Stdin.Close() os.Stdout.Close() os.Stderr.Close() return c.Restore(lxc.RestoreOptions{ Directory: imagesDir, Verbose: true, }) } lxd-2.0.0/lxd/migrate.pb.go000066400000000000000000000120031270277227600154560ustar00rootroot00000000000000// Code generated by protoc-gen-go. // source: lxd/migrate.proto // DO NOT EDIT! /* Package main is a generated protocol buffer package. It is generated from these files: lxd/migrate.proto It has these top-level messages: IDMapType MigrationHeader MigrationControl */ package main import proto "github.com/golang/protobuf/proto" import math "math" // Reference imports to suppress errors if they are not otherwise used. var _ = proto.Marshal var _ = math.Inf type MigrationFSType int32 const ( MigrationFSType_RSYNC MigrationFSType = 0 MigrationFSType_BTRFS MigrationFSType = 1 MigrationFSType_ZFS MigrationFSType = 2 ) var MigrationFSType_name = map[int32]string{ 0: "RSYNC", 1: "BTRFS", 2: "ZFS", } var MigrationFSType_value = map[string]int32{ "RSYNC": 0, "BTRFS": 1, "ZFS": 2, } func (x MigrationFSType) Enum() *MigrationFSType { p := new(MigrationFSType) *p = x return p } func (x MigrationFSType) String() string { return proto.EnumName(MigrationFSType_name, int32(x)) } func (x *MigrationFSType) UnmarshalJSON(data []byte) error { value, err := proto.UnmarshalJSONEnum(MigrationFSType_value, data, "MigrationFSType") if err != nil { return err } *x = MigrationFSType(value) return nil } type CRIUType int32 const ( CRIUType_CRIU_RSYNC CRIUType = 0 CRIUType_PHAUL CRIUType = 1 ) var CRIUType_name = map[int32]string{ 0: "CRIU_RSYNC", 1: "PHAUL", } var CRIUType_value = map[string]int32{ "CRIU_RSYNC": 0, "PHAUL": 1, } func (x CRIUType) Enum() *CRIUType { p := new(CRIUType) *p = x return p } func (x CRIUType) String() string { return proto.EnumName(CRIUType_name, int32(x)) } func (x *CRIUType) UnmarshalJSON(data []byte) error { value, err := proto.UnmarshalJSONEnum(CRIUType_value, data, "CRIUType") if err != nil { return err } *x = CRIUType(value) return nil } type IDMapType struct { Isuid *bool `protobuf:"varint,1,req,name=isuid" json:"isuid,omitempty"` Isgid *bool `protobuf:"varint,2,req,name=isgid" json:"isgid,omitempty"` Hostid *int32 `protobuf:"varint,3,req,name=hostid" json:"hostid,omitempty"` Nsid *int32 `protobuf:"varint,4,req,name=nsid" json:"nsid,omitempty"` Maprange *int32 `protobuf:"varint,5,req,name=maprange" json:"maprange,omitempty"` XXX_unrecognized []byte `json:"-"` } func (m *IDMapType) Reset() { *m = IDMapType{} } func (m *IDMapType) String() string { return proto.CompactTextString(m) } func (*IDMapType) ProtoMessage() {} func (m *IDMapType) GetIsuid() bool { if m != nil && m.Isuid != nil { return *m.Isuid } return false } func (m *IDMapType) GetIsgid() bool { if m != nil && m.Isgid != nil { return *m.Isgid } return false } func (m *IDMapType) GetHostid() int32 { if m != nil && m.Hostid != nil { return *m.Hostid } return 0 } func (m *IDMapType) GetNsid() int32 { if m != nil && m.Nsid != nil { return *m.Nsid } return 0 } func (m *IDMapType) GetMaprange() int32 { if m != nil && m.Maprange != nil { return *m.Maprange } return 0 } type MigrationHeader struct { Fs *MigrationFSType `protobuf:"varint,1,req,name=fs,enum=main.MigrationFSType" json:"fs,omitempty"` Criu *CRIUType `protobuf:"varint,2,opt,name=criu,enum=main.CRIUType" json:"criu,omitempty"` Idmap []*IDMapType `protobuf:"bytes,3,rep,name=idmap" json:"idmap,omitempty"` Snapshots []string `protobuf:"bytes,4,rep,name=snapshots" json:"snapshots,omitempty"` XXX_unrecognized []byte `json:"-"` } func (m *MigrationHeader) Reset() { *m = MigrationHeader{} } func (m *MigrationHeader) String() string { return proto.CompactTextString(m) } func (*MigrationHeader) ProtoMessage() {} func (m *MigrationHeader) GetFs() MigrationFSType { if m != nil && m.Fs != nil { return *m.Fs } return MigrationFSType_RSYNC } func (m *MigrationHeader) GetCriu() CRIUType { if m != nil && m.Criu != nil { return *m.Criu } return CRIUType_CRIU_RSYNC } func (m *MigrationHeader) GetIdmap() []*IDMapType { if m != nil { return m.Idmap } return nil } func (m *MigrationHeader) GetSnapshots() []string { if m != nil { return m.Snapshots } return nil } type MigrationControl struct { Success *bool `protobuf:"varint,1,req,name=success" json:"success,omitempty"` // optional failure message if sending a failure Message *string `protobuf:"bytes,2,opt,name=message" json:"message,omitempty"` XXX_unrecognized []byte `json:"-"` } func (m *MigrationControl) Reset() { *m = MigrationControl{} } func (m *MigrationControl) String() string { return proto.CompactTextString(m) } func (*MigrationControl) ProtoMessage() {} func (m *MigrationControl) GetSuccess() bool { if m != nil && m.Success != nil { return *m.Success } return false } func (m *MigrationControl) GetMessage() string { if m != nil && m.Message != nil { return *m.Message } return "" } func init() { proto.RegisterEnum("main.MigrationFSType", MigrationFSType_name, MigrationFSType_value) proto.RegisterEnum("main.CRIUType", CRIUType_name, CRIUType_value) } lxd-2.0.0/lxd/migrate.proto000066400000000000000000000013071270277227600156210ustar00rootroot00000000000000package main; enum MigrationFSType { RSYNC = 0; BTRFS = 1; ZFS = 2; } enum CRIUType { CRIU_RSYNC = 0; PHAUL = 1; } message IDMapType { required bool isuid = 1; required bool isgid = 2; required int32 hostid = 3; required int32 nsid = 4; required int32 maprange = 5; } message MigrationHeader { required MigrationFSType fs = 1; optional CRIUType criu = 2; repeated IDMapType idmap = 3; repeated string snapshots = 4; } message MigrationControl { required bool success = 1; /* optional failure message if sending a failure */ optional string message = 2; } lxd-2.0.0/lxd/networks.go000066400000000000000000000050501270277227600153060ustar00rootroot00000000000000package main import ( "fmt" "net" "net/http" "strconv" "github.com/gorilla/mux" "github.com/lxc/lxd/shared" ) func networksGet(d *Daemon, r *http.Request) Response { recursionStr := r.FormValue("recursion") recursion, err := strconv.Atoi(recursionStr) if err != nil { recursion = 0 } ifs, err := net.Interfaces() if err != nil { return InternalError(err) } resultString := []string{} resultMap := []network{} for _, iface := range ifs { if recursion == 0 { resultString = append(resultString, fmt.Sprintf("/%s/networks/%s", shared.APIVersion, iface.Name)) } else { net, err := doNetworkGet(d, iface.Name) if err != nil { continue } resultMap = append(resultMap, net) } } if recursion == 0 { return SyncResponse(true, resultString) } return SyncResponse(true, resultMap) } var networksCmd = Command{name: "networks", get: networksGet} type network struct { Name string `json:"name"` Type string `json:"type"` UsedBy []string `json:"used_by"` } func isOnBridge(c container, bridge string) bool { for _, device := range c.ExpandedDevices() { if device["type"] != "nic" { continue } if !shared.StringInSlice(device["nictype"], []string{"bridged", "macvlan"}) { continue } if device["parent"] == "" { continue } if device["parent"] == bridge { return true } } return false } func networkGet(d *Daemon, r *http.Request) Response { name := mux.Vars(r)["name"] n, err := doNetworkGet(d, name) if err != nil { return InternalError(err) } return SyncResponse(true, &n) } func doNetworkGet(d *Daemon, name string) (network, error) { iface, err := net.InterfaceByName(name) if err != nil { return network{}, err } // Prepare the response n := network{} n.Name = iface.Name n.UsedBy = []string{} // Look for containers using the interface cts, err := dbContainersList(d.db, cTypeRegular) if err != nil { return network{}, err } for _, ct := range cts { c, err := containerLoadByName(d, ct) if err != nil { return network{}, err } if isOnBridge(c, n.Name) { n.UsedBy = append(n.UsedBy, fmt.Sprintf("/%s/containers/%s", shared.APIVersion, ct)) } } // Set the device type as needed if shared.IsLoopback(iface) { n.Type = "loopback" } else if shared.PathExists(fmt.Sprintf("/sys/class/net/%s/bridge", n.Name)) { n.Type = "bridge" } else if shared.PathExists(fmt.Sprintf("/sys/class/net/%s/device", n.Name)) { n.Type = "physical" } else { n.Type = "unknown" } return n, nil } var networkCmd = Command{name: "networks/{name}", get: networkGet} lxd-2.0.0/lxd/nsexec.go000066400000000000000000000217621270277227600147270ustar00rootroot00000000000000/** * This file is a bit funny. The goal here is to use setns() to manipulate * files inside the container, so we don't have to reason about the paths to * make sure they don't escape (we can simply rely on the kernel for * correctness). Unfortunately, you can't setns() to a mount namespace with a * multi-threaded program, which every golang binary is. However, by declaring * our init as an initializer, we can capture process control before it is * transferred to the golang runtime, so we can then setns() as we'd like * before golang has a chance to set up any threads. So, we implement two new * lxd fork* commands which are captured here, and take a file on the host fs * and copy it into the container ns. * * An alternative to this would be to move this code into a separate binary, * which of course has problems of its own when it comes to packaging (how do * we find the binary, what do we do if someone does file push and it is * missing, etc.). After some discussion, even though the embedded method is * somewhat convoluted, it was preferred. */ package main /* #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // This expects: // ./lxd forkputfile /source/path /target/path // or // ./lxd forkgetfile /target/path /soruce/path // i.e. 8 arguments, each which have a max length of PATH_MAX. // Unfortunately, lseek() and fstat() both fail (EINVAL and 0 size) for // procfs. Also, we can't mmap, because procfs doesn't support that, either. // #define CMDLINE_SIZE (8 * PATH_MAX) int mkdir_p(const char *dir, mode_t mode) { const char *tmp = dir; const char *orig = dir; char *makeme; do { dir = tmp + strspn(tmp, "/"); tmp = dir + strcspn(dir, "/"); makeme = strndup(orig, dir - orig); if (*makeme) { if (mkdir(makeme, mode) && errno != EEXIST) { fprintf(stderr, "failed to create directory '%s'", makeme); free(makeme); return -1; } } free(makeme); } while(tmp != dir); return 0; } int copy(int target, int source) { ssize_t n; char buf[1024]; if (ftruncate(target, 0) < 0) { perror("error: truncate"); return -1; } while ((n = read(source, buf, 1024)) > 0) { if (write(target, buf, n) != n) { perror("error: write"); return -1; } } if (n < 0) { perror("error: read"); return -1; } return 0; } int dosetns(int pid, char *nstype) { int mntns; char buf[PATH_MAX]; sprintf(buf, "/proc/%d/ns/%s", pid, nstype); mntns = open(buf, O_RDONLY); if (mntns < 0) { perror("error: open mntns"); return -1; } if (setns(mntns, 0) < 0) { perror("error: setns"); close(mntns); return -1; } close(mntns); return 0; } int manip_file_in_ns(char *rootfs, int pid, char *host, char *container, bool is_put, uid_t uid, gid_t gid, mode_t mode) { int host_fd, container_fd; int ret = -1; int container_open_flags; struct stat st; host_fd = open(host, O_RDWR); if (host_fd < 0) { perror("error: open"); return -1; } container_open_flags = O_RDWR; if (is_put) container_open_flags |= O_CREAT; if (pid > 0) { if (dosetns(pid, "mnt") < 0) { perror("error: setns"); goto close_host; } } else { if (chroot(rootfs) < 0) { perror("error: chroot"); goto close_host; } if (chdir("/") < 0) { perror("error: chdir"); goto close_host; } } umask(0); container_fd = open(container, container_open_flags, mode); if (container_fd < 0) { perror("error: open"); goto close_host; } if (is_put) { if (copy(container_fd, host_fd) < 0) { perror("error: copy"); goto close_container; } if (fchown(container_fd, uid, gid) < 0) { perror("error: chown"); goto close_container; } ret = 0; } else { ret = copy(host_fd, container_fd); if (fstat(container_fd, &st) < 0) { perror("error: stat"); goto close_container; } fprintf(stderr, "uid: %ld\n", (long)st.st_uid); fprintf(stderr, "gid: %ld\n", (long)st.st_gid); fprintf(stderr, "mode: %ld\n", (unsigned long)st.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO)); } close_container: close(container_fd); close_host: close(host_fd); return ret; } #define ADVANCE_ARG_REQUIRED() \ do { \ while (*cur != 0) \ cur++; \ cur++; \ if (size <= cur - buf) { \ fprintf(stderr, "not enough arguments\n"); \ _exit(1); \ } \ } while(0) void ensure_dir(char *dest) { struct stat sb; if (stat(dest, &sb) == 0) { if ((sb.st_mode & S_IFMT) == S_IFDIR) return; if (unlink(dest) < 0) { fprintf(stderr, "Failed to remove old %s: %s\n", dest, strerror(errno)); _exit(1); } } if (mkdir(dest, 0755) < 0) { fprintf(stderr, "Failed to mkdir %s: %s\n", dest, strerror(errno)); _exit(1); } } void ensure_file(char *dest) { struct stat sb; int fd; if (stat(dest, &sb) == 0) { if ((sb.st_mode & S_IFMT) != S_IFDIR) return; if (rmdir(dest) < 0) { fprintf(stderr, "Failed to remove old %s: %s\n", dest, strerror(errno)); _exit(1); } } fd = creat(dest, 0755); if (fd < 0) { fprintf(stderr, "Failed to mkdir %s: %s\n", dest, strerror(errno)); _exit(1); } close(fd); } void create(char *src, char *dest) { char *destdirname; struct stat sb; if (stat(src, &sb) < 0) { fprintf(stderr, "source %s does not exist\n", src); _exit(1); } destdirname = strdup(dest); destdirname = dirname(destdirname); if (mkdir_p(destdirname, 0755) < 0) { fprintf(stderr, "failed to create path: %s\n", destdirname); free(destdirname); _exit(1); } switch (sb.st_mode & S_IFMT) { case S_IFDIR: ensure_dir(dest); return; default: ensure_file(dest); return; } free(destdirname); } void forkmount(char *buf, char *cur, ssize_t size) { char *src, *dest, *opts; ADVANCE_ARG_REQUIRED(); int pid = atoi(cur); if (dosetns(pid, "mnt") < 0) { fprintf(stderr, "Failed setns to container mount namespace: %s\n", strerror(errno)); _exit(1); } ADVANCE_ARG_REQUIRED(); src = cur; ADVANCE_ARG_REQUIRED(); dest = cur; create(src, dest); if (access(src, F_OK) < 0) { fprintf(stderr, "Mount source doesn't exist: %s\n", strerror(errno)); _exit(1); } if (access(dest, F_OK) < 0) { fprintf(stderr, "Mount destination doesn't exist: %s\n", strerror(errno)); _exit(1); } // Here, we always move recursively, because we sometimes allow // recursive mounts. If the mount has no kids then it doesn't matter, // but if it does, we want to move those too. if (mount(src, dest, "none", MS_MOVE | MS_REC, NULL) < 0) { fprintf(stderr, "Failed mounting %s onto %s: %s\n", src, dest, strerror(errno)); _exit(1); } _exit(0); } void forkumount(char *buf, char *cur, ssize_t size) { ADVANCE_ARG_REQUIRED(); int pid = atoi(cur); if (dosetns(pid, "mnt") < 0) { fprintf(stderr, "Failed setns to container mount namespace: %s\n", strerror(errno)); _exit(1); } ADVANCE_ARG_REQUIRED(); if (access(cur, F_OK) < 0) { fprintf(stderr, "Mount path doesn't exist: %s\n", strerror(errno)); _exit(1); } if (umount2(cur, MNT_DETACH) < 0) { fprintf(stderr, "Error unmounting %s: %s\n", cur, strerror(errno)); _exit(1); } _exit(0); } void forkdofile(char *buf, char *cur, bool is_put, ssize_t size) { uid_t uid = 0; gid_t gid = 0; mode_t mode = 0; char *command = cur, *rootfs = NULL, *source = NULL, *target = NULL; pid_t pid; ADVANCE_ARG_REQUIRED(); rootfs = cur; ADVANCE_ARG_REQUIRED(); pid = atoi(cur); ADVANCE_ARG_REQUIRED(); source = cur; ADVANCE_ARG_REQUIRED(); target = cur; if (is_put) { ADVANCE_ARG_REQUIRED(); uid = atoi(cur); ADVANCE_ARG_REQUIRED(); gid = atoi(cur); ADVANCE_ARG_REQUIRED(); mode = atoi(cur); } _exit(manip_file_in_ns(rootfs, pid, source, target, is_put, uid, gid, mode)); } void forkgetnet(char *buf, char *cur, ssize_t size) { ADVANCE_ARG_REQUIRED(); int pid = atoi(cur); if (dosetns(pid, "net") < 0) { fprintf(stderr, "Failed setns to container network namespace: %s\n", strerror(errno)); _exit(1); } // The rest happens in Go } __attribute__((constructor)) void init(void) { int cmdline; char buf[CMDLINE_SIZE]; ssize_t size; char *cur; cmdline = open("/proc/self/cmdline", O_RDONLY); if (cmdline < 0) { perror("error: open"); _exit(232); } memset(buf, 0, sizeof(buf)); if ((size = read(cmdline, buf, sizeof(buf)-1)) < 0) { close(cmdline); perror("error: read"); _exit(232); } close(cmdline); cur = buf; // skip argv[0] while (*cur != 0) cur++; cur++; if (size <= cur - buf) return; if (strcmp(cur, "forkputfile") == 0) { forkdofile(buf, cur, true, size); } else if (strcmp(cur, "forkgetfile") == 0) { forkdofile(buf, cur, false, size); } else if (strcmp(cur, "forkmount") == 0) { forkmount(buf, cur, size); } else if (strcmp(cur, "forkumount") == 0) { forkumount(buf, cur, size); } else if (strcmp(cur, "forkgetnet") == 0) { forkgetnet(buf, cur, size); } } */ import "C" lxd-2.0.0/lxd/operations.go000066400000000000000000000302761270277227600156250ustar00rootroot00000000000000package main import ( "fmt" "net/http" "runtime" "strings" "sync" "time" "github.com/gorilla/mux" "github.com/pborman/uuid" "github.com/lxc/lxd/shared" ) var operationsLock sync.Mutex var operations map[string]*operation = make(map[string]*operation) type operationClass int const ( operationClassTask operationClass = 1 operationClassWebsocket operationClass = 2 operationClassToken operationClass = 3 ) func (t operationClass) String() string { return map[operationClass]string{ operationClassTask: "task", operationClassWebsocket: "websocket", operationClassToken: "token", }[t] } type operation struct { id string class operationClass createdAt time.Time updatedAt time.Time status shared.StatusCode url string resources map[string][]string metadata map[string]interface{} err string readonly bool // Those functions are called at various points in the operation lifecycle onRun func(*operation) error onCancel func(*operation) error onConnect func(*operation, *http.Request, http.ResponseWriter) error // Channels used for error reporting and state tracking of background actions chanDone chan error // Locking for concurent access to the operation lock sync.Mutex } func (op *operation) done() { if op.readonly { return } op.lock.Lock() op.readonly = true op.onRun = nil op.onCancel = nil op.onConnect = nil close(op.chanDone) op.lock.Unlock() time.AfterFunc(time.Second*5, func() { operationsLock.Lock() _, ok := operations[op.id] if !ok { operationsLock.Unlock() return } delete(operations, op.id) operationsLock.Unlock() /* * When we create a new lxc.Container, it adds a finalizer (via * SetFinalizer) that frees the struct. However, it sometimes * takes the go GC a while to actually free the struct, * presumably since it is a small amount of memory. * Unfortunately, the struct also keeps the log fd open, so if * we leave too many of these around, we end up running out of * fds. So, let's explicitly do a GC to collect these at the * end of each request. */ runtime.GC() }) } func (op *operation) Run() (chan error, error) { if op.status != shared.Pending { return nil, fmt.Errorf("Only pending operations can be started") } chanRun := make(chan error, 1) op.lock.Lock() op.status = shared.Running if op.onRun != nil { go func(op *operation, chanRun chan error) { err := op.onRun(op) if err != nil { op.lock.Lock() op.status = shared.Failure op.err = err.Error() op.lock.Unlock() op.done() chanRun <- err shared.Debugf("Failure for %s operation: %s: %s", op.class.String(), op.id, err) _, md, _ := op.Render() eventSend("operation", md) return } op.lock.Lock() op.status = shared.Success op.lock.Unlock() op.done() chanRun <- nil shared.Debugf("Success for %s operation: %s", op.class.String(), op.id) _, md, _ := op.Render() eventSend("operation", md) }(op, chanRun) } op.lock.Unlock() shared.Debugf("Started %s operation: %s", op.class.String(), op.id) _, md, _ := op.Render() eventSend("operation", md) return chanRun, nil } func (op *operation) Cancel() (chan error, error) { if op.status != shared.Running { return nil, fmt.Errorf("Only running operations can be cancelled") } if !op.mayCancel() { return nil, fmt.Errorf("This operation can't be cancelled") } chanCancel := make(chan error, 1) op.lock.Lock() oldStatus := op.status op.status = shared.Cancelling op.lock.Unlock() if op.onCancel != nil { go func(op *operation, oldStatus shared.StatusCode, chanCancel chan error) { err := op.onCancel(op) if err != nil { op.lock.Lock() op.status = oldStatus op.lock.Unlock() chanCancel <- err shared.Debugf("Failed to cancel %s operation: %s: %s", op.class.String(), op.id, err) _, md, _ := op.Render() eventSend("operation", md) return } op.lock.Lock() op.status = shared.Cancelled op.lock.Unlock() op.done() chanCancel <- nil shared.Debugf("Cancelled %s operation: %s", op.class.String(), op.id) _, md, _ := op.Render() eventSend("operation", md) }(op, oldStatus, chanCancel) } shared.Debugf("Cancelling %s operation: %s", op.class.String(), op.id) _, md, _ := op.Render() eventSend("operation", md) if op.onCancel == nil { op.lock.Lock() op.status = shared.Cancelled op.lock.Unlock() op.done() chanCancel <- nil } shared.Debugf("Cancelled %s operation: %s", op.class.String(), op.id) _, md, _ = op.Render() eventSend("operation", md) return chanCancel, nil } func (op *operation) Connect(r *http.Request, w http.ResponseWriter) (chan error, error) { if op.class != operationClassWebsocket { return nil, fmt.Errorf("Only websocket operations can be connected") } if op.status != shared.Running { return nil, fmt.Errorf("Only running operations can be connected") } chanConnect := make(chan error, 1) op.lock.Lock() go func(op *operation, chanConnect chan error) { err := op.onConnect(op, r, w) if err != nil { chanConnect <- err shared.Debugf("Failed to handle %s operation: %s: %s", op.class.String(), op.id, err) _, md, _ := op.Render() eventSend("operation", md) return } chanConnect <- nil shared.Debugf("Handled %s operation: %s", op.class.String(), op.id) _, md, _ := op.Render() eventSend("operation", md) }(op, chanConnect) op.lock.Unlock() shared.Debugf("Connected %s operation: %s", op.class.String(), op.id) _, md, _ := op.Render() eventSend("operation", md) return chanConnect, nil } func (op *operation) mayCancel() bool { return op.onCancel != nil || op.class == operationClassToken } func (op *operation) Render() (string, *shared.Operation, error) { // Setup the resource URLs resources := op.resources if resources != nil { tmpResources := make(map[string][]string) for key, value := range resources { var values []string for _, c := range value { values = append(values, fmt.Sprintf("/%s/%s/%s", shared.APIVersion, key, c)) } tmpResources[key] = values } resources = tmpResources } md := shared.Jmap(op.metadata) return op.url, &shared.Operation{ Id: op.id, Class: op.class.String(), CreatedAt: op.createdAt, UpdatedAt: op.updatedAt, Status: op.status.String(), StatusCode: op.status, Resources: resources, Metadata: &md, MayCancel: op.mayCancel(), Err: op.err, }, nil } func (op *operation) WaitFinal(timeout int) (bool, error) { // Check current state if op.status.IsFinal() { return true, nil } // Wait indefinitely if timeout == -1 { for { <-op.chanDone return true, nil } } // Wait until timeout if timeout > 0 { timer := time.NewTimer(time.Duration(timeout) * time.Second) for { select { case <-op.chanDone: return false, nil case <-timer.C: return false, nil } } } return false, nil } func (op *operation) UpdateResources(opResources map[string][]string) error { if op.status != shared.Pending && op.status != shared.Running { return fmt.Errorf("Only pending or running operations can be updated") } if op.readonly { return fmt.Errorf("Read-only operations can't be updated") } op.lock.Lock() op.updatedAt = time.Now() op.resources = opResources op.lock.Unlock() shared.Debugf("Updated resources for %s operation: %s", op.class.String(), op.id) _, md, _ := op.Render() eventSend("operation", md) return nil } func (op *operation) UpdateMetadata(opMetadata interface{}) error { if op.status != shared.Pending && op.status != shared.Running { return fmt.Errorf("Only pending or running operations can be updated") } if op.readonly { return fmt.Errorf("Read-only operations can't be updated") } newMetadata, err := shared.ParseMetadata(opMetadata) if err != nil { return err } op.lock.Lock() op.updatedAt = time.Now() op.metadata = newMetadata op.lock.Unlock() shared.Debugf("Updated metadata for %s operation: %s", op.class.String(), op.id) _, md, _ := op.Render() eventSend("operation", md) return nil } func operationCreate(opClass operationClass, opResources map[string][]string, opMetadata interface{}, onRun func(*operation) error, onCancel func(*operation) error, onConnect func(*operation, *http.Request, http.ResponseWriter) error) (*operation, error) { // Main attributes op := operation{} op.id = uuid.NewRandom().String() op.class = opClass op.createdAt = time.Now() op.updatedAt = op.createdAt op.status = shared.Pending op.url = fmt.Sprintf("/%s/operations/%s", shared.APIVersion, op.id) op.resources = opResources op.chanDone = make(chan error) newMetadata, err := shared.ParseMetadata(opMetadata) if err != nil { return nil, err } op.metadata = newMetadata // Callback functions op.onRun = onRun op.onCancel = onCancel op.onConnect = onConnect // Sanity check if op.class != operationClassWebsocket && op.onConnect != nil { return nil, fmt.Errorf("Only websocket operations can have a Connect hook") } if op.class == operationClassWebsocket && op.onConnect == nil { return nil, fmt.Errorf("Websocket operations must have a Connect hook") } if op.class == operationClassToken && op.onRun != nil { return nil, fmt.Errorf("Token operations can't have a Run hook") } if op.class == operationClassToken && op.onCancel != nil { return nil, fmt.Errorf("Token operations can't have a Cancel hook") } operationsLock.Lock() operations[op.id] = &op operationsLock.Unlock() shared.Debugf("New %s operation: %s", op.class.String(), op.id) _, md, _ := op.Render() eventSend("operation", md) return &op, nil } func operationGet(id string) (*operation, error) { operationsLock.Lock() op, ok := operations[id] operationsLock.Unlock() if !ok { return nil, fmt.Errorf("Operation '%s' doesn't exist", id) } return op, nil } // API functions func operationAPIGet(d *Daemon, r *http.Request) Response { id := mux.Vars(r)["id"] op, err := operationGet(id) if err != nil { return NotFound } _, body, err := op.Render() if err != nil { return InternalError(err) } return SyncResponse(true, body) } func operationAPIDelete(d *Daemon, r *http.Request) Response { id := mux.Vars(r)["id"] op, err := operationGet(id) if err != nil { return NotFound } _, err = op.Cancel() if err != nil { return BadRequest(err) } return EmptySyncResponse } var operationCmd = Command{name: "operations/{id}", get: operationAPIGet, delete: operationAPIDelete} func operationsAPIGet(d *Daemon, r *http.Request) Response { var md shared.Jmap recursion := d.isRecursionRequest(r) md = shared.Jmap{} operationsLock.Lock() ops := operations operationsLock.Unlock() for _, v := range ops { status := strings.ToLower(v.status.String()) _, ok := md[status] if !ok { if recursion { md[status] = make([]*shared.Operation, 0) } else { md[status] = make([]string, 0) } } if !recursion { md[status] = append(md[status].([]string), v.url) continue } _, body, err := v.Render() if err != nil { continue } md[status] = append(md[status].([]*shared.Operation), body) } return SyncResponse(true, md) } var operationsCmd = Command{name: "operations", get: operationsAPIGet} func operationAPIWaitGet(d *Daemon, r *http.Request) Response { timeout, err := shared.AtoiEmptyDefault(r.FormValue("timeout"), -1) if err != nil { return InternalError(err) } id := mux.Vars(r)["id"] op, err := operationGet(id) if err != nil { return NotFound } _, err = op.WaitFinal(timeout) if err != nil { return InternalError(err) } _, body, err := op.Render() if err != nil { return InternalError(err) } return SyncResponse(true, body) } var operationWait = Command{name: "operations/{id}/wait", get: operationAPIWaitGet} type operationWebSocket struct { req *http.Request op *operation } func (r *operationWebSocket) Render(w http.ResponseWriter) error { chanErr, err := r.op.Connect(r.req, w) if err != nil { return err } err = <-chanErr return err } func operationAPIWebsocketGet(d *Daemon, r *http.Request) Response { id := mux.Vars(r)["id"] op, err := operationGet(id) if err != nil { return NotFound } return &operationWebSocket{r, op} } var operationWebsocket = Command{name: "operations/{id}/websocket", untrustedGet: true, get: operationAPIWebsocketGet} lxd-2.0.0/lxd/profiles.go000066400000000000000000000136251270277227600152640ustar00rootroot00000000000000package main import ( "encoding/json" "fmt" "net/http" "reflect" "github.com/gorilla/mux" _ "github.com/mattn/go-sqlite3" "github.com/lxc/lxd/shared" log "gopkg.in/inconshreveable/log15.v2" ) /* This is used for both profiles post and profile put */ type profilesPostReq struct { Name string `json:"name"` Config map[string]string `json:"config"` Description string `json:"description"` Devices shared.Devices `json:"devices"` } func profilesGet(d *Daemon, r *http.Request) Response { results, err := dbProfiles(d.db) if err != nil { return SmartError(err) } recursion := d.isRecursionRequest(r) resultString := make([]string, len(results)) resultMap := make([]*shared.ProfileConfig, len(results)) i := 0 for _, name := range results { if !recursion { url := fmt.Sprintf("/%s/profiles/%s", shared.APIVersion, name) resultString[i] = url } else { profile, err := doProfileGet(d, name) if err != nil { shared.Log.Error("Failed to get profile", log.Ctx{"profile": name}) continue } resultMap[i] = profile } i++ } if !recursion { return SyncResponse(true, resultString) } return SyncResponse(true, resultMap) } func profilesPost(d *Daemon, r *http.Request) Response { req := profilesPostReq{} if err := json.NewDecoder(r.Body).Decode(&req); err != nil { return BadRequest(err) } // Sanity checks if req.Name == "" { return BadRequest(fmt.Errorf("No name provided")) } err := containerValidConfig(req.Config, true, false) if err != nil { return BadRequest(err) } err = containerValidDevices(req.Devices, true, false) if err != nil { return BadRequest(err) } // Update DB entry _, err = dbProfileCreate(d.db, req.Name, req.Description, req.Config, req.Devices) if err != nil { return InternalError( fmt.Errorf("Error inserting %s into database: %s", req.Name, err)) } return EmptySyncResponse } var profilesCmd = Command{ name: "profiles", get: profilesGet, post: profilesPost} func doProfileGet(d *Daemon, name string) (*shared.ProfileConfig, error) { _, profile, err := dbProfileGet(d.db, name) return profile, err } func profileGet(d *Daemon, r *http.Request) Response { name := mux.Vars(r)["name"] resp, err := doProfileGet(d, name) if err != nil { return SmartError(err) } return SyncResponse(true, resp) } func getRunningContainersWithProfile(d *Daemon, profile string) []container { results := []container{} output, err := dbProfileContainersGet(d.db, profile) if err != nil { return results } for _, name := range output { c, err := containerLoadByName(d, name) if err != nil { shared.Log.Error("Failed opening container", log.Ctx{"container": name}) continue } results = append(results, c) } return results } func profilePut(d *Daemon, r *http.Request) Response { name := mux.Vars(r)["name"] req := profilesPostReq{} if err := json.NewDecoder(r.Body).Decode(&req); err != nil { return BadRequest(err) } // Sanity checks err := containerValidConfig(req.Config, true, false) if err != nil { return BadRequest(err) } err = containerValidDevices(req.Devices, true, false) if err != nil { return BadRequest(err) } // Get the running container list clist := getRunningContainersWithProfile(d, name) var containers []container for _, c := range clist { if !c.IsRunning() { continue } containers = append(containers, c) } // Update the database id, profile, err := dbProfileGet(d.db, name) if err != nil { return InternalError(fmt.Errorf("Failed to retrieve profile='%s'", name)) } tx, err := dbBegin(d.db) if err != nil { return InternalError(err) } if profile.Description != req.Description { err = dbProfileDescriptionUpdate(tx, id, req.Description) if err != nil { tx.Rollback() return InternalError(err) } } // Optimize for description-only changes if reflect.DeepEqual(profile.Config, req.Config) && reflect.DeepEqual(profile.Devices, req.Devices) { err = txCommit(tx) if err != nil { return InternalError(err) } return EmptySyncResponse } err = dbProfileConfigClear(tx, id) if err != nil { tx.Rollback() return InternalError(err) } err = dbProfileConfigAdd(tx, id, req.Config) if err != nil { tx.Rollback() return SmartError(err) } err = dbDevicesAdd(tx, "profile", id, req.Devices) if err != nil { tx.Rollback() return SmartError(err) } err = txCommit(tx) if err != nil { return InternalError(err) } // Update all the containers using the profile. Must be done after txCommit due to DB lock. failures := map[string]error{} for _, c := range containers { err = c.Update(containerArgs{ Architecture: c.Architecture(), Ephemeral: c.IsEphemeral(), Config: c.LocalConfig(), Devices: c.LocalDevices(), Profiles: c.Profiles()}, true) if err != nil { failures[c.Name()] = err } } if len(failures) != 0 { msg := "The following containers failed to update (profile change still saved):\n" for cname, err := range failures { msg += fmt.Sprintf(" - %s: %s\n", cname, err) } return InternalError(fmt.Errorf("%s", msg)) } return EmptySyncResponse } // The handler for the post operation. func profilePost(d *Daemon, r *http.Request) Response { name := mux.Vars(r)["name"] req := profilesPostReq{} if err := json.NewDecoder(r.Body).Decode(&req); err != nil { return BadRequest(err) } // Sanity checks if req.Name == "" { return BadRequest(fmt.Errorf("No name provided")) } err := dbProfileUpdate(d.db, name, req.Name) if err != nil { return InternalError(err) } return EmptySyncResponse } // The handler for the delete operation. func profileDelete(d *Daemon, r *http.Request) Response { name := mux.Vars(r)["name"] err := dbProfileDelete(d.db, name) if err != nil { return InternalError(err) } return EmptySyncResponse } var profileCmd = Command{name: "profiles/{name}", get: profileGet, put: profilePut, delete: profileDelete, post: profilePost} lxd-2.0.0/lxd/profiles_test.go000066400000000000000000000032101270277227600163100ustar00rootroot00000000000000package main import ( "database/sql" "testing" ) func Test_removing_a_profile_deletes_associated_configuration_entries(t *testing.T) { var db *sql.DB var err error d := &Daemon{} err = initializeDbObject(d, ":memory:") db = d.db // Insert a container and a related profile. Dont't forget that the profile // we insert is profile ID 2 (there is a default profile already). statements := ` INSERT INTO containers (name, architecture, type) VALUES ('thename', 1, 1); INSERT INTO profiles (name) VALUES ('theprofile'); INSERT INTO containers_profiles (container_id, profile_id) VALUES (1, 2); INSERT INTO profiles_devices (name, profile_id) VALUES ('somename', 2); INSERT INTO profiles_config (key, value, profile_id) VALUES ('thekey', 'thevalue', 2); INSERT INTO profiles_devices_config (profile_device_id, key, value) VALUES (1, 'something', 'boring');` _, err = db.Exec(statements) if err != nil { t.Fatal(err) } // Delete the profile we just created with dbProfileDelete err = dbProfileDelete(db, "theprofile") if err != nil { t.Fatal(err) } // Make sure there are 0 profiles_devices entries left. devices, err := dbDevices(d.db, "theprofile", true) if err != nil { t.Fatal(err) } if len(devices) != 0 { t.Errorf("Deleting a profile didn't delete the related profiles_devices! There are %d left", len(devices)) } // Make sure there are 0 profiles_config entries left. config, err := dbProfileConfig(d.db, "theprofile") if err == nil { t.Fatal("found the profile!") } if len(config) != 0 { t.Errorf("Deleting a profile didn't delete the related profiles_config! There are %d left", len(config)) } } lxd-2.0.0/lxd/remote.go000066400000000000000000000010341270277227600147230ustar00rootroot00000000000000package main import ( "encoding/json" "fmt" "github.com/lxc/lxd/shared" ) func remoteGetImageFingerprint(d *Daemon, server string, certificate string, alias string) (string, error) { url := fmt.Sprintf( "%s/%s/images/aliases/%s", server, shared.APIVersion, alias) resp, err := d.httpGetSync(url, certificate) if err != nil { return "", err } var result shared.ImageAliasesEntry if err = json.Unmarshal(resp.Metadata, &result); err != nil { return "", fmt.Errorf("Error reading alias") } return result.Target, nil } lxd-2.0.0/lxd/response.go000066400000000000000000000124551270277227600152770ustar00rootroot00000000000000package main import ( "bytes" "database/sql" "encoding/json" "fmt" "io" "mime/multipart" "net/http" "os" "github.com/mattn/go-sqlite3" "github.com/lxc/lxd" "github.com/lxc/lxd/shared" ) type syncResp struct { Type lxd.ResponseType `json:"type"` Status string `json:"status"` StatusCode shared.StatusCode `json:"status_code"` Metadata interface{} `json:"metadata"` } type asyncResp struct { Type lxd.ResponseType `json:"type"` Status string `json:"status"` StatusCode shared.StatusCode `json:"status_code"` Metadata interface{} `json:"metadata"` Operation string `json:"operation"` } type Response interface { Render(w http.ResponseWriter) error } // Sync response type syncResponse struct { success bool metadata interface{} } func (r *syncResponse) Render(w http.ResponseWriter) error { status := shared.Success if !r.success { status = shared.Failure } resp := syncResp{Type: lxd.Sync, Status: status.String(), StatusCode: status, Metadata: r.metadata} return WriteJSON(w, resp) } func SyncResponse(success bool, metadata interface{}) Response { return &syncResponse{success, metadata} } var EmptySyncResponse = &syncResponse{true, make(map[string]interface{})} // File transfer response type fileResponseEntry struct { identifier string path string filename string } type fileResponse struct { req *http.Request files []fileResponseEntry headers map[string]string removeAfterServe bool } func (r *fileResponse) Render(w http.ResponseWriter) error { if r.headers != nil { for k, v := range r.headers { w.Header().Set(k, v) } } // No file, well, it's easy then if len(r.files) == 0 { return nil } // For a single file, return it inline if len(r.files) == 1 { f, err := os.Open(r.files[0].path) if err != nil { return err } defer f.Close() fi, err := f.Stat() if err != nil { return err } w.Header().Set("Content-Type", "application/octet-stream") w.Header().Set("Content-Length", fmt.Sprintf("%d", fi.Size())) w.Header().Set("Content-Disposition", fmt.Sprintf("inline;filename=%s", r.files[0].filename)) http.ServeContent(w, r.req, r.files[0].filename, fi.ModTime(), f) if r.removeAfterServe { err = os.Remove(r.files[0].path) if err != nil { return err } } return nil } // Now the complex multipart answer body := &bytes.Buffer{} mw := multipart.NewWriter(body) for _, entry := range r.files { fd, err := os.Open(entry.path) if err != nil { return err } defer fd.Close() fw, err := mw.CreateFormFile(entry.identifier, entry.filename) if err != nil { return err } _, err = io.Copy(fw, fd) if err != nil { return err } } mw.Close() w.Header().Set("Content-Type", mw.FormDataContentType()) w.Header().Set("Content-Length", fmt.Sprintf("%d", body.Len())) _, err := io.Copy(w, body) return err } func FileResponse(r *http.Request, files []fileResponseEntry, headers map[string]string, removeAfterServe bool) Response { return &fileResponse{r, files, headers, removeAfterServe} } // Operation response type operationResponse struct { op *operation } func (r *operationResponse) Render(w http.ResponseWriter) error { _, err := r.op.Run() if err != nil { return err } url, md, err := r.op.Render() if err != nil { return err } body := asyncResp{ Type: lxd.Async, Status: shared.OperationCreated.String(), StatusCode: shared.OperationCreated, Operation: url, Metadata: md} w.Header().Set("Location", url) w.WriteHeader(202) return WriteJSON(w, body) } func OperationResponse(op *operation) Response { return &operationResponse{op} } // Error response type errorResponse struct { code int msg string } func (r *errorResponse) Render(w http.ResponseWriter) error { var output io.Writer buf := &bytes.Buffer{} output = buf var captured *bytes.Buffer if debug { captured = &bytes.Buffer{} output = io.MultiWriter(buf, captured) } err := json.NewEncoder(output).Encode(shared.Jmap{"type": lxd.Error, "error": r.msg, "error_code": r.code}) if err != nil { return err } if debug { shared.DebugJson(captured) } w.Header().Set("Content-Type", "application/json") w.Header().Set("X-Content-Type-Options", "nosniff") w.WriteHeader(r.code) fmt.Fprintln(w, buf.String()) return nil } /* Some standard responses */ var NotImplemented = &errorResponse{http.StatusNotImplemented, "not implemented"} var NotFound = &errorResponse{http.StatusNotFound, "not found"} var Forbidden = &errorResponse{http.StatusForbidden, "not authorized"} var Conflict = &errorResponse{http.StatusConflict, "already exists"} func BadRequest(err error) Response { return &errorResponse{http.StatusBadRequest, err.Error()} } func InternalError(err error) Response { return &errorResponse{http.StatusInternalServerError, err.Error()} } /* * SmartError returns the right error message based on err. */ func SmartError(err error) Response { switch err { case nil: return EmptySyncResponse case os.ErrNotExist: return NotFound case sql.ErrNoRows: return NotFound case NoSuchObjectError: return NotFound case os.ErrPermission: return Forbidden case DbErrAlreadyDefined: return Conflict case sqlite3.ErrConstraintUnique: return Conflict default: return InternalError(err) } } lxd-2.0.0/lxd/rsync.go000066400000000000000000000100171270277227600145670ustar00rootroot00000000000000package main import ( "fmt" "io" "io/ioutil" "net" "os" "os/exec" "github.com/gorilla/websocket" "github.com/lxc/lxd/shared" ) func rsyncWebsocket(path string, cmd *exec.Cmd, conn *websocket.Conn) error { stdin, err := cmd.StdinPipe() if err != nil { return err } stdout, err := cmd.StdoutPipe() if err != nil { return err } stderr, err := cmd.StderrPipe() if err != nil { return err } if err := cmd.Start(); err != nil { return err } readDone, writeDone := shared.WebsocketMirror(conn, stdin, stdout) data, err2 := ioutil.ReadAll(stderr) if err2 != nil { shared.Debugf("error reading rsync stderr: %s", err2) return err2 } err = cmd.Wait() if err != nil { shared.Debugf("rsync recv error for path %s: %s: %s", path, err, string(data)) } <-readDone <-writeDone return err } func rsyncSendSetup(path string) (*exec.Cmd, net.Conn, io.ReadCloser, error) { /* * It's sort of unfortunate, but there's no library call to get a * temporary name, so we get the file and close it and use its name. */ f, err := ioutil.TempFile("", "lxd_rsync_") if err != nil { return nil, nil, nil, err } f.Close() os.Remove(f.Name()) /* * The way rsync works, it invokes a subprocess that does the actual * talking (given to it by a -E argument). Since there isn't an easy * way for us to capture this process' stdin/stdout, we just use netcat * and write to/from a unix socket. * * In principle we don't need this socket. It seems to me that some * clever invocation of rsync --server --sender and usage of that * process' stdin/stdout could work around the need for this socket, * but I couldn't get it to work. Another option would be to look at * the spawned process' first child and read/write from its * stdin/stdout, but that also seemed messy. In any case, this seems to * work just fine. */ l, err := net.Listen("unix", f.Name()) if err != nil { return nil, nil, nil, err } /* * Here, the path /tmp/foo is ignored. Since we specify localhost, * rsync thinks we are syncing to a remote host (in this case, the * other end of the lxd websocket), and so the path specified on the * --server instance of rsync takes precedence. * * Additionally, we use sh -c instead of just calling nc directly * because rsync passes a whole bunch of arguments to the wrapper * command (i.e. the command to run on --server). However, we're * hardcoding that at the other end, so we can just ignore it. */ rsyncCmd := fmt.Sprintf("sh -c \"nc -U %s\"", f.Name()) cmd := exec.Command( "rsync", "-arvP", "--devices", "--numeric-ids", "--partial", path, "localhost:/tmp/foo", "-e", rsyncCmd) stderr, err := cmd.StderrPipe() if err != nil { return nil, nil, nil, err } if err := cmd.Start(); err != nil { return nil, nil, nil, err } conn, err := l.Accept() if err != nil { return nil, nil, nil, err } l.Close() return cmd, conn, stderr, nil } // RsyncSend sets up the sending half of an rsync, to recursively send the // directory pointed to by path over the websocket. func RsyncSend(path string, conn *websocket.Conn) error { cmd, dataSocket, stderr, err := rsyncSendSetup(path) if dataSocket != nil { defer dataSocket.Close() } if err != nil { return err } readDone, writeDone := shared.WebsocketMirror(conn, dataSocket, dataSocket) output, err := ioutil.ReadAll(stderr) if err != nil { shared.Debugf("problem reading rsync stderr %s", err) } if err := cmd.Wait(); err != nil { shared.Debugf("problem with rsync send of %s: %s: %s", path, err, string(output)) } <-readDone <-writeDone return err } func rsyncRecvCmd(path string) *exec.Cmd { return exec.Command("rsync", "--server", "-vlogDtpre.iLsfx", "--numeric-ids", "--devices", "--partial", ".", path) } // RsyncRecv sets up the receiving half of the websocket to rsync (the other // half set up by RsyncSend), putting the contents in the directory specified // by path. func RsyncRecv(path string, conn *websocket.Conn) error { return rsyncWebsocket(path, rsyncRecvCmd(path), conn) } lxd-2.0.0/lxd/rsync_test.go000066400000000000000000000033041270277227600156270ustar00rootroot00000000000000package main import ( "io" "io/ioutil" "os" "path" "testing" "github.com/lxc/lxd/shared" ) const helloWorld = "hello world\n" func TestRsyncSendRecv(t *testing.T) { source, err := ioutil.TempDir("", "lxd_test_source_") if err != nil { t.Error(err) return } defer os.RemoveAll(source) sink, err := ioutil.TempDir("", "lxd_test_sink_") if err != nil { t.Error(err) return } defer os.RemoveAll(sink) /* now, write something to rsync over */ f, err := os.Create(path.Join(source, "foo")) if err != nil { t.Error(err) return } f.Write([]byte(helloWorld)) f.Close() send, sendConn, _, err := rsyncSendSetup(shared.AddSlash(source)) if err != nil { t.Error(err) return } recv := rsyncRecvCmd(sink) recvOut, err := recv.StdoutPipe() if err != nil { t.Error(err) return } recvIn, err := recv.StdinPipe() if err != nil { t.Error(err) return } if err := recv.Start(); err != nil { t.Error(err) return } go func() { defer sendConn.Close() if _, err := io.Copy(sendConn, recvOut); err != nil { t.Error(err) } if err := recv.Wait(); err != nil { t.Error(err) } }() /* * We close the socket in the above gofunc, but go tells us * https://github.com/golang/go/issues/4373 that this is an error * because we were reading from a socket that was closed. Thus, we * ignore it */ io.Copy(recvIn, sendConn) if err := send.Wait(); err != nil { t.Error(err) return } f, err = os.Open(path.Join(sink, "foo")) if err != nil { t.Error(err) return } defer f.Close() buf, err := ioutil.ReadAll(f) if err != nil { t.Error(err) return } if string(buf) != helloWorld { t.Errorf("expected %s got %s", helloWorld, buf) return } } lxd-2.0.0/lxd/seccomp.go000066400000000000000000000024571270277227600150730ustar00rootroot00000000000000package main import ( "io/ioutil" "os" "path" "github.com/lxc/lxd/shared" ) const DEFAULT_SECCOMP_POLICY = ` 2 blacklist reject_force_umount # comment this to allow umount -f; not recommended [all] kexec_load errno 1 open_by_handle_at errno 1 init_module errno 1 finit_module errno 1 delete_module errno 1 ` var seccompPath = shared.VarPath("security", "seccomp") func SeccompProfilePath(c container) string { return path.Join(seccompPath, c.Name()) } func getSeccompProfileContent(c container) string { /* for now there are no seccomp knobs. */ return DEFAULT_SECCOMP_POLICY } func SeccompCreateProfile(c container) error { /* Unlike apparmor, there is no way to "cache" profiles, and profiles * are automatically unloaded when a task dies. Thus, we don't need to * unload them when a container stops, and we don't have to worry about * the mtime on the file for any compiler purpose, so let's just write * out the profile. */ profile := getSeccompProfileContent(c) if err := os.MkdirAll(seccompPath, 0700); err != nil { return err } return ioutil.WriteFile(SeccompProfilePath(c), []byte(profile), 0600) } func SeccompDeleteProfile(c container) { /* similar to AppArmor, if we've never started this container, the * delete can fail and that's ok. */ os.Remove(SeccompProfilePath(c)) } lxd-2.0.0/lxd/storage.go000066400000000000000000000444411270277227600151050ustar00rootroot00000000000000package main import ( "encoding/json" "fmt" "os" "os/exec" "path/filepath" "reflect" "syscall" "time" "github.com/gorilla/websocket" "github.com/lxc/lxd/shared" "github.com/lxc/lxd/shared/logging" log "gopkg.in/inconshreveable/log15.v2" ) /* Some interesting filesystems */ const ( filesystemSuperMagicTmpfs = 0x01021994 filesystemSuperMagicExt4 = 0xEF53 filesystemSuperMagicXfs = 0x58465342 filesystemSuperMagicNfs = 0x6969 filesystemSuperMagicZfs = 0x2fc12fc1 ) /* * filesystemDetect returns the filesystem on which * the passed-in path sits */ func filesystemDetect(path string) (string, error) { fs := syscall.Statfs_t{} err := syscall.Statfs(path, &fs) if err != nil { return "", err } switch fs.Type { case filesystemSuperMagicBtrfs: return "btrfs", nil case filesystemSuperMagicZfs: return "zfs", nil case filesystemSuperMagicTmpfs: return "tmpfs", nil case filesystemSuperMagicExt4: return "ext4", nil case filesystemSuperMagicXfs: return "xfs", nil case filesystemSuperMagicNfs: return "nfs", nil default: shared.Debugf("Unknown backing filesystem type: 0x%x", fs.Type) return string(fs.Type), nil } } // storageRsyncCopy copies a directory using rsync (with the --devices option). func storageRsyncCopy(source string, dest string) (string, error) { if err := os.MkdirAll(dest, 0755); err != nil { return "", err } rsyncVerbosity := "-q" if debug { rsyncVerbosity = "-vi" } output, err := exec.Command( "rsync", "-a", "-HAX", "--devices", "--delete", "--checksum", "--numeric-ids", rsyncVerbosity, shared.AddSlash(source), dest).CombinedOutput() return string(output), err } // storageType defines the type of a storage type storageType int const ( storageTypeBtrfs storageType = iota storageTypeZfs storageTypeLvm storageTypeDir storageTypeMock ) func storageTypeToString(sType storageType) string { switch sType { case storageTypeBtrfs: return "btrfs" case storageTypeZfs: return "zfs" case storageTypeLvm: return "lvm" case storageTypeMock: return "mock" } return "dir" } type MigrationStorageSourceDriver interface { /* snapshots for this container, if any */ Snapshots() []container /* send any bits of the container/snapshots that are possible while the * container is still running. */ SendWhileRunning(conn *websocket.Conn) error /* send the final bits (e.g. a final delta snapshot for zfs, btrfs, or * do a final rsync) of the fs after the container has been * checkpointed. This will only be called when a container is actually * being live migrated. */ SendAfterCheckpoint(conn *websocket.Conn) error /* Called after either success or failure of a migration, can be used * to clean up any temporary snapshots, etc. */ Cleanup() } type storage interface { Init(config map[string]interface{}) (storage, error) GetStorageType() storageType GetStorageTypeName() string GetStorageTypeVersion() string // ContainerCreate creates an empty container (no rootfs/metadata.yaml) ContainerCreate(container container) error // ContainerCreateFromImage creates a container from a image. ContainerCreateFromImage(container container, imageFingerprint string) error ContainerCanRestore(container container, sourceContainer container) error ContainerDelete(container container) error ContainerCopy(container container, sourceContainer container) error ContainerStart(container container) error ContainerStop(container container) error ContainerRename(container container, newName string) error ContainerRestore(container container, sourceContainer container) error ContainerSetQuota(container container, size int64) error ContainerGetUsage(container container) (int64, error) ContainerSnapshotCreate( snapshotContainer container, sourceContainer container) error ContainerSnapshotDelete(snapshotContainer container) error ContainerSnapshotRename(snapshotContainer container, newName string) error ContainerSnapshotStart(container container) error ContainerSnapshotStop(container container) error /* for use in migrating snapshots */ ContainerSnapshotCreateEmpty(snapshotContainer container) error ImageCreate(fingerprint string) error ImageDelete(fingerprint string) error MigrationType() MigrationFSType // Get the pieces required to migrate the source. This contains a list // of the "object" (i.e. container or snapshot, depending on whether or // not it is a snapshot name) to be migrated in order, and a channel // for arguments of the specific migration command. We use a channel // here so we don't have to invoke `zfs send` or `rsync` or whatever // and keep its stdin/stdout open for each snapshot during the course // of migration, we can do it lazily. // // N.B. that the order here important: e.g. in btrfs/zfs, snapshots // which are parents of other snapshots should be sent first, to save // as much transfer as possible. However, the base container is always // sent as the first object, since that is the grandparent of every // snapshot. // // We leave sending containers which are snapshots of other containers // already present on the target instance as an exercise for the // enterprising developer. MigrationSource(container container) (MigrationStorageSourceDriver, error) MigrationSink(live bool, container container, objects []container, conn *websocket.Conn) error } func newStorage(d *Daemon, sType storageType) (storage, error) { var nilmap map[string]interface{} return newStorageWithConfig(d, sType, nilmap) } func newStorageWithConfig(d *Daemon, sType storageType, config map[string]interface{}) (storage, error) { if d.MockMode { return d.Storage, nil } var s storage switch sType { case storageTypeBtrfs: if d.Storage != nil && d.Storage.GetStorageType() == storageTypeBtrfs { return d.Storage, nil } s = &storageLogWrapper{w: &storageBtrfs{d: d}} case storageTypeZfs: if d.Storage != nil && d.Storage.GetStorageType() == storageTypeZfs { return d.Storage, nil } s = &storageLogWrapper{w: &storageZfs{d: d}} case storageTypeLvm: if d.Storage != nil && d.Storage.GetStorageType() == storageTypeLvm { return d.Storage, nil } s = &storageLogWrapper{w: &storageLvm{d: d}} default: if d.Storage != nil && d.Storage.GetStorageType() == storageTypeDir { return d.Storage, nil } s = &storageLogWrapper{w: &storageDir{d: d}} } return s.Init(config) } func storageForFilename(d *Daemon, filename string) (storage, error) { config := make(map[string]interface{}) storageType := storageTypeDir if d.MockMode { return newStorageWithConfig(d, storageTypeMock, config) } filesystem, err := filesystemDetect(filename) if err != nil { return nil, fmt.Errorf("couldn't detect filesystem for '%s': %v", filename, err) } if shared.PathExists(filename + ".lv") { storageType = storageTypeLvm lvPath, err := os.Readlink(filename + ".lv") if err != nil { return nil, fmt.Errorf("couldn't read link dest for '%s': %v", filename+".lv", err) } vgname := filepath.Base(filepath.Dir(lvPath)) config["vgName"] = vgname } else if shared.PathExists(filename + ".zfs") { storageType = storageTypeZfs } else if shared.PathExists(filename+".btrfs") || filesystem == "btrfs" { storageType = storageTypeBtrfs } return newStorageWithConfig(d, storageType, config) } func storageForImage(d *Daemon, imgInfo *shared.ImageInfo) (storage, error) { imageFilename := shared.VarPath("images", imgInfo.Fingerprint) return storageForFilename(d, imageFilename) } type storageShared struct { sType storageType sTypeName string sTypeVersion string log shared.Logger } func (ss *storageShared) initShared() error { ss.log = logging.AddContext( shared.Log, log.Ctx{"driver": fmt.Sprintf("storage/%s", ss.sTypeName)}, ) return nil } func (ss *storageShared) GetStorageType() storageType { return ss.sType } func (ss *storageShared) GetStorageTypeName() string { return ss.sTypeName } func (ss *storageShared) GetStorageTypeVersion() string { return ss.sTypeVersion } func (ss *storageShared) shiftRootfs(c container) error { dpath := c.Path() rpath := c.RootfsPath() shared.Log.Debug("Shifting root filesystem", log.Ctx{"container": c.Name(), "rootfs": rpath}) idmapset := c.IdmapSet() if idmapset == nil { return fmt.Errorf("IdmapSet of container '%s' is nil", c.Name()) } err := idmapset.ShiftRootfs(rpath) if err != nil { shared.Debugf("Shift of rootfs %s failed: %s", rpath, err) return err } /* Set an acl so the container root can descend the container dir */ // TODO: i changed this so it calls ss.setUnprivUserAcl, which does // the acl change only if the container is not privileged, think thats right. return ss.setUnprivUserAcl(c, dpath) } func (ss *storageShared) setUnprivUserAcl(c container, destPath string) error { idmapset := c.IdmapSet() // Skip for privileged containers if idmapset == nil { return nil } // Make sure the map is valid. Skip if container uid 0 == host uid 0 uid, _ := idmapset.ShiftIntoNs(0, 0) switch uid { case -1: return fmt.Errorf("Container doesn't have a uid 0 in its map") case 0: return nil } // Attempt to set a POSIX ACL first. Fallback to chmod if the fs doesn't support it. acl := fmt.Sprintf("%d:rx", uid) _, err := exec.Command("setfacl", "-m", acl, destPath).CombinedOutput() if err != nil { _, err := exec.Command("chmod", "+x", destPath).CombinedOutput() if err != nil { return fmt.Errorf("Failed to chmod the container path.") } } return nil } type storageLogWrapper struct { w storage log shared.Logger } func (lw *storageLogWrapper) Init(config map[string]interface{}) (storage, error) { _, err := lw.w.Init(config) lw.log = logging.AddContext( shared.Log, log.Ctx{"driver": fmt.Sprintf("storage/%s", lw.w.GetStorageTypeName())}, ) lw.log.Info("Init") return lw, err } func (lw *storageLogWrapper) GetStorageType() storageType { return lw.w.GetStorageType() } func (lw *storageLogWrapper) GetStorageTypeName() string { return lw.w.GetStorageTypeName() } func (lw *storageLogWrapper) GetStorageTypeVersion() string { return lw.w.GetStorageTypeVersion() } func (lw *storageLogWrapper) ContainerCreate(container container) error { lw.log.Debug( "ContainerCreate", log.Ctx{ "name": container.Name(), "isPrivileged": container.IsPrivileged()}) return lw.w.ContainerCreate(container) } func (lw *storageLogWrapper) ContainerCreateFromImage( container container, imageFingerprint string) error { lw.log.Debug( "ContainerCreateFromImage", log.Ctx{ "imageFingerprint": imageFingerprint, "name": container.Name(), "isPrivileged": container.IsPrivileged()}) return lw.w.ContainerCreateFromImage(container, imageFingerprint) } func (lw *storageLogWrapper) ContainerCanRestore(container container, sourceContainer container) error { lw.log.Debug("ContainerCanRestore", log.Ctx{"container": container.Name()}) return lw.w.ContainerCanRestore(container, sourceContainer) } func (lw *storageLogWrapper) ContainerDelete(container container) error { lw.log.Debug("ContainerDelete", log.Ctx{"container": container.Name()}) return lw.w.ContainerDelete(container) } func (lw *storageLogWrapper) ContainerCopy( container container, sourceContainer container) error { lw.log.Debug( "ContainerCopy", log.Ctx{ "container": container.Name(), "source": sourceContainer.Name()}) return lw.w.ContainerCopy(container, sourceContainer) } func (lw *storageLogWrapper) ContainerStart(container container) error { lw.log.Debug("ContainerStart", log.Ctx{"container": container.Name()}) return lw.w.ContainerStart(container) } func (lw *storageLogWrapper) ContainerStop(container container) error { lw.log.Debug("ContainerStop", log.Ctx{"container": container.Name()}) return lw.w.ContainerStop(container) } func (lw *storageLogWrapper) ContainerRename( container container, newName string) error { lw.log.Debug( "ContainerRename", log.Ctx{ "container": container.Name(), "newName": newName}) return lw.w.ContainerRename(container, newName) } func (lw *storageLogWrapper) ContainerRestore( container container, sourceContainer container) error { lw.log.Debug( "ContainerRestore", log.Ctx{ "container": container.Name(), "source": sourceContainer.Name()}) return lw.w.ContainerRestore(container, sourceContainer) } func (lw *storageLogWrapper) ContainerSetQuota( container container, size int64) error { lw.log.Debug( "ContainerSetQuota", log.Ctx{ "container": container.Name(), "size": size}) return lw.w.ContainerSetQuota(container, size) } func (lw *storageLogWrapper) ContainerGetUsage( container container) (int64, error) { lw.log.Debug( "ContainerGetUsage", log.Ctx{ "container": container.Name()}) return lw.w.ContainerGetUsage(container) } func (lw *storageLogWrapper) ContainerSnapshotCreate( snapshotContainer container, sourceContainer container) error { lw.log.Debug("ContainerSnapshotCreate", log.Ctx{ "snapshotContainer": snapshotContainer.Name(), "sourceContainer": sourceContainer.Name()}) return lw.w.ContainerSnapshotCreate(snapshotContainer, sourceContainer) } func (lw *storageLogWrapper) ContainerSnapshotCreateEmpty(snapshotContainer container) error { lw.log.Debug("ContainerSnapshotCreateEmpty", log.Ctx{ "snapshotContainer": snapshotContainer.Name()}) return lw.w.ContainerSnapshotCreateEmpty(snapshotContainer) } func (lw *storageLogWrapper) ContainerSnapshotDelete( snapshotContainer container) error { lw.log.Debug("ContainerSnapshotDelete", log.Ctx{"snapshotContainer": snapshotContainer.Name()}) return lw.w.ContainerSnapshotDelete(snapshotContainer) } func (lw *storageLogWrapper) ContainerSnapshotRename( snapshotContainer container, newName string) error { lw.log.Debug("ContainerSnapshotRename", log.Ctx{ "snapshotContainer": snapshotContainer.Name(), "newName": newName}) return lw.w.ContainerSnapshotRename(snapshotContainer, newName) } func (lw *storageLogWrapper) ContainerSnapshotStart(container container) error { lw.log.Debug("ContainerSnapshotStart", log.Ctx{"container": container.Name()}) return lw.w.ContainerSnapshotStart(container) } func (lw *storageLogWrapper) ContainerSnapshotStop(container container) error { lw.log.Debug("ContainerSnapshotStop", log.Ctx{"container": container.Name()}) return lw.w.ContainerSnapshotStop(container) } func (lw *storageLogWrapper) ImageCreate(fingerprint string) error { lw.log.Debug( "ImageCreate", log.Ctx{"fingerprint": fingerprint}) return lw.w.ImageCreate(fingerprint) } func (lw *storageLogWrapper) ImageDelete(fingerprint string) error { lw.log.Debug("ImageDelete", log.Ctx{"fingerprint": fingerprint}) return lw.w.ImageDelete(fingerprint) } func (lw *storageLogWrapper) MigrationType() MigrationFSType { return lw.w.MigrationType() } func (lw *storageLogWrapper) MigrationSource(container container) (MigrationStorageSourceDriver, error) { lw.log.Debug("MigrationSource", log.Ctx{"container": container.Name()}) return lw.w.MigrationSource(container) } func (lw *storageLogWrapper) MigrationSink(live bool, container container, objects []container, conn *websocket.Conn) error { objNames := []string{} for _, obj := range objects { objNames = append(objNames, obj.Name()) } lw.log.Debug("MigrationSink", log.Ctx{ "live": live, "container": container.Name(), "objects": objNames, }) return lw.w.MigrationSink(live, container, objects, conn) } func ShiftIfNecessary(container container, srcIdmap *shared.IdmapSet) error { dstIdmap := container.IdmapSet() if dstIdmap == nil { dstIdmap = new(shared.IdmapSet) } if !reflect.DeepEqual(srcIdmap, dstIdmap) { var jsonIdmap string if srcIdmap != nil { idmapBytes, err := json.Marshal(srcIdmap.Idmap) if err != nil { return err } jsonIdmap = string(idmapBytes) } else { jsonIdmap = "[]" } err := container.ConfigKeySet("volatile.last_state.idmap", jsonIdmap) if err != nil { return err } } return nil } type rsyncStorageSourceDriver struct { container container snapshots []container } func (s rsyncStorageSourceDriver) Snapshots() []container { return s.snapshots } func (s rsyncStorageSourceDriver) SendWhileRunning(conn *websocket.Conn) error { toSend := append([]container{s.container}, s.snapshots...) for _, send := range toSend { path := send.Path() if err := RsyncSend(shared.AddSlash(path), conn); err != nil { return err } } return nil } func (s rsyncStorageSourceDriver) SendAfterCheckpoint(conn *websocket.Conn) error { /* resync anything that changed between our first send and the checkpoint */ return RsyncSend(shared.AddSlash(s.container.Path()), conn) } func (s rsyncStorageSourceDriver) Cleanup() { /* no-op */ } func rsyncMigrationSource(container container) (MigrationStorageSourceDriver, error) { snapshots, err := container.Snapshots() if err != nil { return nil, err } return rsyncStorageSourceDriver{container, snapshots}, nil } func rsyncMigrationSink(live bool, container container, snapshots []container, conn *websocket.Conn) error { /* the first object is the actual container */ if err := RsyncRecv(shared.AddSlash(container.Path()), conn); err != nil { return err } if len(snapshots) > 0 { err := os.MkdirAll(shared.VarPath(fmt.Sprintf("snapshots/%s", container.Name())), 0700) if err != nil { return err } } for _, snap := range snapshots { if err := RsyncRecv(shared.AddSlash(snap.Path()), conn); err != nil { return err } } if live { /* now receive the final sync */ if err := RsyncRecv(shared.AddSlash(container.Path()), conn); err != nil { return err } } return nil } // Useful functions for unreliable backends func tryExec(name string, arg ...string) ([]byte, error) { var err error var output []byte for i := 0; i < 20; i++ { output, err = exec.Command(name, arg...).CombinedOutput() if err == nil { break } time.Sleep(500 * time.Millisecond) } return output, err } func tryMount(src string, dst string, fs string, flags uintptr, options string) error { var err error for i := 0; i < 20; i++ { err = syscall.Mount(src, dst, fs, flags, options) if err == nil { break } time.Sleep(500 * time.Millisecond) } if err != nil { return err } return nil } func tryUnmount(path string, flags int) error { var err error for i := 0; i < 20; i++ { err = syscall.Unmount(path, flags) if err == nil { break } time.Sleep(500 * time.Millisecond) } if err != nil { return err } return nil } lxd-2.0.0/lxd/storage_32bit.go000066400000000000000000000003171270277227600161020ustar00rootroot00000000000000// +build 386 arm ppc s390 package main const ( /* This is really 0x9123683E, go wants us to give it in signed form * since we use it as a signed constant. */ filesystemSuperMagicBtrfs = -1859950530 ) lxd-2.0.0/lxd/storage_64bit.go000066400000000000000000000001531270277227600161050ustar00rootroot00000000000000// +build amd64 ppc64 ppc64le arm64 s390x package main const ( filesystemSuperMagicBtrfs = 0x9123683E ) lxd-2.0.0/lxd/storage_btrfs.go000066400000000000000000000562361270277227600163120ustar00rootroot00000000000000package main import ( "fmt" "io/ioutil" "os" "os/exec" "path" "path/filepath" "strconv" "strings" "syscall" "github.com/gorilla/websocket" "github.com/pborman/uuid" "github.com/lxc/lxd/shared" log "gopkg.in/inconshreveable/log15.v2" ) type storageBtrfs struct { d *Daemon storageShared } func (s *storageBtrfs) Init(config map[string]interface{}) (storage, error) { s.sType = storageTypeBtrfs s.sTypeName = storageTypeToString(s.sType) if err := s.initShared(); err != nil { return s, err } out, err := exec.LookPath("btrfs") if err != nil || len(out) == 0 { return s, fmt.Errorf("The 'btrfs' tool isn't available") } output, err := exec.Command("btrfs", "version").CombinedOutput() if err != nil { return s, fmt.Errorf("The 'btrfs' tool isn't working properly") } count, err := fmt.Sscanf(strings.SplitN(string(output), " ", 2)[1], "v%s\n", &s.sTypeVersion) if err != nil || count != 1 { return s, fmt.Errorf("The 'btrfs' tool isn't working properly") } return s, nil } func (s *storageBtrfs) ContainerCreate(container container) error { cPath := container.Path() // MkdirAll the pardir of the BTRFS Subvolume. if err := os.MkdirAll(filepath.Dir(cPath), 0755); err != nil { return err } // Create the BTRFS Subvolume err := s.subvolCreate(cPath) if err != nil { return err } if container.IsPrivileged() { if err := os.Chmod(cPath, 0700); err != nil { return err } } return container.TemplateApply("create") } func (s *storageBtrfs) ContainerCreateFromImage( container container, imageFingerprint string) error { imageSubvol := fmt.Sprintf( "%s.btrfs", shared.VarPath("images", imageFingerprint)) // Create the btrfs subvol of the image first if it doesn exists. if !shared.PathExists(imageSubvol) { if err := s.ImageCreate(imageFingerprint); err != nil { return err } } // Now make a snapshot of the image subvol err := s.subvolsSnapshot(imageSubvol, container.Path(), false) if err != nil { return err } if !container.IsPrivileged() { if err = s.shiftRootfs(container); err != nil { s.ContainerDelete(container) return err } } else { if err := os.Chmod(container.Path(), 0700); err != nil { return err } } return container.TemplateApply("create") } func (s *storageBtrfs) ContainerCanRestore(container container, sourceContainer container) error { return nil } func (s *storageBtrfs) ContainerDelete(container container) error { cPath := container.Path() // First remove the subvol (if it was one). if s.isSubvolume(cPath) { if err := s.subvolsDelete(cPath); err != nil { return err } } // Then the directory (if it still exists). err := os.RemoveAll(cPath) if err != nil { s.log.Error("ContainerDelete: failed", log.Ctx{"cPath": cPath, "err": err}) return fmt.Errorf("Error cleaning up %s: %s", cPath, err) } return nil } func (s *storageBtrfs) ContainerCopy(container container, sourceContainer container) error { subvol := sourceContainer.Path() dpath := container.Path() if s.isSubvolume(subvol) { // Snapshot the sourcecontainer err := s.subvolsSnapshot(subvol, dpath, false) if err != nil { return err } } else { // Create the BTRFS Container. if err := s.ContainerCreate(container); err != nil { return err } /* * Copy by using rsync */ output, err := storageRsyncCopy( sourceContainer.Path(), container.Path()) if err != nil { s.ContainerDelete(container) s.log.Error("ContainerCopy: rsync failed", log.Ctx{"output": string(output)}) return fmt.Errorf("rsync failed: %s", string(output)) } } if err := s.setUnprivUserAcl(sourceContainer, dpath); err != nil { s.ContainerDelete(container) return err } return container.TemplateApply("copy") } func (s *storageBtrfs) ContainerStart(container container) error { return nil } func (s *storageBtrfs) ContainerStop(container container) error { return nil } func (s *storageBtrfs) ContainerRename(container container, newName string) error { oldName := container.Name() oldPath := container.Path() newPath := containerPath(newName, false) if err := os.Rename(oldPath, newPath); err != nil { return err } if shared.PathExists(shared.VarPath(fmt.Sprintf("snapshots/%s", oldName))) { err := os.Rename(shared.VarPath(fmt.Sprintf("snapshots/%s", oldName)), shared.VarPath(fmt.Sprintf("snapshots/%s", newName))) if err != nil { return err } } return nil } func (s *storageBtrfs) ContainerRestore( container container, sourceContainer container) error { targetSubVol := container.Path() sourceSubVol := sourceContainer.Path() sourceBackupPath := container.Path() + ".back" // Create a backup of the container err := os.Rename(container.Path(), sourceBackupPath) if err != nil { return err } var failure error if s.isSubvolume(sourceSubVol) { // Restore using btrfs snapshots. err := s.subvolsSnapshot(sourceSubVol, targetSubVol, false) if err != nil { failure = err } } else { // Restore using rsync but create a btrfs subvol. if err := s.subvolCreate(targetSubVol); err == nil { output, err := storageRsyncCopy( sourceSubVol, targetSubVol) if err != nil { s.log.Error( "ContainerRestore: rsync failed", log.Ctx{"output": string(output)}) failure = err } } else { failure = err } } // Now allow unprivileged users to access its data. if err := s.setUnprivUserAcl(sourceContainer, targetSubVol); err != nil { failure = err } if failure != nil { // Restore original container s.ContainerDelete(container) os.Rename(sourceBackupPath, container.Path()) } else { // Remove the backup, we made if s.isSubvolume(sourceBackupPath) { return s.subvolDelete(sourceBackupPath) } os.RemoveAll(sourceBackupPath) } return failure } func (s *storageBtrfs) ContainerSetQuota(container container, size int64) error { subvol := container.Path() _, err := s.subvolQGroup(subvol) if err != nil { return err } output, err := exec.Command( "btrfs", "qgroup", "limit", "-e", fmt.Sprintf("%d", size), subvol).CombinedOutput() if err != nil { return fmt.Errorf("Failed to set btrfs quota: %s", output) } return nil } func (s *storageBtrfs) ContainerGetUsage(container container) (int64, error) { return s.subvolQGroupUsage(container.Path()) } func (s *storageBtrfs) ContainerSnapshotCreate( snapshotContainer container, sourceContainer container) error { subvol := sourceContainer.Path() dpath := snapshotContainer.Path() if s.isSubvolume(subvol) { // Create a readonly snapshot of the source. err := s.subvolsSnapshot(subvol, dpath, true) if err != nil { s.ContainerSnapshotDelete(snapshotContainer) return err } } else { /* * Copy by using rsync */ output, err := storageRsyncCopy( subvol, dpath) if err != nil { s.ContainerSnapshotDelete(snapshotContainer) s.log.Error( "ContainerSnapshotCreate: rsync failed", log.Ctx{"output": string(output)}) return fmt.Errorf("rsync failed: %s", string(output)) } } return nil } func (s *storageBtrfs) ContainerSnapshotDelete( snapshotContainer container) error { err := s.ContainerDelete(snapshotContainer) if err != nil { return fmt.Errorf("Error deleting snapshot %s: %s", snapshotContainer.Name(), err) } oldPathParent := filepath.Dir(snapshotContainer.Path()) if ok, _ := shared.PathIsEmpty(oldPathParent); ok { os.Remove(oldPathParent) } return nil } func (s *storageBtrfs) ContainerSnapshotStart(container container) error { if shared.PathExists(container.Path() + ".ro") { return fmt.Errorf("The snapshot is already mounted read-write.") } err := os.Rename(container.Path(), container.Path()+".ro") if err != nil { return err } err = s.subvolsSnapshot(container.Path()+".ro", container.Path(), false) if err != nil { return err } return nil } func (s *storageBtrfs) ContainerSnapshotStop(container container) error { if !shared.PathExists(container.Path() + ".ro") { return fmt.Errorf("The snapshot isn't currently mounted read-write.") } err := s.subvolsDelete(container.Path()) if err != nil { return err } err = os.Rename(container.Path()+".ro", container.Path()) if err != nil { return err } return nil } // ContainerSnapshotRename renames a snapshot of a container. func (s *storageBtrfs) ContainerSnapshotRename( snapshotContainer container, newName string) error { oldPath := snapshotContainer.Path() newPath := containerPath(newName, true) // Create the new parent. if !shared.PathExists(filepath.Dir(newPath)) { os.MkdirAll(filepath.Dir(newPath), 0700) } // Now rename the snapshot. if !s.isSubvolume(oldPath) { if err := os.Rename(oldPath, newPath); err != nil { return err } } else { if err := s.subvolsSnapshot(oldPath, newPath, true); err != nil { return err } if err := s.subvolsDelete(oldPath); err != nil { return err } } // Remove the old parent (on container rename) if its empty. if ok, _ := shared.PathIsEmpty(filepath.Dir(oldPath)); ok { os.Remove(filepath.Dir(oldPath)) } return nil } func (s *storageBtrfs) ContainerSnapshotCreateEmpty(snapshotContainer container) error { dpath := snapshotContainer.Path() return s.subvolCreate(dpath) } func (s *storageBtrfs) ImageCreate(fingerprint string) error { imagePath := shared.VarPath("images", fingerprint) subvol := fmt.Sprintf("%s.btrfs", imagePath) if err := s.subvolCreate(subvol); err != nil { return err } if err := untarImage(imagePath, subvol); err != nil { return err } return nil } func (s *storageBtrfs) ImageDelete(fingerprint string) error { imagePath := shared.VarPath("images", fingerprint) subvol := fmt.Sprintf("%s.btrfs", imagePath) return s.subvolDelete(subvol) } func (s *storageBtrfs) subvolCreate(subvol string) error { parentDestPath := filepath.Dir(subvol) if !shared.PathExists(parentDestPath) { if err := os.MkdirAll(parentDestPath, 0700); err != nil { return err } } output, err := exec.Command( "btrfs", "subvolume", "create", subvol).CombinedOutput() if err != nil { s.log.Debug( "subvolume create failed", log.Ctx{"subvol": subvol, "output": string(output)}, ) return fmt.Errorf( "btrfs subvolume create failed, subvol=%s, output%s", subvol, string(output), ) } return nil } func (s *storageBtrfs) subvolQGroup(subvol string) (string, error) { output, err := exec.Command( "btrfs", "qgroup", "show", subvol, "-e", "-f").CombinedOutput() if err != nil { return "", fmt.Errorf("btrfs quotas not supported. Try enabling them with 'btrfs quota enable'.") } var qgroup string for _, line := range strings.Split(string(output), "\n") { if line == "" || strings.HasPrefix(line, "qgroupid") || strings.HasPrefix(line, "---") { continue } fields := strings.Fields(line) if len(fields) != 4 { continue } qgroup = fields[0] } if qgroup == "" { return "", fmt.Errorf("Unable to find quota group") } return qgroup, nil } func (s *storageBtrfs) subvolQGroupUsage(subvol string) (int64, error) { output, err := exec.Command( "btrfs", "qgroup", "show", subvol, "-e", "-f").CombinedOutput() if err != nil { return -1, fmt.Errorf("btrfs quotas not supported. Try enabling them with 'btrfs quota enable'.") } for _, line := range strings.Split(string(output), "\n") { if line == "" || strings.HasPrefix(line, "qgroupid") || strings.HasPrefix(line, "---") { continue } fields := strings.Fields(line) if len(fields) != 4 { continue } usage, err := strconv.ParseInt(fields[2], 10, 64) if err != nil { continue } return usage, nil } return -1, fmt.Errorf("Unable to find current qgroup usage") } func (s *storageBtrfs) subvolDelete(subvol string) error { // Attempt (but don't fail on) to delete any qgroup on the subvolume qgroup, err := s.subvolQGroup(subvol) if err == nil { output, err := exec.Command( "btrfs", "qgroup", "destroy", qgroup, subvol).CombinedOutput() if err != nil { s.log.Warn( "subvolume qgroup delete failed", log.Ctx{"subvol": subvol, "output": string(output)}, ) } } // Delete the subvolume itself output, err := exec.Command( "btrfs", "subvolume", "delete", subvol, ).CombinedOutput() if err != nil { s.log.Warn( "subvolume delete failed", log.Ctx{"subvol": subvol, "output": string(output)}, ) } return nil } // subvolsDelete is the recursive variant on subvolDelete, // it first deletes subvolumes of the subvolume and then the // subvolume itself. func (s *storageBtrfs) subvolsDelete(subvol string) error { // Delete subsubvols. subsubvols, err := s.getSubVolumes(subvol) if err != nil { return err } for _, subsubvol := range subsubvols { s.log.Debug( "Deleting subsubvol", log.Ctx{ "subvol": subvol, "subsubvol": subsubvol}) if err := s.subvolDelete(path.Join(subvol, subsubvol)); err != nil { return err } } // Delete the subvol itself if err := s.subvolDelete(subvol); err != nil { return err } return nil } /* * subvolSnapshot creates a snapshot of "source" to "dest" * the result will be readonly if "readonly" is True. */ func (s *storageBtrfs) subvolSnapshot( source string, dest string, readonly bool) error { parentDestPath := filepath.Dir(dest) if !shared.PathExists(parentDestPath) { if err := os.MkdirAll(parentDestPath, 0700); err != nil { return err } } if shared.PathExists(dest) { if err := os.Remove(dest); err != nil { return err } } var output []byte var err error if readonly { output, err = exec.Command( "btrfs", "subvolume", "snapshot", "-r", source, dest).CombinedOutput() } else { output, err = exec.Command( "btrfs", "subvolume", "snapshot", source, dest).CombinedOutput() } if err != nil { s.log.Error( "subvolume snapshot failed", log.Ctx{"source": source, "dest": dest, "output": string(output)}, ) return fmt.Errorf( "subvolume snapshot failed, source=%s, dest=%s, output=%s", source, dest, string(output), ) } return err } func (s *storageBtrfs) subvolsSnapshot( source string, dest string, readonly bool) error { // Get a list of subvolumes of the root subsubvols, err := s.getSubVolumes(source) if err != nil { return err } if len(subsubvols) > 0 && readonly { // A root with subvolumes can never be readonly, // also don't make subvolumes readonly. readonly = false s.log.Warn( "Subvolumes detected, ignoring ro flag", log.Ctx{"source": source, "dest": dest}) } // First snapshot the root if err := s.subvolSnapshot(source, dest, readonly); err != nil { return err } // Now snapshot all subvolumes of the root. for _, subsubvol := range subsubvols { if err := s.subvolSnapshot( path.Join(source, subsubvol), path.Join(dest, subsubvol), readonly); err != nil { return err } } return nil } /* * isSubvolume returns true if the given Path is a btrfs subvolume * else false. */ func (s *storageBtrfs) isSubvolume(subvolPath string) bool { if runningInUserns { // subvolume show is restricted to real root, use a workaround fs := syscall.Statfs_t{} err := syscall.Statfs(subvolPath, &fs) if err != nil { return false } if fs.Type != filesystemSuperMagicBtrfs { return false } parentFs := syscall.Statfs_t{} err = syscall.Statfs(path.Dir(subvolPath), &parentFs) if err != nil { return false } if fs.Fsid == parentFs.Fsid { return false } return true } output, err := exec.Command( "btrfs", "subvolume", "show", subvolPath).CombinedOutput() if err != nil || strings.HasPrefix(string(output), "ERROR: ") { return false } return true } // getSubVolumes returns a list of relative subvolume paths of "path". func (s *storageBtrfs) getSubVolumes(path string) ([]string, error) { result := []string{} if runningInUserns { if !strings.HasSuffix(path, "/") { path = path + "/" } // Unprivileged users can't get to fs internals filepath.Walk(path, func(fpath string, fi os.FileInfo, err error) error { if strings.TrimRight(fpath, "/") == strings.TrimRight(path, "/") { return nil } if err != nil { return nil } if !fi.IsDir() { return nil } if s.isSubvolume(fpath) { result = append(result, strings.TrimPrefix(fpath, path)) } return nil }) return result, nil } out, err := exec.Command( "btrfs", "inspect-internal", "rootid", path).CombinedOutput() if err != nil { return result, fmt.Errorf( "Unable to get btrfs rootid, path='%s', err='%s'", path, err) } rootid := strings.TrimRight(string(out), "\n") out, err = exec.Command( "btrfs", "inspect-internal", "subvolid-resolve", rootid, path).CombinedOutput() if err != nil { return result, fmt.Errorf( "Unable to resolve btrfs rootid, path='%s', err='%s'", path, err) } basePath := strings.TrimRight(string(out), "\n") out, err = exec.Command( "btrfs", "subvolume", "list", "-o", path).CombinedOutput() if err != nil { return result, fmt.Errorf( "Unable to list subvolumes, path='%s', err='%s'", path, err) } lines := strings.Split(string(out), "\n") for _, line := range lines { if line == "" { continue } cols := strings.Fields(line) result = append(result, cols[8][len(basePath):]) } return result, nil } type btrfsMigrationSourceDriver struct { container container snapshots []container btrfsSnapshotNames []string btrfs *storageBtrfs runningSnapName string stoppedSnapName string } func (s *btrfsMigrationSourceDriver) Snapshots() []container { return s.snapshots } func (s *btrfsMigrationSourceDriver) send(conn *websocket.Conn, btrfsPath string, btrfsParent string) error { args := []string{"send", btrfsPath} if btrfsParent != "" { args = append(args, "-p", btrfsParent) } cmd := exec.Command("btrfs", args...) stdout, err := cmd.StdoutPipe() if err != nil { return err } stderr, err := cmd.StderrPipe() if err != nil { return err } if err := cmd.Start(); err != nil { return err } <-shared.WebsocketSendStream(conn, stdout) output, err := ioutil.ReadAll(stderr) if err != nil { shared.Log.Error("problem reading btrfs send stderr", "err", err) } err = cmd.Wait() if err != nil { shared.Log.Error("problem with btrfs send", "output", string(output)) } return err } func (s *btrfsMigrationSourceDriver) SendWhileRunning(conn *websocket.Conn) error { if s.container.IsSnapshot() { tmpPath := containerPath(fmt.Sprintf("%s/.migration-send-%s", s.container.Name(), uuid.NewRandom().String()), true) err := os.MkdirAll(tmpPath, 0700) if err != nil { return err } btrfsPath := fmt.Sprintf("%s/.root", tmpPath) if err := s.btrfs.subvolSnapshot(s.container.Path(), btrfsPath, true); err != nil { return err } defer s.btrfs.subvolDelete(btrfsPath) return s.send(conn, btrfsPath, "") } for i, snap := range s.snapshots { prev := "" if i > 0 { prev = s.snapshots[i-1].Path() } if err := s.send(conn, snap.Path(), prev); err != nil { return err } } /* We can't send running fses, so let's snapshot the fs and send * the snapshot. */ tmpPath := containerPath(fmt.Sprintf("%s/.migration-send-%s", s.container.Name(), uuid.NewRandom().String()), true) err := os.MkdirAll(tmpPath, 0700) if err != nil { return err } s.runningSnapName = fmt.Sprintf("%s/.root", tmpPath) if err := s.btrfs.subvolSnapshot(s.container.Path(), s.runningSnapName, true); err != nil { return err } btrfsParent := "" if len(s.btrfsSnapshotNames) > 0 { btrfsParent = s.btrfsSnapshotNames[len(s.btrfsSnapshotNames)-1] } return s.send(conn, s.runningSnapName, btrfsParent) } func (s *btrfsMigrationSourceDriver) SendAfterCheckpoint(conn *websocket.Conn) error { tmpPath := containerPath(fmt.Sprintf("%s/.migration-send-%s", s.container.Name(), uuid.NewRandom().String()), true) err := os.MkdirAll(tmpPath, 0700) if err != nil { return err } s.stoppedSnapName = fmt.Sprintf("%s/.root", tmpPath) if err := s.btrfs.subvolSnapshot(s.container.Path(), s.stoppedSnapName, true); err != nil { return err } return s.send(conn, s.stoppedSnapName, s.runningSnapName) } func (s *btrfsMigrationSourceDriver) Cleanup() { if s.stoppedSnapName != "" { s.btrfs.subvolDelete(s.stoppedSnapName) } if s.runningSnapName != "" { s.btrfs.subvolDelete(s.runningSnapName) } } func (s *storageBtrfs) MigrationType() MigrationFSType { if runningInUserns { return MigrationFSType_RSYNC } else { return MigrationFSType_BTRFS } } func (s *storageBtrfs) MigrationSource(c container) (MigrationStorageSourceDriver, error) { if runningInUserns { return rsyncMigrationSource(c) } /* List all the snapshots in order of reverse creation. The idea here * is that we send the oldest to newest snapshot, hopefully saving on * xfer costs. Then, after all that, we send the container itself. */ snapshots, err := c.Snapshots() if err != nil { return nil, err } driver := &btrfsMigrationSourceDriver{ container: c, snapshots: snapshots, btrfsSnapshotNames: []string{}, btrfs: s, } for _, snap := range snapshots { btrfsPath := snap.Path() driver.btrfsSnapshotNames = append(driver.btrfsSnapshotNames, btrfsPath) } return driver, nil } func (s *storageBtrfs) MigrationSink(live bool, container container, snapshots []container, conn *websocket.Conn) error { if runningInUserns { return rsyncMigrationSink(live, container, snapshots, conn) } cName := container.Name() snapshotsPath := shared.VarPath(fmt.Sprintf("snapshots/%s", cName)) if !shared.PathExists(snapshotsPath) { err := os.MkdirAll(shared.VarPath(fmt.Sprintf("snapshots/%s", cName)), 0700) if err != nil { return err } } btrfsRecv := func(btrfsPath string, targetPath string, isSnapshot bool) error { args := []string{"receive", "-e", btrfsPath} cmd := exec.Command("btrfs", args...) // Remove the existing pre-created subvolume err := s.subvolsDelete(targetPath) if err != nil { return err } stdin, err := cmd.StdinPipe() if err != nil { return err } stderr, err := cmd.StderrPipe() if err != nil { return err } if err := cmd.Start(); err != nil { return err } <-shared.WebsocketRecvStream(stdin, conn) output, err := ioutil.ReadAll(stderr) if err != nil { shared.Debugf("problem reading btrfs receive stderr %s", err) } err = cmd.Wait() if err != nil { shared.Log.Error("problem with btrfs receive", log.Ctx{"output": string(output)}) return err } if !isSnapshot { cPath := containerPath(fmt.Sprintf("%s/.root", cName), true) err := s.subvolSnapshot(cPath, targetPath, false) if err != nil { shared.Log.Error("problem with btrfs snapshot", log.Ctx{"err": err}) return err } err = s.subvolsDelete(cPath) if err != nil { shared.Log.Error("problem with btrfs delete", log.Ctx{"err": err}) return err } } return nil } for _, snap := range snapshots { if err := btrfsRecv(containerPath(cName, true), snap.Path(), true); err != nil { return err } } /* finally, do the real container */ if err := btrfsRecv(containerPath(cName, true), container.Path(), false); err != nil { return err } if live { if err := btrfsRecv(containerPath(cName, true), container.Path(), false); err != nil { return err } } // Cleanup if ok, _ := shared.PathIsEmpty(snapshotsPath); ok { err := os.Remove(snapshotsPath) if err != nil { return err } } return nil } lxd-2.0.0/lxd/storage_dir.go000066400000000000000000000150421270277227600157360ustar00rootroot00000000000000package main import ( "fmt" "os" "os/exec" "path/filepath" "strings" "github.com/gorilla/websocket" "github.com/lxc/lxd/shared" log "gopkg.in/inconshreveable/log15.v2" ) type storageDir struct { d *Daemon storageShared } func (s *storageDir) Init(config map[string]interface{}) (storage, error) { s.sType = storageTypeDir s.sTypeName = storageTypeToString(s.sType) if err := s.initShared(); err != nil { return s, err } return s, nil } func (s *storageDir) ContainerCreate(container container) error { cPath := container.Path() if err := os.MkdirAll(cPath, 0755); err != nil { return fmt.Errorf("Error creating containers directory") } if container.IsPrivileged() { if err := os.Chmod(cPath, 0700); err != nil { return err } } return container.TemplateApply("create") } func (s *storageDir) ContainerCreateFromImage( container container, imageFingerprint string) error { rootfsPath := container.RootfsPath() if err := os.MkdirAll(rootfsPath, 0755); err != nil { return fmt.Errorf("Error creating rootfs directory") } if container.IsPrivileged() { if err := os.Chmod(container.Path(), 0700); err != nil { return err } } imagePath := shared.VarPath("images", imageFingerprint) if err := untarImage(imagePath, container.Path()); err != nil { s.ContainerDelete(container) return err } if !container.IsPrivileged() { if err := s.shiftRootfs(container); err != nil { s.ContainerDelete(container) return err } } return container.TemplateApply("create") } func (s *storageDir) ContainerCanRestore(container container, sourceContainer container) error { return nil } func (s *storageDir) ContainerDelete(container container) error { cPath := container.Path() err := os.RemoveAll(cPath) if err != nil { // RemovaAll fails on very long paths, so attempt an rm -Rf output, err := exec.Command("rm", "-Rf", cPath).CombinedOutput() if err != nil { s.log.Error("ContainerDelete: failed", log.Ctx{"cPath": cPath, "output": output}) return fmt.Errorf("Error cleaning up %s: %s", cPath, string(output)) } } return nil } func (s *storageDir) ContainerCopy( container container, sourceContainer container) error { oldPath := sourceContainer.RootfsPath() newPath := container.RootfsPath() /* * Copy by using rsync */ output, err := storageRsyncCopy(oldPath, newPath) if err != nil { s.ContainerDelete(container) s.log.Error("ContainerCopy: rsync failed", log.Ctx{"output": string(output)}) return fmt.Errorf("rsync failed: %s", string(output)) } err = s.setUnprivUserAcl(sourceContainer, container.Path()) if err != nil { return err } return container.TemplateApply("copy") } func (s *storageDir) ContainerStart(container container) error { return nil } func (s *storageDir) ContainerStop(container container) error { return nil } func (s *storageDir) ContainerRename(container container, newName string) error { oldName := container.Name() oldPath := container.Path() newPath := containerPath(newName, false) if err := os.Rename(oldPath, newPath); err != nil { return err } if shared.PathExists(shared.VarPath(fmt.Sprintf("snapshots/%s", oldName))) { err := os.Rename(shared.VarPath(fmt.Sprintf("snapshots/%s", oldName)), shared.VarPath(fmt.Sprintf("snapshots/%s", newName))) if err != nil { return err } } return nil } func (s *storageDir) ContainerRestore( container container, sourceContainer container) error { targetPath := container.Path() sourcePath := sourceContainer.Path() // Restore using rsync output, err := storageRsyncCopy( sourcePath, targetPath) if err != nil { s.log.Error( "ContainerRestore: rsync failed", log.Ctx{"output": string(output)}) return err } // Now allow unprivileged users to access its data. if err := s.setUnprivUserAcl(sourceContainer, targetPath); err != nil { return err } return nil } func (s *storageDir) ContainerSetQuota(container container, size int64) error { return fmt.Errorf("The directory container backend doesn't support quotas.") } func (s *storageDir) ContainerGetUsage(container container) (int64, error) { return -1, fmt.Errorf("The directory container backend doesn't support quotas.") } func (s *storageDir) ContainerSnapshotCreate( snapshotContainer container, sourceContainer container) error { oldPath := sourceContainer.Path() newPath := snapshotContainer.Path() /* * Copy by using rsync */ output, err := storageRsyncCopy(oldPath, newPath) if err != nil { s.ContainerDelete(snapshotContainer) s.log.Error("ContainerSnapshotCreate: rsync failed", log.Ctx{"output": string(output)}) return fmt.Errorf("rsync failed: %s", string(output)) } return nil } func (s *storageDir) ContainerSnapshotCreateEmpty(snapshotContainer container) error { return os.MkdirAll(snapshotContainer.Path(), 0700) } func (s *storageDir) ContainerSnapshotDelete( snapshotContainer container) error { err := s.ContainerDelete(snapshotContainer) if err != nil { return fmt.Errorf("Error deleting snapshot %s: %s", snapshotContainer.Name(), err) } oldPathParent := filepath.Dir(snapshotContainer.Path()) if ok, _ := shared.PathIsEmpty(oldPathParent); ok { os.Remove(oldPathParent) } return nil } func (s *storageDir) ContainerSnapshotRename( snapshotContainer container, newName string) error { oldPath := snapshotContainer.Path() newPath := containerPath(newName, true) // Create the new parent. if strings.Contains(snapshotContainer.Name(), "/") { if !shared.PathExists(filepath.Dir(newPath)) { os.MkdirAll(filepath.Dir(newPath), 0700) } } // Now rename the snapshot. if err := os.Rename(oldPath, newPath); err != nil { return err } // Remove the old parent (on container rename) if its empty. if strings.Contains(snapshotContainer.Name(), "/") { if ok, _ := shared.PathIsEmpty(filepath.Dir(oldPath)); ok { os.Remove(filepath.Dir(oldPath)) } } return nil } func (s *storageDir) ContainerSnapshotStart(container container) error { return nil } func (s *storageDir) ContainerSnapshotStop(container container) error { return nil } func (s *storageDir) ImageCreate(fingerprint string) error { return nil } func (s *storageDir) ImageDelete(fingerprint string) error { return nil } func (s *storageDir) MigrationType() MigrationFSType { return MigrationFSType_RSYNC } func (s *storageDir) MigrationSource(container container) (MigrationStorageSourceDriver, error) { return rsyncMigrationSource(container) } func (s *storageDir) MigrationSink(live bool, container container, snapshots []container, conn *websocket.Conn) error { return rsyncMigrationSink(live, container, snapshots, conn) } lxd-2.0.0/lxd/storage_lvm.go000066400000000000000000000623211270277227600157600ustar00rootroot00000000000000package main import ( "fmt" "io/ioutil" "os" "os/exec" "path/filepath" "strconv" "strings" "syscall" "github.com/gorilla/websocket" "github.com/lxc/lxd/shared" log "gopkg.in/inconshreveable/log15.v2" ) var storageLvmDefaultThinLVSize = "10GiB" var storageLvmDefaultThinPoolName = "LXDPool" func storageLVMCheckVolumeGroup(vgName string) error { output, err := exec.Command("vgdisplay", "-s", vgName).CombinedOutput() if err != nil { shared.Log.Debug("vgdisplay failed to find vg", log.Ctx{"output": string(output)}) return fmt.Errorf("LVM volume group '%s' not found", vgName) } return nil } func storageLVMThinpoolExists(vgName string, poolName string) (bool, error) { output, err := exec.Command("vgs", "--noheadings", "-o", "lv_attr", fmt.Sprintf("%s/%s", vgName, poolName)).Output() if err != nil { if exitError, ok := err.(*exec.ExitError); ok { waitStatus := exitError.Sys().(syscall.WaitStatus) if waitStatus.ExitStatus() == 5 { // pool LV was not found return false, nil } } return false, fmt.Errorf("Error checking for pool '%s'", poolName) } // Found LV named poolname, check type: attrs := strings.TrimSpace(string(output[:])) if strings.HasPrefix(attrs, "t") { return true, nil } return false, fmt.Errorf("Pool named '%s' exists but is not a thin pool.", poolName) } func storageLVMGetThinPoolUsers(d *Daemon) ([]string, error) { results := []string{} vgname, err := d.ConfigValueGet("storage.lvm_vg_name") if err != nil { return results, fmt.Errorf("Error getting lvm_vg_name config") } if vgname == "" { return results, nil } poolname, err := d.ConfigValueGet("storage.lvm_thinpool_name") if err != nil { return results, fmt.Errorf("Error getting lvm_thinpool_name config") } if poolname == "" { return results, nil } cNames, err := dbContainersList(d.db, cTypeRegular) if err != nil { return results, err } for _, cName := range cNames { var lvLinkPath string if strings.Contains(cName, shared.SnapshotDelimiter) { lvLinkPath = shared.VarPath("snapshots", fmt.Sprintf("%s.lv", cName)) } else { lvLinkPath = shared.VarPath("containers", fmt.Sprintf("%s.lv", cName)) } if shared.PathExists(lvLinkPath) { results = append(results, cName) } } imageNames, err := dbImagesGet(d.db, false) if err != nil { return results, err } for _, imageName := range imageNames { imageLinkPath := shared.VarPath("images", fmt.Sprintf("%s.lv", imageName)) if shared.PathExists(imageLinkPath) { results = append(results, imageName) } } return results, nil } func storageLVMSetThinPoolNameConfig(d *Daemon, poolname string) error { users, err := storageLVMGetThinPoolUsers(d) if err != nil { return fmt.Errorf("Error checking if a pool is already in use: %v", err) } if len(users) > 0 { return fmt.Errorf("Can not change LVM config. Images or containers are still using LVs: %v", users) } vgname, err := d.ConfigValueGet("storage.lvm_vg_name") if err != nil { return fmt.Errorf("Error getting lvm_vg_name config: %v", err) } if poolname != "" { if vgname == "" { return fmt.Errorf("Can not set lvm_thinpool_name without lvm_vg_name set.") } poolExists, err := storageLVMThinpoolExists(vgname, poolname) if err != nil { return fmt.Errorf("Error checking for thin pool '%s' in '%s': %v", poolname, vgname, err) } if !poolExists { return fmt.Errorf("Pool '%s' does not exist in Volume Group '%s'", poolname, vgname) } } err = d.ConfigValueSet("storage.lvm_thinpool_name", poolname) if err != nil { return err } return nil } func storageLVMSetVolumeGroupNameConfig(d *Daemon, vgname string) error { users, err := storageLVMGetThinPoolUsers(d) if err != nil { return fmt.Errorf("Error checking if a pool is already in use: %v", err) } if len(users) > 0 { return fmt.Errorf("Can not change LVM config. Images or containers are still using LVs: %v", users) } if vgname != "" { err = storageLVMCheckVolumeGroup(vgname) if err != nil { return err } } err = d.ConfigValueSet("storage.lvm_vg_name", vgname) if err != nil { return err } return nil } func xfsGenerateNewUUID(lvpath string) error { output, err := exec.Command( "xfs_admin", "-U", "generate", lvpath).CombinedOutput() if err != nil { return fmt.Errorf("Error generating new UUID: %v\noutput:'%s'", err, string(output)) } return nil } func containerNameToLVName(containerName string) string { lvName := strings.Replace(containerName, "-", "--", -1) return strings.Replace(lvName, shared.SnapshotDelimiter, "-", -1) } type storageLvm struct { d *Daemon vgName string storageShared } func (s *storageLvm) Init(config map[string]interface{}) (storage, error) { s.sType = storageTypeLvm s.sTypeName = storageTypeToString(s.sType) if err := s.initShared(); err != nil { return s, err } output, err := exec.Command("lvm", "version").CombinedOutput() if err != nil { return nil, fmt.Errorf("Error getting LVM version: %v\noutput:'%s'", err, string(output)) } lines := strings.Split(string(output), "\n") s.sTypeVersion = "" for idx, line := range lines { fields := strings.SplitAfterN(line, ":", 2) if len(fields) < 2 { continue } if idx > 0 { s.sTypeVersion += " / " } s.sTypeVersion += strings.TrimSpace(fields[1]) } if config["vgName"] == nil { vgName, err := s.d.ConfigValueGet("storage.lvm_vg_name") if err != nil { return s, fmt.Errorf("Error checking server config: %v", err) } if vgName == "" { return s, fmt.Errorf("LVM isn't enabled") } if err := storageLVMCheckVolumeGroup(vgName); err != nil { return s, err } s.vgName = vgName } else { s.vgName = config["vgName"].(string) } return s, nil } func versionSplit(versionString string) (int, int, int, error) { fs := strings.Split(versionString, ".") majs, mins, incs := fs[0], fs[1], fs[2] maj, err := strconv.Atoi(majs) if err != nil { return 0, 0, 0, err } min, err := strconv.Atoi(mins) if err != nil { return 0, 0, 0, err } incs = strings.Split(incs, "(")[0] inc, err := strconv.Atoi(incs) if err != nil { return 0, 0, 0, err } return maj, min, inc, nil } func (s *storageLvm) lvmVersionIsAtLeast(versionString string) (bool, error) { lvmVersion := strings.Split(s.sTypeVersion, "/")[0] lvmMaj, lvmMin, lvmInc, err := versionSplit(lvmVersion) if err != nil { return false, err } inMaj, inMin, inInc, err := versionSplit(versionString) if err != nil { return false, err } if lvmMaj < inMaj || lvmMin < inMin || lvmInc < inInc { return false, nil } else { return true, nil } } func (s *storageLvm) ContainerCreate(container container) error { containerName := containerNameToLVName(container.Name()) lvpath, err := s.createThinLV(containerName) if err != nil { return err } if err := os.MkdirAll(container.Path(), 0755); err != nil { return err } var mode os.FileMode if container.IsPrivileged() { mode = 0700 } else { mode = 0755 } err = os.Chmod(container.Path(), mode) if err != nil { return err } dst := fmt.Sprintf("%s.lv", container.Path()) err = os.Symlink(lvpath, dst) if err != nil { return err } return nil } func (s *storageLvm) ContainerCreateFromImage( container container, imageFingerprint string) error { imageLVFilename := shared.VarPath( "images", fmt.Sprintf("%s.lv", imageFingerprint)) if !shared.PathExists(imageLVFilename) { if err := s.ImageCreate(imageFingerprint); err != nil { return err } } containerName := containerNameToLVName(container.Name()) lvpath, err := s.createSnapshotLV(containerName, imageFingerprint, false) if err != nil { return err } destPath := container.Path() if err := os.MkdirAll(destPath, 0755); err != nil { return fmt.Errorf("Error creating container directory: %v", err) } var mode os.FileMode if container.IsPrivileged() { mode = 0700 } else { mode = 0755 } err = os.Chmod(destPath, mode) if err != nil { return err } dst := shared.VarPath("containers", fmt.Sprintf("%s.lv", container.Name())) err = os.Symlink(lvpath, dst) if err != nil { return err } var fstype string fstype, err = s.d.ConfigValueGet("storage.lvm_fstype") if err != nil { return fmt.Errorf("Error checking server config, err=%v", err) } if fstype == "" { fstype = "ext4" } // Generate a new xfs's UUID if fstype == "xfs" { err := xfsGenerateNewUUID(lvpath) if err != nil { s.ContainerDelete(container) return err } } err = tryMount(lvpath, destPath, fstype, 0, "discard") if err != nil { s.ContainerDelete(container) return fmt.Errorf("Error mounting snapshot LV: %v", err) } if !container.IsPrivileged() { if err = s.shiftRootfs(container); err != nil { err2 := tryUnmount(destPath, 0) if err2 != nil { return fmt.Errorf("Error in umount: '%s' while cleaning up after error in shiftRootfs: '%s'", err2, err) } s.ContainerDelete(container) return fmt.Errorf("Error in shiftRootfs: %v", err) } } err = container.TemplateApply("create") if err != nil { s.log.Error("Error in create template during ContainerCreateFromImage, continuing to unmount", log.Ctx{"err": err}) } umounterr := tryUnmount(destPath, 0) if umounterr != nil { return fmt.Errorf("Error unmounting '%s' after shiftRootfs: %v", destPath, umounterr) } return err } func (s *storageLvm) ContainerCanRestore(container container, sourceContainer container) error { return nil } func (s *storageLvm) ContainerDelete(container container) error { lvName := containerNameToLVName(container.Name()) if err := s.removeLV(lvName); err != nil { return err } lvLinkPath := fmt.Sprintf("%s.lv", container.Path()) if err := os.Remove(lvLinkPath); err != nil { return err } cPath := container.Path() if err := os.RemoveAll(cPath); err != nil { s.log.Error("ContainerDelete: failed to remove path", log.Ctx{"cPath": cPath, "err": err}) return fmt.Errorf("Cleaning up %s: %s", cPath, err) } return nil } func (s *storageLvm) ContainerCopy(container container, sourceContainer container) error { if s.isLVMContainer(sourceContainer) { if err := s.createSnapshotContainer(container, sourceContainer, false); err != nil { s.log.Error("Error creating snapshot LV for copy", log.Ctx{"err": err}) return err } } else { s.log.Info("Copy from Non-LVM container", log.Ctx{"container": container.Name(), "sourceContainer": sourceContainer.Name()}) if err := s.ContainerCreate(container); err != nil { s.log.Error("Error creating empty container", log.Ctx{"err": err}) return err } if err := s.ContainerStart(container); err != nil { s.log.Error("Error starting/mounting container", log.Ctx{"err": err, "container": container.Name()}) s.ContainerDelete(container) return err } output, err := storageRsyncCopy( sourceContainer.Path(), container.Path()) if err != nil { s.log.Error("ContainerCopy: rsync failed", log.Ctx{"output": string(output)}) s.ContainerDelete(container) return fmt.Errorf("rsync failed: %s", string(output)) } if err := s.ContainerStop(container); err != nil { return err } } return container.TemplateApply("copy") } func (s *storageLvm) ContainerStart(container container) error { lvName := containerNameToLVName(container.Name()) lvpath := fmt.Sprintf("/dev/%s/%s", s.vgName, lvName) fstype, err := s.d.ConfigValueGet("storage.lvm_fstype") if err != nil { return fmt.Errorf("Error checking server config, err=%v", err) } if fstype == "" { fstype = "ext4" } err = tryMount(lvpath, container.Path(), fstype, 0, "discard") if err != nil { return fmt.Errorf( "Error mounting snapshot LV path='%s': %v", container.Path(), err) } return nil } func (s *storageLvm) ContainerStop(container container) error { err := tryUnmount(container.Path(), 0) if err != nil { return fmt.Errorf( "failed to unmount container path '%s'.\nError: %v", container.Path(), err) } return nil } func (s *storageLvm) ContainerRename( container container, newContainerName string) error { oldName := containerNameToLVName(container.Name()) newName := containerNameToLVName(newContainerName) output, err := s.renameLV(oldName, newName) if err != nil { s.log.Error("Failed to rename a container LV", log.Ctx{"oldName": oldName, "newName": newName, "err": err, "output": string(output)}) return fmt.Errorf("Failed to rename a container LV, oldName='%s', newName='%s', err='%s'", oldName, newName, err) } // Rename the snapshots if !container.IsSnapshot() { snaps, err := container.Snapshots() if err != nil { return err } for _, snap := range snaps { baseSnapName := filepath.Base(snap.Name()) newSnapshotName := newName + shared.SnapshotDelimiter + baseSnapName err := s.ContainerRename(snap, newSnapshotName) if err != nil { return err } oldPathParent := filepath.Dir(snap.Path()) if ok, _ := shared.PathIsEmpty(oldPathParent); ok { os.Remove(oldPathParent) } } } // Create a new symlink newSymPath := fmt.Sprintf("%s.lv", containerPath(newContainerName, container.IsSnapshot())) err = os.MkdirAll(filepath.Dir(containerPath(newContainerName, container.IsSnapshot())), 0700) if err != nil { return err } err = os.Symlink(fmt.Sprintf("/dev/%s/%s", s.vgName, newName), newSymPath) if err != nil { return err } // Remove the old symlink oldSymPath := fmt.Sprintf("%s.lv", container.Path()) err = os.Remove(oldSymPath) if err != nil { return err } // Rename the directory err = os.Rename(container.Path(), containerPath(newContainerName, container.IsSnapshot())) if err != nil { return err } return nil } func (s *storageLvm) ContainerRestore( container container, sourceContainer container) error { srcName := containerNameToLVName(sourceContainer.Name()) destName := containerNameToLVName(container.Name()) err := s.removeLV(destName) if err != nil { return fmt.Errorf("Error removing LV about to be restored over: %v", err) } _, err = s.createSnapshotLV(destName, srcName, false) if err != nil { return fmt.Errorf("Error creating snapshot LV: %v", err) } return nil } func (s *storageLvm) ContainerSetQuota(container container, size int64) error { return fmt.Errorf("The LVM container backend doesn't support quotas.") } func (s *storageLvm) ContainerGetUsage(container container) (int64, error) { return -1, fmt.Errorf("The LVM container backend doesn't support quotas.") } func (s *storageLvm) ContainerSnapshotCreate( snapshotContainer container, sourceContainer container) error { return s.createSnapshotContainer(snapshotContainer, sourceContainer, true) } func (s *storageLvm) createSnapshotContainer( snapshotContainer container, sourceContainer container, readonly bool) error { srcName := containerNameToLVName(sourceContainer.Name()) destName := containerNameToLVName(snapshotContainer.Name()) shared.Log.Debug( "Creating snapshot", log.Ctx{"srcName": srcName, "destName": destName}) lvpath, err := s.createSnapshotLV(destName, srcName, readonly) if err != nil { return fmt.Errorf("Error creating snapshot LV: %v", err) } destPath := snapshotContainer.Path() if err := os.MkdirAll(destPath, 0755); err != nil { return fmt.Errorf("Error creating container directory: %v", err) } var mode os.FileMode if snapshotContainer.IsPrivileged() { mode = 0700 } else { mode = 0755 } err = os.Chmod(destPath, mode) if err != nil { return err } dest := fmt.Sprintf("%s.lv", snapshotContainer.Path()) err = os.Symlink(lvpath, dest) if err != nil { return err } return nil } func (s *storageLvm) ContainerSnapshotDelete( snapshotContainer container) error { err := s.ContainerDelete(snapshotContainer) if err != nil { return fmt.Errorf("Error deleting snapshot %s: %s", snapshotContainer.Name(), err) } oldPathParent := filepath.Dir(snapshotContainer.Path()) if ok, _ := shared.PathIsEmpty(oldPathParent); ok { os.Remove(oldPathParent) } return nil } func (s *storageLvm) ContainerSnapshotRename( snapshotContainer container, newContainerName string) error { oldName := containerNameToLVName(snapshotContainer.Name()) newName := containerNameToLVName(newContainerName) oldPath := snapshotContainer.Path() oldSymPath := fmt.Sprintf("%s.lv", oldPath) newPath := containerPath(newContainerName, true) newSymPath := fmt.Sprintf("%s.lv", newPath) // Rename the LV output, err := s.renameLV(oldName, newName) if err != nil { s.log.Error("Failed to rename a snapshot LV", log.Ctx{"oldName": oldName, "newName": newName, "err": err, "output": string(output)}) return fmt.Errorf("Failed to rename a container LV, oldName='%s', newName='%s', err='%s'", oldName, newName, err) } // Delete the symlink err = os.Remove(oldSymPath) if err != nil { return fmt.Errorf("Failed to remove old symlink: %s", err) } // Create the symlink err = os.Symlink(fmt.Sprintf("/dev/%s/%s", s.vgName, newName), newSymPath) if err != nil { return fmt.Errorf("Failed to create symlink: %s", err) } // Rename the mount point err = os.Rename(oldPath, newPath) if err != nil { return fmt.Errorf("Failed to rename mountpoint: %s", err) } return nil } func (s *storageLvm) ContainerSnapshotStart(container container) error { srcName := containerNameToLVName(container.Name()) destName := containerNameToLVName(container.Name() + "/rw") shared.Log.Debug( "Creating snapshot", log.Ctx{"srcName": srcName, "destName": destName}) lvpath, err := s.createSnapshotLV(destName, srcName, false) if err != nil { return fmt.Errorf("Error creating snapshot LV: %v", err) } destPath := container.Path() if !shared.PathExists(destPath) { if err := os.MkdirAll(destPath, 0755); err != nil { return fmt.Errorf("Error creating container directory: %v", err) } } var fstype string fstype, err = s.d.ConfigValueGet("storage.lvm_fstype") if err != nil { return fmt.Errorf("Error checking server config, err=%v", err) } if fstype == "" { fstype = "ext4" } // Generate a new xfs's UUID if fstype == "xfs" { err := xfsGenerateNewUUID(lvpath) if err != nil { s.ContainerDelete(container) return err } } err = tryMount(lvpath, container.Path(), fstype, 0, "discard") if err != nil { return fmt.Errorf( "Error mounting snapshot LV path='%s': %v", container.Path(), err) } return nil } func (s *storageLvm) ContainerSnapshotStop(container container) error { err := s.ContainerStop(container) if err != nil { return err } lvName := containerNameToLVName(container.Name() + "/rw") if err := s.removeLV(lvName); err != nil { return err } return nil } func (s *storageLvm) ContainerSnapshotCreateEmpty(snapshotContainer container) error { return s.ContainerCreate(snapshotContainer) } func (s *storageLvm) ImageCreate(fingerprint string) error { finalName := shared.VarPath("images", fingerprint) lvpath, err := s.createThinLV(fingerprint) if err != nil { s.log.Error("LVMCreateThinLV", log.Ctx{"err": err}) return fmt.Errorf("Error Creating LVM LV for new image: %v", err) } dst := shared.VarPath("images", fmt.Sprintf("%s.lv", fingerprint)) err = os.Symlink(lvpath, dst) if err != nil { return err } tempLVMountPoint, err := ioutil.TempDir(shared.VarPath("images"), "tmp_lv_mnt") if err != nil { return err } defer func() { if err := os.RemoveAll(tempLVMountPoint); err != nil { s.log.Error("Deleting temporary LVM mount point", log.Ctx{"err": err}) } }() var fstype string fstype, err = s.d.ConfigValueGet("storage.lvm_fstype") if err != nil { return fmt.Errorf("Error checking server config, err=%v", err) } if fstype == "" { fstype = "ext4" } err = tryMount(lvpath, tempLVMountPoint, fstype, 0, "discard") if err != nil { shared.Logf("Error mounting image LV for untarring: %v", err) return fmt.Errorf("Error mounting image LV: %v", err) } untarErr := untarImage(finalName, tempLVMountPoint) err = tryUnmount(tempLVMountPoint, 0) if err != nil { s.log.Warn("could not unmount LV. Will not remove", log.Ctx{"lvpath": lvpath, "mountpoint": tempLVMountPoint, "err": err}) if untarErr == nil { return err } return fmt.Errorf( "Error unmounting '%s' during cleanup of error %v", tempLVMountPoint, untarErr) } return untarErr } func (s *storageLvm) ImageDelete(fingerprint string) error { err := s.removeLV(fingerprint) if err != nil { return err } lvsymlink := fmt.Sprintf( "%s.lv", shared.VarPath("images", fingerprint)) err = os.Remove(lvsymlink) if err != nil { return fmt.Errorf( "Failed to remove symlink to deleted image LV: '%s': %v", lvsymlink, err) } return nil } func (s *storageLvm) createDefaultThinPool() (string, error) { // Create a tiny 1G thinpool output, err := tryExec( "lvcreate", "--poolmetadatasize", "1G", "-L", "1G", "--thinpool", fmt.Sprintf("%s/%s", s.vgName, storageLvmDefaultThinPoolName)) if err != nil { s.log.Error( "Could not create thin pool", log.Ctx{ "name": storageLvmDefaultThinPoolName, "err": err, "output": string(output)}) return "", fmt.Errorf( "Could not create LVM thin pool named %s", storageLvmDefaultThinPoolName) } // Grow it to the maximum VG size (two step process required by old LVM) output, err = tryExec( "lvextend", "--alloc", "anywhere", "-l", "100%FREE", fmt.Sprintf("%s/%s", s.vgName, storageLvmDefaultThinPoolName)) if err != nil { s.log.Error( "Could not grow thin pool", log.Ctx{ "name": storageLvmDefaultThinPoolName, "err": err, "output": string(output)}) return "", fmt.Errorf( "Could not grow LVM thin pool named %s", storageLvmDefaultThinPoolName) } return storageLvmDefaultThinPoolName, nil } func (s *storageLvm) createThinLV(lvname string) (string, error) { poolname, err := s.d.ConfigValueGet("storage.lvm_thinpool_name") if err != nil { return "", fmt.Errorf("Error checking server config, err=%v", err) } if poolname == "" { poolname, err = s.createDefaultThinPool() if err != nil { return "", fmt.Errorf("Error creating LVM thin pool: %v", err) } err = storageLVMSetThinPoolNameConfig(s.d, poolname) if err != nil { s.log.Error("Setting thin pool name", log.Ctx{"err": err}) return "", fmt.Errorf("Error setting LVM thin pool config: %v", err) } } lvSize, err := s.d.ConfigValueGet("storage.lvm_volume_size") if err != nil { return "", fmt.Errorf("Error checking server config, err=%v", err) } if lvSize == "" { lvSize = storageLvmDefaultThinLVSize } output, err := tryExec( "lvcreate", "--thin", "-n", lvname, "--virtualsize", lvSize, fmt.Sprintf("%s/%s", s.vgName, poolname)) if err != nil { s.log.Error("Could not create LV", log.Ctx{"lvname": lvname, "output": string(output)}) return "", fmt.Errorf("Could not create thin LV named %s", lvname) } lvpath := fmt.Sprintf("/dev/%s/%s", s.vgName, lvname) fstype, err := s.d.ConfigValueGet("storage.lvm_fstype") switch fstype { case "xfs": output, err = tryExec( "mkfs.xfs", lvpath) default: // default = ext4 output, err = tryExec( "mkfs.ext4", "-E", "nodiscard,lazy_itable_init=0,lazy_journal_init=0", lvpath) } if err != nil { s.log.Error("mkfs.ext4", log.Ctx{"output": string(output)}) return "", fmt.Errorf("Error making filesystem on image LV: %v", err) } return lvpath, nil } func (s *storageLvm) removeLV(lvname string) error { var err error var output []byte output, err = tryExec( "lvremove", "-f", fmt.Sprintf("%s/%s", s.vgName, lvname)) if err != nil { s.log.Error("Could not remove LV", log.Ctx{"lvname": lvname, "output": string(output)}) return fmt.Errorf("Could not remove LV named %s", lvname) } return nil } func (s *storageLvm) createSnapshotLV(lvname string, origlvname string, readonly bool) (string, error) { s.log.Debug("in createSnapshotLV:", log.Ctx{"lvname": lvname, "dev string": fmt.Sprintf("/dev/%s/%s", s.vgName, origlvname)}) isRecent, err := s.lvmVersionIsAtLeast("2.02.99") if err != nil { return "", fmt.Errorf("Error checking LVM version: %v", err) } var output []byte if isRecent { output, err = tryExec( "lvcreate", "-kn", "-n", lvname, "-s", fmt.Sprintf("/dev/%s/%s", s.vgName, origlvname)) } else { output, err = tryExec( "lvcreate", "-n", lvname, "-s", fmt.Sprintf("/dev/%s/%s", s.vgName, origlvname)) } if err != nil { s.log.Error("Could not create LV snapshot", log.Ctx{"lvname": lvname, "origlvname": origlvname, "output": string(output)}) return "", fmt.Errorf("Could not create snapshot LV named %s", lvname) } snapshotFullName := fmt.Sprintf("/dev/%s/%s", s.vgName, lvname) if readonly { output, err = tryExec("lvchange", "-ay", "-pr", snapshotFullName) } else { output, err = tryExec("lvchange", "-ay", snapshotFullName) } if err != nil { return "", fmt.Errorf("Could not activate new snapshot '%s': %v\noutput:%s", lvname, err, string(output)) } return snapshotFullName, nil } func (s *storageLvm) isLVMContainer(container container) bool { return shared.PathExists(fmt.Sprintf("%s.lv", container.Path())) } func (s *storageLvm) renameLV(oldName string, newName string) (string, error) { output, err := tryExec("lvrename", s.vgName, oldName, newName) return string(output), err } func (s *storageLvm) MigrationType() MigrationFSType { return MigrationFSType_RSYNC } func (s *storageLvm) MigrationSource(container container) (MigrationStorageSourceDriver, error) { return rsyncMigrationSource(container) } func (s *storageLvm) MigrationSink(live bool, container container, snapshots []container, conn *websocket.Conn) error { return rsyncMigrationSink(live, container, snapshots, conn) } lxd-2.0.0/lxd/storage_test.go000066400000000000000000000053741270277227600161460ustar00rootroot00000000000000package main import ( "fmt" "github.com/gorilla/websocket" log "gopkg.in/inconshreveable/log15.v2" ) type storageMock struct { d *Daemon sType storageType log log.Logger storageShared } func (s *storageMock) Init(config map[string]interface{}) (storage, error) { s.sType = storageTypeMock s.sTypeName = storageTypeToString(storageTypeMock) if err := s.initShared(); err != nil { return s, err } return s, nil } func (s *storageMock) GetStorageType() storageType { return s.sType } func (s *storageMock) GetStorageTypeName() string { return s.sTypeName } func (s *storageMock) ContainerCreate(container container) error { return nil } func (s *storageMock) ContainerCreateFromImage( container container, imageFingerprint string) error { return nil } func (s *storageMock) ContainerCanRestore(container container, sourceContainer container) error { return nil } func (s *storageMock) ContainerDelete(container container) error { return nil } func (s *storageMock) ContainerCopy( container container, sourceContainer container) error { return nil } func (s *storageMock) ContainerStart(container container) error { return nil } func (s *storageMock) ContainerStop(container container) error { return nil } func (s *storageMock) ContainerRename( container container, newName string) error { return nil } func (s *storageMock) ContainerRestore( container container, sourceContainer container) error { return nil } func (s *storageMock) ContainerSetQuota( container container, size int64) error { return nil } func (s *storageMock) ContainerGetUsage( container container) (int64, error) { return 0, nil } func (s *storageMock) ContainerSnapshotCreate( snapshotContainer container, sourceContainer container) error { return nil } func (s *storageMock) ContainerSnapshotDelete( snapshotContainer container) error { return nil } func (s *storageMock) ContainerSnapshotRename( snapshotContainer container, newName string) error { return nil } func (s *storageMock) ContainerSnapshotStart(container container) error { return nil } func (s *storageMock) ContainerSnapshotStop(container container) error { return nil } func (s *storageMock) ContainerSnapshotCreateEmpty(snapshotContainer container) error { return nil } func (s *storageMock) ImageCreate(fingerprint string) error { return nil } func (s *storageMock) ImageDelete(fingerprint string) error { return nil } func (s *storageMock) MigrationType() MigrationFSType { return MigrationFSType_RSYNC } func (s *storageMock) MigrationSource(container container) (MigrationStorageSourceDriver, error) { return nil, fmt.Errorf("not implemented") } func (s *storageMock) MigrationSink(live bool, container container, snapshots []container, conn *websocket.Conn) error { return nil } lxd-2.0.0/lxd/storage_zfs.go000066400000000000000000001006551270277227600157670ustar00rootroot00000000000000package main import ( "fmt" "io/ioutil" "os" "os/exec" "strconv" "strings" "syscall" "github.com/gorilla/websocket" "github.com/lxc/lxd/shared" "github.com/pborman/uuid" log "gopkg.in/inconshreveable/log15.v2" ) type storageZfs struct { d *Daemon zfsPool string storageShared } func (s *storageZfs) Init(config map[string]interface{}) (storage, error) { s.sType = storageTypeZfs s.sTypeName = storageTypeToString(s.sType) err := s.initShared() if err != nil { return s, err } if config["zfsPool"] == nil { zfsPool, err := s.d.ConfigValueGet("storage.zfs_pool_name") if err != nil { return s, fmt.Errorf("Error checking server config: %v", err) } if zfsPool == "" { return s, fmt.Errorf("ZFS isn't enabled") } s.zfsPool = zfsPool } else { s.zfsPool = config["zfsPool"].(string) } out, err := exec.LookPath("zfs") if err != nil || len(out) == 0 { return s, fmt.Errorf("The 'zfs' tool isn't available") } err = s.zfsCheckPool(s.zfsPool) if err != nil { if shared.PathExists(shared.VarPath("zfs.img")) { _ = exec.Command("modprobe", "zfs").Run() output, err := exec.Command("zpool", "import", "-d", shared.VarPath(), s.zfsPool).CombinedOutput() if err != nil { return s, fmt.Errorf("Unable to import the ZFS pool: %s", output) } } else { return s, err } } output, err := exec.Command("zfs", "get", "version", "-H", "-o", "value", s.zfsPool).CombinedOutput() if err != nil { return s, fmt.Errorf("The 'zfs' tool isn't working properly") } count, err := fmt.Sscanf(string(output), "%s\n", &s.sTypeVersion) if err != nil || count != 1 { return s, fmt.Errorf("The 'zfs' tool isn't working properly") } return s, nil } // Things we don't need to care about func (s *storageZfs) ContainerStart(container container) error { return nil } func (s *storageZfs) ContainerStop(container container) error { return nil } // Things we do have to care about func (s *storageZfs) ContainerCreate(container container) error { cPath := container.Path() fs := fmt.Sprintf("containers/%s", container.Name()) err := s.zfsCreate(fs) if err != nil { return err } err = os.Symlink(cPath+".zfs", cPath) if err != nil { return err } var mode os.FileMode if container.IsPrivileged() { mode = 0700 } else { mode = 0755 } err = os.Chmod(cPath, mode) if err != nil { return err } return container.TemplateApply("create") } func (s *storageZfs) ContainerCreateFromImage(container container, fingerprint string) error { cPath := container.Path() imagePath := shared.VarPath("images", fingerprint) subvol := fmt.Sprintf("%s.zfs", imagePath) fs := fmt.Sprintf("containers/%s", container.Name()) fsImage := fmt.Sprintf("images/%s", fingerprint) if !shared.PathExists(subvol) { err := s.ImageCreate(fingerprint) if err != nil { return err } } err := s.zfsClone(fsImage, "readonly", fs, true) if err != nil { return err } err = os.Symlink(cPath+".zfs", cPath) if err != nil { return err } var mode os.FileMode if container.IsPrivileged() { mode = 0700 } else { mode = 0755 } err = os.Chmod(cPath, mode) if err != nil { return err } if !container.IsPrivileged() { err = s.shiftRootfs(container) if err != nil { return err } } return container.TemplateApply("create") } func (s *storageZfs) ContainerCanRestore(container container, sourceContainer container) error { fields := strings.SplitN(sourceContainer.Name(), shared.SnapshotDelimiter, 2) cName := fields[0] snapName := fmt.Sprintf("snapshot-%s", fields[1]) snapshots, err := s.zfsListSnapshots(fmt.Sprintf("containers/%s", cName)) if err != nil { return err } if snapshots[len(snapshots)-1] != snapName { return fmt.Errorf("ZFS can only restore from the latest snapshot. Delete newer snapshots or copy the snapshot into a new container instead.") } return nil } func (s *storageZfs) ContainerDelete(container container) error { fs := fmt.Sprintf("containers/%s", container.Name()) removable := true snaps, err := s.zfsListSnapshots(fs) if err != nil { return err } for _, snap := range snaps { var err error removable, err = s.zfsSnapshotRemovable(fs, snap) if err != nil { return err } if !removable { break } } if removable { origin, err := s.zfsGet(fs, "origin") if err != nil { return err } origin = strings.TrimPrefix(origin, fmt.Sprintf("%s/", s.zfsPool)) err = s.zfsDestroy(fs) if err != nil { return err } err = s.zfsCleanup(origin) if err != nil { return err } } else { err := s.zfsSet(fs, "mountpoint", "none") if err != nil { return err } err = s.zfsRename(fs, fmt.Sprintf("deleted/containers/%s", uuid.NewRandom().String())) if err != nil { return err } } if shared.PathExists(shared.VarPath(fs)) { os.Remove(shared.VarPath(fs)) if err != nil { return err } } if shared.PathExists(shared.VarPath(fs) + ".zfs") { os.Remove(shared.VarPath(fs) + ".zfs") if err != nil { return err } } s.zfsDestroy(fmt.Sprintf("snapshots/%s", container.Name())) return nil } func (s *storageZfs) ContainerCopy(container container, sourceContainer container) error { var sourceFs string var sourceSnap string sourceFields := strings.SplitN(sourceContainer.Name(), shared.SnapshotDelimiter, 2) sourceName := sourceFields[0] destName := container.Name() destFs := fmt.Sprintf("containers/%s", destName) if len(sourceFields) == 2 { sourceSnap = sourceFields[1] } if sourceSnap == "" { if s.zfsExists(fmt.Sprintf("containers/%s", sourceName)) { sourceSnap = fmt.Sprintf("copy-%s", uuid.NewRandom().String()) sourceFs = fmt.Sprintf("containers/%s", sourceName) err := s.zfsSnapshotCreate(fmt.Sprintf("containers/%s", sourceName), sourceSnap) if err != nil { return err } } } else { if s.zfsExists(fmt.Sprintf("containers/%s@snapshot-%s", sourceName, sourceSnap)) { sourceFs = fmt.Sprintf("containers/%s", sourceName) sourceSnap = fmt.Sprintf("snapshot-%s", sourceSnap) } } if sourceFs != "" { err := s.zfsClone(sourceFs, sourceSnap, destFs, true) if err != nil { return err } cPath := container.Path() err = os.Symlink(cPath+".zfs", cPath) if err != nil { return err } var mode os.FileMode if container.IsPrivileged() { mode = 0700 } else { mode = 0755 } err = os.Chmod(cPath, mode) if err != nil { return err } } else { err := s.ContainerCreate(container) if err != nil { return err } output, err := storageRsyncCopy(sourceContainer.Path(), container.Path()) if err != nil { return fmt.Errorf("rsync failed: %s", string(output)) } } return container.TemplateApply("copy") } func (s *storageZfs) ContainerRename(container container, newName string) error { oldName := container.Name() // Unmount the filesystem err := s.zfsUnmount(fmt.Sprintf("containers/%s", oldName)) if err != nil { return err } // Rename the filesystem err = s.zfsRename(fmt.Sprintf("containers/%s", oldName), fmt.Sprintf("containers/%s", newName)) if err != nil { return err } // Update to the new mountpoint err = s.zfsSet(fmt.Sprintf("containers/%s", newName), "mountpoint", shared.VarPath(fmt.Sprintf("containers/%s.zfs", newName))) if err != nil { return err } // In case ZFS didn't mount the filesystem, do it ourselves err = s.zfsMount(fmt.Sprintf("containers/%s", newName)) if err != nil { return err } // In case the change of mountpoint didn't remove the old path, do it ourselves if shared.PathExists(shared.VarPath(fmt.Sprintf("containers/%s.zfs", oldName))) { err = os.Remove(shared.VarPath(fmt.Sprintf("containers/%s.zfs", oldName))) if err != nil { return err } } // Remove the old symlink err = os.Remove(shared.VarPath(fmt.Sprintf("containers/%s", oldName))) if err != nil { return err } // Create a new symlink err = os.Symlink(shared.VarPath(fmt.Sprintf("containers/%s.zfs", newName)), shared.VarPath(fmt.Sprintf("containers/%s", newName))) if err != nil { return err } // Rename the snapshot path if shared.PathExists(shared.VarPath(fmt.Sprintf("snapshots/%s", oldName))) { err = os.Rename(shared.VarPath(fmt.Sprintf("snapshots/%s", oldName)), shared.VarPath(fmt.Sprintf("snapshots/%s", newName))) if err != nil { return err } } return nil } func (s *storageZfs) ContainerRestore(container container, sourceContainer container) error { fields := strings.SplitN(sourceContainer.Name(), shared.SnapshotDelimiter, 2) cName := fields[0] snapName := fmt.Sprintf("snapshot-%s", fields[1]) err := s.zfsSnapshotRestore(fmt.Sprintf("containers/%s", cName), snapName) if err != nil { return err } return nil } func (s *storageZfs) ContainerSetQuota(container container, size int64) error { var err error fs := fmt.Sprintf("containers/%s", container.Name()) if size > 0 { err = s.zfsSet(fs, "quota", fmt.Sprintf("%d", size)) } else { err = s.zfsSet(fs, "quota", "none") } if err != nil { return err } return nil } func (s *storageZfs) ContainerGetUsage(container container) (int64, error) { var err error fs := fmt.Sprintf("containers/%s", container.Name()) value, err := s.zfsGet(fs, "used") if err != nil { return -1, err } valueInt, err := strconv.ParseInt(value, 10, 64) if err != nil { return -1, err } return valueInt, nil } func (s *storageZfs) ContainerSnapshotCreate(snapshotContainer container, sourceContainer container) error { fields := strings.SplitN(snapshotContainer.Name(), shared.SnapshotDelimiter, 2) cName := fields[0] snapName := fmt.Sprintf("snapshot-%s", fields[1]) err := s.zfsSnapshotCreate(fmt.Sprintf("containers/%s", cName), snapName) if err != nil { return err } if !shared.PathExists(shared.VarPath(fmt.Sprintf("snapshots/%s", cName))) { err = os.MkdirAll(shared.VarPath(fmt.Sprintf("snapshots/%s", cName)), 0700) if err != nil { return err } } err = os.Symlink("on-zfs", shared.VarPath(fmt.Sprintf("snapshots/%s/%s.zfs", cName, fields[1]))) if err != nil { return err } return nil } func (s *storageZfs) ContainerSnapshotDelete(snapshotContainer container) error { fields := strings.SplitN(snapshotContainer.Name(), shared.SnapshotDelimiter, 2) cName := fields[0] snapName := fmt.Sprintf("snapshot-%s", fields[1]) removable, err := s.zfsSnapshotRemovable(fmt.Sprintf("containers/%s", cName), snapName) if removable { err = s.zfsSnapshotDestroy(fmt.Sprintf("containers/%s", cName), snapName) if err != nil { return err } } else { err = s.zfsSnapshotRename(fmt.Sprintf("containers/%s", cName), snapName, fmt.Sprintf("copy-%s", uuid.NewRandom().String())) if err != nil { return err } } err = os.Remove(shared.VarPath(fmt.Sprintf("snapshots/%s/%s.zfs", cName, fields[1]))) if err != nil { return err } parent := shared.VarPath(fmt.Sprintf("snapshots/%s", cName)) if ok, _ := shared.PathIsEmpty(parent); ok { err = os.Remove(parent) if err != nil { return err } } return nil } func (s *storageZfs) ContainerSnapshotRename(snapshotContainer container, newName string) error { oldFields := strings.SplitN(snapshotContainer.Name(), shared.SnapshotDelimiter, 2) oldcName := oldFields[0] oldName := fmt.Sprintf("snapshot-%s", oldFields[1]) newFields := strings.SplitN(newName, shared.SnapshotDelimiter, 2) newcName := newFields[0] newName = fmt.Sprintf("snapshot-%s", newFields[1]) if oldName != newName { err := s.zfsSnapshotRename(fmt.Sprintf("containers/%s", oldcName), oldName, newName) if err != nil { return err } } err := os.Remove(shared.VarPath(fmt.Sprintf("snapshots/%s/%s.zfs", oldcName, oldFields[1]))) if err != nil { return err } if !shared.PathExists(shared.VarPath(fmt.Sprintf("snapshots/%s", newcName))) { err = os.MkdirAll(shared.VarPath(fmt.Sprintf("snapshots/%s", newcName)), 0700) if err != nil { return err } } err = os.Symlink("on-zfs", shared.VarPath(fmt.Sprintf("snapshots/%s/%s.zfs", newcName, newFields[1]))) if err != nil { return err } parent := shared.VarPath(fmt.Sprintf("snapshots/%s", oldcName)) if ok, _ := shared.PathIsEmpty(parent); ok { err = os.Remove(parent) if err != nil { return err } } return nil } func (s *storageZfs) ContainerSnapshotStart(container container) error { fields := strings.SplitN(container.Name(), shared.SnapshotDelimiter, 2) if len(fields) < 2 { return fmt.Errorf("Invalid snapshot name: %s", container.Name()) } cName := fields[0] sName := fields[1] sourceFs := fmt.Sprintf("containers/%s", cName) sourceSnap := fmt.Sprintf("snapshot-%s", sName) destFs := fmt.Sprintf("snapshots/%s/%s", cName, sName) err := s.zfsClone(sourceFs, sourceSnap, destFs, false) if err != nil { return err } return nil } func (s *storageZfs) ContainerSnapshotStop(container container) error { fields := strings.SplitN(container.Name(), shared.SnapshotDelimiter, 2) if len(fields) < 2 { return fmt.Errorf("Invalid snapshot name: %s", container.Name()) } cName := fields[0] sName := fields[1] destFs := fmt.Sprintf("snapshots/%s/%s", cName, sName) err := s.zfsDestroy(destFs) if err != nil { return err } /* zfs creates this directory on clone (start), so we need to clean it * up on stop */ return os.RemoveAll(container.Path()) } func (s *storageZfs) ContainerSnapshotCreateEmpty(snapshotContainer container) error { /* don't touch the fs yet, as migration will do that for us */ return nil } func (s *storageZfs) ImageCreate(fingerprint string) error { imagePath := shared.VarPath("images", fingerprint) subvol := fmt.Sprintf("%s.zfs", imagePath) fs := fmt.Sprintf("images/%s", fingerprint) if s.zfsExists(fmt.Sprintf("deleted/%s", fs)) { err := s.zfsRename(fmt.Sprintf("deleted/%s", fs), fs) if err != nil { return err } err = s.zfsSet(fs, "mountpoint", subvol) if err != nil { return err } return nil } err := s.zfsCreate(fs) if err != nil { return err } err = untarImage(imagePath, subvol) if err != nil { return err } err = s.zfsSet(fs, "readonly", "on") if err != nil { return err } err = s.zfsSnapshotCreate(fs, "readonly") if err != nil { return err } return nil } func (s *storageZfs) ImageDelete(fingerprint string) error { fs := fmt.Sprintf("images/%s", fingerprint) removable, err := s.zfsSnapshotRemovable(fs, "readonly") if err != nil { return err } if removable { err := s.zfsDestroy(fs) if err != nil { return err } } else { err := s.zfsSet(fs, "mountpoint", "none") if err != nil { return err } err = s.zfsRename(fs, fmt.Sprintf("deleted/%s", fs)) if err != nil { return err } } if shared.PathExists(shared.VarPath(fs + ".zfs")) { os.Remove(shared.VarPath(fs + ".zfs")) } return nil } // Helper functions func (s *storageZfs) zfsCheckPool(pool string) error { output, err := exec.Command( "zfs", "get", "type", "-H", "-o", "value", pool).CombinedOutput() if err != nil { return fmt.Errorf(strings.Split(string(output), "\n")[0]) } poolType := strings.Split(string(output), "\n")[0] if poolType != "filesystem" { return fmt.Errorf("Unsupported pool type: %s", poolType) } return nil } func (s *storageZfs) zfsClone(source string, name string, dest string, dotZfs bool) error { var mountpoint string mountpoint = shared.VarPath(dest) if dotZfs { mountpoint += ".zfs" } output, err := exec.Command( "zfs", "clone", "-p", "-o", fmt.Sprintf("mountpoint=%s", mountpoint), fmt.Sprintf("%s/%s@%s", s.zfsPool, source, name), fmt.Sprintf("%s/%s", s.zfsPool, dest)).CombinedOutput() if err != nil { s.log.Error("zfs clone failed", log.Ctx{"output": string(output)}) return fmt.Errorf("Failed to clone the filesystem: %s", output) } subvols, err := s.zfsListSubvolumes(source) if err != nil { return err } for _, sub := range subvols { snaps, err := s.zfsListSnapshots(sub) if err != nil { return err } if !shared.StringInSlice(name, snaps) { continue } destSubvol := dest + strings.TrimPrefix(sub, source) mountpoint = shared.VarPath(destSubvol) if dotZfs { mountpoint += ".zfs" } output, err := exec.Command( "zfs", "clone", "-p", "-o", fmt.Sprintf("mountpoint=%s", mountpoint), fmt.Sprintf("%s/%s@%s", s.zfsPool, sub, name), fmt.Sprintf("%s/%s", s.zfsPool, destSubvol)).CombinedOutput() if err != nil { s.log.Error("zfs clone failed", log.Ctx{"output": string(output)}) return fmt.Errorf("Failed to clone the sub-volume: %s", output) } } return nil } func (s *storageZfs) zfsCreate(path string) error { output, err := exec.Command( "zfs", "create", "-p", "-o", fmt.Sprintf("mountpoint=%s.zfs", shared.VarPath(path)), fmt.Sprintf("%s/%s", s.zfsPool, path)).CombinedOutput() if err != nil { s.log.Error("zfs create failed", log.Ctx{"output": string(output)}) return fmt.Errorf("Failed to create ZFS filesystem: %s", output) } return nil } func (s *storageZfs) zfsDestroy(path string) error { mountpoint, err := s.zfsGet(path, "mountpoint") if err != nil { return err } if mountpoint != "none" && shared.IsMountPoint(mountpoint) { err := syscall.Unmount(mountpoint, syscall.MNT_DETACH) if err != nil { s.log.Error("umount failed", log.Ctx{"err": err}) return err } } // Due to open fds or kernel refs, this may fail for a bit, give it 10s output, err := tryExec( "zfs", "destroy", "-r", fmt.Sprintf("%s/%s", s.zfsPool, path)) if err != nil { s.log.Error("zfs destroy failed", log.Ctx{"output": string(output)}) return fmt.Errorf("Failed to destroy ZFS filesystem: %s", output) } return nil } func (s *storageZfs) zfsCleanup(path string) error { if strings.HasPrefix(path, "deleted/") { removablePath, err := s.zfsSnapshotRemovable(path, "") if err != nil { return err } if removablePath { subPath := strings.SplitN(path, "@", 2)[0] origin, err := s.zfsGet(subPath, "origin") if err != nil { return err } origin = strings.TrimPrefix(origin, fmt.Sprintf("%s/", s.zfsPool)) err = s.zfsDestroy(subPath) if err != nil { return err } s.zfsCleanup(origin) return nil } } return nil } func (s *storageZfs) zfsExists(path string) bool { output, _ := s.zfsGet(path, "name") if output == fmt.Sprintf("%s/%s", s.zfsPool, path) { return true } return false } func (s *storageZfs) zfsGet(path string, key string) (string, error) { output, err := exec.Command( "zfs", "get", "-H", "-p", "-o", "value", key, fmt.Sprintf("%s/%s", s.zfsPool, path)).CombinedOutput() if err != nil { return string(output), fmt.Errorf("Failed to get ZFS config: %s", output) } return strings.TrimRight(string(output), "\n"), nil } func (s *storageZfs) zfsRename(source string, dest string) error { output, err := tryExec( "zfs", "rename", "-p", fmt.Sprintf("%s/%s", s.zfsPool, source), fmt.Sprintf("%s/%s", s.zfsPool, dest)) if err != nil { if s.zfsExists(source) || !s.zfsExists(dest) { s.log.Error("zfs rename failed", log.Ctx{"output": string(output)}) return fmt.Errorf("Failed to rename ZFS filesystem: %s", output) } } return nil } func (s *storageZfs) zfsSet(path string, key string, value string) error { output, err := exec.Command( "zfs", "set", fmt.Sprintf("%s=%s", key, value), fmt.Sprintf("%s/%s", s.zfsPool, path)).CombinedOutput() if err != nil { s.log.Error("zfs set failed", log.Ctx{"output": string(output)}) return fmt.Errorf("Failed to set ZFS config: %s", output) } return nil } func (s *storageZfs) zfsSnapshotCreate(path string, name string) error { output, err := exec.Command( "zfs", "snapshot", "-r", fmt.Sprintf("%s/%s@%s", s.zfsPool, path, name)).CombinedOutput() if err != nil { s.log.Error("zfs snapshot failed", log.Ctx{"output": string(output)}) return fmt.Errorf("Failed to create ZFS snapshot: %s", output) } return nil } func (s *storageZfs) zfsSnapshotDestroy(path string, name string) error { output, err := exec.Command( "zfs", "destroy", "-r", fmt.Sprintf("%s/%s@%s", s.zfsPool, path, name)).CombinedOutput() if err != nil { s.log.Error("zfs destroy failed", log.Ctx{"output": string(output)}) return fmt.Errorf("Failed to destroy ZFS snapshot: %s", output) } return nil } func (s *storageZfs) zfsSnapshotRestore(path string, name string) error { output, err := tryExec( "zfs", "rollback", fmt.Sprintf("%s/%s@%s", s.zfsPool, path, name)) if err != nil { s.log.Error("zfs rollback failed", log.Ctx{"output": string(output)}) return fmt.Errorf("Failed to restore ZFS snapshot: %s", output) } subvols, err := s.zfsListSubvolumes(path) if err != nil { return err } for _, sub := range subvols { snaps, err := s.zfsListSnapshots(sub) if err != nil { return err } if !shared.StringInSlice(name, snaps) { continue } output, err := tryExec( "zfs", "rollback", fmt.Sprintf("%s/%s@%s", s.zfsPool, sub, name)) if err != nil { s.log.Error("zfs rollback failed", log.Ctx{"output": string(output)}) return fmt.Errorf("Failed to restore ZFS sub-volume snapshot: %s", output) } } return nil } func (s *storageZfs) zfsSnapshotRename(path string, oldName string, newName string) error { output, err := exec.Command( "zfs", "rename", "-r", fmt.Sprintf("%s/%s@%s", s.zfsPool, path, oldName), fmt.Sprintf("%s/%s@%s", s.zfsPool, path, newName)).CombinedOutput() if err != nil { s.log.Error("zfs snapshot rename failed", log.Ctx{"output": string(output)}) return fmt.Errorf("Failed to rename ZFS snapshot: %s", output) } return nil } func (s *storageZfs) zfsMount(path string) error { output, err := tryExec( "zfs", "mount", fmt.Sprintf("%s/%s", s.zfsPool, path)) if err != nil { s.log.Error("zfs mount failed", log.Ctx{"output": string(output)}) return fmt.Errorf("Failed to mount ZFS filesystem: %s", output) } return nil } func (s *storageZfs) zfsUnmount(path string) error { output, err := tryExec( "zfs", "unmount", fmt.Sprintf("%s/%s", s.zfsPool, path)) if err != nil { s.log.Error("zfs unmount failed", log.Ctx{"output": string(output)}) return fmt.Errorf("Failed to unmount ZFS filesystem: %s", output) } return nil } func (s *storageZfs) zfsListSubvolumes(path string) ([]string, error) { path = strings.TrimRight(path, "/") fullPath := s.zfsPool if path != "" { fullPath = fmt.Sprintf("%s/%s", s.zfsPool, path) } output, err := exec.Command( "zfs", "list", "-t", "filesystem", "-o", "name", "-H", "-r", fullPath).CombinedOutput() if err != nil { s.log.Error("zfs list failed", log.Ctx{"output": string(output)}) return []string{}, fmt.Errorf("Failed to list ZFS filesystems: %s", output) } children := []string{} for _, entry := range strings.Split(string(output), "\n") { if entry == "" { continue } if entry == fullPath { continue } children = append(children, strings.TrimPrefix(entry, fmt.Sprintf("%s/", s.zfsPool))) } return children, nil } func (s *storageZfs) zfsListSnapshots(path string) ([]string, error) { path = strings.TrimRight(path, "/") fullPath := s.zfsPool if path != "" { fullPath = fmt.Sprintf("%s/%s", s.zfsPool, path) } output, err := exec.Command( "zfs", "list", "-t", "snapshot", "-o", "name", "-H", "-d", "1", "-s", "creation", "-r", fullPath).CombinedOutput() if err != nil { s.log.Error("zfs list failed", log.Ctx{"output": string(output)}) return []string{}, fmt.Errorf("Failed to list ZFS snapshots: %s", output) } children := []string{} for _, entry := range strings.Split(string(output), "\n") { if entry == "" { continue } if entry == fullPath { continue } children = append(children, strings.SplitN(entry, "@", 2)[1]) } return children, nil } func (s *storageZfs) zfsSnapshotRemovable(path string, name string) (bool, error) { var snap string if name == "" { snap = path } else { snap = fmt.Sprintf("%s@%s", path, name) } clones, err := s.zfsGet(snap, "clones") if err != nil { return false, err } if clones == "-" || clones == "" { return true, nil } return false, nil } func (s *storageZfs) zfsGetPoolUsers() ([]string, error) { subvols, err := s.zfsListSubvolumes("") if err != nil { return []string{}, err } exceptions := []string{ "containers", "images", "snapshots", "deleted", "deleted/containers", "deleted/images"} users := []string{} for _, subvol := range subvols { path := strings.Split(subvol, "/") // Only care about plausible LXD paths if !shared.StringInSlice(path[0], exceptions) { continue } // Ignore empty paths if shared.StringInSlice(subvol, exceptions) { continue } users = append(users, subvol) } return users, nil } // Global functions func storageZFSSetPoolNameConfig(d *Daemon, poolname string) error { s := storageZfs{} // Confirm the backend is working err := s.initShared() if err != nil { return fmt.Errorf("Unable to initialize the ZFS backend: %v", err) } // Confirm the new pool exists and is compatible if poolname != "" { err = s.zfsCheckPool(poolname) if err != nil { return fmt.Errorf("Invalid ZFS pool: %v", err) } } // Check if we're switching pools oldPoolname, err := d.ConfigValueGet("storage.zfs_pool_name") if err != nil { return err } // Confirm the old pool isn't in use anymore if oldPoolname != "" { s.zfsPool = oldPoolname users, err := s.zfsGetPoolUsers() if err != nil { return fmt.Errorf("Error checking if a pool is already in use: %v", err) } if len(users) > 0 { return fmt.Errorf("Can not change ZFS config. Images or containers are still using the ZFS pool: %v", users) } } s.zfsPool = poolname // All good, set the new pool name err = d.ConfigValueSet("storage.zfs_pool_name", poolname) if err != nil { return err } return nil } type zfsMigrationSourceDriver struct { container container snapshots []container zfsSnapshotNames []string zfs *storageZfs runningSnapName string stoppedSnapName string } func (s *zfsMigrationSourceDriver) Snapshots() []container { return s.snapshots } func (s *zfsMigrationSourceDriver) send(conn *websocket.Conn, zfsName string, zfsParent string) error { fields := strings.SplitN(s.container.Name(), shared.SnapshotDelimiter, 2) args := []string{"send", fmt.Sprintf("%s/containers/%s@%s", s.zfs.zfsPool, fields[0], zfsName)} if zfsParent != "" { args = append(args, "-i", fmt.Sprintf("%s/containers/%s@%s", s.zfs.zfsPool, s.container.Name(), zfsParent)) } cmd := exec.Command("zfs", args...) stdout, err := cmd.StdoutPipe() if err != nil { return err } stderr, err := cmd.StderrPipe() if err != nil { return err } if err := cmd.Start(); err != nil { return err } <-shared.WebsocketSendStream(conn, stdout) output, err := ioutil.ReadAll(stderr) if err != nil { shared.Log.Error("problem reading zfs send stderr", "err", err) } err = cmd.Wait() if err != nil { shared.Log.Error("problem with zfs send", "output", string(output)) } return err } func (s *zfsMigrationSourceDriver) SendWhileRunning(conn *websocket.Conn) error { if s.container.IsSnapshot() { fields := strings.SplitN(s.container.Name(), shared.SnapshotDelimiter, 2) snapshotName := fmt.Sprintf("snapshot-%s", fields[1]) return s.send(conn, snapshotName, "") } lastSnap := "" for i, snap := range s.zfsSnapshotNames { prev := "" if i > 0 { prev = s.zfsSnapshotNames[i-1] } lastSnap = snap if err := s.send(conn, snap, prev); err != nil { return err } } s.runningSnapName = fmt.Sprintf("migration-send-%s", uuid.NewRandom().String()) if err := s.zfs.zfsSnapshotCreate(fmt.Sprintf("containers/%s", s.container.Name()), s.runningSnapName); err != nil { return err } if err := s.send(conn, s.runningSnapName, lastSnap); err != nil { return err } return nil } func (s *zfsMigrationSourceDriver) SendAfterCheckpoint(conn *websocket.Conn) error { s.stoppedSnapName = fmt.Sprintf("migration-send-%s", uuid.NewRandom().String()) if err := s.zfs.zfsSnapshotCreate(fmt.Sprintf("containers/%s", s.container.Name()), s.stoppedSnapName); err != nil { return err } if err := s.send(conn, s.stoppedSnapName, s.runningSnapName); err != nil { return err } return nil } func (s *zfsMigrationSourceDriver) Cleanup() { if s.stoppedSnapName != "" { s.zfs.zfsSnapshotDestroy(fmt.Sprintf("containers/%s", s.container.Name()), s.stoppedSnapName) } if s.runningSnapName != "" { s.zfs.zfsSnapshotDestroy(fmt.Sprintf("containers/%s", s.container.Name()), s.runningSnapName) } } func (s *storageZfs) MigrationType() MigrationFSType { return MigrationFSType_ZFS } func (s *storageZfs) MigrationSource(ct container) (MigrationStorageSourceDriver, error) { /* If the container is a snapshot, let's just send that; we don't need * to send anything else, because that's all the user asked for. */ if ct.IsSnapshot() { return &zfsMigrationSourceDriver{container: ct, zfs: s}, nil } driver := zfsMigrationSourceDriver{ container: ct, snapshots: []container{}, zfsSnapshotNames: []string{}, zfs: s, } /* List all the snapshots in order of reverse creation. The idea here * is that we send the oldest to newest snapshot, hopefully saving on * xfer costs. Then, after all that, we send the container itself. */ snapshots, err := s.zfsListSnapshots(fmt.Sprintf("containers/%s", ct.Name())) if err != nil { return nil, err } for _, snap := range snapshots { /* In the case of e.g. multiple copies running at the same * time, we will have potentially multiple migration-send * snapshots. (Or in the case of the test suite, sometimes one * will take too long to delete.) */ if !strings.HasPrefix(snap, "snapshot-") { continue } lxdName := fmt.Sprintf("%s%s%s", ct.Name(), shared.SnapshotDelimiter, snap[len("snapshot-"):]) snapshot, err := containerLoadByName(s.d, lxdName) if err != nil { return nil, err } driver.snapshots = append(driver.snapshots, snapshot) driver.zfsSnapshotNames = append(driver.zfsSnapshotNames, snap) } return &driver, nil } func (s *storageZfs) MigrationSink(live bool, container container, snapshots []container, conn *websocket.Conn) error { zfsRecv := func(zfsName string) error { zfsFsName := fmt.Sprintf("%s/%s", s.zfsPool, zfsName) args := []string{"receive", "-F", "-u", zfsFsName} cmd := exec.Command("zfs", args...) stdin, err := cmd.StdinPipe() if err != nil { return err } stderr, err := cmd.StderrPipe() if err != nil { return err } if err := cmd.Start(); err != nil { return err } <-shared.WebsocketRecvStream(stdin, conn) output, err := ioutil.ReadAll(stderr) if err != nil { shared.Debugf("problem reading zfs recv stderr %s", "err", err) } err = cmd.Wait() if err != nil { shared.Log.Error("problem with zfs recv", "output", string(output)) } return err } /* In some versions of zfs we can write `zfs recv -F` to mounted * filesystems, and in some versions we can't. So, let's always unmount * this fs (it's empty anyway) before we zfs recv. N.B. that `zfs recv` * of a snapshot also needs tha actual fs that it has snapshotted * unmounted, so we do this before receiving anything. */ zfsName := fmt.Sprintf("containers/%s", container.Name()) err := s.zfsUnmount(zfsName) if err != nil { return err } for _, snap := range snapshots { fields := strings.SplitN(snap.Name(), shared.SnapshotDelimiter, 2) name := fmt.Sprintf("containers/%s@snapshot-%s", fields[0], fields[1]) if err := zfsRecv(name); err != nil { return err } err := os.MkdirAll(shared.VarPath(fmt.Sprintf("snapshots/%s", fields[0])), 0700) if err != nil { return err } err = os.Symlink("on-zfs", shared.VarPath(fmt.Sprintf("snapshots/%s/%s.zfs", fields[0], fields[1]))) if err != nil { return err } } defer func() { /* clean up our migration-send snapshots that we got from recv. */ zfsSnapshots, err := s.zfsListSnapshots(fmt.Sprintf("containers/%s", container.Name())) if err != nil { shared.Log.Error("failed listing snapshots post migration", "err", err) return } for _, snap := range zfsSnapshots { // If we received a bunch of snapshots, remove the migration-send-* ones, if not, wipe any snapshot we got if snapshots != nil && len(snapshots) > 0 && !strings.HasPrefix(snap, "migration-send") { continue } s.zfsSnapshotDestroy(fmt.Sprintf("containers/%s", container.Name()), snap) } }() /* finally, do the real container */ if err := zfsRecv(zfsName); err != nil { return err } if live { /* and again for the post-running snapshot if this was a live migration */ if err := zfsRecv(zfsName); err != nil { return err } } /* Sometimes, zfs recv mounts this anyway, even if we pass -u * (https://forums.freebsd.org/threads/zfs-receive-u-shouldnt-mount-received-filesystem-right.36844/) * but sometimes it doesn't. Let's try to mount, but not complain about * failure. */ s.zfsMount(zfsName) return nil } lxd-2.0.0/lxd/util.go000066400000000000000000000006521270277227600144120ustar00rootroot00000000000000package main import ( "bytes" "encoding/json" "io" "net/http" "github.com/lxc/lxd/shared" ) func WriteJSON(w http.ResponseWriter, body interface{}) error { var output io.Writer var captured *bytes.Buffer output = w if debug { captured = &bytes.Buffer{} output = io.MultiWriter(w, captured) } err := json.NewEncoder(output).Encode(body) if captured != nil { shared.DebugJson(captured) } return err } lxd-2.0.0/po/000077500000000000000000000000001270277227600127325ustar00rootroot00000000000000lxd-2.0.0/po/de.po000066400000000000000000001360711270277227600136720ustar00rootroot00000000000000# German translation for LXD # Copyright (C) 2015 - LXD contributors # This file is distributed under the same license as LXD. # Felix Engelmann , 2015. # msgid "" msgstr "" "Project-Id-Version: LXD\n" "Report-Msgid-Bugs-To: lxc-devel@lists.linuxcontainers.org\n" "POT-Creation-Date: 2016-04-11 15:01-0400\n" "PO-Revision-Date: 2015-06-13 06:10+0200\n" "Last-Translator: Felix Engelmann \n" "Language-Team: \n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: lxc/info.go:140 msgid " Disk usage:" msgstr "" #: lxc/info.go:163 msgid " Memory usage:" msgstr "" #: lxc/info.go:180 msgid " Network usage:" msgstr "" #: lxc/config.go:37 #, fuzzy msgid "" "### This is a yaml representation of the configuration.\n" "### Any line starting with a '# will be ignored.\n" "###\n" "### A sample configuration looks like:\n" "### name: container1\n" "### profiles:\n" "### - default\n" "### config:\n" "### volatile.eth0.hwaddr: 00:16:3e:e9:f8:7f\n" "### devices:\n" "### homedir:\n" "### path: /extra\n" "### source: /home/user\n" "### type: disk\n" "### ephemeral: false\n" "###\n" "### Note that the name is shown but cannot be changed" msgstr "" "### Dies ist eine Darstellung der Konfiguration in yaml.\n" "### Jede Zeile die mit '# beginnt wird ignoriert.\n" "###\n" "### Beispiel einer Konfiguration:\n" "### name: container1\n" "### profiles:\n" "### - default\n" "### config:\n" "### volatile.eth0.hwaddr: 00:16:3e:e9:f8:7f\n" "### devices:\n" "### homedir:\n" "### path: /extra\n" "### source: /home/user\n" "### type: disk\n" "### ephemeral: false\n" "###\n" "### Der Name wird zwar angezeigt, lässt sich jedoch nicht ändern.\n" #: lxc/image.go:83 #, fuzzy msgid "" "### This is a yaml representation of the image properties.\n" "### Any line starting with a '# will be ignored.\n" "###\n" "### Each property is represented by a single line:\n" "### An example would be:\n" "### description: My custom image" msgstr "" "### Dies ist eine Darstellung der Eigenschaften eines Abbildes in yaml.\n" "### Jede Zeile die mit '# beginnt wird ignoriert.\n" "###\n" "### Pro Eigenschaft wird eine Zeile verwendet:\n" "### Zum Beispiel:\n" "### description: Mein eigenes Abbild\n" #: lxc/profile.go:27 #, fuzzy msgid "" "### This is a yaml representation of the profile.\n" "### Any line starting with a '# will be ignored.\n" "###\n" "### A profile consists of a set of configuration items followed by a set of\n" "### devices.\n" "###\n" "### An example would look like:\n" "### name: onenic\n" "### config:\n" "### raw.lxc: lxc.aa_profile=unconfined\n" "### devices:\n" "### eth0:\n" "### nictype: bridged\n" "### parent: lxdbr0\n" "### type: nic\n" "###\n" "### Note that the name is shown but cannot be changed" msgstr "" "### Dies ist eine Darstellung eines Profils in yaml.\n" "### Jede Zeile die mit '# beginnt wird ignoriert.\n" "###\n" "### Ein Profil besteht aus mehreren Konfigurationselementen gefolgt von\n" "### mehrere Geräten.\n" "###\n" "### Zum Beispiel:\n" "### name: onenic\n" "### config:\n" "### raw.lxc: lxc.aa_profile=unconfined\n" "### devices:\n" "### eth0:\n" "### nictype: bridged\n" "### parent: lxdbr0\n" "### type: nic\n" "###\n" "### Der Name wird zwar angezeigt, lässt sich jedoch nicht ändern.\n" #: lxc/image.go:583 #, c-format msgid "%s (%d more)" msgstr "" #: lxc/snapshot.go:61 #, fuzzy msgid "'/' not allowed in snapshot name" msgstr "'/' ist kein gültiges Zeichen im Namen eines Sicherungspunktes\n" #: lxc/profile.go:226 msgid "(none)" msgstr "" #: lxc/image.go:604 lxc/image.go:633 msgid "ALIAS" msgstr "" #: lxc/image.go:608 msgid "ARCH" msgstr "" #: lxc/list.go:367 msgid "ARCHITECTURE" msgstr "" #: lxc/remote.go:53 msgid "Accept certificate" msgstr "Akzeptiere Zertifikat" #: lxc/remote.go:256 #, c-format msgid "Admin password for %s: " msgstr "Administrator Passwort für %s: " #: lxc/image.go:347 #, fuzzy msgid "Aliases:" msgstr "Aliasse:\n" #: lxc/exec.go:54 msgid "An environment variable of the form HOME=/home/foo" msgstr "" #: lxc/image.go:330 lxc/info.go:90 #, fuzzy, c-format msgid "Architecture: %s" msgstr "Architektur: %s\n" #: lxc/image.go:351 #, c-format msgid "Auto update: %s" msgstr "" #: lxc/help.go:49 msgid "Available commands:" msgstr "" #: lxc/info.go:172 msgid "Bytes received" msgstr "" #: lxc/info.go:173 msgid "Bytes sent" msgstr "" #: lxc/config.go:270 msgid "COMMON NAME" msgstr "" #: lxc/list.go:368 msgid "CREATED AT" msgstr "" #: lxc/config.go:114 #, c-format msgid "Can't read from stdin: %s" msgstr "" #: lxc/config.go:127 lxc/config.go:160 lxc/config.go:182 #, c-format msgid "Can't unset key '%s', it's not currently set." msgstr "" #: lxc/profile.go:343 msgid "Cannot provide container name to list" msgstr "" #: lxc/remote.go:206 #, fuzzy, c-format msgid "Certificate fingerprint: %x" msgstr "Fingerabdruck des Zertifikats: % x\n" #: lxc/action.go:28 #, fuzzy, c-format msgid "" "Changes state of one or more containers to %s.\n" "\n" "lxc %s [...]" msgstr "" "Ändert den Laufzustand eines Containers in %s.\n" "\n" "lxd %s \n" #: lxc/remote.go:279 msgid "Client certificate stored at server: " msgstr "Gespeichertes Nutzerzertifikat auf dem Server: " #: lxc/list.go:97 lxc/list.go:98 msgid "Columns" msgstr "" #: lxc/init.go:134 lxc/init.go:135 lxc/launch.go:40 lxc/launch.go:41 #, fuzzy msgid "Config key/value to apply to the new container" msgstr "kann nicht zum selben Container Namen kopieren" #: lxc/config.go:500 lxc/config.go:565 lxc/image.go:687 lxc/profile.go:190 #, fuzzy, c-format msgid "Config parsing error: %s" msgstr "YAML Analyse Fehler %v\n" #: lxc/main.go:37 msgid "Connection refused; is LXD running?" msgstr "" #: lxc/publish.go:59 msgid "Container name is mandatory" msgstr "" #: lxc/init.go:209 #, c-format msgid "Container name is: %s" msgstr "" #: lxc/publish.go:141 lxc/publish.go:156 #, fuzzy, c-format msgid "Container published with fingerprint: %s" msgstr "Abbild mit Fingerabdruck %s importiert\n" #: lxc/image.go:155 msgid "Copy aliases from source" msgstr "Kopiere Aliasse von der Quelle" #: lxc/copy.go:22 #, fuzzy msgid "" "Copy containers within or in between lxd instances.\n" "\n" "lxc copy [remote:] [remote:] [--" "ephemeral|e]" msgstr "" "Kopiert Container innerhalb einer oder zwischen lxd Instanzen\n" "\n" "lxc copy \n" #: lxc/image.go:268 #, c-format msgid "Copying the image: %s" msgstr "" #: lxc/remote.go:221 msgid "Could not create server cert dir" msgstr "Kann Verzeichnis für Zertifikate auf dem Server nicht erstellen" #: lxc/snapshot.go:21 msgid "" "Create a read-only snapshot of a container.\n" "\n" "lxc snapshot [remote:] [--stateful]\n" "\n" "Creates a snapshot of the container (optionally with the container's memory\n" "state). When --stateful is used, LXD attempts to checkpoint the container's\n" "running state, including process memory state, TCP connections, etc. so that " "it\n" "can be restored (via lxc restore) at a later time (although some things, e." "g.\n" "TCP connections after the TCP timeout window has expired, may not be " "restored\n" "successfully).\n" "\n" "Example:\n" "lxc snapshot u1 snap0" msgstr "" #: lxc/image.go:335 lxc/info.go:92 #, c-format msgid "Created: %s" msgstr "" #: lxc/init.go:177 lxc/launch.go:116 #, c-format msgid "Creating %s" msgstr "" #: lxc/init.go:175 #, fuzzy msgid "Creating the container" msgstr "kann nicht zum selben Container Namen kopieren" #: lxc/image.go:607 lxc/image.go:635 msgid "DESCRIPTION" msgstr "" #: lxc/delete.go:25 #, fuzzy msgid "" "Delete containers or container snapshots.\n" "\n" "lxc delete [remote:][/] [remote:][[/" "]...]\n" "\n" "Destroy containers or snapshots with any attached data (configuration, " "snapshots, ...)." msgstr "" "Löscht einen Container oder Container Sicherungspunkt.\n" "\n" "Entfernt einen Container (oder Sicherungspunkt) und alle dazugehörigen\n" "Daten (Konfiguration, Sicherungspunkte, ...).\n" #: lxc/config.go:617 #, fuzzy, c-format msgid "Device %s added to %s" msgstr "Gerät %s wurde zu %s hinzugefügt\n" #: lxc/config.go:804 #, fuzzy, c-format msgid "Device %s removed from %s" msgstr "Gerät %s wurde von %s entfernt\n" #: lxc/list.go:451 msgid "EPHEMERAL" msgstr "" #: lxc/config.go:272 msgid "EXPIRY DATE" msgstr "" #: lxc/main.go:55 msgid "Enables debug mode." msgstr "Aktiviert Debug Modus" #: lxc/main.go:54 msgid "Enables verbose mode." msgstr "Aktiviert ausführliche Ausgabe" #: lxc/help.go:68 msgid "Environment:" msgstr "" #: lxc/copy.go:29 lxc/copy.go:30 lxc/init.go:138 lxc/init.go:139 #: lxc/launch.go:44 lxc/launch.go:45 msgid "Ephemeral container" msgstr "Flüchtiger Container" #: lxc/monitor.go:56 msgid "Event type to listen for" msgstr "" #: lxc/exec.go:45 #, fuzzy msgid "" "Execute the specified command in a container.\n" "\n" "lxc exec [remote:]container [--mode=auto|interactive|non-interactive] [--env " "EDITOR=/usr/bin/vim]... \n" "\n" "Mode defaults to non-interactive, interactive mode is selected if both stdin " "AND stdout are terminals (stderr is ignored)." msgstr "" "Führt den angegebenen Befehl in einem Container aus.\n" "\n" "lxc exec [--env EDITOR=/usr/bin/vim]... \n" #: lxc/image.go:339 #, c-format msgid "Expires: %s" msgstr "" #: lxc/image.go:341 msgid "Expires: never" msgstr "" #: lxc/config.go:269 lxc/image.go:605 lxc/image.go:634 msgid "FINGERPRINT" msgstr "" #: lxc/list.go:100 msgid "Fast mode (same as --columns=nsacPt" msgstr "" #: lxc/image.go:328 #, fuzzy, c-format msgid "Fingerprint: %s" msgstr "Fingerabdruck: %s\n" #: lxc/finger.go:17 #, fuzzy msgid "" "Fingers the LXD instance to check if it is up and working.\n" "\n" "lxc finger " msgstr "" "Fingert die LXD Instanz zum überprüfen ob diese funktionsfähig ist.\n" "\n" "lxc finger \n" #: lxc/action.go:37 msgid "Force the container to shutdown." msgstr "Herunterfahren des Containers erzwingen." #: lxc/delete.go:34 lxc/delete.go:35 msgid "Force the removal of stopped containers." msgstr "" #: lxc/main.go:56 msgid "Force using the local unix socket." msgstr "" #: lxc/list.go:99 msgid "Format" msgstr "" #: lxc/main.go:138 #, fuzzy msgid "Generating a client certificate. This may take a minute..." msgstr "Generiere Nutzerzertifikat. Dies kann wenige Minuten dauern...\n" #: lxc/list.go:365 msgid "IPV4" msgstr "" #: lxc/list.go:366 msgid "IPV6" msgstr "" #: lxc/config.go:271 msgid "ISSUE DATE" msgstr "" #: lxc/main.go:146 msgid "" "If this is your first time using LXD, you should also run: sudo lxd init" msgstr "" #: lxc/main.go:57 msgid "Ignore aliases when determining what command to run." msgstr "" #: lxc/action.go:39 #, fuzzy msgid "Ignore the container state (only forstart)." msgstr "Herunterfahren des Containers erzwingen." #: lxc/image.go:273 msgid "Image copied successfully!" msgstr "" #: lxc/image.go:419 #, fuzzy, c-format msgid "Image imported with fingerprint: %s" msgstr "Abbild mit Fingerabdruck %s importiert\n" #: lxc/init.go:73 #, fuzzy msgid "" "Initialize a container from a particular image.\n" "\n" "lxc init [remote:] [remote:][] [--ephemeral|-e] [--profile|-p " "...] [--config|-c ...]\n" "\n" "Initializes a container using the specified image and name.\n" "\n" "Not specifying -p will result in the default profile.\n" "Specifying \"-p\" with no argument will result in no profile.\n" "\n" "Example:\n" "lxc init ubuntu u1" msgstr "" "Starte Container von gegebenem Abbild.\n" "\n" "lxc launch [] [—ephemeral|-e] [—profile|-p …]\n" "\n" "Startet einen Container von gegebenem Abbild und mit Namen\n" "\n" "Ohne den -p Parameter wird das default Profil benutzt.\n" "Wird -p ohne Argument angegeben, wird kein Profil verwendet\n" "\n" "Beispiel:\n" "lxc launch ubuntu u1\n" #: lxc/remote.go:122 #, c-format msgid "Invalid URL scheme \"%s\" in \"%s\"" msgstr "" #: lxc/init.go:30 lxc/init.go:35 msgid "Invalid configuration key" msgstr "" #: lxc/file.go:190 #, c-format msgid "Invalid source %s" msgstr "Ungültige Quelle %s" #: lxc/file.go:57 #, c-format msgid "Invalid target %s" msgstr "Ungültiges Ziel %s" #: lxc/info.go:121 msgid "Ips:" msgstr "" #: lxc/image.go:156 msgid "Keep the image up to date after initial copy" msgstr "" #: lxc/main.go:35 msgid "LXD socket not found; is LXD running?" msgstr "" #: lxc/launch.go:22 #, fuzzy msgid "" "Launch a container from a particular image.\n" "\n" "lxc launch [remote:] [remote:][] [--ephemeral|-e] [--profile|-p " "...] [--config|-c ...]\n" "\n" "Launches a container using the specified image and name.\n" "\n" "Not specifying -p will result in the default profile.\n" "Specifying \"-p\" with no argument will result in no profile.\n" "\n" "Example:\n" "lxc launch ubuntu u1" msgstr "" "Starte Container von gegebenem Abbild.\n" "\n" "lxc launch [] [—ephemeral|-e] [—profile|-p …]\n" "\n" "Startet einen Container von gegebenem Abbild und mit Namen\n" "\n" "Ohne den -p Parameter wird das default Profil benutzt.\n" "Wird -p ohne Argument angegeben, wird kein Profil verwendet\n" "\n" "Beispiel:\n" "lxc launch ubuntu u1\n" #: lxc/info.go:25 #, fuzzy msgid "" "List information on LXD servers and containers.\n" "\n" "For a container:\n" " lxc info [:]container [--show-log]\n" "\n" "For a server:\n" " lxc info [:]" msgstr "" "Listet Informationen über Container.\n" "\n" "Dies wird entfernte Instanzen und Abbilder unterstützen, \n" "zur Zeit jedoch nur Container.\n" "\n" "lxc info [:]Container [--show-log]\n" #: lxc/list.go:67 #, fuzzy msgid "" "Lists the available resources.\n" "\n" "lxc list [resource] [filters] [--format table|json] [-c columns] [--fast]\n" "\n" "The filters are:\n" "* A single keyword like \"web\" which will list any container with \"web\" " "in its name.\n" "* A key/value pair referring to a configuration item. For those, the " "namespace can be abreviated to the smallest unambiguous identifier:\n" "* \"user.blah=abc\" will list all containers with the \"blah\" user property " "set to \"abc\"\n" "* \"u.blah=abc\" will do the same\n" "* \"security.privileged=1\" will list all privileged containers\n" "* \"s.privileged=1\" will do the same\n" "\n" "Columns for table format are:\n" "* 4 - IPv4 address\n" "* 6 - IPv6 address\n" "* a - architecture\n" "* c - creation date\n" "* n - name\n" "* p - pid of container init process\n" "* P - profiles\n" "* s - state\n" "* S - number of snapshots\n" "* t - type (persistent or ephemeral)\n" "\n" "Default column layout: ns46tS\n" "Fast column layout: nsacPt" msgstr "" "Listet vorhandene Ressourcen.\n" "\n" "lxc list [Resource] [Filter]\n" "\n" "Filter sind:\n" "* Ein einzelnes Schlüsselwort wie \"web“, was alle Container mit \"web\" im " "Namen listet.\n" "* Ein key/value Paar bezüglich eines Konfigurationsparameters. Dafür kann " "der Namensraum, solange eindeutig, abgekürzt werden:\n" "* \"user.blah=abc\" listet alle Container mit der \"blah\" Benutzer " "Eigenschaft \"abc\"\n" "* \"u.blah=abc\" ebenfalls\n" "* \"security.privileged=1\" listet alle privilegierten Container\n" "* \"s.privileged=1\" ebenfalls\n" #: lxc/info.go:225 msgid "Log:" msgstr "" #: lxc/image.go:154 msgid "Make image public" msgstr "Veröffentliche Abbild" #: lxc/publish.go:32 #, fuzzy msgid "Make the image public" msgstr "Veröffentliche Abbild" #: lxc/profile.go:48 #, fuzzy msgid "" "Manage configuration profiles.\n" "\n" "lxc profile list [filters] List available profiles.\n" "lxc profile show Show details of a profile.\n" "lxc profile create Create a profile.\n" "lxc profile copy Copy the profile to the " "specified remote.\n" "lxc profile get Get profile configuration.\n" "lxc profile set Set profile configuration.\n" "lxc profile delete Delete a profile.\n" "lxc profile edit \n" " Edit profile, either by launching external editor or reading STDIN.\n" " Example: lxc profile edit # launch editor\n" " cat profile.yml | lxc profile edit # read from " "profile.yml\n" "lxc profile apply \n" " Apply a comma-separated list of profiles to a container, in order.\n" " All profiles passed in this call (and only those) will be applied\n" " to the specified container.\n" " Example: lxc profile apply foo default,bar # Apply default and bar\n" " lxc profile apply foo default # Only default is active\n" " lxc profile apply '' # no profiles are applied anymore\n" " lxc profile apply bar,default # Apply default second now\n" "\n" "Devices:\n" "lxc profile device list List " "devices in the given profile.\n" "lxc profile device show Show " "full device details in the given profile.\n" "lxc profile device remove Remove a " "device from a profile.\n" "lxc profile device get <[remote:]profile> Get a " "device property.\n" "lxc profile device set <[remote:]profile> Set a " "device property.\n" "lxc profile device unset <[remote:]profile> Unset a " "device property.\n" "lxc profile device add " "[key=value]...\n" " Add a profile device, such as a disk or a nic, to the containers\n" " using the specified profile." msgstr "" "Verwalte Konfigurationsprofile.\n" "\n" "lxc profile list [Filter] Listet verfügbare Profile\n" "lxc profile show Zeigt Details zu einem Profil\n" "lxc profile create Erstellt ein Profil\n" "lxc profile edit Bearbeitet das Profil in " "externem Editor\n" "lxc profile copy Kopiert das Profil zur " "entfernten Instanz\n" "lxc profile set Setzt eine " "Profilkonfiguration\n" "lxc profile delete Löscht ein Profil\n" "lxc profile apply \n" " Wendet eine durch Kommata getrennte Liste von Profilen,\n" " in gegeben Reihenfolge, auf einen Container an.\n" " Alle angegeben, und nur diese, werden auf den Container angewandt.\n" " Beispiel: lxc profile apply foo default,bar # Wende default und bar an\n" " lxc profile apply foo default # Nur default ist aktiv\n" " lxc profile apply '' # keine Profile werden angewandt\n" " lxc profile apply bar,default # Wende nun default als zweites " "an\n" "\n" "Geräte:\n" "lxc profile device list Listet Geräte im Profil\n" "lxc profile device show Zeigt alle Geräte Details im " "gegebenen Profil.\n" "lxc profile device remove Entfernt ein Gerät von dem " "Profil.\n" "lxc profile device add " "[key=value]...\n" " Fügt ein Gerät, wie zum Beispiel eine Festplatte oder Netzwerkkarte, den " "Containern hinzu,\n" " die dieses Profil verwenden.\n" #: lxc/config.go:58 #, fuzzy msgid "" "Manage configuration.\n" "\n" "lxc config device add <[remote:]container> [key=value]... " "Add a device to a container.\n" "lxc config device get <[remote:]container> " "Get a device property.\n" "lxc config device set <[remote:]container> " "Set a device property.\n" "lxc config device unset <[remote:]container> " "Unset a device property.\n" "lxc config device list <[remote:]container> " "List devices for container.\n" "lxc config device show <[remote:]container> " "Show full device details for container.\n" "lxc config device remove <[remote:]container> " "Remove device from container.\n" "\n" "lxc config get [remote:][container] " "Get container or server configuration key.\n" "lxc config set [remote:][container] " "Set container or server configuration key.\n" "lxc config unset [remote:][container] " "Unset container or server configuration key.\n" "lxc config show [remote:][container] [--expanded] " "Show container or server configuration.\n" "lxc config edit [remote:][container] " "Edit container or server configuration in external editor.\n" " Edit configuration, either by launching external editor or reading " "STDIN.\n" " Example: lxc config edit # launch editor\n" " cat config.yml | lxc config edit # read from config." "yml\n" "\n" "lxc config trust list [remote] " "List all trusted certs.\n" "lxc config trust add [remote] " "Add certfile.crt to trusted hosts.\n" "lxc config trust remove [remote] [hostname|fingerprint] " "Remove the cert from trusted hosts.\n" "\n" "Examples:\n" "To mount host's /share/c1 onto /opt in the container:\n" " lxc config device add [remote:]container1 disk source=/" "share/c1 path=opt\n" "\n" "To set an lxc config value:\n" " lxc config set [remote:] raw.lxc 'lxc.aa_allow_incomplete = " "1'\n" "\n" "To listen on IPv4 and IPv6 port 8443 (you can omit the 8443 its the " "default):\n" " lxc config set core.https_address [::]:8443\n" "\n" "To set the server trust password:\n" " lxc config set core.trust_password blah" msgstr "" "Verwalte Konfiguration.\n" "\n" "lxc config device add [key=value]...\n" " Füge ein Gerät zu einem Container hinzu\n" "lxc config device list Listet die Geräte des " "Containers\n" "lxc config device show Zeigt alle Geräte " "Details für den Container\n" "lxc config device remove Entfernt Gerät vom " "Container\n" "lxc config edit Bearbeite Container " "Konfiguration in externem Editor\n" "lxc config get key Holt " "Konfigurationsschlüssel\n" "lxc config set key [value] Setzt Container " "Konfigurationsschlüssel\n" "lxc config show Zeigt Konfiguration " "des Containers\n" "lxc config trust list [remote] Liste alle " "vertrauenswürdigen Zertifikate.\n" "lxc config trust add [remote] [certfile.crt] Füge certfile.crt zu " "vertrauenden Instanzen hinzu.\n" "lxc config trust remove [remote] [hostname|fingerprint]\n" " Löscht das Zertifikat aus der Liste der vertrauenswürdigen.\n" "\n" "Beispiele:\n" "Zum mounten von /share/c1 des Hosts nach /opt im Container:\n" "\tlxc config device add container1 mntdir disk source=/share/c1 path=opt\n" "Um einen lxc config Wert zu setzen:\n" "\tlxc config set raw.lxc 'lxc.aa_allow_incomplete = 1'\n" "Um das Server Passwort zur authentifizierung zu setzen:\n" "\tlxc config set core.trust_password blah\n" #: lxc/file.go:32 #, fuzzy msgid "" "Manage files on a container.\n" "\n" "lxc file pull [...] \n" "lxc file push [--uid=UID] [--gid=GID] [--mode=MODE] [...] " "\n" "lxc file edit \n" "\n" " in the case of pull, in the case of push and in the " "case of edit are /" msgstr "" "Verwaltet Dateien in einem Container.\n" "\n" "lxc file pull [...] \n" "lxc file push [--uid=UID] [--gid=GID] [--mode=MODE] [...] " "\n" "\n" " bei pull und bei push sind jeweils von der Form /\n" #: lxc/remote.go:39 #, fuzzy msgid "" "Manage remote LXD servers.\n" "\n" "lxc remote add [--accept-certificate] [--password=PASSWORD]\n" " [--public] [--protocol=PROTOCOL] " "Add the remote at .\n" "lxc remote remove " "Remove the remote .\n" "lxc remote list " "List all remotes.\n" "lxc remote rename " "Rename remote to .\n" "lxc remote set-url " "Update 's url to .\n" "lxc remote set-default " "Set the default remote.\n" "lxc remote get-default " "Print the default remote." msgstr "" "Verwalte entfernte LXD Server.\n" "\n" "lxc remote add [--accept-certificate] [--password=PASSWORT] " "Fügt die Instanz auf hinzu.\n" "lxc remote remove " "Entfernt die Instanz .\n" "lxc remote list " "Listet alle entfernte Instanzen.\n" "lxc remote rename " "Benennt Instanz von nach um.\n" "lxc remote set-url " "Setzt die URL von auf .\n" "lxc remote set-default " "Setzt die Standard Instanz.\n" "lxc remote get-default " "Gibt die Standard Instanz aus.\n" #: lxc/image.go:93 msgid "" "Manipulate container images.\n" "\n" "In LXD containers are created from images. Those images were themselves\n" "either generated from an existing container or downloaded from an image\n" "server.\n" "\n" "When using remote images, LXD will automatically cache images for you\n" "and remove them upon expiration.\n" "\n" "The image unique identifier is the hash (sha-256) of its representation\n" "as a compressed tarball (or for split images, the concatenation of the\n" "metadata and rootfs tarballs).\n" "\n" "Images can be referenced by their full hash, shortest unique partial\n" "hash or alias name (if one is set).\n" "\n" "\n" "lxc image import [rootfs tarball|URL] [remote:] [--public] [--" "created-at=ISO-8601] [--expires-at=ISO-8601] [--fingerprint=FINGERPRINT] " "[prop=value]\n" " Import an image tarball (or tarballs) into the LXD image store.\n" "\n" "lxc image copy [remote:] : [--alias=ALIAS].. [--copy-aliases] " "[--public] [--auto-update]\n" " Copy an image from one LXD daemon to another over the network.\n" "\n" " The auto-update flag instructs the server to keep this image up to\n" " date. It requires the source to be an alias and for it to be public.\n" "\n" "lxc image delete [remote:]\n" " Delete an image from the LXD image store.\n" "\n" "lxc image export [remote:]\n" " Export an image from the LXD image store into a distributable tarball.\n" "\n" "lxc image info [remote:]\n" " Print everything LXD knows about a given image.\n" "\n" "lxc image list [remote:] [filter]\n" " List images in the LXD image store. Filters may be of the\n" " = form for property based filtering, or part of the image\n" " hash or part of the image alias name.\n" "\n" "lxc image show [remote:]\n" " Yaml output of the user modifiable properties of an image.\n" "\n" "lxc image edit [remote:]\n" " Edit image, either by launching external editor or reading STDIN.\n" " Example: lxc image edit # launch editor\n" " cat image.yml | lxc image edit # read from image.yml\n" "\n" "lxc image alias create [remote:] \n" " Create a new alias for an existing image.\n" "\n" "lxc image alias delete [remote:]\n" " Delete an alias.\n" "\n" "lxc image alias list [remote:] [filter]\n" " List the aliases. Filters may be part of the image hash or part of the " "image alias name.\n" msgstr "" #: lxc/info.go:147 msgid "Memory (current)" msgstr "" #: lxc/info.go:151 msgid "Memory (peak)" msgstr "" #: lxc/help.go:86 msgid "Missing summary." msgstr "Fehlende Zusammenfassung." #: lxc/monitor.go:41 msgid "" "Monitor activity on the LXD server.\n" "\n" "lxc monitor [remote:] [--type=TYPE...]\n" "\n" "Connects to the monitoring interface of the specified LXD server.\n" "\n" "By default will listen to all message types.\n" "Specific types to listen to can be specified with --type.\n" "\n" "Example:\n" "lxc monitor --type=logging" msgstr "" #: lxc/file.go:178 msgid "More than one file to download, but target is not a directory" msgstr "" "Mehr als eine Datei herunterzuladen, aber das Ziel ist kein Verzeichnis" #: lxc/move.go:17 #, fuzzy msgid "" "Move containers within or in between lxd instances.\n" "\n" "lxc move [remote:] [remote:]\n" " Move a container between two hosts, renaming it if destination name " "differs.\n" "\n" "lxc move \n" " Rename a local container.\n" msgstr "" "Verschiebt Container innerhalb einer oder zwischen lxd Instanzen\n" "\n" "lxc move \n" #: lxc/action.go:63 #, fuzzy msgid "Must supply container name for: " msgstr "der Name des Ursprung Containers muss angegeben werden" #: lxc/list.go:369 lxc/remote.go:363 msgid "NAME" msgstr "" #: lxc/remote.go:337 lxc/remote.go:342 msgid "NO" msgstr "" #: lxc/info.go:89 #, c-format msgid "Name: %s" msgstr "" #: lxc/image.go:157 lxc/publish.go:33 msgid "New alias to define at target" msgstr "" #: lxc/config.go:281 #, fuzzy msgid "No certificate provided to add" msgstr "Kein Zertifikat zum hinzufügen bereitgestellt" #: lxc/config.go:304 msgid "No fingerprint specified." msgstr "Kein Fingerabdruck angegeben." #: lxc/remote.go:107 msgid "Only https URLs are supported for simplestreams" msgstr "" #: lxc/image.go:411 msgid "Only https:// is supported for remote image import." msgstr "" #: lxc/help.go:63 lxc/main.go:122 msgid "Options:" msgstr "" #: lxc/image.go:506 #, c-format msgid "Output is in %s" msgstr "" #: lxc/exec.go:55 msgid "Override the terminal mode (auto, interactive or non-interactive)" msgstr "" #: lxc/list.go:453 msgid "PERSISTENT" msgstr "" #: lxc/list.go:370 msgid "PID" msgstr "" #: lxc/list.go:371 msgid "PROFILES" msgstr "" #: lxc/remote.go:365 msgid "PROTOCOL" msgstr "" #: lxc/image.go:606 lxc/remote.go:366 msgid "PUBLIC" msgstr "" #: lxc/info.go:174 msgid "Packets received" msgstr "" #: lxc/info.go:175 msgid "Packets sent" msgstr "" #: lxc/help.go:69 #, fuzzy msgid "Path to an alternate client configuration directory." msgstr "Alternatives config Verzeichnis." #: lxc/help.go:70 #, fuzzy msgid "Path to an alternate server directory." msgstr "Alternatives config Verzeichnis." #: lxc/main.go:39 msgid "Permisson denied, are you in the lxd group?" msgstr "" #: lxc/info.go:103 #, c-format msgid "Pid: %d" msgstr "" #: lxc/help.go:25 #, fuzzy msgid "" "Presents details on how to use LXD.\n" "\n" "lxd help [--all]" msgstr "" "Zeigt Details über die Benutzung von LXD an.\n" "\n" "lxd help [—all]\n" #: lxc/profile.go:191 msgid "Press enter to open the editor again" msgstr "" #: lxc/config.go:501 lxc/config.go:566 lxc/image.go:688 msgid "Press enter to start the editor again" msgstr "" #: lxc/help.go:65 msgid "Print debug information." msgstr "" #: lxc/help.go:64 msgid "Print less common commands." msgstr "" #: lxc/help.go:66 msgid "Print verbose information." msgstr "" #: lxc/version.go:18 #, fuzzy msgid "" "Prints the version number of this client tool.\n" "\n" "lxc version" msgstr "" "Zeigt die Versionsnummer von LXD.\n" "\n" "lxc version\n" #: lxc/info.go:127 #, fuzzy, c-format msgid "Processes: %d" msgstr "Profil %s erstellt\n" #: lxc/profile.go:228 #, fuzzy, c-format msgid "Profile %s applied to %s" msgstr "Profil %s wurde auf %s angewandt\n" #: lxc/profile.go:142 #, fuzzy, c-format msgid "Profile %s created" msgstr "Profil %s erstellt\n" #: lxc/profile.go:212 #, fuzzy, c-format msgid "Profile %s deleted" msgstr "Profil %s gelöscht\n" #: lxc/init.go:136 lxc/init.go:137 lxc/launch.go:42 lxc/launch.go:43 #, fuzzy msgid "Profile to apply to the new container" msgstr "kann nicht zum selben Container Namen kopieren" #: lxc/info.go:101 #, fuzzy, c-format msgid "Profiles: %s" msgstr "Profil %s erstellt\n" #: lxc/image.go:343 #, fuzzy msgid "Properties:" msgstr "Eigenschaften:\n" #: lxc/remote.go:56 msgid "Public image server" msgstr "" #: lxc/image.go:331 #, fuzzy, c-format msgid "Public: %s" msgstr "Öffentlich: %s\n" #: lxc/publish.go:25 msgid "" "Publish containers as images.\n" "\n" "lxc publish [remote:]container [remote:] [--alias=ALIAS]... [prop-key=prop-" "value]..." msgstr "" #: lxc/remote.go:54 msgid "Remote admin password" msgstr "Entferntes Administrator Passwort" #: lxc/delete.go:42 #, c-format msgid "Remove %s (yes/no): " msgstr "" #: lxc/delete.go:36 lxc/delete.go:37 msgid "Require user confirmation." msgstr "" #: lxc/info.go:124 msgid "Resources:" msgstr "" #: lxc/init.go:246 #, c-format msgid "Retrieving image: %s" msgstr "" #: lxc/image.go:609 msgid "SIZE" msgstr "" #: lxc/list.go:372 msgid "SNAPSHOTS" msgstr "" #: lxc/list.go:373 msgid "STATE" msgstr "" #: lxc/remote.go:367 msgid "STATIC" msgstr "" #: lxc/remote.go:214 msgid "Server certificate NACKed by user" msgstr "Server Zertifikat vom Benutzer nicht akzeptiert" #: lxc/remote.go:276 msgid "Server doesn't trust us after adding our cert" msgstr "" "Der Server vertraut uns nicht nachdem er unser Zertifikat hinzugefügt hat" #: lxc/remote.go:55 msgid "Server protocol (lxd or simplestreams)" msgstr "" #: lxc/restore.go:21 msgid "" "Set the current state of a resource back to a snapshot.\n" "\n" "lxc restore [remote:] [--stateful]\n" "\n" "Restores a container from a snapshot (optionally with running state, see\n" "snapshot help for details).\n" "\n" "For example:\n" "lxc snapshot u1 snap0 # create the snapshot\n" "lxc restore u1 snap0 # restore the snapshot" msgstr "" #: lxc/file.go:44 msgid "Set the file's gid on push" msgstr "Setzt die gid der Datei beim Übertragen" #: lxc/file.go:45 msgid "Set the file's perms on push" msgstr "Setzt die Dateiberechtigungen beim Übertragen" #: lxc/file.go:43 msgid "Set the file's uid on push" msgstr "Setzt die uid der Datei beim Übertragen" #: lxc/help.go:32 msgid "Show all commands (not just interesting ones)" msgstr "Zeigt alle Befehle (nicht nur die interessanten)" #: lxc/info.go:36 msgid "Show the container's last 100 log lines?" msgstr "Zeige die letzten 100 Zeilen Protokoll des Containers?" #: lxc/image.go:329 #, fuzzy, c-format msgid "Size: %.2fMB" msgstr "Größe: %.2vMB\n" #: lxc/info.go:194 msgid "Snapshots:" msgstr "" #: lxc/image.go:353 msgid "Source:" msgstr "" #: lxc/launch.go:122 #, c-format msgid "Starting %s" msgstr "" #: lxc/info.go:95 #, c-format msgid "Status: %s" msgstr "" #: lxc/publish.go:34 lxc/publish.go:35 msgid "Stop the container if currently running" msgstr "" #: lxc/delete.go:106 lxc/publish.go:111 msgid "Stopping container failed!" msgstr "Anhalten des Containers fehlgeschlagen!" #: lxc/action.go:38 #, fuzzy msgid "Store the container state (only for stop)." msgstr "Herunterfahren des Containers erzwingen." #: lxc/info.go:155 msgid "Swap (current)" msgstr "" #: lxc/info.go:159 msgid "Swap (peak)" msgstr "" #: lxc/list.go:374 msgid "TYPE" msgstr "" #: lxc/delete.go:92 msgid "The container is currently running, stop it first or pass --force." msgstr "" #: lxc/publish.go:89 msgid "" "The container is currently running. Use --force to have it stopped and " "restarted." msgstr "" #: lxc/config.go:645 lxc/config.go:657 lxc/config.go:690 lxc/config.go:708 #: lxc/config.go:746 lxc/config.go:764 #, fuzzy msgid "The device doesn't exist" msgstr "entfernte Instanz %s existiert nicht" #: lxc/publish.go:62 msgid "There is no \"image name\". Did you want an alias?" msgstr "" #: lxc/action.go:36 msgid "Time to wait for the container before killing it." msgstr "Wartezeit bevor der Container gestoppt wird." #: lxc/image.go:332 #, fuzzy msgid "Timestamps:" msgstr "Zeitstempel:\n" #: lxc/image.go:402 #, c-format msgid "Transferring image: %d%%" msgstr "" #: lxc/action.go:93 lxc/launch.go:130 #, c-format msgid "Try `lxc info --show-log %s` for more info" msgstr "" #: lxc/info.go:97 msgid "Type: ephemeral" msgstr "" #: lxc/info.go:99 msgid "Type: persistent" msgstr "" #: lxc/image.go:610 msgid "UPLOAD DATE" msgstr "" #: lxc/remote.go:364 msgid "URL" msgstr "" #: lxc/remote.go:82 msgid "Unable to read remote TLS certificate" msgstr "" #: lxc/image.go:337 #, c-format msgid "Uploaded: %s" msgstr "" #: lxc/main.go:122 #, fuzzy, c-format msgid "Usage: %s" msgstr "" "Benutzung: %s\n" "\n" "Optionen:\n" "\n" #: lxc/help.go:48 #, fuzzy msgid "Usage: lxc [subcommand] [options]" msgstr "" "Benutzung: lxc [Unterbefehl] [Optionen]\n" "Verfügbare Befehle:\n" #: lxc/delete.go:46 msgid "User aborted delete operation." msgstr "" #: lxc/restore.go:35 msgid "" "Whether or not to restore the container's running state from snapshot (if " "available)" msgstr "" "Laufenden Zustand des Containers aus dem Sicherungspunkt (falls vorhanden) " "wiederherstellen oder nicht" #: lxc/snapshot.go:38 msgid "Whether or not to snapshot the container's running state" msgstr "Zustand des laufenden Containers sichern oder nicht" #: lxc/config.go:33 msgid "Whether to show the expanded configuration" msgstr "" #: lxc/remote.go:339 lxc/remote.go:344 msgid "YES" msgstr "" #: lxc/main.go:66 msgid "`lxc config profile` is deprecated, please use `lxc profile`" msgstr "" #: lxc/launch.go:109 msgid "bad number of things scanned from image, container or snapshot" msgstr "" "Falsche Anzahl an Objekten im Abbild, Container oder Sicherungspunkt gelesen." #: lxc/action.go:89 msgid "bad result type from action" msgstr "" #: lxc/copy.go:78 msgid "can't copy to the same container name" msgstr "kann nicht zum selben Container Namen kopieren" #: lxc/remote.go:327 msgid "can't remove the default remote" msgstr "" #: lxc/remote.go:353 msgid "default" msgstr "" #: lxc/init.go:199 lxc/init.go:204 lxc/launch.go:93 lxc/launch.go:98 msgid "didn't get any affected image, container or snapshot from server" msgstr "" #: lxc/image.go:323 msgid "disabled" msgstr "" #: lxc/image.go:325 msgid "enabled" msgstr "" #: lxc/main.go:25 lxc/main.go:158 #, fuzzy, c-format msgid "error: %v" msgstr "Fehler: %v\n" #: lxc/help.go:40 lxc/main.go:117 #, fuzzy, c-format msgid "error: unknown command: %s" msgstr "Fehler: unbekannter Befehl: %s\n" #: lxc/launch.go:113 msgid "got bad version" msgstr "Versionskonflikt" #: lxc/image.go:318 lxc/image.go:586 msgid "no" msgstr "" #: lxc/copy.go:101 msgid "not all the profiles from the source exist on the target" msgstr "nicht alle Profile der Quelle sind am Ziel vorhanden." #: lxc/remote.go:207 #, fuzzy msgid "ok (y/n)?" msgstr "OK (y/n)? " #: lxc/main.go:265 lxc/main.go:269 #, c-format msgid "processing aliases failed %s\n" msgstr "" #: lxc/remote.go:389 #, c-format msgid "remote %s already exists" msgstr "entfernte Instanz %s existiert bereits" #: lxc/remote.go:319 lxc/remote.go:381 lxc/remote.go:416 lxc/remote.go:432 #, c-format msgid "remote %s doesn't exist" msgstr "entfernte Instanz %s existiert nicht" #: lxc/remote.go:302 #, c-format msgid "remote %s exists as <%s>" msgstr "entfernte Instanz %s existiert als <%s>" #: lxc/remote.go:323 lxc/remote.go:385 lxc/remote.go:420 #, c-format msgid "remote %s is static and cannot be modified" msgstr "" #: lxc/info.go:205 msgid "stateful" msgstr "" #: lxc/info.go:207 msgid "stateless" msgstr "" #: lxc/info.go:201 #, c-format msgid "taken at %s" msgstr "" #: lxc/exec.go:166 msgid "unreachable return reached" msgstr "" #: lxc/main.go:198 msgid "wrong number of subcommand arguments" msgstr "falsche Anzahl an Parametern für Unterbefehl" #: lxc/delete.go:45 lxc/image.go:320 lxc/image.go:590 msgid "yes" msgstr "" #: lxc/copy.go:38 msgid "you must specify a source container name" msgstr "der Name des Ursprung Containers muss angegeben werden" #, fuzzy #~ msgid "For example: 'lxd-images import ubuntu --alias ubuntu'." #~ msgstr "Zum Beispiel: 'lxd-images import ubuntu --alias ubuntu'.\n" #, fuzzy #~ msgid "" #~ "If this is your first run, you will need to import images using the 'lxd-" #~ "images' script." #~ msgstr "" #~ "Falls dies der erste Start ist, sollten Sie mit dem 'lxd-images' Script " #~ "Abbilder importieren.\n" #, fuzzy #~ msgid "Bad image property: %s" #~ msgstr "Ungültige Abbild Eigenschaft: %s\n" #~ msgid "Cannot change profile name" #~ msgstr "Profilname kann nicht geändert werden" #, fuzzy #~ msgid "" #~ "Create a read-only snapshot of a container.\n" #~ "\n" #~ "lxc snapshot [remote:] [--stateful]" #~ msgstr "" #~ "Erstellt einen schreibgeschützten Sicherungspunkt des Containers.\n" #~ "\n" #~ "lxc snapshot [--stateful]\n" #, fuzzy #~ msgid "Error adding alias %s" #~ msgstr "Fehler beim hinzufügen des Alias %s\n" #, fuzzy #~ msgid "" #~ "Manipulate container images.\n" #~ "\n" #~ "lxc image import [rootfs tarball|URL] [target] [--public] [--" #~ "created-at=ISO-8601] [--expires-at=ISO-8601] [--fingerprint=FINGERPRINT] " #~ "[prop=value]\n" #~ "\n" #~ "lxc image copy [remote:] : [--alias=ALIAS].. [--copy-" #~ "aliases] [--public]\n" #~ "lxc image delete [remote:]\n" #~ "lxc image export [remote:]\n" #~ "lxc image info [remote:]\n" #~ "lxc image list [remote:] [filter]\n" #~ "lxc image show [remote:]\n" #~ "lxc image edit [remote:]\n" #~ " Edit image, either by launching external editor or reading STDIN.\n" #~ " Example: lxc image edit # launch editor\n" #~ " cat image.yml | lxc image edit # read from image." #~ "yml\n" #~ "\n" #~ "Lists the images at specified remote, or local images.\n" #~ "Filters are not yet supported.\n" #~ "\n" #~ "lxc image alias create \n" #~ "lxc image alias delete \n" #~ "lxc image alias list [remote:]\n" #~ "\n" #~ "Create, delete, list image aliases. Example:\n" #~ "lxc remote add store2 images.linuxcontainers.org\n" #~ "lxc image alias list store2:" #~ msgstr "" #~ "Ändere Container Abbilder\n" #~ "\n" #~ "lxc image import [Ziel] [--public] [--created-at=ISO-8601] [--" #~ "expires-at=ISO-8601] [--fingerprint=FINGERPRINT] [prop=value]\n" #~ "\n" #~ "lxc image copy [remote:] : [--alias=ALIAS].. [--copy-" #~ "alias]\n" #~ "lxc image delete [remote:]\n" #~ "lxc image edit [remote:]\n" #~ "lxc image export [remote:]\n" #~ "lxc image info [remote:]\n" #~ "lxc image list [remote:] [Filter]\n" #~ "lxc image show [remote:]\n" #~ "\n" #~ "Listet die Abbilder auf der entfernten oder lokalen Instanz.\n" #~ "Filter werden noch nicht unterstützt.\n" #~ "\n" #~ "lxc image alias create \n" #~ "lxc image alias delete \n" #~ "lxc remote add images images.linuxcontainers.org\n" #~ "lxc image alias list images:\n" #~ "erstelle, lösche und liste Abbild Aliasse\n" #~ msgid "No certificate on this connection" #~ msgstr "Kein Zertifikat für diese Verbindung" #~ msgid "" #~ "Server certificate for host %s has changed. Add correct certificate or " #~ "remove certificate in %s" #~ msgstr "" #~ "Server Zertifikat für Rechner %s hat sich geändert. Fürgen Sie das " #~ "richtige Zertifikat hinzu oder löschen Sie das Zertifikat unter %s" #, fuzzy #~ msgid "" #~ "Set the current state of a resource back to its state at the time the " #~ "snapshot was created.\n" #~ "\n" #~ "lxc restore [remote:] [--stateful]" #~ msgstr "" #~ "Setzt eine Ressource auf einen Sicherungspunkt zurück.\n" #~ "\n" #~ "lxc restore [—stateful]\n" #~ msgid "api version mismatch: mine: %q, daemon: %q" #~ msgstr "API Versionskonflikt: meine: %q, Hintergrund Dienst: %q" #~ msgid "bad profile url %s" #~ msgstr "Fehlerhafte Profil URL %s" #~ msgid "bad version in profile url" #~ msgstr "Falsche Version in Profil URL" #, fuzzy #~ msgid "device already exists" #~ msgstr "entfernte Instanz %s existiert bereits" #, fuzzy #~ msgid "error." #~ msgstr "Fehler: %v\n" #~ msgid "no response!" #~ msgstr "keine Antwort!" #, fuzzy #~ msgid "no value found in %q" #~ msgstr "kein Wert in %q gefunden\n" #~ msgid "unknown remote name: %q" #~ msgstr "unbekannter entfernter Instanz Name: %q" #, fuzzy #~ msgid "unknown transport type: %s" #~ msgstr "unbekannter entfernter Instanz Name: %q" #~ msgid "cannot resolve unix socket address: %v" #~ msgstr "kann unix Socket Adresse %v nicht auflösen" #, fuzzy #~ msgid "unknown group %s" #~ msgstr "unbekannter entfernter Instanz Name: %q" #, fuzzy #~ msgid "Information about remotes not yet supported" #~ msgstr "" #~ "Informationen über entfernte Instanzen wird noch nicht unterstützt\n" #~ msgid "Unknown image command %s" #~ msgstr "Unbekannter Befehl %s für Abbild" #~ msgid "Unknown remote subcommand %s" #~ msgstr "Unbekannter Unterbefehl %s für entfernte Instanz" #~ msgid "Unkonwn config trust command %s" #~ msgstr "Unbekannter config Befehl %s" #, fuzzy #~ msgid "YAML parse error %v" #~ msgstr "YAML Analyse Fehler %v\n" #~ msgid "invalid argument %s" #~ msgstr "ungültiges Argument %s" #, fuzzy #~ msgid "unknown profile cmd %s" #~ msgstr "Unbekannter Befehl %s für Abbild" #, fuzzy #~ msgid "Publish to remote server is not supported yet" #~ msgstr "" #~ "Anzeigen von Informationen über entfernte Instanzen wird noch nicht " #~ "unterstützt\n" #, fuzzy #~ msgid "Use an alternative config path." #~ msgstr "Alternatives config Verzeichnis." #, fuzzy #~ msgid "" #~ "error: %v\n" #~ "%s\n" #~ msgstr "" #~ "Fehler: %v\n" #~ "%s" #, fuzzy #~ msgid "" #~ "lxc init [remote:] [remote:][] [--ephemeral|-e] [--profile|-" #~ "p ...]\n" #~ "\n" #~ "Initializes a container using the specified image and name.\n" #~ "\n" #~ "Not specifying -p will result in the default profile.\n" #~ "Specifying \"-p\" with no argument will result in no profile.\n" #~ "\n" #~ "Example:\n" #~ "lxc init ubuntu u1\n" #~ msgstr "" #~ "lxc init [] [--ephemeral|-e] [--profile|-p ...]\n" #~ "\n" #~ "Initialisiert einen Container mit Namen von dem angegebenen Abbild .\n" #~ "\n" #~ "Ohne den -p Parameter wird das default Profil benutzt.\n" #~ "Wird -p ohne Argument angegeben, wird kein Profil verwendet\n" #~ "\n" #~ "Beispiel:\n" #~ "lxc init ubuntu u1\n" #~ msgid "" #~ "Changing the name of a running container during copy isn't supported." #~ msgstr "" #~ "Den Namen eines laufenden Containers beim kopieren zu ändern wird nicht " #~ "unterstützt." #~ msgid "non-http remotes are not supported for migration right now" #~ msgstr "" #~ "die Migration an entfernte Instanzen wird zur Zeit nur über http " #~ "unterstützt." #~ msgid "Cannot connect to unix socket at %s Is the server running?\n" #~ msgstr "" #~ "Keine Verbindung zum unix Socket unter %s möglich. Läuft der Server?\n" #~ msgid "Show for remotes is not yet supported\n" #~ msgstr "" #~ "Anzeigen von Informationen über entfernte Instanzen wird noch nicht " #~ "unterstützt\n" lxd-2.0.0/po/fr.po000066400000000000000000001122351270277227600137050ustar00rootroot00000000000000# French translation for LXD # Copyright (C) 2015 - LXD contributors # This file is distributed under the same license as LXD. # Stéphane Graber \n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: lxc/info.go:140 msgid " Disk usage:" msgstr "" #: lxc/info.go:163 msgid " Memory usage:" msgstr "" #: lxc/info.go:180 msgid " Network usage:" msgstr "" #: lxc/config.go:37 msgid "" "### This is a yaml representation of the configuration.\n" "### Any line starting with a '# will be ignored.\n" "###\n" "### A sample configuration looks like:\n" "### name: container1\n" "### profiles:\n" "### - default\n" "### config:\n" "### volatile.eth0.hwaddr: 00:16:3e:e9:f8:7f\n" "### devices:\n" "### homedir:\n" "### path: /extra\n" "### source: /home/user\n" "### type: disk\n" "### ephemeral: false\n" "###\n" "### Note that the name is shown but cannot be changed" msgstr "" #: lxc/image.go:83 msgid "" "### This is a yaml representation of the image properties.\n" "### Any line starting with a '# will be ignored.\n" "###\n" "### Each property is represented by a single line:\n" "### An example would be:\n" "### description: My custom image" msgstr "" #: lxc/profile.go:27 msgid "" "### This is a yaml representation of the profile.\n" "### Any line starting with a '# will be ignored.\n" "###\n" "### A profile consists of a set of configuration items followed by a set of\n" "### devices.\n" "###\n" "### An example would look like:\n" "### name: onenic\n" "### config:\n" "### raw.lxc: lxc.aa_profile=unconfined\n" "### devices:\n" "### eth0:\n" "### nictype: bridged\n" "### parent: lxdbr0\n" "### type: nic\n" "###\n" "### Note that the name is shown but cannot be changed" msgstr "" #: lxc/image.go:583 #, c-format msgid "%s (%d more)" msgstr "" #: lxc/snapshot.go:61 #, fuzzy msgid "'/' not allowed in snapshot name" msgstr "'/' n'est pas autorisé dans le nom d'un instantané (snapshot)\n" #: lxc/profile.go:226 msgid "(none)" msgstr "" #: lxc/image.go:604 lxc/image.go:633 msgid "ALIAS" msgstr "" #: lxc/image.go:608 msgid "ARCH" msgstr "" #: lxc/list.go:367 msgid "ARCHITECTURE" msgstr "" #: lxc/remote.go:53 msgid "Accept certificate" msgstr "" #: lxc/remote.go:256 #, c-format msgid "Admin password for %s: " msgstr "Mot de passe administrateur pour %s: " #: lxc/image.go:347 msgid "Aliases:" msgstr "" #: lxc/exec.go:54 msgid "An environment variable of the form HOME=/home/foo" msgstr "" #: lxc/image.go:330 lxc/info.go:90 #, c-format msgid "Architecture: %s" msgstr "" #: lxc/image.go:351 #, c-format msgid "Auto update: %s" msgstr "" #: lxc/help.go:49 msgid "Available commands:" msgstr "" #: lxc/info.go:172 msgid "Bytes received" msgstr "" #: lxc/info.go:173 msgid "Bytes sent" msgstr "" #: lxc/config.go:270 msgid "COMMON NAME" msgstr "" #: lxc/list.go:368 msgid "CREATED AT" msgstr "" #: lxc/config.go:114 #, c-format msgid "Can't read from stdin: %s" msgstr "" #: lxc/config.go:127 lxc/config.go:160 lxc/config.go:182 #, c-format msgid "Can't unset key '%s', it's not currently set." msgstr "" #: lxc/profile.go:343 msgid "Cannot provide container name to list" msgstr "" #: lxc/remote.go:206 #, fuzzy, c-format msgid "Certificate fingerprint: %x" msgstr "Empreinte du certificat: % x\n" #: lxc/action.go:28 #, fuzzy, c-format msgid "" "Changes state of one or more containers to %s.\n" "\n" "lxc %s [...]" msgstr "Change l'état du conteneur à %s.\n" #: lxc/remote.go:279 msgid "Client certificate stored at server: " msgstr "Certificat client enregistré avec le serveur: " #: lxc/list.go:97 lxc/list.go:98 msgid "Columns" msgstr "" #: lxc/init.go:134 lxc/init.go:135 lxc/launch.go:40 lxc/launch.go:41 msgid "Config key/value to apply to the new container" msgstr "" #: lxc/config.go:500 lxc/config.go:565 lxc/image.go:687 lxc/profile.go:190 #, fuzzy, c-format msgid "Config parsing error: %s" msgstr "erreur: %v\n" #: lxc/main.go:37 msgid "Connection refused; is LXD running?" msgstr "" #: lxc/publish.go:59 msgid "Container name is mandatory" msgstr "" #: lxc/init.go:209 #, c-format msgid "Container name is: %s" msgstr "" #: lxc/publish.go:141 lxc/publish.go:156 #, fuzzy, c-format msgid "Container published with fingerprint: %s" msgstr "Empreinte du certificat: % x\n" #: lxc/image.go:155 msgid "Copy aliases from source" msgstr "" #: lxc/copy.go:22 msgid "" "Copy containers within or in between lxd instances.\n" "\n" "lxc copy [remote:] [remote:] [--" "ephemeral|e]" msgstr "" #: lxc/image.go:268 #, c-format msgid "Copying the image: %s" msgstr "" #: lxc/remote.go:221 msgid "Could not create server cert dir" msgstr "Le dossier de stockage des certificats serveurs n'a pas pû être créé" #: lxc/snapshot.go:21 msgid "" "Create a read-only snapshot of a container.\n" "\n" "lxc snapshot [remote:] [--stateful]\n" "\n" "Creates a snapshot of the container (optionally with the container's memory\n" "state). When --stateful is used, LXD attempts to checkpoint the container's\n" "running state, including process memory state, TCP connections, etc. so that " "it\n" "can be restored (via lxc restore) at a later time (although some things, e." "g.\n" "TCP connections after the TCP timeout window has expired, may not be " "restored\n" "successfully).\n" "\n" "Example:\n" "lxc snapshot u1 snap0" msgstr "" #: lxc/image.go:335 lxc/info.go:92 #, c-format msgid "Created: %s" msgstr "" #: lxc/init.go:177 lxc/launch.go:116 #, c-format msgid "Creating %s" msgstr "" #: lxc/init.go:175 msgid "Creating the container" msgstr "" #: lxc/image.go:607 lxc/image.go:635 msgid "DESCRIPTION" msgstr "" #: lxc/delete.go:25 msgid "" "Delete containers or container snapshots.\n" "\n" "lxc delete [remote:][/] [remote:][[/" "]...]\n" "\n" "Destroy containers or snapshots with any attached data (configuration, " "snapshots, ...)." msgstr "" #: lxc/config.go:617 #, c-format msgid "Device %s added to %s" msgstr "" #: lxc/config.go:804 #, c-format msgid "Device %s removed from %s" msgstr "" #: lxc/list.go:451 msgid "EPHEMERAL" msgstr "" #: lxc/config.go:272 msgid "EXPIRY DATE" msgstr "" #: lxc/main.go:55 msgid "Enables debug mode." msgstr "Active le mode de déboguage." #: lxc/main.go:54 msgid "Enables verbose mode." msgstr "Active le mode verbeux." #: lxc/help.go:68 msgid "Environment:" msgstr "" #: lxc/copy.go:29 lxc/copy.go:30 lxc/init.go:138 lxc/init.go:139 #: lxc/launch.go:44 lxc/launch.go:45 msgid "Ephemeral container" msgstr "" #: lxc/monitor.go:56 msgid "Event type to listen for" msgstr "" #: lxc/exec.go:45 #, fuzzy msgid "" "Execute the specified command in a container.\n" "\n" "lxc exec [remote:]container [--mode=auto|interactive|non-interactive] [--env " "EDITOR=/usr/bin/vim]... \n" "\n" "Mode defaults to non-interactive, interactive mode is selected if both stdin " "AND stdout are terminals (stderr is ignored)." msgstr "Exécute la commande spécifiée dans un conteneur.\n" #: lxc/image.go:339 #, c-format msgid "Expires: %s" msgstr "" #: lxc/image.go:341 msgid "Expires: never" msgstr "" #: lxc/config.go:269 lxc/image.go:605 lxc/image.go:634 msgid "FINGERPRINT" msgstr "" #: lxc/list.go:100 msgid "Fast mode (same as --columns=nsacPt" msgstr "" #: lxc/image.go:328 #, fuzzy, c-format msgid "Fingerprint: %s" msgstr "Empreinte du certificat: % x\n" #: lxc/finger.go:17 #, fuzzy msgid "" "Fingers the LXD instance to check if it is up and working.\n" "\n" "lxc finger " msgstr "Contacte LXD pour voir s'il est fonctionel.\n" #: lxc/action.go:37 msgid "Force the container to shutdown." msgstr "Force l'arrêt du conteneur." #: lxc/delete.go:34 lxc/delete.go:35 msgid "Force the removal of stopped containers." msgstr "" #: lxc/main.go:56 msgid "Force using the local unix socket." msgstr "" #: lxc/list.go:99 msgid "Format" msgstr "" #: lxc/main.go:138 #, fuzzy msgid "Generating a client certificate. This may take a minute..." msgstr "Géneration d'un certificat client. Ceci peut prendre une minute...\n" #: lxc/list.go:365 msgid "IPV4" msgstr "" #: lxc/list.go:366 msgid "IPV6" msgstr "" #: lxc/config.go:271 msgid "ISSUE DATE" msgstr "" #: lxc/main.go:146 msgid "" "If this is your first time using LXD, you should also run: sudo lxd init" msgstr "" #: lxc/main.go:57 msgid "Ignore aliases when determining what command to run." msgstr "" #: lxc/action.go:39 #, fuzzy msgid "Ignore the container state (only forstart)." msgstr "Force l'arrêt du conteneur." #: lxc/image.go:273 msgid "Image copied successfully!" msgstr "" #: lxc/image.go:419 #, fuzzy, c-format msgid "Image imported with fingerprint: %s" msgstr "Empreinte du certificat: % x\n" #: lxc/init.go:73 msgid "" "Initialize a container from a particular image.\n" "\n" "lxc init [remote:] [remote:][] [--ephemeral|-e] [--profile|-p " "...] [--config|-c ...]\n" "\n" "Initializes a container using the specified image and name.\n" "\n" "Not specifying -p will result in the default profile.\n" "Specifying \"-p\" with no argument will result in no profile.\n" "\n" "Example:\n" "lxc init ubuntu u1" msgstr "" #: lxc/remote.go:122 #, c-format msgid "Invalid URL scheme \"%s\" in \"%s\"" msgstr "" #: lxc/init.go:30 lxc/init.go:35 #, fuzzy msgid "Invalid configuration key" msgstr "Gérer la configuration.\n" #: lxc/file.go:190 #, c-format msgid "Invalid source %s" msgstr "Source invalide %s" #: lxc/file.go:57 #, c-format msgid "Invalid target %s" msgstr "Destination invalide %s" #: lxc/info.go:121 msgid "Ips:" msgstr "" #: lxc/image.go:156 msgid "Keep the image up to date after initial copy" msgstr "" #: lxc/main.go:35 msgid "LXD socket not found; is LXD running?" msgstr "" #: lxc/launch.go:22 msgid "" "Launch a container from a particular image.\n" "\n" "lxc launch [remote:] [remote:][] [--ephemeral|-e] [--profile|-p " "...] [--config|-c ...]\n" "\n" "Launches a container using the specified image and name.\n" "\n" "Not specifying -p will result in the default profile.\n" "Specifying \"-p\" with no argument will result in no profile.\n" "\n" "Example:\n" "lxc launch ubuntu u1" msgstr "" #: lxc/info.go:25 msgid "" "List information on LXD servers and containers.\n" "\n" "For a container:\n" " lxc info [:]container [--show-log]\n" "\n" "For a server:\n" " lxc info [:]" msgstr "" #: lxc/list.go:67 msgid "" "Lists the available resources.\n" "\n" "lxc list [resource] [filters] [--format table|json] [-c columns] [--fast]\n" "\n" "The filters are:\n" "* A single keyword like \"web\" which will list any container with \"web\" " "in its name.\n" "* A key/value pair referring to a configuration item. For those, the " "namespace can be abreviated to the smallest unambiguous identifier:\n" "* \"user.blah=abc\" will list all containers with the \"blah\" user property " "set to \"abc\"\n" "* \"u.blah=abc\" will do the same\n" "* \"security.privileged=1\" will list all privileged containers\n" "* \"s.privileged=1\" will do the same\n" "\n" "Columns for table format are:\n" "* 4 - IPv4 address\n" "* 6 - IPv6 address\n" "* a - architecture\n" "* c - creation date\n" "* n - name\n" "* p - pid of container init process\n" "* P - profiles\n" "* s - state\n" "* S - number of snapshots\n" "* t - type (persistent or ephemeral)\n" "\n" "Default column layout: ns46tS\n" "Fast column layout: nsacPt" msgstr "" #: lxc/info.go:225 msgid "Log:" msgstr "" #: lxc/image.go:154 msgid "Make image public" msgstr "" #: lxc/publish.go:32 msgid "Make the image public" msgstr "" #: lxc/profile.go:48 msgid "" "Manage configuration profiles.\n" "\n" "lxc profile list [filters] List available profiles.\n" "lxc profile show Show details of a profile.\n" "lxc profile create Create a profile.\n" "lxc profile copy Copy the profile to the " "specified remote.\n" "lxc profile get Get profile configuration.\n" "lxc profile set Set profile configuration.\n" "lxc profile delete Delete a profile.\n" "lxc profile edit \n" " Edit profile, either by launching external editor or reading STDIN.\n" " Example: lxc profile edit # launch editor\n" " cat profile.yml | lxc profile edit # read from " "profile.yml\n" "lxc profile apply \n" " Apply a comma-separated list of profiles to a container, in order.\n" " All profiles passed in this call (and only those) will be applied\n" " to the specified container.\n" " Example: lxc profile apply foo default,bar # Apply default and bar\n" " lxc profile apply foo default # Only default is active\n" " lxc profile apply '' # no profiles are applied anymore\n" " lxc profile apply bar,default # Apply default second now\n" "\n" "Devices:\n" "lxc profile device list List " "devices in the given profile.\n" "lxc profile device show Show " "full device details in the given profile.\n" "lxc profile device remove Remove a " "device from a profile.\n" "lxc profile device get <[remote:]profile> Get a " "device property.\n" "lxc profile device set <[remote:]profile> Set a " "device property.\n" "lxc profile device unset <[remote:]profile> Unset a " "device property.\n" "lxc profile device add " "[key=value]...\n" " Add a profile device, such as a disk or a nic, to the containers\n" " using the specified profile." msgstr "" #: lxc/config.go:58 msgid "" "Manage configuration.\n" "\n" "lxc config device add <[remote:]container> [key=value]... " "Add a device to a container.\n" "lxc config device get <[remote:]container> " "Get a device property.\n" "lxc config device set <[remote:]container> " "Set a device property.\n" "lxc config device unset <[remote:]container> " "Unset a device property.\n" "lxc config device list <[remote:]container> " "List devices for container.\n" "lxc config device show <[remote:]container> " "Show full device details for container.\n" "lxc config device remove <[remote:]container> " "Remove device from container.\n" "\n" "lxc config get [remote:][container] " "Get container or server configuration key.\n" "lxc config set [remote:][container] " "Set container or server configuration key.\n" "lxc config unset [remote:][container] " "Unset container or server configuration key.\n" "lxc config show [remote:][container] [--expanded] " "Show container or server configuration.\n" "lxc config edit [remote:][container] " "Edit container or server configuration in external editor.\n" " Edit configuration, either by launching external editor or reading " "STDIN.\n" " Example: lxc config edit # launch editor\n" " cat config.yml | lxc config edit # read from config." "yml\n" "\n" "lxc config trust list [remote] " "List all trusted certs.\n" "lxc config trust add [remote] " "Add certfile.crt to trusted hosts.\n" "lxc config trust remove [remote] [hostname|fingerprint] " "Remove the cert from trusted hosts.\n" "\n" "Examples:\n" "To mount host's /share/c1 onto /opt in the container:\n" " lxc config device add [remote:]container1 disk source=/" "share/c1 path=opt\n" "\n" "To set an lxc config value:\n" " lxc config set [remote:] raw.lxc 'lxc.aa_allow_incomplete = " "1'\n" "\n" "To listen on IPv4 and IPv6 port 8443 (you can omit the 8443 its the " "default):\n" " lxc config set core.https_address [::]:8443\n" "\n" "To set the server trust password:\n" " lxc config set core.trust_password blah" msgstr "" #: lxc/file.go:32 msgid "" "Manage files on a container.\n" "\n" "lxc file pull [...] \n" "lxc file push [--uid=UID] [--gid=GID] [--mode=MODE] [...] " "\n" "lxc file edit \n" "\n" " in the case of pull, in the case of push and in the " "case of edit are /" msgstr "" #: lxc/remote.go:39 msgid "" "Manage remote LXD servers.\n" "\n" "lxc remote add [--accept-certificate] [--password=PASSWORD]\n" " [--public] [--protocol=PROTOCOL] " "Add the remote at .\n" "lxc remote remove " "Remove the remote .\n" "lxc remote list " "List all remotes.\n" "lxc remote rename " "Rename remote to .\n" "lxc remote set-url " "Update 's url to .\n" "lxc remote set-default " "Set the default remote.\n" "lxc remote get-default " "Print the default remote." msgstr "" #: lxc/image.go:93 msgid "" "Manipulate container images.\n" "\n" "In LXD containers are created from images. Those images were themselves\n" "either generated from an existing container or downloaded from an image\n" "server.\n" "\n" "When using remote images, LXD will automatically cache images for you\n" "and remove them upon expiration.\n" "\n" "The image unique identifier is the hash (sha-256) of its representation\n" "as a compressed tarball (or for split images, the concatenation of the\n" "metadata and rootfs tarballs).\n" "\n" "Images can be referenced by their full hash, shortest unique partial\n" "hash or alias name (if one is set).\n" "\n" "\n" "lxc image import [rootfs tarball|URL] [remote:] [--public] [--" "created-at=ISO-8601] [--expires-at=ISO-8601] [--fingerprint=FINGERPRINT] " "[prop=value]\n" " Import an image tarball (or tarballs) into the LXD image store.\n" "\n" "lxc image copy [remote:] : [--alias=ALIAS].. [--copy-aliases] " "[--public] [--auto-update]\n" " Copy an image from one LXD daemon to another over the network.\n" "\n" " The auto-update flag instructs the server to keep this image up to\n" " date. It requires the source to be an alias and for it to be public.\n" "\n" "lxc image delete [remote:]\n" " Delete an image from the LXD image store.\n" "\n" "lxc image export [remote:]\n" " Export an image from the LXD image store into a distributable tarball.\n" "\n" "lxc image info [remote:]\n" " Print everything LXD knows about a given image.\n" "\n" "lxc image list [remote:] [filter]\n" " List images in the LXD image store. Filters may be of the\n" " = form for property based filtering, or part of the image\n" " hash or part of the image alias name.\n" "\n" "lxc image show [remote:]\n" " Yaml output of the user modifiable properties of an image.\n" "\n" "lxc image edit [remote:]\n" " Edit image, either by launching external editor or reading STDIN.\n" " Example: lxc image edit # launch editor\n" " cat image.yml | lxc image edit # read from image.yml\n" "\n" "lxc image alias create [remote:] \n" " Create a new alias for an existing image.\n" "\n" "lxc image alias delete [remote:]\n" " Delete an alias.\n" "\n" "lxc image alias list [remote:] [filter]\n" " List the aliases. Filters may be part of the image hash or part of the " "image alias name.\n" msgstr "" #: lxc/info.go:147 msgid "Memory (current)" msgstr "" #: lxc/info.go:151 msgid "Memory (peak)" msgstr "" #: lxc/help.go:86 msgid "Missing summary." msgstr "Sommaire manquant." #: lxc/monitor.go:41 msgid "" "Monitor activity on the LXD server.\n" "\n" "lxc monitor [remote:] [--type=TYPE...]\n" "\n" "Connects to the monitoring interface of the specified LXD server.\n" "\n" "By default will listen to all message types.\n" "Specific types to listen to can be specified with --type.\n" "\n" "Example:\n" "lxc monitor --type=logging" msgstr "" #: lxc/file.go:178 msgid "More than one file to download, but target is not a directory" msgstr "" "Plusieurs fichiers à télécharger mais la destination n'est pas un dossier" #: lxc/move.go:17 msgid "" "Move containers within or in between lxd instances.\n" "\n" "lxc move [remote:] [remote:]\n" " Move a container between two hosts, renaming it if destination name " "differs.\n" "\n" "lxc move \n" " Rename a local container.\n" msgstr "" #: lxc/action.go:63 msgid "Must supply container name for: " msgstr "" #: lxc/list.go:369 lxc/remote.go:363 msgid "NAME" msgstr "" #: lxc/remote.go:337 lxc/remote.go:342 msgid "NO" msgstr "" #: lxc/info.go:89 #, c-format msgid "Name: %s" msgstr "" #: lxc/image.go:157 lxc/publish.go:33 msgid "New alias to define at target" msgstr "" #: lxc/config.go:281 #, fuzzy msgid "No certificate provided to add" msgstr "Un certificat n'a pas été fournis" #: lxc/config.go:304 msgid "No fingerprint specified." msgstr "Aucune empreinte n'a été spécifié." #: lxc/remote.go:107 msgid "Only https URLs are supported for simplestreams" msgstr "" #: lxc/image.go:411 msgid "Only https:// is supported for remote image import." msgstr "" #: lxc/help.go:63 lxc/main.go:122 #, fuzzy msgid "Options:" msgstr "Opération %s" #: lxc/image.go:506 #, c-format msgid "Output is in %s" msgstr "" #: lxc/exec.go:55 msgid "Override the terminal mode (auto, interactive or non-interactive)" msgstr "" #: lxc/list.go:453 msgid "PERSISTENT" msgstr "" #: lxc/list.go:370 msgid "PID" msgstr "" #: lxc/list.go:371 msgid "PROFILES" msgstr "" #: lxc/remote.go:365 msgid "PROTOCOL" msgstr "" #: lxc/image.go:606 lxc/remote.go:366 msgid "PUBLIC" msgstr "" #: lxc/info.go:174 msgid "Packets received" msgstr "" #: lxc/info.go:175 msgid "Packets sent" msgstr "" #: lxc/help.go:69 #, fuzzy msgid "Path to an alternate client configuration directory." msgstr "Dossier de configuration alternatif." #: lxc/help.go:70 #, fuzzy msgid "Path to an alternate server directory." msgstr "Dossier de configuration alternatif." #: lxc/main.go:39 msgid "Permisson denied, are you in the lxd group?" msgstr "" #: lxc/info.go:103 #, c-format msgid "Pid: %d" msgstr "" #: lxc/help.go:25 #, fuzzy msgid "" "Presents details on how to use LXD.\n" "\n" "lxd help [--all]" msgstr "Explique comment utiliser LXD.\n" #: lxc/profile.go:191 msgid "Press enter to open the editor again" msgstr "" #: lxc/config.go:501 lxc/config.go:566 lxc/image.go:688 msgid "Press enter to start the editor again" msgstr "" #: lxc/help.go:65 msgid "Print debug information." msgstr "" #: lxc/help.go:64 msgid "Print less common commands." msgstr "" #: lxc/help.go:66 msgid "Print verbose information." msgstr "" #: lxc/version.go:18 #, fuzzy msgid "" "Prints the version number of this client tool.\n" "\n" "lxc version" msgstr "Montre le numéro de version de LXD.\n" #: lxc/info.go:127 #, fuzzy, c-format msgid "Processes: %d" msgstr "Mauvaise URL pour le conteneur %s" #: lxc/profile.go:228 #, c-format msgid "Profile %s applied to %s" msgstr "" #: lxc/profile.go:142 #, c-format msgid "Profile %s created" msgstr "" #: lxc/profile.go:212 #, c-format msgid "Profile %s deleted" msgstr "" #: lxc/init.go:136 lxc/init.go:137 lxc/launch.go:42 lxc/launch.go:43 msgid "Profile to apply to the new container" msgstr "" #: lxc/info.go:101 #, fuzzy, c-format msgid "Profiles: %s" msgstr "Mauvaise URL pour le conteneur %s" #: lxc/image.go:343 msgid "Properties:" msgstr "" #: lxc/remote.go:56 msgid "Public image server" msgstr "" #: lxc/image.go:331 #, c-format msgid "Public: %s" msgstr "" #: lxc/publish.go:25 msgid "" "Publish containers as images.\n" "\n" "lxc publish [remote:]container [remote:] [--alias=ALIAS]... [prop-key=prop-" "value]..." msgstr "" #: lxc/remote.go:54 msgid "Remote admin password" msgstr "" #: lxc/delete.go:42 #, c-format msgid "Remove %s (yes/no): " msgstr "" #: lxc/delete.go:36 lxc/delete.go:37 msgid "Require user confirmation." msgstr "" #: lxc/info.go:124 msgid "Resources:" msgstr "" #: lxc/init.go:246 #, c-format msgid "Retrieving image: %s" msgstr "" #: lxc/image.go:609 msgid "SIZE" msgstr "" #: lxc/list.go:372 msgid "SNAPSHOTS" msgstr "" #: lxc/list.go:373 msgid "STATE" msgstr "" #: lxc/remote.go:367 msgid "STATIC" msgstr "" #: lxc/remote.go:214 msgid "Server certificate NACKed by user" msgstr "Le certificat serveur a été rejeté par l'utilisateur" #: lxc/remote.go:276 msgid "Server doesn't trust us after adding our cert" msgstr "Identification refuse après l'ajout du certificat client" #: lxc/remote.go:55 msgid "Server protocol (lxd or simplestreams)" msgstr "" #: lxc/restore.go:21 msgid "" "Set the current state of a resource back to a snapshot.\n" "\n" "lxc restore [remote:] [--stateful]\n" "\n" "Restores a container from a snapshot (optionally with running state, see\n" "snapshot help for details).\n" "\n" "For example:\n" "lxc snapshot u1 snap0 # create the snapshot\n" "lxc restore u1 snap0 # restore the snapshot" msgstr "" #: lxc/file.go:44 msgid "Set the file's gid on push" msgstr "Définit le gid lors de l'envoi" #: lxc/file.go:45 msgid "Set the file's perms on push" msgstr "Définit les permissions lors de l'envoi" #: lxc/file.go:43 msgid "Set the file's uid on push" msgstr "Définit le uid lors de l'envoi" #: lxc/help.go:32 msgid "Show all commands (not just interesting ones)" msgstr "Affiche toutes les comandes (pas seulement les intéresantes)" #: lxc/info.go:36 msgid "Show the container's last 100 log lines?" msgstr "" #: lxc/image.go:329 #, c-format msgid "Size: %.2fMB" msgstr "" #: lxc/info.go:194 msgid "Snapshots:" msgstr "" #: lxc/image.go:353 msgid "Source:" msgstr "" #: lxc/launch.go:122 #, c-format msgid "Starting %s" msgstr "" #: lxc/info.go:95 #, c-format msgid "Status: %s" msgstr "" #: lxc/publish.go:34 lxc/publish.go:35 msgid "Stop the container if currently running" msgstr "" #: lxc/delete.go:106 lxc/publish.go:111 msgid "Stopping container failed!" msgstr "L'arrêt du conteneur a échoué!" #: lxc/action.go:38 #, fuzzy msgid "Store the container state (only for stop)." msgstr "Force l'arrêt du conteneur." #: lxc/info.go:155 msgid "Swap (current)" msgstr "" #: lxc/info.go:159 msgid "Swap (peak)" msgstr "" #: lxc/list.go:374 msgid "TYPE" msgstr "" #: lxc/delete.go:92 msgid "The container is currently running, stop it first or pass --force." msgstr "" #: lxc/publish.go:89 msgid "" "The container is currently running. Use --force to have it stopped and " "restarted." msgstr "" #: lxc/config.go:645 lxc/config.go:657 lxc/config.go:690 lxc/config.go:708 #: lxc/config.go:746 lxc/config.go:764 #, fuzzy msgid "The device doesn't exist" msgstr "le serveur distant %s n'existe pas" #: lxc/publish.go:62 msgid "There is no \"image name\". Did you want an alias?" msgstr "" #: lxc/action.go:36 msgid "Time to wait for the container before killing it." msgstr "Temps d'attente avant de tuer le conteneur." #: lxc/image.go:332 msgid "Timestamps:" msgstr "" #: lxc/image.go:402 #, c-format msgid "Transferring image: %d%%" msgstr "" #: lxc/action.go:93 lxc/launch.go:130 #, c-format msgid "Try `lxc info --show-log %s` for more info" msgstr "" #: lxc/info.go:97 msgid "Type: ephemeral" msgstr "" #: lxc/info.go:99 msgid "Type: persistent" msgstr "" #: lxc/image.go:610 msgid "UPLOAD DATE" msgstr "" #: lxc/remote.go:364 msgid "URL" msgstr "" #: lxc/remote.go:82 msgid "Unable to read remote TLS certificate" msgstr "" #: lxc/image.go:337 #, c-format msgid "Uploaded: %s" msgstr "" #: lxc/main.go:122 #, fuzzy, c-format msgid "Usage: %s" msgstr "" "Utilisation: %s\n" "\n" "Options:\n" "\n" #: lxc/help.go:48 #, fuzzy msgid "Usage: lxc [subcommand] [options]" msgstr "" "Utilisation: lxc [sous commande] [options]\n" "Comande disponibles:\n" #: lxc/delete.go:46 msgid "User aborted delete operation." msgstr "" #: lxc/restore.go:35 #, fuzzy msgid "" "Whether or not to restore the container's running state from snapshot (if " "available)" msgstr "" "Est-ce que l'état de fonctionement du conteneur doit être inclus dans " "l'instantané (snapshot)" #: lxc/snapshot.go:38 msgid "Whether or not to snapshot the container's running state" msgstr "" "Est-ce que l'état de fonctionement du conteneur doit être inclus dans " "l'instantané (snapshot)" #: lxc/config.go:33 msgid "Whether to show the expanded configuration" msgstr "" #: lxc/remote.go:339 lxc/remote.go:344 msgid "YES" msgstr "" #: lxc/main.go:66 msgid "`lxc config profile` is deprecated, please use `lxc profile`" msgstr "" #: lxc/launch.go:109 #, fuzzy msgid "bad number of things scanned from image, container or snapshot" msgstr "nombre de propriété invalide pour la ressource" #: lxc/action.go:89 msgid "bad result type from action" msgstr "mauvais type de réponse pour l'action!" #: lxc/copy.go:78 msgid "can't copy to the same container name" msgstr "" #: lxc/remote.go:327 msgid "can't remove the default remote" msgstr "" #: lxc/remote.go:353 msgid "default" msgstr "" #: lxc/init.go:199 lxc/init.go:204 lxc/launch.go:93 lxc/launch.go:98 #, fuzzy msgid "didn't get any affected image, container or snapshot from server" msgstr "N'a pas pû obtenir de resource du serveur" #: lxc/image.go:323 msgid "disabled" msgstr "" #: lxc/image.go:325 msgid "enabled" msgstr "" #: lxc/main.go:25 lxc/main.go:158 #, fuzzy, c-format msgid "error: %v" msgstr "erreur: %v\n" #: lxc/help.go:40 lxc/main.go:117 #, fuzzy, c-format msgid "error: unknown command: %s" msgstr "erreur: comande inconnue: %s\n" #: lxc/launch.go:113 msgid "got bad version" msgstr "reçu une version invalide" #: lxc/image.go:318 lxc/image.go:586 msgid "no" msgstr "" #: lxc/copy.go:101 msgid "not all the profiles from the source exist on the target" msgstr "" #: lxc/remote.go:207 #, fuzzy msgid "ok (y/n)?" msgstr "ok (y/n)?" #: lxc/main.go:265 lxc/main.go:269 #, c-format msgid "processing aliases failed %s\n" msgstr "" #: lxc/remote.go:389 #, c-format msgid "remote %s already exists" msgstr "le serveur distant %s existe déjà" #: lxc/remote.go:319 lxc/remote.go:381 lxc/remote.go:416 lxc/remote.go:432 #, c-format msgid "remote %s doesn't exist" msgstr "le serveur distant %s n'existe pas" #: lxc/remote.go:302 #, c-format msgid "remote %s exists as <%s>" msgstr "le serveur distant %s existe en tant que <%s>" #: lxc/remote.go:323 lxc/remote.go:385 lxc/remote.go:420 #, c-format msgid "remote %s is static and cannot be modified" msgstr "" #: lxc/info.go:205 msgid "stateful" msgstr "" #: lxc/info.go:207 msgid "stateless" msgstr "" #: lxc/info.go:201 #, c-format msgid "taken at %s" msgstr "" #: lxc/exec.go:166 msgid "unreachable return reached" msgstr "Un retour inacessible à été atteint" #: lxc/main.go:198 msgid "wrong number of subcommand arguments" msgstr "nombre d'argument incorrect pour la sous-comande" #: lxc/delete.go:45 lxc/image.go:320 lxc/image.go:590 msgid "yes" msgstr "" #: lxc/copy.go:38 msgid "you must specify a source container name" msgstr "" #, fuzzy #~ msgid "Bad image property: %s" #~ msgstr "(Image invalide: %s\n" #, fuzzy #~ msgid "" #~ "Create a read-only snapshot of a container.\n" #~ "\n" #~ "lxc snapshot [remote:] [--stateful]" #~ msgstr "Prend un instantané (snapshot) en lecture seule d'un conteneur.\n" #~ msgid "No certificate on this connection" #~ msgstr "Aucun certificat pour cette connexion" #, fuzzy #~ msgid "" #~ "Set the current state of a resource back to its state at the time the " #~ "snapshot was created.\n" #~ "\n" #~ "lxc restore [remote:] [--stateful]" #~ msgstr "Prend un instantané (snapshot) en lecture seule d'un conteneur.\n" #~ msgid "api version mismatch: mine: %q, daemon: %q" #~ msgstr "Version de l'API incompatible: local: %q, distant: %q" #, fuzzy #~ msgid "bad version in profile url" #~ msgstr "version invalide dans l'URL du conteneur" #, fuzzy #~ msgid "device already exists" #~ msgstr "le serveur distant %s existe déjà" #, fuzzy #~ msgid "error." #~ msgstr "erreur: %v\n" #~ msgid "got bad op status %s" #~ msgstr "reçu un status d'opration invalide %s" #, fuzzy #~ msgid "got bad response type, expected %s got %s" #~ msgstr "reçu une mauvaise réponse pour \"exec\"" #~ msgid "invalid wait url %s" #~ msgstr "URL d'attente invalide %s" #~ msgid "no response!" #~ msgstr "pas de réponse!" #~ msgid "unknown remote name: %q" #~ msgstr "serveur distant inconnu: %q" #, fuzzy #~ msgid "unknown transport type: %s" #~ msgstr "serveur distant inconnu: %q" #~ msgid "cannot resolve unix socket address: %v" #~ msgstr "Ne peut pas résoudre l'adresse du unix socket: %v" #, fuzzy #~ msgid "unknown group %s" #~ msgstr "serveur distant inconnu: %q" #, fuzzy #~ msgid "Information about remotes not yet supported" #~ msgstr "" #~ "Il n'est pas encore possible d'obtenir de l'information sur un serveur " #~ "distant\n" #~ msgid "Unknown image command %s" #~ msgstr "Comande d'image inconnue %s" #~ msgid "Unknown remote subcommand %s" #~ msgstr "Comande de serveur distant inconnue %s" #~ msgid "Unkonwn config trust command %s" #~ msgstr "Comande de configuration de confiance inconnue %s" #, fuzzy #~ msgid "YAML parse error %v" #~ msgstr "erreur: %v\n" #~ msgid "invalid argument %s" #~ msgstr "Arguments invalides %s" #, fuzzy #~ msgid "unknown profile cmd %s" #~ msgstr "Comande de configuration inconue %s" #, fuzzy #~ msgid "Publish to remote server is not supported yet" #~ msgstr "" #~ "Il n'est pas encore possible d'obtenir de l'information sur un serveur " #~ "distant\n" #, fuzzy #~ msgid "Use an alternative config path." #~ msgstr "Dossier de configuration alternatif." #, fuzzy #~ msgid "" #~ "error: %v\n" #~ "%s\n" #~ msgstr "" #~ "erreur: %v\n" #~ "%s" #, fuzzy #~ msgid "Show for remotes is not yet supported\n" #~ msgstr "" #~ "Il n'est pas encore possible d'obtenir de l'information sur un serveur " #~ "distant\n" #~ msgid "(Bad alias entry: %s\n" #~ msgstr "(Alias invalide: %s\n" #~ msgid "bad container url %s" #~ msgstr "Mauvaise URL pour le conteneur %s" #~ msgid "bad version in container url" #~ msgstr "version invalide dans l'URL du conteneur" #, fuzzy #~ msgid "Ephemeral containers not yet supported\n" #~ msgstr "" #~ "Il n'est pas encore possible d'obtenir de l'information sur un serveur " #~ "distant\n" #~ msgid "(Bad image entry: %s\n" #~ msgstr "(Image invalide: %s\n" #~ msgid "Certificate already stored.\n" #~ msgstr "Le certificat a déjà été enregistré.\n" #, fuzzy #~ msgid "Non-async response from delete!" #~ msgstr "Réponse invalide (non-async) durant la suppression!" #, fuzzy #~ msgid "Non-async response from init!" #~ msgstr "" #~ "Réponse invalide (non-async) durant la cration d'un instantané (snapshot)!" #~ msgid "Non-async response from snapshot!" #~ msgstr "" #~ "Réponse invalide (non-async) durant la cration d'un instantané (snapshot)!" #~ msgid "Server certificate has changed" #~ msgstr "Le certificat serveur a changé" #, fuzzy #~ msgid "Unexpected non-async response" #~ msgstr "Réponse invalide (non-async) durant la suppression!" #~ msgid "bad response type from image list!" #~ msgstr "mauvais type de réponse pour la liste d'image!" #~ msgid "bad response type from list!" #~ msgstr "mauvais type de réponse pour la liste!" #, fuzzy #~ msgid "got non-async response!" #~ msgstr "Réponse invalide (non-async) durant la suppression!" #~ msgid "got non-sync response from containers get!" #~ msgstr "Réponse invalide (non-async) durant le chargement!" #~ msgid "Delete a container or container snapshot.\n" #~ msgstr "Supprime un conteneur ou l'instantané (snapshot) d'un conteneur.\n" #~ msgid "List information on containers.\n" #~ msgstr "Liste de l'information sur les conteneurs.\n" #~ msgid "Lists the available resources.\n" #~ msgstr "Liste des ressources disponibles.\n" #~ msgid "Manage files on a container.\n" #~ msgstr "Gérer les fichiers du conteneur.\n" #~ msgid "Manage remote lxc servers.\n" #~ msgstr "Gérer les serveurs distants.\n" #~ msgid "Non-async response from create!" #~ msgstr "Réponse invalide (non-async) durant la cration!" #~ msgid "Only 'password' can be set currently" #~ msgstr "Seul 'password' peut être configuré en ce moment" #~ msgid "" #~ "lxc image import [target] [--created-at=ISO-8601] [--expires-" #~ "at=ISO-8601] [--fingerprint=HASH] [prop=value]\n" #~ msgstr "" #~ "lxc image import [destination] [--created-at=ISO-8601] [--" #~ "expires-at=ISO-8601] [--fingerprint=HASH] [proprit=valeur]\n" #~ msgid "lxc init ubuntu []\n" #~ msgstr "lxc init ubuntu []\n" #~ msgid "lxc launch ubuntu []\n" #~ msgstr "lxc launch ubuntu []\n" lxd-2.0.0/po/ja.po000066400000000000000000001633441270277227600136770ustar00rootroot00000000000000# Japanese translation for LXD # Copyright (C) 2015 - LXD contributors # This file is distributed under the same license as LXD. # Hiroaki Nakamura , 2015. # msgid "" msgstr "" "Project-Id-Version: LXD\n" "Report-Msgid-Bugs-To: lxc-devel@lists.linuxcontainers.org\n" "POT-Creation-Date: 2016-04-11 15:01-0400\n" "PO-Revision-Date: 2016-04-10 23:40+0900\n" "Last-Translator: KATOH Yasufumi \n" "Language-Team: Japanese \n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: lxc/info.go:140 msgid " Disk usage:" msgstr " ディスク使用é‡:" #: lxc/info.go:163 msgid " Memory usage:" msgstr " メモリ消費é‡:" #: lxc/info.go:180 msgid " Network usage:" msgstr " ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ä½¿ç”¨çжæ³:" #: lxc/config.go:37 msgid "" "### This is a yaml representation of the configuration.\n" "### Any line starting with a '# will be ignored.\n" "###\n" "### A sample configuration looks like:\n" "### name: container1\n" "### profiles:\n" "### - default\n" "### config:\n" "### volatile.eth0.hwaddr: 00:16:3e:e9:f8:7f\n" "### devices:\n" "### homedir:\n" "### path: /extra\n" "### source: /home/user\n" "### type: disk\n" "### ephemeral: false\n" "###\n" "### Note that the name is shown but cannot be changed" msgstr "" #: lxc/image.go:83 msgid "" "### This is a yaml representation of the image properties.\n" "### Any line starting with a '# will be ignored.\n" "###\n" "### Each property is represented by a single line:\n" "### An example would be:\n" "### description: My custom image" msgstr "" #: lxc/profile.go:27 msgid "" "### This is a yaml representation of the profile.\n" "### Any line starting with a '# will be ignored.\n" "###\n" "### A profile consists of a set of configuration items followed by a set of\n" "### devices.\n" "###\n" "### An example would look like:\n" "### name: onenic\n" "### config:\n" "### raw.lxc: lxc.aa_profile=unconfined\n" "### devices:\n" "### eth0:\n" "### nictype: bridged\n" "### parent: lxdbr0\n" "### type: nic\n" "###\n" "### Note that the name is shown but cannot be changed" msgstr "" #: lxc/image.go:583 #, c-format msgid "%s (%d more)" msgstr "" #: lxc/snapshot.go:61 msgid "'/' not allowed in snapshot name" msgstr "'/' ã¯ã‚¹ãƒŠãƒƒãƒ—ショットã®åå‰ã«ã¯ä½¿ç”¨ã§ãã¾ã›ã‚“。" #: lxc/profile.go:226 msgid "(none)" msgstr "" #: lxc/image.go:604 lxc/image.go:633 msgid "ALIAS" msgstr "" #: lxc/image.go:608 msgid "ARCH" msgstr "" #: lxc/list.go:367 msgid "ARCHITECTURE" msgstr "" #: lxc/remote.go:53 msgid "Accept certificate" msgstr "証明書ã®ãƒ•ィンガープリントã®ç¢ºèªãªã—ã§è¨¼æ˜Žæ›¸ã‚’å—ã‘入れã¾ã™" #: lxc/remote.go:256 #, c-format msgid "Admin password for %s: " msgstr "%s ã®ç®¡ç†è€…パスワード: " #: lxc/image.go:347 msgid "Aliases:" msgstr "エイリアス:" #: lxc/exec.go:54 msgid "An environment variable of the form HOME=/home/foo" msgstr "環境変数を HOME=/home/foo ã®å½¢å¼ã§æŒ‡å®šã—ã¾ã™" #: lxc/image.go:330 lxc/info.go:90 #, c-format msgid "Architecture: %s" msgstr "アーキテクãƒãƒ£: %s" #: lxc/image.go:351 #, c-format msgid "Auto update: %s" msgstr "自動更新: %s" #: lxc/help.go:49 msgid "Available commands:" msgstr "使用å¯èƒ½ãªã‚³ãƒžãƒ³ãƒ‰:" #: lxc/info.go:172 msgid "Bytes received" msgstr "å—ä¿¡ãƒã‚¤ãƒˆæ•°" #: lxc/info.go:173 msgid "Bytes sent" msgstr "é€ä¿¡ãƒã‚¤ãƒˆæ•°" #: lxc/config.go:270 msgid "COMMON NAME" msgstr "" #: lxc/list.go:368 msgid "CREATED AT" msgstr "" #: lxc/config.go:114 #, c-format msgid "Can't read from stdin: %s" msgstr "標準入力ã‹ã‚‰èª­ã¿è¾¼ã‚ã¾ã›ã‚“: %s" #: lxc/config.go:127 lxc/config.go:160 lxc/config.go:182 #, c-format msgid "Can't unset key '%s', it's not currently set." msgstr "キー '%s' ãŒæŒ‡å®šã•れã¦ã„ãªã„ã®ã§å‰Šé™¤ã§ãã¾ã›ã‚“。" #: lxc/profile.go:343 msgid "Cannot provide container name to list" msgstr "コンテナåã‚’å–å¾—ã§ãã¾ã›ã‚“" #: lxc/remote.go:206 #, c-format msgid "Certificate fingerprint: %x" msgstr "証明書ã®ãƒ•ィンガープリント: %x" #: lxc/action.go:28 #, c-format msgid "" "Changes state of one or more containers to %s.\n" "\n" "lxc %s [...]" msgstr "" "コンテナã®çŠ¶æ…‹ã‚’ %s ã«å¤‰æ›´ã—ã¾ã™ã€‚\n" "\n" "lxc %s [...]" #: lxc/remote.go:279 msgid "Client certificate stored at server: " msgstr "クライアント証明書ãŒã‚µãƒ¼ãƒã«æ ¼ç´ã•れã¾ã—ãŸ: " #: lxc/list.go:97 lxc/list.go:98 msgid "Columns" msgstr "カラムレイアウト" #: lxc/init.go:134 lxc/init.go:135 lxc/launch.go:40 lxc/launch.go:41 msgid "Config key/value to apply to the new container" msgstr "設定キー/値ã®çµ„ã‚’æ–°ã—ã„コンテナã«é©ç”¨ã—ã¾ã—ãŸ" #: lxc/config.go:500 lxc/config.go:565 lxc/image.go:687 lxc/profile.go:190 #, c-format msgid "Config parsing error: %s" msgstr "è¨­å®šã®æ§‹æ–‡ã‚¨ãƒ©ãƒ¼: %s" #: lxc/main.go:37 msgid "Connection refused; is LXD running?" msgstr "æŽ¥ç¶šãŒæ‹’å¦ã•れã¾ã—ãŸã€‚LXDãŒå®Ÿè¡Œã•れã¦ã„ã¾ã™ã‹?" #: lxc/publish.go:59 msgid "Container name is mandatory" msgstr "コンテナåを指定ã™ã‚‹å¿…è¦ãŒã‚りã¾ã™" #: lxc/init.go:209 #, c-format msgid "Container name is: %s" msgstr "コンテナå: %s" #: lxc/publish.go:141 lxc/publish.go:156 #, c-format msgid "Container published with fingerprint: %s" msgstr "コンテナã¯ä»¥ä¸‹ã®ãƒ•ィンガープリント㧠publish ã•れã¾ã™: %s" #: lxc/image.go:155 msgid "Copy aliases from source" msgstr "ソースã‹ã‚‰ã‚¨ã‚¤ãƒªã‚¢ã‚¹ã‚’コピーã—ã¾ã—ãŸ" #: lxc/copy.go:22 msgid "" "Copy containers within or in between lxd instances.\n" "\n" "lxc copy [remote:] [remote:] [--" "ephemeral|e]" msgstr "" "LXDインスタンス内もã—ãã¯LXDインスタンス間ã§ã‚³ãƒ³ãƒ†ãƒŠã‚’コピーã—ã¾ã™ã€‚\n" "\n" "lxc copy [remote:] [remote:] [--" "ephemeral|e]" #: lxc/image.go:268 #, c-format msgid "Copying the image: %s" msgstr "イメージã®ã‚³ãƒ”ー中: %s" #: lxc/remote.go:221 msgid "Could not create server cert dir" msgstr "サーãƒè¨¼æ˜Žæ›¸æ ¼ç´ç”¨ã®ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã‚’作æˆã§ãã¾ã›ã‚“。" #: lxc/snapshot.go:21 msgid "" "Create a read-only snapshot of a container.\n" "\n" "lxc snapshot [remote:] [--stateful]\n" "\n" "Creates a snapshot of the container (optionally with the container's memory\n" "state). When --stateful is used, LXD attempts to checkpoint the container's\n" "running state, including process memory state, TCP connections, etc. so that " "it\n" "can be restored (via lxc restore) at a later time (although some things, e." "g.\n" "TCP connections after the TCP timeout window has expired, may not be " "restored\n" "successfully).\n" "\n" "Example:\n" "lxc snapshot u1 snap0" msgstr "" "コンテナã®èª­ã¿å–り専用ã®ã‚¹ãƒŠãƒƒãƒ—ショットを作æˆã—ã¾ã™ã€‚\n" "\n" "lxc snapshot [remote:] [--stateful]\n" "\n" "コンテナã®ã‚¹ãƒŠãƒƒãƒ—ショットを作æˆã—ã¾ã™ (オプションã§ã‚³ãƒ³ãƒ†ãƒŠã®ãƒ¡ãƒ¢ãƒªçŠ¶æ…‹ã‚’\n" "å«ã‚ã¦)。--statefulãŒæŒ‡å®šã•れãŸå ´åˆã€LXDã¯ã‚³ãƒ³ãƒ†ãƒŠãƒ—ロセスã®ãƒ¡ãƒ¢ãƒªçŠ¶æ…‹ã€TCP\n" "接続ãªã©ã®å®Ÿè¡ŒçŠ¶æ…‹ã‚’ã€ã‚ã¨ã§lxc restoreを使ã£ã¦ãƒªã‚¹ãƒˆã‚¢ã§ãるよã†ã«ã€ã‚³ãƒ³ãƒ†\n" "ナã®ãƒã‚§ãƒƒã‚¯ãƒã‚¤ãƒ³ãƒˆã‚’å–å¾—ã—よã†ã¨ã—ã¾ã™ (ã—ã‹ã—ã€ã‚¿ã‚¤ãƒ ã‚¢ã‚¦ãƒˆã‚¦ã‚£ãƒ³ãƒ‰ã‚¦ãŒ\n" "expireã—ãŸã‚ã¨ã®TCP接続ã®ã‚ˆã†ã«æ­£å¸¸ã«ãƒªã‚¹ãƒˆã‚¢ã§ããªã„ã‚‚ã®ã‚‚ã‚りã¾ã™)\n" "\n" "例:\n" "lxc snapshot u1 snap0" #: lxc/image.go:335 lxc/info.go:92 #, c-format msgid "Created: %s" msgstr "ä½œæˆæ—¥æ™‚: %s" #: lxc/init.go:177 lxc/launch.go:116 #, c-format msgid "Creating %s" msgstr "%s を作æˆä¸­" #: lxc/init.go:175 msgid "Creating the container" msgstr "コンテナを作æˆä¸­" #: lxc/image.go:607 lxc/image.go:635 msgid "DESCRIPTION" msgstr "" #: lxc/delete.go:25 msgid "" "Delete containers or container snapshots.\n" "\n" "lxc delete [remote:][/] [remote:][[/" "]...]\n" "\n" "Destroy containers or snapshots with any attached data (configuration, " "snapshots, ...)." msgstr "" "コンテナもã—ãã¯ã‚³ãƒ³ãƒ†ãƒŠã®ã‚¹ãƒŠãƒƒãƒ—ショットを消去ã—ã¾ã™ã€‚\n" "\n" "lxc delete [remote:][/] [remote:]" "[[]...]\n" "\n" "付属ã™ã‚‹ãƒ‡ãƒ¼ã‚¿ (設定ã€ã‚¹ãƒŠãƒƒãƒ—ショットã€...) ã¨ä¸€ç·’ã«ã‚³ãƒ³ãƒ†ãƒŠã‚‚ã—ãã¯ã‚³ãƒ³ãƒ†\n" "ナã®ã‚¹ãƒŠãƒƒãƒ—ショットを消去ã—ã¾ã™ã€‚" #: lxc/config.go:617 #, c-format msgid "Device %s added to %s" msgstr "デãƒã‚¤ã‚¹ %s ㌠%s ã«è¿½åŠ ã•れã¾ã—ãŸ" #: lxc/config.go:804 #, c-format msgid "Device %s removed from %s" msgstr "デãƒã‚¤ã‚¹ %s ㌠%s ã‹ã‚‰å‰Šé™¤ã•れã¾ã—ãŸ" #: lxc/list.go:451 msgid "EPHEMERAL" msgstr "" #: lxc/config.go:272 msgid "EXPIRY DATE" msgstr "" #: lxc/main.go:55 msgid "Enables debug mode." msgstr "デãƒãƒƒã‚°ãƒ¢ãƒ¼ãƒ‰ã‚’有効ã«ã—ã¾ã™ã€‚" #: lxc/main.go:54 msgid "Enables verbose mode." msgstr "詳細モードを有効ã«ã—ã¾ã™ã€‚" #: lxc/help.go:68 msgid "Environment:" msgstr "環境変数:" #: lxc/copy.go:29 lxc/copy.go:30 lxc/init.go:138 lxc/init.go:139 #: lxc/launch.go:44 lxc/launch.go:45 msgid "Ephemeral container" msgstr "Ephemeral コンテナ" #: lxc/monitor.go:56 msgid "Event type to listen for" msgstr "Listenã™ã‚‹ã‚¤ãƒ™ãƒ³ãƒˆã‚¿ã‚¤ãƒ—" #: lxc/exec.go:45 msgid "" "Execute the specified command in a container.\n" "\n" "lxc exec [remote:]container [--mode=auto|interactive|non-interactive] [--env " "EDITOR=/usr/bin/vim]... \n" "\n" "Mode defaults to non-interactive, interactive mode is selected if both stdin " "AND stdout are terminals (stderr is ignored)." msgstr "" "ã‚³ãƒ³ãƒ†ãƒŠã§æŒ‡å®šã—ãŸã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã—ã¾ã™ã€‚\n" "\n" "lxc exec [remote:]container [--mode=auto|interactive|non-interactive] [--env " "EDITOR=/usr/bin/vim]... \n" "\n" "デフォルトã®ãƒ¢ãƒ¼ãƒ‰ã¯ non-interactive ã§ã™ã€‚ã‚‚ã—æ¨™æº–入出力ãŒä¸¡æ–¹ã¨ã‚‚ターミナ\n" "ルã®å ´åˆã¯ interactive モードãŒé¸æŠžã•れã¾ã™ (標準エラー出力ã¯ç„¡è¦–ã•れã¾ã™)。" #: lxc/image.go:339 #, c-format msgid "Expires: %s" msgstr "失効日時: %s" #: lxc/image.go:341 msgid "Expires: never" msgstr "失効日時: 失効ã—ãªã„" #: lxc/config.go:269 lxc/image.go:605 lxc/image.go:634 msgid "FINGERPRINT" msgstr "" #: lxc/list.go:100 msgid "Fast mode (same as --columns=nsacPt" msgstr "Fast モード (--columns=nsacPt ã¨åŒã˜)" #: lxc/image.go:328 #, c-format msgid "Fingerprint: %s" msgstr "証明書ã®ãƒ•ィンガープリント: %s" #: lxc/finger.go:17 msgid "" "Fingers the LXD instance to check if it is up and working.\n" "\n" "lxc finger " msgstr "" "LXDインスタンスãŒç¨¼åƒä¸­ã‹ã‚’確èªã—ã¾ã™ã€‚\n" "\n" "lxc finger " #: lxc/action.go:37 msgid "Force the container to shutdown." msgstr "コンテナを強制シャットダウンã—ã¾ã™ã€‚" #: lxc/delete.go:34 lxc/delete.go:35 msgid "Force the removal of stopped containers." msgstr "åœæ­¢ã—ãŸã‚³ãƒ³ãƒ†ãƒŠã‚’強制的ã«å‰Šé™¤ã—ã¾ã™ã€‚" #: lxc/main.go:56 msgid "Force using the local unix socket." msgstr "強制的ã«ãƒ­ãƒ¼ã‚«ãƒ«ã®UNIXソケットを使ã„ã¾ã™ã€‚" #: lxc/list.go:99 msgid "Format" msgstr "" #: lxc/main.go:138 msgid "Generating a client certificate. This may take a minute..." msgstr "クライアント証明書を生æˆã—ã¾ã™ã€‚1分ãらã„ã‹ã‹ã‚Šã¾ã™..." #: lxc/list.go:365 msgid "IPV4" msgstr "" #: lxc/list.go:366 msgid "IPV6" msgstr "" #: lxc/config.go:271 msgid "ISSUE DATE" msgstr "" #: lxc/main.go:146 msgid "" "If this is your first time using LXD, you should also run: sudo lxd init" msgstr "åˆã‚㦠LXD を使ã†å ´åˆã€sudo lxd init ã¨å®Ÿè¡Œã™ã‚‹å¿…è¦ãŒã‚りã¾ã™" #: lxc/main.go:57 msgid "Ignore aliases when determining what command to run." msgstr "コマンドを実行ã™ã‚‹éš›ã«ã‚¨ã‚¤ãƒªã‚¢ã‚¹ã‚’無視ã—ã¾ã™ã€‚" #: lxc/action.go:39 msgid "Ignore the container state (only forstart)." msgstr "コンテナã®çŠ¶æ…‹ã‚’ç„¡è¦–ã—ã¾ã™ (startã®ã¿)。" #: lxc/image.go:273 msgid "Image copied successfully!" msgstr "イメージã®ã‚³ãƒ”ãƒ¼ãŒæˆåŠŸã—ã¾ã—ãŸ!" #: lxc/image.go:419 #, c-format msgid "Image imported with fingerprint: %s" msgstr "イメージã¯ä»¥ä¸‹ã®ãƒ•ィンガープリントã§ã‚¤ãƒ³ãƒãƒ¼ãƒˆã•れã¾ã—ãŸ: %s" #: lxc/init.go:73 msgid "" "Initialize a container from a particular image.\n" "\n" "lxc init [remote:] [remote:][] [--ephemeral|-e] [--profile|-p " "...] [--config|-c ...]\n" "\n" "Initializes a container using the specified image and name.\n" "\n" "Not specifying -p will result in the default profile.\n" "Specifying \"-p\" with no argument will result in no profile.\n" "\n" "Example:\n" "lxc init ubuntu u1" msgstr "" "指定ã—ãŸã‚¤ãƒ¡ãƒ¼ã‚¸ã‹ã‚‰ã‚³ãƒ³ãƒ†ãƒŠã‚’åˆæœŸåŒ–ã—ã¾ã™ã€‚\n" "\n" "lxc init [remote:] [remote:][] [--ephemeral|-e] [--profile|-p " "...] [--config|-c ...]\n" "\n" "指定ã—ãŸã‚¤ãƒ¡ãƒ¼ã‚¸ã¨ã‚³ãƒ³ãƒ†ãƒŠåを使ã£ã¦ã‚³ãƒ³ãƒ†ãƒŠã‚’åˆæœŸåŒ–ã—ã¾ã™ã€‚\n" "\n" "-p を指定ã—ãªã„å ´åˆã¯ãƒ‡ãƒ•ォルトã®ãƒ—ロファイルを使ã„ã¾ã™ã€‚\n" "\"-p\" ã®ã‚ˆã†ã«å¼•æ•°ãªã—ã§ -p を使ã†ã¨ãƒ—ロファイルãªã—ã¨ãªã‚Šã¾ã™ã€‚\n" "\n" "例:\n" "lxc init ubuntu u1" #: lxc/remote.go:122 #, c-format msgid "Invalid URL scheme \"%s\" in \"%s\"" msgstr "䏿­£ãª URL スキーム \"%s\" (\"%s\" 内)" #: lxc/init.go:30 lxc/init.go:35 msgid "Invalid configuration key" msgstr "æ­£ã—ããªã„設定項目 (key) ã§ã™" #: lxc/file.go:190 #, c-format msgid "Invalid source %s" msgstr "䏿­£ãªã‚½ãƒ¼ã‚¹ %s" #: lxc/file.go:57 #, c-format msgid "Invalid target %s" msgstr "䏿­£ãªé€ã‚Šå…ˆ %s" #: lxc/info.go:121 msgid "Ips:" msgstr "IPアドレス:" #: lxc/image.go:156 msgid "Keep the image up to date after initial copy" msgstr "最åˆã«ã‚³ãƒ”ーã—ãŸå¾Œã‚‚常ã«ã‚¤ãƒ¡ãƒ¼ã‚¸ã‚’最新ã®çŠ¶æ…‹ã«ä¿ã¤" #: lxc/main.go:35 msgid "LXD socket not found; is LXD running?" msgstr "LXD ã®ã‚½ã‚±ãƒƒãƒˆãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。LXD ãŒå®Ÿè¡Œã•れã¦ã„ã¾ã™ã‹?" #: lxc/launch.go:22 msgid "" "Launch a container from a particular image.\n" "\n" "lxc launch [remote:] [remote:][] [--ephemeral|-e] [--profile|-p " "...] [--config|-c ...]\n" "\n" "Launches a container using the specified image and name.\n" "\n" "Not specifying -p will result in the default profile.\n" "Specifying \"-p\" with no argument will result in no profile.\n" "\n" "Example:\n" "lxc launch ubuntu u1" msgstr "" "指定ã—ãŸã‚¤ãƒ¡ãƒ¼ã‚¸ã‹ã‚‰ã‚³ãƒ³ãƒ†ãƒŠã‚’èµ·å‹•ã—ã¾ã™ã€‚\n" "\n" "lxc launch [remote:] [remote:][] [--ephemeral|-e] [--profile|-p " "...] [--config|-c ...]\n" "\n" "指定ã—ãŸã‚¤ãƒ¡ãƒ¼ã‚¸ã¨åå‰ã‚’使ã£ã¦ã‚³ãƒ³ãƒ†ãƒŠã‚’èµ·å‹•ã—ã¾ã™ã€‚\n" "\n" "-p を指定ã—ãªã„å ´åˆã¯ãƒ‡ãƒ•ォルトã®ãƒ—ロファイルを使ã„ã¾ã™ã€‚\n" "\"-p\" ã®ã‚ˆã†ã«å¼•æ•°ãªã—ã§ -p を使ã†ã¨ãƒ—ロファイルãªã—ã¨ãªã‚Šã¾ã™ã€‚" #: lxc/info.go:25 msgid "" "List information on LXD servers and containers.\n" "\n" "For a container:\n" " lxc info [:]container [--show-log]\n" "\n" "For a server:\n" " lxc info [:]" msgstr "" "LXD サーãƒã¨ã‚³ãƒ³ãƒ†ãƒŠã®æƒ…報を一覧表示ã—ã¾ã™ã€‚\n" "\n" "コンテナ情報:\n" " lxc info [:]container [--show-log]\n" "\n" "ã‚µãƒ¼ãƒæƒ…å ±:\n" " lxc info [:]" #: lxc/list.go:67 msgid "" "Lists the available resources.\n" "\n" "lxc list [resource] [filters] [--format table|json] [-c columns] [--fast]\n" "\n" "The filters are:\n" "* A single keyword like \"web\" which will list any container with \"web\" " "in its name.\n" "* A key/value pair referring to a configuration item. For those, the " "namespace can be abreviated to the smallest unambiguous identifier:\n" "* \"user.blah=abc\" will list all containers with the \"blah\" user property " "set to \"abc\"\n" "* \"u.blah=abc\" will do the same\n" "* \"security.privileged=1\" will list all privileged containers\n" "* \"s.privileged=1\" will do the same\n" "\n" "Columns for table format are:\n" "* 4 - IPv4 address\n" "* 6 - IPv6 address\n" "* a - architecture\n" "* c - creation date\n" "* n - name\n" "* p - pid of container init process\n" "* P - profiles\n" "* s - state\n" "* S - number of snapshots\n" "* t - type (persistent or ephemeral)\n" "\n" "Default column layout: ns46tS\n" "Fast column layout: nsacPt" msgstr "" "利用å¯èƒ½ãªãƒªã‚½ãƒ¼ã‚¹ã‚’一覧表示ã—ã¾ã™ã€‚\n" "\n" "lxc list [resource] [filters] [--format table|json] [-c columns] [--fast]\n" "\n" "ãƒ•ã‚£ãƒ«ã‚¿ã®æŒ‡å®š:\n" "* å˜ä¸€ã® \"web\" ã®ã‚ˆã†ãªã‚­ãƒ¼ãƒ¯ãƒ¼ãƒ‰ã‚’指定ã™ã‚‹ã¨ã€åå‰ã« \"web\" ãŒå«ã¾ã‚Œã‚‹ã‚³" "ンテ\n" " ナãŒä¸€è¦§è¡¨ç¤ºã•れã¾ã™ã€‚\n" "* 設定項目ã®ã‚­ãƒ¼ã¨å€¤ã€‚キーã®åå‰ç©ºé–“ã¯ä¸€æ„ã«è­˜åˆ¥ã§ãã‚‹å ´åˆã¯çŸ­ç¸®ã™ã‚‹ã“ã¨ãŒ" "ã§\n" " ãã¾ã™:\n" "* \"user.blah=abc\" 㯠\"blah\" ã¨ã„ㆠuser プロパティ㌠\"abc\" ã«è¨­å®šã•れã¦" "ã„ã‚‹\n" " コンテナをã™ã¹ã¦ä¸€è¦§è¡¨ç¤ºã—ã¾ã™ã€‚\n" "* \"u.blah\" ã¯ä¸Šè¨˜ã¨åŒã˜æ„味ã«ãªã‚Šã¾ã™ã€‚\n" "* \"security.privileged=1\" ã¯ç‰¹æ¨©ã‚³ãƒ³ãƒ†ãƒŠã‚’ã™ã¹ã¦ä¸€è¦§è¡¨ç¤ºã—ã¾ã™ã€‚\n" "* \"s.privilaged=1\" ã¯ä¸Šè¨˜ã¨åŒã˜æ„味ã«ãªã‚Šã¾ã™ã€‚\n" "\n" "表ã®ã‚«ãƒ©ãƒ ã®æŒ‡å®š:\n" "* 4 - IPv4 アドレス\n" "* 6 - IPv6 アドレス\n" "* a - アーキテクãƒãƒ£\n" "* c - ä½œæˆæ—¥\n" "* n - åå‰\n" "* p - コンテナ㮠init プロセス㮠pid\n" "* P - プロファイル\n" "* s - 状態\n" "* S - ã‚¹ãƒŠãƒƒãƒ—ã‚·ãƒ§ãƒƒãƒˆã®æ•°\n" "* t - タイプ (persistent or ephemeral)\n" "\n" "デフォルトã®ã‚«ãƒ©ãƒ ãƒ¬ã‚¤ã‚¢ã‚¦ãƒˆ: ns46tS\n" "Fast モードã®ã‚«ãƒ©ãƒ ãƒ¬ã‚¤ã‚¢ã‚¦ãƒˆ: nsacPt" #: lxc/info.go:225 msgid "Log:" msgstr "ログ:" #: lxc/image.go:154 msgid "Make image public" msgstr "イメージを public ã«ã™ã‚‹" #: lxc/publish.go:32 msgid "Make the image public" msgstr "イメージを public ã«ã™ã‚‹" #: lxc/profile.go:48 msgid "" "Manage configuration profiles.\n" "\n" "lxc profile list [filters] List available profiles.\n" "lxc profile show Show details of a profile.\n" "lxc profile create Create a profile.\n" "lxc profile copy Copy the profile to the " "specified remote.\n" "lxc profile get Get profile configuration.\n" "lxc profile set Set profile configuration.\n" "lxc profile delete Delete a profile.\n" "lxc profile edit \n" " Edit profile, either by launching external editor or reading STDIN.\n" " Example: lxc profile edit # launch editor\n" " cat profile.yml | lxc profile edit # read from " "profile.yml\n" "lxc profile apply \n" " Apply a comma-separated list of profiles to a container, in order.\n" " All profiles passed in this call (and only those) will be applied\n" " to the specified container.\n" " Example: lxc profile apply foo default,bar # Apply default and bar\n" " lxc profile apply foo default # Only default is active\n" " lxc profile apply '' # no profiles are applied anymore\n" " lxc profile apply bar,default # Apply default second now\n" "\n" "Devices:\n" "lxc profile device list List " "devices in the given profile.\n" "lxc profile device show Show " "full device details in the given profile.\n" "lxc profile device remove Remove a " "device from a profile.\n" "lxc profile device get <[remote:]profile> Get a " "device property.\n" "lxc profile device set <[remote:]profile> Set a " "device property.\n" "lxc profile device unset <[remote:]profile> Unset a " "device property.\n" "lxc profile device add " "[key=value]...\n" " Add a profile device, such as a disk or a nic, to the containers\n" " using the specified profile." msgstr "" "設定プロファイルを管ç†ã—ã¾ã™ã€‚\n" "\n" "lxc profile list [filters]\n" " 利用å¯èƒ½ãªãƒ—ロファイルを一覧ã—ã¾ã™ã€‚\n" "lxc profile show \n" " プロファイルã®è©³ç´°ã‚’表示ã—ã¾ã™ã€‚\n" "lxc profile create \n" " プロファイルを作æˆã—ã¾ã™ã€‚\n" "lxc profile copy \n" " プロファイルを remote ã«ã‚³ãƒ”ーã—ã¾ã™ã€‚\n" "lxc profile get \n" " プロファイルã®è¨­å®šã‚’å–å¾—ã—ã¾ã™ã€‚\n" "lxc profile set \n" " プロファイルã®è¨­å®šã‚’設定ã—ã¾ã™ã€‚\n" "lxc profile delete \n" " プロファイルを削除ã—ã¾ã™ã€‚\n" "lxc profile edit \n" " プロファイルを編集ã—ã¾ã™ã€‚外部エディタもã—ãã¯STDINã‹ã‚‰èª­ã¿è¾¼ã¿ã¾ã™ã€‚\n" " 例: lxc profile edit # エディタã®èµ·å‹•\n" " cat profile.yml | lxc profile edit # profile.yml ã‹ã‚‰èª­ã¿è¾¼" "ã¿\n" "lxc profile apply \n" " プロファイルã®ã‚³ãƒ³ãƒžåŒºåˆ‡ã‚Šã®ãƒªã‚¹ãƒˆã‚’コンテナã«é †ç•ªã«é©ç”¨ã—ã¾ã™ã€‚\n" " ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã§æŒ‡å®šã—ãŸãƒ—ロファイルã ã‘ãŒå¯¾è±¡ã®ã‚³ãƒ³ãƒ†ãƒŠã«é©ç”¨ã•れã¾ã™ã€‚\n" " 例: lxc profile apply foo default,bar # defaultã¨barã‚’é©ç”¨\n" " lxc profile apply foo default # defaultã ã‘を有効化\n" " lxc profile apply '' # 一切ã®ãƒ—ロファイルをé©ç”¨ã—ãªã„\n" " lxc profile apply bar,default # defaultã‚’2番目ã«é©ç”¨\n" "\n" "デãƒã‚¤ã‚¹:\n" "lxc profile device list \n" " 指定ã—ãŸãƒ—ロファイル内ã®ãƒ‡ãƒã‚¤ã‚¹ã‚’一覧表示ã—ã¾ã™\n" "lxc profile device show \n" " 指定ã—ãŸãƒ—ロファイル内ã®å…¨ãƒ‡ãƒã‚¤ã‚¹ã®è©³ç´°ã‚’表示ã—ã¾ã™\n" "lxc profile device remove \n" " プロファイルã‹ã‚‰ãƒ‡ãƒã‚¤ã‚¹ã‚’削除ã—ã¾ã™\n" "lxc profile device get <[remote:]profile> \n" " デãƒã‚¤ã‚¹ãƒ—ロパティをå–å¾—ã—ã¾ã™\n" "lxc profile device set <[remote:]profile> \n" " デãƒã‚¤ã‚¹ãƒ—ロパティを設定ã—ã¾ã™\n" "lxc profile device unset <[remote:]profile> \n" " デãƒã‚¤ã‚¹ãƒ—ロパティを削除ã—ã¾ã™\n" "lxc profile device add " "[key=value]...\n" " ディスクやNICã®ã‚ˆã†ãªãƒ—ロファイルデãƒã‚¤ã‚¹ã‚’指定ã—ãŸãƒ—ロファイルを使ã£ã¦\n" " コンテナã«è¿½åŠ ã—ã¾ã™ã€‚" #: lxc/config.go:58 msgid "" "Manage configuration.\n" "\n" "lxc config device add <[remote:]container> [key=value]... " "Add a device to a container.\n" "lxc config device get <[remote:]container> " "Get a device property.\n" "lxc config device set <[remote:]container> " "Set a device property.\n" "lxc config device unset <[remote:]container> " "Unset a device property.\n" "lxc config device list <[remote:]container> " "List devices for container.\n" "lxc config device show <[remote:]container> " "Show full device details for container.\n" "lxc config device remove <[remote:]container> " "Remove device from container.\n" "\n" "lxc config get [remote:][container] " "Get container or server configuration key.\n" "lxc config set [remote:][container] " "Set container or server configuration key.\n" "lxc config unset [remote:][container] " "Unset container or server configuration key.\n" "lxc config show [remote:][container] [--expanded] " "Show container or server configuration.\n" "lxc config edit [remote:][container] " "Edit container or server configuration in external editor.\n" " Edit configuration, either by launching external editor or reading " "STDIN.\n" " Example: lxc config edit # launch editor\n" " cat config.yml | lxc config edit # read from config." "yml\n" "\n" "lxc config trust list [remote] " "List all trusted certs.\n" "lxc config trust add [remote] " "Add certfile.crt to trusted hosts.\n" "lxc config trust remove [remote] [hostname|fingerprint] " "Remove the cert from trusted hosts.\n" "\n" "Examples:\n" "To mount host's /share/c1 onto /opt in the container:\n" " lxc config device add [remote:]container1 disk source=/" "share/c1 path=opt\n" "\n" "To set an lxc config value:\n" " lxc config set [remote:] raw.lxc 'lxc.aa_allow_incomplete = " "1'\n" "\n" "To listen on IPv4 and IPv6 port 8443 (you can omit the 8443 its the " "default):\n" " lxc config set core.https_address [::]:8443\n" "\n" "To set the server trust password:\n" " lxc config set core.trust_password blah" msgstr "" "設定を管ç†ã—ã¾ã™ã€‚\n" "\n" "lxc config device add <[remote:]container> [key=value]...\n" " コンテナã«ãƒ‡ãƒã‚¤ã‚¹ã‚’追加ã—ã¾ã™ã€‚\n" "lxc config device get <[remote:]container> \n" " デãƒã‚¤ã‚¹ã®ãƒ—ロパティをå–å¾—ã—ã¾ã™ã€‚\n" "lxc config device set <[remote:]container> \n" " デãƒã‚¤ã‚¹ã®ãƒ—ロパティを設定ã—ã¾ã™ã€‚\n" "lxc config device unset <[remote:]container> \n" " デãƒã‚¤ã‚¹ã®ãƒ—ロパティを削除ã—ã¾ã™ã€‚\n" "lxc config device list <[remote:]container>\n" " コンテナã®ãƒ‡ãƒã‚¤ã‚¹ã‚’一覧表示ã—ã¾ã™ã€‚\n" "lxc config device show <[remote:]container>\n" " å…¨ã¦ã®ãƒ‡ãƒã‚¤ã‚¹ã®è©³ç´°ã‚’表示ã—ã¾ã™ã€‚\n" "lxc config device remove <[remote:]container> \n" " コンテナã‹ã‚‰ãƒ‡ãƒã‚¤ã‚¹ã‚’削除ã—ã¾ã™ã€‚\n" "\n" "lxc config get [remote:][container] \n" " コンテナもã—ãã¯ã‚µãƒ¼ãƒã®è¨­å®šé …ç›®ã®å€¤ã‚’å–å¾—ã—ã¾ã™ã€‚\n" "lxc config set [remote:][container] \n" " コンテナもã—ãã¯ã‚µãƒ¼ãƒã®è¨­å®šé …ç›®ã«å€¤ã‚’設定ã—ã¾ã™ã€‚\n" "lxc config unset [remote:][container] \n" " コンテナもã—ãã¯ã‚µãƒ¼ãƒã®è¨­å®šé …目を削除ã—ã¾ã™ã€‚\n" "lxc config show [remote:][container] [--expanded]\n" " コンテナもã—ãã¯ã‚µãƒ¼ãƒã®è¨­å®šã‚’表示ã—ã¾ã™ã€‚\n" "lxc config edit [remote:][container]\n" " コンテナもã—ãã¯ã‚µãƒ¼ãƒã®è¨­å®šã‚’外部エディタã§ç·¨é›†ã—ã¾ã™ã€‚\n" " 設定ã®ç·¨é›†ã¯å¤–部エディタを起動ã™ã‚‹ã‹ã€æ¨™æº–入力ã‹ã‚‰ã®èª­ã¿è¾¼ã¿ã§è¡Œã„ã¾" "ã™ã€‚\n" " 例: lxc config edit # エディタã®èµ·å‹•\n" " cat config.yml | lxc config edit # config.ymlã‹ã‚‰èª­ã¿è¾¼ã¿\n" "\n" "lxc config trust list [remote]\n" " ä¿¡é ¼ã™ã‚‹è¨¼æ˜Žæ›¸ã‚’å…¨ã¦è¡¨ç¤ºã—ã¾ã™ã€‚\n" "lxc config trust add [remote] \n" " certfile.crt ã‚’ä¿¡é ¼ã™ã‚‹ãƒ›ã‚¹ãƒˆã«è¿½åŠ ã—ã¾ã™ã€‚\n" "lxc config trust remove [remote] [hostname|fingerprint]\n" " ä¿¡é ¼ã™ã‚‹ãƒ›ã‚¹ãƒˆã‹ã‚‰è¨¼æ˜Žæ›¸ã‚’消去ã—ã¾ã™ã€‚\n" "\n" "例:\n" "ホスト㮠/share/c1 をコンテナ内㮠/opt ã«ãƒžã‚¦ãƒ³ãƒˆã™ã‚‹ã«ã¯:\n" " lxc config device add [remote:]container1 disk source=/" "share/c1 path=opt\n" "\n" "lxc 設定項目ã«å€¤ã‚’設定ã™ã‚‹ã«ã¯:\n" " lxc config set [remote:] raw.lxc 'lxc.aa_allow_incomplete = " "1'\n" "\n" "IPv4 㨠IPv6 ã®ãƒãƒ¼ãƒˆ 8443 ã§ Listen ã™ã‚‹ã«ã¯\n" "(8443 ã¯ãƒ‡ãƒ•ォルトãªã®ã§çœç•¥ã§ãã¾ã™):\n" " lxc config set core.https_address [::]:8443\n" "\n" "サーãƒã®ãƒ‘スワードを設定ã™ã‚‹ã«ã¯:\n" " lxc config set core.trust_password blah" #: lxc/file.go:32 msgid "" "Manage files on a container.\n" "\n" "lxc file pull [...] \n" "lxc file push [--uid=UID] [--gid=GID] [--mode=MODE] [...] " "\n" "lxc file edit \n" "\n" " in the case of pull, in the case of push and in the " "case of edit are /" msgstr "" "コンテナ上ã®ãƒ•ァイルã®ç®¡ç†\n" "\n" "lxc file pull [...] \n" "lxc file push [--uid=UID] [--gid=GID] [--mode=MODE] [...] " "\n" "lxc file edit \n" "\n" "pull ã®å ´åˆã® ã€push ã®å ´åˆã® ã€edit ã®å ´åˆã® ã¯ã€ã„\n" "ãšã‚Œã‚‚ / ã®å½¢å¼ã§ã™ã€‚" #: lxc/remote.go:39 msgid "" "Manage remote LXD servers.\n" "\n" "lxc remote add [--accept-certificate] [--password=PASSWORD]\n" " [--public] [--protocol=PROTOCOL] " "Add the remote at .\n" "lxc remote remove " "Remove the remote .\n" "lxc remote list " "List all remotes.\n" "lxc remote rename " "Rename remote to .\n" "lxc remote set-url " "Update 's url to .\n" "lxc remote set-default " "Set the default remote.\n" "lxc remote get-default " "Print the default remote." msgstr "" "リモート㮠LXD サーãƒã‚’管ç†ã—ã¾ã™ã€‚\n" "\n" "lxc remote add \n" " [--accept-certificate] [--password=PASSWORD]\n" " [--public] [--protocol=PROTOCOL]\n" " をリモートホスト ã¨ã—ã¦è¿½åŠ ã—ã¾ã™ã€‚\n" "lxc remote remove \n" " リモートホスト を削除ã—ã¾ã™ã€‚\n" "lxc remote list\n" " 登録済ã¿ã®ãƒªãƒ¢ãƒ¼ãƒˆãƒ›ã‚¹ãƒˆã‚’å…¨ã¦ä¸€è¦§è¡¨ç¤ºã—ã¾ã™ã€‚\n" "lxc remote rename \n" " リモートホストã®åå‰ã‚’ ã‹ã‚‰ ã«å¤‰æ›´ã—ã¾ã™ã€‚\n" "lxc remote set-url \n" " ã® url ã‚’ ã«æ›´æ–°ã—ã¾ã™ã€‚\n" "lxc remote set-default \n" " をデフォルトã®ãƒªãƒ¢ãƒ¼ãƒˆãƒ›ã‚¹ãƒˆã«è¨­å®šã—ã¾ã™ã€‚\n" "lxc remote get-default\n" " デフォルトã«è¨­å®šã•れã¦ã„るリモートホストを表示ã—ã¾ã™ã€‚" #: lxc/image.go:93 msgid "" "Manipulate container images.\n" "\n" "In LXD containers are created from images. Those images were themselves\n" "either generated from an existing container or downloaded from an image\n" "server.\n" "\n" "When using remote images, LXD will automatically cache images for you\n" "and remove them upon expiration.\n" "\n" "The image unique identifier is the hash (sha-256) of its representation\n" "as a compressed tarball (or for split images, the concatenation of the\n" "metadata and rootfs tarballs).\n" "\n" "Images can be referenced by their full hash, shortest unique partial\n" "hash or alias name (if one is set).\n" "\n" "\n" "lxc image import [rootfs tarball|URL] [remote:] [--public] [--" "created-at=ISO-8601] [--expires-at=ISO-8601] [--fingerprint=FINGERPRINT] " "[prop=value]\n" " Import an image tarball (or tarballs) into the LXD image store.\n" "\n" "lxc image copy [remote:] : [--alias=ALIAS].. [--copy-aliases] " "[--public] [--auto-update]\n" " Copy an image from one LXD daemon to another over the network.\n" "\n" " The auto-update flag instructs the server to keep this image up to\n" " date. It requires the source to be an alias and for it to be public.\n" "\n" "lxc image delete [remote:]\n" " Delete an image from the LXD image store.\n" "\n" "lxc image export [remote:]\n" " Export an image from the LXD image store into a distributable tarball.\n" "\n" "lxc image info [remote:]\n" " Print everything LXD knows about a given image.\n" "\n" "lxc image list [remote:] [filter]\n" " List images in the LXD image store. Filters may be of the\n" " = form for property based filtering, or part of the image\n" " hash or part of the image alias name.\n" "\n" "lxc image show [remote:]\n" " Yaml output of the user modifiable properties of an image.\n" "\n" "lxc image edit [remote:]\n" " Edit image, either by launching external editor or reading STDIN.\n" " Example: lxc image edit # launch editor\n" " cat image.yml | lxc image edit # read from image.yml\n" "\n" "lxc image alias create [remote:] \n" " Create a new alias for an existing image.\n" "\n" "lxc image alias delete [remote:]\n" " Delete an alias.\n" "\n" "lxc image alias list [remote:] [filter]\n" " List the aliases. Filters may be part of the image hash or part of the " "image alias name.\n" msgstr "" "コンテナイメージをæ“作ã—ã¾ã™ã€‚\n" "\n" "LXD ã§ã¯ã€ã‚³ãƒ³ãƒ†ãƒŠã¯ã‚¤ãƒ¡ãƒ¼ã‚¸ã‹ã‚‰ä½œã‚‰ã‚Œã¾ã™ã€‚ã“ã®ã‚¤ãƒ¡ãƒ¼ã‚¸ã¯ã€æ—¢å­˜ã®ã‚³ãƒ³ãƒ†ãƒŠ\n" "やイメージサーãƒã‹ã‚‰ãƒ€ã‚¦ãƒ³ãƒ­ãƒ¼ãƒ‰ã—ãŸã‚¤ãƒ¡ãƒ¼ã‚¸ã‹ã‚‰ä½œã‚‰ã‚Œã¾ã™ã€‚\n" "\n" "リモートã®ã‚¤ãƒ¡ãƒ¼ã‚¸ã‚’使ã†å ´åˆã€LXD ã¯è‡ªå‹•çš„ã«ã‚¤ãƒ¡ãƒ¼ã‚¸ã‚’キャッシュã—ã¾ã™ã€‚ã\n" "ã—ã¦ã€ã‚¤ãƒ¡ãƒ¼ã‚¸ã®æœŸé™ãŒåˆ‡ã‚Œã‚‹ã¨ã‚­ãƒ£ãƒƒã‚·ãƒ¥ã‚’削除ã—ã¾ã™ã€‚\n" "\n" "イメージ固有ã®è­˜åˆ¥å­ã¯åœ§ç¸®ã•れ㟠tarball (分割イメージã®å ´åˆã¯ã€ãƒ¡ã‚¿ãƒ‡ãƒ¼ã‚¿\n" "㨠rootfs tarball ã‚’çµåˆã—ãŸã‚‚ã®) ã®ãƒãƒƒã‚·ãƒ¥ (sha-256) ã§ã™ã€‚\n" "\n" "イメージã¯å…¨ãƒãƒƒã‚·ãƒ¥æ–‡å­—列ã€ä¸€æ„ã«å®šã¾ã‚‹ãƒãƒƒã‚·ãƒ¥ã®çŸ­ç¸®è¡¨ç¾ã€(設定ã•れã¦ã„\n" "ã‚‹å ´åˆã¯) エイリアスã§å‚ç…§ã§ãã¾ã™ã€‚\n" "\n" "\n" "lxc image import [rootfs tarball|URL] [remote:] [--public] [--" "created-at=ISO-8601] [--expires-at=ISO-8601] [--fingerprint=FINGERPRINT] " "[prop=value]\n" " イメージ㮠tarball (複数もå¯èƒ½) ã‚’ LXD ã®ã‚¤ãƒ¡ãƒ¼ã‚¸ã‚¹ãƒˆã‚¢ã«ã‚¤ãƒ³ãƒãƒ¼ãƒˆã—ã¾\n" " ã™ã€‚\n" "\n" "lxc image copy [remote:] : [--alias=ALIAS].. [--copy-aliases] " "[--public] [--auto-update]\n" " ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯çµŒç”±ã§ã‚ã‚‹ LXD デーモンã‹ã‚‰ä»–ã® LXD デーモンã¸ã‚¤ãƒ¡ãƒ¼ã‚¸ã‚’\n" " コピーã—ã¾ã™ã€‚\n" "\n" " auto-update フラグã¯ã€ã‚µãƒ¼ãƒãŒã‚¤ãƒ¡ãƒ¼ã‚¸ã‚’最新ã«ä¿ã¤ã‚ˆã†ã«æŒ‡ç¤ºã—ã¾ã™ã€‚イ\n" " メージã®ã‚½ãƒ¼ã‚¹ãŒã‚¨ã‚¤ãƒªã‚¢ã‚¹ã§ã‚りã€public ã§ã‚ã‚‹å¿…è¦ãŒã‚りã¾ã™ã€‚\n" "\n" "lxc image delete [remote:]\n" " LXD ã®ã‚¤ãƒ¡ãƒ¼ã‚¸ã‚¹ãƒˆã‚¢ã‹ã‚‰ã‚¤ãƒ¡ãƒ¼ã‚¸ã‚’削除ã—ã¾ã™ã€‚\n" "\n" "lxc image export [remote:]\n" " LXD ã®ã‚¤ãƒ¡ãƒ¼ã‚¸ã‚¹ãƒˆã‚¢ã‹ã‚‰é…布å¯èƒ½ãª tarball ã¨ã—ã¦ã‚¤ãƒ¡ãƒ¼ã‚¸ã‚’エクスãƒãƒ¼ãƒˆ\n" " ã—ã¾ã™ã€‚\n" "\n" "lxc image info [remote:]\n" " 指定ã—ãŸã‚¤ãƒ¡ãƒ¼ã‚¸ã«ã¤ã„ã¦ã®ã™ã¹ã¦ã®æƒ…報を表示ã—ã¾ã™ã€‚\n" "\n" "lxc image list [remote:] [filter]\n" " LXD ã®ã‚¤ãƒ¡ãƒ¼ã‚¸ã‚¹ãƒˆã‚¢å†…ã®ã‚¤ãƒ¡ãƒ¼ã‚¸ã‚’一覧表示ã—ã¾ã™ã€‚プロパティã§ãƒ•ィルタ\n" " を行ã†å ´åˆã¯ã€ãƒ•ィルタ㯠= ã®å½¢ã«ãªã‚Šã¾ã™ã€‚フィルタã¯ã‚¤ãƒ¡ãƒ¼\n" " ジãƒãƒƒã‚·ãƒ¥ã®ä¸€éƒ¨ã‚„イメージエイリアスåã®ä¸€éƒ¨ã‚‚指定ã§ãã¾ã™ã€‚\n" "\n" "lxc image show [remote:]\n" " ユーザãŒå¤‰æ›´ã§ãるプロパティ㮠YAML å½¢å¼ã®å‡ºåŠ›ã‚’è¡Œã„ã¾ã™ã€‚\n" "\n" "lxc image edit [remote:]\n" " 外部エディタã¾ãŸã¯æ¨™æº–入力ã‹ã‚‰ã®èª­ã¿è¾¼ã¿ã«ã‚ˆã‚Šã€ã‚¤ãƒ¡ãƒ¼ã‚¸ã‚’編集ã—ã¾ã™ã€‚\n" " 例: lxc image edit # エディタã®èµ·å‹•\n" " cat image.yml | lxc image edit # image.yml ã‹ã‚‰èª­ã¿è¾¼ã¿\n" "\n" "lxc image alias create [remote:] \n" " 既存ã®ã‚¤ãƒ¡ãƒ¼ã‚¸ã«æ–°ãŸã«ã‚¨ã‚¤ãƒªã‚¢ã‚¹ã‚’作æˆã—ã¾ã™ã€‚\n" "\n" "lxc image alias delete [remote:]\n" " エイリアスを削除ã—ã¾ã™ã€‚\n" "\n" "lxc image alias list [remote:] [filter]\n" " エイリアスを一覧表示ã—ã¾ã™ã€‚イメージãƒãƒƒã‚·ãƒ¥ã®ä¸€éƒ¨ã‚„イメージã®ã‚¨ã‚¤ãƒªã‚¢" "ス\n" " åã®ä¸€éƒ¨ã‚’フィルタã¨ã—ã¦æŒ‡å®šã§ãã¾ã™ã€‚\n" #: lxc/info.go:147 msgid "Memory (current)" msgstr "メモリ (ç¾åœ¨å€¤)" #: lxc/info.go:151 msgid "Memory (peak)" msgstr "メモリ (ピーク)" #: lxc/help.go:86 msgid "Missing summary." msgstr "サマリーã¯ã‚りã¾ã›ã‚“。" #: lxc/monitor.go:41 msgid "" "Monitor activity on the LXD server.\n" "\n" "lxc monitor [remote:] [--type=TYPE...]\n" "\n" "Connects to the monitoring interface of the specified LXD server.\n" "\n" "By default will listen to all message types.\n" "Specific types to listen to can be specified with --type.\n" "\n" "Example:\n" "lxc monitor --type=logging" msgstr "" "LXD サーãƒã®å‹•作をモニタリングã—ã¾ã™ã€‚\n" "\n" "lxc monitor [remote:] [--type=TYPE...]\n" "\n" "指定ã—㟠LXD サーãƒã®ãƒ¢ãƒ‹ã‚¿ãƒªãƒ³ã‚°ã‚¤ãƒ³ã‚¿ãƒ¼ãƒ•ã‚§ãƒ¼ã‚¹ã«æŽ¥ç¶šã—ã¾ã™ã€‚\n" "\n" "デフォルトã§ã¯å…¨ã¦ã®ã‚¿ã‚¤ãƒ—をモニタリングã—ã¾ã™ã€‚\n" "--type ã«ã‚ˆã‚Šã€ãƒ¢ãƒ‹ã‚¿ãƒªãƒ³ã‚°ã™ã‚‹ã‚¿ã‚¤ãƒ—を指定ã§ãã¾ã™ã€‚\n" "\n" "例:\n" "lxc monitor --type=logging" #: lxc/file.go:178 msgid "More than one file to download, but target is not a directory" msgstr "" "ダウンロード対象ã®ãƒ•ァイルãŒè¤‡æ•°ã‚りã¾ã™ãŒã€ã‚³ãƒ”ー先ãŒãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã§ã¯ã‚りã¾" "ã›ã‚“。" #: lxc/move.go:17 msgid "" "Move containers within or in between lxd instances.\n" "\n" "lxc move [remote:] [remote:]\n" " Move a container between two hosts, renaming it if destination name " "differs.\n" "\n" "lxc move \n" " Rename a local container.\n" msgstr "" "LXD ホスト内ã€ã‚‚ã—ã㯠LXD ホスト間ã§ã‚³ãƒ³ãƒ†ãƒŠã‚’移動ã—ã¾ã™ã€‚\n" "\n" "lxc move [remote:] [remote:]\n" " 2 ã¤ã®ãƒ›ã‚¹ãƒˆé–“ã§ã‚³ãƒ³ãƒ†ãƒŠã‚’移動ã—ã¾ã™ã€‚コピー先ã®åå‰ãŒå…ƒã¨é•ã†å ´åˆã¯\n" " åŒæ™‚ã«ãƒªãƒãƒ¼ãƒ ã•れã¾ã™ã€‚\n" "\n" "lxc move \n" " ローカルã®ã‚³ãƒ³ãƒ†ãƒŠã‚’リãƒãƒ¼ãƒ ã—ã¾ã™ã€‚\n" #: lxc/action.go:63 msgid "Must supply container name for: " msgstr "コンテナåを指定ã™ã‚‹å¿…è¦ãŒã‚りã¾ã™: " #: lxc/list.go:369 lxc/remote.go:363 msgid "NAME" msgstr "" #: lxc/remote.go:337 lxc/remote.go:342 msgid "NO" msgstr "" #: lxc/info.go:89 #, c-format msgid "Name: %s" msgstr "コンテナå: %s" #: lxc/image.go:157 lxc/publish.go:33 msgid "New alias to define at target" msgstr "æ–°ã—ã„エイリアスを定義ã™ã‚‹" #: lxc/config.go:281 msgid "No certificate provided to add" msgstr "追加ã™ã¹ãè¨¼æ˜Žæ›¸ãŒæä¾›ã•れã¦ã„ã¾ã›ã‚“" #: lxc/config.go:304 msgid "No fingerprint specified." msgstr "ãƒ•ã‚£ãƒ³ã‚¬ãƒ¼ãƒ—ãƒªãƒ³ãƒˆãŒæŒ‡å®šã•れã¦ã„ã¾ã›ã‚“。" #: lxc/remote.go:107 msgid "Only https URLs are supported for simplestreams" msgstr "simplestreams 㯠https ã® URL ã®ã¿ã‚µãƒãƒ¼ãƒˆã—ã¾ã™" #: lxc/image.go:411 msgid "Only https:// is supported for remote image import." msgstr "リモートイメージã®ã‚¤ãƒ³ãƒãƒ¼ãƒˆã¯ https:// ã®ã¿ã‚’サãƒãƒ¼ãƒˆã—ã¾ã™ã€‚" #: lxc/help.go:63 lxc/main.go:122 msgid "Options:" msgstr "オプション:" #: lxc/image.go:506 #, c-format msgid "Output is in %s" msgstr "%s ã«å‡ºåŠ›ã•れã¾ã™" #: lxc/exec.go:55 msgid "Override the terminal mode (auto, interactive or non-interactive)" msgstr "ターミナルモードを上書ãã—ã¾ã™ (auto, interactive, non-interactive)" #: lxc/list.go:453 msgid "PERSISTENT" msgstr "" #: lxc/list.go:370 msgid "PID" msgstr "" #: lxc/list.go:371 msgid "PROFILES" msgstr "" #: lxc/remote.go:365 msgid "PROTOCOL" msgstr "" #: lxc/image.go:606 lxc/remote.go:366 msgid "PUBLIC" msgstr "" #: lxc/info.go:174 msgid "Packets received" msgstr "å—信パケット" #: lxc/info.go:175 msgid "Packets sent" msgstr "é€ä¿¡ãƒ‘ケット" #: lxc/help.go:69 msgid "Path to an alternate client configuration directory." msgstr "別ã®ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆç”¨è¨­å®šãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒª" #: lxc/help.go:70 msgid "Path to an alternate server directory." msgstr "別ã®ã‚µãƒ¼ãƒç”¨è¨­å®šãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒª" #: lxc/main.go:39 msgid "Permisson denied, are you in the lxd group?" msgstr "ã‚¢ã‚¯ã‚»ã‚¹ãŒæ‹’å¦ã•れã¾ã—ãŸã€‚lxd ã‚°ãƒ«ãƒ¼ãƒ—ã«æ‰€å±žã—ã¦ã„ã¾ã™ã‹?" #: lxc/info.go:103 #, c-format msgid "Pid: %d" msgstr "" #: lxc/help.go:25 msgid "" "Presents details on how to use LXD.\n" "\n" "lxd help [--all]" msgstr "" "LXDã®ä½¿ã„æ–¹ã®è©³ç´°ã‚’表示ã—ã¾ã™ã€‚\n" "\n" "lxd help [--all]" #: lxc/profile.go:191 msgid "Press enter to open the editor again" msgstr "å†åº¦ã‚¨ãƒ‡ã‚£ã‚¿ã‚’é–‹ããŸã‚ã«ã¯ Enter キーを押ã—ã¾ã™" #: lxc/config.go:501 lxc/config.go:566 lxc/image.go:688 msgid "Press enter to start the editor again" msgstr "å†åº¦ã‚¨ãƒ‡ã‚£ã‚¿ã‚’èµ·å‹•ã™ã‚‹ã«ã¯ Enter キーを押ã—ã¾ã™" #: lxc/help.go:65 msgid "Print debug information." msgstr "デãƒãƒƒã‚°æƒ…報を表示ã—ã¾ã™" #: lxc/help.go:64 msgid "Print less common commands." msgstr "å…¨ã¦ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’表示ã—ã¾ã™ (主ãªã‚³ãƒžãƒ³ãƒ‰ã ã‘ã§ã¯ãªã)。" #: lxc/help.go:66 msgid "Print verbose information." msgstr "詳細情報を表示ã—ã¾ã™ã€‚" #: lxc/version.go:18 msgid "" "Prints the version number of this client tool.\n" "\n" "lxc version" msgstr "" "ãŠä½¿ã„ã®ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ç•ªå·ã‚’表示ã—ã¾ã™ã€‚\n" "\n" "lxc version" #: lxc/info.go:127 #, c-format msgid "Processes: %d" msgstr "プロセス数: %d" #: lxc/profile.go:228 #, c-format msgid "Profile %s applied to %s" msgstr "プロファイル %s ㌠%s ã«è¿½åŠ ã•れã¾ã—ãŸ" #: lxc/profile.go:142 #, c-format msgid "Profile %s created" msgstr "プロファイル %s を作æˆã—ã¾ã—ãŸ" #: lxc/profile.go:212 #, c-format msgid "Profile %s deleted" msgstr "プロファイル %s を削除ã—ã¾ã—ãŸ" #: lxc/init.go:136 lxc/init.go:137 lxc/launch.go:42 lxc/launch.go:43 msgid "Profile to apply to the new container" msgstr "ãƒ—ãƒ­ãƒ•ã‚¡ã‚¤ãƒ«ãŒæ–°ã—ã„コンテナã«é©ç”¨ã•れã¾ã—ãŸ" #: lxc/info.go:101 #, c-format msgid "Profiles: %s" msgstr "プロファイル: %s" #: lxc/image.go:343 msgid "Properties:" msgstr "プロパティ:" #: lxc/remote.go:56 msgid "Public image server" msgstr "Public ãªã‚¤ãƒ¡ãƒ¼ã‚¸ã‚µãƒ¼ãƒã¨ã—ã¦è¨­å®šã—ã¾ã™" #: lxc/image.go:331 #, c-format msgid "Public: %s" msgstr "" #: lxc/publish.go:25 msgid "" "Publish containers as images.\n" "\n" "lxc publish [remote:]container [remote:] [--alias=ALIAS]... [prop-key=prop-" "value]..." msgstr "" "イメージã¨ã—ã¦ã‚³ãƒ³ãƒ†ãƒŠã‚’ publish ã—ã¾ã™ã€‚\n" "\n" "lxc publish [remote:]container [remote:] [--alias=ALIAS]... [prop-key=prop-" "value]..." #: lxc/remote.go:54 msgid "Remote admin password" msgstr "リモートã®ç®¡ç†è€…パスワード" #: lxc/delete.go:42 #, c-format msgid "Remove %s (yes/no): " msgstr "%s を消去ã—ã¾ã™ã‹ (yes/no): " #: lxc/delete.go:36 lxc/delete.go:37 msgid "Require user confirmation." msgstr "ユーザã®ç¢ºèªã‚’è¦æ±‚ã™ã‚‹ã€‚" #: lxc/info.go:124 msgid "Resources:" msgstr "リソース:" #: lxc/init.go:246 #, c-format msgid "Retrieving image: %s" msgstr "イメージã®å–得中: %s" #: lxc/image.go:609 msgid "SIZE" msgstr "" #: lxc/list.go:372 msgid "SNAPSHOTS" msgstr "" #: lxc/list.go:373 msgid "STATE" msgstr "" #: lxc/remote.go:367 msgid "STATIC" msgstr "" #: lxc/remote.go:214 msgid "Server certificate NACKed by user" msgstr "ユーザã«ã‚ˆã‚Šã‚µãƒ¼ãƒè¨¼æ˜Žæ›¸ãŒæ‹’å¦ã•れã¾ã—ãŸ" #: lxc/remote.go:276 msgid "Server doesn't trust us after adding our cert" msgstr "サーãƒãŒæˆ‘々ã®è¨¼æ˜Žæ›¸ã‚’追加ã—ãŸå¾Œæˆ‘々を信頼ã—ã¦ã„ã¾ã›ã‚“" #: lxc/remote.go:55 msgid "Server protocol (lxd or simplestreams)" msgstr "サーãƒã®ãƒ—ロトコル (lxd or simplestreams)" #: lxc/restore.go:21 msgid "" "Set the current state of a resource back to a snapshot.\n" "\n" "lxc restore [remote:] [--stateful]\n" "\n" "Restores a container from a snapshot (optionally with running state, see\n" "snapshot help for details).\n" "\n" "For example:\n" "lxc snapshot u1 snap0 # create the snapshot\n" "lxc restore u1 snap0 # restore the snapshot" msgstr "" "リソースã®ç¾åœ¨ã®çŠ¶æ…‹ã‚’ã‚¹ãƒŠãƒƒãƒ—ã‚·ãƒ§ãƒƒãƒˆæ™‚ç‚¹ã®çŠ¶æ…‹ã«è¨­å®šã—ã¾ã™ã€‚\n" "\n" "lxc restore [remote:] [--stateful]\n" "\n" "スナップショットã‹ã‚‰ã‚³ãƒ³ãƒ†ãƒŠã‚’リストアã—ã¾ã™ (オプションã§å®Ÿè¡ŒçŠ¶æ…‹ã‚‚ãƒªã‚¹ãƒˆ\n" "ã‚¢ã—ã¾ã™ã€‚詳ã—ãã¯ã‚¹ãƒŠãƒƒãƒ—ショットã®ãƒ˜ãƒ«ãƒ—ã‚’ã”覧ãã ã•ã„)。\n" "\n" "例:\n" "lxc snapshot u1 snap0 # スナップショットã®ä½œæˆ\n" "lxc restore u1 snap0 # スナップショットã‹ã‚‰ãƒªã‚¹ãƒˆã‚¢" #: lxc/file.go:44 msgid "Set the file's gid on push" msgstr "プッシュ時ã«ãƒ•ァイルã®gidを設定ã—ã¾ã™" #: lxc/file.go:45 msgid "Set the file's perms on push" msgstr "プッシュ時ã«ãƒ•ァイルã®ãƒ‘ーミションを設定ã—ã¾ã™" #: lxc/file.go:43 msgid "Set the file's uid on push" msgstr "プッシュ時ã«ãƒ•ァイルã®uidを設定ã—ã¾ã™" #: lxc/help.go:32 msgid "Show all commands (not just interesting ones)" msgstr "å…¨ã¦ã‚³ãƒžãƒ³ãƒ‰ã‚’表示ã—ã¾ã™ (主ãªã‚³ãƒžãƒ³ãƒ‰ã ã‘ã§ã¯ãªã)" #: lxc/info.go:36 msgid "Show the container's last 100 log lines?" msgstr "ã‚³ãƒ³ãƒ†ãƒŠãƒ­ã‚°ã®æœ€å¾Œã® 100 行を表示ã—ã¾ã™ã‹?" #: lxc/image.go:329 #, c-format msgid "Size: %.2fMB" msgstr "サイズ: %.2fMB" #: lxc/info.go:194 msgid "Snapshots:" msgstr "スナップショット:" #: lxc/image.go:353 msgid "Source:" msgstr "å–å¾—å…ƒ:" #: lxc/launch.go:122 #, c-format msgid "Starting %s" msgstr "%s を起動中" #: lxc/info.go:95 #, c-format msgid "Status: %s" msgstr "状態: %s" #: lxc/publish.go:34 lxc/publish.go:35 msgid "Stop the container if currently running" msgstr "実行中ã®å ´åˆã€ã‚³ãƒ³ãƒ†ãƒŠã‚’åœæ­¢ã—ã¾ã™" #: lxc/delete.go:106 lxc/publish.go:111 msgid "Stopping container failed!" msgstr "コンテナã®åœæ­¢ã«å¤±æ•—ã—ã¾ã—ãŸï¼" #: lxc/action.go:38 msgid "Store the container state (only for stop)." msgstr "コンテナã®çŠ¶æ…‹ã‚’ä¿å­˜ã—ã¾ã™ (stopã®ã¿)。" #: lxc/info.go:155 msgid "Swap (current)" msgstr "Swap (ç¾åœ¨å€¤)" #: lxc/info.go:159 msgid "Swap (peak)" msgstr "Swap (ピーク)" #: lxc/list.go:374 msgid "TYPE" msgstr "" #: lxc/delete.go:92 msgid "The container is currently running, stop it first or pass --force." msgstr "コンテナã¯å®Ÿè¡Œä¸­ã§ã™ã€‚å…ˆã«åœæ­¢ã•ã›ã‚‹ã‹ã€--force を指定ã—ã¦ãã ã•ã„。" #: lxc/publish.go:89 msgid "" "The container is currently running. Use --force to have it stopped and " "restarted." msgstr "" "コンテナã¯ç¾åœ¨å®Ÿè¡Œä¸­ã§ã™ã€‚åœæ­¢ã—ã¦ã€å†èµ·å‹•ã™ã‚‹ãŸã‚ã« --force を使用ã—ã¦ãã \n" "ã•ã„。" #: lxc/config.go:645 lxc/config.go:657 lxc/config.go:690 lxc/config.go:708 #: lxc/config.go:746 lxc/config.go:764 msgid "The device doesn't exist" msgstr "デãƒã‚¤ã‚¹ãŒå­˜åœ¨ã—ã¾ã›ã‚“" #: lxc/publish.go:62 msgid "There is no \"image name\". Did you want an alias?" msgstr "" "publish å…ˆã«ã¯ã‚¤ãƒ¡ãƒ¼ã‚¸åã¯æŒ‡å®šã§ãã¾ã›ã‚“。\"--alias\" オプションを使ã£ã¦ã" "ã \n" "ã•ã„。" #: lxc/action.go:36 msgid "Time to wait for the container before killing it." msgstr "ã‚³ãƒ³ãƒ†ãƒŠã‚’å¼·åˆ¶åœæ­¢ã™ã‚‹ã¾ã§ã®æ™‚é–“" #: lxc/image.go:332 msgid "Timestamps:" msgstr "タイムスタンプ:" #: lxc/image.go:402 #, c-format msgid "Transferring image: %d%%" msgstr "イメージを転é€ä¸­: %d%%" #: lxc/action.go:93 lxc/launch.go:130 #, c-format msgid "Try `lxc info --show-log %s` for more info" msgstr "æ›´ã«æƒ…報を得るãŸã‚ã« `lxc info --show-log` を実行ã—ã¦ã¿ã¦ãã ã•ã„" #: lxc/info.go:97 msgid "Type: ephemeral" msgstr "タイプ: ephemeral" #: lxc/info.go:99 msgid "Type: persistent" msgstr "タイプ: persistent" #: lxc/image.go:610 msgid "UPLOAD DATE" msgstr "" #: lxc/remote.go:364 msgid "URL" msgstr "" #: lxc/remote.go:82 msgid "Unable to read remote TLS certificate" msgstr "リモート㮠TLS 証明書を読ã‚ã¾ã›ã‚“" #: lxc/image.go:337 #, c-format msgid "Uploaded: %s" msgstr "アップロード日時: %s" #: lxc/main.go:122 #, c-format msgid "Usage: %s" msgstr "ä½¿ã„æ–¹: %s" #: lxc/help.go:48 msgid "Usage: lxc [subcommand] [options]" msgstr "ä½¿ã„æ–¹: lxc [サブコマンド] [オプション]" #: lxc/delete.go:46 msgid "User aborted delete operation." msgstr "ユーザãŒå‰Šé™¤æ“作を中断ã—ã¾ã—ãŸã€‚" #: lxc/restore.go:35 msgid "" "Whether or not to restore the container's running state from snapshot (if " "available)" msgstr "" "スナップショットã‹ã‚‰ã‚³ãƒ³ãƒ†ãƒŠã®ç¨¼å‹•状態をリストアã™ã‚‹ã‹ã©ã†ã‹ (å–å¾—å¯èƒ½ãªå ´åˆ)" #: lxc/snapshot.go:38 msgid "Whether or not to snapshot the container's running state" msgstr "コンテナã®ç¨¼å‹•状態ã®ã‚¹ãƒŠãƒƒãƒ—ショットをå–å¾—ã™ã‚‹ã‹ã©ã†ã‹" #: lxc/config.go:33 msgid "Whether to show the expanded configuration" msgstr "æ‹¡å¼µã—ãŸè¨­å®šã‚’表示ã™ã‚‹ã‹ã©ã†ã‹" #: lxc/remote.go:339 lxc/remote.go:344 msgid "YES" msgstr "" #: lxc/main.go:66 msgid "`lxc config profile` is deprecated, please use `lxc profile`" msgstr "`lxc config profile` ã¯å»ƒæ­¢ã•れã¾ã—ãŸã€‚`lxc profile` を使ã£ã¦ãã ã•ã„" #: lxc/launch.go:109 msgid "bad number of things scanned from image, container or snapshot" msgstr "" "イメージã€ã‚³ãƒ³ãƒ†ãƒŠã€ã‚¹ãƒŠãƒƒãƒ—ショットã®ã„ãšã‚Œã‹ã‹ã‚‰ã‚¹ã‚­ãƒ£ãƒ³ã•ã‚ŒãŸæ•°ãŒä¸æ­£" #: lxc/action.go:89 msgid "bad result type from action" msgstr "アクションã‹ã‚‰ã®çµæžœã‚¿ã‚¤ãƒ—ãŒä¸æ­£ã§ã™" #: lxc/copy.go:78 msgid "can't copy to the same container name" msgstr "åŒã˜ã‚³ãƒ³ãƒ†ãƒŠåã¸ã¯ã‚³ãƒ”ーã§ãã¾ã›ã‚“" #: lxc/remote.go:327 msgid "can't remove the default remote" msgstr "デフォルトã®ãƒªãƒ¢ãƒ¼ãƒˆã¯å‰Šé™¤ã§ãã¾ã›ã‚“" #: lxc/remote.go:353 msgid "default" msgstr "" #: lxc/init.go:199 lxc/init.go:204 lxc/launch.go:93 lxc/launch.go:98 msgid "didn't get any affected image, container or snapshot from server" msgstr "" "サーãƒã‹ã‚‰å¤‰æ›´ã•れãŸã‚¤ãƒ¡ãƒ¼ã‚¸ã€ã‚³ãƒ³ãƒ†ãƒŠã€ã‚¹ãƒŠãƒƒãƒ—ショットをå–å¾—ã§ãã¾ã›ã‚“ã§\n" "ã—ãŸ" #: lxc/image.go:323 msgid "disabled" msgstr "無効" #: lxc/image.go:325 msgid "enabled" msgstr "有効" #: lxc/main.go:25 lxc/main.go:158 #, c-format msgid "error: %v" msgstr "エラー: %v" #: lxc/help.go:40 lxc/main.go:117 #, c-format msgid "error: unknown command: %s" msgstr "エラー: 未知ã®ã‚³ãƒžãƒ³ãƒ‰: %s" #: lxc/launch.go:113 msgid "got bad version" msgstr "䏿­£ãªãƒãƒ¼ã‚¸ãƒ§ãƒ³ã‚’å¾—ã¾ã—ãŸ" #: lxc/image.go:318 lxc/image.go:586 msgid "no" msgstr "" #: lxc/copy.go:101 msgid "not all the profiles from the source exist on the target" msgstr "コピー元ã®å…¨ã¦ã®ãƒ—ロファイルãŒã‚¿ãƒ¼ã‚²ãƒƒãƒˆã«å­˜åœ¨ã—ã¾ã›ã‚“" #: lxc/remote.go:207 msgid "ok (y/n)?" msgstr "ok (y/n)?" #: lxc/main.go:265 lxc/main.go:269 #, c-format msgid "processing aliases failed %s\n" msgstr "エイリアスã®å‡¦ç†ãŒå¤±æ•—ã—ã¾ã—㟠%s\n" #: lxc/remote.go:389 #, c-format msgid "remote %s already exists" msgstr "リモート %s ã¯æ—¢ã«å­˜åœ¨ã—ã¾ã™" #: lxc/remote.go:319 lxc/remote.go:381 lxc/remote.go:416 lxc/remote.go:432 #, c-format msgid "remote %s doesn't exist" msgstr "リモート %s ã¯å­˜åœ¨ã—ã¾ã›ã‚“" #: lxc/remote.go:302 #, c-format msgid "remote %s exists as <%s>" msgstr "リモート %s 㯠<%s> ã¨ã—ã¦å­˜åœ¨ã—ã¾ã™" #: lxc/remote.go:323 lxc/remote.go:385 lxc/remote.go:420 #, c-format msgid "remote %s is static and cannot be modified" msgstr "リモート %s 㯠static ã§ã™ã®ã§å¤‰æ›´ã§ãã¾ã›ã‚“" #: lxc/info.go:205 msgid "stateful" msgstr "" #: lxc/info.go:207 msgid "stateless" msgstr "" #: lxc/info.go:201 #, c-format msgid "taken at %s" msgstr "%s ã«å–å¾—ã—ã¾ã—ãŸ" #: lxc/exec.go:166 msgid "unreachable return reached" msgstr "到é”ã—ãªã„ã¯ãšã®returnã«åˆ°é”ã—ã¾ã—ãŸ" #: lxc/main.go:198 msgid "wrong number of subcommand arguments" msgstr "サブコマンドã®å¼•æ•°ã®æ•°ãŒæ­£ã—ãã‚りã¾ã›ã‚“" #: lxc/delete.go:45 lxc/image.go:320 lxc/image.go:590 msgid "yes" msgstr "" #: lxc/copy.go:38 msgid "you must specify a source container name" msgstr "コピー元ã®ã‚³ãƒ³ãƒ†ãƒŠåを指定ã—ã¦ãã ã•ã„" #, fuzzy #~ msgid "Bad image property: %s" #~ msgstr "(䏿­£ãªã‚¤ãƒ¡ãƒ¼ã‚¸ãƒ—ロパティ形å¼: %s\n" #~ msgid "Cannot change profile name" #~ msgstr "プロファイルåを変更ã§ãã¾ã›ã‚“" #, fuzzy #~ msgid "" #~ "Create a read-only snapshot of a container.\n" #~ "\n" #~ "lxc snapshot [remote:] [--stateful]" #~ msgstr "コンテナã®èª­ã¿å–り専用スナップショットを作æˆã—ã¾ã™ã€‚\n" #~ msgid "No certificate on this connection" #~ msgstr "ã“ã®æŽ¥ç¶šã«ä½¿ç”¨ã™ã‚‹è¨¼æ˜Žæ›¸ãŒã‚りã¾ã›ã‚“" #, fuzzy #~ msgid "" #~ "Set the current state of a resource back to its state at the time the " #~ "snapshot was created.\n" #~ "\n" #~ "lxc restore [remote:] [--stateful]" #~ msgstr "コンテナã®èª­ã¿å–り専用スナップショットを作æˆã—ã¾ã™ã€‚\n" #~ msgid "api version mismatch: mine: %q, daemon: %q" #~ msgstr "APIã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ä¸ä¸€è‡´: クライアント: %q, サーãƒ: %q" #, fuzzy #~ msgid "bad profile url %s" #~ msgstr "プロファイルURLãŒä¸æ­£ %s" #, fuzzy #~ msgid "bad version in profile url" #~ msgstr "プロファイルURL内ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ãŒä¸æ­£" #, fuzzy #~ msgid "device already exists" #~ msgstr "リモート %s ã¯æ—¢ã«å­˜åœ¨ã—ã¾ã™" #, fuzzy #~ msgid "error." #~ msgstr "エラー: %v\n" #~ msgid "got bad op status %s" #~ msgstr "䏿­£ãªæ“作ステータスを得ã¾ã—㟠%s" #, fuzzy #~ msgid "got bad response type, expected %s got %s" #~ msgstr "\"exec\"ã‹ã‚‰ä¸æ­£ãªå¿œç­”タイプを得ã¾ã—ãŸ" #~ msgid "invalid wait url %s" #~ msgstr "å¾…ã¤URLãŒä¸æ­£ %s" #~ msgid "no response!" #~ msgstr "応答ãŒã‚りã¾ã›ã‚“ï¼" #~ msgid "unknown remote name: %q" #~ msgstr "未知ã®ãƒªãƒ¢ãƒ¼ãƒˆå: %q" #, fuzzy #~ msgid "unknown transport type: %s" #~ msgstr "未知ã®ãƒªãƒ¢ãƒ¼ãƒˆå: %q" #~ msgid "cannot resolve unix socket address: %v" #~ msgstr "UNIXソケットã®ã‚¢ãƒ‰ãƒ¬ã‚¹ã‚’解決ã§ãã¾ã›ã‚“: %v" #, fuzzy #~ msgid "unknown group %s" #~ msgstr "未知ã®ãƒªãƒ¢ãƒ¼ãƒˆå: %q" #, fuzzy #~ msgid "Information about remotes not yet supported" #~ msgstr "ãƒªãƒ¢ãƒ¼ãƒˆã®æƒ…報表示ã¯ã¾ã ã‚µãƒãƒ¼ãƒˆã•れã¦ã„ã¾ã›ã‚“。\n" #~ msgid "Unknown image command %s" #~ msgstr "未知ã®ã‚¤ãƒ¡ãƒ¼ã‚¸ã‚³ãƒžãƒ³ãƒ‰ %s" #~ msgid "Unknown remote subcommand %s" #~ msgstr "未知ã®ãƒªãƒ¢ãƒ¼ãƒˆã‚µãƒ–コマンド %s" #~ msgid "Unkonwn config trust command %s" #~ msgstr "未知ã®è¨­å®šä¿¡é ¼ã‚³ãƒžãƒ³ãƒ‰ %s" #, fuzzy #~ msgid "YAML parse error %v" #~ msgstr "エラー: %v\n" #~ msgid "invalid argument %s" #~ msgstr "䏿­£ãªå¼•æ•° %s" #, fuzzy #~ msgid "unknown profile cmd %s" #~ msgstr "未知ã®è¨­å®šã‚³ãƒžãƒ³ãƒ‰ %s" #, fuzzy #~ msgid "Publish to remote server is not supported yet" #~ msgstr "ãƒªãƒ¢ãƒ¼ãƒˆã®æƒ…報表示ã¯ã¾ã ã‚µãƒãƒ¼ãƒˆã•れã¦ã„ã¾ã›ã‚“。\n" #, fuzzy #~ msgid "Use an alternative config path." #~ msgstr "別ã®è¨­å®šãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒª" #, fuzzy #~ msgid "" #~ "error: %v\n" #~ "%s\n" #~ msgstr "" #~ "エラー: %v\n" #~ "%s" #, fuzzy #~ msgid "Show for remotes is not yet supported\n" #~ msgstr "ãƒªãƒ¢ãƒ¼ãƒˆã®æƒ…報表示ã¯ã¾ã ã‚µãƒãƒ¼ãƒˆã•れã¦ã„ã¾ã›ã‚“。\n" #~ msgid "(Bad alias entry: %s\n" #~ msgstr "(䏿­£ãªã‚¨ã‚¤ãƒªã‚¢ã‚¹: %s\n" #~ msgid "bad container url %s" #~ msgstr "コンテナã®ä¸æ­£ãªURL %s" #~ msgid "bad version in container url" #~ msgstr "コンテナURL内ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ãŒä¸æ­£" #, fuzzy #~ msgid "Ephemeral containers not yet supported\n" #~ msgstr "ãƒªãƒ¢ãƒ¼ãƒˆã®æƒ…報表示ã¯ã¾ã ã‚µãƒãƒ¼ãƒˆã•れã¦ã„ã¾ã›ã‚“。\n" #~ msgid "(Bad image entry: %s\n" #~ msgstr "(䏿­£ãªã‚¤ãƒ¡ãƒ¼ã‚¸: %s\n" #~ msgid "Certificate already stored.\n" #~ msgstr "è¨¼æ˜Žæ›¸ã¯æ—¢ã«æ ¼ç´ã•れã¦ã„ã¾ã™ã€‚\n" #, fuzzy #~ msgid "Non-async response from delete!" #~ msgstr "削除コマンドã‹ã‚‰ã®å¿œç­”ãŒä¸æ­£(éžåŒæœŸã§ãªã„)ã§ã™ï¼" #, fuzzy #~ msgid "Non-async response from init!" #~ msgstr "åˆæœŸåŒ–コマンドã‹ã‚‰ã®å¿œç­”ãŒä¸æ­£(éžåŒæœŸã§ãªã„)ã§ã™ï¼" #~ msgid "Non-async response from snapshot!" #~ msgstr "スナップショットã‹ã‚‰ã®å¿œç­”ãŒä¸æ­£(éžåŒæœŸã§ãªã„)ã§ã™ï¼" #~ msgid "Server certificate has changed" #~ msgstr "サーãƒã®è¨¼æ˜Žæ›¸ãŒå¤‰æ›´ã•れã¦ã„ã¾ã—ãŸ" #, fuzzy #~ msgid "Unexpected non-async response" #~ msgstr "䏿­£ãªãƒ¬ã‚¹ãƒãƒ³ã‚¹ (éžåŒæœŸã§ãªã„)" #~ msgid "bad response type from image list!" #~ msgstr "イメージリストã‹ã‚‰ã®ãƒ¬ã‚¹ãƒãƒ³ã‚¹ã‚¿ã‚¤ãƒ—ãŒä¸æ­£ï¼" #~ msgid "bad response type from list!" #~ msgstr "一覧ã‹ã‚‰ã®ãƒ¬ã‚¹ãƒãƒ³ã‚¹ã‚¿ã‚¤ãƒ—ãŒä¸æ­£ï¼" #, fuzzy #~ msgid "got non-async response!" #~ msgstr "䏿­£ãª(éžåŒæœŸã§ãªã„)応答を得ã¾ã—ãŸï¼" #~ msgid "got non-sync response from containers get!" #~ msgstr "コンテナã‹ã‚‰ä¸æ­£ãª(éžåŒæœŸã§ãªã„)応答を得ã¾ã—ãŸï¼" #~ msgid "Delete a container or container snapshot.\n" #~ msgstr "コンテナã¾ãŸã¯ã‚³ãƒ³ãƒ†ãƒŠã®ã‚¹ãƒŠãƒƒãƒ—ショットを削除ã—ã¾ã™ã€‚\n" #~ msgid "List information on containers.\n" #~ msgstr "ã‚³ãƒ³ãƒ†ãƒŠã®æƒ…報を一覧表示ã—ã¾ã™ã€‚\n" #~ msgid "Lists the available resources.\n" #~ msgstr "利用å¯èƒ½ãªãƒªã‚½ãƒ¼ã‚¹ã‚’一覧表示ã—ã¾ã™ã€‚\n" #~ msgid "Manage files on a container.\n" #~ msgstr "コンテナ上ã®ãƒ•ァイルを管ç†ã—ã¾ã™ã€‚\n" #~ msgid "Manage remote lxc servers.\n" #~ msgstr "リモートã®lxcサーãƒã‚’管ç†ã—ã¾ã™ã€‚\n" #~ msgid "Non-async response from create!" #~ msgstr "作æˆã‚³ãƒžãƒ³ãƒ‰ã‹ã‚‰ã®ãƒ¬ã‚¹ãƒãƒ³ã‚¹ãŒä¸æ­£(éžåŒæœŸã§ãªã„)ï¼" #~ msgid "Only 'password' can be set currently" #~ msgstr "ç¾æ™‚点ã§ã¯ 'password' ã®ã¿ãŒè¨­å®šå¯èƒ½ã§ã™" #~ msgid "" #~ "lxc image import [target] [--created-at=ISO-8601] [--expires-" #~ "at=ISO-8601] [--fingerprint=HASH] [prop=value]\n" #~ msgstr "" #~ "lxc image import [destination] [--created-at=ISO-8601] [--" #~ "expires-at=ISO-8601] [--fingerprint=HASH] [proprit=valeur]\n" #~ msgid "lxc init ubuntu []\n" #~ msgstr "lxc init ubuntu []\n" #~ msgid "lxc launch ubuntu []\n" #~ msgstr "lxc launch ubuntu []\n" lxd-2.0.0/po/lxd.pot000066400000000000000000000774311270277227600142610ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. # #, fuzzy msgid "" msgstr "Project-Id-Version: lxd\n" "Report-Msgid-Bugs-To: lxc-devel@lists.linuxcontainers.org\n" "POT-Creation-Date: 2016-04-11 15:01-0400\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=CHARSET\n" "Content-Transfer-Encoding: 8bit\n" #: lxc/info.go:140 msgid " Disk usage:" msgstr "" #: lxc/info.go:163 msgid " Memory usage:" msgstr "" #: lxc/info.go:180 msgid " Network usage:" msgstr "" #: lxc/config.go:37 msgid "### This is a yaml representation of the configuration.\n" "### Any line starting with a '# will be ignored.\n" "###\n" "### A sample configuration looks like:\n" "### name: container1\n" "### profiles:\n" "### - default\n" "### config:\n" "### volatile.eth0.hwaddr: 00:16:3e:e9:f8:7f\n" "### devices:\n" "### homedir:\n" "### path: /extra\n" "### source: /home/user\n" "### type: disk\n" "### ephemeral: false\n" "###\n" "### Note that the name is shown but cannot be changed" msgstr "" #: lxc/image.go:83 msgid "### This is a yaml representation of the image properties.\n" "### Any line starting with a '# will be ignored.\n" "###\n" "### Each property is represented by a single line:\n" "### An example would be:\n" "### description: My custom image" msgstr "" #: lxc/profile.go:27 msgid "### This is a yaml representation of the profile.\n" "### Any line starting with a '# will be ignored.\n" "###\n" "### A profile consists of a set of configuration items followed by a set of\n" "### devices.\n" "###\n" "### An example would look like:\n" "### name: onenic\n" "### config:\n" "### raw.lxc: lxc.aa_profile=unconfined\n" "### devices:\n" "### eth0:\n" "### nictype: bridged\n" "### parent: lxdbr0\n" "### type: nic\n" "###\n" "### Note that the name is shown but cannot be changed" msgstr "" #: lxc/image.go:583 #, c-format msgid "%s (%d more)" msgstr "" #: lxc/snapshot.go:61 msgid "'/' not allowed in snapshot name" msgstr "" #: lxc/profile.go:226 msgid "(none)" msgstr "" #: lxc/image.go:604 lxc/image.go:633 msgid "ALIAS" msgstr "" #: lxc/image.go:608 msgid "ARCH" msgstr "" #: lxc/list.go:367 msgid "ARCHITECTURE" msgstr "" #: lxc/remote.go:53 msgid "Accept certificate" msgstr "" #: lxc/remote.go:256 #, c-format msgid "Admin password for %s: " msgstr "" #: lxc/image.go:347 msgid "Aliases:" msgstr "" #: lxc/exec.go:54 msgid "An environment variable of the form HOME=/home/foo" msgstr "" #: lxc/image.go:330 lxc/info.go:90 #, c-format msgid "Architecture: %s" msgstr "" #: lxc/image.go:351 #, c-format msgid "Auto update: %s" msgstr "" #: lxc/help.go:49 msgid "Available commands:" msgstr "" #: lxc/info.go:172 msgid "Bytes received" msgstr "" #: lxc/info.go:173 msgid "Bytes sent" msgstr "" #: lxc/config.go:270 msgid "COMMON NAME" msgstr "" #: lxc/list.go:368 msgid "CREATED AT" msgstr "" #: lxc/config.go:114 #, c-format msgid "Can't read from stdin: %s" msgstr "" #: lxc/config.go:127 lxc/config.go:160 lxc/config.go:182 #, c-format msgid "Can't unset key '%s', it's not currently set." msgstr "" #: lxc/profile.go:343 msgid "Cannot provide container name to list" msgstr "" #: lxc/remote.go:206 #, c-format msgid "Certificate fingerprint: %x" msgstr "" #: lxc/action.go:28 #, c-format msgid "Changes state of one or more containers to %s.\n" "\n" "lxc %s [...]" msgstr "" #: lxc/remote.go:279 msgid "Client certificate stored at server: " msgstr "" #: lxc/list.go:97 lxc/list.go:98 msgid "Columns" msgstr "" #: lxc/init.go:134 lxc/init.go:135 lxc/launch.go:40 lxc/launch.go:41 msgid "Config key/value to apply to the new container" msgstr "" #: lxc/config.go:500 lxc/config.go:565 lxc/image.go:687 lxc/profile.go:190 #, c-format msgid "Config parsing error: %s" msgstr "" #: lxc/main.go:37 msgid "Connection refused; is LXD running?" msgstr "" #: lxc/publish.go:59 msgid "Container name is mandatory" msgstr "" #: lxc/init.go:209 #, c-format msgid "Container name is: %s" msgstr "" #: lxc/publish.go:141 lxc/publish.go:156 #, c-format msgid "Container published with fingerprint: %s" msgstr "" #: lxc/image.go:155 msgid "Copy aliases from source" msgstr "" #: lxc/copy.go:22 msgid "Copy containers within or in between lxd instances.\n" "\n" "lxc copy [remote:] [remote:] [--ephemeral|e]" msgstr "" #: lxc/image.go:268 #, c-format msgid "Copying the image: %s" msgstr "" #: lxc/remote.go:221 msgid "Could not create server cert dir" msgstr "" #: lxc/snapshot.go:21 msgid "Create a read-only snapshot of a container.\n" "\n" "lxc snapshot [remote:] [--stateful]\n" "\n" "Creates a snapshot of the container (optionally with the container's memory\n" "state). When --stateful is used, LXD attempts to checkpoint the container's\n" "running state, including process memory state, TCP connections, etc. so that it\n" "can be restored (via lxc restore) at a later time (although some things, e.g.\n" "TCP connections after the TCP timeout window has expired, may not be restored\n" "successfully).\n" "\n" "Example:\n" "lxc snapshot u1 snap0" msgstr "" #: lxc/image.go:335 lxc/info.go:92 #, c-format msgid "Created: %s" msgstr "" #: lxc/init.go:177 lxc/launch.go:116 #, c-format msgid "Creating %s" msgstr "" #: lxc/init.go:175 msgid "Creating the container" msgstr "" #: lxc/image.go:607 lxc/image.go:635 msgid "DESCRIPTION" msgstr "" #: lxc/delete.go:25 msgid "Delete containers or container snapshots.\n" "\n" "lxc delete [remote:][/] [remote:][[/]...]\n" "\n" "Destroy containers or snapshots with any attached data (configuration, snapshots, ...)." msgstr "" #: lxc/config.go:617 #, c-format msgid "Device %s added to %s" msgstr "" #: lxc/config.go:804 #, c-format msgid "Device %s removed from %s" msgstr "" #: lxc/list.go:451 msgid "EPHEMERAL" msgstr "" #: lxc/config.go:272 msgid "EXPIRY DATE" msgstr "" #: lxc/main.go:55 msgid "Enables debug mode." msgstr "" #: lxc/main.go:54 msgid "Enables verbose mode." msgstr "" #: lxc/help.go:68 msgid "Environment:" msgstr "" #: lxc/copy.go:29 lxc/copy.go:30 lxc/init.go:138 lxc/init.go:139 lxc/launch.go:44 lxc/launch.go:45 msgid "Ephemeral container" msgstr "" #: lxc/monitor.go:56 msgid "Event type to listen for" msgstr "" #: lxc/exec.go:45 msgid "Execute the specified command in a container.\n" "\n" "lxc exec [remote:]container [--mode=auto|interactive|non-interactive] [--env EDITOR=/usr/bin/vim]... \n" "\n" "Mode defaults to non-interactive, interactive mode is selected if both stdin AND stdout are terminals (stderr is ignored)." msgstr "" #: lxc/image.go:339 #, c-format msgid "Expires: %s" msgstr "" #: lxc/image.go:341 msgid "Expires: never" msgstr "" #: lxc/config.go:269 lxc/image.go:605 lxc/image.go:634 msgid "FINGERPRINT" msgstr "" #: lxc/list.go:100 msgid "Fast mode (same as --columns=nsacPt" msgstr "" #: lxc/image.go:328 #, c-format msgid "Fingerprint: %s" msgstr "" #: lxc/finger.go:17 msgid "Fingers the LXD instance to check if it is up and working.\n" "\n" "lxc finger " msgstr "" #: lxc/action.go:37 msgid "Force the container to shutdown." msgstr "" #: lxc/delete.go:34 lxc/delete.go:35 msgid "Force the removal of stopped containers." msgstr "" #: lxc/main.go:56 msgid "Force using the local unix socket." msgstr "" #: lxc/list.go:99 msgid "Format" msgstr "" #: lxc/main.go:138 msgid "Generating a client certificate. This may take a minute..." msgstr "" #: lxc/list.go:365 msgid "IPV4" msgstr "" #: lxc/list.go:366 msgid "IPV6" msgstr "" #: lxc/config.go:271 msgid "ISSUE DATE" msgstr "" #: lxc/main.go:146 msgid "If this is your first time using LXD, you should also run: sudo lxd init" msgstr "" #: lxc/main.go:57 msgid "Ignore aliases when determining what command to run." msgstr "" #: lxc/action.go:39 msgid "Ignore the container state (only forstart)." msgstr "" #: lxc/image.go:273 msgid "Image copied successfully!" msgstr "" #: lxc/image.go:419 #, c-format msgid "Image imported with fingerprint: %s" msgstr "" #: lxc/init.go:73 msgid "Initialize a container from a particular image.\n" "\n" "lxc init [remote:] [remote:][] [--ephemeral|-e] [--profile|-p ...] [--config|-c ...]\n" "\n" "Initializes a container using the specified image and name.\n" "\n" "Not specifying -p will result in the default profile.\n" "Specifying \"-p\" with no argument will result in no profile.\n" "\n" "Example:\n" "lxc init ubuntu u1" msgstr "" #: lxc/remote.go:122 #, c-format msgid "Invalid URL scheme \"%s\" in \"%s\"" msgstr "" #: lxc/init.go:30 lxc/init.go:35 msgid "Invalid configuration key" msgstr "" #: lxc/file.go:190 #, c-format msgid "Invalid source %s" msgstr "" #: lxc/file.go:57 #, c-format msgid "Invalid target %s" msgstr "" #: lxc/info.go:121 msgid "Ips:" msgstr "" #: lxc/image.go:156 msgid "Keep the image up to date after initial copy" msgstr "" #: lxc/main.go:35 msgid "LXD socket not found; is LXD running?" msgstr "" #: lxc/launch.go:22 msgid "Launch a container from a particular image.\n" "\n" "lxc launch [remote:] [remote:][] [--ephemeral|-e] [--profile|-p ...] [--config|-c ...]\n" "\n" "Launches a container using the specified image and name.\n" "\n" "Not specifying -p will result in the default profile.\n" "Specifying \"-p\" with no argument will result in no profile.\n" "\n" "Example:\n" "lxc launch ubuntu u1" msgstr "" #: lxc/info.go:25 msgid "List information on LXD servers and containers.\n" "\n" "For a container:\n" " lxc info [:]container [--show-log]\n" "\n" "For a server:\n" " lxc info [:]" msgstr "" #: lxc/list.go:67 msgid "Lists the available resources.\n" "\n" "lxc list [resource] [filters] [--format table|json] [-c columns] [--fast]\n" "\n" "The filters are:\n" "* A single keyword like \"web\" which will list any container with \"web\" in its name.\n" "* A key/value pair referring to a configuration item. For those, the namespace can be abreviated to the smallest unambiguous identifier:\n" "* \"user.blah=abc\" will list all containers with the \"blah\" user property set to \"abc\"\n" "* \"u.blah=abc\" will do the same\n" "* \"security.privileged=1\" will list all privileged containers\n" "* \"s.privileged=1\" will do the same\n" "\n" "Columns for table format are:\n" "* 4 - IPv4 address\n" "* 6 - IPv6 address\n" "* a - architecture\n" "* c - creation date\n" "* n - name\n" "* p - pid of container init process\n" "* P - profiles\n" "* s - state\n" "* S - number of snapshots\n" "* t - type (persistent or ephemeral)\n" "\n" "Default column layout: ns46tS\n" "Fast column layout: nsacPt" msgstr "" #: lxc/info.go:225 msgid "Log:" msgstr "" #: lxc/image.go:154 msgid "Make image public" msgstr "" #: lxc/publish.go:32 msgid "Make the image public" msgstr "" #: lxc/profile.go:48 msgid "Manage configuration profiles.\n" "\n" "lxc profile list [filters] List available profiles.\n" "lxc profile show Show details of a profile.\n" "lxc profile create Create a profile.\n" "lxc profile copy Copy the profile to the specified remote.\n" "lxc profile get Get profile configuration.\n" "lxc profile set Set profile configuration.\n" "lxc profile delete Delete a profile.\n" "lxc profile edit \n" " Edit profile, either by launching external editor or reading STDIN.\n" " Example: lxc profile edit # launch editor\n" " cat profile.yml | lxc profile edit # read from profile.yml\n" "lxc profile apply \n" " Apply a comma-separated list of profiles to a container, in order.\n" " All profiles passed in this call (and only those) will be applied\n" " to the specified container.\n" " Example: lxc profile apply foo default,bar # Apply default and bar\n" " lxc profile apply foo default # Only default is active\n" " lxc profile apply '' # no profiles are applied anymore\n" " lxc profile apply bar,default # Apply default second now\n" "\n" "Devices:\n" "lxc profile device list List devices in the given profile.\n" "lxc profile device show Show full device details in the given profile.\n" "lxc profile device remove Remove a device from a profile.\n" "lxc profile device get <[remote:]profile> Get a device property.\n" "lxc profile device set <[remote:]profile> Set a device property.\n" "lxc profile device unset <[remote:]profile> Unset a device property.\n" "lxc profile device add [key=value]...\n" " Add a profile device, such as a disk or a nic, to the containers\n" " using the specified profile." msgstr "" #: lxc/config.go:58 msgid "Manage configuration.\n" "\n" "lxc config device add <[remote:]container> [key=value]... Add a device to a container.\n" "lxc config device get <[remote:]container> Get a device property.\n" "lxc config device set <[remote:]container> Set a device property.\n" "lxc config device unset <[remote:]container> Unset a device property.\n" "lxc config device list <[remote:]container> List devices for container.\n" "lxc config device show <[remote:]container> Show full device details for container.\n" "lxc config device remove <[remote:]container> Remove device from container.\n" "\n" "lxc config get [remote:][container] Get container or server configuration key.\n" "lxc config set [remote:][container] Set container or server configuration key.\n" "lxc config unset [remote:][container] Unset container or server configuration key.\n" "lxc config show [remote:][container] [--expanded] Show container or server configuration.\n" "lxc config edit [remote:][container] Edit container or server configuration in external editor.\n" " Edit configuration, either by launching external editor or reading STDIN.\n" " Example: lxc config edit # launch editor\n" " cat config.yml | lxc config edit # read from config.yml\n" "\n" "lxc config trust list [remote] List all trusted certs.\n" "lxc config trust add [remote] Add certfile.crt to trusted hosts.\n" "lxc config trust remove [remote] [hostname|fingerprint] Remove the cert from trusted hosts.\n" "\n" "Examples:\n" "To mount host's /share/c1 onto /opt in the container:\n" " lxc config device add [remote:]container1 disk source=/share/c1 path=opt\n" "\n" "To set an lxc config value:\n" " lxc config set [remote:] raw.lxc 'lxc.aa_allow_incomplete = 1'\n" "\n" "To listen on IPv4 and IPv6 port 8443 (you can omit the 8443 its the default):\n" " lxc config set core.https_address [::]:8443\n" "\n" "To set the server trust password:\n" " lxc config set core.trust_password blah" msgstr "" #: lxc/file.go:32 msgid "Manage files on a container.\n" "\n" "lxc file pull [...] \n" "lxc file push [--uid=UID] [--gid=GID] [--mode=MODE] [...] \n" "lxc file edit \n" "\n" " in the case of pull, in the case of push and in the case of edit are /" msgstr "" #: lxc/remote.go:39 msgid "Manage remote LXD servers.\n" "\n" "lxc remote add [--accept-certificate] [--password=PASSWORD]\n" " [--public] [--protocol=PROTOCOL] Add the remote at .\n" "lxc remote remove Remove the remote .\n" "lxc remote list List all remotes.\n" "lxc remote rename Rename remote to .\n" "lxc remote set-url Update 's url to .\n" "lxc remote set-default Set the default remote.\n" "lxc remote get-default Print the default remote." msgstr "" #: lxc/image.go:93 msgid "Manipulate container images.\n" "\n" "In LXD containers are created from images. Those images were themselves\n" "either generated from an existing container or downloaded from an image\n" "server.\n" "\n" "When using remote images, LXD will automatically cache images for you\n" "and remove them upon expiration.\n" "\n" "The image unique identifier is the hash (sha-256) of its representation\n" "as a compressed tarball (or for split images, the concatenation of the\n" "metadata and rootfs tarballs).\n" "\n" "Images can be referenced by their full hash, shortest unique partial\n" "hash or alias name (if one is set).\n" "\n" "\n" "lxc image import [rootfs tarball|URL] [remote:] [--public] [--created-at=ISO-8601] [--expires-at=ISO-8601] [--fingerprint=FINGERPRINT] [prop=value]\n" " Import an image tarball (or tarballs) into the LXD image store.\n" "\n" "lxc image copy [remote:] : [--alias=ALIAS].. [--copy-aliases] [--public] [--auto-update]\n" " Copy an image from one LXD daemon to another over the network.\n" "\n" " The auto-update flag instructs the server to keep this image up to\n" " date. It requires the source to be an alias and for it to be public.\n" "\n" "lxc image delete [remote:]\n" " Delete an image from the LXD image store.\n" "\n" "lxc image export [remote:]\n" " Export an image from the LXD image store into a distributable tarball.\n" "\n" "lxc image info [remote:]\n" " Print everything LXD knows about a given image.\n" "\n" "lxc image list [remote:] [filter]\n" " List images in the LXD image store. Filters may be of the\n" " = form for property based filtering, or part of the image\n" " hash or part of the image alias name.\n" "\n" "lxc image show [remote:]\n" " Yaml output of the user modifiable properties of an image.\n" "\n" "lxc image edit [remote:]\n" " Edit image, either by launching external editor or reading STDIN.\n" " Example: lxc image edit # launch editor\n" " cat image.yml | lxc image edit # read from image.yml\n" "\n" "lxc image alias create [remote:] \n" " Create a new alias for an existing image.\n" "\n" "lxc image alias delete [remote:]\n" " Delete an alias.\n" "\n" "lxc image alias list [remote:] [filter]\n" " List the aliases. Filters may be part of the image hash or part of the image alias name.\n" msgstr "" #: lxc/info.go:147 msgid "Memory (current)" msgstr "" #: lxc/info.go:151 msgid "Memory (peak)" msgstr "" #: lxc/help.go:86 msgid "Missing summary." msgstr "" #: lxc/monitor.go:41 msgid "Monitor activity on the LXD server.\n" "\n" "lxc monitor [remote:] [--type=TYPE...]\n" "\n" "Connects to the monitoring interface of the specified LXD server.\n" "\n" "By default will listen to all message types.\n" "Specific types to listen to can be specified with --type.\n" "\n" "Example:\n" "lxc monitor --type=logging" msgstr "" #: lxc/file.go:178 msgid "More than one file to download, but target is not a directory" msgstr "" #: lxc/move.go:17 msgid "Move containers within or in between lxd instances.\n" "\n" "lxc move [remote:] [remote:]\n" " Move a container between two hosts, renaming it if destination name differs.\n" "\n" "lxc move \n" " Rename a local container.\n" msgstr "" #: lxc/action.go:63 msgid "Must supply container name for: " msgstr "" #: lxc/list.go:369 lxc/remote.go:363 msgid "NAME" msgstr "" #: lxc/remote.go:337 lxc/remote.go:342 msgid "NO" msgstr "" #: lxc/info.go:89 #, c-format msgid "Name: %s" msgstr "" #: lxc/image.go:157 lxc/publish.go:33 msgid "New alias to define at target" msgstr "" #: lxc/config.go:281 msgid "No certificate provided to add" msgstr "" #: lxc/config.go:304 msgid "No fingerprint specified." msgstr "" #: lxc/remote.go:107 msgid "Only https URLs are supported for simplestreams" msgstr "" #: lxc/image.go:411 msgid "Only https:// is supported for remote image import." msgstr "" #: lxc/help.go:63 lxc/main.go:122 msgid "Options:" msgstr "" #: lxc/image.go:506 #, c-format msgid "Output is in %s" msgstr "" #: lxc/exec.go:55 msgid "Override the terminal mode (auto, interactive or non-interactive)" msgstr "" #: lxc/list.go:453 msgid "PERSISTENT" msgstr "" #: lxc/list.go:370 msgid "PID" msgstr "" #: lxc/list.go:371 msgid "PROFILES" msgstr "" #: lxc/remote.go:365 msgid "PROTOCOL" msgstr "" #: lxc/image.go:606 lxc/remote.go:366 msgid "PUBLIC" msgstr "" #: lxc/info.go:174 msgid "Packets received" msgstr "" #: lxc/info.go:175 msgid "Packets sent" msgstr "" #: lxc/help.go:69 msgid "Path to an alternate client configuration directory." msgstr "" #: lxc/help.go:70 msgid "Path to an alternate server directory." msgstr "" #: lxc/main.go:39 msgid "Permisson denied, are you in the lxd group?" msgstr "" #: lxc/info.go:103 #, c-format msgid "Pid: %d" msgstr "" #: lxc/help.go:25 msgid "Presents details on how to use LXD.\n" "\n" "lxd help [--all]" msgstr "" #: lxc/profile.go:191 msgid "Press enter to open the editor again" msgstr "" #: lxc/config.go:501 lxc/config.go:566 lxc/image.go:688 msgid "Press enter to start the editor again" msgstr "" #: lxc/help.go:65 msgid "Print debug information." msgstr "" #: lxc/help.go:64 msgid "Print less common commands." msgstr "" #: lxc/help.go:66 msgid "Print verbose information." msgstr "" #: lxc/version.go:18 msgid "Prints the version number of this client tool.\n" "\n" "lxc version" msgstr "" #: lxc/info.go:127 #, c-format msgid "Processes: %d" msgstr "" #: lxc/profile.go:228 #, c-format msgid "Profile %s applied to %s" msgstr "" #: lxc/profile.go:142 #, c-format msgid "Profile %s created" msgstr "" #: lxc/profile.go:212 #, c-format msgid "Profile %s deleted" msgstr "" #: lxc/init.go:136 lxc/init.go:137 lxc/launch.go:42 lxc/launch.go:43 msgid "Profile to apply to the new container" msgstr "" #: lxc/info.go:101 #, c-format msgid "Profiles: %s" msgstr "" #: lxc/image.go:343 msgid "Properties:" msgstr "" #: lxc/remote.go:56 msgid "Public image server" msgstr "" #: lxc/image.go:331 #, c-format msgid "Public: %s" msgstr "" #: lxc/publish.go:25 msgid "Publish containers as images.\n" "\n" "lxc publish [remote:]container [remote:] [--alias=ALIAS]... [prop-key=prop-value]..." msgstr "" #: lxc/remote.go:54 msgid "Remote admin password" msgstr "" #: lxc/delete.go:42 #, c-format msgid "Remove %s (yes/no): " msgstr "" #: lxc/delete.go:36 lxc/delete.go:37 msgid "Require user confirmation." msgstr "" #: lxc/info.go:124 msgid "Resources:" msgstr "" #: lxc/init.go:246 #, c-format msgid "Retrieving image: %s" msgstr "" #: lxc/image.go:609 msgid "SIZE" msgstr "" #: lxc/list.go:372 msgid "SNAPSHOTS" msgstr "" #: lxc/list.go:373 msgid "STATE" msgstr "" #: lxc/remote.go:367 msgid "STATIC" msgstr "" #: lxc/remote.go:214 msgid "Server certificate NACKed by user" msgstr "" #: lxc/remote.go:276 msgid "Server doesn't trust us after adding our cert" msgstr "" #: lxc/remote.go:55 msgid "Server protocol (lxd or simplestreams)" msgstr "" #: lxc/restore.go:21 msgid "Set the current state of a resource back to a snapshot.\n" "\n" "lxc restore [remote:] [--stateful]\n" "\n" "Restores a container from a snapshot (optionally with running state, see\n" "snapshot help for details).\n" "\n" "For example:\n" "lxc snapshot u1 snap0 # create the snapshot\n" "lxc restore u1 snap0 # restore the snapshot" msgstr "" #: lxc/file.go:44 msgid "Set the file's gid on push" msgstr "" #: lxc/file.go:45 msgid "Set the file's perms on push" msgstr "" #: lxc/file.go:43 msgid "Set the file's uid on push" msgstr "" #: lxc/help.go:32 msgid "Show all commands (not just interesting ones)" msgstr "" #: lxc/info.go:36 msgid "Show the container's last 100 log lines?" msgstr "" #: lxc/image.go:329 #, c-format msgid "Size: %.2fMB" msgstr "" #: lxc/info.go:194 msgid "Snapshots:" msgstr "" #: lxc/image.go:353 msgid "Source:" msgstr "" #: lxc/launch.go:122 #, c-format msgid "Starting %s" msgstr "" #: lxc/info.go:95 #, c-format msgid "Status: %s" msgstr "" #: lxc/publish.go:34 lxc/publish.go:35 msgid "Stop the container if currently running" msgstr "" #: lxc/delete.go:106 lxc/publish.go:111 msgid "Stopping container failed!" msgstr "" #: lxc/action.go:38 msgid "Store the container state (only for stop)." msgstr "" #: lxc/info.go:155 msgid "Swap (current)" msgstr "" #: lxc/info.go:159 msgid "Swap (peak)" msgstr "" #: lxc/list.go:374 msgid "TYPE" msgstr "" #: lxc/delete.go:92 msgid "The container is currently running, stop it first or pass --force." msgstr "" #: lxc/publish.go:89 msgid "The container is currently running. Use --force to have it stopped and restarted." msgstr "" #: lxc/config.go:645 lxc/config.go:657 lxc/config.go:690 lxc/config.go:708 lxc/config.go:746 lxc/config.go:764 msgid "The device doesn't exist" msgstr "" #: lxc/publish.go:62 msgid "There is no \"image name\". Did you want an alias?" msgstr "" #: lxc/action.go:36 msgid "Time to wait for the container before killing it." msgstr "" #: lxc/image.go:332 msgid "Timestamps:" msgstr "" #: lxc/image.go:402 #, c-format msgid "Transferring image: %d%%" msgstr "" #: lxc/action.go:93 lxc/launch.go:130 #, c-format msgid "Try `lxc info --show-log %s` for more info" msgstr "" #: lxc/info.go:97 msgid "Type: ephemeral" msgstr "" #: lxc/info.go:99 msgid "Type: persistent" msgstr "" #: lxc/image.go:610 msgid "UPLOAD DATE" msgstr "" #: lxc/remote.go:364 msgid "URL" msgstr "" #: lxc/remote.go:82 msgid "Unable to read remote TLS certificate" msgstr "" #: lxc/image.go:337 #, c-format msgid "Uploaded: %s" msgstr "" #: lxc/main.go:122 #, c-format msgid "Usage: %s" msgstr "" #: lxc/help.go:48 msgid "Usage: lxc [subcommand] [options]" msgstr "" #: lxc/delete.go:46 msgid "User aborted delete operation." msgstr "" #: lxc/restore.go:35 msgid "Whether or not to restore the container's running state from snapshot (if available)" msgstr "" #: lxc/snapshot.go:38 msgid "Whether or not to snapshot the container's running state" msgstr "" #: lxc/config.go:33 msgid "Whether to show the expanded configuration" msgstr "" #: lxc/remote.go:339 lxc/remote.go:344 msgid "YES" msgstr "" #: lxc/main.go:66 msgid "`lxc config profile` is deprecated, please use `lxc profile`" msgstr "" #: lxc/launch.go:109 msgid "bad number of things scanned from image, container or snapshot" msgstr "" #: lxc/action.go:89 msgid "bad result type from action" msgstr "" #: lxc/copy.go:78 msgid "can't copy to the same container name" msgstr "" #: lxc/remote.go:327 msgid "can't remove the default remote" msgstr "" #: lxc/remote.go:353 msgid "default" msgstr "" #: lxc/init.go:199 lxc/init.go:204 lxc/launch.go:93 lxc/launch.go:98 msgid "didn't get any affected image, container or snapshot from server" msgstr "" #: lxc/image.go:323 msgid "disabled" msgstr "" #: lxc/image.go:325 msgid "enabled" msgstr "" #: lxc/main.go:25 lxc/main.go:158 #, c-format msgid "error: %v" msgstr "" #: lxc/help.go:40 lxc/main.go:117 #, c-format msgid "error: unknown command: %s" msgstr "" #: lxc/launch.go:113 msgid "got bad version" msgstr "" #: lxc/image.go:318 lxc/image.go:586 msgid "no" msgstr "" #: lxc/copy.go:101 msgid "not all the profiles from the source exist on the target" msgstr "" #: lxc/remote.go:207 msgid "ok (y/n)?" msgstr "" #: lxc/main.go:265 lxc/main.go:269 #, c-format msgid "processing aliases failed %s\n" msgstr "" #: lxc/remote.go:389 #, c-format msgid "remote %s already exists" msgstr "" #: lxc/remote.go:319 lxc/remote.go:381 lxc/remote.go:416 lxc/remote.go:432 #, c-format msgid "remote %s doesn't exist" msgstr "" #: lxc/remote.go:302 #, c-format msgid "remote %s exists as <%s>" msgstr "" #: lxc/remote.go:323 lxc/remote.go:385 lxc/remote.go:420 #, c-format msgid "remote %s is static and cannot be modified" msgstr "" #: lxc/info.go:205 msgid "stateful" msgstr "" #: lxc/info.go:207 msgid "stateless" msgstr "" #: lxc/info.go:201 #, c-format msgid "taken at %s" msgstr "" #: lxc/exec.go:166 msgid "unreachable return reached" msgstr "" #: lxc/main.go:198 msgid "wrong number of subcommand arguments" msgstr "" #: lxc/delete.go:45 lxc/image.go:320 lxc/image.go:590 msgid "yes" msgstr "" #: lxc/copy.go:38 msgid "you must specify a source container name" msgstr "" lxd-2.0.0/scripts/000077500000000000000000000000001270277227600140035ustar00rootroot00000000000000lxd-2.0.0/scripts/lxc-to-lxd000077500000000000000000000316331270277227600157320ustar00rootroot00000000000000#!/usr/bin/python3 import argparse import json import lxc import os import subprocess import time from pylxd import api as api # Fetch a config key as a list def config_get(config, key, default=None): result = [] for line in config: fields = line.split("=", 1) if fields[0].strip() == key: result.append(fields[-1].strip()) if len(result) == 0: return default else: return result # Parse a LXC configuration file, called recursively for includes def config_parse(path): config = [] with open(path, "r") as fd: for line in fd: line = line.strip() key = line.split("=", 1)[0].strip() value = line.split("=", 1)[-1].strip() # Parse user-added includes if key == "lxc.include": # Ignore our own default configs if value.startswith("/usr/share/lxc/config/"): continue if os.path.isfile(value): config += config_parse(value) continue elif os.path.isdir(value): for entry in os.listdir(value): if not entry.endswith(".conf"): continue config += config_parse(os.path.join(value, entry)) continue else: print("Invalid include: %s", line) # Expand any fstab if key == "lxc.mount": if not os.path.exists(value): print("Container fstab file doesn't exist, skipping...") return False with open(value, "r") as fd: for line in fd: line = line.strip() if line and not line.startswith("#"): config.append("lxc.mount.entry = %s" % line) continue # Proces normal configuration keys if line and not line.startswith("#"): config.append(line) return config # Convert a LXC container to a LXD one def convert_container(container_name, args): # Connect to LXD if args.lxdpath: os.environ['LXD_DIR'] = args.lxdpath lxd = api.API() print("==> Processing container: %s" % container_name) # Load the container try: container = lxc.Container(container_name, args.lxcpath) except: print("Invalid container configuration, skipping...") return False if container.running: print("Only stopped containers can be migrated, skipping...") return False # As some keys can't be queried over the API, parse the config ourselves print("Parsing LXC configuration") lxc_config = config_parse(container.config_file_name) if args.debug: print("Container configuration:") print(" ", end="") print("\n ".join(lxc_config)) print("") if config_get(lxc_config, "lxd.migrated"): print("Container has already been migrated, skipping...") return False # Make sure we don't have a conflict print("Checking for existing containers") if lxd.container_defined(container_name): print("Container already exists, skipping...") return False # Validate lxc.utsname print("Validating container name") value = config_get(lxc_config, "lxc.utsname") if value and value[0] != container_name: print("Container name doesn't match lxc.utsname, skipping...") return False # Detect privileged containers print("Validating container mode") if config_get(lxc_config, "lxc.id_map"): print("Unprivileged containers aren't supported, skipping...") return False # Detect hooks in config for line in lxc_config: if line.startswith("lxc.hook."): print("Hooks aren't supported, skipping...") return False # Extract and valid rootfs key print("Validating container rootfs") value = config_get(lxc_config, "lxc.rootfs") if not value: print("Invalid container, missing lxc.rootfs key, skipping...") return False rootfs = value[0] if not os.path.exists(rootfs): print("Couldn't find the container rootfs '%s', skipping..." % rootfs) return False # Base config config = {} config['security.privileged'] = "true" devices = {} devices['eth0'] = {'type': "none"} # Convert network configuration print("Processing network configuration") try: count = len(container.get_config_item("lxc.network")) except: count = 0 for i in range(count): device = {"type": "nic"} # Get the device type device["nictype"] = container.get_config_item("lxc.network")[i] # Get everything else dev = container.network[i] # Validate configuration if dev.ipv4 or dev.ipv4_gateway: print("IPv4 network configuration isn't supported, skipping...") return False if dev.ipv6 or dev.ipv6_gateway: print("IPv6 network configuration isn't supported, skipping...") return False if dev.script_up or dev.script_down: print("Network config scripts aren't supported, skipping...") return False if device["nictype"] == "none": print("\"none\" network mode isn't supported, skipping...") return False if device["nictype"] == "vlan": print("\"vlan\" network mode isn't supported, skipping...") return False # Convert the configuration if dev.hwaddr: device['hwaddr'] = dev.hwaddr if dev.link: device['parent'] = dev.link if dev.mtu: device['mtu'] = int(dev.mtu) if dev.name: device['name'] = dev.name if dev.veth_pair: device['host_name'] = dev.veth_pair if device["nictype"] == "veth": if "parent" in device: device["nictype"] = "bridged" else: device["nictype"] = "p2p" if device["nictype"] == "phys": device["nictype"] = "physical" if device["nictype"] == "empty": continue devices['convert_net%d' % i] = device count += 1 # Convert storage configuration value = config_get(lxc_config, "lxc.mount.entry", []) i = 0 for entry in value: mount = entry.split(" ") if len(mount) < 4: print("Invalid mount configuration, skipping...") return False device = {'type': "disk"} # Deal with read-only mounts if "ro" in mount[3].split(","): device['readonly'] = "true" # Deal with optional mounts if "optional" in mount[3].split(","): device['optional'] = "true" # Set the source device['source'] = mount[0] # Figure out the target if mount[1][0] != "/": device['path'] = "/%s" % mount[1] else: device['path'] = mount[1].split(rootfs, 1)[-1] devices['convert_mount%d' % i] = device i += 1 # Convert environment print("Processing environment configuration") value = config_get(lxc_config, "lxc.environment", []) for env in value: entry = env.split("=", 1) config['environment.%s' % entry[0].strip()] = entry[-1].strip() # Convert auto-start print("Processing container boot configuration") value = config_get(lxc_config, "lxc.start.auto") if value and int(value[0]) > 0: config['boot.autostart'] = "true" value = config_get(lxc_config, "lxc.start.delay") if value and int(value[0]) > 0: config['boot.autostart.delay'] = value[0] value = config_get(lxc_config, "lxc.start.order") if value and int(value[0]) > 0: config['boot.autostart.priority'] = value[0] # Convert apparmor print("Processing container apparmor configuration") value = config_get(lxc_config, "lxc.aa_profile") if value: if value[0] == "lxc-container-default-with-nesting": config['security.nesting'] = "true" elif value[0] != "lxc-container-default": print("Unsupported custom apparmor profile, skipping...") return False # Convert seccomp print("Processing container seccomp configuration") value = config_get(lxc_config, "lxc.seccomp") if value: print("Custom seccomp profiles aren't supported, skipping...") return False # Convert SELinux print("Processing container SELinux configuration") value = config_get(lxc_config, "lxc.se_context") if value: print("Custom SELinux policies aren't supported, skipping...") return False # Convert capabilities print("Processing container capabilities configuration") value = config_get(lxc_config, "lxc.cap.drop") if value: print("Custom capabilities aren't supported, skipping...") return False value = config_get(lxc_config, "lxc.cap.keep") if value: print("Custom capabilities aren't supported, skipping...") return False # Setup the container creation request new = {'name': container_name, 'source': {'type': 'none'}, 'config': config, 'devices': devices, 'profiles': ["default"]} # Set the container architecture if set in LXC print("Converting container architecture configuration") arches = {'i686': 1, 'x86_64': 2, 'armhf': 3, 'arm64': 4, 'powerpc': 5, 'powerpc64': 6, 'ppc64el': 7, 's390x': 8} arch = None try: arch = config_get(lxc_config, "lxc.arch", None) if arch and arch[0] in arches: new['architecture'] = arches[arch[0]] else: print("Unknown architecture, assuming native.") except: print("Couldn't find container architecture, assuming native.") # Define the container in LXD if args.debug: print("LXD container config:") print(json.dumps(new, indent=True, sort_keys=True)) if args.dry_run: return True try: print("Creating the container") lxd.container_init(new) except Exception as e: print("Failed to create the container: %s" % e) return False time.sleep(1) # Transfer the filesystem lxd_rootfs = os.path.join("/var/lib/lxd/", "containers", container_name, "rootfs") if args.copy_rootfs: print("Copying container rootfs") if not os.path.exists(lxd_rootfs): os.mkdir(lxd_rootfs) if subprocess.call(["rsync", "-Aa", "--sparse", "--acls", "--numeric-ids", "--hard-links", "%s/" % rootfs, "%s/" % lxd_rootfs]) != 0: print("Failed to transfer the container rootfs, skipping...") return False else: if os.path.exists(lxd_rootfs): os.rmdir(lxd_rootfs) if subprocess.call(["mv", rootfs, lxd_rootfs]) != 0: print("Failed to move the container rootfs, skipping...") return False os.mkdir(rootfs) # Delete the source if args.delete: print("Deleting source container") container.delete() # Mark the container as migrated with open(container.config_file_name, "a") as fd: fd.write("lxd.migrated=true\n") print("Container is ready to use") # Argument parsing parser = argparse.ArgumentParser() parser.add_argument("--dry-run", action="store_true", default=False, help="Dry run mode") parser.add_argument("--debug", action="store_true", default=False, help="Print debugging output") parser.add_argument("--all", action="store_true", default=False, help="Import all containers") parser.add_argument("--delete", action="store_true", default=False, help="Delete the source container") parser.add_argument("--copy-rootfs", action="store_true", default=False, help="Copy the container rootfs rather than moving it") parser.add_argument("--lxcpath", type=str, default=False, help="Alternate LXC path") parser.add_argument("--lxdpath", type=str, default=False, help="Alternate LXD path") parser.add_argument(dest='containers', metavar="CONTAINER", type=str, help="Container to import", nargs="*") args = parser.parse_args() # Sanity checks if not os.geteuid() == 0: parser.error("You must be root to run this tool") if (not args.containers and not args.all) or (args.containers and args.all): parser.error("You must either pass container names or --all") for container_name in lxc.list_containers(config_path=args.lxcpath): if args.containers and container_name not in args.containers: continue convert_container(container_name, args) lxd-2.0.0/scripts/lxd-setup-lvm-storage000077500000000000000000000167311270277227600201240ustar00rootroot00000000000000#!/usr/bin/env python3 # Let's stick to core python3 modules import argparse import gettext import http.client import json import os import socket from subprocess import check_output import sys DEFAULT_VGNAME = "LXDStorage" _ = gettext.gettext gettext.textdomain("lxd") class FriendlyParser(argparse.ArgumentParser): def error(self, message): sys.stderr.write('error: %s\n' % message) self.print_help() sys.exit(2) class UnixHTTPConnection(http.client.HTTPConnection): def __init__(self, path): http.client.HTTPConnection.__init__(self, 'localhost') self.path = path def connect(self): sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) sock.connect(self.path) self.sock = sock class LXD(object): def __init__(self, path): self.lxd = UnixHTTPConnection(path) def rest_call(self, path, data=None, method="GET", headers={}): if method == "GET" and data: self.lxd.request( method, "%s?%s" % "&".join(["%s=%s" % (key, value) for key, value in data.items()]), headers) else: self.lxd.request(method, path, data, headers) r = self.lxd.getresponse() d = json.loads(r.read().decode("utf-8")) return r.status, d def set_lvm_vgname(self, vgname): self._set_lvm_config("storage.lvm_vg_name", vgname) def set_lvm_poolname(self, poolname): self._set_lvm_config("storage.lvm_thinpool_name", poolname) def _set_lvm_config(self, key, val): data = json.dumps({"config": {key: val}}) status, data = self.rest_call("/1.0", data, "PUT") if status != 200: sys.stderr.write("Error in setting vgname:{}\n{}\n".format(status, data)) raise Exception("Failed to set vgname: %s" % val) def get_server_config(self): status, config = self.rest_call("/1.0", "", "GET") if status != 200: sys.stderr.write("Error in getting vgname\n") raise Exception("Failed to get vgname") return config["metadata"]["config"] def lxd_dir(): if "LXD_DIR" in os.environ: return os.environ["LXD_DIR"] else: return "/var/lib/lxd" def connect_to_socket(): lxd_socket = os.path.join(lxd_dir(), "unix.socket") if not os.path.exists(lxd_socket): print(_("LXD isn't running.")) sys.exit(1) return LXD(lxd_socket) def create_image(args): imgfname = os.path.join(lxd_dir(), "{}.img".format(args.size)) rollbacks = [] try: print("Creating sparse backing file {}".format(imgfname), flush=True) check_output("truncate -s {} {}".format(args.size, imgfname), shell=True) rollbacks.append("rm {}".format(imgfname)) print("Setting up loop device", flush=True) pvloopdev = check_output("losetup -f", shell=True).decode().strip() check_output("losetup {} {}".format(pvloopdev, imgfname), shell=True) rollbacks.append("losetup -d " + pvloopdev) print("Creating LVM PV {}".format(pvloopdev), flush=True) check_output("pvcreate {}".format(pvloopdev), shell=True) rollbacks.append("pvremove " + pvloopdev) print("Creating LVM VG {}".format(DEFAULT_VGNAME), flush=True) check_output("vgcreate {} {}".format(DEFAULT_VGNAME, pvloopdev), shell=True) rollbacks.append("vgremove {}".format(DEFAULT_VGNAME)) except Exception as e: sys.stderr.write("Error: {}. Cleaning up:\n".format(e)) for rbcmd in reversed(rollbacks): sys.stderr.write("+ {}\n".format(rbcmd)) check_output(rbcmd, shell=True) raise e def destroy_image(args, lxd): print("Checking current LXD configuration", flush=True) cfg = lxd.get_server_config() vgname = cfg.get("storage.lvm_vg_name", None) if vgname is None: sys.stderr.write("LXD is not configured for LVM. " "No changes will be made.\n") return lvnames = check_output("lvs {} -o name,lv_attr --noheadings" .format(vgname), shell=True).decode().strip() used_lvs = [] for lvline in lvnames.split("\n"): if lvline == '': continue name, attrs = lvline.split() if attrs.strip().startswith("V"): used_lvs.append(name) if len(used_lvs) > 0: print("LVM storage is still in use by the following volumes: {}" .format(used_lvs)) print("Please delete the corresponding images and/or " "containers before destroying storage.") sys.exit() pvname = check_output("vgs {} --noheadings -o pv_name" .format(vgname), shell=True).decode().strip() print("Removing volume group {}".format(vgname)) check_output("vgremove -f {}".format(vgname), shell=True) print("Removing physical volume {}".format(pvname)) check_output("pvremove -y {}".format(pvname), shell=True) lostr = check_output("losetup -a | grep {}".format(pvname), shell=True).decode().strip() imgfname = lostr.split('(')[-1].replace(')', '') print("Detaching loop device {}".format(pvname)) check_output("losetup -d {}".format(pvname), shell=True) print("Deleting backing file {}".format(imgfname)) if os.path.exists(imgfname): check_output("rm '{}'".format(imgfname), shell=True) def do_main(): parser = FriendlyParser( description=_("LXD: LVM storage helper"), formatter_class=argparse.RawTextHelpFormatter, epilog=_("""Examples: To create a 10G sparse loopback file and register it with LVM and LXD: %s -s 10G To de-configure LXD and destroy the LVM volumes and backing file: %s --destroy """ % (sys.argv[0], sys.argv[0]))) parser.add_argument("-s", "--size", default="10G", help=_("Size of backing file to register as LVM PV")) parser.add_argument("--destroy", action="store_true", default=False, help=_("Un-configure LXD and delete image file")) args = parser.parse_args() if os.geteuid() != 0: sys.exit("Configuring LVM requires root privileges.") try: check_output("type vgcreate", shell=True) except: sys.exit("lvm2 tools not found. try 'apt-get install lvm2 " "thin-provisioning-tools'") try: check_output("type thin_check", shell=True) except: sys.exit("lvm thin provisioning tools are required. " "try 'apt-get install thin-provisioning-tools'") lxd = connect_to_socket() if args.destroy: try: destroy_image(args, lxd) print("Clearing LXD storage configuration") lxd.set_lvm_vgname("") lxd.set_lvm_poolname("") except Exception as e: sys.stderr.write("Error destroying image:") sys.stderr.write(str(e)) sys.stderr.write("\n") else: try: create_image(args) except: sys.stderr.write("Stopping.\n") else: try: print("Configuring LXD") lxd.set_lvm_vgname(DEFAULT_VGNAME) except: sys.stderr.write("Error configuring LXD, " "removing backing file\n") destroy_image(args, lxd) print("Done.") if __name__ == "__main__": do_main() lxd-2.0.0/scripts/vagrant/000077500000000000000000000000001270277227600154455ustar00rootroot00000000000000lxd-2.0.0/scripts/vagrant/install-go.sh000066400000000000000000000006511270277227600200540ustar00rootroot00000000000000#!/bin/bash set -xe export DEBIAN_FRONTEND=noninteractive which add-apt-repository || (sudo apt-get update ; sudo apt-get install -y software-properties-common) sudo add-apt-repository ppa:ubuntu-lxc/lxd-git-master sudo apt-get update which go || sudo apt-get install -y golang [ -e $HOME/go ] || mkdir -p $HOME/go cat << 'EOF' | sudo tee /etc/profile.d/S99go.sh export GOPATH=$HOME/go export PATH=$PATH:$GOPATH/bin EOF lxd-2.0.0/scripts/vagrant/install-lxd.sh000066400000000000000000000014101270277227600202300ustar00rootroot00000000000000#!/bin/bash set -xe export DEBIAN_FRONTEND=noninteractive # install runtime dependencies sudo apt-get -y install xz-utils tar acl curl gettext \ jq sqlite3 # install build dependencies sudo apt-get -y install lxc lxc-dev mercurial git pkg-config \ protobuf-compiler golang-goprotobuf-dev # setup env [ -e uid_gid_setup ] || \ echo "root:1000000:65536" | sudo tee -a /etc/subuid /etc/subgid && \ touch uid_gid_setup go get github.com/lxc/lxd cd $GOPATH/src/github.com/lxc/lxd go get -v -d ./... make cat << 'EOF' | sudo tee /etc/init/lxd.conf description "LXD daemon" author "John Brooker" start on filesystem or runlevel [2345] stop on shutdown script exec /home/vagrant/go/bin/lxd --group vagrant end script EOF sudo service lxd start lxd-2.0.0/shared/000077500000000000000000000000001270277227600135625ustar00rootroot00000000000000lxd-2.0.0/shared/architectures.go000066400000000000000000000062621270277227600167640ustar00rootroot00000000000000package shared import ( "fmt" ) const ( ARCH_UNKNOWN = 0 ARCH_32BIT_INTEL_X86 = 1 ARCH_64BIT_INTEL_X86 = 2 ARCH_32BIT_ARMV7_LITTLE_ENDIAN = 3 ARCH_64BIT_ARMV8_LITTLE_ENDIAN = 4 ARCH_32BIT_POWERPC_BIG_ENDIAN = 5 ARCH_64BIT_POWERPC_BIG_ENDIAN = 6 ARCH_64BIT_POWERPC_LITTLE_ENDIAN = 7 ARCH_64BIT_S390_BIG_ENDIAN = 8 ) var architectureNames = map[int]string{ ARCH_32BIT_INTEL_X86: "i686", ARCH_64BIT_INTEL_X86: "x86_64", ARCH_32BIT_ARMV7_LITTLE_ENDIAN: "armv7l", ARCH_64BIT_ARMV8_LITTLE_ENDIAN: "aarch64", ARCH_32BIT_POWERPC_BIG_ENDIAN: "ppc", ARCH_64BIT_POWERPC_BIG_ENDIAN: "ppc64", ARCH_64BIT_POWERPC_LITTLE_ENDIAN: "ppc64le", ARCH_64BIT_S390_BIG_ENDIAN: "s390x", } var architectureAliases = map[int][]string{ ARCH_32BIT_INTEL_X86: []string{"i386"}, ARCH_64BIT_INTEL_X86: []string{"amd64"}, ARCH_32BIT_ARMV7_LITTLE_ENDIAN: []string{"armel", "armhf"}, ARCH_64BIT_ARMV8_LITTLE_ENDIAN: []string{"arm64"}, ARCH_32BIT_POWERPC_BIG_ENDIAN: []string{"powerpc"}, ARCH_64BIT_POWERPC_BIG_ENDIAN: []string{"powerpc64"}, ARCH_64BIT_POWERPC_LITTLE_ENDIAN: []string{"ppc64el"}, } var architecturePersonalities = map[int]string{ ARCH_32BIT_INTEL_X86: "linux32", ARCH_64BIT_INTEL_X86: "linux64", ARCH_32BIT_ARMV7_LITTLE_ENDIAN: "linux32", ARCH_64BIT_ARMV8_LITTLE_ENDIAN: "linux64", ARCH_32BIT_POWERPC_BIG_ENDIAN: "linux32", ARCH_64BIT_POWERPC_BIG_ENDIAN: "linux64", ARCH_64BIT_POWERPC_LITTLE_ENDIAN: "linux64", ARCH_64BIT_S390_BIG_ENDIAN: "linux64", } var architectureSupportedPersonalities = map[int][]int{ ARCH_32BIT_INTEL_X86: []int{}, ARCH_64BIT_INTEL_X86: []int{ARCH_32BIT_INTEL_X86}, ARCH_32BIT_ARMV7_LITTLE_ENDIAN: []int{}, ARCH_64BIT_ARMV8_LITTLE_ENDIAN: []int{ARCH_32BIT_ARMV7_LITTLE_ENDIAN}, ARCH_32BIT_POWERPC_BIG_ENDIAN: []int{}, ARCH_64BIT_POWERPC_BIG_ENDIAN: []int{ARCH_32BIT_POWERPC_BIG_ENDIAN}, ARCH_64BIT_POWERPC_LITTLE_ENDIAN: []int{}, ARCH_64BIT_S390_BIG_ENDIAN: []int{}, } const ArchitectureDefault = "x86_64" func ArchitectureName(arch int) (string, error) { arch_name, exists := architectureNames[arch] if exists { return arch_name, nil } return "unknown", fmt.Errorf("Architecture isn't supported: %d", arch) } func ArchitectureId(arch string) (int, error) { for arch_id, arch_name := range architectureNames { if arch_name == arch { return arch_id, nil } } for arch_id, arch_aliases := range architectureAliases { for _, arch_name := range arch_aliases { if arch_name == arch { return arch_id, nil } } } return 0, fmt.Errorf("Architecture isn't supported: %s", arch) } func ArchitecturePersonality(arch int) (string, error) { arch_personality, exists := architecturePersonalities[arch] if exists { return arch_personality, nil } return "", fmt.Errorf("Architecture isn't supported: %d", arch) } func ArchitecturePersonalities(arch int) ([]int, error) { personalities, exists := architectureSupportedPersonalities[arch] if exists { return personalities, nil } return []int{}, fmt.Errorf("Architecture isn't supported: %d", arch) } lxd-2.0.0/shared/architectures_linux.go000066400000000000000000000005671270277227600202050ustar00rootroot00000000000000// +build linux package shared import ( "syscall" ) func ArchitectureGetLocal() (string, error) { uname := syscall.Utsname{} if err := syscall.Uname(&uname); err != nil { return ArchitectureDefault, err } architectureName := "" for _, c := range uname.Machine { if c == 0 { break } architectureName += string(byte(c)) } return architectureName, nil } lxd-2.0.0/shared/architectures_others.go000066400000000000000000000001631270277227600203420ustar00rootroot00000000000000// +build !linux package shared func ArchitectureGetLocal() (string, error) { return ArchitectureDefault, nil } lxd-2.0.0/shared/cert.go000066400000000000000000000106111270277227600150450ustar00rootroot00000000000000// http://golang.org/src/pkg/crypto/tls/generate_cert.go // Copyright 2009 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package shared import ( "crypto/rand" "crypto/rsa" "crypto/x509" "crypto/x509/pkix" "encoding/pem" "fmt" "io/ioutil" "log" "math/big" "net" "os" "os/user" "path" "time" ) // CertInfo is the representation of a Certificate in the API. type CertInfo struct { Certificate string `json:"certificate"` Fingerprint string `json:"fingerprint"` Type string `json:"type"` } /* * Generate a list of names for which the certificate will be valid. * This will include the hostname and ip address */ func mynames() ([]string, error) { h, err := os.Hostname() if err != nil { return nil, err } ret := []string{h} ifs, err := net.Interfaces() if err != nil { return nil, err } for _, iface := range ifs { if IsLoopback(&iface) { continue } addrs, err := iface.Addrs() if err != nil { return nil, err } for _, addr := range addrs { ret = append(ret, addr.String()) } } return ret, nil } func FindOrGenCert(certf string, keyf string) error { if PathExists(certf) && PathExists(keyf) { return nil } /* If neither stat succeeded, then this is our first run and we * need to generate cert and privkey */ err := GenCert(certf, keyf) if err != nil { return err } return nil } // GenCert will create and populate a certificate file and a key file func GenCert(certf string, keyf string) error { /* Create the basenames if needed */ dir := path.Dir(certf) err := os.MkdirAll(dir, 0750) if err != nil { return err } dir = path.Dir(keyf) err = os.MkdirAll(dir, 0750) if err != nil { return err } certBytes, keyBytes, err := GenerateMemCert() if err != nil { return err } certOut, err := os.Create(certf) if err != nil { log.Fatalf("failed to open %s for writing: %s", certf, err) return err } certOut.Write(certBytes) certOut.Close() keyOut, err := os.OpenFile(keyf, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600) if err != nil { log.Printf("failed to open %s for writing: %s", keyf, err) return err } keyOut.Write(keyBytes) keyOut.Close() return nil } // GenerateMemCert creates a certificate and key pair, returning them as byte // arrays in memory. func GenerateMemCert() ([]byte, []byte, error) { privk, err := rsa.GenerateKey(rand.Reader, 4096) if err != nil { log.Fatalf("failed to generate key") return nil, nil, err } hosts, err := mynames() if err != nil { log.Fatalf("Failed to get my hostname") return nil, nil, err } validFrom := time.Now() validTo := validFrom.Add(10 * 365 * 24 * time.Hour) serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128) serialNumber, err := rand.Int(rand.Reader, serialNumberLimit) if err != nil { log.Fatalf("failed to generate serial number: %s", err) return nil, nil, err } userEntry, err := user.Current() var username string if err == nil { username = userEntry.Username if username == "" { username = "UNKNOWN" } } else { username = "UNKNOWN" } hostname, err := os.Hostname() if err != nil { hostname = "UNKNOWN" } template := x509.Certificate{ SerialNumber: serialNumber, Subject: pkix.Name{ Organization: []string{"linuxcontainers.org"}, CommonName: fmt.Sprintf("%s@%s", username, hostname), }, NotBefore: validFrom, NotAfter: validTo, KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, BasicConstraintsValid: true, } for _, h := range hosts { if ip := net.ParseIP(h); ip != nil { template.IPAddresses = append(template.IPAddresses, ip) } else { template.DNSNames = append(template.DNSNames, h) } } derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &privk.PublicKey, privk) if err != nil { log.Fatalf("Failed to create certificate: %s", err) return nil, nil, err } cert := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: derBytes}) key := pem.EncodeToMemory(&pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(privk)}) return cert, key, nil } func ReadCert(fpath string) (*x509.Certificate, error) { cf, err := ioutil.ReadFile(fpath) if err != nil { return nil, err } certBlock, _ := pem.Decode(cf) return x509.ParseCertificate(certBlock.Bytes) } lxd-2.0.0/shared/cert_test.go000066400000000000000000000016761270277227600161170ustar00rootroot00000000000000package shared import ( "encoding/pem" "testing" ) func TestGenerateMemCert(t *testing.T) { if testing.Short() { t.Skip("skipping cert generation in short mode") } cert, key, err := GenerateMemCert() if err != nil { t.Error(err) return } if cert == nil { t.Error("GenerateMemCert returned a nil cert") return } if key == nil { t.Error("GenerateMemCert returned a nil key") return } block, rest := pem.Decode(cert) if len(rest) != 0 { t.Errorf("GenerateMemCert returned a cert with trailing content: %q", string(rest)) } if block.Type != "CERTIFICATE" { t.Errorf("GenerateMemCert returned a cert with Type %q not \"CERTIFICATE\"", block.Type) } block, rest = pem.Decode(key) if len(rest) != 0 { t.Errorf("GenerateMemCert returned a key with trailing content: %q", string(rest)) } if block.Type != "RSA PRIVATE KEY" { t.Errorf("GenerateMemCert returned a cert with Type %q not \"RSA PRIVATE KEY\"", block.Type) } } lxd-2.0.0/shared/container.go000066400000000000000000000105321270277227600160740ustar00rootroot00000000000000package shared import ( "time" ) type ContainerState struct { Status string `json:"status"` StatusCode StatusCode `json:"status_code"` Disk map[string]ContainerStateDisk `json:"disk"` Memory ContainerStateMemory `json:"memory"` Network map[string]ContainerStateNetwork `json:"network"` Pid int64 `json:"pid"` Processes int64 `json:"processes"` } type ContainerStateDisk struct { Usage int64 `json:"usage"` } type ContainerStateMemory struct { Usage int64 `json:"usage"` UsagePeak int64 `json:"usage_peak"` SwapUsage int64 `json:"swap_usage"` SwapUsagePeak int64 `json:"swap_usage_peak"` } type ContainerStateNetwork struct { Addresses []ContainerStateNetworkAddress `json:"addresses"` Counters ContainerStateNetworkCounters `json:"counters"` Hwaddr string `json:"hwaddr"` HostName string `json:"host_name"` Mtu int `json:"mtu"` State string `json:"state"` Type string `json:"type"` } type ContainerStateNetworkAddress struct { Family string `json:"family"` Address string `json:"address"` Netmask string `json:"netmask"` Scope string `json:"scope"` } type ContainerStateNetworkCounters struct { BytesReceived int64 `json:"bytes_received"` BytesSent int64 `json:"bytes_sent"` PacketsReceived int64 `json:"packets_received"` PacketsSent int64 `json:"packets_sent"` } type ContainerExecControl struct { Command string `json:"command"` Args map[string]string `json:"args"` } type SnapshotInfo struct { Architecture string `json:"architecture"` Config map[string]string `json:"config"` CreationDate time.Time `json:"created_at"` Devices Devices `json:"devices"` Ephemeral bool `json:"ephemeral"` ExpandedConfig map[string]string `json:"expanded_config"` ExpandedDevices Devices `json:"expanded_devices"` Name string `json:"name"` Profiles []string `json:"profiles"` Stateful bool `json:"stateful"` } type ContainerInfo struct { Architecture string `json:"architecture"` Config map[string]string `json:"config"` CreationDate time.Time `json:"created_at"` Devices Devices `json:"devices"` Ephemeral bool `json:"ephemeral"` ExpandedConfig map[string]string `json:"expanded_config"` ExpandedDevices Devices `json:"expanded_devices"` Name string `json:"name"` Profiles []string `json:"profiles"` Stateful bool `json:"stateful"` Status string `json:"status"` StatusCode StatusCode `json:"status_code"` } func (c ContainerInfo) IsActive() bool { switch c.StatusCode { case Stopped: return false case Error: return false default: return true } } /* * BriefContainerState contains a subset of the fields in * ContainerState, namely those which a user may update */ type BriefContainerInfo struct { Name string `json:"name"` Profiles []string `json:"profiles"` Config map[string]string `json:"config"` Devices Devices `json:"devices"` Ephemeral bool `json:"ephemeral"` } func (c *ContainerInfo) Brief() BriefContainerInfo { retstate := BriefContainerInfo{Name: c.Name, Profiles: c.Profiles, Config: c.Config, Devices: c.Devices, Ephemeral: c.Ephemeral} return retstate } func (c *ContainerInfo) BriefExpanded() BriefContainerInfo { retstate := BriefContainerInfo{Name: c.Name, Profiles: c.Profiles, Config: c.ExpandedConfig, Devices: c.ExpandedDevices, Ephemeral: c.Ephemeral} return retstate } type ContainerAction string const ( Stop ContainerAction = "stop" Start ContainerAction = "start" Restart ContainerAction = "restart" Freeze ContainerAction = "freeze" Unfreeze ContainerAction = "unfreeze" ) type ProfileConfig struct { Name string `json:"name"` Config map[string]string `json:"config"` Description string `json:"description"` Devices Devices `json:"devices"` } lxd-2.0.0/shared/devices.go000066400000000000000000000040561270277227600155400ustar00rootroot00000000000000package shared type Device map[string]string type Devices map[string]Device func (list Devices) ContainsName(k string) bool { if list[k] != nil { return true } return false } func (d Device) get(key string) string { return d[key] } func (list Devices) Contains(k string, d Device) bool { // If it didn't exist, it's different if list[k] == nil { return false } old := list[k] return deviceEquals(old, d) } func deviceEquals(old Device, d Device) bool { // Check for any difference and addition/removal of properties for k, _ := range d { if d[k] != old[k] { return false } } for k, _ := range old { if d[k] != old[k] { return false } } return true } func (old Devices) Update(newlist Devices) (map[string]Device, map[string]Device, map[string]Device) { rmlist := map[string]Device{} addlist := map[string]Device{} updatelist := map[string]Device{} for key, d := range old { if !newlist.Contains(key, d) { rmlist[key] = d } } for key, d := range newlist { if !old.Contains(key, d) { addlist[key] = d } } for key, d := range addlist { srcOldDevice := rmlist[key] var oldDevice Device err := DeepCopy(&srcOldDevice, &oldDevice) if err != nil { continue } srcNewDevice := newlist[key] var newDevice Device err = DeepCopy(&srcNewDevice, &newDevice) if err != nil { continue } for _, k := range []string{"limits.max", "limits.read", "limits.write", "limits.egress", "limits.ingress"} { delete(oldDevice, k) delete(newDevice, k) } if deviceEquals(oldDevice, newDevice) { delete(rmlist, key) delete(addlist, key) updatelist[key] = d } } return rmlist, addlist, updatelist } func (newBaseDevices Devices) ExtendFromProfile(currentFullDevices Devices, newDevicesFromProfile Devices) error { // For any entry which exists in a profile and doesn't in the container config, add it for name, newDev := range newDevicesFromProfile { if curDev, ok := currentFullDevices[name]; ok { newBaseDevices[name] = curDev } else { newBaseDevices[name] = newDev } } return nil } lxd-2.0.0/shared/flex.go000066400000000000000000000004361270277227600150520ustar00rootroot00000000000000/* This is a FLEXible file which can be used by both client and daemon. * Teehee. */ package shared var Version = "2.0.0" var UserAgent = "LXD " + Version /* * Please increment the api compat number every time you change the API. * * Version 1.0: ping */ var APIVersion = "1.0" lxd-2.0.0/shared/gnuflag/000077500000000000000000000000001270277227600152055ustar00rootroot00000000000000lxd-2.0.0/shared/gnuflag/export_test.go000066400000000000000000000012111270277227600201070ustar00rootroot00000000000000// Copyright 2010 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package gnuflag import ( "os" ) // Additional routines compiled into the package only during testing. // ResetForTesting clears all flag state and sets the usage function as directed. // After calling ResetForTesting, parse errors in flag handling will not // exit the program. func ResetForTesting(usage func()) { commandLine = NewFlagSet(os.Args[0], ContinueOnError) Usage = usage } // CommandLine returns the default FlagSet. func CommandLine() *FlagSet { return commandLine } lxd-2.0.0/shared/gnuflag/flag.go000066400000000000000000000670141270277227600164550ustar00rootroot00000000000000// Copyright 2009 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. /* Package flag implements command-line flag parsing in the GNU style. It is almost exactly the same as the standard flag package, the only difference being the extra argument to Parse. Command line flag syntax: -f // single letter flag -fg // two single letter flags together --flag // multiple letter flag --flag x // non-boolean flags only -f x // non-boolean flags only -fx // if f is a non-boolean flag, x is its argument. The last three forms are not permitted for boolean flags because the meaning of the command cmd -f * will change if there is a file called 0, false, etc. There is currently no way to turn off a boolean flag. Flag parsing stops after the terminator "--", or just before the first non-flag argument ("-" is a non-flag argument) if the interspersed argument to Parse is false. */ package gnuflag import ( "bytes" "errors" "fmt" "io" "os" "sort" "strconv" "strings" "time" "unicode/utf8" ) // ErrHelp is the error returned if the flag -help is invoked but no such flag is defined. var ErrHelp = errors.New("flag: help requested") // -- bool Value type boolValue bool func newBoolValue(val bool, p *bool) *boolValue { *p = val return (*boolValue)(p) } func (b *boolValue) Set(s string) error { v, err := strconv.ParseBool(s) *b = boolValue(v) return err } func (b *boolValue) String() string { return fmt.Sprintf("%v", *b) } // -- int Value type intValue int func newIntValue(val int, p *int) *intValue { *p = val return (*intValue)(p) } func (i *intValue) Set(s string) error { v, err := strconv.ParseInt(s, 0, 64) *i = intValue(v) return err } func (i *intValue) String() string { return fmt.Sprintf("%v", *i) } // -- int64 Value type int64Value int64 func newInt64Value(val int64, p *int64) *int64Value { *p = val return (*int64Value)(p) } func (i *int64Value) Set(s string) error { v, err := strconv.ParseInt(s, 0, 64) *i = int64Value(v) return err } func (i *int64Value) String() string { return fmt.Sprintf("%v", *i) } // -- uint Value type uintValue uint func newUintValue(val uint, p *uint) *uintValue { *p = val return (*uintValue)(p) } func (i *uintValue) Set(s string) error { v, err := strconv.ParseUint(s, 0, 64) *i = uintValue(v) return err } func (i *uintValue) String() string { return fmt.Sprintf("%v", *i) } // -- uint64 Value type uint64Value uint64 func newUint64Value(val uint64, p *uint64) *uint64Value { *p = val return (*uint64Value)(p) } func (i *uint64Value) Set(s string) error { v, err := strconv.ParseUint(s, 0, 64) *i = uint64Value(v) return err } func (i *uint64Value) String() string { return fmt.Sprintf("%v", *i) } // -- string Value type stringValue string func newStringValue(val string, p *string) *stringValue { *p = val return (*stringValue)(p) } func (s *stringValue) Set(val string) error { *s = stringValue(val) return nil } func (s *stringValue) String() string { return fmt.Sprintf("%s", *s) } // -- float64 Value type float64Value float64 func newFloat64Value(val float64, p *float64) *float64Value { *p = val return (*float64Value)(p) } func (f *float64Value) Set(s string) error { v, err := strconv.ParseFloat(s, 64) *f = float64Value(v) return err } func (f *float64Value) String() string { return fmt.Sprintf("%v", *f) } // -- time.Duration Value type durationValue time.Duration func newDurationValue(val time.Duration, p *time.Duration) *durationValue { *p = val return (*durationValue)(p) } func (d *durationValue) Set(s string) error { v, err := time.ParseDuration(s) *d = durationValue(v) return err } func (d *durationValue) String() string { return (*time.Duration)(d).String() } // Value is the interface to the dynamic value stored in a flag. // (The default value is represented as a string.) type Value interface { String() string Set(string) error } // ErrorHandling defines how to handle flag parsing errors. type ErrorHandling int const ( ContinueOnError ErrorHandling = iota ExitOnError PanicOnError ) // A FlagSet represents a set of defined flags. type FlagSet struct { // Usage is the function called when an error occurs while parsing flags. // The field is a function (not a method) that may be changed to point to // a custom error handler. Usage func() name string parsed bool actual map[string]*Flag formal map[string]*Flag args []string // arguments after flags procArgs []string // arguments being processed (gnu only) procFlag string // flag being processed (gnu only) allowIntersperse bool // (gnu only) exitOnError bool // does the program exit if there's an error? errorHandling ErrorHandling output io.Writer // nil means stderr; use out() accessor } // A Flag represents the state of a flag. type Flag struct { Name string // name as it appears on command line Usage string // help message Value Value // value as set DefValue string // default value (as text); for usage message } // sortFlags returns the flags as a slice in lexicographical sorted order. func sortFlags(flags map[string]*Flag) []*Flag { list := make(sort.StringSlice, len(flags)) i := 0 for _, f := range flags { list[i] = f.Name i++ } list.Sort() result := make([]*Flag, len(list)) for i, name := range list { result[i] = flags[name] } return result } func (f *FlagSet) out() io.Writer { if f.output == nil { return os.Stderr } return f.output } // SetOutput sets the destination for usage and error messages. // If output is nil, os.Stderr is used. func (f *FlagSet) SetOutput(output io.Writer) { f.output = output } // VisitAll visits the flags in lexicographical order, calling fn for each. // It visits all flags, even those not set. func (f *FlagSet) VisitAll(fn func(*Flag)) { for _, flag := range sortFlags(f.formal) { fn(flag) } } // VisitAll visits the command-line flags in lexicographical order, calling // fn for each. It visits all flags, even those not set. func VisitAll(fn func(*Flag)) { commandLine.VisitAll(fn) } // Visit visits the flags in lexicographical order, calling fn for each. // It visits only those flags that have been set. func (f *FlagSet) Visit(fn func(*Flag)) { for _, flag := range sortFlags(f.actual) { fn(flag) } } // Visit visits the command-line flags in lexicographical order, calling fn // for each. It visits only those flags that have been set. func Visit(fn func(*Flag)) { commandLine.Visit(fn) } // Lookup returns the Flag structure of the named flag, returning nil if none exists. func (f *FlagSet) Lookup(name string) *Flag { return f.formal[name] } // Lookup returns the Flag structure of the named command-line flag, // returning nil if none exists. func Lookup(name string) *Flag { return commandLine.formal[name] } // Set sets the value of the named flag. func (f *FlagSet) Set(name, value string) error { flag, ok := f.formal[name] if !ok { return fmt.Errorf("no such flag -%v", name) } err := flag.Value.Set(value) if err != nil { return err } if f.actual == nil { f.actual = make(map[string]*Flag) } f.actual[name] = flag return nil } // Set sets the value of the named command-line flag. func Set(name, value string) error { return commandLine.Set(name, value) } // flagsByLength is a slice of flags implementing sort.Interface, // sorting primarily by the length of the flag, and secondarily // alphabetically. type flagsByLength []*Flag func (f flagsByLength) Less(i, j int) bool { s1, s2 := f[i].Name, f[j].Name if len(s1) != len(s2) { return len(s1) < len(s2) } return s1 < s2 } func (f flagsByLength) Swap(i, j int) { f[i], f[j] = f[j], f[i] } func (f flagsByLength) Len() int { return len(f) } // flagsByName is a slice of slices of flags implementing sort.Interface, // alphabetically sorting by the name of the first flag in each slice. type flagsByName [][]*Flag func (f flagsByName) Less(i, j int) bool { return f[i][0].Name < f[j][0].Name } func (f flagsByName) Swap(i, j int) { f[i], f[j] = f[j], f[i] } func (f flagsByName) Len() int { return len(f) } // PrintDefaults prints, to standard error unless configured // otherwise, the default values of all defined flags in the set. // If there is more than one name for a given flag, the usage information and // default value from the shortest will be printed (or the least alphabetically // if there are several equally short flag names). func (f *FlagSet) PrintDefaults() { // group together all flags for a given value flags := make(map[interface{}]flagsByLength) f.VisitAll(func(f *Flag) { flags[f.Value] = append(flags[f.Value], f) }) // sort the output flags by shortest name for each group. var byName flagsByName for _, f := range flags { sort.Sort(f) byName = append(byName, f) } sort.Sort(byName) var line bytes.Buffer for _, fs := range byName { line.Reset() for i, f := range fs { if i > 0 { line.WriteString(", ") } line.WriteString(flagWithMinus(f.Name)) } format := " %s (= %s)\n %s\n" if _, ok := fs[0].Value.(*stringValue); ok { // put quotes on the value format = " %s (= %q)\n %s\n" } fmt.Fprintf(f.out(), format, line.Bytes(), fs[0].DefValue, fs[0].Usage) } } // PrintDefaults prints to standard error the default values of all defined command-line flags. func PrintDefaults() { commandLine.PrintDefaults() } // defaultUsage is the default function to print a usage message. func defaultUsage(f *FlagSet) { fmt.Fprintf(f.out(), "Usage of %s:\n", f.name) f.PrintDefaults() } // NOTE: Usage is not just defaultUsage(commandLine) // because it serves (via godoc flag Usage) as the example // for how to write your own usage function. // Usage prints to standard error a usage message documenting all defined command-line flags. // The function is a variable that may be changed to point to a custom function. var Usage = func() { fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0]) PrintDefaults() } // NFlag returns the number of flags that have been set. func (f *FlagSet) NFlag() int { return len(f.actual) } // NFlag returns the number of command-line flags that have been set. func NFlag() int { return len(commandLine.actual) } // Arg returns the i'th argument. Arg(0) is the first remaining argument // after flags have been processed. func (f *FlagSet) Arg(i int) string { if i < 0 || i >= len(f.args) { return "" } return f.args[i] } // Arg returns the i'th command-line argument. Arg(0) is the first remaining argument // after flags have been processed. func Arg(i int) string { return commandLine.Arg(i) } // NArg is the number of arguments remaining after flags have been processed. func (f *FlagSet) NArg() int { return len(f.args) } // NArg is the number of arguments remaining after flags have been processed. func NArg() int { return len(commandLine.args) } // Args returns the non-flag arguments. func (f *FlagSet) Args() []string { return f.args } // Args returns the non-flag command-line arguments. func Args() []string { return commandLine.args } // BoolVar defines a bool flag with specified name, default value, and usage string. // The argument p points to a bool variable in which to store the value of the flag. func (f *FlagSet) BoolVar(p *bool, name string, value bool, usage string) { f.Var(newBoolValue(value, p), name, usage) } // BoolVar defines a bool flag with specified name, default value, and usage string. // The argument p points to a bool variable in which to store the value of the flag. func BoolVar(p *bool, name string, value bool, usage string) { commandLine.Var(newBoolValue(value, p), name, usage) } // Bool defines a bool flag with specified name, default value, and usage string. // The return value is the address of a bool variable that stores the value of the flag. func (f *FlagSet) Bool(name string, value bool, usage string) *bool { p := new(bool) f.BoolVar(p, name, value, usage) return p } // Bool defines a bool flag with specified name, default value, and usage string. // The return value is the address of a bool variable that stores the value of the flag. func Bool(name string, value bool, usage string) *bool { return commandLine.Bool(name, value, usage) } // IntVar defines an int flag with specified name, default value, and usage string. // The argument p points to an int variable in which to store the value of the flag. func (f *FlagSet) IntVar(p *int, name string, value int, usage string) { f.Var(newIntValue(value, p), name, usage) } // IntVar defines an int flag with specified name, default value, and usage string. // The argument p points to an int variable in which to store the value of the flag. func IntVar(p *int, name string, value int, usage string) { commandLine.Var(newIntValue(value, p), name, usage) } // Int defines an int flag with specified name, default value, and usage string. // The return value is the address of an int variable that stores the value of the flag. func (f *FlagSet) Int(name string, value int, usage string) *int { p := new(int) f.IntVar(p, name, value, usage) return p } // Int defines an int flag with specified name, default value, and usage string. // The return value is the address of an int variable that stores the value of the flag. func Int(name string, value int, usage string) *int { return commandLine.Int(name, value, usage) } // Int64Var defines an int64 flag with specified name, default value, and usage string. // The argument p points to an int64 variable in which to store the value of the flag. func (f *FlagSet) Int64Var(p *int64, name string, value int64, usage string) { f.Var(newInt64Value(value, p), name, usage) } // Int64Var defines an int64 flag with specified name, default value, and usage string. // The argument p points to an int64 variable in which to store the value of the flag. func Int64Var(p *int64, name string, value int64, usage string) { commandLine.Var(newInt64Value(value, p), name, usage) } // Int64 defines an int64 flag with specified name, default value, and usage string. // The return value is the address of an int64 variable that stores the value of the flag. func (f *FlagSet) Int64(name string, value int64, usage string) *int64 { p := new(int64) f.Int64Var(p, name, value, usage) return p } // Int64 defines an int64 flag with specified name, default value, and usage string. // The return value is the address of an int64 variable that stores the value of the flag. func Int64(name string, value int64, usage string) *int64 { return commandLine.Int64(name, value, usage) } // UintVar defines a uint flag with specified name, default value, and usage string. // The argument p points to a uint variable in which to store the value of the flag. func (f *FlagSet) UintVar(p *uint, name string, value uint, usage string) { f.Var(newUintValue(value, p), name, usage) } // UintVar defines a uint flag with specified name, default value, and usage string. // The argument p points to a uint variable in which to store the value of the flag. func UintVar(p *uint, name string, value uint, usage string) { commandLine.Var(newUintValue(value, p), name, usage) } // Uint defines a uint flag with specified name, default value, and usage string. // The return value is the address of a uint variable that stores the value of the flag. func (f *FlagSet) Uint(name string, value uint, usage string) *uint { p := new(uint) f.UintVar(p, name, value, usage) return p } // Uint defines a uint flag with specified name, default value, and usage string. // The return value is the address of a uint variable that stores the value of the flag. func Uint(name string, value uint, usage string) *uint { return commandLine.Uint(name, value, usage) } // Uint64Var defines a uint64 flag with specified name, default value, and usage string. // The argument p points to a uint64 variable in which to store the value of the flag. func (f *FlagSet) Uint64Var(p *uint64, name string, value uint64, usage string) { f.Var(newUint64Value(value, p), name, usage) } // Uint64Var defines a uint64 flag with specified name, default value, and usage string. // The argument p points to a uint64 variable in which to store the value of the flag. func Uint64Var(p *uint64, name string, value uint64, usage string) { commandLine.Var(newUint64Value(value, p), name, usage) } // Uint64 defines a uint64 flag with specified name, default value, and usage string. // The return value is the address of a uint64 variable that stores the value of the flag. func (f *FlagSet) Uint64(name string, value uint64, usage string) *uint64 { p := new(uint64) f.Uint64Var(p, name, value, usage) return p } // Uint64 defines a uint64 flag with specified name, default value, and usage string. // The return value is the address of a uint64 variable that stores the value of the flag. func Uint64(name string, value uint64, usage string) *uint64 { return commandLine.Uint64(name, value, usage) } // StringVar defines a string flag with specified name, default value, and usage string. // The argument p points to a string variable in which to store the value of the flag. func (f *FlagSet) StringVar(p *string, name string, value string, usage string) { f.Var(newStringValue(value, p), name, usage) } // StringVar defines a string flag with specified name, default value, and usage string. // The argument p points to a string variable in which to store the value of the flag. func StringVar(p *string, name string, value string, usage string) { commandLine.Var(newStringValue(value, p), name, usage) } // String defines a string flag with specified name, default value, and usage string. // The return value is the address of a string variable that stores the value of the flag. func (f *FlagSet) String(name string, value string, usage string) *string { p := new(string) f.StringVar(p, name, value, usage) return p } // String defines a string flag with specified name, default value, and usage string. // The return value is the address of a string variable that stores the value of the flag. func String(name string, value string, usage string) *string { return commandLine.String(name, value, usage) } // Float64Var defines a float64 flag with specified name, default value, and usage string. // The argument p points to a float64 variable in which to store the value of the flag. func (f *FlagSet) Float64Var(p *float64, name string, value float64, usage string) { f.Var(newFloat64Value(value, p), name, usage) } // Float64Var defines a float64 flag with specified name, default value, and usage string. // The argument p points to a float64 variable in which to store the value of the flag. func Float64Var(p *float64, name string, value float64, usage string) { commandLine.Var(newFloat64Value(value, p), name, usage) } // Float64 defines a float64 flag with specified name, default value, and usage string. // The return value is the address of a float64 variable that stores the value of the flag. func (f *FlagSet) Float64(name string, value float64, usage string) *float64 { p := new(float64) f.Float64Var(p, name, value, usage) return p } // Float64 defines a float64 flag with specified name, default value, and usage string. // The return value is the address of a float64 variable that stores the value of the flag. func Float64(name string, value float64, usage string) *float64 { return commandLine.Float64(name, value, usage) } // DurationVar defines a time.Duration flag with specified name, default value, and usage string. // The argument p points to a time.Duration variable in which to store the value of the flag. func (f *FlagSet) DurationVar(p *time.Duration, name string, value time.Duration, usage string) { f.Var(newDurationValue(value, p), name, usage) } // DurationVar defines a time.Duration flag with specified name, default value, and usage string. // The argument p points to a time.Duration variable in which to store the value of the flag. func DurationVar(p *time.Duration, name string, value time.Duration, usage string) { commandLine.Var(newDurationValue(value, p), name, usage) } // Duration defines a time.Duration flag with specified name, default value, and usage string. // The return value is the address of a time.Duration variable that stores the value of the flag. func (f *FlagSet) Duration(name string, value time.Duration, usage string) *time.Duration { p := new(time.Duration) f.DurationVar(p, name, value, usage) return p } // Duration defines a time.Duration flag with specified name, default value, and usage string. // The return value is the address of a time.Duration variable that stores the value of the flag. func Duration(name string, value time.Duration, usage string) *time.Duration { return commandLine.Duration(name, value, usage) } // Var defines a flag with the specified name and usage string. The type and // value of the flag are represented by the first argument, of type Value, which // typically holds a user-defined implementation of Value. For instance, the // caller could create a flag that turns a comma-separated string into a slice // of strings by giving the slice the methods of Value; in particular, Set would // decompose the comma-separated string into the slice. func (f *FlagSet) Var(value Value, name string, usage string) { // Remember the default value as a string; it won't change. flag := &Flag{name, usage, value, value.String()} _, alreadythere := f.formal[name] if alreadythere { fmt.Fprintf(f.out(), "%s flag redefined: %s\n", f.name, name) panic("flag redefinition") // Happens only if flags are declared with identical names } if f.formal == nil { f.formal = make(map[string]*Flag) } f.formal[name] = flag } // Var defines a flag with the specified name and usage string. The type and // value of the flag are represented by the first argument, of type Value, which // typically holds a user-defined implementation of Value. For instance, the // caller could create a flag that turns a comma-separated string into a slice // of strings by giving the slice the methods of Value; in particular, Set would // decompose the comma-separated string into the slice. func Var(value Value, name string, usage string) { commandLine.Var(value, name, usage) } // failf prints to standard error a formatted error and usage message and // returns the error. func (f *FlagSet) failf(format string, a ...interface{}) error { err := fmt.Errorf(format, a...) fmt.Fprintf(f.out(), "error: %v\n", err) return err } // usage calls the Usage method for the flag set, or the usage function if // the flag set is commandLine. func (f *FlagSet) usage() { if f == commandLine { Usage() } else if f.Usage == nil { defaultUsage(f) } else { f.Usage() } } func (f *FlagSet) parseOneGnu() (flagName string, long, finished bool, err error) { if len(f.procArgs) == 0 { finished = true return } // processing previously encountered single-rune flag if flag := f.procFlag; len(flag) > 0 { _, n := utf8.DecodeRuneInString(flag) f.procFlag = flag[n:] flagName = flag[0:n] return } a := f.procArgs[0] // one non-flag argument if a == "-" || a == "" || a[0] != '-' { if f.allowIntersperse { f.args = append(f.args, a) f.procArgs = f.procArgs[1:] return } f.args = append(f.args, f.procArgs...) f.procArgs = nil finished = true return } // end of flags if f.procArgs[0] == "--" { f.args = append(f.args, f.procArgs[1:]...) f.procArgs = nil finished = true return } // long flag signified with "--" prefix if a[1] == '-' { long = true i := strings.Index(a, "=") if i < 0 { f.procArgs = f.procArgs[1:] flagName = a[2:] return } flagName = a[2:i] if flagName == "" { err = fmt.Errorf("empty flag in argument %q", a) return } f.procArgs = f.procArgs[1:] f.procFlag = a[i:] return } // some number of single-rune flags a = a[1:] _, n := utf8.DecodeRuneInString(a) flagName = a[0:n] f.procFlag = a[n:] f.procArgs = f.procArgs[1:] return } func flagWithMinus(name string) string { if len(name) > 1 { return "--" + name } return "-" + name } func (f *FlagSet) parseGnuFlagArg(name string, long bool) (finished bool, err error) { m := f.formal flag, alreadythere := m[name] // BUG if !alreadythere { if name == "help" || name == "h" { // special case for nice help message. f.usage() return false, ErrHelp } // TODO print --xxx when flag is more than one rune. return false, f.failf("flag provided but not defined: %s", flagWithMinus(name)) } if fv, ok := flag.Value.(*boolValue); ok && !strings.HasPrefix(f.procFlag, "=") { // special case: doesn't need an arg, and an arg hasn't // been provided explicitly. fv.Set("true") } else { // It must have a value, which might be the next argument. var hasValue bool var value string if f.procFlag != "" { // value directly follows flag value = f.procFlag if long { if value[0] != '=' { panic("no leading '=' in long flag") } value = value[1:] } hasValue = true f.procFlag = "" } if !hasValue && len(f.procArgs) > 0 { // value is the next arg hasValue = true value, f.procArgs = f.procArgs[0], f.procArgs[1:] } if !hasValue { return false, f.failf("flag needs an argument: %s", flagWithMinus(name)) } if err := flag.Value.Set(value); err != nil { return false, f.failf("invalid value %q for flag %s: %v", value, flagWithMinus(name), err) } } if f.actual == nil { f.actual = make(map[string]*Flag) } f.actual[name] = flag return } // Parse parses flag definitions from the argument list, which should not // include the command name. Must be called after all flags in the FlagSet // are defined and before flags are accessed by the program. // The return value will be ErrHelp if --help was set but not defined. // If allowIntersperse is set, arguments and flags can be interspersed, that // is flags can follow positional arguments. func (f *FlagSet) Parse(allowIntersperse bool, arguments []string) error { f.parsed = true f.procArgs = arguments f.procFlag = "" f.args = nil f.allowIntersperse = allowIntersperse for { name, long, finished, err := f.parseOneGnu() if !finished { if name != "" { finished, err = f.parseGnuFlagArg(name, long) } } if err != nil { switch f.errorHandling { case ContinueOnError: return err case ExitOnError: os.Exit(2) case PanicOnError: panic(err) } } if !finished { continue } if err == nil { break } } return nil } // Parsed reports whether f.Parse has been called. func (f *FlagSet) Parsed() bool { return f.parsed } // Parse parses the command-line flags from os.Args[1:]. Must be called // after all flags are defined and before flags are accessed by the program. // If allowIntersperse is set, arguments and flags can be interspersed, that // is flags can follow positional arguments. func Parse(allowIntersperse bool) { // Ignore errors; commandLine is set for ExitOnError. commandLine.Parse(allowIntersperse, os.Args[1:]) } // Parsed returns true if the command-line flags have been parsed. func Parsed() bool { return commandLine.Parsed() } // The default set of command-line flags, parsed from os.Args. var commandLine = NewFlagSet(os.Args[0], ExitOnError) // SetOut sets the output writer for the default FlagSet. func SetOut(w io.Writer) { commandLine.output = w } // NewFlagSet returns a new, empty flag set with the specified name and // error handling property. func NewFlagSet(name string, errorHandling ErrorHandling) *FlagSet { f := &FlagSet{ name: name, errorHandling: errorHandling, } return f } // Init sets the name and error handling property for a flag set. // By default, the zero FlagSet uses an empty name and the // ContinueOnError error handling policy. func (f *FlagSet) Init(name string, errorHandling ErrorHandling) { f.name = name f.errorHandling = errorHandling } lxd-2.0.0/shared/gnuflag/flag_test.go000066400000000000000000000272141270277227600175120ustar00rootroot00000000000000// Copyright 2009 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package gnuflag_test import ( "bytes" "fmt" "os" "reflect" "sort" "strings" "testing" "time" . "github.com/lxc/lxd/shared/gnuflag" ) var ( test_bool = Bool("test_bool", false, "bool value") test_int = Int("test_int", 0, "int value") test_int64 = Int64("test_int64", 0, "int64 value") test_uint = Uint("test_uint", 0, "uint value") test_uint64 = Uint64("test_uint64", 0, "uint64 value") test_string = String("test_string", "0", "string value") test_float64 = Float64("test_float64", 0, "float64 value") test_duration = Duration("test_duration", 0, "time.Duration value") ) func boolString(s string) string { if s == "0" { return "false" } return "true" } func TestEverything(t *testing.T) { m := make(map[string]*Flag) desired := "0" visitor := func(f *Flag) { if len(f.Name) > 5 && f.Name[0:5] == "test_" { m[f.Name] = f ok := false switch { case f.Value.String() == desired: ok = true case f.Name == "test_bool" && f.Value.String() == boolString(desired): ok = true case f.Name == "test_duration" && f.Value.String() == desired+"s": ok = true } if !ok { t.Error("Visit: bad value", f.Value.String(), "for", f.Name) } } } VisitAll(visitor) if len(m) != 8 { t.Error("VisitAll misses some flags") for k, v := range m { t.Log(k, *v) } } m = make(map[string]*Flag) Visit(visitor) if len(m) != 0 { t.Errorf("Visit sees unset flags") for k, v := range m { t.Log(k, *v) } } // Now set all flags Set("test_bool", "true") Set("test_int", "1") Set("test_int64", "1") Set("test_uint", "1") Set("test_uint64", "1") Set("test_string", "1") Set("test_float64", "1") Set("test_duration", "1s") desired = "1" Visit(visitor) if len(m) != 8 { t.Error("Visit fails after set") for k, v := range m { t.Log(k, *v) } } // Now test they're visited in sort order. var flagNames []string Visit(func(f *Flag) { flagNames = append(flagNames, f.Name) }) if !sort.StringsAreSorted(flagNames) { t.Errorf("flag names not sorted: %v", flagNames) } } func TestUsage(t *testing.T) { called := false ResetForTesting(func() { called = true }) f := CommandLine() f.SetOutput(nullWriter{}) if f.Parse(true, []string{"-x"}) == nil { t.Error("parse did not fail for unknown flag") } if called { t.Error("called Usage for unknown flag") } } var parseTests = []struct { about string intersperse bool args []string vals map[string]interface{} remaining []string error string }{{ about: "regular args", intersperse: true, args: []string{ "--bool2", "--int", "22", "--int64", "0x23", "--uint", "24", "--uint64", "25", "--string", "hello", "--float64", "2718e28", "--duration", "2m", "one - extra - argument", }, vals: map[string]interface{}{ "bool": false, "bool2": true, "int": 22, "int64": int64(0x23), "uint": uint(24), "uint64": uint64(25), "string": "hello", "float64": 2718e28, "duration": 2 * 60 * time.Second, }, remaining: []string{ "one - extra - argument", }, }, { about: "playing with -", intersperse: true, args: []string{ "-a", "-", "-bc", "2", "-de1s", "-f2s", "-g", "3s", "--h", "--long", "--long2", "-4s", "3", "4", "--", "-5", }, vals: map[string]interface{}{ "a": true, "b": true, "c": true, "d": true, "e": "1s", "f": "2s", "g": "3s", "h": true, "long": true, "long2": "-4s", "z": "default", "www": 99, }, remaining: []string{ "-", "2", "3", "4", "-5", }, }, { about: "flag after explicit --", intersperse: true, args: []string{ "-a", "--", "-b", }, vals: map[string]interface{}{ "a": true, "b": false, }, remaining: []string{ "-b", }, }, { about: "flag after end", args: []string{ "-a", "foo", "-b", }, vals: map[string]interface{}{ "a": true, "b": false, }, remaining: []string{ "foo", "-b", }, }, { about: "arg and flag after explicit end", args: []string{ "-a", "--", "foo", "-b", }, vals: map[string]interface{}{ "a": true, "b": false, }, remaining: []string{ "foo", "-b", }, }, { about: "boolean args, explicitly and non-explicitly given", args: []string{ "--a=false", "--b=true", "--c", }, vals: map[string]interface{}{ "a": false, "b": true, "c": true, }, }, { about: "using =", args: []string{ "--arble=bar", "--bletch=", "--a=something", "-b=other", "-cdand more", "--curdle=--milk", "--sandwich", "=", "--darn=", "=arg", }, vals: map[string]interface{}{ "arble": "bar", "bletch": "", "a": "something", "b": "=other", "c": true, "d": "and more", "curdle": "--milk", "sandwich": "=", "darn": "", }, remaining: []string{"=arg"}, }, { about: "empty flag #1", args: []string{ "--=bar", }, error: `empty flag in argument "--=bar"`, }, { about: "single-letter equals", args: []string{ "-=bar", }, error: `flag provided but not defined: -=`, }, { about: "empty flag #2", args: []string{ "--=", }, error: `empty flag in argument "--="`, }, { about: "no equals", args: []string{ "-=", }, error: `flag provided but not defined: -=`, }, { args: []string{ "-a=true", }, vals: map[string]interface{}{ "a": true, }, error: `invalid value "=true" for flag -a: strconv.ParseBool: parsing "=true": invalid syntax`, }, { intersperse: true, args: []string{ "-a", "-b", }, vals: map[string]interface{}{ "a": true, }, error: "flag provided but not defined: -b", }, { intersperse: true, args: []string{ "-a", }, vals: map[string]interface{}{ "a": "default", }, error: "flag needs an argument: -a", }, { intersperse: true, args: []string{ "-a", "b", }, vals: map[string]interface{}{ "a": 0, }, error: `invalid value "b" for flag -a: strconv.ParseInt: parsing "b": invalid syntax`, }, } func testParse(newFlagSet func() *FlagSet, t *testing.T) { for i, g := range parseTests { t.Logf("test %d. %s", i, g.about) f := newFlagSet() flags := make(map[string]interface{}) for name, val := range g.vals { switch val.(type) { case bool: flags[name] = f.Bool(name, false, "bool value "+name) case string: flags[name] = f.String(name, "default", "string value "+name) case int: flags[name] = f.Int(name, 99, "int value "+name) case uint: flags[name] = f.Uint(name, 0, "uint value") case uint64: flags[name] = f.Uint64(name, 0, "uint64 value") case int64: flags[name] = f.Int64(name, 0, "uint64 value") case float64: flags[name] = f.Float64(name, 0, "float64 value") case time.Duration: flags[name] = f.Duration(name, 5*time.Second, "duration value") default: t.Fatalf("unhandled type %T", val) } } err := f.Parse(g.intersperse, g.args) if g.error != "" { if err == nil { t.Errorf("expected error %q got nil", g.error) } else if err.Error() != g.error { t.Errorf("expected error %q got %q", g.error, err.Error()) } continue } for name, val := range g.vals { actual := reflect.ValueOf(flags[name]).Elem().Interface() if val != actual { t.Errorf("flag %q, expected %v got %v", name, val, actual) } } if len(f.Args()) != len(g.remaining) { t.Fatalf("remaining args, expected %q got %q", g.remaining, f.Args()) } for j, a := range f.Args() { if a != g.remaining[j] { t.Errorf("arg %d, expected %q got %q", j, g.remaining[i], a) } } } } func TestParse(t *testing.T) { testParse(func() *FlagSet { ResetForTesting(func() {}) f := CommandLine() f.SetOutput(nullWriter{}) return f }, t) } func TestFlagSetParse(t *testing.T) { testParse(func() *FlagSet { f := NewFlagSet("test", ContinueOnError) f.SetOutput(nullWriter{}) return f }, t) } // Declare a user-defined flag type. type flagVar []string func (f *flagVar) String() string { return fmt.Sprint([]string(*f)) } func (f *flagVar) Set(value string) error { *f = append(*f, value) return nil } func TestUserDefined(t *testing.T) { var flags FlagSet flags.Init("test", ContinueOnError) var v flagVar flags.Var(&v, "v", "usage") if err := flags.Parse(true, []string{"-v", "1", "-v", "2", "-v3"}); err != nil { t.Error(err) } if len(v) != 3 { t.Fatal("expected 3 args; got ", len(v)) } expect := "[1 2 3]" if v.String() != expect { t.Errorf("expected value %q got %q", expect, v.String()) } } func TestSetOutput(t *testing.T) { var flags FlagSet var buf bytes.Buffer flags.SetOutput(&buf) flags.Init("test", ContinueOnError) flags.Parse(true, []string{"-unknown"}) if out := buf.String(); !strings.Contains(out, "-unknown") { t.Logf("expected output mentioning unknown; got %q", out) } } // This tests that one can reset the flags. This still works but not well, and is // superseded by FlagSet. func TestChangingArgs(t *testing.T) { ResetForTesting(func() { t.Fatal("bad parse") }) oldArgs := os.Args defer func() { os.Args = oldArgs }() os.Args = []string{"cmd", "--before", "subcmd", "--after", "args"} before := Bool("before", false, "") if err := CommandLine().Parse(false, os.Args[1:]); err != nil { t.Fatal(err) } cmd := Arg(0) os.Args = Args() after := Bool("after", false, "") Parse(false) args := Args() if !*before || cmd != "subcmd" || !*after || len(args) != 1 || args[0] != "args" { t.Fatalf("expected true subcmd true [args] got %v %v %v %v", *before, cmd, *after, args) } } // Test that -help invokes the usage message and returns ErrHelp. func TestHelp(t *testing.T) { var helpCalled = false fs := NewFlagSet("help test", ContinueOnError) fs.SetOutput(nullWriter{}) fs.Usage = func() { helpCalled = true } var flag bool fs.BoolVar(&flag, "flag", false, "regular flag") // Regular flag invocation should work err := fs.Parse(true, []string{"--flag"}) if err != nil { t.Fatal("expected no error; got ", err) } if !flag { t.Error("flag was not set by --flag") } if helpCalled { t.Error("help called for regular flag") helpCalled = false // reset for next test } // Help flag should work as expected. err = fs.Parse(true, []string{"--help"}) if err == nil { t.Fatal("error expected") } if err != ErrHelp { t.Fatal("expected ErrHelp; got ", err) } if !helpCalled { t.Fatal("help was not called") } // If we define a help flag, that should override. var help bool fs.BoolVar(&help, "help", false, "help flag") helpCalled = false err = fs.Parse(true, []string{"--help"}) if err != nil { t.Fatal("expected no error for defined --help; got ", err) } if helpCalled { t.Fatal("help was called; should not have been for defined help flag") } } type nullWriter struct{} func (nullWriter) Write(buf []byte) (int, error) { return len(buf), nil } func TestPrintDefaults(t *testing.T) { f := NewFlagSet("print test", ContinueOnError) f.SetOutput(nullWriter{}) var b bool var c int var d string var e float64 f.IntVar(&c, "trapclap", 99, "usage not shown") f.IntVar(&c, "c", 99, "c usage") f.BoolVar(&b, "bal", false, "usage not shown") f.BoolVar(&b, "x", false, "usage not shown") f.BoolVar(&b, "b", false, "b usage") f.BoolVar(&b, "balalaika", false, "usage not shown") f.StringVar(&d, "d", "d default", "d usage") f.Float64Var(&e, "elephant", 3.14, "elephant usage") var buf bytes.Buffer f.SetOutput(&buf) f.PrintDefaults() f.SetOutput(nullWriter{}) expect := ` -b, -x, --bal, --balalaika (= false) b usage -c, --trapclap (= 99) c usage -d (= "d default") d usage --elephant (= 3.14) elephant usage ` if buf.String() != expect { t.Errorf("expect %q got %q", expect, buf.String()) } } lxd-2.0.0/shared/i18n/000077500000000000000000000000001270277227600143415ustar00rootroot00000000000000lxd-2.0.0/shared/i18n/i18n.go000066400000000000000000000002341270277227600154460ustar00rootroot00000000000000// +build !linux package i18n func G(msgid string) string { return msgid } func NG(msgid string, msgidPlural string, n uint64) string { return msgid } lxd-2.0.0/shared/i18n/i18n_linux.go000066400000000000000000000005411270277227600166660ustar00rootroot00000000000000// +build linux package i18n import ( "github.com/gosexy/gettext" ) var TEXTDOMAIN = "lxd" func G(msgid string) string { return gettext.DGettext(TEXTDOMAIN, msgid) } func NG(msgid string, msgidPlural string, n uint64) string { return gettext.DNGettext(TEXTDOMAIN, msgid, msgidPlural, n) } func init() { gettext.SetLocale(gettext.LC_ALL, "") } lxd-2.0.0/shared/idmapset_linux.go000066400000000000000000000202531270277227600171400ustar00rootroot00000000000000package shared import ( "bufio" "fmt" "os" "os/exec" "os/user" "path" "path/filepath" "strconv" "strings" ) /* * One entry in id mapping set - a single range of either * uid or gid mappings. */ type IdmapEntry struct { Isuid bool Isgid bool Hostid int // id as seen on the host - i.e. 100000 Nsid int // id as seen in the ns - i.e. 0 Maprange int } func (e *IdmapEntry) ToLxcString() string { if e.Isuid { return fmt.Sprintf("u %d %d %d", e.Nsid, e.Hostid, e.Maprange) } return fmt.Sprintf("g %d %d %d", e.Nsid, e.Hostid, e.Maprange) } func is_between(x, low, high int) bool { return x >= low && x < high } func (e *IdmapEntry) Intersects(i IdmapEntry) bool { if (e.Isuid && i.Isuid) || (e.Isgid && i.Isgid) { switch { case is_between(e.Hostid, i.Hostid, i.Hostid+i.Maprange): return true case is_between(i.Hostid, e.Hostid, e.Hostid+e.Maprange): return true case is_between(e.Hostid+e.Maprange, i.Hostid, i.Hostid+i.Maprange): return true case is_between(i.Hostid+e.Maprange, e.Hostid, e.Hostid+e.Maprange): return true case is_between(e.Nsid, i.Nsid, i.Nsid+i.Maprange): return true case is_between(i.Nsid, e.Nsid, e.Nsid+e.Maprange): return true case is_between(e.Nsid+e.Maprange, i.Nsid, i.Nsid+i.Maprange): return true case is_between(i.Nsid+e.Maprange, e.Nsid, e.Nsid+e.Maprange): return true } } return false } func (e *IdmapEntry) parse(s string) error { split := strings.Split(s, ":") var err error if len(split) != 4 { return fmt.Errorf("Bad idmap: %q", s) } switch split[0] { case "u": e.Isuid = true case "g": e.Isgid = true case "b": e.Isuid = true e.Isgid = true default: return fmt.Errorf("Bad idmap type in %q", s) } e.Nsid, err = strconv.Atoi(split[1]) if err != nil { return err } e.Hostid, err = strconv.Atoi(split[2]) if err != nil { return err } e.Maprange, err = strconv.Atoi(split[3]) if err != nil { return err } // wraparound if e.Hostid+e.Maprange < e.Hostid || e.Nsid+e.Maprange < e.Nsid { return fmt.Errorf("Bad mapping: id wraparound") } return nil } /* * Shift a uid from the host into the container * I.e. 0 -> 1000 -> 101000 */ func (e *IdmapEntry) shift_into_ns(id int) (int, error) { if id < e.Nsid || id >= e.Nsid+e.Maprange { // this mapping doesn't apply return 0, fmt.Errorf("N/A") } return id - e.Nsid + e.Hostid, nil } /* * Shift a uid from the container back to the host * I.e. 101000 -> 1000 */ func (e *IdmapEntry) shift_from_ns(id int) (int, error) { if id < e.Hostid || id >= e.Hostid+e.Maprange { // this mapping doesn't apply return 0, fmt.Errorf("N/A") } return id - e.Hostid + e.Nsid, nil } /* taken from http://blog.golang.org/slices (which is under BSD licence) */ func Extend(slice []IdmapEntry, element IdmapEntry) []IdmapEntry { n := len(slice) if n == cap(slice) { // Slice is full; must grow. // We double its size and add 1, so if the size is zero we still grow. newSlice := make([]IdmapEntry, len(slice), 2*len(slice)+1) copy(newSlice, slice) slice = newSlice } slice = slice[0 : n+1] slice[n] = element return slice } type IdmapSet struct { Idmap []IdmapEntry } func (m IdmapSet) Len() int { return len(m.Idmap) } func (m IdmapSet) Intersects(i IdmapEntry) bool { for _, e := range m.Idmap { if i.Intersects(e) { return true } } return false } func (m IdmapSet) ToLxcString() []string { var lines []string for _, e := range m.Idmap { lines = append(lines, e.ToLxcString()+"\n") } return lines } func (m IdmapSet) Append(s string) (IdmapSet, error) { e := IdmapEntry{} err := e.parse(s) if err != nil { return m, err } if m.Intersects(e) { return m, fmt.Errorf("Conflicting id mapping") } m.Idmap = Extend(m.Idmap, e) return m, nil } func (m IdmapSet) doShiftIntoNs(uid int, gid int, how string) (int, int) { u := -1 g := -1 for _, e := range m.Idmap { var err error var tmpu, tmpg int if e.Isuid && u == -1 { switch how { case "in": tmpu, err = e.shift_into_ns(uid) case "out": tmpu, err = e.shift_from_ns(uid) } if err == nil { u = tmpu } } if e.Isgid && g == -1 { switch how { case "in": tmpg, err = e.shift_into_ns(gid) case "out": tmpg, err = e.shift_from_ns(gid) } if err == nil { g = tmpg } } } return u, g } func (m IdmapSet) ShiftIntoNs(uid int, gid int) (int, int) { return m.doShiftIntoNs(uid, gid, "in") } func (m IdmapSet) ShiftFromNs(uid int, gid int) (int, int) { return m.doShiftIntoNs(uid, gid, "out") } func GetOwner(path string) (int, int, error) { uid, gid, _, _, _, _, err := GetFileStat(path) return uid, gid, err } func (set *IdmapSet) doUidshiftIntoContainer(dir string, testmode bool, how string) error { // Expand any symlink in dir and cleanup resulting path dir, err := filepath.EvalSymlinks(dir) if err != nil { return err } dir = strings.TrimRight(dir, "/") convert := func(path string, fi os.FileInfo, err error) (e error) { uid, gid, err := GetOwner(path) if err != nil { return err } var newuid, newgid int switch how { case "in": newuid, newgid = set.ShiftIntoNs(uid, gid) case "out": newuid, newgid = set.ShiftFromNs(uid, gid) } if testmode { fmt.Printf("I would shift %q to %d %d\n", path, newuid, newgid) } else { err = ShiftOwner(dir, path, int(newuid), int(newgid)) if err != nil { return err } } return nil } if !PathExists(dir) { return fmt.Errorf("No such file or directory: %q", dir) } return filepath.Walk(dir, convert) } func (set *IdmapSet) UidshiftIntoContainer(dir string, testmode bool) error { return set.doUidshiftIntoContainer(dir, testmode, "in") } func (set *IdmapSet) UidshiftFromContainer(dir string, testmode bool) error { return set.doUidshiftIntoContainer(dir, testmode, "out") } func (set *IdmapSet) ShiftRootfs(p string) error { return set.doUidshiftIntoContainer(p, false, "in") } func (set *IdmapSet) UnshiftRootfs(p string) error { return set.doUidshiftIntoContainer(p, false, "out") } func (set *IdmapSet) ShiftFile(p string) error { return set.ShiftRootfs(p) } const ( minIDRange = 65536 ) /* * get a uid or gid mapping from /etc/subxid */ func getFromMap(fname string, username string) (int, int, error) { f, err := os.Open(fname) var min int var idrange int if err != nil { return 0, 0, err } defer f.Close() scanner := bufio.NewScanner(f) min = 0 idrange = 0 for scanner.Scan() { /* * /etc/sub{gu}id allow comments in the files, so ignore * everything after a '#' */ s := strings.Split(scanner.Text(), "#") if len(s[0]) == 0 { continue } s = strings.Split(s[0], ":") if len(s) < 3 { return 0, 0, fmt.Errorf("unexpected values in %q: %q", fname, s) } if strings.EqualFold(s[0], username) { bigmin, err := strconv.ParseUint(s[1], 10, 32) if err != nil { continue } bigIdrange, err := strconv.ParseUint(s[2], 10, 32) if err != nil { continue } min = int(bigmin) idrange = int(bigIdrange) if idrange < minIDRange { continue } return min, idrange, nil } } return 0, 0, fmt.Errorf("User %q has no %ss.", username, path.Base(fname)) } /* * Get current username */ func getUsername() (string, error) { me, err := user.Current() if err == nil { return me.Username, nil } else { /* user.Current() requires cgo */ username := os.Getenv("USER") if username == "" { return "", err } return username, nil } } /* * Create a new default idmap */ func DefaultIdmapSet() (*IdmapSet, error) { myname, err := getUsername() if err != nil { return nil, err } umin := 1000000 urange := 100000 gmin := 1000000 grange := 100000 newuidmap, _ := exec.LookPath("newuidmap") newgidmap, _ := exec.LookPath("newgidmap") if newuidmap != "" && newgidmap != "" && PathExists("/etc/subuid") && PathExists("/etc/subgid") { umin, urange, err = getFromMap("/etc/subuid", myname) if err != nil { return nil, err } gmin, grange, err = getFromMap("/etc/subgid", myname) if err != nil { return nil, err } } m := new(IdmapSet) e := IdmapEntry{Isuid: true, Nsid: 0, Hostid: umin, Maprange: urange} m.Idmap = Extend(m.Idmap, e) e = IdmapEntry{Isgid: true, Nsid: 0, Hostid: gmin, Maprange: grange} m.Idmap = Extend(m.Idmap, e) return m, nil } lxd-2.0.0/shared/image.go000066400000000000000000000032661270277227600152020ustar00rootroot00000000000000package shared import ( "time" ) type ImageProperties map[string]string type ImageAliasesEntry struct { Name string `json:"name"` Description string `json:"description"` Target string `json:"target"` } type ImageAliases []ImageAliasesEntry type ImageAlias struct { Name string `json:"name"` Description string `json:"description"` } type ImageSource struct { Server string `json:"server"` Protocol string `json:"protocol"` Certificate string `json:"certificate"` Alias string `json:"alias"` } type ImageInfo struct { Aliases []ImageAlias `json:"aliases"` Architecture string `json:"architecture"` Cached bool `json:"cached"` Filename string `json:"filename"` Fingerprint string `json:"fingerprint"` Properties map[string]string `json:"properties"` Public bool `json:"public"` Size int64 `json:"size"` AutoUpdate bool `json:"auto_update"` Source *ImageSource `json:"update_source,omitempty"` CreationDate time.Time `json:"created_at"` ExpiryDate time.Time `json:"expires_at"` LastUsedDate time.Time `json:"last_used_at"` UploadDate time.Time `json:"uploaded_at"` } /* * BriefImageInfo contains a subset of the fields in * ImageInfo, namely those which a user may update */ type BriefImageInfo struct { AutoUpdate bool `json:"auto_update"` Properties map[string]string `json:"properties"` Public bool `json:"public"` } func (i *ImageInfo) Brief() BriefImageInfo { retstate := BriefImageInfo{ AutoUpdate: i.AutoUpdate, Properties: i.Properties, Public: i.Public} return retstate } lxd-2.0.0/shared/json.go000066400000000000000000000027211270277227600150640ustar00rootroot00000000000000package shared import ( "bytes" "encoding/json" "fmt" ) type Jmap map[string]interface{} func (m Jmap) GetString(key string) (string, error) { if val, ok := m[key]; !ok { return "", fmt.Errorf("Response was missing `%s`", key) } else if val, ok := val.(string); !ok { return "", fmt.Errorf("`%s` was not a string", key) } else { return val, nil } } func (m Jmap) GetMap(key string) (Jmap, error) { if val, ok := m[key]; !ok { return nil, fmt.Errorf("Response was missing `%s`", key) } else if val, ok := val.(map[string]interface{}); !ok { return nil, fmt.Errorf("`%s` was not a map, got %T", key, m[key]) } else { return val, nil } } func (m Jmap) GetInt(key string) (int, error) { if val, ok := m[key]; !ok { return -1, fmt.Errorf("Response was missing `%s`", key) } else if val, ok := val.(float64); !ok { return -1, fmt.Errorf("`%s` was not an int", key) } else { return int(val), nil } } func (m Jmap) GetBool(key string) (bool, error) { if val, ok := m[key]; !ok { return false, fmt.Errorf("Response was missing `%s`", key) } else if val, ok := val.(bool); !ok { return false, fmt.Errorf("`%s` was not an int", key) } else { return val, nil } } func DebugJson(r *bytes.Buffer) { pretty := &bytes.Buffer{} if err := json.Indent(pretty, r.Bytes(), "\t", "\t"); err != nil { Debugf("error indenting json: %s", err) return } // Print the JSON without the last "\n" str := pretty.String() Debugf("\n\t%s", str[0:len(str)-1]) } lxd-2.0.0/shared/log.go000066400000000000000000000023741270277227600147000ustar00rootroot00000000000000package shared import ( "fmt" "runtime" ) type Logger interface { Debug(msg string, ctx ...interface{}) Info(msg string, ctx ...interface{}) Warn(msg string, ctx ...interface{}) Error(msg string, ctx ...interface{}) Crit(msg string, ctx ...interface{}) } var Log Logger type nullLogger struct{} func (nl nullLogger) Debug(msg string, ctx ...interface{}) {} func (nl nullLogger) Info(msg string, ctx ...interface{}) {} func (nl nullLogger) Warn(msg string, ctx ...interface{}) {} func (nl nullLogger) Error(msg string, ctx ...interface{}) {} func (nl nullLogger) Crit(msg string, ctx ...interface{}) {} func init() { Log = nullLogger{} } // Logf sends to the logger registered via SetLogger the string resulting // from running format and args through Sprintf. func Logf(format string, args ...interface{}) { if Log != nil { Log.Info(fmt.Sprintf(format, args...)) } } // Debugf sends to the logger registered via SetLogger the string resulting // from running format and args through Sprintf, but only if debugging was // enabled via SetDebug. func Debugf(format string, args ...interface{}) { if Log != nil { Log.Debug(fmt.Sprintf(format, args...)) } } func PrintStack() { buf := make([]byte, 1<<16) runtime.Stack(buf, true) Debugf("%s", buf) } lxd-2.0.0/shared/logging/000077500000000000000000000000001270277227600152105ustar00rootroot00000000000000lxd-2.0.0/shared/logging/log.go000066400000000000000000000035261270277227600163260ustar00rootroot00000000000000package logging import ( "fmt" "os" "path/filepath" "github.com/lxc/lxd/shared" log "gopkg.in/inconshreveable/log15.v2" ) // GetLogger returns a logger suitable for using as shared.Log. func GetLogger(syslog string, logfile string, verbose bool, debug bool, customHandler log.Handler) (shared.Logger, error) { Log := log.New() var handlers []log.Handler var syshandler log.Handler // System specific handler syshandler = getSystemHandler(syslog, debug) if syshandler != nil { handlers = append(handlers, syshandler) } // FileHandler if logfile != "" { if !pathExists(filepath.Dir(logfile)) { return nil, fmt.Errorf("Log file path doesn't exist: %s", filepath.Dir(logfile)) } if !debug { handlers = append( handlers, log.LvlFilterHandler( log.LvlInfo, log.Must.FileHandler(logfile, log.LogfmtFormat()), ), ) } else { handlers = append(handlers, log.Must.FileHandler(logfile, log.LogfmtFormat())) } } // StderrHandler if verbose || debug { if !debug { handlers = append( handlers, log.LvlFilterHandler( log.LvlInfo, log.StderrHandler, ), ) } else { handlers = append(handlers, log.StderrHandler) } } else { handlers = append( handlers, log.LvlFilterHandler( log.LvlWarn, log.StderrHandler, ), ) } if customHandler != nil { handlers = append(handlers, customHandler) } Log.SetHandler(log.MultiHandler(handlers...)) return Log, nil } func AddContext(logger shared.Logger, ctx log.Ctx) shared.Logger { log15logger, ok := logger.(log.Logger) if !ok { logger.Error("couldn't downcast logger to add context", log.Ctx{"logger": log15logger, "ctx": ctx}) return logger } return log15logger.New(ctx) } func pathExists(name string) bool { _, err := os.Lstat(name) if err != nil && os.IsNotExist(err) { return false } return true } lxd-2.0.0/shared/logging/log_posix.go000066400000000000000000000007241270277227600175450ustar00rootroot00000000000000// +build linux darwin package logging import ( log "gopkg.in/inconshreveable/log15.v2" ) // getSystemHandler on Linux writes messages to syslog. func getSystemHandler(syslog string, debug bool) log.Handler { // SyslogHandler if syslog != "" { if !debug { return log.LvlFilterHandler( log.LvlInfo, log.Must.SyslogHandler(syslog, log.LogfmtFormat()), ) } else { return log.Must.SyslogHandler(syslog, log.LogfmtFormat()) } } return nil } lxd-2.0.0/shared/logging/log_windows.go000066400000000000000000000003231270277227600200700ustar00rootroot00000000000000// +build windows package logging import ( log "gopkg.in/inconshreveable/log15.v2" ) // getSystemHandler on Windows does nothing. func getSystemHandler(syslog string, debug bool) log.Handler { return nil } lxd-2.0.0/shared/network.go000066400000000000000000000137621270277227600156130ustar00rootroot00000000000000package shared import ( "crypto/tls" "crypto/x509" "encoding/pem" "fmt" "io" "io/ioutil" "net" "time" "github.com/gorilla/websocket" ) func RFC3493Dialer(network, address string) (net.Conn, error) { host, port, err := net.SplitHostPort(address) if err != nil { return nil, err } addrs, err := net.LookupHost(host) if err != nil { return nil, err } for _, a := range addrs { c, err := net.DialTimeout(network, net.JoinHostPort(a, port), 10*time.Second) if err != nil { continue } return c, err } return nil, fmt.Errorf("Unable to connect to: " + address) } func initTLSConfig() *tls.Config { return &tls.Config{ MinVersion: tls.VersionTLS12, MaxVersion: tls.VersionTLS12, CipherSuites: []uint16{ tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256}, PreferServerCipherSuites: true, } } func finalizeTLSConfig(tlsConfig *tls.Config, tlsRemoteCert *x509.Certificate) { // Trusted certificates if tlsRemoteCert != nil { caCertPool := x509.NewCertPool() // Make it a valid RootCA tlsRemoteCert.IsCA = true tlsRemoteCert.KeyUsage = x509.KeyUsageCertSign // Setup the pool caCertPool.AddCert(tlsRemoteCert) tlsConfig.RootCAs = caCertPool // Set the ServerName if tlsRemoteCert.DNSNames != nil { tlsConfig.ServerName = tlsRemoteCert.DNSNames[0] } } tlsConfig.BuildNameToCertificate() } func GetTLSConfig(tlsClientCertFile string, tlsClientKeyFile string, tlsRemoteCert *x509.Certificate) (*tls.Config, error) { tlsConfig := initTLSConfig() // Client authentication if tlsClientCertFile != "" && tlsClientKeyFile != "" { cert, err := tls.LoadX509KeyPair(tlsClientCertFile, tlsClientKeyFile) if err != nil { return nil, err } tlsConfig.Certificates = []tls.Certificate{cert} } finalizeTLSConfig(tlsConfig, tlsRemoteCert) return tlsConfig, nil } func GetTLSConfigMem(tlsClientCert string, tlsClientKey string, tlsRemoteCertPEM string) (*tls.Config, error) { tlsConfig := initTLSConfig() // Client authentication if tlsClientCert != "" && tlsClientKey != "" { cert, err := tls.X509KeyPair([]byte(tlsClientCert), []byte(tlsClientKey)) if err != nil { return nil, err } tlsConfig.Certificates = []tls.Certificate{cert} } var tlsRemoteCert *x509.Certificate if tlsRemoteCertPEM != "" { // Ignore any content outside of the PEM bytes we care about certBlock, _ := pem.Decode([]byte(tlsRemoteCertPEM)) var err error tlsRemoteCert, err = x509.ParseCertificate(certBlock.Bytes) if err != nil { return nil, err } } finalizeTLSConfig(tlsConfig, tlsRemoteCert) return tlsConfig, nil } func IsLoopback(iface *net.Interface) bool { return int(iface.Flags&net.FlagLoopback) > 0 } func WebsocketSendStream(conn *websocket.Conn, r io.Reader) chan bool { ch := make(chan bool) if r == nil { close(ch) return ch } go func(conn *websocket.Conn, r io.Reader) { in := ReaderToChannel(r) for { buf, ok := <-in if !ok { break } w, err := conn.NextWriter(websocket.BinaryMessage) if err != nil { Debugf("Got error getting next writer %s", err) break } _, err = w.Write(buf) w.Close() if err != nil { Debugf("Got err writing %s", err) break } } conn.WriteMessage(websocket.TextMessage, []byte{}) ch <- true }(conn, r) return ch } func WebsocketRecvStream(w io.WriteCloser, conn *websocket.Conn) chan bool { ch := make(chan bool) go func(w io.WriteCloser, conn *websocket.Conn) { for { mt, r, err := conn.NextReader() if mt == websocket.CloseMessage { Debugf("Got close message for reader") break } if mt == websocket.TextMessage { Debugf("got message barrier") break } if err != nil { Debugf("Got error getting next reader %s, %s", err, w) break } buf, err := ioutil.ReadAll(r) if err != nil { Debugf("Got error writing to writer %s", err) break } if w == nil { continue } i, err := w.Write(buf) if i != len(buf) { Debugf("Didn't write all of buf") break } if err != nil { Debugf("Error writing buf %s", err) break } } ch <- true }(w, conn) return ch } // WebsocketMirror allows mirroring a reader to a websocket and taking the // result and writing it to a writer. This function allows for multiple // mirrorings and correctly negotiates stream endings. However, it means any // websocket.Conns passed to it are live when it returns, and must be closed // explicitly. func WebsocketMirror(conn *websocket.Conn, w io.WriteCloser, r io.ReadCloser) (chan bool, chan bool) { readDone := make(chan bool, 1) writeDone := make(chan bool, 1) go func(conn *websocket.Conn, w io.WriteCloser) { for { mt, r, err := conn.NextReader() if err != nil { Debugf("Got error getting next reader %s, %s", err, w) break } if mt == websocket.CloseMessage { Debugf("Got close message for reader") break } if mt == websocket.TextMessage { Debugf("Got message barrier, resetting stream") break } buf, err := ioutil.ReadAll(r) if err != nil { Debugf("Got error writing to writer %s", err) break } i, err := w.Write(buf) if i != len(buf) { Debugf("Didn't write all of buf") break } if err != nil { Debugf("Error writing buf %s", err) break } } writeDone <- true w.Close() }(conn, w) go func(conn *websocket.Conn, r io.ReadCloser) { in := ReaderToChannel(r) for { buf, ok := <-in if !ok { readDone <- true r.Close() Debugf("sending write barrier") conn.WriteMessage(websocket.TextMessage, []byte{}) return } w, err := conn.NextWriter(websocket.BinaryMessage) if err != nil { Debugf("Got error getting next writer %s", err) break } _, err = w.Write(buf) w.Close() if err != nil { Debugf("Got err writing %s", err) break } } closeMsg := websocket.FormatCloseMessage(websocket.CloseNormalClosure, "") conn.WriteMessage(websocket.CloseMessage, closeMsg) readDone <- true r.Close() }(conn, r) return readDone, writeDone } lxd-2.0.0/shared/operation.go000066400000000000000000000013661270277227600161170ustar00rootroot00000000000000package shared import ( "net/http" "time" "github.com/gorilla/websocket" ) var WebsocketUpgrader = websocket.Upgrader{ ReadBufferSize: 1024, WriteBufferSize: 1024, CheckOrigin: func(r *http.Request) bool { return true }, } type Operation struct { Id string `json:"id"` Class string `json:"class"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` Status string `json:"status"` StatusCode StatusCode `json:"status_code"` Resources map[string][]string `json:"resources"` Metadata *Jmap `json:"metadata"` MayCancel bool `json:"may_cancel"` Err string `json:"err"` } lxd-2.0.0/shared/proxy.go000066400000000000000000000064471270277227600153050ustar00rootroot00000000000000package shared import ( "fmt" "net" "net/http" "net/url" "os" "strings" "sync" ) var ( httpProxyEnv = &envOnce{ names: []string{"HTTP_PROXY", "http_proxy"}, } httpsProxyEnv = &envOnce{ names: []string{"HTTPS_PROXY", "https_proxy"}, } noProxyEnv = &envOnce{ names: []string{"NO_PROXY", "no_proxy"}, } ) type envOnce struct { names []string once sync.Once val string } func (e *envOnce) Get() string { e.once.Do(e.init) return e.val } func (e *envOnce) init() { for _, n := range e.names { e.val = os.Getenv(n) if e.val != "" { return } } } // This is basically the same as golang's ProxyFromEnvironment, except it // doesn't fall back to http_proxy when https_proxy isn't around, which is // incorrect behavior. It still respects HTTP_PROXY, HTTPS_PROXY, and NO_PROXY. func ProxyFromEnvironment(req *http.Request) (*url.URL, error) { return ProxyFromConfig("", "", "")(req) } func ProxyFromConfig(httpsProxy string, httpProxy string, noProxy string) func(req *http.Request) (*url.URL, error) { return func(req *http.Request) (*url.URL, error) { var proxy, port string var err error switch req.URL.Scheme { case "https": proxy = httpsProxy if proxy == "" { proxy = httpsProxyEnv.Get() } port = ":443" case "http": proxy = httpProxy if proxy == "" { proxy = httpProxyEnv.Get() } port = ":80" default: return nil, fmt.Errorf("unknown scheme %s", req.URL.Scheme) } if proxy == "" { return nil, nil } addr := req.URL.Host if !hasPort(addr) { addr = addr + port } use, err := useProxy(addr, noProxy) if err != nil { return nil, err } if !use { return nil, nil } proxyURL, err := url.Parse(proxy) if err != nil || !strings.HasPrefix(proxyURL.Scheme, "http") { // proxy was bogus. Try prepending "http://" to it and // see if that parses correctly. If not, we fall // through and complain about the original one. if proxyURL, err := url.Parse("http://" + proxy); err == nil { return proxyURL, nil } } if err != nil { return nil, fmt.Errorf("invalid proxy address %q: %v", proxy, err) } return proxyURL, nil } } func hasPort(s string) bool { return strings.LastIndex(s, ":") > strings.LastIndex(s, "]") } func useProxy(addr string, noProxy string) (bool, error) { if noProxy == "" { noProxy = noProxyEnv.Get() } if len(addr) == 0 { return true, nil } host, _, err := net.SplitHostPort(addr) if err != nil { return false, nil } if host == "localhost" { return false, nil } if ip := net.ParseIP(host); ip != nil { if ip.IsLoopback() { return false, nil } } if noProxy == "*" { return false, nil } addr = strings.ToLower(strings.TrimSpace(addr)) if hasPort(addr) { addr = addr[:strings.LastIndex(addr, ":")] } for _, p := range strings.Split(noProxy, ",") { p = strings.ToLower(strings.TrimSpace(p)) if len(p) == 0 { continue } if hasPort(p) { p = p[:strings.LastIndex(p, ":")] } if addr == p { return false, nil } if p[0] == '.' && (strings.HasSuffix(addr, p) || addr == p[1:]) { // noProxy ".foo.com" matches "bar.foo.com" or "foo.com" return false, nil } if p[0] != '.' && strings.HasSuffix(addr, p) && addr[len(addr)-len(p)-1] == '.' { // noProxy "foo.com" matches "bar.foo.com" return false, nil } } return true, nil } lxd-2.0.0/shared/server.go000066400000000000000000000022601270277227600154170ustar00rootroot00000000000000package shared type ServerStateEnvironment struct { Addresses []string `json:"addresses"` Architectures []string `json:"architectures"` Certificate string `json:"certificate"` Driver string `json:"driver"` DriverVersion string `json:"driver_version"` Kernel string `json:"kernel"` KernelArchitecture string `json:"kernel_architecture"` KernelVersion string `json:"kernel_version"` Server string `json:"server"` ServerPid int `json:"server_pid"` ServerVersion string `json:"server_version"` Storage string `json:"storage"` StorageVersion string `json:"storage_version"` } type ServerState struct { APICompat int `json:"api_compat"` Auth string `json:"auth"` Environment ServerStateEnvironment `json:"environment"` Config map[string]interface{} `json:"config"` Public bool `json:"public"` } type BriefServerState struct { Config map[string]interface{} `json:"config"` } func (c *ServerState) Brief() BriefServerState { retstate := BriefServerState{Config: c.Config} return retstate } lxd-2.0.0/shared/simplestreams.go000066400000000000000000000336511270277227600170110ustar00rootroot00000000000000package shared import ( "crypto/sha256" "encoding/json" "fmt" "io" "io/ioutil" "net/http" "net/url" "os" "path/filepath" "sort" "strings" "time" ) type ssSortImage []ImageInfo func (a ssSortImage) Len() int { return len(a) } func (a ssSortImage) Swap(i, j int) { a[i], a[j] = a[j], a[i] } func (a ssSortImage) Less(i, j int) bool { if a[i].Properties["os"] == a[j].Properties["os"] { if a[i].Properties["release"] == a[j].Properties["release"] { if a[i].CreationDate.UTC().Unix() == 0 { return true } if a[j].CreationDate.UTC().Unix() == 0 { return false } return a[i].CreationDate.UTC().Unix() > a[j].CreationDate.UTC().Unix() } if a[i].Properties["release"] == "" { return false } if a[j].Properties["release"] == "" { return true } return a[i].Properties["release"] < a[j].Properties["release"] } if a[i].Properties["os"] == "" { return false } if a[j].Properties["os"] == "" { return true } return a[i].Properties["os"] < a[j].Properties["os"] } var ssDefaultOS = map[string]string{ "https://cloud-images.ubuntu.com": "ubuntu", } type SimpleStreamsManifest struct { Updated string `json:"updated"` DataType string `json:"datatype"` Format string `json:"format"` License string `json:"license"` Products map[string]SimpleStreamsManifestProduct `json:"products"` } func (s *SimpleStreamsManifest) ToLXD() ([]ImageInfo, map[string][][]string) { downloads := map[string][][]string{} images := []ImageInfo{} nameLayout := "20060102" eolLayout := "2006-01-02" for _, product := range s.Products { // Skip unsupported architectures architecture, err := ArchitectureId(product.Architecture) if err != nil { continue } architectureName, err := ArchitectureName(architecture) if err != nil { continue } for name, version := range product.Versions { // Short of anything better, use the name as date (see format above) if len(name) < 8 { continue } creationDate, err := time.Parse(nameLayout, name[0:8]) if err != nil { continue } size := int64(0) filename := "" fingerprint := "" metaPath := "" metaHash := "" rootfsPath := "" rootfsHash := "" found := 0 for _, item := range version.Items { // Skip the files we don't care about if !StringInSlice(item.FileType, []string{"root.tar.xz", "lxd.tar.xz"}) { continue } found += 1 size += item.Size if item.LXDHashSha256 != "" { fingerprint = item.LXDHashSha256 } if item.FileType == "lxd.tar.xz" { fields := strings.Split(item.Path, "/") filename = fields[len(fields)-1] metaPath = item.Path metaHash = item.HashSha256 } if item.FileType == "root.tar.xz" { rootfsPath = item.Path rootfsHash = item.HashSha256 } } if found != 2 || size == 0 || filename == "" || fingerprint == "" { // Invalid image continue } // Generate the actual image entry image := ImageInfo{} image.Architecture = architectureName image.Public = true image.Size = size image.CreationDate = creationDate image.UploadDate = creationDate image.Filename = filename image.Fingerprint = fingerprint image.Properties = map[string]string{ "aliases": product.Aliases, "os": product.OperatingSystem, "release": product.Release, "version": product.Version, "architecture": product.Architecture, "label": version.Label, "serial": name, "description": fmt.Sprintf("%s %s %s (%s) (%s)", product.OperatingSystem, product.ReleaseTitle, product.Architecture, version.Label, name), } // Attempt to parse the EOL if product.SupportedEOL != "" { eolDate, err := time.Parse(eolLayout, product.SupportedEOL) if err == nil { image.ExpiryDate = eolDate } } downloads[fingerprint] = [][]string{[]string{metaPath, metaHash, "meta"}, []string{rootfsPath, rootfsHash, "root"}} images = append(images, image) } } return images, downloads } type SimpleStreamsManifestProduct struct { Aliases string `json:"aliases"` Architecture string `json:"arch"` OperatingSystem string `json:"os"` Release string `json:"release"` ReleaseCodename string `json:"release_codename"` ReleaseTitle string `json:"release_title"` Supported bool `json:"supported"` SupportedEOL string `json:"support_eol"` Version string `json:"version"` Versions map[string]SimpleStreamsManifestProductVersion `json:"versions"` } type SimpleStreamsManifestProductVersion struct { PublicName string `json:"pubname"` Label string `json:"label"` Items map[string]SimpleStreamsManifestProductVersionItem `json:"items"` } type SimpleStreamsManifestProductVersionItem struct { Path string `json:"path"` FileType string `json:"ftype"` HashMd5 string `json:"md5"` HashSha256 string `json:"sha256"` LXDHashSha256 string `json:"combined_sha256"` Size int64 `json:"size"` } type SimpleStreamsIndex struct { Format string `json:"format"` Index map[string]SimpleStreamsIndexStream `json:"index"` Updated string `json:"updated"` } type SimpleStreamsIndexStream struct { Updated string `json:"updated"` DataType string `json:"datatype"` Path string `json:"path"` Products []string `json:"products"` } func SimpleStreamsClient(url string, proxy func(*http.Request) (*url.URL, error)) (*SimpleStreams, error) { // Setup a http client tlsConfig, err := GetTLSConfig("", "", nil) if err != nil { return nil, err } tr := &http.Transport{ TLSClientConfig: tlsConfig, Dial: RFC3493Dialer, Proxy: proxy, } myHttp := http.Client{ Transport: tr, } return &SimpleStreams{ http: &myHttp, url: url, cachedManifest: map[string]*SimpleStreamsManifest{}}, nil } type SimpleStreams struct { http *http.Client url string cachedIndex *SimpleStreamsIndex cachedManifest map[string]*SimpleStreamsManifest cachedImages []ImageInfo cachedAliases map[string]*ImageAliasesEntry } func (s *SimpleStreams) parseIndex() (*SimpleStreamsIndex, error) { if s.cachedIndex != nil { return s.cachedIndex, nil } req, err := http.NewRequest("GET", fmt.Sprintf("%s/streams/v1/index.json", s.url), nil) if err != nil { return nil, err } req.Header.Set("User-Agent", UserAgent) r, err := s.http.Do(req) if err != nil { return nil, err } defer r.Body.Close() body, err := ioutil.ReadAll(r.Body) if err != nil { return nil, err } // Parse the idnex ssIndex := SimpleStreamsIndex{} err = json.Unmarshal(body, &ssIndex) if err != nil { return nil, err } s.cachedIndex = &ssIndex return &ssIndex, nil } func (s *SimpleStreams) parseManifest(path string) (*SimpleStreamsManifest, error) { if s.cachedManifest[path] != nil { return s.cachedManifest[path], nil } req, err := http.NewRequest("GET", fmt.Sprintf("%s/%s", s.url, path), nil) if err != nil { return nil, err } req.Header.Set("User-Agent", UserAgent) r, err := s.http.Do(req) if err != nil { return nil, err } defer r.Body.Close() body, err := ioutil.ReadAll(r.Body) if err != nil { return nil, err } // Parse the idnex ssManifest := SimpleStreamsManifest{} err = json.Unmarshal(body, &ssManifest) if err != nil { return nil, err } s.cachedManifest[path] = &ssManifest return &ssManifest, nil } func (s *SimpleStreams) applyAliases(images []ImageInfo) ([]ImageInfo, map[string]*ImageAliasesEntry, error) { aliases := map[string]*ImageAliasesEntry{} sort.Sort(ssSortImage(images)) defaultOS := "" for k, v := range ssDefaultOS { if strings.HasPrefix(s.url, k) { defaultOS = v break } } addAlias := func(name string, fingerprint string) *ImageAlias { if defaultOS != "" { name = strings.TrimPrefix(name, fmt.Sprintf("%s/", defaultOS)) } if aliases[name] != nil { return nil } alias := ImageAliasesEntry{} alias.Name = name alias.Target = fingerprint aliases[name] = &alias return &ImageAlias{Name: name} } architectureName, _ := ArchitectureGetLocal() newImages := []ImageInfo{} for _, image := range images { if image.Properties["aliases"] != "" { aliases := strings.Split(image.Properties["aliases"], ",") for _, entry := range aliases { // Short if image.Architecture == architectureName { alias := addAlias(fmt.Sprintf("%s", entry), image.Fingerprint) if alias != nil { image.Aliases = append(image.Aliases, *alias) } } // Medium alias := addAlias(fmt.Sprintf("%s/%s", entry, image.Properties["architecture"]), image.Fingerprint) if alias != nil { image.Aliases = append(image.Aliases, *alias) } } } newImages = append(newImages, image) } return newImages, aliases, nil } func (s *SimpleStreams) getImages() ([]ImageInfo, map[string]*ImageAliasesEntry, error) { if s.cachedImages != nil && s.cachedAliases != nil { return s.cachedImages, s.cachedAliases, nil } images := []ImageInfo{} // Load the main index ssIndex, err := s.parseIndex() if err != nil { return nil, nil, err } // Iterate through the various image manifests for _, entry := range ssIndex.Index { // We only care about images if entry.DataType != "image-downloads" { continue } // No point downloading an empty image list if len(entry.Products) == 0 { continue } manifest, err := s.parseManifest(entry.Path) if err != nil { return nil, nil, err } manifestImages, _ := manifest.ToLXD() for _, image := range manifestImages { images = append(images, image) } } // Setup the aliases images, aliases, err := s.applyAliases(images) if err != nil { return nil, nil, err } s.cachedImages = images s.cachedAliases = aliases return images, aliases, nil } func (s *SimpleStreams) getPaths(fingerprint string) ([][]string, error) { // Load the main index ssIndex, err := s.parseIndex() if err != nil { return nil, err } // Iterate through the various image manifests for _, entry := range ssIndex.Index { // We only care about images if entry.DataType != "image-downloads" { continue } // No point downloading an empty image list if len(entry.Products) == 0 { continue } manifest, err := s.parseManifest(entry.Path) if err != nil { return nil, err } manifestImages, downloads := manifest.ToLXD() for _, image := range manifestImages { if strings.HasPrefix(image.Fingerprint, fingerprint) { urls := [][]string{} for _, path := range downloads[image.Fingerprint] { urls = append(urls, []string{path[0], path[1], path[2]}) } return urls, nil } } } return nil, fmt.Errorf("Couldn't find the requested image") } func (s *SimpleStreams) downloadFile(path string, hash string, target string, progress func(int)) error { download := func(url string, hash string, target string) error { out, err := os.Create(target) if err != nil { return err } defer out.Close() resp, err := s.http.Get(url) if err != nil { } defer resp.Body.Close() body := &TransferProgress{Reader: resp.Body, Length: resp.ContentLength, Handler: progress} sha256 := sha256.New() _, err = io.Copy(io.MultiWriter(out, sha256), body) if err != nil { return err } if fmt.Sprintf("%x", sha256.Sum(nil)) != hash { os.Remove(target) return fmt.Errorf("Hash mismatch") } return nil } // Try http first if strings.HasPrefix(s.url, "https://") { err := download(fmt.Sprintf("http://%s/%s", strings.TrimPrefix(s.url, "https://"), path), hash, target) if err == nil { return nil } } err := download(fmt.Sprintf("%s/%s", s.url, path), hash, target) if err != nil { return err } return nil } func (s *SimpleStreams) ListAliases() (ImageAliases, error) { _, aliasesMap, err := s.getImages() if err != nil { return nil, err } aliases := ImageAliases{} for _, alias := range aliasesMap { aliases = append(aliases, *alias) } return aliases, nil } func (s *SimpleStreams) ListImages() ([]ImageInfo, error) { images, _, err := s.getImages() return images, err } func (s *SimpleStreams) GetAlias(name string) string { _, aliasesMap, err := s.getImages() if err != nil { return "" } alias, ok := aliasesMap[name] if !ok { return "" } return alias.Target } func (s *SimpleStreams) GetImageInfo(fingerprint string) (*ImageInfo, error) { images, _, err := s.getImages() if err != nil { return nil, err } for _, image := range images { if strings.HasPrefix(image.Fingerprint, fingerprint) { return &image, nil } } return nil, fmt.Errorf("The requested image couldn't be found.") } func (s *SimpleStreams) ExportImage(image string, target string) (string, error) { if !IsDir(target) { return "", fmt.Errorf("Split images can only be written to a directory.") } paths, err := s.getPaths(image) if err != nil { return "", err } for _, path := range paths { fields := strings.Split(path[0], "/") targetFile := filepath.Join(target, fields[len(fields)-1]) err := s.downloadFile(path[0], path[1], targetFile, nil) if err != nil { return "", err } } return target, nil } func (s *SimpleStreams) Download(image string, file string, target string, progress func(int)) error { paths, err := s.getPaths(image) if err != nil { return err } for _, path := range paths { if file != path[2] { continue } return s.downloadFile(path[0], path[1], target, progress) } return fmt.Errorf("The file couldn't be found.") } lxd-2.0.0/shared/status.go000066400000000000000000000031351270277227600154360ustar00rootroot00000000000000package shared type StatusCode int const ( OperationCreated StatusCode = 100 Started StatusCode = 101 Stopped StatusCode = 102 Running StatusCode = 103 Cancelling StatusCode = 104 Pending StatusCode = 105 Starting StatusCode = 106 Stopping StatusCode = 107 Aborting StatusCode = 108 Freezing StatusCode = 109 Frozen StatusCode = 110 Thawed StatusCode = 111 Error StatusCode = 112 Success StatusCode = 200 Failure StatusCode = 400 Cancelled StatusCode = 401 ) func (o StatusCode) String() string { return map[StatusCode]string{ OperationCreated: "Operation created", Started: "Started", Stopped: "Stopped", Running: "Running", Cancelling: "Cancelling", Pending: "Pending", Success: "Success", Failure: "Failure", Cancelled: "Cancelled", Starting: "Starting", Stopping: "Stopping", Aborting: "Aborting", Freezing: "Freezing", Frozen: "Frozen", Thawed: "Thawed", Error: "Error", }[o] } func (o StatusCode) IsFinal() bool { return int(o) >= 200 } /* * Create a StatusCode from an lxc.State code. N.B.: we accept an int instead * of a lxc.State so that the shared code doesn't depend on lxc, which depends * on liblxc, etc. */ func FromLXCState(state int) StatusCode { return map[int]StatusCode{ 1: Stopped, 2: Starting, 3: Running, 4: Stopping, 5: Aborting, 6: Freezing, 7: Frozen, 8: Thawed, 9: Error, }[state] } lxd-2.0.0/shared/stringset.go000066400000000000000000000007161270277227600161370ustar00rootroot00000000000000// That this code needs to exist is kind of dumb, but I'm not sure how else to // do it. package shared type StringSet map[string]bool func (ss StringSet) IsSubset(oss StringSet) bool { for k, _ := range map[string]bool(ss) { if _, ok := map[string]bool(oss)[k]; !ok { return false } } return true } func NewStringSet(strings []string) StringSet { ret := map[string]bool{} for _, s := range strings { ret[s] = true } return StringSet(ret) } lxd-2.0.0/shared/stringset_test.go000066400000000000000000000006011270277227600171670ustar00rootroot00000000000000package shared import ( "testing" ) func TestStringSetSubset(t *testing.T) { ss := NewStringSet([]string{"one", "two"}) if !ss.IsSubset(ss) { t.Error("subests wrong") return } if !ss.IsSubset(NewStringSet([]string{"one", "two", "three"})) { t.Error("subsets wrong") return } if ss.IsSubset(NewStringSet([]string{"four"})) { t.Error("subests wrong") return } } lxd-2.0.0/shared/termios/000077500000000000000000000000001270277227600152445ustar00rootroot00000000000000lxd-2.0.0/shared/termios/termios.go000066400000000000000000000026441270277227600172630ustar00rootroot00000000000000// +build !windows package termios import ( "syscall" "unsafe" "github.com/lxc/lxd/shared" ) // #include import "C" type State struct { Termios syscall.Termios } func IsTerminal(fd int) bool { _, err := GetState(fd) return err == nil } func GetState(fd int) (*State, error) { termios := syscall.Termios{} ret, err := C.tcgetattr(C.int(fd), (*C.struct_termios)(unsafe.Pointer(&termios))) if ret != 0 { return nil, err.(syscall.Errno) } state := State{} state.Termios = termios return &state, nil } func GetSize(fd int) (int, int, error) { var dimensions [4]uint16 if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), uintptr(syscall.TIOCGWINSZ), uintptr(unsafe.Pointer(&dimensions)), 0, 0, 0); err != 0 { return -1, -1, err } return int(dimensions[1]), int(dimensions[0]), nil } func MakeRaw(fd int) (*State, error) { var err error var oldState, newState *State oldState, err = GetState(fd) if err != nil { return nil, err } err = shared.DeepCopy(&oldState, &newState) if err != nil { return nil, err } C.cfmakeraw((*C.struct_termios)(unsafe.Pointer(&newState.Termios))) err = Restore(fd, newState) if err != nil { return nil, err } return oldState, nil } func Restore(fd int, state *State) error { ret, err := C.tcsetattr(C.int(fd), C.TCSANOW, (*C.struct_termios)(unsafe.Pointer(&state.Termios))) if ret != 0 { return err.(syscall.Errno) } return nil } lxd-2.0.0/shared/termios/termios_windows.go000066400000000000000000000013141270277227600210260ustar00rootroot00000000000000// +build windows package termios import ( "golang.org/x/crypto/ssh/terminal" ) type State terminal.State func IsTerminal(fd int) bool { return terminal.IsTerminal(fd) } func GetState(fd int) (*State, error) { state, err := terminal.GetState(fd) if err != nil { return nil, err } currentState := State(*state) return ¤tState, nil } func GetSize(fd int) (int, int, error) { return terminal.GetSize(fd) } func MakeRaw(fd int) (*State, error) { state, err := terminal.MakeRaw(fd) if err != nil { return nil, err } oldState := State(*state) return &oldState, nil } func Restore(fd int, state *State) error { newState := terminal.State(*state) return terminal.Restore(fd, &newState) } lxd-2.0.0/shared/util.go000066400000000000000000000341551270277227600150760ustar00rootroot00000000000000package shared import ( "bufio" "bytes" "crypto/rand" "encoding/gob" "encoding/hex" "encoding/json" "fmt" "io" "io/ioutil" "net/http" "os" "os/exec" "path" "path/filepath" "reflect" "regexp" "strconv" "strings" ) const SnapshotDelimiter = "/" const DefaultPort = "8443" // AddSlash adds a slash to the end of paths if they don't already have one. // This can be useful for rsyncing things, since rsync has behavior present on // the presence or absence of a trailing slash. func AddSlash(path string) string { if path[len(path)-1] != '/' { return path + "/" } return path } func PathExists(name string) bool { _, err := os.Lstat(name) if err != nil && os.IsNotExist(err) { return false } return true } // PathIsEmpty checks if the given path is empty. func PathIsEmpty(path string) (bool, error) { f, err := os.Open(path) if err != nil { return false, err } defer f.Close() // read in ONLY one file _, err = f.Readdir(1) // and if the file is EOF... well, the dir is empty. if err == io.EOF { return true, nil } return false, err } // IsDir returns true if the given path is a directory. func IsDir(name string) bool { stat, err := os.Lstat(name) if err != nil { return false } return stat.IsDir() } // VarPath returns the provided path elements joined by a slash and // appended to the end of $LXD_DIR, which defaults to /var/lib/lxd. func VarPath(path ...string) string { varDir := os.Getenv("LXD_DIR") if varDir == "" { varDir = "/var/lib/lxd" } items := []string{varDir} items = append(items, path...) return filepath.Join(items...) } // LogPath returns the directory that LXD should put logs under. If LXD_DIR is // set, this path is $LXD_DIR/logs, otherwise it is /var/log/lxd. func LogPath(path ...string) string { varDir := os.Getenv("LXD_DIR") logDir := "/var/log/lxd" if varDir != "" { logDir = filepath.Join(varDir, "logs") } items := []string{logDir} items = append(items, path...) return filepath.Join(items...) } func ParseLXDFileHeaders(headers http.Header) (uid int, gid int, mode os.FileMode) { uid, err := strconv.Atoi(headers.Get("X-LXD-uid")) if err != nil { uid = 0 } gid, err = strconv.Atoi(headers.Get("X-LXD-gid")) if err != nil { gid = 0 } /* Allow people to send stuff with a leading 0 for octal or a regular * int that represents the perms when redered in octal. */ rawMode, err := strconv.ParseInt(headers.Get("X-LXD-mode"), 0, 0) if err != nil { rawMode = 0644 } mode = os.FileMode(rawMode) return uid, gid, mode } func ReadToJSON(r io.Reader, req interface{}) error { buf, err := ioutil.ReadAll(r) if err != nil { return err } return json.Unmarshal(buf, req) } func ReaderToChannel(r io.Reader) <-chan []byte { ch := make(chan ([]byte)) go func() { for { /* io.Copy uses a 32KB buffer, so we might as well too. */ buf := make([]byte, 32*1024) nr, err := r.Read(buf) if nr > 0 { ch <- buf[0:nr] } if err != nil { close(ch) break } } }() return ch } // Returns a random base64 encoded string from crypto/rand. func RandomCryptoString() (string, error) { buf := make([]byte, 32) n, err := rand.Read(buf) if err != nil { return "", err } if n != len(buf) { return "", fmt.Errorf("not enough random bytes read") } return hex.EncodeToString(buf), nil } func SplitExt(fpath string) (string, string) { b := path.Base(fpath) ext := path.Ext(fpath) return b[:len(b)-len(ext)], ext } func AtoiEmptyDefault(s string, def int) (int, error) { if s == "" { return def, nil } return strconv.Atoi(s) } func ReadStdin() ([]byte, error) { buf := bufio.NewReader(os.Stdin) line, _, err := buf.ReadLine() if err != nil { return nil, err } return line, nil } func WriteAll(w io.Writer, buf []byte) error { return WriteAllBuf(w, bytes.NewBuffer(buf)) } func WriteAllBuf(w io.Writer, buf *bytes.Buffer) error { toWrite := int64(buf.Len()) for { n, err := io.Copy(w, buf) if err != nil { return err } toWrite -= n if toWrite <= 0 { return nil } } } // FileMove tries to move a file by using os.Rename, // if that fails it tries to copy the file and remove the source. func FileMove(oldPath string, newPath string) error { if err := os.Rename(oldPath, newPath); err == nil { return nil } if err := FileCopy(oldPath, newPath); err != nil { return err } os.Remove(oldPath) return nil } // FileCopy copies a file, overwriting the target if it exists. func FileCopy(source string, dest string) error { s, err := os.Open(source) if err != nil { return err } defer s.Close() d, err := os.Create(dest) if err != nil { if os.IsExist(err) { d, err = os.OpenFile(dest, os.O_WRONLY, 0700) if err != nil { return err } } else { return err } } defer d.Close() _, err = io.Copy(d, s) return err } type BytesReadCloser struct { Buf *bytes.Buffer } func (r BytesReadCloser) Read(b []byte) (n int, err error) { return r.Buf.Read(b) } func (r BytesReadCloser) Close() error { /* no-op since we're in memory */ return nil } func IsSnapshot(name string) bool { return strings.Contains(name, SnapshotDelimiter) } func ExtractSnapshotName(name string) string { return strings.SplitN(name, SnapshotDelimiter, 2)[1] } func ReadDir(p string) ([]string, error) { ents, err := ioutil.ReadDir(p) if err != nil { return []string{}, err } var ret []string for _, ent := range ents { ret = append(ret, ent.Name()) } return ret, nil } func MkdirAllOwner(path string, perm os.FileMode, uid int, gid int) error { // This function is a slightly modified version of MkdirAll from the Go standard library. // https://golang.org/src/os/path.go?s=488:535#L9 // Fast path: if we can tell whether path is a directory or file, stop with success or error. dir, err := os.Stat(path) if err == nil { if dir.IsDir() { return nil } return fmt.Errorf("path exists but isn't a directory") } // Slow path: make sure parent exists and then call Mkdir for path. i := len(path) for i > 0 && os.IsPathSeparator(path[i-1]) { // Skip trailing path separator. i-- } j := i for j > 0 && !os.IsPathSeparator(path[j-1]) { // Scan backward over element. j-- } if j > 1 { // Create parent err = MkdirAllOwner(path[0:j-1], perm, uid, gid) if err != nil { return err } } // Parent now exists; invoke Mkdir and use its result. err = os.Mkdir(path, perm) err_chown := os.Chown(path, uid, gid) if err_chown != nil { return err_chown } if err != nil { // Handle arguments like "foo/." by // double-checking that directory doesn't exist. dir, err1 := os.Lstat(path) if err1 == nil && dir.IsDir() { return nil } return err } return nil } func StringInSlice(key string, list []string) bool { for _, entry := range list { if entry == key { return true } } return false } func IntInSlice(key int, list []int) bool { for _, entry := range list { if entry == key { return true } } return false } func IsOnSharedMount(pathName string) (bool, error) { file, err := os.Open("/proc/self/mountinfo") if err != nil { return false, err } defer file.Close() absPath, err := filepath.Abs(pathName) if err != nil { return false, err } expPath, err := os.Readlink(absPath) if err != nil { expPath = absPath } scanner := bufio.NewScanner(file) for scanner.Scan() { line := scanner.Text() rows := strings.Fields(line) if rows[4] != expPath { continue } if strings.HasPrefix(rows[6], "shared:") { return true, nil } else { return false, nil } } return false, nil } func IsBlockdev(fm os.FileMode) bool { return ((fm&os.ModeDevice != 0) && (fm&os.ModeCharDevice == 0)) } func IsBlockdevPath(pathName string) bool { sb, err := os.Stat(pathName) if err != nil { return false } fm := sb.Mode() return ((fm&os.ModeDevice != 0) && (fm&os.ModeCharDevice == 0)) } func BlockFsDetect(dev string) (string, error) { out, err := exec.Command("blkid", "-s", "TYPE", "-o", "value", dev).Output() if err != nil { return "", fmt.Errorf("Failed to run blkid on: %s", dev) } return strings.TrimSpace(string(out)), nil } // DeepCopy copies src to dest by using encoding/gob so its not that fast. func DeepCopy(src, dest interface{}) error { buff := new(bytes.Buffer) enc := gob.NewEncoder(buff) dec := gob.NewDecoder(buff) if err := enc.Encode(src); err != nil { return err } if err := dec.Decode(dest); err != nil { return err } return nil } func RunningInUserNS() bool { file, err := os.Open("/proc/self/uid_map") if err != nil { return false } defer file.Close() buf := bufio.NewReader(file) l, _, err := buf.ReadLine() if err != nil { return false } line := string(l) var a, b, c int64 fmt.Sscanf(line, "%d %d %d", &a, &b, &c) if a == 0 && b == 0 && c == 4294967295 { return false } return true } func ValidHostname(name string) bool { // Validate length if len(name) < 1 || len(name) > 63 { return false } // Validate first character if strings.HasPrefix(name, "-") { return false } if _, err := strconv.Atoi(string(name[0])); err == nil { return false } // Validate last character if strings.HasSuffix(name, "-") { return false } // Validate the character set match, _ := regexp.MatchString("^[-a-zA-Z0-9]*$", name) if !match { return false } return true } func TextEditor(inPath string, inContent []byte) ([]byte, error) { var f *os.File var err error var path string // Detect the text editor to use editor := os.Getenv("VISUAL") if editor == "" { editor = os.Getenv("EDITOR") if editor == "" { for _, p := range []string{"editor", "vi", "emacs", "nano"} { _, err := exec.LookPath(p) if err == nil { editor = p break } } if editor == "" { return []byte{}, fmt.Errorf("No text editor found, please set the EDITOR environment variable.") } } } if inPath == "" { // If provided input, create a new file f, err = ioutil.TempFile("", "lxd_editor_") if err != nil { return []byte{}, err } if err = f.Chmod(0600); err != nil { f.Close() os.Remove(f.Name()) return []byte{}, err } f.Write(inContent) f.Close() path = f.Name() defer os.Remove(path) } else { path = inPath } cmdParts := strings.Fields(editor) cmd := exec.Command(cmdParts[0], append(cmdParts[1:], path)...) cmd.Stdin = os.Stdin cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr err = cmd.Run() if err != nil { return []byte{}, err } content, err := ioutil.ReadFile(path) if err != nil { return []byte{}, err } return content, nil } func ParseMetadata(metadata interface{}) (map[string]interface{}, error) { newMetadata := make(map[string]interface{}) s := reflect.ValueOf(metadata) if !s.IsValid() { return nil, nil } if s.Kind() == reflect.Map { for _, k := range s.MapKeys() { if k.Kind() != reflect.String { return nil, fmt.Errorf("Invalid metadata provided (key isn't a string).") } newMetadata[k.String()] = s.MapIndex(k).Interface() } } else if s.Kind() == reflect.Ptr && !s.Elem().IsValid() { return nil, nil } else { return nil, fmt.Errorf("Invalid metadata provided (type isn't a map).") } return newMetadata, nil } // Parse a size string in bytes (e.g. 200kB or 5GB) into the number of bytes it // represents. Supports suffixes up to EB. "" == 0. func ParseByteSizeString(input string) (int64, error) { if input == "" { return 0, nil } if len(input) < 3 { return -1, fmt.Errorf("Invalid value: %s", input) } // Extract the suffix suffix := input[len(input)-2:] // Extract the value value := input[0 : len(input)-2] valueInt, err := strconv.ParseInt(value, 10, 64) if err != nil { return -1, fmt.Errorf("Invalid integer: %s", input) } if valueInt < 0 { return -1, fmt.Errorf("Invalid value: %d", valueInt) } // Figure out the multiplicator multiplicator := int64(0) switch suffix { case "kB": multiplicator = 1024 case "MB": multiplicator = 1024 * 1024 case "GB": multiplicator = 1024 * 1024 * 1024 case "TB": multiplicator = 1024 * 1024 * 1024 * 1024 case "PB": multiplicator = 1024 * 1024 * 1024 * 1024 * 1024 case "EB": multiplicator = 1024 * 1024 * 1024 * 1024 * 1024 * 1024 default: return -1, fmt.Errorf("Unsupported suffix: %s", suffix) } return valueInt * multiplicator, nil } // Parse a size string in bits (e.g. 200kbit or 5Gbit) into the number of bits // it represents. Supports suffixes up to Ebit. "" == 0. func ParseBitSizeString(input string) (int64, error) { if input == "" { return 0, nil } if len(input) < 5 { return -1, fmt.Errorf("Invalid value: %s", input) } // Extract the suffix suffix := input[len(input)-4:] // Extract the value value := input[0 : len(input)-4] valueInt, err := strconv.ParseInt(value, 10, 64) if err != nil { return -1, fmt.Errorf("Invalid integer: %s", input) } if valueInt < 0 { return -1, fmt.Errorf("Invalid value: %d", valueInt) } // Figure out the multiplicator multiplicator := int64(0) switch suffix { case "kbit": multiplicator = 1000 case "Mbit": multiplicator = 1000 * 1000 case "Gbit": multiplicator = 1000 * 1000 * 1000 case "Tbit": multiplicator = 1000 * 1000 * 1000 * 1000 case "Pbit": multiplicator = 1000 * 1000 * 1000 * 1000 * 1000 case "Ebit": multiplicator = 1000 * 1000 * 1000 * 1000 * 1000 * 1000 default: return -1, fmt.Errorf("Unsupported suffix: %s", suffix) } return valueInt * multiplicator, nil } func GetByteSizeString(input int64) string { if input < 1024 { return fmt.Sprintf("%d bytes", input) } value := float64(input) for _, unit := range []string{"kB", "MB", "GB", "TB", "PB", "EB"} { value = value / 1024 if value < 1024 { return fmt.Sprintf("%.2f%s", value, unit) } } return fmt.Sprintf("%.2fEB", value) } type TransferProgress struct { io.Reader percentage float64 total int64 Length int64 Handler func(int) } func (pt *TransferProgress) Read(p []byte) (int, error) { n, err := pt.Reader.Read(p) if pt.Handler == nil { return n, err } if n > 0 { pt.total += int64(n) percentage := float64(pt.total) / float64(pt.Length) * float64(100) if percentage-pt.percentage > 0.9 { pt.percentage = percentage progressInt := 1 - (int(percentage) % 1) + int(percentage) if progressInt > 100 { progressInt = 100 } pt.Handler(progressInt) } } return n, err } lxd-2.0.0/shared/util_linux.go000066400000000000000000000203061270277227600163060ustar00rootroot00000000000000// +build linux // +build cgo package shared import ( "errors" "fmt" "os" "os/exec" "syscall" "unsafe" ) // #cgo LDFLAGS: -lutil -lpthread /* #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #ifndef AT_SYMLINK_FOLLOW #define AT_SYMLINK_FOLLOW 0x400 #endif #ifndef AT_EMPTY_PATH #define AT_EMPTY_PATH 0x1000 #endif // This is an adaption from https://codereview.appspot.com/4589049, to be // included in the stdlib with the stdlib's license. static int mygetgrgid_r(int gid, struct group *grp, char *buf, size_t buflen, struct group **result) { return getgrgid_r(gid, grp, buf, buflen, result); } void configure_pty(int fd) { struct termios term_settings; struct winsize win; if (tcgetattr(fd, &term_settings) < 0) { fprintf(stderr, "Failed to get settings: %s\n", strerror(errno)); return; } term_settings.c_iflag |= IMAXBEL; term_settings.c_iflag |= IUTF8; term_settings.c_iflag |= BRKINT; term_settings.c_iflag |= IXANY; term_settings.c_cflag |= HUPCL; if (tcsetattr(fd, TCSANOW, &term_settings) < 0) { fprintf(stderr, "Failed to set settings: %s\n", strerror(errno)); return; } if (ioctl(fd, TIOCGWINSZ, &win) < 0) { fprintf(stderr, "Failed to get the terminal size: %s\n", strerror(errno)); return; } win.ws_col = 80; win.ws_row = 25; if (ioctl(fd, TIOCSWINSZ, &win) < 0) { fprintf(stderr, "Failed to set the terminal size: %s\n", strerror(errno)); return; } if (fcntl(fd, F_SETFD, FD_CLOEXEC) < 0) { fprintf(stderr, "Failed to set FD_CLOEXEC: %s\n", strerror(errno)); return; } return; } void create_pty(int *master, int *slave, int uid, int gid) { if (openpty(master, slave, NULL, NULL, NULL) < 0) { fprintf(stderr, "Failed to openpty: %s\n", strerror(errno)); return; } configure_pty(*master); configure_pty(*slave); if (fchown(*slave, uid, gid) < 0) { fprintf(stderr, "Warning: error chowning pty to container root\n"); fprintf(stderr, "Continuing...\n"); } if (fchown(*master, uid, gid) < 0) { fprintf(stderr, "Warning: error chowning pty to container root\n"); fprintf(stderr, "Continuing...\n"); } } void create_pipe(int *master, int *slave) { int pipefd[2]; if (pipe2(pipefd, O_CLOEXEC) < 0) { fprintf(stderr, "Failed to create a pipe: %s\n", strerror(errno)); return; } *master = pipefd[0]; *slave = pipefd[1]; } int shiftowner(char *basepath, char *path, int uid, int gid) { struct stat sb; int fd, r; char fdpath[PATH_MAX]; char realpath[PATH_MAX]; fd = open(path, O_PATH|O_NOFOLLOW); if (fd < 0 ) { perror("Failed open"); return 1; } r = sprintf(fdpath, "/proc/self/fd/%d", fd); if (r < 0) { perror("Failed sprintf"); close(fd); return 1; } r = readlink(fdpath, realpath, PATH_MAX); if (r < 0) { perror("Failed readlink"); close(fd); return 1; } if (strlen(realpath) < strlen(basepath)) { printf("Invalid path, source (%s) is outside of basepath (%s).\n", realpath, basepath); close(fd); return 1; } if (strncmp(realpath, basepath, strlen(basepath))) { printf("Invalid path, source (%s) is outside of basepath (%s).\n", realpath, basepath); close(fd); return 1; } r = fstat(fd, &sb); if (r < 0) { perror("Failed fstat"); close(fd); return 1; } r = fchownat(fd, "", uid, gid, AT_EMPTY_PATH|AT_SYMLINK_NOFOLLOW); if (r < 0) { perror("Failed chown"); close(fd); return 1; } if (!S_ISLNK(sb.st_mode)) { r = chmod(fdpath, sb.st_mode); if (r < 0) { perror("Failed chmod"); close(fd); return 1; } } close(fd); return 0; } */ import "C" func ShiftOwner(basepath string, path string, uid int, gid int) error { cbasepath := C.CString(basepath) defer C.free(unsafe.Pointer(cbasepath)) cpath := C.CString(path) defer C.free(unsafe.Pointer(cpath)) r := C.shiftowner(cbasepath, cpath, C.int(uid), C.int(gid)) if r != 0 { return fmt.Errorf("Failed to change ownership of: %s", path) } return nil } func OpenPty(uid, gid int) (master *os.File, slave *os.File, err error) { fd_master := C.int(-1) fd_slave := C.int(-1) rootUid := C.int(uid) rootGid := C.int(gid) C.create_pty(&fd_master, &fd_slave, rootUid, rootGid) if fd_master == -1 || fd_slave == -1 { return nil, nil, errors.New("Failed to create a new pts pair") } master = os.NewFile(uintptr(fd_master), "master") slave = os.NewFile(uintptr(fd_slave), "slave") return master, slave, nil } func Pipe() (master *os.File, slave *os.File, err error) { fd_master := C.int(-1) fd_slave := C.int(-1) C.create_pipe(&fd_master, &fd_slave) if fd_master == -1 || fd_slave == -1 { return nil, nil, errors.New("Failed to create a new pipe") } master = os.NewFile(uintptr(fd_master), "master") slave = os.NewFile(uintptr(fd_slave), "slave") return master, slave, nil } // GroupName is an adaption from https://codereview.appspot.com/4589049. func GroupName(gid int) (string, error) { var grp C.struct_group var result *C.struct_group bufSize := C.size_t(C.sysconf(C._SC_GETGR_R_SIZE_MAX)) buf := C.malloc(bufSize) if buf == nil { return "", fmt.Errorf("allocation failed") } defer C.free(buf) // mygetgrgid_r is a wrapper around getgrgid_r to // to avoid using gid_t because C.gid_t(gid) for // unknown reasons doesn't work on linux. rv := C.mygetgrgid_r(C.int(gid), &grp, (*C.char)(buf), bufSize, &result) if rv != 0 { return "", fmt.Errorf("failed group lookup: %s", syscall.Errno(rv)) } if result == nil { return "", fmt.Errorf("unknown group %d", gid) } return C.GoString(result.gr_name), nil } // GroupId is an adaption from https://codereview.appspot.com/4589049. func GroupId(name string) (int, error) { var grp C.struct_group var result *C.struct_group bufSize := C.size_t(C.sysconf(C._SC_GETGR_R_SIZE_MAX)) buf := C.malloc(bufSize) if buf == nil { return -1, fmt.Errorf("allocation failed") } defer C.free(buf) // mygetgrgid_r is a wrapper around getgrgid_r to // to avoid using gid_t because C.gid_t(gid) for // unknown reasons doesn't work on linux. cname := C.CString(name) defer C.free(unsafe.Pointer(cname)) rv := C.getgrnam_r(cname, &grp, (*C.char)(buf), bufSize, &result) if rv != 0 { return -1, fmt.Errorf("failed group lookup: %s", syscall.Errno(rv)) } if result == nil { return -1, fmt.Errorf("unknown group %s", name) } return int(C.int(result.gr_gid)), nil } // --- pure Go functions --- func GetFileStat(p string) (uid int, gid int, major int, minor int, inode uint64, nlink int, err error) { var stat syscall.Stat_t err = syscall.Lstat(p, &stat) if err != nil { return } uid = int(stat.Uid) gid = int(stat.Gid) inode = uint64(stat.Ino) nlink = int(stat.Nlink) major = -1 minor = -1 if stat.Mode&syscall.S_IFBLK != 0 || stat.Mode&syscall.S_IFCHR != 0 { major = int(stat.Rdev / 256) minor = int(stat.Rdev % 256) } return } func IsMountPoint(name string) bool { _, err := exec.LookPath("mountpoint") if err == nil { err = exec.Command("mountpoint", "-q", name).Run() if err != nil { return false } return true } stat, err := os.Stat(name) if err != nil { return false } rootStat, err := os.Lstat(name + "/..") if err != nil { return false } // If the directory has the same device as parent, then it's not a mountpoint. return stat.Sys().(*syscall.Stat_t).Dev != rootStat.Sys().(*syscall.Stat_t).Dev } func ReadLastNLines(f *os.File, lines int) (string, error) { if lines <= 0 { return "", fmt.Errorf("invalid line count") } stat, err := f.Stat() if err != nil { return "", err } data, err := syscall.Mmap(int(f.Fd()), 0, int(stat.Size()), syscall.PROT_READ, syscall.MAP_SHARED) if err != nil { return "", err } defer syscall.Munmap(data) for i := len(data) - 1; i >= 0; i-- { if data[i] == '\n' { lines-- } if lines < 0 { return string(data[i+1 : len(data)]), nil } } return string(data), nil } func SetSize(fd int, width int, height int) (err error) { var dimensions [4]uint16 dimensions[0] = uint16(height) dimensions[1] = uint16(width) if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), uintptr(syscall.TIOCSWINSZ), uintptr(unsafe.Pointer(&dimensions)), 0, 0, 0); err != 0 { return err } return nil } lxd-2.0.0/shared/util_test.go000066400000000000000000000033171270277227600161310ustar00rootroot00000000000000package shared import ( "fmt" "io/ioutil" "os" "strings" "testing" ) func TestFileCopy(t *testing.T) { helloWorld := []byte("hello world\n") source, err := ioutil.TempFile("", "") if err != nil { t.Error(err) return } defer os.Remove(source.Name()) if err := WriteAll(source, helloWorld); err != nil { source.Close() t.Error(err) return } source.Close() dest, err := ioutil.TempFile("", "") defer os.Remove(dest.Name()) if err != nil { t.Error(err) return } dest.Close() if err := FileCopy(source.Name(), dest.Name()); err != nil { t.Error(err) return } dest2, err := os.Open(dest.Name()) if err != nil { t.Error(err) return } content, err := ioutil.ReadAll(dest2) if err != nil { t.Error(err) return } if string(content) != string(helloWorld) { t.Error("content mismatch: ", string(content), "!=", string(helloWorld)) return } } func TestReadLastNLines(t *testing.T) { source, err := ioutil.TempFile("", "") if err != nil { t.Error(err) return } defer os.Remove(source.Name()) for i := 0; i < 50; i++ { fmt.Fprintf(source, "%d\n", i) } lines, err := ReadLastNLines(source, 100) if err != nil { t.Error(err) return } split := strings.Split(lines, "\n") for i := 0; i < 50; i++ { if fmt.Sprintf("%d", i) != split[i] { t.Error(fmt.Sprintf("got %s expected %d", split[i], i)) return } } source.Seek(0, 0) for i := 0; i < 150; i++ { fmt.Fprintf(source, "%d\n", i) } lines, err = ReadLastNLines(source, 100) if err != nil { t.Error(err) return } split = strings.Split(lines, "\n") for i := 0; i < 100; i++ { if fmt.Sprintf("%d", i+50) != split[i] { t.Error(fmt.Sprintf("got %s expected %d", split[i], i)) return } } } lxd-2.0.0/test/000077500000000000000000000000001270277227600132735ustar00rootroot00000000000000lxd-2.0.0/test/README.md000066400000000000000000000024201270277227600145500ustar00rootroot00000000000000# How to run To run all tests, including the Go tests, run from repository root: sudo -E make check To run only the integration tests, run from the test directory: sudo -E ./main.sh # Environment variables Name | Default | Description :-- | :--- | :---------- LXD\_BACKEND | dir | What backend to test against (btrfs, dir, lvm or zfs) LXD\_CONCURRENT | 0 | Run concurency tests, very CPU intensive LXD\_DEBUG | 0 | Run lxd, lxc and the shell in debug mode (very verbose) LXD\_INSPECT | 0 | Don't teardown the test environment on failure LXD\_LOGS | "" | Path to a directory to copy all the LXD logs to LXD\_OFFLINE | 0 | Skip anything that requires network access LXD\_TEST\_IMAGE | "" (busybox test image) | Path to an image tarball to use instead of the default busybox image LXD\_TMPFS | 0 | Sets up a tmpfs for the whole testsuite to run on (fast but needs memory) lxd-2.0.0/test/backends/000077500000000000000000000000001270277227600150455ustar00rootroot00000000000000lxd-2.0.0/test/backends/btrfs.sh000066400000000000000000000012701270277227600165210ustar00rootroot00000000000000#!/bin/sh btrfs_setup() { local LXD_DIR LXD_DIR=$1 echo "==> Setting up btrfs backend in ${LXD_DIR}" if ! which btrfs >/dev/null 2>&1; then echo "Couldn't find the btrfs binary"; false fi truncate -s 100G "${TEST_DIR}/$(basename "${LXD_DIR}").btrfs" mkfs.btrfs "${TEST_DIR}/$(basename "${LXD_DIR}").btrfs" mount -o loop "${TEST_DIR}/$(basename "${LXD_DIR}").btrfs" "${LXD_DIR}" } btrfs_configure() { local LXD_DIR LXD_DIR=$1 echo "==> Configuring btrfs backend in ${LXD_DIR}" } btrfs_teardown() { local LXD_DIR LXD_DIR=$1 echo "==> Tearing down btrfs backend in ${LXD_DIR}" umount -l "${LXD_DIR}" rm -f "${TEST_DIR}/$(basename "${LXD_DIR}").btrfs" } lxd-2.0.0/test/backends/dir.sh000066400000000000000000000011421270277227600161550ustar00rootroot00000000000000#!/bin/sh # Nothing need be done for the dir backed, but we still need some functions. # This file can also serve as a skel file for what needs to be done to # implement a new backend. # Any necessary backend-specific setup dir_setup() { local LXD_DIR LXD_DIR=$1 echo "==> Setting up directory backend in ${LXD_DIR}" } # Do the API voodoo necessary to configure LXD to use this backend dir_configure() { local LXD_DIR LXD_DIR=$1 echo "==> Configuring directory backend in ${LXD_DIR}" } dir_teardown() { local LXD_DIR LXD_DIR=$1 echo "==> Tearing down directory backend in ${LXD_DIR}" } lxd-2.0.0/test/backends/lvm.sh000066400000000000000000000026731270277227600162070ustar00rootroot00000000000000#!/bin/sh lvm_setup() { local LXD_DIR LXD_DIR=$1 echo "==> Setting up lvm backend in ${LXD_DIR}" if ! which lvm >/dev/null 2>&1; then echo "Couldn't find the lvm binary"; false fi truncate -s 4G "${TEST_DIR}/$(basename "${LXD_DIR}").lvm" pvloopdev=$(losetup --show -f "${TEST_DIR}/$(basename "${LXD_DIR}").lvm") if [ ! -e "${pvloopdev}" ]; then echo "failed to setup loop" false fi echo "${pvloopdev}" > "${TEST_DIR}/$(basename "${LXD_DIR}").lvm.vg" pvcreate "${pvloopdev}" vgcreate "lxdtest-$(basename "${LXD_DIR}")" "${pvloopdev}" } lvm_configure() { local LXD_DIR LXD_DIR=$1 echo "==> Configuring lvm backend in ${LXD_DIR}" lxc config set storage.lvm_volume_size "10Mib" lxc config set storage.lvm_vg_name "lxdtest-$(basename "${LXD_DIR}")" } lvm_teardown() { local LXD_DIR LXD_DIR=$1 echo "==> Tearing down lvm backend in ${LXD_DIR}" SUCCESS=0 # shellcheck disable=SC2034 for i in $(seq 10); do vgremove -f "lxdtest-$(basename "${LXD_DIR}")" >/dev/null 2>&1 || true pvremove -f "$(cat "${TEST_DIR}/$(basename "${LXD_DIR}").lvm.vg")" >/dev/null 2>&1 || true if losetup -d "$(cat "${TEST_DIR}/$(basename "${LXD_DIR}").lvm.vg")"; then SUCCESS=1 break fi sleep 0.5 done if [ "${SUCCESS}" = "0" ]; then echo "Failed to tear down LVM" false fi rm -f "${TEST_DIR}/$(basename "${LXD_DIR}").lvm" rm -f "${TEST_DIR}/$(basename "${LXD_DIR}").lvm.vg" } lxd-2.0.0/test/backends/zfs.sh000066400000000000000000000021661270277227600162100ustar00rootroot00000000000000#!/bin/sh zfs_setup() { local LXD_DIR LXD_DIR=$1 echo "==> Setting up ZFS backend in ${LXD_DIR}" if ! which zfs >/dev/null 2>&1; then echo "Couldn't find zfs binary"; false fi truncate -s 100G "${LXD_DIR}/zfspool" # prefix lxdtest- here, as zfs pools must start with a letter, but tempdir # won't necessarily generate one that does. zpool create "lxdtest-$(basename "${LXD_DIR}")" "${LXD_DIR}/zfspool" -m none } zfs_configure() { local LXD_DIR LXD_DIR=$1 echo "==> Configuring ZFS backend in ${LXD_DIR}" lxc config set storage.zfs_pool_name "lxdtest-$(basename "${LXD_DIR}")" } zfs_teardown() { local LXD_DIR LXD_DIR=$1 echo "==> Tearing down ZFS backend in ${LXD_DIR}" # Wait up to 5s for zpool destroy to succeed SUCCESS=0 # shellcheck disable=SC2034 for i in $(seq 10); do zpool destroy -f "lxdtest-$(basename "${LXD_DIR}")" >/dev/null 2>&1 || true if ! zpool list -o name -H | grep -q "^lxdtest-$(basename "${LXD_DIR}")"; then SUCCESS=1 break fi sleep 0.5 done if [ "${SUCCESS}" = "0" ]; then echo "Failed to destroy the zpool" false fi } lxd-2.0.0/test/deps/000077500000000000000000000000001270277227600142265ustar00rootroot00000000000000lxd-2.0.0/test/deps/devlxd-client.go000066400000000000000000000030001270277227600173100ustar00rootroot00000000000000/* * An example of how to use lxd's golang /dev/lxd client. This is intended to * be run from inside a container. */ package main import ( "encoding/json" "fmt" "io/ioutil" "net" "net/http" "os" ) type DevLxdDialer struct { Path string } func (d DevLxdDialer) DevLxdDial(network, path string) (net.Conn, error) { addr, err := net.ResolveUnixAddr("unix", d.Path) if err != nil { return nil, err } conn, err := net.DialUnix("unix", nil, addr) if err != nil { return nil, err } return conn, err } var DevLxdTransport = &http.Transport{ Dial: DevLxdDialer{"/dev/lxd/sock"}.DevLxdDial, } func main() { c := http.Client{Transport: DevLxdTransport} raw, err := c.Get("http://meshuggah-rocks/") if err != nil { fmt.Println(err) os.Exit(1) } if raw.StatusCode != http.StatusOK { fmt.Println("http error", raw.StatusCode) result, err := ioutil.ReadAll(raw.Body) if err == nil { fmt.Println(string(result)) } os.Exit(1) } result := []string{} if err := json.NewDecoder(raw.Body).Decode(&result); err != nil { fmt.Println("err decoding response", err) os.Exit(1) } if result[0] != "/1.0" { fmt.Println("unknown response", result) os.Exit(1) } if len(os.Args) > 1 { raw, err := c.Get(fmt.Sprintf("http://meshuggah-rocks/1.0/config/%s", os.Args[1])) if err != nil { fmt.Println(err) os.Exit(1) } value, err := ioutil.ReadAll(raw.Body) if err != nil { fmt.Println(err) os.Exit(1) } fmt.Println(string(value)) } else { fmt.Println("/dev/lxd ok") } } lxd-2.0.0/test/deps/import-busybox000077500000000000000000000274751270277227600171760ustar00rootroot00000000000000#!/usr/bin/env python3 import argparse import atexit import hashlib import http.client import io import json import os import shutil import socket import subprocess import sys import tarfile import tempfile import uuid class FriendlyParser(argparse.ArgumentParser): def error(self, message): sys.stderr.write('\nerror: %s\n' % message) self.print_help() sys.exit(2) def find_on_path(command): """Is command on the executable search path?""" if 'PATH' not in os.environ: return False path = os.environ['PATH'] for element in path.split(os.pathsep): if not element: continue filename = os.path.join(element, command) if os.path.isfile(filename) and os.access(filename, os.X_OK): return True return False class UnixHTTPConnection(http.client.HTTPConnection): def __init__(self, path): http.client.HTTPConnection.__init__(self, 'localhost') self.path = path def connect(self): sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) sock.connect(self.path) self.sock = sock class LXD(object): workdir = None def __init__(self, path): self.lxd = UnixHTTPConnection(path) # Create our workdir self.workdir = tempfile.mkdtemp() atexit.register(self.cleanup) def cleanup(self): if self.workdir: shutil.rmtree(self.workdir) def rest_call(self, path, data=None, method="GET", headers={}): if method == "GET" and data: self.lxd.request( method, "%s?%s" % "&".join(["%s=%s" % (key, value) for key, value in data.items()]), headers) else: self.lxd.request(method, path, data, headers) r = self.lxd.getresponse() d = json.loads(r.read().decode("utf-8")) return r.status, d def aliases_create(self, name, target): data = json.dumps({"target": target, "name": name}) status, data = self.rest_call("/1.0/images/aliases", data, "POST") if status != 200: raise Exception("Failed to create alias: %s" % name) def aliases_remove(self, name): status, data = self.rest_call("/1.0/images/aliases/%s" % name, method="DELETE") if status != 200: raise Exception("Failed to remove alias: %s" % name) def aliases_list(self): status, data = self.rest_call("/1.0/images/aliases") return [alias.split("/1.0/images/aliases/")[-1] for alias in data['metadata']] def images_list(self, recursive=False): if recursive: status, data = self.rest_call("/1.0/images?recursion=1") return data['metadata'] else: status, data = self.rest_call("/1.0/images") return [image.split("/1.0/images/")[-1] for image in data['metadata']] def images_upload(self, path, filename, public): headers = {} if public: headers['X-LXD-public'] = "1" if isinstance(path, str): headers['Content-Type'] = "application/octet-stream" status, data = self.rest_call("/1.0/images", open(path, "rb"), "POST", headers) else: meta_path, rootfs_path = path boundary = str(uuid.uuid1()) upload_path = os.path.join(self.workdir, "upload") body = open(upload_path, "wb+") for name, path in [("metadata", meta_path), ("rootfs", rootfs_path)]: filename = os.path.basename(path) body.write(bytes("--%s\r\n" % boundary, "utf-8")) body.write(bytes("Content-Disposition: form-data; " "name=%s; filename=%s\r\n" % (name, filename), "utf-8")) body.write(b"Content-Type: application/octet-stream\r\n") body.write(b"\r\n") with open(path, "rb") as fd: shutil.copyfileobj(fd, body) body.write(b"\r\n") body.write(bytes("--%s--\r\n" % boundary, "utf-8")) body.write(b"\r\n") body.close() headers['Content-Type'] = "multipart/form-data; boundary=%s" \ % boundary status, data = self.rest_call("/1.0/images", open(upload_path, "rb"), "POST", headers) if status != 202: raise Exception("Failed to upload the image: %s" % status) status, data = self.rest_call(data['operation'] + "/wait", "", "GET", {}) if status != 200: raise Exception("Failed to query the operation: %s" % status) if data['status_code'] != 200: raise Exception("Failed to import the image: %s" % data['metadata']) return data['metadata']['metadata'] class Busybox(object): workdir = None def __init__(self): # Create our workdir self.workdir = tempfile.mkdtemp() atexit.register(self.cleanup) def cleanup(self): if self.workdir: shutil.rmtree(self.workdir) def create_tarball(self, split=False): xz = "pxz" if find_on_path("pxz") else "xz" destination_tar = os.path.join(self.workdir, "busybox.tar") target_tarball = tarfile.open(destination_tar, "w:") if split: destination_tar_rootfs = os.path.join(self.workdir, "busybox.rootfs.tar") target_tarball_rootfs = tarfile.open(destination_tar_rootfs, "w:") metadata = {'architecture': os.uname()[4], 'creation_date': int(os.stat("/bin/busybox").st_ctime), 'properties': { 'os': "Busybox", 'architecture': os.uname()[4], 'description': "Busybox %s" % os.uname()[4], 'name': "busybox-%s" % os.uname()[4] }, } # Add busybox with open("/bin/busybox", "rb") as fd: busybox_file = tarfile.TarInfo() busybox_file.size = os.stat("/bin/busybox").st_size busybox_file.mode = 0o755 if split: busybox_file.name = "bin/busybox" target_tarball_rootfs.addfile(busybox_file, fd) else: busybox_file.name = "rootfs/bin/busybox" target_tarball.addfile(busybox_file, fd) # Add symlinks busybox = subprocess.Popen(["/bin/busybox", "--list-full"], stdout=subprocess.PIPE, universal_newlines=True) busybox.wait() for path in busybox.stdout.read().split("\n"): if not path.strip(): continue symlink_file = tarfile.TarInfo() symlink_file.type = tarfile.SYMTYPE symlink_file.linkname = "/bin/busybox" if split: symlink_file.name = "%s" % path.strip() target_tarball_rootfs.addfile(symlink_file) else: symlink_file.name = "rootfs/%s" % path.strip() target_tarball.addfile(symlink_file) # Add directories for path in ("dev", "mnt", "proc", "root", "sys", "tmp"): directory_file = tarfile.TarInfo() directory_file.type = tarfile.DIRTYPE if split: directory_file.name = "%s" % path target_tarball_rootfs.addfile(directory_file) else: directory_file.name = "rootfs/%s" % path target_tarball.addfile(directory_file) # Add the metadata file metadata_yaml = json.dumps(metadata, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False).encode('utf-8') + b"\n" metadata_file = tarfile.TarInfo() metadata_file.size = len(metadata_yaml) metadata_file.name = "metadata.yaml" target_tarball.addfile(metadata_file, io.BytesIO(metadata_yaml)) # Add an /etc/inittab; this is to work around: # http://lists.busybox.net/pipermail/busybox/2015-November/083618.html # Basically, since there are some hardcoded defaults that misbehave, we # just pass an empty inittab so those aren't applied, and then busybox # doesn't spin forever. inittab = tarfile.TarInfo() inittab.size = 1 inittab.name = "/rootfs/etc/inittab" target_tarball.addfile(inittab, io.BytesIO(b"\n")) target_tarball.close() if split: target_tarball_rootfs.close() # Compress the tarball r = subprocess.call([xz, "-9", destination_tar]) if r: raise Exception("Failed to compress: %s" % destination_tar) if split: r = subprocess.call([xz, "-9", destination_tar_rootfs]) if r: raise Exception("Failed to compress: %s" % destination_tar_rootfs) return destination_tar + ".xz", destination_tar_rootfs + ".xz" else: return destination_tar + ".xz" if __name__ == "__main__": if "LXD_DIR" in os.environ: lxd_socket = os.path.join(os.environ['LXD_DIR'], "unix.socket") else: lxd_socket = "/var/lib/lxd/unix.socket" if not os.path.exists(lxd_socket): print("LXD isn't running.") sys.exit(1) lxd = LXD(lxd_socket) def setup_alias(aliases, fingerprint): existing = lxd.aliases_list() for alias in aliases: if alias in existing: lxd.aliases_remove(alias) lxd.aliases_create(alias, fingerprint) print("Setup alias: %s" % alias) def import_busybox(parser, args): busybox = Busybox() if args.split: meta_path, rootfs_path = busybox.create_tarball(split=True) with open(meta_path, "rb") as meta_fd: with open(rootfs_path, "rb") as rootfs_fd: fingerprint = hashlib.sha256(meta_fd.read() + rootfs_fd.read()).hexdigest() if fingerprint in lxd.images_list(): parser.exit(1, "This image is already in the store.\n") r = lxd.images_upload((meta_path, rootfs_path), meta_path.split("/")[-1], args.public) print("Image imported as: %s" % r['fingerprint']) else: path = busybox.create_tarball() with open(path, "rb") as fd: fingerprint = hashlib.sha256(fd.read()).hexdigest() if fingerprint in lxd.images_list(): parser.exit(1, "This image is already in the store.\n") r = lxd.images_upload(path, path.split("/")[-1], args.public) print("Image imported as: %s" % r['fingerprint']) setup_alias(args.alias, fingerprint) parser = FriendlyParser(description="Import a busybox image") parser.add_argument("--alias", action="append", default=[], help="Aliases for the image") parser.add_argument("--public", action="store_true", default=False, help="Make the image public") parser.add_argument("--split", action="store_true", default=False, help="Whether to create a split image") parser.set_defaults(func=import_busybox) # Call the function args = parser.parse_args() try: args.func(parser, args) except Exception as e: parser.error(e) lxd-2.0.0/test/deps/schema1.sql000066400000000000000000000031001270277227600162620ustar00rootroot00000000000000-- Database schema version 1 as taken from febb96e8164fbd189698da77383c26ce68b9762a CREATE TABLE certificates ( id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, fingerprint VARCHAR(255) NOT NULL, type INTEGER NOT NULL, name VARCHAR(255) NOT NULL, certificate TEXT NOT NULL, UNIQUE (fingerprint) ); CREATE TABLE containers ( id INTEGER primary key AUTOINCREMENT NOT NULL, name VARCHAR(255) NOT NULL, architecture INTEGER NOT NULL, type INTEGER NOT NULL, UNIQUE (name) ); CREATE TABLE containers_config ( id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, container_id INTEGER NOT NULL, key VARCHAR(255) NOT NULL, value TEXT, FOREIGN KEY (container_id) REFERENCES containers (id), UNIQUE (container_id, key) ); CREATE TABLE images ( id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, fingerprint VARCHAR(255) NOT NULL, filename VARCHAR(255) NOT NULL, size INTEGER NOT NULL, public INTEGER NOT NULL DEFAULT 0, architecture INTEGER NOT NULL, creation_date DATETIME, expiry_date DATETIME, upload_date DATETIME NOT NULL, UNIQUE (fingerprint) ); CREATE TABLE images_properties ( id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, image_id INTEGER NOT NULL, type INTEGER NOT NULL, key VARCHAR(255) NOT NULL, value TEXT, FOREIGN KEY (image_id) REFERENCES images (id) ); CREATE TABLE schema ( id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, version INTEGER NOT NULL, updated_at DATETIME NOT NULL, UNIQUE (version) ); INSERT INTO schema (version, updated_at) values (1, "now"); lxd-2.0.0/test/deps/server.crt000066400000000000000000000040321270277227600162450ustar00rootroot00000000000000-----BEGIN CERTIFICATE----- MIIFzjCCA7igAwIBAgIRAKnCQRdpkZ86oXYOd9hGrPgwCwYJKoZIhvcNAQELMB4x HDAaBgNVBAoTE2xpbnV4Y29udGFpbmVycy5vcmcwHhcNMTUwNzE1MDQ1NjQ0WhcN MjUwNzEyMDQ1NjQ0WjAeMRwwGgYDVQQKExNsaW51eGNvbnRhaW5lcnMub3JnMIIC IjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAyViJkCzoxa1NYilXqGJog6xz lSm4xt8KIzayc0JdB9VxEdIVdJqUzBAUtyCS4KZ9MbPmMEOX9NbBASL0tRK58/7K Scq99Kj4XbVMLU1P/y5aW0ymnF0OpKbG6unmgAI2k/duRlbYHvGRdhlswpKl0Yst l8i2kXOK0Rxcz90FewcEXGSnIYW21sz8YpBLfIZqOx6XEV36mOdi3MLrhUSAhXDw Pay33Y7NonCQUBtiO7BT938cqI14FJrWdKon1UnODtzONcVBLTWtoe7D41+mx7EE Taq5OPxBSe0DD6KQcPOZ7ZSJEhIqVKMvzLyiOJpyShmhm4OuGNoAG6jAuSij/9Kc aLU4IitcrvFOuAo8M9OpiY9ZCR7Gb/qaPAXPAxE7Ci3f9DDNKXtPXDjhj3YG01+h fNXMW3kCkMImn0A/+mZUMdCL87GWN2AN3Do5qaIc5XVEt1gp+LVqJeMoZ/lAeZWT IbzcnkneOzE25m+bjw3r3WlR26amhyrWNwjGzRkgfEpw336kniX/GmwaCNgdNk+g 5aIbVxIHO0DbgkDBtdljR3VOic4djW/LtUIYIQ2egnPPyRR3fcFI+x5EQdVQYUXf jpGIwovUDyG0Lkam2tpdeEXvLMZr8+Lhzu+H6vUFSj3cz6gcw/Xepw40FOkYdAI9 LYB6nwpZLTVaOqZCJ2ECAwEAAaOCAQkwggEFMA4GA1UdDwEB/wQEAwIAoDATBgNV HSUEDDAKBggrBgEFBQcDATAMBgNVHRMBAf8EAjAAMIHPBgNVHREEgccwgcSCCVVi dW50dVByb4IRMTAuMTY3LjE2MC4xODMvMjSCHzIwMDE6MTVjMDo2NzM1OmVlMDA6 OmU6ZTMxMy8xMjiCKWZkNTc6Yzg3ZDpmMWVlOmVlMDA6MjFkOjdkZmY6ZmUwOToz NzUzLzY0gikyMDAxOjE1YzA6NjczNTplZTAwOjIxZDo3ZGZmOmZlMDk6Mzc1My82 NIIbZmU4MDo6MjFkOjdkZmY6ZmUwOTozNzUzLzY0ghAxOTIuMTY4LjEyMi4xLzI0 MAsGCSqGSIb3DQEBCwOCAgEAmcJUSBH7cLw3auEEV1KewtdqY1ARVB/pafAtbe9F 7ZKBbxUcS7cP3P1hRs5FH1bH44bIJKHxckctNUPqvC+MpXSryKinQ5KvGPNjGdlW 6EPlQr23btizC6hRdQ6RjEkCnQxhyTLmQ9n78nt47hjA96rFAhCUyfPdv9dI4Zux bBTJekhCx5taamQKoxr7tql4Y2TchVlwASZvOfar8I0GxBRFT8w9IjckOSLoT9/s OhlvXpeoxxFT7OHwqXEXdRUvw/8MGBo6JDnw+J/NGDBw3Z0goebG4FMT//xGSHia czl3A0M0flk4/45L7N6vctwSqi+NxVaJRKeiYPZyzOO9K/d+No+WVBPwKmyP8icQ b7FGTelPJOUolC6kmoyM+vyaNUoU4nz6lgOSHAtuqGNDWZWuX/gqzZw77hzDIgkN qisOHZWPVlG/iUh1JBkbglBaPeaa3zf0XwSdgwwf4v8Z+YtEiRqkuFgQY70eQKI/ CIkj1p0iW5IBEsEAGUGklz4ZwqJwH3lQIqDBzIgHe3EP4cXaYsx6oYhPSDdHLPv4 HMZhl05DP75CEkEWRD0AIaL7SHdyuYUmCZ2zdrMI7TEDrAqcUuPbYpHcdJ2wnYmi 2G8XHJibfu4PCpIm1J8kPL8rqpdgW3moKR8Mp0HJQOH4tSBr1Ep7xNLP1wg6PIe+ p7U= -----END CERTIFICATE----- lxd-2.0.0/test/deps/server.key000066400000000000000000000062531270277227600162540ustar00rootroot00000000000000-----BEGIN RSA PRIVATE KEY----- MIIJKAIBAAKCAgEAyViJkCzoxa1NYilXqGJog6xzlSm4xt8KIzayc0JdB9VxEdIV dJqUzBAUtyCS4KZ9MbPmMEOX9NbBASL0tRK58/7KScq99Kj4XbVMLU1P/y5aW0ym nF0OpKbG6unmgAI2k/duRlbYHvGRdhlswpKl0Ystl8i2kXOK0Rxcz90FewcEXGSn IYW21sz8YpBLfIZqOx6XEV36mOdi3MLrhUSAhXDwPay33Y7NonCQUBtiO7BT938c qI14FJrWdKon1UnODtzONcVBLTWtoe7D41+mx7EETaq5OPxBSe0DD6KQcPOZ7ZSJ EhIqVKMvzLyiOJpyShmhm4OuGNoAG6jAuSij/9KcaLU4IitcrvFOuAo8M9OpiY9Z CR7Gb/qaPAXPAxE7Ci3f9DDNKXtPXDjhj3YG01+hfNXMW3kCkMImn0A/+mZUMdCL 87GWN2AN3Do5qaIc5XVEt1gp+LVqJeMoZ/lAeZWTIbzcnkneOzE25m+bjw3r3WlR 26amhyrWNwjGzRkgfEpw336kniX/GmwaCNgdNk+g5aIbVxIHO0DbgkDBtdljR3VO ic4djW/LtUIYIQ2egnPPyRR3fcFI+x5EQdVQYUXfjpGIwovUDyG0Lkam2tpdeEXv LMZr8+Lhzu+H6vUFSj3cz6gcw/Xepw40FOkYdAI9LYB6nwpZLTVaOqZCJ2ECAwEA AQKCAgBCe8GwoaOa4kaTCyOurg/kqqTftA8XW751MjJqbJdbZtcXE0+SWRiY6RZu AYt+MntUVhrEBQ3AAsloHqq+v5g3QQJ6qz9d8g1Qo/SrYMPxdtTPINhC+VdEdu1n 1CQQUKrE4QbAoxxp20o0vOB0vweR0WsUm2ntTUGhGsRqvoh4vzBpcbLeFtDwzG7p /MtwKtIZA1jOm0GMC5tRWet67cuiRFCPjOCJgAXWhWShjuk43FhdeNN1tIDaDOaT Tzwn6V7o+W/9wUxsKTVUKwrzoTno5kKNgrn2XxUP2/sOxpb7NPS2xj0cgnMHz3qR GBhYqGbkoOID/88U1acDew1oFktQL24yd8/cvooh7KLN3k5oSKjpKmGAKaMMwsSv ccRSM9EkTtgTANLpSFiVF738drZw7UXUsvVTCF8WHhMtGD50XOahR02D1kZnpqpe SdxJ9qFNEeozk6w56cTerJNz4od18/gQtNADcPI6WE+8NBrqYjN/X4CBNS76IEtp 5ddGbi6+4HgO5B0pU87f2bZH4BwR8XJ07wdMRyXXhmnKcnirkyqUtgHmLF3LZnGX +Fph5KmhBGs/ZovBvnBI2nREsMfNvzffK7x3hyFXv6J+XxILk4i3LkgKLJFC+RY0 sjWNQB5tHuA1dbq3AtsbfJcTK764kSaUsq0JoqPQgiSuiNoCIQKCAQEA1Fk4SR5I H1QHlXeQ/k1sg6B5H0uosPAnAQxjuI8SvYkty+b4diP+CJIS4IphgLIItROORUFE bOi6pj2D2oK04J55fhlJaE8LQs7i90nFXT4B09Ut4oBYGCz5aE/wAUxUanaq1dxj K17y+ejlqh7yKTwupHOvIm4ddDwU1U5H9J/Cyywvp5fznVIGMJynVk7zriXYM6aC tioNCbOTHwQxjYEaG3AwymXaI6sNwdNiAzgq6M7v43GF3IOj8SYK2VhVdLqLJPnL 6G5OqMRxxQtxOcSctFOuicu+Jq/KVWJGDaERQZJloHcBJCtO34ONswGJqC/PGoU+ Ny/BOaZdLQDIpwKCAQEA8rxOKaLuOWEi4MDJuAgQYqpO9JxY0h3yN1YrspBuGezR 4Lzdh0vUh9Jr4npV723gGwA7r8AcqIPZvSk8MmcYVuwoxz9VWYeNP8P6cRc3bDO8 shnSvFxV32gKTEH8fOH3/BlJOnbn62tebSFHnGxyh2WPsRbzAMOKj9Q3Yq6ad3DD 6rJhtopIedC3AWc3aVeO2FHPC+Lza0PhUVsHf5X7Bg+zQlHaaEXB0lysruXkDlU9 WdW+Ajvo0enhOROgEa7QBC74NsKZF4KJGMGTaglydRtVYbqfx4QbfgDU5h2zaUnB lRINZvKNYGRXDN944ymynE9bo4xfOERbWc68GFaItwKCAQBCY+qvIaKW+OSuHIXe nEJTHPcBi9wgBdWMBF2hNEo9rAf/eiUweqxP7autPFajsAX85zJSAMft7Q1+MDlr NfZrS+DcRfenfx8cMibP/eaQ8nQL0NjZuhrQ5C7OKD/3h+/UoWlkF9WBl9wLun8j oy0/KyvCCtE0yIy47Jfu4NyqZNC4SQZVNbLa+uwogrHm0CRrzDU+YM75OUh+QgC7 b8o2XajV70ux3ApJoI9ajEZWj1cLFrf1umaJvTaijKxTq8R8DF64nsjb0LETHugb HSq3TvtXfdpSBrtayRdPfrw8QqFsiOLxOoPG1SuBwlWpI8/wH5J2zjXXdzzIU3VK PrZ9AoIBAQDazTjbuT1pxZCN7donJEW42nHPdvttc4b5sJg1HpHQlrNdFIHPyl/q iperD8FU0MM5M42Zz99FW4yzQW88s8ex2rCrYgCKcnC1cO/YbygLRduq4zIdjlHt zrexo6132K0TtqtWowZNJHx6fIwziWH3gGn1JI2pO5o0KgQ+1MryLVi8v0zrIV1R SP0dq6+8Kivd/GhY+5uWLhr1nct1i3k6Ln7Uojnw0ihzegxCn4FiFh32U4AyPVSR m3PkYjdgmSZzDu+5VNJw6b6w7RT3eUqOGzRsorASRZgOjatbPpyRpOV1fU9NZAhi QjBhrzMl+VlCIxqkowzWCHAb1QmiGqajAoIBAGYKD5h7jTgPFKFlMViTg8LoMcQl 9vbpmWkB+WdY5xXOwO0hO99rFDmLx6elsmYjdpq8zJkOFTnSB2o3IpenxZltNMsI +aDlZWxDxokTxr6gbQPPrjePT1oON0/6sLEYkDOln8H1P9jmLPqTrET0DxCMgE5D NE9TAEuUKVhRTWy6FSdP58hUimyVnlbnvbGOh2tviNO+TK/H7k0WjRg57Sz9XTHO q36ob5TEsQngkTATEoksE9xhXFxtmTm/nu/26wN2Py49LSwu2aAYTfX/KhQKklNX P/tP5//z+hGeba8/xv8YhEr7vhbnlBdwp0wHJj5g7nHAbYfo9ELbXSON8wc= -----END RSA PRIVATE KEY----- lxd-2.0.0/test/extras/000077500000000000000000000000001270277227600146015ustar00rootroot00000000000000lxd-2.0.0/test/extras/speedtest_create.sh000077500000000000000000000014101270277227600204570ustar00rootroot00000000000000#!/bin/bash MYDIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) CIMAGE="testimage" CNAME="speedtest" count=${1} if [ "x${count}" == "x" ]; then echo "USAGE: ${0} 10" echo "This creates 10 busybox containers" exit 1 fi if [ "x${2}" != "xnotime" ]; then time ${0} ${count} notime exit 0 fi ${MYDIR}/deps/import-busybox --alias busybox PIDS="" for c in $(seq 1 $count); do lxc init busybox "${CNAME}${c}" 2>&1 & PIDS="$PIDS $!" done for pid in $PIDS; do wait $pid done echo -e "\nlxc list: All shutdown" time lxc list 1>/dev/null PIDS="" for c in $(seq 1 $count); do lxc start "${CNAME}${c}" 2>&1 & PIDS="$PIDS $!" done for pid in $PIDS; do wait $pid done echo -e "\nlxc list: All started" time lxc list 1>/dev/null echo -e "\nRun completed" lxd-2.0.0/test/extras/speedtest_delete.sh000077500000000000000000000007231270277227600204640ustar00rootroot00000000000000#!/bin/bash MYDIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) CIMAGE="testimage" CNAME="speedtest" count=${1} if [ "x${count}" == "x" ]; then echo "USAGE: ${0} 10" echo "This deletes 10 busybox containers" exit 1 fi if [ "x${2}" != "xnotime" ]; then time ${0} ${count} notime exit 0 fi PIDS="" for c in $(seq 1 $count); do lxc delete "${CNAME}${c}" 2>&1 & PIDS="$PIDS $!" done for pid in $PIDS; do wait $pid done echo -e "\nRun completed" lxd-2.0.0/test/extras/stresstest.sh000077500000000000000000000114631270277227600173700ustar00rootroot00000000000000#!/bin/bash export PATH=$GOPATH/bin:$PATH # /tmp isn't moutned exec on most systems, so we can't actually start # containers that are created there. export SRC_DIR=$(pwd) export LXD_DIR=$(mktemp -d -p $(pwd)) chmod 777 "${LXD_DIR}" export LXD_CONF=$(mktemp -d) export LXD_FUIDMAP_DIR=${LXD_DIR}/fuidmap mkdir -p ${LXD_FUIDMAP_DIR} BASEURL=https://127.0.0.1:18443 RESULT=failure set -e if [ -n "$LXD_DEBUG" ]; then set -x debug=--debug fi echo "==> Running the LXD testsuite" BASEURL=https://127.0.0.1:18443 my_curl() { curl -k -s --cert "${LXD_CONF}/client.crt" --key "${LXD_CONF}/client.key" $@ } wait_for() { op=$($@ | jq -r .operation) my_curl $BASEURL$op/wait } lxc() { INJECTED=0 CMD="$(which lxc)" for arg in $@; do if [ "$arg" = "--" ]; then INJECTED=1 CMD="$CMD $debug" CMD="$CMD --" else CMD="$CMD \"$arg\"" fi done if [ "$INJECTED" = "0" ]; then CMD="$CMD $debug" fi eval "$CMD" } cleanup() { read -p "Tests Completed ($RESULT): hit enter to continue" x echo "==> Cleaning up" # Try to stop all the containers my_curl "$BASEURL/1.0/containers" | jq -r .metadata[] 2>/dev/null | while read -r line; do wait_for my_curl -X PUT "$BASEURL$line/state" -d "{\"action\":\"stop\",\"force\":true}" done # kill the lxds which share our pgrp as parent mygrp=`awk '{ print $5 }' /proc/self/stat` for p in `pidof lxd`; do pgrp=`awk '{ print $5 }' /proc/$p/stat` if [ "$pgrp" = "$mygrp" ]; then do_kill_lxd $p fi done # Apparently we need to wait a while for everything to die sleep 3 rm -Rf ${LXD_DIR} rm -Rf ${LXD_CONF} echo "" echo "" echo "==> Test result: $RESULT" } trap cleanup EXIT HUP INT TERM if [ -z "`which lxc`" ]; then echo "==> Couldn't find lxc" && false fi spawn_lxd() { # LXD_DIR is local here because since `lxc` is actually a function, it # overwrites the environment and we would lose LXD_DIR's value otherwise. local LXD_DIR addr=$1 lxddir=$2 shift shift echo "==> Spawning lxd on $addr in $lxddir" LXD_DIR=$lxddir lxd ${DEBUG} $extraargs $* 2>&1 > $lxddir/lxd.log & echo "==> Confirming lxd on $addr is responsive" alive=0 while [ $alive -eq 0 ]; do [ -e "${lxddir}/unix.socket" ] && LXD_DIR=$lxddir lxc finger && alive=1 sleep 1s done echo "==> Binding to network" LXD_DIR=$lxddir lxc config set core.https_address $addr echo "==> Setting trust password" LXD_DIR=$lxddir lxc config set core.trust_password foo } spawn_lxd 127.0.0.1:18443 $LXD_DIR ## tests go here if [ ! -e "$LXD_TEST_IMAGE" ]; then echo "Please define LXD_TEST_IMAGE" false fi lxc image import $LXD_TEST_IMAGE --alias busybox lxc image list lxc list NUMCREATES=5 createthread() { echo "createthread: I am $$" for i in `seq 1 $NUMCREATES`; do echo "createthread: starting loop $i out of $NUMCREATES" declare -a pids for j in `seq 1 20`; do lxc launch busybox b.$i.$j & pids[$j]=$! done for j in `seq 1 20`; do # ignore errors if the task has already exited wait ${pids[$j]} 2>/dev/null || true done echo "createthread: deleting..." for j in `seq 1 20`; do lxc delete b.$i.$j & pids[$j]=$! done for j in `seq 1 20`; do # ignore errors if the task has already exited wait ${pids[$j]} 2>/dev/null || true done done exit 0 } listthread() { echo "listthread: I am $$" while [ 1 ]; do lxc list sleep 2s done exit 0 } configthread() { echo "configthread: I am $$" for i in `seq 1 20`; do lxc profile create p$i lxc profile set p$i limits.memory 100MB lxc profile delete p$i done exit 0 } disturbthread() { echo "disturbthread: I am $$" while [ 1 ]; do lxc profile create empty lxc init busybox disturb1 lxc profile apply disturb1 empty lxc start disturb1 lxc exec disturb1 -- ps -ef lxc stop disturb1 --force lxc delete disturb1 lxc profile delete empty done exit 0 } echo "Starting create thread" createthread 2>&1 | tee $LXD_DIR/createthread.out & p1=$! echo "starting the disturb thread" disturbthread 2>&1 | tee $LXD_DIR/disturbthread.out & pdisturb=$! echo "Starting list thread" listthread 2>&1 | tee $LXD_DIR/listthread.out & p2=$! echo "Starting config thread" configthread 2>&1 | tee $LXD_DIR/configthread.out & p3=$! # wait for listthread to finish wait $p1 # and configthread, it should be quick wait $p3 echo "The creation loop is done, killing the list and disturb threads" kill $p2 wait $p2 || true kill $pdisturb wait $pdisturb || true RESULT=success lxd-2.0.0/test/lxd-benchmark/000077500000000000000000000000001270277227600160125ustar00rootroot00000000000000lxd-2.0.0/test/lxd-benchmark/main.go000066400000000000000000000177151270277227600173000ustar00rootroot00000000000000package main import ( "fmt" "io/ioutil" "os" "strings" "sync" "time" "github.com/lxc/lxd" "github.com/lxc/lxd/shared" "github.com/lxc/lxd/shared/gnuflag" ) var argCount = gnuflag.Int("count", 100, "Number of containers to create") var argParallel = gnuflag.Int("parallel", -1, "Number of threads to use") var argImage = gnuflag.String("image", "ubuntu:", "Image to use for the test") var argPrivileged = gnuflag.Bool("privileged", false, "Use privileged containers") var argFreeze = gnuflag.Bool("freeze", false, "Freeze the container right after start") func main() { err := run(os.Args) if err != nil { fmt.Fprintf(os.Stderr, "error: %s\n", err) os.Exit(1) } os.Exit(0) } func run(args []string) error { // Parse command line gnuflag.Parse(true) if len(os.Args) == 1 || !shared.StringInSlice(os.Args[1], []string{"spawn", "delete"}) { fmt.Printf("Usage: %s spawn [--count=COUNT] [--image=IMAGE] [--privileged=BOOL] [--parallel=COUNT]\n", os.Args[0]) fmt.Printf(" %s delete [--parallel=COUNT]\n\n", os.Args[0]) gnuflag.Usage() fmt.Printf("\n") return fmt.Errorf("An action (spawn or delete) must be passed.") } // Connect to LXD c, err := lxd.NewClient(&lxd.DefaultConfig, "local") if err != nil { return err } switch os.Args[1] { case "spawn": return spawnContainers(c, *argCount, *argImage, *argPrivileged) case "delete": return deleteContainers(c) } return nil } func logf(format string, args ...interface{}) { fmt.Printf(fmt.Sprintf("[%s] %s\n", time.Now().Format(time.StampMilli), format), args...) } func spawnContainers(c *lxd.Client, count int, image string, privileged bool) error { batch := *argParallel if batch < 1 { // Detect the number of parallel actions cpus, err := ioutil.ReadDir("/sys/bus/cpu/devices") if err != nil { return err } batch = len(cpus) } batches := count / batch remainder := count % batch // Print the test header st, err := c.ServerStatus() if err != nil { return err } privilegedStr := "unprivileged" if privileged { privilegedStr = "privileged" } mode := "normal startup" if *argFreeze { mode = "start and freeze" } fmt.Printf("Test environment:\n") fmt.Printf(" Server backend: %s\n", st.Environment.Server) fmt.Printf(" Server version: %s\n", st.Environment.ServerVersion) fmt.Printf(" Kernel: %s\n", st.Environment.Kernel) fmt.Printf(" Kernel architecture: %s\n", st.Environment.KernelArchitecture) fmt.Printf(" Kernel version: %s\n", st.Environment.KernelVersion) fmt.Printf(" Storage backend: %s\n", st.Environment.Storage) fmt.Printf(" Storage version: %s\n", st.Environment.StorageVersion) fmt.Printf(" Container backend: %s\n", st.Environment.Driver) fmt.Printf(" Container version: %s\n", st.Environment.DriverVersion) fmt.Printf("\n") fmt.Printf("Test variables:\n") fmt.Printf(" Container count: %d\n", count) fmt.Printf(" Container mode: %s\n", privilegedStr) fmt.Printf(" Startup mode: %s\n", mode) fmt.Printf(" Image: %s\n", image) fmt.Printf(" Batches: %d\n", batches) fmt.Printf(" Batch size: %d\n", batch) fmt.Printf(" Remainder: %d\n", remainder) fmt.Printf("\n") // Pre-load the image var fingerprint string if strings.Contains(image, ":") { var remote string remote, fingerprint = lxd.DefaultConfig.ParseRemoteAndContainer(image) if fingerprint == "" { fingerprint = "default" } d, err := lxd.NewClient(&lxd.DefaultConfig, remote) if err != nil { return err } target := d.GetAlias(fingerprint) if target != "" { fingerprint = target } _, err = c.GetImageInfo(fingerprint) if err != nil { logf("Importing image into local store: %s", fingerprint) err := d.CopyImage(fingerprint, c, false, nil, false, false, nil) if err != nil { return err } } else { logf("Found image in local store: %s", fingerprint) } } else { fingerprint = image logf("Found image in local store: %s", fingerprint) } // Start the containers spawnedCount := 0 nameFormat := "benchmark-%." + fmt.Sprintf("%d", len(fmt.Sprintf("%d", count))) + "d" wgBatch := sync.WaitGroup{} nextStat := batch startContainer := func(name string) { defer wgBatch.Done() // Configure config := map[string]string{} if privileged { config["security.privileged"] = "true" } config["user.lxd-benchmark"] = "true" // Create resp, err := c.Init(name, "local", fingerprint, nil, config, false) if err != nil { logf(fmt.Sprintf("Failed to spawn container '%s': %s", name, err)) return } err = c.WaitForSuccess(resp.Operation) if err != nil { logf(fmt.Sprintf("Failed to spawn container '%s': %s", name, err)) return } // Start resp, err = c.Action(name, "start", -1, false, false) if err != nil { logf(fmt.Sprintf("Failed to spawn container '%s': %s", name, err)) return } err = c.WaitForSuccess(resp.Operation) if err != nil { logf(fmt.Sprintf("Failed to spawn container '%s': %s", name, err)) return } // Freeze if *argFreeze { resp, err = c.Action(name, "freeze", -1, false, false) if err != nil { logf(fmt.Sprintf("Failed to spawn container '%s': %s", name, err)) return } err = c.WaitForSuccess(resp.Operation) if err != nil { logf(fmt.Sprintf("Failed to spawn container '%s': %s", name, err)) return } } } logf("Starting the test") timeStart := time.Now() for i := 0; i < batches; i++ { for j := 0; j < batch; j++ { spawnedCount = spawnedCount + 1 name := fmt.Sprintf(nameFormat, spawnedCount) wgBatch.Add(1) go startContainer(name) } wgBatch.Wait() if spawnedCount >= nextStat { interval := time.Since(timeStart).Seconds() logf("Started %d containers in %.3fs (%.3f/s)", spawnedCount, interval, float64(spawnedCount)/interval) nextStat = nextStat * 2 } } for k := 0; k < remainder; k++ { spawnedCount = spawnedCount + 1 name := fmt.Sprintf(nameFormat, spawnedCount) wgBatch.Add(1) go startContainer(name) } wgBatch.Wait() logf("Test completed in %.3fs", time.Since(timeStart).Seconds()) return nil } func deleteContainers(c *lxd.Client) error { batch := *argParallel if batch < 1 { // Detect the number of parallel actions cpus, err := ioutil.ReadDir("/sys/bus/cpu/devices") if err != nil { return err } batch = len(cpus) } // List all the containers allContainers, err := c.ListContainers() if err != nil { return err } containers := []shared.ContainerInfo{} for _, container := range allContainers { if container.Config["user.lxd-benchmark"] != "true" { continue } containers = append(containers, container) } // Delete them all count := len(containers) logf("%d containers to delete", count) batches := count / batch deletedCount := 0 wgBatch := sync.WaitGroup{} nextStat := batch deleteContainer := func(ct shared.ContainerInfo) { defer wgBatch.Done() // Stop if ct.IsActive() { resp, err := c.Action(ct.Name, "stop", -1, true, false) if err != nil { logf("Failed to delete container: %s", ct.Name) return } err = c.WaitForSuccess(resp.Operation) if err != nil { logf("Failed to delete container: %s", ct.Name) return } } // Delete resp, err := c.Delete(ct.Name) if err != nil { logf("Failed to delete container: %s", ct.Name) return } err = c.WaitForSuccess(resp.Operation) if err != nil { logf("Failed to delete container: %s", ct.Name) return } } logf("Starting the cleanup") timeStart := time.Now() for i := 0; i < batches; i++ { for j := 0; j < batch; j++ { wgBatch.Add(1) go deleteContainer(containers[deletedCount]) deletedCount = deletedCount + 1 } wgBatch.Wait() if deletedCount >= nextStat { interval := time.Since(timeStart).Seconds() logf("Deleted %d containers in %.3fs (%.3f/s)", deletedCount, interval, float64(deletedCount)/interval) nextStat = nextStat * 2 } } for k := deletedCount; k < count; k++ { wgBatch.Add(1) go deleteContainer(containers[deletedCount]) deletedCount = deletedCount + 1 } wgBatch.Wait() logf("Cleanup completed") return nil } lxd-2.0.0/test/main.sh000077500000000000000000000262011270277227600145570ustar00rootroot00000000000000#!/bin/sh -eu [ -n "${GOPATH:-}" ] && export "PATH=${GOPATH}/bin:${PATH}" # Don't translate lxc output for parsing in it in tests. export "LC_ALL=C" if [ -n "${LXD_DEBUG:-}" ]; then set -x DEBUG="--debug" fi echo "==> Checking for dependencies" for dep in lxd lxc curl jq git xgettext sqlite3 msgmerge msgfmt shuf setfacl uuidgen pyflakes3 pep8 shellcheck; do which "${dep}" >/dev/null 2>&1 || (echo "Missing dependency: ${dep}" >&2 && exit 1) done if [ "${USER:-'root'}" != "root" ]; then echo "The testsuite must be run as root." >&2 exit 1 fi if [ -n "${LXD_LOGS:-}" ] && [ ! -d "${LXD_LOGS}" ]; then echo "Your LXD_LOGS path doesn't exist: ${LXD_LOGS}" exit 1 fi # Helper functions local_tcp_port() { while :; do port=$(shuf -i 10000-32768 -n 1) nc -l 127.0.0.1 "${port}" >/dev/null 2>&1 & pid=$! kill "${pid}" >/dev/null 2>&1 || continue wait "${pid}" || true echo "${port}" return done } # import all the backends for backend in backends/*.sh; do . "${backend}" done if [ -z "${LXD_BACKEND:-}" ]; then LXD_BACKEND=dir fi spawn_lxd() { set +x # LXD_DIR is local here because since $(lxc) is actually a function, it # overwrites the environment and we would lose LXD_DIR's value otherwise. local LXD_DIR lxddir=${1} shift # Copy pre generated Certs cp deps/server.crt "${lxddir}" cp deps/server.key "${lxddir}" # setup storage "$LXD_BACKEND"_setup "${lxddir}" echo "==> Spawning lxd in ${lxddir}" # shellcheck disable=SC2086 LXD_DIR="${lxddir}" lxd --logfile "${lxddir}/lxd.log" ${DEBUG-} "$@" 2>&1 & LXD_PID=$! echo "${LXD_PID}" > "${lxddir}/lxd.pid" echo "${lxddir}" >> "${TEST_DIR}/daemons" echo "==> Spawned LXD (PID is ${LXD_PID})" echo "==> Confirming lxd is responsive" LXD_DIR="${lxddir}" lxd waitready --timeout=300 echo "==> Binding to network" # shellcheck disable=SC2034 for i in $(seq 10); do addr="127.0.0.1:$(local_tcp_port)" LXD_DIR="${lxddir}" lxc config set core.https_address "${addr}" || continue echo "${addr}" > "${lxddir}/lxd.addr" echo "==> Bound to ${addr}" break done echo "==> Setting trust password" LXD_DIR="${lxddir}" lxc config set core.trust_password foo if [ -n "${LXD_DEBUG:-}" ]; then set -x fi echo "==> Configuring storage backend" "$LXD_BACKEND"_configure "${lxddir}" } lxc() { LXC_LOCAL=1 lxc_remote "$@" RET=$? unset LXC_LOCAL return ${RET} } lxc_remote() { set +x injected=0 cmd=$(which lxc) # shellcheck disable=SC2048,SC2068 for arg in $@; do if [ "${arg}" = "--" ]; then injected=1 cmd="${cmd} ${DEBUG:-}" [ -n "${LXC_LOCAL}" ] && cmd="${cmd} --force-local" cmd="${cmd} --" elif [ "${arg}" = "--force-local" ]; then continue else cmd="${cmd} \"${arg}\"" fi done if [ "${injected}" = "0" ]; then cmd="${cmd} ${DEBUG-}" fi if [ -n "${LXD_DEBUG:-}" ]; then set -x fi eval "${cmd}" } my_curl() { curl -k -s --cert "${LXD_CONF}/client.crt" --key "${LXD_CONF}/client.key" "$@" } wait_for() { addr=${1} shift op=$("$@" | jq -r .operation) my_curl "https://${addr}${op}/wait" } ensure_has_localhost_remote() { addr=${1} if ! lxc remote list | grep -q "localhost"; then lxc remote add localhost "https://${addr}" --accept-certificate --password foo fi } ensure_import_testimage() { if ! lxc image alias list | grep -q "^| testimage\s*|.*$"; then if [ -e "${LXD_TEST_IMAGE:-}" ]; then lxc image import "${LXD_TEST_IMAGE}" --alias testimage else deps/import-busybox --alias testimage fi fi } check_empty() { if [ "$(find "${1}" 2> /dev/null | wc -l)" -gt "1" ]; then echo "${1} is not empty, content:" find "${1}" false fi } check_empty_table() { if [ -n "$(sqlite3 "${1}" "SELECT * FROM ${2};")" ]; then echo "DB table ${2} is not empty, content:" sqlite3 "${1}" "SELECT * FROM ${2};" false fi } kill_lxd() { # LXD_DIR is local here because since $(lxc) is actually a function, it # overwrites the environment and we would lose LXD_DIR's value otherwise. local LXD_DIR daemon_dir=${1} LXD_DIR=${daemon_dir} daemon_pid=$(cat "${daemon_dir}/lxd.pid") echo "==> Killing LXD at ${daemon_dir}" if [ -e "${daemon_dir}/unix.socket" ]; then # Delete all containers echo "==> Deleting all containers" for container in $(lxc list --force-local | tail -n+3 | grep "^| " | cut -d' ' -f2); do lxc delete "${container}" --force-local -f || true done # Delete all images echo "==> Deleting all images" for image in $(lxc image list --force-local | tail -n+3 | grep "^| " | cut -d'|' -f3 | sed "s/^ //g"); do lxc image delete "${image}" --force-local || true done echo "==> Checking for locked DB tables" for table in $(echo .tables | sqlite3 "${daemon_dir}/lxd.db"); do echo "SELECT * FROM ${table};" | sqlite3 "${daemon_dir}/lxd.db" >/dev/null done # Kill the daemon lxd shutdown || kill -9 "${daemon_pid}" 2>/dev/null || true # Cleanup shmounts (needed due to the forceful kill) find "${daemon_dir}" -name shmounts -exec "umount" "-l" "{}" \; >/dev/null 2>&1 || true fi if [ -n "${LXD_LOGS:-}" ]; then echo "==> Copying the logs" mkdir -p "${LXD_LOGS}/${daemon_pid}" cp -R "${daemon_dir}/logs/" "${LXD_LOGS}/${daemon_pid}/" cp "${daemon_dir}/lxd.log" "${LXD_LOGS}/${daemon_pid}/" fi echo "==> Checking for leftover files" rm -f "${daemon_dir}/containers/lxc-monitord.log" rm -f "${daemon_dir}/security/apparmor/cache/.features" check_empty "${daemon_dir}/containers/" check_empty "${daemon_dir}/devices/" check_empty "${daemon_dir}/images/" # FIXME: Once container logging rework is done, uncomment # check_empty "${daemon_dir}/logs/" check_empty "${daemon_dir}/security/apparmor/cache/" check_empty "${daemon_dir}/security/apparmor/profiles/" check_empty "${daemon_dir}/security/seccomp/" check_empty "${daemon_dir}/shmounts/" check_empty "${daemon_dir}/snapshots/" echo "==> Checking for leftover DB entries" check_empty_table "${daemon_dir}/lxd.db" "containers" check_empty_table "${daemon_dir}/lxd.db" "containers_config" check_empty_table "${daemon_dir}/lxd.db" "containers_devices" check_empty_table "${daemon_dir}/lxd.db" "containers_devices_config" check_empty_table "${daemon_dir}/lxd.db" "containers_profiles" check_empty_table "${daemon_dir}/lxd.db" "images" check_empty_table "${daemon_dir}/lxd.db" "images_aliases" check_empty_table "${daemon_dir}/lxd.db" "images_properties" # teardown storage "$LXD_BACKEND"_teardown "${daemon_dir}" # Wipe the daemon directory wipe "${daemon_dir}" # Remove the daemon from the list sed "\|^${daemon_dir}|d" -i "${TEST_DIR}/daemons" } cleanup() { set +e # Allow for inspection if [ -n "${LXD_INSPECT:-}" ]; then echo "==> Test result: ${TEST_RESULT}" if [ "${TEST_RESULT}" != "success" ]; then echo "failed test: ${TEST_CURRENT}" fi # shellcheck disable=SC2086 printf "To poke around, use:\n LXD_DIR=%s LXD_CONF=%s sudo -E %s/bin/lxc COMMAND\n" "${LXD_DIR}" "${LXD_CONF}" ${GOPATH:-} echo "Tests Completed (${TEST_RESULT}): hit enter to continue" # shellcheck disable=SC2034 read nothing fi echo "==> Cleaning up" # Kill all the LXD instances while read daemon_dir; do kill_lxd "${daemon_dir}" done < "${TEST_DIR}/daemons" # Wipe the test environment wipe "${TEST_DIR}" echo "" echo "" echo "==> Test result: ${TEST_RESULT}" if [ "${TEST_RESULT}" != "success" ]; then echo "failed test: ${TEST_CURRENT}" fi } wipe() { if which btrfs >/dev/null 2>&1; then rm -Rf "${1}" 2>/dev/null || true if [ -d "${1}" ]; then find "${1}" | tac | xargs btrfs subvolume delete >/dev/null 2>&1 || true fi fi # shellcheck disable=SC2009 ps aux | grep lxc-monitord | grep "${1}" | awk '{print $2}' | while read pid; do kill -9 "${pid}" done if [ -f "${TEST_DIR}/loops" ]; then while read line; do losetup -d "${line}" || true done < "${TEST_DIR}/loops" fi if mountpoint -q "${1}"; then umount "${1}" fi rm -Rf "${1}" } # Must be set before cleanup() TEST_CURRENT=setup TEST_RESULT=failure trap cleanup EXIT HUP INT TERM # Import all the testsuites for suite in suites/*.sh; do . "${suite}" done # Setup test directory TEST_DIR=$(mktemp -d -p "$(pwd)" tmp.XXX) chmod +x "${TEST_DIR}" if [ -n "${LXD_TMPFS:-}" ]; then mount -t tmpfs tmpfs "${TEST_DIR}" -o mode=0751 fi LXD_CONF=$(mktemp -d -p "${TEST_DIR}" XXX) export LXD_CONF # Setup the first LXD LXD_DIR=$(mktemp -d -p "${TEST_DIR}" XXX) export LXD_DIR chmod +x "${LXD_DIR}" spawn_lxd "${LXD_DIR}" LXD_ADDR=$(cat "${LXD_DIR}/lxd.addr") export LXD_ADDR # Setup the second LXD LXD2_DIR=$(mktemp -d -p "${TEST_DIR}" XXX) chmod +x "${LXD2_DIR}" spawn_lxd "${LXD2_DIR}" LXD2_ADDR=$(cat "${LXD2_DIR}/lxd.addr") export LXD2_ADDR # allow for running a specific set of tests if [ "$#" -gt 0 ]; then "test_${1}" TEST_RESULT=success exit fi echo "==> TEST: doing static analysis of commits" TEST_CURRENT=test_static_analysis test_static_analysis echo "==> TEST: checking dependencies" TEST_CURRENT=test_check_deps test_check_deps echo "==> TEST: Database schema update" TEST_CURRENT=test_database_update test_database_update echo "==> TEST: lxc remote url" TEST_CURRENT=test_remote_url test_remote_url echo "==> TEST: lxc remote administration" TEST_CURRENT=test_remote_admin test_remote_admin echo "==> TEST: basic usage" TEST_CURRENT=test_basic_usage test_basic_usage echo "==> TEST: images (and cached image expiry)" TEST_CURRENT=test_image_expiry test_image_expiry if [ -n "${LXD_CONCURRENT:-}" ]; then echo "==> TEST: concurrent exec" TEST_CURRENT=test_concurrent_exec test_concurrent_exec echo "==> TEST: concurrent startup" TEST_CURRENT=test_concurrent test_concurrent fi echo "==> TEST: lxc remote usage" TEST_CURRENT=test_remote_usage test_remote_usage echo "==> TEST: snapshots" TEST_CURRENT=test_snapshots test_snapshots echo "==> TEST: snapshot restore" TEST_CURRENT=test_snap_restore test_snap_restore echo "==> TEST: profiles, devices and configuration" TEST_CURRENT=test_config_profiles test_config_profiles echo "==> TEST: server config" TEST_CURRENT=test_server_config test_server_config echo "==> TEST: filemanip" TEST_CURRENT=test_filemanip test_filemanip echo "==> TEST: devlxd" TEST_CURRENT=test_devlxd test_devlxd if which fuidshift >/dev/null 2>&1; then echo "==> TEST: uidshift" TEST_CURRENT=test_fuidshift test_fuidshift else echo "==> SKIP: fuidshift (binary missing)" fi echo "==> TEST: migration" TEST_CURRENT=test_migration test_migration curversion=$(dpkg -s lxc | awk '/^Version/ { print $2 }') if dpkg --compare-versions "${curversion}" gt 1.1.2-0ubuntu3; then echo "==> TEST: fdleak" TEST_CURRENT=test_fdleak test_fdleak else # We temporarily skip the fdleak test because a bug in lxc is # known to make it # fail without lxc commit # 858377e: # logs: introduce a thread-local 'current' lxc_config (v2) echo "==> SKIPPING TEST: fdleak" fi echo "==> TEST: cpu profiling" TEST_CURRENT=test_cpu_profiling test_cpu_profiling echo "==> TEST: memory profiling" TEST_CURRENT=test_mem_profiling test_mem_profiling TEST_RESULT=success lxd-2.0.0/test/suites/000077500000000000000000000000001270277227600146075ustar00rootroot00000000000000lxd-2.0.0/test/suites/basic.sh000066400000000000000000000226521270277227600162330ustar00rootroot00000000000000#!/bin/sh gen_third_cert() { [ -f "${LXD_CONF}/client3.crt" ] && return mv "${LXD_CONF}/client.crt" "${LXD_CONF}/client.crt.bak" mv "${LXD_CONF}/client.key" "${LXD_CONF}/client.key.bak" lxc_remote list > /dev/null 2>&1 mv "${LXD_CONF}/client.crt" "${LXD_CONF}/client3.crt" mv "${LXD_CONF}/client.key" "${LXD_CONF}/client3.key" mv "${LXD_CONF}/client.crt.bak" "${LXD_CONF}/client.crt" mv "${LXD_CONF}/client.key.bak" "${LXD_CONF}/client.key" } test_basic_usage() { ensure_import_testimage ensure_has_localhost_remote "${LXD_ADDR}" # Test image export sum=$(lxc image info testimage | grep ^Fingerprint | cut -d' ' -f2) lxc image export testimage "${LXD_DIR}/" if [ -e "${LXD_TEST_IMAGE:-}" ]; then name=$(basename "${LXD_TEST_IMAGE}") else name=${sum}.tar.xz fi [ "${sum}" = "$(sha256sum "${LXD_DIR}/${name}" | cut -d' ' -f1)" ] # Test an alias with slashes lxc image show "${sum}" lxc image alias create a/b/ "${sum}" lxc image alias delete a/b/ # Test alias list filtering lxc image alias create foo "${sum}" lxc image alias create bar "${sum}" lxc image alias list local: | grep -q foo lxc image alias list local: | grep -q bar lxc image alias list local: foo | grep -q -v bar lxc image alias list local: "${sum}" | grep -q foo lxc image alias list local: non-existent | grep -q -v non-existent lxc image alias delete foo lxc image alias delete bar # Test image delete lxc image delete testimage # test GET /1.0, since the client always puts to /1.0/ my_curl -f -X GET "https://${LXD_ADDR}/1.0" my_curl -f -X GET "https://${LXD_ADDR}/1.0/containers" # Re-import the image mv "${LXD_DIR}/${name}" "${LXD_DIR}/testimage.tar.xz" lxc image import "${LXD_DIR}/testimage.tar.xz" --alias testimage rm "${LXD_DIR}/testimage.tar.xz" # Test filename for image export (should be "out") lxc image export testimage "${LXD_DIR}/" [ "${sum}" = "$(sha256sum "${LXD_DIR}/testimage.tar.xz" | cut -d' ' -f1)" ] rm "${LXD_DIR}/testimage.tar.xz" # Test container creation lxc init testimage foo lxc list | grep foo | grep STOPPED lxc list fo | grep foo | grep STOPPED # Test list json format lxc list --format json | jq '.[]|select(.name="foo")' | grep '"name": "foo"' # Test container rename lxc move foo bar lxc list | grep -v foo lxc list | grep bar # Test container copy lxc copy bar foo lxc delete foo # gen untrusted cert gen_third_cert # don't allow requests without a cert to get trusted data curl -k -s -X GET "https://${LXD_ADDR}/1.0/containers/foo" | grep 403 # Test unprivileged container publish lxc publish bar --alias=foo-image prop1=val1 lxc image show foo-image | grep val1 curl -k -s --cert "${LXD_CONF}/client3.crt" --key "${LXD_CONF}/client3.key" -X GET "https://${LXD_ADDR}/1.0/images" | grep "/1.0/images/" && false lxc image delete foo-image # Test privileged container publish lxc profile create priv lxc profile set priv security.privileged true lxc init testimage barpriv -p default -p priv lxc publish barpriv --alias=foo-image prop1=val1 lxc image show foo-image | grep val1 curl -k -s --cert "${LXD_CONF}/client3.crt" --key "${LXD_CONF}/client3.key" -X GET "https://${LXD_ADDR}/1.0/images" | grep "/1.0/images/" && false lxc image delete foo-image lxc delete barpriv lxc profile delete priv # Test that containers without metadata.yaml are published successfully. # Note that this quick hack won't work for LVM, since it doesn't always mount # the container's filesystem. That's ok though: the logic we're trying to # test here is independent of storage backend, so running it for just one # backend (or all non-lvm backends) is enough. if [ "${LXD_BACKEND}" != "lvm" ]; then lxc init testimage nometadata rm "${LXD_DIR}/containers/nometadata/metadata.yaml" lxc publish nometadata --alias=nometadata-image lxc image delete nometadata-image lxc delete nometadata fi # Test public images lxc publish --public bar --alias=foo-image2 curl -k -s --cert "${LXD_CONF}/client3.crt" --key "${LXD_CONF}/client3.key" -X GET "https://${LXD_ADDR}/1.0/images" | grep "/1.0/images/" lxc image delete foo-image2 # Test invalid container names ! lxc init testimage -abc ! lxc init testimage abc- ! lxc init testimage 1234 ! lxc init testimage 12test ! lxc init testimage a_b_c ! lxc init testimage aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa # Test snapshot publish lxc snapshot bar lxc publish bar/snap0 --alias foo lxc init foo bar2 lxc list | grep bar2 lxc delete bar2 lxc image delete foo # test basic alias support printf "aliases:\n ls: list" >> "${LXD_CONF}/config.yml" lxc ls # Delete the bar container we've used for several tests lxc delete bar # lxc delete should also delete all snapshots of bar [ ! -d "${LXD_DIR}/snapshots/bar" ] # Test randomly named container creation lxc init testimage RDNAME=$(lxc list | tail -n2 | grep ^\| | awk '{print $2}') lxc delete "${RDNAME}" # Test "nonetype" container creation wait_for "${LXD_ADDR}" my_curl -X POST "https://${LXD_ADDR}/1.0/containers" \ -d "{\"name\":\"nonetype\",\"source\":{\"type\":\"none\"}}" lxc delete nonetype # Test "nonetype" container creation with an LXC config wait_for "${LXD_ADDR}" my_curl -X POST "https://${LXD_ADDR}/1.0/containers" \ -d "{\"name\":\"configtest\",\"config\":{\"raw.lxc\":\"lxc.hook.clone=/bin/true\"},\"source\":{\"type\":\"none\"}}" [ "$(my_curl "https://${LXD_ADDR}/1.0/containers/configtest" | jq -r .metadata.config[\"raw.lxc\"])" = "lxc.hook.clone=/bin/true" ] lxc delete configtest # Test socket activation LXD_ACTIVATION_DIR=$(mktemp -d -p "${TEST_DIR}" XXX) spawn_lxd "${LXD_ACTIVATION_DIR}" ( set -e # shellcheck disable=SC2030 LXD_DIR=${LXD_ACTIVATION_DIR} ensure_import_testimage lxd activateifneeded --debug 2>&1 | grep -q "Daemon has core.https_address set, activating..." lxc config unset core.https_address --force-local lxd activateifneeded --debug 2>&1 | grep -q -v "activating..." lxc init testimage autostart --force-local lxd activateifneeded --debug 2>&1 | grep -q -v "activating..." lxc config set autostart boot.autostart true --force-local lxd activateifneeded --debug 2>&1 | grep -q "Daemon has auto-started containers, activating..." lxc delete autostart --force-local ) # shellcheck disable=SC2031 LXD_DIR=${LXD_DIR} kill_lxd "${LXD_ACTIVATION_DIR}" # Create and start a container lxc launch testimage foo lxc list | grep foo | grep RUNNING lxc stop foo --force # stop is hanging # cycle it a few times lxc start foo mac1=$(lxc exec foo cat /sys/class/net/eth0/address) lxc stop foo --force # stop is hanging lxc start foo mac2=$(lxc exec foo cat /sys/class/net/eth0/address) if [ -n "${mac1}" ] && [ -n "${mac2}" ] && [ "${mac1}" != "${mac2}" ]; then echo "==> MAC addresses didn't match across restarts (${mac1} vs ${mac2})" false fi # check that we can set the environment lxc exec foo pwd | grep /root lxc exec --env BEST_BAND=meshuggah foo env | grep meshuggah lxc exec foo ip link show | grep eth0 # test file transfer echo abc > "${LXD_DIR}/in" lxc file push "${LXD_DIR}/in" foo/root/ lxc exec foo /bin/cat /root/in | grep abc lxc exec foo -- /bin/rm -f root/in lxc file push "${LXD_DIR}/in" foo/root/in1 lxc exec foo /bin/cat /root/in1 | grep abc lxc exec foo -- /bin/rm -f root/in1 # make sure stdin is chowned to our container root uid (Issue #590) [ -t 0 ] && [ -t 1 ] && lxc exec foo -- chown 1000:1000 /proc/self/fd/0 echo foo | lxc exec foo tee /tmp/foo # Detect regressions/hangs in exec sum=$(ps aux | tee "${LXD_DIR}/out" | lxc exec foo md5sum | cut -d' ' -f1) [ "${sum}" = "$(md5sum "${LXD_DIR}/out" | cut -d' ' -f1)" ] rm "${LXD_DIR}/out" # FIXME: make this backend agnostic if [ "${LXD_BACKEND}" = "dir" ]; then content=$(cat "${LXD_DIR}/containers/foo/rootfs/tmp/foo") [ "${content}" = "foo" ] fi lxc launch testimage deleterunning my_curl -X DELETE "https://${LXD_ADDR}/1.0/containers/deleterunning" | grep "container is running" lxc delete deleterunning -f # cleanup lxc delete foo -f # check that an apparmor profile is created for this container, that it is # unloaded on stop, and that it is deleted when the container is deleted lxc launch testimage lxd-apparmor-test aa-status | grep "lxd-lxd-apparmor-test_<${LXD_DIR}>" lxc stop lxd-apparmor-test --force ! aa-status | grep -q "lxd-lxd-apparmor-test_<${LXD_DIR}>" lxc delete lxd-apparmor-test [ ! -f "${LXD_DIR}/security/apparmor/profiles/lxd-lxd-apparmor-test" ] # make sure that privileged containers are not world-readable lxc profile create unconfined lxc profile set unconfined security.privileged true lxc init testimage foo2 -p unconfined [ "$(stat -L -c "%a" "${LXD_DIR}/containers/foo2")" = "700" ] lxc delete foo2 lxc profile delete unconfined # Ephemeral lxc launch testimage foo -e OLD_INIT=$(lxc info foo | grep ^Pid) lxc exec foo reboot REBOOTED="false" # shellcheck disable=SC2034 for i in $(seq 10); do NEW_INIT=$(lxc info foo | grep ^Pid || true) if [ -n "${NEW_INIT}" ] && [ "${OLD_INIT}" != "${NEW_INIT}" ]; then REBOOTED="true" break fi sleep 0.5 done [ "${REBOOTED}" = "true" ] # Workaround for LXC bug which causes LXD to double-start containers # on reboot sleep 2 lxc stop foo --force || true ! lxc list | grep -q foo } lxd-2.0.0/test/suites/concurrent.sh000066400000000000000000000011001270277227600173150ustar00rootroot00000000000000#!/bin/sh test_concurrent() { ensure_import_testimage spawn_container() { set -e name=concurrent-${1} lxc launch testimage "${name}" lxc info "${name}" | grep Running echo abc | lxc exec "${name}" -- cat | grep abc lxc stop "${name}" --force lxc delete "${name}" } PIDS="" for id in $(seq $(($(find /sys/bus/cpu/devices/ -type l | wc -l)*8))); do spawn_container "${id}" 2>&1 | tee "${LXD_DIR}/lxc-${id}.out" & PIDS="${PIDS} $!" done for pid in ${PIDS}; do wait "${pid}" done ! lxc list | grep -q concurrent } lxd-2.0.0/test/suites/config.sh000066400000000000000000000125571270277227600164220ustar00rootroot00000000000000#!/bin/sh ensure_removed() { bad=0 lxc exec foo -- stat /dev/ttyS0 && bad=1 if [ "${bad}" -eq 1 ]; then echo "device should have been removed; $*" false fi } dounixdevtest() { lxc start foo lxc config device add foo tty unix-char "$@" lxc exec foo -- stat /dev/ttyS0 lxc exec foo reboot lxc exec foo -- stat /dev/ttyS0 lxc restart foo --force lxc exec foo -- stat /dev/ttyS0 lxc config device remove foo tty ensure_removed "was not hot-removed" lxc exec foo reboot ensure_removed "removed device re-appeared after container reboot" lxc restart foo --force ensure_removed "removed device re-appaared after lxc reboot" lxc stop foo --force } testunixdevs() { echo "Testing passing char device /dev/ttyS0" dounixdevtest path=/dev/ttyS0 echo "Testing passing char device 4 64" dounixdevtest path=/dev/ttyS0 major=4 minor=64 } ensure_fs_unmounted() { bad=0 lxc exec foo -- stat /mnt/hello && bad=1 if [ "${bad}" -eq 1 ]; then echo "device should have been removed; $*" false fi } testloopmounts() { loopfile=$(mktemp -p "${TEST_DIR}" loop_XXX) dd if=/dev/zero of="${loopfile}" bs=1M seek=200 count=1 mkfs.ext4 -F "${loopfile}" lpath=$(losetup --show -f "${loopfile}") if [ ! -e "${lpath}" ]; then echo "failed to setup loop" false fi echo "${lpath}" >> "${TEST_DIR}/loops" mkdir -p "${TEST_DIR}/mnt" mount "${lpath}" "${TEST_DIR}/mnt" || { echo "loop mount failed"; return; } touch "${TEST_DIR}/mnt/hello" umount -l "${TEST_DIR}/mnt" lxc start foo lxc config device add foo mnt disk source="${lpath}" path=/mnt lxc exec foo stat /mnt/hello # Note - we need to add a set_running_config_item to lxc # or work around its absence somehow. Once that's done, we # can run the following two lines: #lxc exec foo reboot #lxc exec foo stat /mnt/hello lxc restart foo --force lxc exec foo stat /mnt/hello lxc config device remove foo mnt ensure_fs_unmounted "fs should have been hot-unmounted" lxc exec foo reboot ensure_fs_unmounted "removed fs re-appeared after reboot" lxc restart foo --force ensure_fs_unmounted "removed fs re-appeared after restart" lxc stop foo --force losetup -d "${lpath}" sed -i "\|^${lpath}|d" "${TEST_DIR}/loops" } test_config_profiles() { ensure_import_testimage lxc init testimage foo lxc profile list | grep default # let's check that 'lxc config profile' still works while it's deprecated lxc config profile list | grep default # setting an invalid config item should error out when setting it, not get # into the database and never let the user edit the container again. ! lxc config set foo raw.lxc "lxc.notaconfigkey = invalid" lxc profile create stdintest echo "BADCONF" | lxc profile set stdintest user.user_data - lxc profile show stdintest | grep BADCONF lxc profile delete stdintest echo "BADCONF" | lxc config set foo user.user_data - lxc config show foo | grep BADCONF lxc config unset foo user.user_data mkdir -p "${TEST_DIR}/mnt1" lxc config device add foo mnt1 disk source="${TEST_DIR}/mnt1" path=/mnt1 readonly=true lxc profile create onenic lxc profile device add onenic eth0 nic nictype=bridged parent=lxdbr0 lxc profile apply foo onenic lxc profile create unconfined lxc profile set unconfined raw.lxc "lxc.aa_profile=unconfined" lxc profile apply foo onenic,unconfined lxc config device list foo | grep mnt1 lxc config device show foo | grep "/mnt1" lxc config show foo | grep "onenic" -A1 | grep "unconfined" lxc profile list | grep onenic lxc profile device list onenic | grep eth0 lxc profile device show onenic | grep lxdbr0 # test live-adding a nic lxc start foo ! lxc config show foo | grep -q "raw.lxc" lxc config show foo --expanded | grep -q "raw.lxc" ! lxc config show foo | grep -v "volatile.eth0" | grep -q "eth0" lxc config show foo --expanded | grep -v "volatile.eth0" | grep -q "eth0" lxc config device add foo eth2 nic nictype=bridged parent=lxdbr0 name=eth10 lxc exec foo -- /sbin/ifconfig -a | grep eth0 lxc exec foo -- /sbin/ifconfig -a | grep eth10 lxc config device list foo | grep eth2 lxc config device remove foo eth2 # test live-adding a disk mkdir "${TEST_DIR}/mnt2" touch "${TEST_DIR}/mnt2/hosts" lxc config device add foo mnt2 disk source="${TEST_DIR}/mnt2" path=/mnt2 readonly=true lxc exec foo -- ls /mnt2/hosts lxc stop foo --force lxc start foo lxc exec foo -- ls /mnt2/hosts lxc config device remove foo mnt2 ! lxc exec foo -- ls /mnt2/hosts lxc stop foo --force lxc start foo ! lxc exec foo -- ls /mnt2/hosts lxc stop foo --force lxc config set foo user.prop value lxc list user.prop=value | grep foo lxc config unset foo user.prop # Test for invalid raw.lxc ! lxc config set foo raw.lxc a ! lxc profile set default raw.lxc a bad=0 lxc list user.prop=value | grep foo && bad=1 if [ "${bad}" -eq 1 ]; then echo "property unset failed" false fi bad=0 lxc config set foo user.prop 2>/dev/null && bad=1 if [ "${bad}" -eq 1 ]; then echo "property set succeded when it shouldn't have" false fi testunixdevs testloopmounts lxc delete foo lxc init testimage foo lxc profile apply foo onenic,unconfined lxc start foo lxc exec foo -- cat /proc/self/attr/current | grep unconfined lxc exec foo -- ls /sys/class/net | grep eth0 lxc stop foo --force lxc delete foo } lxd-2.0.0/test/suites/database_update.sh000066400000000000000000000017041270277227600202530ustar00rootroot00000000000000#!/bin/sh test_database_update(){ LXD_MIGRATE_DIR=$(mktemp -d -p "${TEST_DIR}" XXX) MIGRATE_DB=${LXD_MIGRATE_DIR}/lxd.db # Create the version 1 schema as the database sqlite3 "${MIGRATE_DB}" > /dev/null < deps/schema1.sql # Start an LXD demon in the tmp directory. This should start the updates. spawn_lxd "${LXD_MIGRATE_DIR}" # Assert there are enough tables. expected_tables=16 tables=$(sqlite3 "${MIGRATE_DB}" ".dump" | grep -c "CREATE TABLE") [ "${tables}" -eq "${expected_tables}" ] || { echo "FAIL: Wrong number of tables after database migration. Found: ${tables}, expected ${expected_tables}"; false; } # There should be 10 "ON DELETE CASCADE" occurences expected_cascades=11 cascades=$(sqlite3 "${MIGRATE_DB}" ".dump" | grep -c "ON DELETE CASCADE") [ "${cascades}" -eq "${expected_cascades}" ] || { echo "FAIL: Wrong number of ON DELETE CASCADE foreign keys. Found: ${cascades}, exected: ${expected_cascades}"; false; } } lxd-2.0.0/test/suites/deps.sh000066400000000000000000000001111270277227600160670ustar00rootroot00000000000000#!/bin/sh test_check_deps() { ! ldd "$(which lxc)" | grep -q liblxc } lxd-2.0.0/test/suites/devlxd.sh000066400000000000000000000006271270277227600164360ustar00rootroot00000000000000#!/bin/sh test_devlxd() { ensure_import_testimage cd "${TEST_DIR}" go build -tags netgo -a -installsuffix devlxd ../deps/devlxd-client.go cd - lxc launch testimage devlxd lxc file push "${TEST_DIR}/devlxd-client" devlxd/bin/ lxc exec devlxd chmod +x /bin/devlxd-client lxc config set devlxd user.foo bar lxc exec devlxd devlxd-client user.foo | grep bar lxc stop devlxd --force } lxd-2.0.0/test/suites/exec.sh000066400000000000000000000007041270277227600160700ustar00rootroot00000000000000#!/bin/sh test_concurrent_exec() { ensure_import_testimage name=x1 lxc launch testimage x1 lxc list ${name} | grep RUNNING exec_container() { echo "abc${1}" | lxc exec "${name}" -- cat | grep abc } PIDS="" for i in $(seq 1 50); do exec_container "${i}" > "${LXD_DIR}/exec-${i}.out" 2>&1 & PIDS="${PIDS} $!" done for pid in ${PIDS}; do wait "${pid}" done lxc stop "${name}" --force lxc delete "${name}" } lxd-2.0.0/test/suites/fdleak.sh000066400000000000000000000017011270277227600163700ustar00rootroot00000000000000#!/bin/sh test_fdleak() { LXD_FDLEAK_DIR=$(mktemp -d -p "${TEST_DIR}" XXX) chmod +x "${LXD_FDLEAK_DIR}" spawn_lxd "${LXD_FDLEAK_DIR}" pid=$(cat "${LXD_FDLEAK_DIR}/lxd.pid") beforefds=$(/bin/ls "/proc/${pid}/fd" | wc -l) ( set -e # shellcheck disable=SC2034 LXD_DIR=${LXD_FDLEAK_DIR} ensure_import_testimage for i in $(seq 5); do lxc init "testimage leaktest${i}" lxc info "leaktest${i}" lxc start "leaktest${i}" lxc exec "leaktest${i}" -- ps -ef lxc stop "leaktest${i}" --force lxc delete "leaktest${i}" done sleep 5 exit 0 ) afterfds=$(/bin/ls "/proc/${pid}/fd" | wc -l) leakedfds=$((afterfds - beforefds)) bad=0 # shellcheck disable=SC2015 [ ${leakedfds} -gt 5 ] && bad=1 || true if [ ${bad} -eq 1 ]; then echo "${leakedfds} FDS leaked" ls "/proc/${pid}/fd" -al netstat -anp 2>&1 | grep "${pid}/" false fi kill_lxd "${LXD_FDLEAK_DIR}" } lxd-2.0.0/test/suites/filemanip.sh000066400000000000000000000004301270277227600171040ustar00rootroot00000000000000#!/bin/sh test_filemanip() { ensure_import_testimage lxc launch testimage filemanip lxc exec filemanip -- ln -s /tmp/ /tmp/outside lxc file push main.sh filemanip/tmp/outside/ [ ! -f /tmp/main.sh ] lxc exec filemanip -- ls /tmp/main.sh lxc delete filemanip -f } lxd-2.0.0/test/suites/fuidshift.sh000066400000000000000000000026701270277227600171350ustar00rootroot00000000000000#!/bin/sh test_common_fuidshift() { # test some bad arguments fail=0 fuidshift > /dev/null 2>&1 && fail=1 fuidshift -t > /dev/null 2>&1 && fail=1 fuidshift /tmp -t b:0 > /dev/null 2>&1 && fail=1 fuidshift /tmp -t x:0:0:0 > /dev/null 2>&1 && fail=1 [ "${fail}" -ne 1 ] } test_nonroot_fuidshift() { test_common_fuidshift LXD_FUIDMAP_DIR=$(mktemp -d -p "${TEST_DIR}" XXX) u=$(id -u) g=$(id -g) u1=$((u+1)) g1=$((g+1)) touch "${LXD_FUIDMAP_DIR}/x1" fuidshift "${LXD_FUIDMAP_DIR}/x1" -t "u:${u}:100000:1" "g:${g}:100000:1" | tee /dev/stderr | grep "to 100000 100000" > /dev/null || fail=1 if [ "${fail}" -eq 1 ]; then echo "==> Failed to shift own uid to container root" false fi fuidshift "${LXD_FUIDMAP_DIR}/x1" -t "u:${u1}:10000:1" "g:${g1}:100000:1" | tee /dev/stderr | grep "to -1 -1" > /dev/null || fail=1 if [ "${fail}" -eq 1 ]; then echo "==> Wrongly shifted invalid uid to container root" false fi # unshift it chown 100000:100000 "${LXD_FUIDMAP_DIR}/x1" fuidshift "${LXD_FUIDMAP_DIR}/x1" -r -t "u:${u}:100000:1" "g:${g}:100000:1" | tee /dev/stderr | grep "to 0 0" > /dev/null || fail=1 if [ "${fail}" -eq 1 ]; then echo "==> Failed to unshift container root back to own uid" false fi } test_root_fuidshift() { test_nonroot_fuidshift # Todo - test ranges } test_fuidshift() { if [ "$(id -u)" -ne 0 ]; then test_nonroot_fuidshift else test_root_fuidshift fi } lxd-2.0.0/test/suites/image.sh000066400000000000000000000016561270277227600162350ustar00rootroot00000000000000#!/bin/sh test_image_expiry() { ensure_import_testimage if ! lxc_remote remote list | grep -q l1; then lxc_remote remote add l1 "${LXD_ADDR}" --accept-certificate --password foo fi if ! lxc_remote remote list | grep -q l2; then lxc_remote remote add l2 "${LXD2_ADDR}" --accept-certificate --password foo fi lxc_remote init l1:testimage l2:c1 fp=$(lxc_remote image info testimage | awk -F: '/^Fingerprint/ { print $2 }' | awk '{ print $1 }') [ ! -z "${fp}" ] fpbrief=$(echo "${fp}" | cut -c 1-10) lxc_remote image list l2: | grep -q "${fpbrief}" lxc_remote remote set-default l2 lxc_remote config set images.remote_cache_expiry 0 lxc_remote remote set-default local ! lxc_remote image list l2: | grep -q "${fpbrief}" lxc_remote delete l2:c1 # rest the default expiry lxc_remote remote set-default l2 lxc_remote config set images.remote_cache_expiry 10 lxc_remote remote set-default local } lxd-2.0.0/test/suites/migration.sh000066400000000000000000000044301270277227600171350ustar00rootroot00000000000000#!/bin/sh test_migration() { ensure_import_testimage if ! lxc_remote remote list | grep -q l1; then lxc_remote remote add l1 "${LXD_ADDR}" --accept-certificate --password foo fi if ! lxc_remote remote list | grep -q l2; then lxc_remote remote add l2 "${LXD2_ADDR}" --accept-certificate --password foo fi lxc_remote init testimage nonlive # test moving snapshots lxc_remote snapshot l1:nonlive lxc_remote move l1:nonlive l2: # FIXME: make this backend agnostic if [ "${LXD_BACKEND}" != "lvm" ]; then [ -d "${LXD2_DIR}/containers/nonlive/rootfs" ] fi [ ! -d "${LXD_DIR}/containers/nonlive" ] # FIXME: make this backend agnostic if [ "${LXD_BACKEND}" = "dir" ]; then [ -d "${LXD2_DIR}/snapshots/nonlive/snap0/rootfs/bin" ] fi lxc_remote copy l2:nonlive l1:nonlive2 [ -d "${LXD_DIR}/containers/nonlive2" ] # FIXME: make this backend agnostic if [ "${LXD_BACKEND}" != "lvm" ]; then [ -d "${LXD2_DIR}/containers/nonlive/rootfs/bin" ] fi # FIXME: make this backend agnostic if [ "${LXD_BACKEND}" = "dir" ]; then [ -d "${LXD_DIR}/snapshots/nonlive2/snap0/rootfs/bin" ] fi lxc_remote copy l1:nonlive2/snap0 l2:nonlive3 # FIXME: make this backend agnostic if [ "${LXD_BACKEND}" != "lvm" ]; then [ -d "${LXD2_DIR}/containers/nonlive3/rootfs/bin" ] fi lxc_remote copy l2:nonlive l2:nonlive2 # should have the same base image tag [ "$(lxc_remote config get l2:nonlive volatile.base_image)" = "$(lxc_remote config get l2:nonlive2 volatile.base_image)" ] # check that nonlive2 has a new addr in volatile [ "$(lxc_remote config get l2:nonlive volatile.eth0.hwaddr)" != "$(lxc_remote config get l2:nonlive2 volatile.eth0.hwaddr)" ] lxc_remote config unset l2:nonlive volatile.base_image lxc_remote copy l2:nonlive l1:nobase lxc_remote delete l1:nobase lxc_remote start l1:nonlive2 lxc_remote list l1: | grep RUNNING | grep nonlive2 lxc_remote stop l1:nonlive2 --force lxc_remote start l2:nonlive lxc_remote list l2: | grep RUNNING | grep nonlive lxc_remote stop l2:nonlive --force if ! which criu >/dev/null 2>&1; then echo "==> SKIP: live migration with CRIU (missing binary)" return fi lxc_remote launch testimage migratee lxc_remote move l1:migratee l2:migratee lxc_remote stop l2:migratee --force } lxd-2.0.0/test/suites/profiling.sh000066400000000000000000000016611270277227600171400ustar00rootroot00000000000000#!/bin/sh test_cpu_profiling() { LXD3_DIR=$(mktemp -d -p "${TEST_DIR}" XXX) chmod +x "${LXD3_DIR}" spawn_lxd "${LXD3_DIR}" --cpuprofile "${LXD3_DIR}/cpu.out" lxdpid=$(cat "${LXD3_DIR}/lxd.pid") kill -TERM "${lxdpid}" wait "${lxdpid}" || true export PPROF_TMPDIR="${TEST_DIR}/pprof" echo top5 | go tool pprof "$(which lxd)" "${LXD3_DIR}/cpu.out" echo "" kill_lxd "${LXD3_DIR}" } test_mem_profiling() { LXD4_DIR=$(mktemp -d -p "${TEST_DIR}" XXX) chmod +x "${LXD4_DIR}" spawn_lxd "${LXD4_DIR}" --memprofile "${LXD4_DIR}/mem" lxdpid=$(cat "${LXD4_DIR}/lxd.pid") if [ -e "${LXD4_DIR}/mem" ]; then false fi kill -USR1 "${lxdpid}" timeout=50 while [ "${timeout}" != "0" ]; do [ -e "${LXD4_DIR}/mem" ] && break sleep 0.1 timeout=$((timeout-1)) done export PPROF_TMPDIR="${TEST_DIR}/pprof" echo top5 | go tool pprof "$(which lxd)" "${LXD4_DIR}/mem" echo "" kill_lxd "${LXD4_DIR}" } lxd-2.0.0/test/suites/remote.sh000066400000000000000000000112351270277227600164400ustar00rootroot00000000000000#!/bin/sh gen_second_cert() { [ -f "${LXD_CONF}/client2.crt" ] && return mv "${LXD_CONF}/client.crt" "${LXD_CONF}/client.crt.bak" mv "${LXD_CONF}/client.key" "${LXD_CONF}/client.key.bak" lxc_remote list > /dev/null 2>&1 mv "${LXD_CONF}/client.crt" "${LXD_CONF}/client2.crt" mv "${LXD_CONF}/client.key" "${LXD_CONF}/client2.key" mv "${LXD_CONF}/client.crt.bak" "${LXD_CONF}/client.crt" mv "${LXD_CONF}/client.key.bak" "${LXD_CONF}/client.key" } test_remote_url() { for url in "${LXD_ADDR}" "https://${LXD_ADDR}"; do lxc_remote remote add test "${url}" --accept-certificate --password foo lxc_remote finger test: lxc_remote config trust list | grep @ | awk '{print $2}' | while read line ; do lxc_remote config trust remove "\"${line}\"" done lxc_remote remote remove test done urls="${LXD_DIR}/unix.socket unix:${LXD_DIR}/unix.socket unix://${LXD_DIR}/unix.socket" if [ -z "${LXD_OFFLINE:-}" ]; then urls="images.linuxcontainers.org https://images.linuxcontainers.org ${urls}" fi for url in ${urls}; do lxc_remote remote add test "${url}" lxc_remote finger test: lxc_remote remote remove test done } test_remote_admin() { lxc_remote remote add badpass "${LXD_ADDR}" --accept-certificate --password bad || true ! lxc_remote list badpass: lxc_remote remote add localhost "${LXD_ADDR}" --accept-certificate --password foo lxc_remote remote list | grep 'localhost' lxc_remote remote set-default localhost [ "$(lxc_remote remote get-default)" = "localhost" ] lxc_remote remote rename localhost foo lxc_remote remote list | grep 'foo' lxc_remote remote list | grep -v 'localhost' [ "$(lxc_remote remote get-default)" = "foo" ] ! lxc_remote remote remove foo lxc_remote remote set-default local lxc_remote remote remove foo # This is a test for #91, we expect this to hang asking for a password if we # tried to re-add our cert. echo y | lxc_remote remote add localhost "${LXD_ADDR}" # we just re-add our cert under a different name to test the cert # manipulation mechanism. gen_second_cert # Test for #623 lxc_remote remote add test-623 "${LXD_ADDR}" --accept-certificate --password foo # now re-add under a different alias lxc_remote config trust add "${LXD_CONF}/client2.crt" if [ "$(lxc_remote config trust list | wc -l)" -ne 7 ]; then echo "wrong number of certs" false fi # Check that we can add domains with valid certs without confirmation: # avoid default high port behind some proxies: if [ -z "${LXD_OFFLINE:-}" ]; then lxc_remote remote add images1 images.linuxcontainers.org lxc_remote remote add images2 images.linuxcontainers.org:443 fi } test_remote_usage() { lxc_remote remote add lxd2 "${LXD2_ADDR}" --accept-certificate --password foo # we need a public image on localhost lxc_remote image export localhost:testimage "${LXD_DIR}/foo.img" lxc_remote image delete localhost:testimage sum=$(sha256sum "${LXD_DIR}/foo.img" | cut -d' ' -f1) lxc_remote image import "${LXD_DIR}/foo.img" localhost: --public lxc_remote image alias create localhost:testimage "${sum}" lxc_remote image delete "lxd2:${sum}" || true lxc_remote image copy localhost:testimage lxd2: --copy-aliases --public lxc_remote image delete "localhost:${sum}" lxc_remote image copy "lxd2:${sum}" local: --copy-aliases --public lxc_remote image info localhost:testimage lxc_remote image delete "lxd2:${sum}" lxc_remote image copy "localhost:${sum}" lxd2: lxc_remote image delete "lxd2:${sum}" lxc_remote image copy "localhost:$(echo "${sum}" | colrm 3)" lxd2: lxc_remote image delete "lxd2:${sum}" # test a private image lxc_remote image copy "localhost:${sum}" lxd2: lxc_remote image delete "localhost:${sum}" lxc_remote init "lxd2:${sum}" localhost:c1 lxc_remote delete localhost:c1 lxc_remote image alias create localhost:testimage "${sum}" # test remote publish lxc_remote init testimage pub lxc_remote publish pub lxd2: --alias bar --public a=b lxc_remote image show lxd2:bar | grep -q "a: b" lxc_remote image show lxd2:bar | grep -q "public: true" ! lxc_remote image show bar lxc_remote delete pub lxc_remote image delete lxd2:bar # Double launch to test if the image downloads only once. lxc_remote init localhost:testimage lxd2:c1 & C1PID=$! lxc_remote init localhost:testimage lxd2:c2 lxc_remote delete lxd2:c2 wait "${C1PID}" lxc_remote delete lxd2:c1 # launch testimage stored on localhost as container c1 on lxd2 lxc_remote launch localhost:testimage lxd2:c1 # make sure it is running lxc_remote list lxd2: | grep c1 | grep RUNNING lxc_remote info lxd2:c1 lxc_remote stop lxd2:c1 --force lxc_remote delete lxd2:c1 } lxd-2.0.0/test/suites/serverconfig.sh000066400000000000000000000007751270277227600176500ustar00rootroot00000000000000#!/bin/sh test_server_config() { LXD_SERVERCONFIG_DIR=$(mktemp -d -p "${TEST_DIR}" XXX) spawn_lxd "${LXD_SERVERCONFIG_DIR}" lxc config set core.trust_password 123456 config=$(lxc config show) echo "${config}" | grep -q "trust_password" echo "${config}" | grep -q -v "123456" lxc config unset core.trust_password lxc config show | grep -q -v "trust_password" # test untrusted server GET my_curl -X GET "https://$(cat "${LXD_SERVERCONFIG_DIR}/lxd.addr")/1.0" | grep -v -q environment } lxd-2.0.0/test/suites/snapshots.sh000066400000000000000000000111621270277227600171660ustar00rootroot00000000000000#!/bin/sh test_snapshots() { ensure_import_testimage ensure_has_localhost_remote "${LXD_ADDR}" lxc init testimage foo lxc snapshot foo # FIXME: make this backend agnostic if [ "${LXD_BACKEND}" = "dir" ]; then [ -d "${LXD_DIR}/snapshots/foo/snap0" ] fi lxc snapshot foo # FIXME: make this backend agnostic if [ "${LXD_BACKEND}" = "dir" ]; then [ -d "${LXD_DIR}/snapshots/foo/snap1" ] fi lxc snapshot foo tester # FIXME: make this backend agnostic if [ "${LXD_BACKEND}" = "dir" ]; then [ -d "${LXD_DIR}/snapshots/foo/tester" ] fi lxc copy foo/tester foosnap1 # FIXME: make this backend agnostic if [ "${LXD_BACKEND}" != "lvm" ]; then [ -d "${LXD_DIR}/containers/foosnap1/rootfs" ] fi lxc delete foo/snap0 # FIXME: make this backend agnostic if [ "${LXD_BACKEND}" = "dir" ]; then [ ! -d "${LXD_DIR}/snapshots/foo/snap0" ] fi # no CLI for this, so we use the API directly (rename a snapshot) wait_for "${LXD_ADDR}" my_curl -X POST "https://${LXD_ADDR}/1.0/containers/foo/snapshots/tester" -d "{\"name\":\"tester2\"}" # FIXME: make this backend agnostic if [ "${LXD_BACKEND}" = "dir" ]; then [ ! -d "${LXD_DIR}/snapshots/foo/tester" ] fi lxc move foo/tester2 foo/tester-two lxc delete foo/tester-two # FIXME: make this backend agnostic if [ "${LXD_BACKEND}" = "dir" ]; then [ ! -d "${LXD_DIR}/snapshots/foo/tester-two" ] fi lxc snapshot foo namechange # FIXME: make this backend agnostic if [ "${LXD_BACKEND}" = "dir" ]; then [ -d "${LXD_DIR}/snapshots/foo/namechange" ] fi lxc move foo foople [ ! -d "${LXD_DIR}/containers/foo" ] [ -d "${LXD_DIR}/containers/foople" ] # FIXME: make this backend agnostic if [ "${LXD_BACKEND}" = "dir" ]; then [ -d "${LXD_DIR}/snapshots/foople/namechange" ] [ -d "${LXD_DIR}/snapshots/foople/namechange" ] fi lxc delete foople lxc delete foosnap1 [ ! -d "${LXD_DIR}/containers/foople" ] [ ! -d "${LXD_DIR}/containers/foosnap1" ] } test_snap_restore() { ensure_import_testimage ensure_has_localhost_remote "${LXD_ADDR}" ########################################################## # PREPARATION ########################################################## ## create some state we will check for when snapshot is restored ## prepare snap0 lxc launch testimage bar echo snap0 > state lxc file push state bar/root/state lxc file push state bar/root/file_only_in_snap0 lxc exec bar -- mkdir /root/dir_only_in_snap0 lxc exec bar -- ln -s file_only_in_snap0 /root/statelink lxc stop bar --force lxc snapshot bar snap0 ## prepare snap1 lxc start bar echo snap1 > state lxc file push state bar/root/state lxc file push state bar/root/file_only_in_snap1 lxc exec bar -- rmdir /root/dir_only_in_snap0 lxc exec bar -- rm /root/file_only_in_snap0 lxc exec bar -- rm /root/statelink lxc exec bar -- ln -s file_only_in_snap1 /root/statelink lxc exec bar -- mkdir /root/dir_only_in_snap1 lxc stop bar --force # Delete the state file we created to prevent leaking. rm state lxc config set bar limits.cpu 1 lxc snapshot bar snap1 ########################################################## if [ "${LXD_BACKEND}" != "zfs" ]; then # The problem here is that you can't `zfs rollback` to a snapshot with a # parent, which snap0 has (snap1). restore_and_compare_fs snap0 # Check container config has been restored (limits.cpu is unset) cpus=$(lxc config get bar limits.cpu) if [ -n "${cpus}" ]; then echo "==> config didn't match expected value after restore (${cpus})" false fi fi ########################################################## # test restore using full snapshot name restore_and_compare_fs snap1 # Check config value in snapshot has been restored cpus=$(lxc config get bar limits.cpu) if [ "${cpus}" != "1" ]; then echo "==> config didn't match expected value after restore (${cpus})" false fi ########################################################## # Start container and then restore snapshot to verify the running state after restore. lxc start bar if [ "${LXD_BACKEND}" != "zfs" ]; then # see comment above about snap0 restore_and_compare_fs snap0 # check container is running after restore lxc list | grep bar | grep RUNNING fi lxc stop --force bar lxc delete bar } restore_and_compare_fs() { snap=${1} echo "==> Restoring ${snap}" lxc restore bar "${snap}" # FIXME: make this backend agnostic if [ "${LXD_BACKEND}" = "dir" ]; then # Recursive diff of container FS diff -r "${LXD_DIR}/containers/bar/rootfs" "${LXD_DIR}/snapshots/bar/${snap}/rootfs" fi } lxd-2.0.0/test/suites/static_analysis.sh000066400000000000000000000033401270277227600203350ustar00rootroot00000000000000#!/bin/sh safe_pot_hash() { sed -e "/Project-Id-Version/,/Content-Transfer-Encoding/d" -e "/^#/d" "po/lxd.pot" | tee /tmp/foo | md5sum | cut -f1 -d" " } test_static_analysis() { ( set -e cd ../ # Python3 static analysis pep8 test/deps/import-busybox scripts/lxd-setup-lvm-storage pyflakes3 test/deps/import-busybox scripts/lxd-setup-lvm-storage # Shell static analysis shellcheck lxd-bridge/lxd-bridge test/main.sh test/suites/* test/backends/* # Go static analysis ## Functions starting by empty line OUT=$(grep -r "^$" -B1 . | grep "func " | grep -v "}$" || true) if [ -n "${OUT}" ]; then echo "${OUT}" false fi ## go vet, if it exists have_go_vet=1 go help vet > /dev/null 2>&1 || have_go_vet=0 if [ "${have_go_vet}" -eq 1 ]; then go vet ./... fi ## vet if which vet >/dev/null 2>&1; then vet --all . fi ## deadcode if which deadcode >/dev/null 2>&1; then for path in . lxc/ lxd/ shared/ shared/i18n shared/termios fuidshift/ lxd-bridge/lxd-bridge-proxy/; do OUT=$(deadcode ${path} 2>&1 | grep -v lxd/migrate.pb.go || true) if [ -n "${OUT}" ]; then echo "${OUT}" >&2 false fi done fi # Skip the tests which require git if ! git status; then return fi # go fmt git add -u :/ go fmt ./... git diff --exit-code # make sure the .pot is updated cp --preserve "po/lxd.pot" "po/lxd.pot.bak" hash1=$(safe_pot_hash) make i18n -s hash2=$(safe_pot_hash) mv "po/lxd.pot.bak" "po/lxd.pot" if [ "${hash1}" != "${hash2}" ]; then echo "==> Please update the .pot file in your commit (make i18n)" && false fi ) } lxd-2.0.0/dist/0000755061062106075000000000000012702772333015657 5ustar00stgraberdomain admins00000000000000lxd-2.0.0/dist/src/0000755061062106075000000000000012702772343016447 5ustar00stgraberdomain admins00000000000000lxd-2.0.0/dist/src/golang.org/0000755061062106075000000000000012702772343020504 5ustar00stgraberdomain admins00000000000000lxd-2.0.0/dist/src/golang.org/x/0000755061062106075000000000000012702772343020753 5ustar00stgraberdomain admins00000000000000lxd-2.0.0/dist/src/golang.org/x/crypto/0000755061062106075000000000000012702772344022274 5ustar00stgraberdomain admins00000000000000lxd-2.0.0/dist/src/golang.org/x/crypto/curve25519/0000755061062106075000000000000012702772344024026 5ustar00stgraberdomain admins00000000000000lxd-2.0.0/dist/src/golang.org/x/crypto/curve25519/doc.go0000644061062106075000000000202312702772344025117 0ustar00stgraberdomain admins00000000000000// Copyright 2012 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 curve25519 provides an implementation of scalar multiplication on // the elliptic curve known as curve25519. See http://cr.yp.to/ecdh.html package curve25519 // import "golang.org/x/crypto/curve25519" // basePoint is the x coordinate of the generator of the curve. var basePoint = [32]byte{9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} // ScalarMult sets dst to the product in*base where dst and base are the x // coordinates of group points and all values are in little-endian form. func ScalarMult(dst, in, base *[32]byte) { scalarMult(dst, in, base) } // ScalarBaseMult sets dst to the product in*base where dst and base are the x // coordinates of group points, base is the standard generator and all values // are in little-endian form. func ScalarBaseMult(dst, in *[32]byte) { ScalarMult(dst, in, &basePoint) } lxd-2.0.0/dist/src/golang.org/x/crypto/curve25519/square_amd64.s0000644061062106075000000000447012702772344026512 0ustar00stgraberdomain admins00000000000000// Copyright 2012 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 code was translated into a form compatible with 6a from the public // domain sources in SUPERCOP: http://bench.cr.yp.to/supercop.html // +build amd64,!gccgo,!appengine // func square(out, in *[5]uint64) TEXT ·square(SB),7,$96-16 MOVQ out+0(FP), DI MOVQ in+8(FP), SI MOVQ SP,R11 MOVQ $31,CX NOTQ CX ANDQ CX,SP ADDQ $32, SP MOVQ R11,0(SP) MOVQ R12,8(SP) MOVQ R13,16(SP) MOVQ R14,24(SP) MOVQ R15,32(SP) MOVQ BX,40(SP) MOVQ BP,48(SP) MOVQ 0(SI),AX MULQ 0(SI) MOVQ AX,CX MOVQ DX,R8 MOVQ 0(SI),AX SHLQ $1,AX MULQ 8(SI) MOVQ AX,R9 MOVQ DX,R10 MOVQ 0(SI),AX SHLQ $1,AX MULQ 16(SI) MOVQ AX,R11 MOVQ DX,R12 MOVQ 0(SI),AX SHLQ $1,AX MULQ 24(SI) MOVQ AX,R13 MOVQ DX,R14 MOVQ 0(SI),AX SHLQ $1,AX MULQ 32(SI) MOVQ AX,R15 MOVQ DX,BX MOVQ 8(SI),AX MULQ 8(SI) ADDQ AX,R11 ADCQ DX,R12 MOVQ 8(SI),AX SHLQ $1,AX MULQ 16(SI) ADDQ AX,R13 ADCQ DX,R14 MOVQ 8(SI),AX SHLQ $1,AX MULQ 24(SI) ADDQ AX,R15 ADCQ DX,BX MOVQ 8(SI),DX IMUL3Q $38,DX,AX MULQ 32(SI) ADDQ AX,CX ADCQ DX,R8 MOVQ 16(SI),AX MULQ 16(SI) ADDQ AX,R15 ADCQ DX,BX MOVQ 16(SI),DX IMUL3Q $38,DX,AX MULQ 24(SI) ADDQ AX,CX ADCQ DX,R8 MOVQ 16(SI),DX IMUL3Q $38,DX,AX MULQ 32(SI) ADDQ AX,R9 ADCQ DX,R10 MOVQ 24(SI),DX IMUL3Q $19,DX,AX MULQ 24(SI) ADDQ AX,R9 ADCQ DX,R10 MOVQ 24(SI),DX IMUL3Q $38,DX,AX MULQ 32(SI) ADDQ AX,R11 ADCQ DX,R12 MOVQ 32(SI),DX IMUL3Q $19,DX,AX MULQ 32(SI) ADDQ AX,R13 ADCQ DX,R14 MOVQ ·REDMASK51(SB),SI SHLQ $13,R8:CX ANDQ SI,CX SHLQ $13,R10:R9 ANDQ SI,R9 ADDQ R8,R9 SHLQ $13,R12:R11 ANDQ SI,R11 ADDQ R10,R11 SHLQ $13,R14:R13 ANDQ SI,R13 ADDQ R12,R13 SHLQ $13,BX:R15 ANDQ SI,R15 ADDQ R14,R15 IMUL3Q $19,BX,DX ADDQ DX,CX MOVQ CX,DX SHRQ $51,DX ADDQ R9,DX ANDQ SI,CX MOVQ DX,R8 SHRQ $51,DX ADDQ R11,DX ANDQ SI,R8 MOVQ DX,R9 SHRQ $51,DX ADDQ R13,DX ANDQ SI,R9 MOVQ DX,AX SHRQ $51,DX ADDQ R15,DX ANDQ SI,AX MOVQ DX,R10 SHRQ $51,DX IMUL3Q $19,DX,DX ADDQ DX,CX ANDQ SI,R10 MOVQ CX,0(DI) MOVQ R8,8(DI) MOVQ R9,16(DI) MOVQ AX,24(DI) MOVQ R10,32(DI) MOVQ 0(SP),R11 MOVQ 8(SP),R12 MOVQ 16(SP),R13 MOVQ 24(SP),R14 MOVQ 32(SP),R15 MOVQ 40(SP),BX MOVQ 48(SP),BP MOVQ R11,SP MOVQ DI,AX MOVQ SI,DX RET lxd-2.0.0/dist/src/golang.org/x/crypto/curve25519/cswap_amd64.s0000644061062106075000000000302012702772344026315 0ustar00stgraberdomain admins00000000000000// Copyright 2012 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 code was translated into a form compatible with 6a from the public // domain sources in SUPERCOP: http://bench.cr.yp.to/supercop.html // +build amd64,!gccgo,!appengine // func cswap(inout *[5]uint64, v uint64) TEXT ·cswap(SB),7,$0 MOVQ inout+0(FP),DI MOVQ v+8(FP),SI CMPQ SI,$1 MOVQ 0(DI),SI MOVQ 80(DI),DX MOVQ 8(DI),CX MOVQ 88(DI),R8 MOVQ SI,R9 CMOVQEQ DX,SI CMOVQEQ R9,DX MOVQ CX,R9 CMOVQEQ R8,CX CMOVQEQ R9,R8 MOVQ SI,0(DI) MOVQ DX,80(DI) MOVQ CX,8(DI) MOVQ R8,88(DI) MOVQ 16(DI),SI MOVQ 96(DI),DX MOVQ 24(DI),CX MOVQ 104(DI),R8 MOVQ SI,R9 CMOVQEQ DX,SI CMOVQEQ R9,DX MOVQ CX,R9 CMOVQEQ R8,CX CMOVQEQ R9,R8 MOVQ SI,16(DI) MOVQ DX,96(DI) MOVQ CX,24(DI) MOVQ R8,104(DI) MOVQ 32(DI),SI MOVQ 112(DI),DX MOVQ 40(DI),CX MOVQ 120(DI),R8 MOVQ SI,R9 CMOVQEQ DX,SI CMOVQEQ R9,DX MOVQ CX,R9 CMOVQEQ R8,CX CMOVQEQ R9,R8 MOVQ SI,32(DI) MOVQ DX,112(DI) MOVQ CX,40(DI) MOVQ R8,120(DI) MOVQ 48(DI),SI MOVQ 128(DI),DX MOVQ 56(DI),CX MOVQ 136(DI),R8 MOVQ SI,R9 CMOVQEQ DX,SI CMOVQEQ R9,DX MOVQ CX,R9 CMOVQEQ R8,CX CMOVQEQ R9,R8 MOVQ SI,48(DI) MOVQ DX,128(DI) MOVQ CX,56(DI) MOVQ R8,136(DI) MOVQ 64(DI),SI MOVQ 144(DI),DX MOVQ 72(DI),CX MOVQ 152(DI),R8 MOVQ SI,R9 CMOVQEQ DX,SI CMOVQEQ R9,DX MOVQ CX,R9 CMOVQEQ R8,CX CMOVQEQ R9,R8 MOVQ SI,64(DI) MOVQ DX,144(DI) MOVQ CX,72(DI) MOVQ R8,152(DI) MOVQ DI,AX MOVQ SI,DX RET lxd-2.0.0/dist/src/golang.org/x/crypto/curve25519/mul_amd64.s0000644061062106075000000000550012702772344026002 0ustar00stgraberdomain admins00000000000000// Copyright 2012 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 code was translated into a form compatible with 6a from the public // domain sources in SUPERCOP: http://bench.cr.yp.to/supercop.html // +build amd64,!gccgo,!appengine // func mul(dest, a, b *[5]uint64) TEXT ·mul(SB),0,$128-24 MOVQ dest+0(FP), DI MOVQ a+8(FP), SI MOVQ b+16(FP), DX MOVQ SP,R11 MOVQ $31,CX NOTQ CX ANDQ CX,SP ADDQ $32,SP MOVQ R11,0(SP) MOVQ R12,8(SP) MOVQ R13,16(SP) MOVQ R14,24(SP) MOVQ R15,32(SP) MOVQ BX,40(SP) MOVQ BP,48(SP) MOVQ DI,56(SP) MOVQ DX,CX MOVQ 24(SI),DX IMUL3Q $19,DX,AX MOVQ AX,64(SP) MULQ 16(CX) MOVQ AX,R8 MOVQ DX,R9 MOVQ 32(SI),DX IMUL3Q $19,DX,AX MOVQ AX,72(SP) MULQ 8(CX) ADDQ AX,R8 ADCQ DX,R9 MOVQ 0(SI),AX MULQ 0(CX) ADDQ AX,R8 ADCQ DX,R9 MOVQ 0(SI),AX MULQ 8(CX) MOVQ AX,R10 MOVQ DX,R11 MOVQ 0(SI),AX MULQ 16(CX) MOVQ AX,R12 MOVQ DX,R13 MOVQ 0(SI),AX MULQ 24(CX) MOVQ AX,R14 MOVQ DX,R15 MOVQ 0(SI),AX MULQ 32(CX) MOVQ AX,BX MOVQ DX,BP MOVQ 8(SI),AX MULQ 0(CX) ADDQ AX,R10 ADCQ DX,R11 MOVQ 8(SI),AX MULQ 8(CX) ADDQ AX,R12 ADCQ DX,R13 MOVQ 8(SI),AX MULQ 16(CX) ADDQ AX,R14 ADCQ DX,R15 MOVQ 8(SI),AX MULQ 24(CX) ADDQ AX,BX ADCQ DX,BP MOVQ 8(SI),DX IMUL3Q $19,DX,AX MULQ 32(CX) ADDQ AX,R8 ADCQ DX,R9 MOVQ 16(SI),AX MULQ 0(CX) ADDQ AX,R12 ADCQ DX,R13 MOVQ 16(SI),AX MULQ 8(CX) ADDQ AX,R14 ADCQ DX,R15 MOVQ 16(SI),AX MULQ 16(CX) ADDQ AX,BX ADCQ DX,BP MOVQ 16(SI),DX IMUL3Q $19,DX,AX MULQ 24(CX) ADDQ AX,R8 ADCQ DX,R9 MOVQ 16(SI),DX IMUL3Q $19,DX,AX MULQ 32(CX) ADDQ AX,R10 ADCQ DX,R11 MOVQ 24(SI),AX MULQ 0(CX) ADDQ AX,R14 ADCQ DX,R15 MOVQ 24(SI),AX MULQ 8(CX) ADDQ AX,BX ADCQ DX,BP MOVQ 64(SP),AX MULQ 24(CX) ADDQ AX,R10 ADCQ DX,R11 MOVQ 64(SP),AX MULQ 32(CX) ADDQ AX,R12 ADCQ DX,R13 MOVQ 32(SI),AX MULQ 0(CX) ADDQ AX,BX ADCQ DX,BP MOVQ 72(SP),AX MULQ 16(CX) ADDQ AX,R10 ADCQ DX,R11 MOVQ 72(SP),AX MULQ 24(CX) ADDQ AX,R12 ADCQ DX,R13 MOVQ 72(SP),AX MULQ 32(CX) ADDQ AX,R14 ADCQ DX,R15 MOVQ ·REDMASK51(SB),SI SHLQ $13,R9:R8 ANDQ SI,R8 SHLQ $13,R11:R10 ANDQ SI,R10 ADDQ R9,R10 SHLQ $13,R13:R12 ANDQ SI,R12 ADDQ R11,R12 SHLQ $13,R15:R14 ANDQ SI,R14 ADDQ R13,R14 SHLQ $13,BP:BX ANDQ SI,BX ADDQ R15,BX IMUL3Q $19,BP,DX ADDQ DX,R8 MOVQ R8,DX SHRQ $51,DX ADDQ R10,DX MOVQ DX,CX SHRQ $51,DX ANDQ SI,R8 ADDQ R12,DX MOVQ DX,R9 SHRQ $51,DX ANDQ SI,CX ADDQ R14,DX MOVQ DX,AX SHRQ $51,DX ANDQ SI,R9 ADDQ BX,DX MOVQ DX,R10 SHRQ $51,DX ANDQ SI,AX IMUL3Q $19,DX,DX ADDQ DX,R8 ANDQ SI,R10 MOVQ R8,0(DI) MOVQ CX,8(DI) MOVQ R9,16(DI) MOVQ AX,24(DI) MOVQ R10,32(DI) MOVQ 0(SP),R11 MOVQ 8(SP),R12 MOVQ 16(SP),R13 MOVQ 24(SP),R14 MOVQ 32(SP),R15 MOVQ 40(SP),BX MOVQ 48(SP),BP MOVQ R11,SP MOVQ DI,AX MOVQ SI,DX RET lxd-2.0.0/dist/src/golang.org/x/crypto/curve25519/curve25519.go0000644061062106075000000005303212702772344026112 0ustar00stgraberdomain admins00000000000000// Copyright 2013 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. // We have a implementation in amd64 assembly so this code is only run on // non-amd64 platforms. The amd64 assembly does not support gccgo. // +build !amd64 gccgo appengine package curve25519 // This code is a port of the public domain, "ref10" implementation of // curve25519 from SUPERCOP 20130419 by D. J. Bernstein. // fieldElement represents an element of the field GF(2^255 - 19). An element // t, entries t[0]...t[9], represents the integer t[0]+2^26 t[1]+2^51 t[2]+2^77 // t[3]+2^102 t[4]+...+2^230 t[9]. Bounds on each t[i] vary depending on // context. type fieldElement [10]int32 func feZero(fe *fieldElement) { for i := range fe { fe[i] = 0 } } func feOne(fe *fieldElement) { feZero(fe) fe[0] = 1 } func feAdd(dst, a, b *fieldElement) { for i := range dst { dst[i] = a[i] + b[i] } } func feSub(dst, a, b *fieldElement) { for i := range dst { dst[i] = a[i] - b[i] } } func feCopy(dst, src *fieldElement) { for i := range dst { dst[i] = src[i] } } // feCSwap replaces (f,g) with (g,f) if b == 1; replaces (f,g) with (f,g) if b == 0. // // Preconditions: b in {0,1}. func feCSwap(f, g *fieldElement, b int32) { var x fieldElement b = -b for i := range x { x[i] = b & (f[i] ^ g[i]) } for i := range f { f[i] ^= x[i] } for i := range g { g[i] ^= x[i] } } // load3 reads a 24-bit, little-endian value from in. func load3(in []byte) int64 { var r int64 r = int64(in[0]) r |= int64(in[1]) << 8 r |= int64(in[2]) << 16 return r } // load4 reads a 32-bit, little-endian value from in. func load4(in []byte) int64 { var r int64 r = int64(in[0]) r |= int64(in[1]) << 8 r |= int64(in[2]) << 16 r |= int64(in[3]) << 24 return r } func feFromBytes(dst *fieldElement, src *[32]byte) { h0 := load4(src[:]) h1 := load3(src[4:]) << 6 h2 := load3(src[7:]) << 5 h3 := load3(src[10:]) << 3 h4 := load3(src[13:]) << 2 h5 := load4(src[16:]) h6 := load3(src[20:]) << 7 h7 := load3(src[23:]) << 5 h8 := load3(src[26:]) << 4 h9 := load3(src[29:]) << 2 var carry [10]int64 carry[9] = (h9 + 1<<24) >> 25 h0 += carry[9] * 19 h9 -= carry[9] << 25 carry[1] = (h1 + 1<<24) >> 25 h2 += carry[1] h1 -= carry[1] << 25 carry[3] = (h3 + 1<<24) >> 25 h4 += carry[3] h3 -= carry[3] << 25 carry[5] = (h5 + 1<<24) >> 25 h6 += carry[5] h5 -= carry[5] << 25 carry[7] = (h7 + 1<<24) >> 25 h8 += carry[7] h7 -= carry[7] << 25 carry[0] = (h0 + 1<<25) >> 26 h1 += carry[0] h0 -= carry[0] << 26 carry[2] = (h2 + 1<<25) >> 26 h3 += carry[2] h2 -= carry[2] << 26 carry[4] = (h4 + 1<<25) >> 26 h5 += carry[4] h4 -= carry[4] << 26 carry[6] = (h6 + 1<<25) >> 26 h7 += carry[6] h6 -= carry[6] << 26 carry[8] = (h8 + 1<<25) >> 26 h9 += carry[8] h8 -= carry[8] << 26 dst[0] = int32(h0) dst[1] = int32(h1) dst[2] = int32(h2) dst[3] = int32(h3) dst[4] = int32(h4) dst[5] = int32(h5) dst[6] = int32(h6) dst[7] = int32(h7) dst[8] = int32(h8) dst[9] = int32(h9) } // feToBytes marshals h to s. // Preconditions: // |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. // // Write p=2^255-19; q=floor(h/p). // Basic claim: q = floor(2^(-255)(h + 19 2^(-25)h9 + 2^(-1))). // // Proof: // Have |h|<=p so |q|<=1 so |19^2 2^(-255) q|<1/4. // Also have |h-2^230 h9|<2^230 so |19 2^(-255)(h-2^230 h9)|<1/4. // // Write y=2^(-1)-19^2 2^(-255)q-19 2^(-255)(h-2^230 h9). // Then 0> 25 q = (h[0] + q) >> 26 q = (h[1] + q) >> 25 q = (h[2] + q) >> 26 q = (h[3] + q) >> 25 q = (h[4] + q) >> 26 q = (h[5] + q) >> 25 q = (h[6] + q) >> 26 q = (h[7] + q) >> 25 q = (h[8] + q) >> 26 q = (h[9] + q) >> 25 // Goal: Output h-(2^255-19)q, which is between 0 and 2^255-20. h[0] += 19 * q // Goal: Output h-2^255 q, which is between 0 and 2^255-20. carry[0] = h[0] >> 26 h[1] += carry[0] h[0] -= carry[0] << 26 carry[1] = h[1] >> 25 h[2] += carry[1] h[1] -= carry[1] << 25 carry[2] = h[2] >> 26 h[3] += carry[2] h[2] -= carry[2] << 26 carry[3] = h[3] >> 25 h[4] += carry[3] h[3] -= carry[3] << 25 carry[4] = h[4] >> 26 h[5] += carry[4] h[4] -= carry[4] << 26 carry[5] = h[5] >> 25 h[6] += carry[5] h[5] -= carry[5] << 25 carry[6] = h[6] >> 26 h[7] += carry[6] h[6] -= carry[6] << 26 carry[7] = h[7] >> 25 h[8] += carry[7] h[7] -= carry[7] << 25 carry[8] = h[8] >> 26 h[9] += carry[8] h[8] -= carry[8] << 26 carry[9] = h[9] >> 25 h[9] -= carry[9] << 25 // h10 = carry9 // Goal: Output h[0]+...+2^255 h10-2^255 q, which is between 0 and 2^255-20. // Have h[0]+...+2^230 h[9] between 0 and 2^255-1; // evidently 2^255 h10-2^255 q = 0. // Goal: Output h[0]+...+2^230 h[9]. s[0] = byte(h[0] >> 0) s[1] = byte(h[0] >> 8) s[2] = byte(h[0] >> 16) s[3] = byte((h[0] >> 24) | (h[1] << 2)) s[4] = byte(h[1] >> 6) s[5] = byte(h[1] >> 14) s[6] = byte((h[1] >> 22) | (h[2] << 3)) s[7] = byte(h[2] >> 5) s[8] = byte(h[2] >> 13) s[9] = byte((h[2] >> 21) | (h[3] << 5)) s[10] = byte(h[3] >> 3) s[11] = byte(h[3] >> 11) s[12] = byte((h[3] >> 19) | (h[4] << 6)) s[13] = byte(h[4] >> 2) s[14] = byte(h[4] >> 10) s[15] = byte(h[4] >> 18) s[16] = byte(h[5] >> 0) s[17] = byte(h[5] >> 8) s[18] = byte(h[5] >> 16) s[19] = byte((h[5] >> 24) | (h[6] << 1)) s[20] = byte(h[6] >> 7) s[21] = byte(h[6] >> 15) s[22] = byte((h[6] >> 23) | (h[7] << 3)) s[23] = byte(h[7] >> 5) s[24] = byte(h[7] >> 13) s[25] = byte((h[7] >> 21) | (h[8] << 4)) s[26] = byte(h[8] >> 4) s[27] = byte(h[8] >> 12) s[28] = byte((h[8] >> 20) | (h[9] << 6)) s[29] = byte(h[9] >> 2) s[30] = byte(h[9] >> 10) s[31] = byte(h[9] >> 18) } // feMul calculates h = f * g // Can overlap h with f or g. // // Preconditions: // |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. // |g| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. // // Postconditions: // |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. // // Notes on implementation strategy: // // Using schoolbook multiplication. // Karatsuba would save a little in some cost models. // // Most multiplications by 2 and 19 are 32-bit precomputations; // cheaper than 64-bit postcomputations. // // There is one remaining multiplication by 19 in the carry chain; // one *19 precomputation can be merged into this, // but the resulting data flow is considerably less clean. // // There are 12 carries below. // 10 of them are 2-way parallelizable and vectorizable. // Can get away with 11 carries, but then data flow is much deeper. // // With tighter constraints on inputs can squeeze carries into int32. func feMul(h, f, g *fieldElement) { f0 := f[0] f1 := f[1] f2 := f[2] f3 := f[3] f4 := f[4] f5 := f[5] f6 := f[6] f7 := f[7] f8 := f[8] f9 := f[9] g0 := g[0] g1 := g[1] g2 := g[2] g3 := g[3] g4 := g[4] g5 := g[5] g6 := g[6] g7 := g[7] g8 := g[8] g9 := g[9] g1_19 := 19 * g1 // 1.4*2^29 g2_19 := 19 * g2 // 1.4*2^30; still ok g3_19 := 19 * g3 g4_19 := 19 * g4 g5_19 := 19 * g5 g6_19 := 19 * g6 g7_19 := 19 * g7 g8_19 := 19 * g8 g9_19 := 19 * g9 f1_2 := 2 * f1 f3_2 := 2 * f3 f5_2 := 2 * f5 f7_2 := 2 * f7 f9_2 := 2 * f9 f0g0 := int64(f0) * int64(g0) f0g1 := int64(f0) * int64(g1) f0g2 := int64(f0) * int64(g2) f0g3 := int64(f0) * int64(g3) f0g4 := int64(f0) * int64(g4) f0g5 := int64(f0) * int64(g5) f0g6 := int64(f0) * int64(g6) f0g7 := int64(f0) * int64(g7) f0g8 := int64(f0) * int64(g8) f0g9 := int64(f0) * int64(g9) f1g0 := int64(f1) * int64(g0) f1g1_2 := int64(f1_2) * int64(g1) f1g2 := int64(f1) * int64(g2) f1g3_2 := int64(f1_2) * int64(g3) f1g4 := int64(f1) * int64(g4) f1g5_2 := int64(f1_2) * int64(g5) f1g6 := int64(f1) * int64(g6) f1g7_2 := int64(f1_2) * int64(g7) f1g8 := int64(f1) * int64(g8) f1g9_38 := int64(f1_2) * int64(g9_19) f2g0 := int64(f2) * int64(g0) f2g1 := int64(f2) * int64(g1) f2g2 := int64(f2) * int64(g2) f2g3 := int64(f2) * int64(g3) f2g4 := int64(f2) * int64(g4) f2g5 := int64(f2) * int64(g5) f2g6 := int64(f2) * int64(g6) f2g7 := int64(f2) * int64(g7) f2g8_19 := int64(f2) * int64(g8_19) f2g9_19 := int64(f2) * int64(g9_19) f3g0 := int64(f3) * int64(g0) f3g1_2 := int64(f3_2) * int64(g1) f3g2 := int64(f3) * int64(g2) f3g3_2 := int64(f3_2) * int64(g3) f3g4 := int64(f3) * int64(g4) f3g5_2 := int64(f3_2) * int64(g5) f3g6 := int64(f3) * int64(g6) f3g7_38 := int64(f3_2) * int64(g7_19) f3g8_19 := int64(f3) * int64(g8_19) f3g9_38 := int64(f3_2) * int64(g9_19) f4g0 := int64(f4) * int64(g0) f4g1 := int64(f4) * int64(g1) f4g2 := int64(f4) * int64(g2) f4g3 := int64(f4) * int64(g3) f4g4 := int64(f4) * int64(g4) f4g5 := int64(f4) * int64(g5) f4g6_19 := int64(f4) * int64(g6_19) f4g7_19 := int64(f4) * int64(g7_19) f4g8_19 := int64(f4) * int64(g8_19) f4g9_19 := int64(f4) * int64(g9_19) f5g0 := int64(f5) * int64(g0) f5g1_2 := int64(f5_2) * int64(g1) f5g2 := int64(f5) * int64(g2) f5g3_2 := int64(f5_2) * int64(g3) f5g4 := int64(f5) * int64(g4) f5g5_38 := int64(f5_2) * int64(g5_19) f5g6_19 := int64(f5) * int64(g6_19) f5g7_38 := int64(f5_2) * int64(g7_19) f5g8_19 := int64(f5) * int64(g8_19) f5g9_38 := int64(f5_2) * int64(g9_19) f6g0 := int64(f6) * int64(g0) f6g1 := int64(f6) * int64(g1) f6g2 := int64(f6) * int64(g2) f6g3 := int64(f6) * int64(g3) f6g4_19 := int64(f6) * int64(g4_19) f6g5_19 := int64(f6) * int64(g5_19) f6g6_19 := int64(f6) * int64(g6_19) f6g7_19 := int64(f6) * int64(g7_19) f6g8_19 := int64(f6) * int64(g8_19) f6g9_19 := int64(f6) * int64(g9_19) f7g0 := int64(f7) * int64(g0) f7g1_2 := int64(f7_2) * int64(g1) f7g2 := int64(f7) * int64(g2) f7g3_38 := int64(f7_2) * int64(g3_19) f7g4_19 := int64(f7) * int64(g4_19) f7g5_38 := int64(f7_2) * int64(g5_19) f7g6_19 := int64(f7) * int64(g6_19) f7g7_38 := int64(f7_2) * int64(g7_19) f7g8_19 := int64(f7) * int64(g8_19) f7g9_38 := int64(f7_2) * int64(g9_19) f8g0 := int64(f8) * int64(g0) f8g1 := int64(f8) * int64(g1) f8g2_19 := int64(f8) * int64(g2_19) f8g3_19 := int64(f8) * int64(g3_19) f8g4_19 := int64(f8) * int64(g4_19) f8g5_19 := int64(f8) * int64(g5_19) f8g6_19 := int64(f8) * int64(g6_19) f8g7_19 := int64(f8) * int64(g7_19) f8g8_19 := int64(f8) * int64(g8_19) f8g9_19 := int64(f8) * int64(g9_19) f9g0 := int64(f9) * int64(g0) f9g1_38 := int64(f9_2) * int64(g1_19) f9g2_19 := int64(f9) * int64(g2_19) f9g3_38 := int64(f9_2) * int64(g3_19) f9g4_19 := int64(f9) * int64(g4_19) f9g5_38 := int64(f9_2) * int64(g5_19) f9g6_19 := int64(f9) * int64(g6_19) f9g7_38 := int64(f9_2) * int64(g7_19) f9g8_19 := int64(f9) * int64(g8_19) f9g9_38 := int64(f9_2) * int64(g9_19) h0 := f0g0 + f1g9_38 + f2g8_19 + f3g7_38 + f4g6_19 + f5g5_38 + f6g4_19 + f7g3_38 + f8g2_19 + f9g1_38 h1 := f0g1 + f1g0 + f2g9_19 + f3g8_19 + f4g7_19 + f5g6_19 + f6g5_19 + f7g4_19 + f8g3_19 + f9g2_19 h2 := f0g2 + f1g1_2 + f2g0 + f3g9_38 + f4g8_19 + f5g7_38 + f6g6_19 + f7g5_38 + f8g4_19 + f9g3_38 h3 := f0g3 + f1g2 + f2g1 + f3g0 + f4g9_19 + f5g8_19 + f6g7_19 + f7g6_19 + f8g5_19 + f9g4_19 h4 := f0g4 + f1g3_2 + f2g2 + f3g1_2 + f4g0 + f5g9_38 + f6g8_19 + f7g7_38 + f8g6_19 + f9g5_38 h5 := f0g5 + f1g4 + f2g3 + f3g2 + f4g1 + f5g0 + f6g9_19 + f7g8_19 + f8g7_19 + f9g6_19 h6 := f0g6 + f1g5_2 + f2g4 + f3g3_2 + f4g2 + f5g1_2 + f6g0 + f7g9_38 + f8g8_19 + f9g7_38 h7 := f0g7 + f1g6 + f2g5 + f3g4 + f4g3 + f5g2 + f6g1 + f7g0 + f8g9_19 + f9g8_19 h8 := f0g8 + f1g7_2 + f2g6 + f3g5_2 + f4g4 + f5g3_2 + f6g2 + f7g1_2 + f8g0 + f9g9_38 h9 := f0g9 + f1g8 + f2g7 + f3g6 + f4g5 + f5g4 + f6g3 + f7g2 + f8g1 + f9g0 var carry [10]int64 // |h0| <= (1.1*1.1*2^52*(1+19+19+19+19)+1.1*1.1*2^50*(38+38+38+38+38)) // i.e. |h0| <= 1.2*2^59; narrower ranges for h2, h4, h6, h8 // |h1| <= (1.1*1.1*2^51*(1+1+19+19+19+19+19+19+19+19)) // i.e. |h1| <= 1.5*2^58; narrower ranges for h3, h5, h7, h9 carry[0] = (h0 + (1 << 25)) >> 26 h1 += carry[0] h0 -= carry[0] << 26 carry[4] = (h4 + (1 << 25)) >> 26 h5 += carry[4] h4 -= carry[4] << 26 // |h0| <= 2^25 // |h4| <= 2^25 // |h1| <= 1.51*2^58 // |h5| <= 1.51*2^58 carry[1] = (h1 + (1 << 24)) >> 25 h2 += carry[1] h1 -= carry[1] << 25 carry[5] = (h5 + (1 << 24)) >> 25 h6 += carry[5] h5 -= carry[5] << 25 // |h1| <= 2^24; from now on fits into int32 // |h5| <= 2^24; from now on fits into int32 // |h2| <= 1.21*2^59 // |h6| <= 1.21*2^59 carry[2] = (h2 + (1 << 25)) >> 26 h3 += carry[2] h2 -= carry[2] << 26 carry[6] = (h6 + (1 << 25)) >> 26 h7 += carry[6] h6 -= carry[6] << 26 // |h2| <= 2^25; from now on fits into int32 unchanged // |h6| <= 2^25; from now on fits into int32 unchanged // |h3| <= 1.51*2^58 // |h7| <= 1.51*2^58 carry[3] = (h3 + (1 << 24)) >> 25 h4 += carry[3] h3 -= carry[3] << 25 carry[7] = (h7 + (1 << 24)) >> 25 h8 += carry[7] h7 -= carry[7] << 25 // |h3| <= 2^24; from now on fits into int32 unchanged // |h7| <= 2^24; from now on fits into int32 unchanged // |h4| <= 1.52*2^33 // |h8| <= 1.52*2^33 carry[4] = (h4 + (1 << 25)) >> 26 h5 += carry[4] h4 -= carry[4] << 26 carry[8] = (h8 + (1 << 25)) >> 26 h9 += carry[8] h8 -= carry[8] << 26 // |h4| <= 2^25; from now on fits into int32 unchanged // |h8| <= 2^25; from now on fits into int32 unchanged // |h5| <= 1.01*2^24 // |h9| <= 1.51*2^58 carry[9] = (h9 + (1 << 24)) >> 25 h0 += carry[9] * 19 h9 -= carry[9] << 25 // |h9| <= 2^24; from now on fits into int32 unchanged // |h0| <= 1.8*2^37 carry[0] = (h0 + (1 << 25)) >> 26 h1 += carry[0] h0 -= carry[0] << 26 // |h0| <= 2^25; from now on fits into int32 unchanged // |h1| <= 1.01*2^24 h[0] = int32(h0) h[1] = int32(h1) h[2] = int32(h2) h[3] = int32(h3) h[4] = int32(h4) h[5] = int32(h5) h[6] = int32(h6) h[7] = int32(h7) h[8] = int32(h8) h[9] = int32(h9) } // feSquare calculates h = f*f. Can overlap h with f. // // Preconditions: // |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. // // Postconditions: // |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. func feSquare(h, f *fieldElement) { f0 := f[0] f1 := f[1] f2 := f[2] f3 := f[3] f4 := f[4] f5 := f[5] f6 := f[6] f7 := f[7] f8 := f[8] f9 := f[9] f0_2 := 2 * f0 f1_2 := 2 * f1 f2_2 := 2 * f2 f3_2 := 2 * f3 f4_2 := 2 * f4 f5_2 := 2 * f5 f6_2 := 2 * f6 f7_2 := 2 * f7 f5_38 := 38 * f5 // 1.31*2^30 f6_19 := 19 * f6 // 1.31*2^30 f7_38 := 38 * f7 // 1.31*2^30 f8_19 := 19 * f8 // 1.31*2^30 f9_38 := 38 * f9 // 1.31*2^30 f0f0 := int64(f0) * int64(f0) f0f1_2 := int64(f0_2) * int64(f1) f0f2_2 := int64(f0_2) * int64(f2) f0f3_2 := int64(f0_2) * int64(f3) f0f4_2 := int64(f0_2) * int64(f4) f0f5_2 := int64(f0_2) * int64(f5) f0f6_2 := int64(f0_2) * int64(f6) f0f7_2 := int64(f0_2) * int64(f7) f0f8_2 := int64(f0_2) * int64(f8) f0f9_2 := int64(f0_2) * int64(f9) f1f1_2 := int64(f1_2) * int64(f1) f1f2_2 := int64(f1_2) * int64(f2) f1f3_4 := int64(f1_2) * int64(f3_2) f1f4_2 := int64(f1_2) * int64(f4) f1f5_4 := int64(f1_2) * int64(f5_2) f1f6_2 := int64(f1_2) * int64(f6) f1f7_4 := int64(f1_2) * int64(f7_2) f1f8_2 := int64(f1_2) * int64(f8) f1f9_76 := int64(f1_2) * int64(f9_38) f2f2 := int64(f2) * int64(f2) f2f3_2 := int64(f2_2) * int64(f3) f2f4_2 := int64(f2_2) * int64(f4) f2f5_2 := int64(f2_2) * int64(f5) f2f6_2 := int64(f2_2) * int64(f6) f2f7_2 := int64(f2_2) * int64(f7) f2f8_38 := int64(f2_2) * int64(f8_19) f2f9_38 := int64(f2) * int64(f9_38) f3f3_2 := int64(f3_2) * int64(f3) f3f4_2 := int64(f3_2) * int64(f4) f3f5_4 := int64(f3_2) * int64(f5_2) f3f6_2 := int64(f3_2) * int64(f6) f3f7_76 := int64(f3_2) * int64(f7_38) f3f8_38 := int64(f3_2) * int64(f8_19) f3f9_76 := int64(f3_2) * int64(f9_38) f4f4 := int64(f4) * int64(f4) f4f5_2 := int64(f4_2) * int64(f5) f4f6_38 := int64(f4_2) * int64(f6_19) f4f7_38 := int64(f4) * int64(f7_38) f4f8_38 := int64(f4_2) * int64(f8_19) f4f9_38 := int64(f4) * int64(f9_38) f5f5_38 := int64(f5) * int64(f5_38) f5f6_38 := int64(f5_2) * int64(f6_19) f5f7_76 := int64(f5_2) * int64(f7_38) f5f8_38 := int64(f5_2) * int64(f8_19) f5f9_76 := int64(f5_2) * int64(f9_38) f6f6_19 := int64(f6) * int64(f6_19) f6f7_38 := int64(f6) * int64(f7_38) f6f8_38 := int64(f6_2) * int64(f8_19) f6f9_38 := int64(f6) * int64(f9_38) f7f7_38 := int64(f7) * int64(f7_38) f7f8_38 := int64(f7_2) * int64(f8_19) f7f9_76 := int64(f7_2) * int64(f9_38) f8f8_19 := int64(f8) * int64(f8_19) f8f9_38 := int64(f8) * int64(f9_38) f9f9_38 := int64(f9) * int64(f9_38) h0 := f0f0 + f1f9_76 + f2f8_38 + f3f7_76 + f4f6_38 + f5f5_38 h1 := f0f1_2 + f2f9_38 + f3f8_38 + f4f7_38 + f5f6_38 h2 := f0f2_2 + f1f1_2 + f3f9_76 + f4f8_38 + f5f7_76 + f6f6_19 h3 := f0f3_2 + f1f2_2 + f4f9_38 + f5f8_38 + f6f7_38 h4 := f0f4_2 + f1f3_4 + f2f2 + f5f9_76 + f6f8_38 + f7f7_38 h5 := f0f5_2 + f1f4_2 + f2f3_2 + f6f9_38 + f7f8_38 h6 := f0f6_2 + f1f5_4 + f2f4_2 + f3f3_2 + f7f9_76 + f8f8_19 h7 := f0f7_2 + f1f6_2 + f2f5_2 + f3f4_2 + f8f9_38 h8 := f0f8_2 + f1f7_4 + f2f6_2 + f3f5_4 + f4f4 + f9f9_38 h9 := f0f9_2 + f1f8_2 + f2f7_2 + f3f6_2 + f4f5_2 var carry [10]int64 carry[0] = (h0 + (1 << 25)) >> 26 h1 += carry[0] h0 -= carry[0] << 26 carry[4] = (h4 + (1 << 25)) >> 26 h5 += carry[4] h4 -= carry[4] << 26 carry[1] = (h1 + (1 << 24)) >> 25 h2 += carry[1] h1 -= carry[1] << 25 carry[5] = (h5 + (1 << 24)) >> 25 h6 += carry[5] h5 -= carry[5] << 25 carry[2] = (h2 + (1 << 25)) >> 26 h3 += carry[2] h2 -= carry[2] << 26 carry[6] = (h6 + (1 << 25)) >> 26 h7 += carry[6] h6 -= carry[6] << 26 carry[3] = (h3 + (1 << 24)) >> 25 h4 += carry[3] h3 -= carry[3] << 25 carry[7] = (h7 + (1 << 24)) >> 25 h8 += carry[7] h7 -= carry[7] << 25 carry[4] = (h4 + (1 << 25)) >> 26 h5 += carry[4] h4 -= carry[4] << 26 carry[8] = (h8 + (1 << 25)) >> 26 h9 += carry[8] h8 -= carry[8] << 26 carry[9] = (h9 + (1 << 24)) >> 25 h0 += carry[9] * 19 h9 -= carry[9] << 25 carry[0] = (h0 + (1 << 25)) >> 26 h1 += carry[0] h0 -= carry[0] << 26 h[0] = int32(h0) h[1] = int32(h1) h[2] = int32(h2) h[3] = int32(h3) h[4] = int32(h4) h[5] = int32(h5) h[6] = int32(h6) h[7] = int32(h7) h[8] = int32(h8) h[9] = int32(h9) } // feMul121666 calculates h = f * 121666. Can overlap h with f. // // Preconditions: // |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. // // Postconditions: // |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. func feMul121666(h, f *fieldElement) { h0 := int64(f[0]) * 121666 h1 := int64(f[1]) * 121666 h2 := int64(f[2]) * 121666 h3 := int64(f[3]) * 121666 h4 := int64(f[4]) * 121666 h5 := int64(f[5]) * 121666 h6 := int64(f[6]) * 121666 h7 := int64(f[7]) * 121666 h8 := int64(f[8]) * 121666 h9 := int64(f[9]) * 121666 var carry [10]int64 carry[9] = (h9 + (1 << 24)) >> 25 h0 += carry[9] * 19 h9 -= carry[9] << 25 carry[1] = (h1 + (1 << 24)) >> 25 h2 += carry[1] h1 -= carry[1] << 25 carry[3] = (h3 + (1 << 24)) >> 25 h4 += carry[3] h3 -= carry[3] << 25 carry[5] = (h5 + (1 << 24)) >> 25 h6 += carry[5] h5 -= carry[5] << 25 carry[7] = (h7 + (1 << 24)) >> 25 h8 += carry[7] h7 -= carry[7] << 25 carry[0] = (h0 + (1 << 25)) >> 26 h1 += carry[0] h0 -= carry[0] << 26 carry[2] = (h2 + (1 << 25)) >> 26 h3 += carry[2] h2 -= carry[2] << 26 carry[4] = (h4 + (1 << 25)) >> 26 h5 += carry[4] h4 -= carry[4] << 26 carry[6] = (h6 + (1 << 25)) >> 26 h7 += carry[6] h6 -= carry[6] << 26 carry[8] = (h8 + (1 << 25)) >> 26 h9 += carry[8] h8 -= carry[8] << 26 h[0] = int32(h0) h[1] = int32(h1) h[2] = int32(h2) h[3] = int32(h3) h[4] = int32(h4) h[5] = int32(h5) h[6] = int32(h6) h[7] = int32(h7) h[8] = int32(h8) h[9] = int32(h9) } // feInvert sets out = z^-1. func feInvert(out, z *fieldElement) { var t0, t1, t2, t3 fieldElement var i int feSquare(&t0, z) for i = 1; i < 1; i++ { feSquare(&t0, &t0) } feSquare(&t1, &t0) for i = 1; i < 2; i++ { feSquare(&t1, &t1) } feMul(&t1, z, &t1) feMul(&t0, &t0, &t1) feSquare(&t2, &t0) for i = 1; i < 1; i++ { feSquare(&t2, &t2) } feMul(&t1, &t1, &t2) feSquare(&t2, &t1) for i = 1; i < 5; i++ { feSquare(&t2, &t2) } feMul(&t1, &t2, &t1) feSquare(&t2, &t1) for i = 1; i < 10; i++ { feSquare(&t2, &t2) } feMul(&t2, &t2, &t1) feSquare(&t3, &t2) for i = 1; i < 20; i++ { feSquare(&t3, &t3) } feMul(&t2, &t3, &t2) feSquare(&t2, &t2) for i = 1; i < 10; i++ { feSquare(&t2, &t2) } feMul(&t1, &t2, &t1) feSquare(&t2, &t1) for i = 1; i < 50; i++ { feSquare(&t2, &t2) } feMul(&t2, &t2, &t1) feSquare(&t3, &t2) for i = 1; i < 100; i++ { feSquare(&t3, &t3) } feMul(&t2, &t3, &t2) feSquare(&t2, &t2) for i = 1; i < 50; i++ { feSquare(&t2, &t2) } feMul(&t1, &t2, &t1) feSquare(&t1, &t1) for i = 1; i < 5; i++ { feSquare(&t1, &t1) } feMul(out, &t1, &t0) } func scalarMult(out, in, base *[32]byte) { var e [32]byte copy(e[:], in[:]) e[0] &= 248 e[31] &= 127 e[31] |= 64 var x1, x2, z2, x3, z3, tmp0, tmp1 fieldElement feFromBytes(&x1, base) feOne(&x2) feCopy(&x3, &x1) feOne(&z3) swap := int32(0) for pos := 254; pos >= 0; pos-- { b := e[pos/8] >> uint(pos&7) b &= 1 swap ^= int32(b) feCSwap(&x2, &x3, swap) feCSwap(&z2, &z3, swap) swap = int32(b) feSub(&tmp0, &x3, &z3) feSub(&tmp1, &x2, &z2) feAdd(&x2, &x2, &z2) feAdd(&z2, &x3, &z3) feMul(&z3, &tmp0, &x2) feMul(&z2, &z2, &tmp1) feSquare(&tmp0, &tmp1) feSquare(&tmp1, &x2) feAdd(&x3, &z3, &z2) feSub(&z2, &z3, &z2) feMul(&x2, &tmp1, &tmp0) feSub(&tmp1, &tmp1, &tmp0) feSquare(&z2, &z2) feMul121666(&z3, &tmp1) feSquare(&x3, &x3) feAdd(&tmp0, &tmp0, &z3) feMul(&z3, &x1, &z2) feMul(&z2, &tmp1, &tmp0) } feCSwap(&x2, &x3, swap) feCSwap(&z2, &z3, swap) feInvert(&z2, &z2) feMul(&x2, &x2, &z2) feToBytes(out, &x2) } lxd-2.0.0/dist/src/golang.org/x/crypto/curve25519/const_amd64.s0000644061062106075000000000114012702772344026327 0ustar00stgraberdomain admins00000000000000// Copyright 2012 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 code was translated into a form compatible with 6a from the public // domain sources in SUPERCOP: http://bench.cr.yp.to/supercop.html // +build amd64,!gccgo,!appengine DATA ·REDMASK51(SB)/8, $0x0007FFFFFFFFFFFF GLOBL ·REDMASK51(SB), 8, $8 DATA ·_121666_213(SB)/8, $996687872 GLOBL ·_121666_213(SB), 8, $8 DATA ·_2P0(SB)/8, $0xFFFFFFFFFFFDA GLOBL ·_2P0(SB), 8, $8 DATA ·_2P1234(SB)/8, $0xFFFFFFFFFFFFE GLOBL ·_2P1234(SB), 8, $8 lxd-2.0.0/dist/src/golang.org/x/crypto/curve25519/freeze_amd64.s0000644061062106075000000000301712702772344026466 0ustar00stgraberdomain admins00000000000000// Copyright 2012 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 code was translated into a form compatible with 6a from the public // domain sources in SUPERCOP: http://bench.cr.yp.to/supercop.html // +build amd64,!gccgo,!appengine // func freeze(inout *[5]uint64) TEXT ·freeze(SB),7,$96-8 MOVQ inout+0(FP), DI MOVQ SP,R11 MOVQ $31,CX NOTQ CX ANDQ CX,SP ADDQ $32,SP MOVQ R11,0(SP) MOVQ R12,8(SP) MOVQ R13,16(SP) MOVQ R14,24(SP) MOVQ R15,32(SP) MOVQ BX,40(SP) MOVQ BP,48(SP) MOVQ 0(DI),SI MOVQ 8(DI),DX MOVQ 16(DI),CX MOVQ 24(DI),R8 MOVQ 32(DI),R9 MOVQ ·REDMASK51(SB),AX MOVQ AX,R10 SUBQ $18,R10 MOVQ $3,R11 REDUCELOOP: MOVQ SI,R12 SHRQ $51,R12 ANDQ AX,SI ADDQ R12,DX MOVQ DX,R12 SHRQ $51,R12 ANDQ AX,DX ADDQ R12,CX MOVQ CX,R12 SHRQ $51,R12 ANDQ AX,CX ADDQ R12,R8 MOVQ R8,R12 SHRQ $51,R12 ANDQ AX,R8 ADDQ R12,R9 MOVQ R9,R12 SHRQ $51,R12 ANDQ AX,R9 IMUL3Q $19,R12,R12 ADDQ R12,SI SUBQ $1,R11 JA REDUCELOOP MOVQ $1,R12 CMPQ R10,SI CMOVQLT R11,R12 CMPQ AX,DX CMOVQNE R11,R12 CMPQ AX,CX CMOVQNE R11,R12 CMPQ AX,R8 CMOVQNE R11,R12 CMPQ AX,R9 CMOVQNE R11,R12 NEGQ R12 ANDQ R12,AX ANDQ R12,R10 SUBQ R10,SI SUBQ AX,DX SUBQ AX,CX SUBQ AX,R8 SUBQ AX,R9 MOVQ SI,0(DI) MOVQ DX,8(DI) MOVQ CX,16(DI) MOVQ R8,24(DI) MOVQ R9,32(DI) MOVQ 0(SP),R11 MOVQ 8(SP),R12 MOVQ 16(SP),R13 MOVQ 24(SP),R14 MOVQ 32(SP),R15 MOVQ 40(SP),BX MOVQ 48(SP),BP MOVQ R11,SP MOVQ DI,AX MOVQ SI,DX RET lxd-2.0.0/dist/src/golang.org/x/crypto/curve25519/curve25519_test.go0000644061062106075000000000113512702772344027146 0ustar00stgraberdomain admins00000000000000// Copyright 2012 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 curve25519 import ( "fmt" "testing" ) const expectedHex = "89161fde887b2b53de549af483940106ecc114d6982daa98256de23bdf77661a" func TestBaseScalarMult(t *testing.T) { var a, b [32]byte in := &a out := &b a[0] = 1 for i := 0; i < 200; i++ { ScalarBaseMult(out, in) in, out = out, in } result := fmt.Sprintf("%x", in[:]) if result != expectedHex { t.Errorf("incorrect result: got %s, want %s", result, expectedHex) } } lxd-2.0.0/dist/src/golang.org/x/crypto/curve25519/mont25519_amd64.go0000644061062106075000000001223112702772344026732 0ustar00stgraberdomain admins00000000000000// Copyright 2012 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. // +build amd64,!gccgo,!appengine package curve25519 // These functions are implemented in the .s files. The names of the functions // in the rest of the file are also taken from the SUPERCOP sources to help // people following along. //go:noescape func cswap(inout *[5]uint64, v uint64) //go:noescape func ladderstep(inout *[5][5]uint64) //go:noescape func freeze(inout *[5]uint64) //go:noescape func mul(dest, a, b *[5]uint64) //go:noescape func square(out, in *[5]uint64) // mladder uses a Montgomery ladder to calculate (xr/zr) *= s. func mladder(xr, zr *[5]uint64, s *[32]byte) { var work [5][5]uint64 work[0] = *xr setint(&work[1], 1) setint(&work[2], 0) work[3] = *xr setint(&work[4], 1) j := uint(6) var prevbit byte for i := 31; i >= 0; i-- { for j < 8 { bit := ((*s)[i] >> j) & 1 swap := bit ^ prevbit prevbit = bit cswap(&work[1], uint64(swap)) ladderstep(&work) j-- } j = 7 } *xr = work[1] *zr = work[2] } func scalarMult(out, in, base *[32]byte) { var e [32]byte copy(e[:], (*in)[:]) e[0] &= 248 e[31] &= 127 e[31] |= 64 var t, z [5]uint64 unpack(&t, base) mladder(&t, &z, &e) invert(&z, &z) mul(&t, &t, &z) pack(out, &t) } func setint(r *[5]uint64, v uint64) { r[0] = v r[1] = 0 r[2] = 0 r[3] = 0 r[4] = 0 } // unpack sets r = x where r consists of 5, 51-bit limbs in little-endian // order. func unpack(r *[5]uint64, x *[32]byte) { r[0] = uint64(x[0]) | uint64(x[1])<<8 | uint64(x[2])<<16 | uint64(x[3])<<24 | uint64(x[4])<<32 | uint64(x[5])<<40 | uint64(x[6]&7)<<48 r[1] = uint64(x[6])>>3 | uint64(x[7])<<5 | uint64(x[8])<<13 | uint64(x[9])<<21 | uint64(x[10])<<29 | uint64(x[11])<<37 | uint64(x[12]&63)<<45 r[2] = uint64(x[12])>>6 | uint64(x[13])<<2 | uint64(x[14])<<10 | uint64(x[15])<<18 | uint64(x[16])<<26 | uint64(x[17])<<34 | uint64(x[18])<<42 | uint64(x[19]&1)<<50 r[3] = uint64(x[19])>>1 | uint64(x[20])<<7 | uint64(x[21])<<15 | uint64(x[22])<<23 | uint64(x[23])<<31 | uint64(x[24])<<39 | uint64(x[25]&15)<<47 r[4] = uint64(x[25])>>4 | uint64(x[26])<<4 | uint64(x[27])<<12 | uint64(x[28])<<20 | uint64(x[29])<<28 | uint64(x[30])<<36 | uint64(x[31]&127)<<44 } // pack sets out = x where out is the usual, little-endian form of the 5, // 51-bit limbs in x. func pack(out *[32]byte, x *[5]uint64) { t := *x freeze(&t) out[0] = byte(t[0]) out[1] = byte(t[0] >> 8) out[2] = byte(t[0] >> 16) out[3] = byte(t[0] >> 24) out[4] = byte(t[0] >> 32) out[5] = byte(t[0] >> 40) out[6] = byte(t[0] >> 48) out[6] ^= byte(t[1]<<3) & 0xf8 out[7] = byte(t[1] >> 5) out[8] = byte(t[1] >> 13) out[9] = byte(t[1] >> 21) out[10] = byte(t[1] >> 29) out[11] = byte(t[1] >> 37) out[12] = byte(t[1] >> 45) out[12] ^= byte(t[2]<<6) & 0xc0 out[13] = byte(t[2] >> 2) out[14] = byte(t[2] >> 10) out[15] = byte(t[2] >> 18) out[16] = byte(t[2] >> 26) out[17] = byte(t[2] >> 34) out[18] = byte(t[2] >> 42) out[19] = byte(t[2] >> 50) out[19] ^= byte(t[3]<<1) & 0xfe out[20] = byte(t[3] >> 7) out[21] = byte(t[3] >> 15) out[22] = byte(t[3] >> 23) out[23] = byte(t[3] >> 31) out[24] = byte(t[3] >> 39) out[25] = byte(t[3] >> 47) out[25] ^= byte(t[4]<<4) & 0xf0 out[26] = byte(t[4] >> 4) out[27] = byte(t[4] >> 12) out[28] = byte(t[4] >> 20) out[29] = byte(t[4] >> 28) out[30] = byte(t[4] >> 36) out[31] = byte(t[4] >> 44) } // invert calculates r = x^-1 mod p using Fermat's little theorem. func invert(r *[5]uint64, x *[5]uint64) { var z2, z9, z11, z2_5_0, z2_10_0, z2_20_0, z2_50_0, z2_100_0, t [5]uint64 square(&z2, x) /* 2 */ square(&t, &z2) /* 4 */ square(&t, &t) /* 8 */ mul(&z9, &t, x) /* 9 */ mul(&z11, &z9, &z2) /* 11 */ square(&t, &z11) /* 22 */ mul(&z2_5_0, &t, &z9) /* 2^5 - 2^0 = 31 */ square(&t, &z2_5_0) /* 2^6 - 2^1 */ for i := 1; i < 5; i++ { /* 2^20 - 2^10 */ square(&t, &t) } mul(&z2_10_0, &t, &z2_5_0) /* 2^10 - 2^0 */ square(&t, &z2_10_0) /* 2^11 - 2^1 */ for i := 1; i < 10; i++ { /* 2^20 - 2^10 */ square(&t, &t) } mul(&z2_20_0, &t, &z2_10_0) /* 2^20 - 2^0 */ square(&t, &z2_20_0) /* 2^21 - 2^1 */ for i := 1; i < 20; i++ { /* 2^40 - 2^20 */ square(&t, &t) } mul(&t, &t, &z2_20_0) /* 2^40 - 2^0 */ square(&t, &t) /* 2^41 - 2^1 */ for i := 1; i < 10; i++ { /* 2^50 - 2^10 */ square(&t, &t) } mul(&z2_50_0, &t, &z2_10_0) /* 2^50 - 2^0 */ square(&t, &z2_50_0) /* 2^51 - 2^1 */ for i := 1; i < 50; i++ { /* 2^100 - 2^50 */ square(&t, &t) } mul(&z2_100_0, &t, &z2_50_0) /* 2^100 - 2^0 */ square(&t, &z2_100_0) /* 2^101 - 2^1 */ for i := 1; i < 100; i++ { /* 2^200 - 2^100 */ square(&t, &t) } mul(&t, &t, &z2_100_0) /* 2^200 - 2^0 */ square(&t, &t) /* 2^201 - 2^1 */ for i := 1; i < 50; i++ { /* 2^250 - 2^50 */ square(&t, &t) } mul(&t, &t, &z2_50_0) /* 2^250 - 2^0 */ square(&t, &t) /* 2^251 - 2^1 */ square(&t, &t) /* 2^252 - 2^2 */ square(&t, &t) /* 2^253 - 2^3 */ square(&t, &t) /* 2^254 - 2^4 */ square(&t, &t) /* 2^255 - 2^5 */ mul(r, &t, &z11) /* 2^255 - 21 */ } lxd-2.0.0/dist/src/golang.org/x/crypto/curve25519/ladderstep_amd64.s0000644061062106075000000004772112702772344027347 0ustar00stgraberdomain admins00000000000000// Copyright 2012 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 code was translated into a form compatible with 6a from the public // domain sources in SUPERCOP: http://bench.cr.yp.to/supercop.html // +build amd64,!gccgo,!appengine // func ladderstep(inout *[5][5]uint64) TEXT ·ladderstep(SB),0,$384-8 MOVQ inout+0(FP),DI MOVQ SP,R11 MOVQ $31,CX NOTQ CX ANDQ CX,SP ADDQ $32,SP MOVQ R11,0(SP) MOVQ R12,8(SP) MOVQ R13,16(SP) MOVQ R14,24(SP) MOVQ R15,32(SP) MOVQ BX,40(SP) MOVQ BP,48(SP) MOVQ 40(DI),SI MOVQ 48(DI),DX MOVQ 56(DI),CX MOVQ 64(DI),R8 MOVQ 72(DI),R9 MOVQ SI,AX MOVQ DX,R10 MOVQ CX,R11 MOVQ R8,R12 MOVQ R9,R13 ADDQ ·_2P0(SB),AX ADDQ ·_2P1234(SB),R10 ADDQ ·_2P1234(SB),R11 ADDQ ·_2P1234(SB),R12 ADDQ ·_2P1234(SB),R13 ADDQ 80(DI),SI ADDQ 88(DI),DX ADDQ 96(DI),CX ADDQ 104(DI),R8 ADDQ 112(DI),R9 SUBQ 80(DI),AX SUBQ 88(DI),R10 SUBQ 96(DI),R11 SUBQ 104(DI),R12 SUBQ 112(DI),R13 MOVQ SI,56(SP) MOVQ DX,64(SP) MOVQ CX,72(SP) MOVQ R8,80(SP) MOVQ R9,88(SP) MOVQ AX,96(SP) MOVQ R10,104(SP) MOVQ R11,112(SP) MOVQ R12,120(SP) MOVQ R13,128(SP) MOVQ 96(SP),AX MULQ 96(SP) MOVQ AX,SI MOVQ DX,CX MOVQ 96(SP),AX SHLQ $1,AX MULQ 104(SP) MOVQ AX,R8 MOVQ DX,R9 MOVQ 96(SP),AX SHLQ $1,AX MULQ 112(SP) MOVQ AX,R10 MOVQ DX,R11 MOVQ 96(SP),AX SHLQ $1,AX MULQ 120(SP) MOVQ AX,R12 MOVQ DX,R13 MOVQ 96(SP),AX SHLQ $1,AX MULQ 128(SP) MOVQ AX,R14 MOVQ DX,R15 MOVQ 104(SP),AX MULQ 104(SP) ADDQ AX,R10 ADCQ DX,R11 MOVQ 104(SP),AX SHLQ $1,AX MULQ 112(SP) ADDQ AX,R12 ADCQ DX,R13 MOVQ 104(SP),AX SHLQ $1,AX MULQ 120(SP) ADDQ AX,R14 ADCQ DX,R15 MOVQ 104(SP),DX IMUL3Q $38,DX,AX MULQ 128(SP) ADDQ AX,SI ADCQ DX,CX MOVQ 112(SP),AX MULQ 112(SP) ADDQ AX,R14 ADCQ DX,R15 MOVQ 112(SP),DX IMUL3Q $38,DX,AX MULQ 120(SP) ADDQ AX,SI ADCQ DX,CX MOVQ 112(SP),DX IMUL3Q $38,DX,AX MULQ 128(SP) ADDQ AX,R8 ADCQ DX,R9 MOVQ 120(SP),DX IMUL3Q $19,DX,AX MULQ 120(SP) ADDQ AX,R8 ADCQ DX,R9 MOVQ 120(SP),DX IMUL3Q $38,DX,AX MULQ 128(SP) ADDQ AX,R10 ADCQ DX,R11 MOVQ 128(SP),DX IMUL3Q $19,DX,AX MULQ 128(SP) ADDQ AX,R12 ADCQ DX,R13 MOVQ ·REDMASK51(SB),DX SHLQ $13,CX:SI ANDQ DX,SI SHLQ $13,R9:R8 ANDQ DX,R8 ADDQ CX,R8 SHLQ $13,R11:R10 ANDQ DX,R10 ADDQ R9,R10 SHLQ $13,R13:R12 ANDQ DX,R12 ADDQ R11,R12 SHLQ $13,R15:R14 ANDQ DX,R14 ADDQ R13,R14 IMUL3Q $19,R15,CX ADDQ CX,SI MOVQ SI,CX SHRQ $51,CX ADDQ R8,CX ANDQ DX,SI MOVQ CX,R8 SHRQ $51,CX ADDQ R10,CX ANDQ DX,R8 MOVQ CX,R9 SHRQ $51,CX ADDQ R12,CX ANDQ DX,R9 MOVQ CX,AX SHRQ $51,CX ADDQ R14,CX ANDQ DX,AX MOVQ CX,R10 SHRQ $51,CX IMUL3Q $19,CX,CX ADDQ CX,SI ANDQ DX,R10 MOVQ SI,136(SP) MOVQ R8,144(SP) MOVQ R9,152(SP) MOVQ AX,160(SP) MOVQ R10,168(SP) MOVQ 56(SP),AX MULQ 56(SP) MOVQ AX,SI MOVQ DX,CX MOVQ 56(SP),AX SHLQ $1,AX MULQ 64(SP) MOVQ AX,R8 MOVQ DX,R9 MOVQ 56(SP),AX SHLQ $1,AX MULQ 72(SP) MOVQ AX,R10 MOVQ DX,R11 MOVQ 56(SP),AX SHLQ $1,AX MULQ 80(SP) MOVQ AX,R12 MOVQ DX,R13 MOVQ 56(SP),AX SHLQ $1,AX MULQ 88(SP) MOVQ AX,R14 MOVQ DX,R15 MOVQ 64(SP),AX MULQ 64(SP) ADDQ AX,R10 ADCQ DX,R11 MOVQ 64(SP),AX SHLQ $1,AX MULQ 72(SP) ADDQ AX,R12 ADCQ DX,R13 MOVQ 64(SP),AX SHLQ $1,AX MULQ 80(SP) ADDQ AX,R14 ADCQ DX,R15 MOVQ 64(SP),DX IMUL3Q $38,DX,AX MULQ 88(SP) ADDQ AX,SI ADCQ DX,CX MOVQ 72(SP),AX MULQ 72(SP) ADDQ AX,R14 ADCQ DX,R15 MOVQ 72(SP),DX IMUL3Q $38,DX,AX MULQ 80(SP) ADDQ AX,SI ADCQ DX,CX MOVQ 72(SP),DX IMUL3Q $38,DX,AX MULQ 88(SP) ADDQ AX,R8 ADCQ DX,R9 MOVQ 80(SP),DX IMUL3Q $19,DX,AX MULQ 80(SP) ADDQ AX,R8 ADCQ DX,R9 MOVQ 80(SP),DX IMUL3Q $38,DX,AX MULQ 88(SP) ADDQ AX,R10 ADCQ DX,R11 MOVQ 88(SP),DX IMUL3Q $19,DX,AX MULQ 88(SP) ADDQ AX,R12 ADCQ DX,R13 MOVQ ·REDMASK51(SB),DX SHLQ $13,CX:SI ANDQ DX,SI SHLQ $13,R9:R8 ANDQ DX,R8 ADDQ CX,R8 SHLQ $13,R11:R10 ANDQ DX,R10 ADDQ R9,R10 SHLQ $13,R13:R12 ANDQ DX,R12 ADDQ R11,R12 SHLQ $13,R15:R14 ANDQ DX,R14 ADDQ R13,R14 IMUL3Q $19,R15,CX ADDQ CX,SI MOVQ SI,CX SHRQ $51,CX ADDQ R8,CX ANDQ DX,SI MOVQ CX,R8 SHRQ $51,CX ADDQ R10,CX ANDQ DX,R8 MOVQ CX,R9 SHRQ $51,CX ADDQ R12,CX ANDQ DX,R9 MOVQ CX,AX SHRQ $51,CX ADDQ R14,CX ANDQ DX,AX MOVQ CX,R10 SHRQ $51,CX IMUL3Q $19,CX,CX ADDQ CX,SI ANDQ DX,R10 MOVQ SI,176(SP) MOVQ R8,184(SP) MOVQ R9,192(SP) MOVQ AX,200(SP) MOVQ R10,208(SP) MOVQ SI,SI MOVQ R8,DX MOVQ R9,CX MOVQ AX,R8 MOVQ R10,R9 ADDQ ·_2P0(SB),SI ADDQ ·_2P1234(SB),DX ADDQ ·_2P1234(SB),CX ADDQ ·_2P1234(SB),R8 ADDQ ·_2P1234(SB),R9 SUBQ 136(SP),SI SUBQ 144(SP),DX SUBQ 152(SP),CX SUBQ 160(SP),R8 SUBQ 168(SP),R9 MOVQ SI,216(SP) MOVQ DX,224(SP) MOVQ CX,232(SP) MOVQ R8,240(SP) MOVQ R9,248(SP) MOVQ 120(DI),SI MOVQ 128(DI),DX MOVQ 136(DI),CX MOVQ 144(DI),R8 MOVQ 152(DI),R9 MOVQ SI,AX MOVQ DX,R10 MOVQ CX,R11 MOVQ R8,R12 MOVQ R9,R13 ADDQ ·_2P0(SB),AX ADDQ ·_2P1234(SB),R10 ADDQ ·_2P1234(SB),R11 ADDQ ·_2P1234(SB),R12 ADDQ ·_2P1234(SB),R13 ADDQ 160(DI),SI ADDQ 168(DI),DX ADDQ 176(DI),CX ADDQ 184(DI),R8 ADDQ 192(DI),R9 SUBQ 160(DI),AX SUBQ 168(DI),R10 SUBQ 176(DI),R11 SUBQ 184(DI),R12 SUBQ 192(DI),R13 MOVQ SI,256(SP) MOVQ DX,264(SP) MOVQ CX,272(SP) MOVQ R8,280(SP) MOVQ R9,288(SP) MOVQ AX,296(SP) MOVQ R10,304(SP) MOVQ R11,312(SP) MOVQ R12,320(SP) MOVQ R13,328(SP) MOVQ 280(SP),SI IMUL3Q $19,SI,AX MOVQ AX,336(SP) MULQ 112(SP) MOVQ AX,SI MOVQ DX,CX MOVQ 288(SP),DX IMUL3Q $19,DX,AX MOVQ AX,344(SP) MULQ 104(SP) ADDQ AX,SI ADCQ DX,CX MOVQ 256(SP),AX MULQ 96(SP) ADDQ AX,SI ADCQ DX,CX MOVQ 256(SP),AX MULQ 104(SP) MOVQ AX,R8 MOVQ DX,R9 MOVQ 256(SP),AX MULQ 112(SP) MOVQ AX,R10 MOVQ DX,R11 MOVQ 256(SP),AX MULQ 120(SP) MOVQ AX,R12 MOVQ DX,R13 MOVQ 256(SP),AX MULQ 128(SP) MOVQ AX,R14 MOVQ DX,R15 MOVQ 264(SP),AX MULQ 96(SP) ADDQ AX,R8 ADCQ DX,R9 MOVQ 264(SP),AX MULQ 104(SP) ADDQ AX,R10 ADCQ DX,R11 MOVQ 264(SP),AX MULQ 112(SP) ADDQ AX,R12 ADCQ DX,R13 MOVQ 264(SP),AX MULQ 120(SP) ADDQ AX,R14 ADCQ DX,R15 MOVQ 264(SP),DX IMUL3Q $19,DX,AX MULQ 128(SP) ADDQ AX,SI ADCQ DX,CX MOVQ 272(SP),AX MULQ 96(SP) ADDQ AX,R10 ADCQ DX,R11 MOVQ 272(SP),AX MULQ 104(SP) ADDQ AX,R12 ADCQ DX,R13 MOVQ 272(SP),AX MULQ 112(SP) ADDQ AX,R14 ADCQ DX,R15 MOVQ 272(SP),DX IMUL3Q $19,DX,AX MULQ 120(SP) ADDQ AX,SI ADCQ DX,CX MOVQ 272(SP),DX IMUL3Q $19,DX,AX MULQ 128(SP) ADDQ AX,R8 ADCQ DX,R9 MOVQ 280(SP),AX MULQ 96(SP) ADDQ AX,R12 ADCQ DX,R13 MOVQ 280(SP),AX MULQ 104(SP) ADDQ AX,R14 ADCQ DX,R15 MOVQ 336(SP),AX MULQ 120(SP) ADDQ AX,R8 ADCQ DX,R9 MOVQ 336(SP),AX MULQ 128(SP) ADDQ AX,R10 ADCQ DX,R11 MOVQ 288(SP),AX MULQ 96(SP) ADDQ AX,R14 ADCQ DX,R15 MOVQ 344(SP),AX MULQ 112(SP) ADDQ AX,R8 ADCQ DX,R9 MOVQ 344(SP),AX MULQ 120(SP) ADDQ AX,R10 ADCQ DX,R11 MOVQ 344(SP),AX MULQ 128(SP) ADDQ AX,R12 ADCQ DX,R13 MOVQ ·REDMASK51(SB),DX SHLQ $13,CX:SI ANDQ DX,SI SHLQ $13,R9:R8 ANDQ DX,R8 ADDQ CX,R8 SHLQ $13,R11:R10 ANDQ DX,R10 ADDQ R9,R10 SHLQ $13,R13:R12 ANDQ DX,R12 ADDQ R11,R12 SHLQ $13,R15:R14 ANDQ DX,R14 ADDQ R13,R14 IMUL3Q $19,R15,CX ADDQ CX,SI MOVQ SI,CX SHRQ $51,CX ADDQ R8,CX MOVQ CX,R8 SHRQ $51,CX ANDQ DX,SI ADDQ R10,CX MOVQ CX,R9 SHRQ $51,CX ANDQ DX,R8 ADDQ R12,CX MOVQ CX,AX SHRQ $51,CX ANDQ DX,R9 ADDQ R14,CX MOVQ CX,R10 SHRQ $51,CX ANDQ DX,AX IMUL3Q $19,CX,CX ADDQ CX,SI ANDQ DX,R10 MOVQ SI,96(SP) MOVQ R8,104(SP) MOVQ R9,112(SP) MOVQ AX,120(SP) MOVQ R10,128(SP) MOVQ 320(SP),SI IMUL3Q $19,SI,AX MOVQ AX,256(SP) MULQ 72(SP) MOVQ AX,SI MOVQ DX,CX MOVQ 328(SP),DX IMUL3Q $19,DX,AX MOVQ AX,264(SP) MULQ 64(SP) ADDQ AX,SI ADCQ DX,CX MOVQ 296(SP),AX MULQ 56(SP) ADDQ AX,SI ADCQ DX,CX MOVQ 296(SP),AX MULQ 64(SP) MOVQ AX,R8 MOVQ DX,R9 MOVQ 296(SP),AX MULQ 72(SP) MOVQ AX,R10 MOVQ DX,R11 MOVQ 296(SP),AX MULQ 80(SP) MOVQ AX,R12 MOVQ DX,R13 MOVQ 296(SP),AX MULQ 88(SP) MOVQ AX,R14 MOVQ DX,R15 MOVQ 304(SP),AX MULQ 56(SP) ADDQ AX,R8 ADCQ DX,R9 MOVQ 304(SP),AX MULQ 64(SP) ADDQ AX,R10 ADCQ DX,R11 MOVQ 304(SP),AX MULQ 72(SP) ADDQ AX,R12 ADCQ DX,R13 MOVQ 304(SP),AX MULQ 80(SP) ADDQ AX,R14 ADCQ DX,R15 MOVQ 304(SP),DX IMUL3Q $19,DX,AX MULQ 88(SP) ADDQ AX,SI ADCQ DX,CX MOVQ 312(SP),AX MULQ 56(SP) ADDQ AX,R10 ADCQ DX,R11 MOVQ 312(SP),AX MULQ 64(SP) ADDQ AX,R12 ADCQ DX,R13 MOVQ 312(SP),AX MULQ 72(SP) ADDQ AX,R14 ADCQ DX,R15 MOVQ 312(SP),DX IMUL3Q $19,DX,AX MULQ 80(SP) ADDQ AX,SI ADCQ DX,CX MOVQ 312(SP),DX IMUL3Q $19,DX,AX MULQ 88(SP) ADDQ AX,R8 ADCQ DX,R9 MOVQ 320(SP),AX MULQ 56(SP) ADDQ AX,R12 ADCQ DX,R13 MOVQ 320(SP),AX MULQ 64(SP) ADDQ AX,R14 ADCQ DX,R15 MOVQ 256(SP),AX MULQ 80(SP) ADDQ AX,R8 ADCQ DX,R9 MOVQ 256(SP),AX MULQ 88(SP) ADDQ AX,R10 ADCQ DX,R11 MOVQ 328(SP),AX MULQ 56(SP) ADDQ AX,R14 ADCQ DX,R15 MOVQ 264(SP),AX MULQ 72(SP) ADDQ AX,R8 ADCQ DX,R9 MOVQ 264(SP),AX MULQ 80(SP) ADDQ AX,R10 ADCQ DX,R11 MOVQ 264(SP),AX MULQ 88(SP) ADDQ AX,R12 ADCQ DX,R13 MOVQ ·REDMASK51(SB),DX SHLQ $13,CX:SI ANDQ DX,SI SHLQ $13,R9:R8 ANDQ DX,R8 ADDQ CX,R8 SHLQ $13,R11:R10 ANDQ DX,R10 ADDQ R9,R10 SHLQ $13,R13:R12 ANDQ DX,R12 ADDQ R11,R12 SHLQ $13,R15:R14 ANDQ DX,R14 ADDQ R13,R14 IMUL3Q $19,R15,CX ADDQ CX,SI MOVQ SI,CX SHRQ $51,CX ADDQ R8,CX MOVQ CX,R8 SHRQ $51,CX ANDQ DX,SI ADDQ R10,CX MOVQ CX,R9 SHRQ $51,CX ANDQ DX,R8 ADDQ R12,CX MOVQ CX,AX SHRQ $51,CX ANDQ DX,R9 ADDQ R14,CX MOVQ CX,R10 SHRQ $51,CX ANDQ DX,AX IMUL3Q $19,CX,CX ADDQ CX,SI ANDQ DX,R10 MOVQ SI,DX MOVQ R8,CX MOVQ R9,R11 MOVQ AX,R12 MOVQ R10,R13 ADDQ ·_2P0(SB),DX ADDQ ·_2P1234(SB),CX ADDQ ·_2P1234(SB),R11 ADDQ ·_2P1234(SB),R12 ADDQ ·_2P1234(SB),R13 ADDQ 96(SP),SI ADDQ 104(SP),R8 ADDQ 112(SP),R9 ADDQ 120(SP),AX ADDQ 128(SP),R10 SUBQ 96(SP),DX SUBQ 104(SP),CX SUBQ 112(SP),R11 SUBQ 120(SP),R12 SUBQ 128(SP),R13 MOVQ SI,120(DI) MOVQ R8,128(DI) MOVQ R9,136(DI) MOVQ AX,144(DI) MOVQ R10,152(DI) MOVQ DX,160(DI) MOVQ CX,168(DI) MOVQ R11,176(DI) MOVQ R12,184(DI) MOVQ R13,192(DI) MOVQ 120(DI),AX MULQ 120(DI) MOVQ AX,SI MOVQ DX,CX MOVQ 120(DI),AX SHLQ $1,AX MULQ 128(DI) MOVQ AX,R8 MOVQ DX,R9 MOVQ 120(DI),AX SHLQ $1,AX MULQ 136(DI) MOVQ AX,R10 MOVQ DX,R11 MOVQ 120(DI),AX SHLQ $1,AX MULQ 144(DI) MOVQ AX,R12 MOVQ DX,R13 MOVQ 120(DI),AX SHLQ $1,AX MULQ 152(DI) MOVQ AX,R14 MOVQ DX,R15 MOVQ 128(DI),AX MULQ 128(DI) ADDQ AX,R10 ADCQ DX,R11 MOVQ 128(DI),AX SHLQ $1,AX MULQ 136(DI) ADDQ AX,R12 ADCQ DX,R13 MOVQ 128(DI),AX SHLQ $1,AX MULQ 144(DI) ADDQ AX,R14 ADCQ DX,R15 MOVQ 128(DI),DX IMUL3Q $38,DX,AX MULQ 152(DI) ADDQ AX,SI ADCQ DX,CX MOVQ 136(DI),AX MULQ 136(DI) ADDQ AX,R14 ADCQ DX,R15 MOVQ 136(DI),DX IMUL3Q $38,DX,AX MULQ 144(DI) ADDQ AX,SI ADCQ DX,CX MOVQ 136(DI),DX IMUL3Q $38,DX,AX MULQ 152(DI) ADDQ AX,R8 ADCQ DX,R9 MOVQ 144(DI),DX IMUL3Q $19,DX,AX MULQ 144(DI) ADDQ AX,R8 ADCQ DX,R9 MOVQ 144(DI),DX IMUL3Q $38,DX,AX MULQ 152(DI) ADDQ AX,R10 ADCQ DX,R11 MOVQ 152(DI),DX IMUL3Q $19,DX,AX MULQ 152(DI) ADDQ AX,R12 ADCQ DX,R13 MOVQ ·REDMASK51(SB),DX SHLQ $13,CX:SI ANDQ DX,SI SHLQ $13,R9:R8 ANDQ DX,R8 ADDQ CX,R8 SHLQ $13,R11:R10 ANDQ DX,R10 ADDQ R9,R10 SHLQ $13,R13:R12 ANDQ DX,R12 ADDQ R11,R12 SHLQ $13,R15:R14 ANDQ DX,R14 ADDQ R13,R14 IMUL3Q $19,R15,CX ADDQ CX,SI MOVQ SI,CX SHRQ $51,CX ADDQ R8,CX ANDQ DX,SI MOVQ CX,R8 SHRQ $51,CX ADDQ R10,CX ANDQ DX,R8 MOVQ CX,R9 SHRQ $51,CX ADDQ R12,CX ANDQ DX,R9 MOVQ CX,AX SHRQ $51,CX ADDQ R14,CX ANDQ DX,AX MOVQ CX,R10 SHRQ $51,CX IMUL3Q $19,CX,CX ADDQ CX,SI ANDQ DX,R10 MOVQ SI,120(DI) MOVQ R8,128(DI) MOVQ R9,136(DI) MOVQ AX,144(DI) MOVQ R10,152(DI) MOVQ 160(DI),AX MULQ 160(DI) MOVQ AX,SI MOVQ DX,CX MOVQ 160(DI),AX SHLQ $1,AX MULQ 168(DI) MOVQ AX,R8 MOVQ DX,R9 MOVQ 160(DI),AX SHLQ $1,AX MULQ 176(DI) MOVQ AX,R10 MOVQ DX,R11 MOVQ 160(DI),AX SHLQ $1,AX MULQ 184(DI) MOVQ AX,R12 MOVQ DX,R13 MOVQ 160(DI),AX SHLQ $1,AX MULQ 192(DI) MOVQ AX,R14 MOVQ DX,R15 MOVQ 168(DI),AX MULQ 168(DI) ADDQ AX,R10 ADCQ DX,R11 MOVQ 168(DI),AX SHLQ $1,AX MULQ 176(DI) ADDQ AX,R12 ADCQ DX,R13 MOVQ 168(DI),AX SHLQ $1,AX MULQ 184(DI) ADDQ AX,R14 ADCQ DX,R15 MOVQ 168(DI),DX IMUL3Q $38,DX,AX MULQ 192(DI) ADDQ AX,SI ADCQ DX,CX MOVQ 176(DI),AX MULQ 176(DI) ADDQ AX,R14 ADCQ DX,R15 MOVQ 176(DI),DX IMUL3Q $38,DX,AX MULQ 184(DI) ADDQ AX,SI ADCQ DX,CX MOVQ 176(DI),DX IMUL3Q $38,DX,AX MULQ 192(DI) ADDQ AX,R8 ADCQ DX,R9 MOVQ 184(DI),DX IMUL3Q $19,DX,AX MULQ 184(DI) ADDQ AX,R8 ADCQ DX,R9 MOVQ 184(DI),DX IMUL3Q $38,DX,AX MULQ 192(DI) ADDQ AX,R10 ADCQ DX,R11 MOVQ 192(DI),DX IMUL3Q $19,DX,AX MULQ 192(DI) ADDQ AX,R12 ADCQ DX,R13 MOVQ ·REDMASK51(SB),DX SHLQ $13,CX:SI ANDQ DX,SI SHLQ $13,R9:R8 ANDQ DX,R8 ADDQ CX,R8 SHLQ $13,R11:R10 ANDQ DX,R10 ADDQ R9,R10 SHLQ $13,R13:R12 ANDQ DX,R12 ADDQ R11,R12 SHLQ $13,R15:R14 ANDQ DX,R14 ADDQ R13,R14 IMUL3Q $19,R15,CX ADDQ CX,SI MOVQ SI,CX SHRQ $51,CX ADDQ R8,CX ANDQ DX,SI MOVQ CX,R8 SHRQ $51,CX ADDQ R10,CX ANDQ DX,R8 MOVQ CX,R9 SHRQ $51,CX ADDQ R12,CX ANDQ DX,R9 MOVQ CX,AX SHRQ $51,CX ADDQ R14,CX ANDQ DX,AX MOVQ CX,R10 SHRQ $51,CX IMUL3Q $19,CX,CX ADDQ CX,SI ANDQ DX,R10 MOVQ SI,160(DI) MOVQ R8,168(DI) MOVQ R9,176(DI) MOVQ AX,184(DI) MOVQ R10,192(DI) MOVQ 184(DI),SI IMUL3Q $19,SI,AX MOVQ AX,56(SP) MULQ 16(DI) MOVQ AX,SI MOVQ DX,CX MOVQ 192(DI),DX IMUL3Q $19,DX,AX MOVQ AX,64(SP) MULQ 8(DI) ADDQ AX,SI ADCQ DX,CX MOVQ 160(DI),AX MULQ 0(DI) ADDQ AX,SI ADCQ DX,CX MOVQ 160(DI),AX MULQ 8(DI) MOVQ AX,R8 MOVQ DX,R9 MOVQ 160(DI),AX MULQ 16(DI) MOVQ AX,R10 MOVQ DX,R11 MOVQ 160(DI),AX MULQ 24(DI) MOVQ AX,R12 MOVQ DX,R13 MOVQ 160(DI),AX MULQ 32(DI) MOVQ AX,R14 MOVQ DX,R15 MOVQ 168(DI),AX MULQ 0(DI) ADDQ AX,R8 ADCQ DX,R9 MOVQ 168(DI),AX MULQ 8(DI) ADDQ AX,R10 ADCQ DX,R11 MOVQ 168(DI),AX MULQ 16(DI) ADDQ AX,R12 ADCQ DX,R13 MOVQ 168(DI),AX MULQ 24(DI) ADDQ AX,R14 ADCQ DX,R15 MOVQ 168(DI),DX IMUL3Q $19,DX,AX MULQ 32(DI) ADDQ AX,SI ADCQ DX,CX MOVQ 176(DI),AX MULQ 0(DI) ADDQ AX,R10 ADCQ DX,R11 MOVQ 176(DI),AX MULQ 8(DI) ADDQ AX,R12 ADCQ DX,R13 MOVQ 176(DI),AX MULQ 16(DI) ADDQ AX,R14 ADCQ DX,R15 MOVQ 176(DI),DX IMUL3Q $19,DX,AX MULQ 24(DI) ADDQ AX,SI ADCQ DX,CX MOVQ 176(DI),DX IMUL3Q $19,DX,AX MULQ 32(DI) ADDQ AX,R8 ADCQ DX,R9 MOVQ 184(DI),AX MULQ 0(DI) ADDQ AX,R12 ADCQ DX,R13 MOVQ 184(DI),AX MULQ 8(DI) ADDQ AX,R14 ADCQ DX,R15 MOVQ 56(SP),AX MULQ 24(DI) ADDQ AX,R8 ADCQ DX,R9 MOVQ 56(SP),AX MULQ 32(DI) ADDQ AX,R10 ADCQ DX,R11 MOVQ 192(DI),AX MULQ 0(DI) ADDQ AX,R14 ADCQ DX,R15 MOVQ 64(SP),AX MULQ 16(DI) ADDQ AX,R8 ADCQ DX,R9 MOVQ 64(SP),AX MULQ 24(DI) ADDQ AX,R10 ADCQ DX,R11 MOVQ 64(SP),AX MULQ 32(DI) ADDQ AX,R12 ADCQ DX,R13 MOVQ ·REDMASK51(SB),DX SHLQ $13,CX:SI ANDQ DX,SI SHLQ $13,R9:R8 ANDQ DX,R8 ADDQ CX,R8 SHLQ $13,R11:R10 ANDQ DX,R10 ADDQ R9,R10 SHLQ $13,R13:R12 ANDQ DX,R12 ADDQ R11,R12 SHLQ $13,R15:R14 ANDQ DX,R14 ADDQ R13,R14 IMUL3Q $19,R15,CX ADDQ CX,SI MOVQ SI,CX SHRQ $51,CX ADDQ R8,CX MOVQ CX,R8 SHRQ $51,CX ANDQ DX,SI ADDQ R10,CX MOVQ CX,R9 SHRQ $51,CX ANDQ DX,R8 ADDQ R12,CX MOVQ CX,AX SHRQ $51,CX ANDQ DX,R9 ADDQ R14,CX MOVQ CX,R10 SHRQ $51,CX ANDQ DX,AX IMUL3Q $19,CX,CX ADDQ CX,SI ANDQ DX,R10 MOVQ SI,160(DI) MOVQ R8,168(DI) MOVQ R9,176(DI) MOVQ AX,184(DI) MOVQ R10,192(DI) MOVQ 200(SP),SI IMUL3Q $19,SI,AX MOVQ AX,56(SP) MULQ 152(SP) MOVQ AX,SI MOVQ DX,CX MOVQ 208(SP),DX IMUL3Q $19,DX,AX MOVQ AX,64(SP) MULQ 144(SP) ADDQ AX,SI ADCQ DX,CX MOVQ 176(SP),AX MULQ 136(SP) ADDQ AX,SI ADCQ DX,CX MOVQ 176(SP),AX MULQ 144(SP) MOVQ AX,R8 MOVQ DX,R9 MOVQ 176(SP),AX MULQ 152(SP) MOVQ AX,R10 MOVQ DX,R11 MOVQ 176(SP),AX MULQ 160(SP) MOVQ AX,R12 MOVQ DX,R13 MOVQ 176(SP),AX MULQ 168(SP) MOVQ AX,R14 MOVQ DX,R15 MOVQ 184(SP),AX MULQ 136(SP) ADDQ AX,R8 ADCQ DX,R9 MOVQ 184(SP),AX MULQ 144(SP) ADDQ AX,R10 ADCQ DX,R11 MOVQ 184(SP),AX MULQ 152(SP) ADDQ AX,R12 ADCQ DX,R13 MOVQ 184(SP),AX MULQ 160(SP) ADDQ AX,R14 ADCQ DX,R15 MOVQ 184(SP),DX IMUL3Q $19,DX,AX MULQ 168(SP) ADDQ AX,SI ADCQ DX,CX MOVQ 192(SP),AX MULQ 136(SP) ADDQ AX,R10 ADCQ DX,R11 MOVQ 192(SP),AX MULQ 144(SP) ADDQ AX,R12 ADCQ DX,R13 MOVQ 192(SP),AX MULQ 152(SP) ADDQ AX,R14 ADCQ DX,R15 MOVQ 192(SP),DX IMUL3Q $19,DX,AX MULQ 160(SP) ADDQ AX,SI ADCQ DX,CX MOVQ 192(SP),DX IMUL3Q $19,DX,AX MULQ 168(SP) ADDQ AX,R8 ADCQ DX,R9 MOVQ 200(SP),AX MULQ 136(SP) ADDQ AX,R12 ADCQ DX,R13 MOVQ 200(SP),AX MULQ 144(SP) ADDQ AX,R14 ADCQ DX,R15 MOVQ 56(SP),AX MULQ 160(SP) ADDQ AX,R8 ADCQ DX,R9 MOVQ 56(SP),AX MULQ 168(SP) ADDQ AX,R10 ADCQ DX,R11 MOVQ 208(SP),AX MULQ 136(SP) ADDQ AX,R14 ADCQ DX,R15 MOVQ 64(SP),AX MULQ 152(SP) ADDQ AX,R8 ADCQ DX,R9 MOVQ 64(SP),AX MULQ 160(SP) ADDQ AX,R10 ADCQ DX,R11 MOVQ 64(SP),AX MULQ 168(SP) ADDQ AX,R12 ADCQ DX,R13 MOVQ ·REDMASK51(SB),DX SHLQ $13,CX:SI ANDQ DX,SI SHLQ $13,R9:R8 ANDQ DX,R8 ADDQ CX,R8 SHLQ $13,R11:R10 ANDQ DX,R10 ADDQ R9,R10 SHLQ $13,R13:R12 ANDQ DX,R12 ADDQ R11,R12 SHLQ $13,R15:R14 ANDQ DX,R14 ADDQ R13,R14 IMUL3Q $19,R15,CX ADDQ CX,SI MOVQ SI,CX SHRQ $51,CX ADDQ R8,CX MOVQ CX,R8 SHRQ $51,CX ANDQ DX,SI ADDQ R10,CX MOVQ CX,R9 SHRQ $51,CX ANDQ DX,R8 ADDQ R12,CX MOVQ CX,AX SHRQ $51,CX ANDQ DX,R9 ADDQ R14,CX MOVQ CX,R10 SHRQ $51,CX ANDQ DX,AX IMUL3Q $19,CX,CX ADDQ CX,SI ANDQ DX,R10 MOVQ SI,40(DI) MOVQ R8,48(DI) MOVQ R9,56(DI) MOVQ AX,64(DI) MOVQ R10,72(DI) MOVQ 216(SP),AX MULQ ·_121666_213(SB) SHRQ $13,AX MOVQ AX,SI MOVQ DX,CX MOVQ 224(SP),AX MULQ ·_121666_213(SB) SHRQ $13,AX ADDQ AX,CX MOVQ DX,R8 MOVQ 232(SP),AX MULQ ·_121666_213(SB) SHRQ $13,AX ADDQ AX,R8 MOVQ DX,R9 MOVQ 240(SP),AX MULQ ·_121666_213(SB) SHRQ $13,AX ADDQ AX,R9 MOVQ DX,R10 MOVQ 248(SP),AX MULQ ·_121666_213(SB) SHRQ $13,AX ADDQ AX,R10 IMUL3Q $19,DX,DX ADDQ DX,SI ADDQ 136(SP),SI ADDQ 144(SP),CX ADDQ 152(SP),R8 ADDQ 160(SP),R9 ADDQ 168(SP),R10 MOVQ SI,80(DI) MOVQ CX,88(DI) MOVQ R8,96(DI) MOVQ R9,104(DI) MOVQ R10,112(DI) MOVQ 104(DI),SI IMUL3Q $19,SI,AX MOVQ AX,56(SP) MULQ 232(SP) MOVQ AX,SI MOVQ DX,CX MOVQ 112(DI),DX IMUL3Q $19,DX,AX MOVQ AX,64(SP) MULQ 224(SP) ADDQ AX,SI ADCQ DX,CX MOVQ 80(DI),AX MULQ 216(SP) ADDQ AX,SI ADCQ DX,CX MOVQ 80(DI),AX MULQ 224(SP) MOVQ AX,R8 MOVQ DX,R9 MOVQ 80(DI),AX MULQ 232(SP) MOVQ AX,R10 MOVQ DX,R11 MOVQ 80(DI),AX MULQ 240(SP) MOVQ AX,R12 MOVQ DX,R13 MOVQ 80(DI),AX MULQ 248(SP) MOVQ AX,R14 MOVQ DX,R15 MOVQ 88(DI),AX MULQ 216(SP) ADDQ AX,R8 ADCQ DX,R9 MOVQ 88(DI),AX MULQ 224(SP) ADDQ AX,R10 ADCQ DX,R11 MOVQ 88(DI),AX MULQ 232(SP) ADDQ AX,R12 ADCQ DX,R13 MOVQ 88(DI),AX MULQ 240(SP) ADDQ AX,R14 ADCQ DX,R15 MOVQ 88(DI),DX IMUL3Q $19,DX,AX MULQ 248(SP) ADDQ AX,SI ADCQ DX,CX MOVQ 96(DI),AX MULQ 216(SP) ADDQ AX,R10 ADCQ DX,R11 MOVQ 96(DI),AX MULQ 224(SP) ADDQ AX,R12 ADCQ DX,R13 MOVQ 96(DI),AX MULQ 232(SP) ADDQ AX,R14 ADCQ DX,R15 MOVQ 96(DI),DX IMUL3Q $19,DX,AX MULQ 240(SP) ADDQ AX,SI ADCQ DX,CX MOVQ 96(DI),DX IMUL3Q $19,DX,AX MULQ 248(SP) ADDQ AX,R8 ADCQ DX,R9 MOVQ 104(DI),AX MULQ 216(SP) ADDQ AX,R12 ADCQ DX,R13 MOVQ 104(DI),AX MULQ 224(SP) ADDQ AX,R14 ADCQ DX,R15 MOVQ 56(SP),AX MULQ 240(SP) ADDQ AX,R8 ADCQ DX,R9 MOVQ 56(SP),AX MULQ 248(SP) ADDQ AX,R10 ADCQ DX,R11 MOVQ 112(DI),AX MULQ 216(SP) ADDQ AX,R14 ADCQ DX,R15 MOVQ 64(SP),AX MULQ 232(SP) ADDQ AX,R8 ADCQ DX,R9 MOVQ 64(SP),AX MULQ 240(SP) ADDQ AX,R10 ADCQ DX,R11 MOVQ 64(SP),AX MULQ 248(SP) ADDQ AX,R12 ADCQ DX,R13 MOVQ ·REDMASK51(SB),DX SHLQ $13,CX:SI ANDQ DX,SI SHLQ $13,R9:R8 ANDQ DX,R8 ADDQ CX,R8 SHLQ $13,R11:R10 ANDQ DX,R10 ADDQ R9,R10 SHLQ $13,R13:R12 ANDQ DX,R12 ADDQ R11,R12 SHLQ $13,R15:R14 ANDQ DX,R14 ADDQ R13,R14 IMUL3Q $19,R15,CX ADDQ CX,SI MOVQ SI,CX SHRQ $51,CX ADDQ R8,CX MOVQ CX,R8 SHRQ $51,CX ANDQ DX,SI ADDQ R10,CX MOVQ CX,R9 SHRQ $51,CX ANDQ DX,R8 ADDQ R12,CX MOVQ CX,AX SHRQ $51,CX ANDQ DX,R9 ADDQ R14,CX MOVQ CX,R10 SHRQ $51,CX ANDQ DX,AX IMUL3Q $19,CX,CX ADDQ CX,SI ANDQ DX,R10 MOVQ SI,80(DI) MOVQ R8,88(DI) MOVQ R9,96(DI) MOVQ AX,104(DI) MOVQ R10,112(DI) MOVQ 0(SP),R11 MOVQ 8(SP),R12 MOVQ 16(SP),R13 MOVQ 24(SP),R14 MOVQ 32(SP),R15 MOVQ 40(SP),BX MOVQ 48(SP),BP MOVQ R11,SP MOVQ DI,AX MOVQ SI,DX RET lxd-2.0.0/dist/src/golang.org/x/crypto/LICENSE0000644061062106075000000000270712702772344023307 0ustar00stgraberdomain admins00000000000000Copyright (c) 2009 The Go Authors. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Google Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. lxd-2.0.0/dist/src/golang.org/x/crypto/CONTRIBUTORS0000644061062106075000000000025212702772344024153 0ustar00stgraberdomain admins00000000000000# This source code was written by the Go contributors. # The master list of contributors is in the main Go distribution, # visible at http://tip.golang.org/CONTRIBUTORS. lxd-2.0.0/dist/src/golang.org/x/crypto/ripemd160/0000755061062106075000000000000012702772344024003 5ustar00stgraberdomain admins00000000000000lxd-2.0.0/dist/src/golang.org/x/crypto/ripemd160/ripemd160.go0000644061062106075000000000465412702772344026052 0ustar00stgraberdomain admins00000000000000// Copyright 2010 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Package ripemd160 implements the RIPEMD-160 hash algorithm. package ripemd160 // import "golang.org/x/crypto/ripemd160" // RIPEMD-160 is designed by by Hans Dobbertin, Antoon Bosselaers, and Bart // Preneel with specifications available at: // http://homes.esat.kuleuven.be/~cosicart/pdf/AB-9601/AB-9601.pdf. import ( "crypto" "hash" ) func init() { crypto.RegisterHash(crypto.RIPEMD160, New) } // The size of the checksum in bytes. const Size = 20 // The block size of the hash algorithm in bytes. const BlockSize = 64 const ( _s0 = 0x67452301 _s1 = 0xefcdab89 _s2 = 0x98badcfe _s3 = 0x10325476 _s4 = 0xc3d2e1f0 ) // digest represents the partial evaluation of a checksum. type digest struct { s [5]uint32 // running context x [BlockSize]byte // temporary buffer nx int // index into x tc uint64 // total count of bytes processed } func (d *digest) Reset() { d.s[0], d.s[1], d.s[2], d.s[3], d.s[4] = _s0, _s1, _s2, _s3, _s4 d.nx = 0 d.tc = 0 } // New returns a new hash.Hash computing the checksum. func New() hash.Hash { result := new(digest) result.Reset() return result } func (d *digest) Size() int { return Size } func (d *digest) BlockSize() int { return BlockSize } func (d *digest) Write(p []byte) (nn int, err error) { nn = len(p) d.tc += uint64(nn) if d.nx > 0 { n := len(p) if n > BlockSize-d.nx { n = BlockSize - d.nx } for i := 0; i < n; i++ { d.x[d.nx+i] = p[i] } d.nx += n if d.nx == BlockSize { _Block(d, d.x[0:]) d.nx = 0 } p = p[n:] } n := _Block(d, p) p = p[n:] if len(p) > 0 { d.nx = copy(d.x[:], p) } return } func (d0 *digest) Sum(in []byte) []byte { // Make a copy of d0 so that caller can keep writing and summing. d := *d0 // Padding. Add a 1 bit and 0 bits until 56 bytes mod 64. tc := d.tc var tmp [64]byte tmp[0] = 0x80 if tc%64 < 56 { d.Write(tmp[0 : 56-tc%64]) } else { d.Write(tmp[0 : 64+56-tc%64]) } // Length in bits. tc <<= 3 for i := uint(0); i < 8; i++ { tmp[i] = byte(tc >> (8 * i)) } d.Write(tmp[0:8]) if d.nx != 0 { panic("d.nx != 0") } var digest [Size]byte for i, s := range d.s { digest[i*4] = byte(s) digest[i*4+1] = byte(s >> 8) digest[i*4+2] = byte(s >> 16) digest[i*4+3] = byte(s >> 24) } return append(in, digest[:]...) } lxd-2.0.0/dist/src/golang.org/x/crypto/ripemd160/ripemd160block.go0000644061062106075000000001024112702772344027052 0ustar00stgraberdomain admins00000000000000// Copyright 2010 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // RIPEMD-160 block step. // In its own file so that a faster assembly or C version // can be substituted easily. package ripemd160 // work buffer indices and roll amounts for one line var _n = [80]uint{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8, 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12, 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2, 4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13, } var _r = [80]uint{ 11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8, 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12, 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5, 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12, 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6, } // same for the other parallel one var n_ = [80]uint{ 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12, 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2, 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13, 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14, 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11, } var r_ = [80]uint{ 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6, 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11, 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5, 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8, 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11, } func _Block(md *digest, p []byte) int { n := 0 var x [16]uint32 var alpha, beta uint32 for len(p) >= BlockSize { a, b, c, d, e := md.s[0], md.s[1], md.s[2], md.s[3], md.s[4] aa, bb, cc, dd, ee := a, b, c, d, e j := 0 for i := 0; i < 16; i++ { x[i] = uint32(p[j]) | uint32(p[j+1])<<8 | uint32(p[j+2])<<16 | uint32(p[j+3])<<24 j += 4 } // round 1 i := 0 for i < 16 { alpha = a + (b ^ c ^ d) + x[_n[i]] s := _r[i] alpha = (alpha<>(32-s)) + e beta = c<<10 | c>>22 a, b, c, d, e = e, alpha, b, beta, d // parallel line alpha = aa + (bb ^ (cc | ^dd)) + x[n_[i]] + 0x50a28be6 s = r_[i] alpha = (alpha<>(32-s)) + ee beta = cc<<10 | cc>>22 aa, bb, cc, dd, ee = ee, alpha, bb, beta, dd i++ } // round 2 for i < 32 { alpha = a + (b&c | ^b&d) + x[_n[i]] + 0x5a827999 s := _r[i] alpha = (alpha<>(32-s)) + e beta = c<<10 | c>>22 a, b, c, d, e = e, alpha, b, beta, d // parallel line alpha = aa + (bb&dd | cc&^dd) + x[n_[i]] + 0x5c4dd124 s = r_[i] alpha = (alpha<>(32-s)) + ee beta = cc<<10 | cc>>22 aa, bb, cc, dd, ee = ee, alpha, bb, beta, dd i++ } // round 3 for i < 48 { alpha = a + (b | ^c ^ d) + x[_n[i]] + 0x6ed9eba1 s := _r[i] alpha = (alpha<>(32-s)) + e beta = c<<10 | c>>22 a, b, c, d, e = e, alpha, b, beta, d // parallel line alpha = aa + (bb | ^cc ^ dd) + x[n_[i]] + 0x6d703ef3 s = r_[i] alpha = (alpha<>(32-s)) + ee beta = cc<<10 | cc>>22 aa, bb, cc, dd, ee = ee, alpha, bb, beta, dd i++ } // round 4 for i < 64 { alpha = a + (b&d | c&^d) + x[_n[i]] + 0x8f1bbcdc s := _r[i] alpha = (alpha<>(32-s)) + e beta = c<<10 | c>>22 a, b, c, d, e = e, alpha, b, beta, d // parallel line alpha = aa + (bb&cc | ^bb&dd) + x[n_[i]] + 0x7a6d76e9 s = r_[i] alpha = (alpha<>(32-s)) + ee beta = cc<<10 | cc>>22 aa, bb, cc, dd, ee = ee, alpha, bb, beta, dd i++ } // round 5 for i < 80 { alpha = a + (b ^ (c | ^d)) + x[_n[i]] + 0xa953fd4e s := _r[i] alpha = (alpha<>(32-s)) + e beta = c<<10 | c>>22 a, b, c, d, e = e, alpha, b, beta, d // parallel line alpha = aa + (bb ^ cc ^ dd) + x[n_[i]] s = r_[i] alpha = (alpha<>(32-s)) + ee beta = cc<<10 | cc>>22 aa, bb, cc, dd, ee = ee, alpha, bb, beta, dd i++ } // combine results dd += c + md.s[1] md.s[1] = md.s[2] + d + ee md.s[2] = md.s[3] + e + aa md.s[3] = md.s[4] + a + bb md.s[4] = md.s[0] + b + cc md.s[0] = dd p = p[BlockSize:] n += BlockSize } return n } lxd-2.0.0/dist/src/golang.org/x/crypto/ripemd160/ripemd160_test.go0000644061062106075000000000337712702772344027112 0ustar00stgraberdomain admins00000000000000// Copyright 2010 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package ripemd160 // Test vectors are from: // http://homes.esat.kuleuven.be/~bosselae/ripemd160.html import ( "fmt" "io" "testing" ) type mdTest struct { out string in string } var vectors = [...]mdTest{ {"9c1185a5c5e9fc54612808977ee8f548b2258d31", ""}, {"0bdc9d2d256b3ee9daae347be6f4dc835a467ffe", "a"}, {"8eb208f7e05d987a9b044a8e98c6b087f15a0bfc", "abc"}, {"5d0689ef49d2fae572b881b123a85ffa21595f36", "message digest"}, {"f71c27109c692c1b56bbdceb5b9d2865b3708dbc", "abcdefghijklmnopqrstuvwxyz"}, {"12a053384a9c0c88e405a06c27dcf49ada62eb2b", "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"}, {"b0e20b6e3116640286ed3a87a5713079b21f5189", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"}, {"9b752e45573d4b39f4dbd3323cab82bf63326bfb", "12345678901234567890123456789012345678901234567890123456789012345678901234567890"}, } func TestVectors(t *testing.T) { for i := 0; i < len(vectors); i++ { tv := vectors[i] md := New() for j := 0; j < 3; j++ { if j < 2 { io.WriteString(md, tv.in) } else { io.WriteString(md, tv.in[0:len(tv.in)/2]) md.Sum(nil) io.WriteString(md, tv.in[len(tv.in)/2:]) } s := fmt.Sprintf("%x", md.Sum(nil)) if s != tv.out { t.Fatalf("RIPEMD-160[%d](%s) = %s, expected %s", j, tv.in, s, tv.out) } md.Reset() } } } func TestMillionA(t *testing.T) { md := New() for i := 0; i < 100000; i++ { io.WriteString(md, "aaaaaaaaaa") } out := "52783243c1697bdbe16d37f97f68f08325dc1528" s := fmt.Sprintf("%x", md.Sum(nil)) if s != out { t.Fatalf("RIPEMD-160 (1 million 'a') = %s, expected %s", s, out) } md.Reset() } lxd-2.0.0/dist/src/golang.org/x/crypto/md4/0000755061062106075000000000000012702772344022760 5ustar00stgraberdomain admins00000000000000lxd-2.0.0/dist/src/golang.org/x/crypto/md4/md4.go0000644061062106075000000000411412702772344023773 0ustar00stgraberdomain admins00000000000000// Copyright 2009 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Package md4 implements the MD4 hash algorithm as defined in RFC 1320. package md4 // import "golang.org/x/crypto/md4" import ( "crypto" "hash" ) func init() { crypto.RegisterHash(crypto.MD4, New) } // The size of an MD4 checksum in bytes. const Size = 16 // The blocksize of MD4 in bytes. const BlockSize = 64 const ( _Chunk = 64 _Init0 = 0x67452301 _Init1 = 0xEFCDAB89 _Init2 = 0x98BADCFE _Init3 = 0x10325476 ) // digest represents the partial evaluation of a checksum. type digest struct { s [4]uint32 x [_Chunk]byte nx int len uint64 } func (d *digest) Reset() { d.s[0] = _Init0 d.s[1] = _Init1 d.s[2] = _Init2 d.s[3] = _Init3 d.nx = 0 d.len = 0 } // New returns a new hash.Hash computing the MD4 checksum. func New() hash.Hash { d := new(digest) d.Reset() return d } func (d *digest) Size() int { return Size } func (d *digest) BlockSize() int { return BlockSize } func (d *digest) Write(p []byte) (nn int, err error) { nn = len(p) d.len += uint64(nn) if d.nx > 0 { n := len(p) if n > _Chunk-d.nx { n = _Chunk - d.nx } for i := 0; i < n; i++ { d.x[d.nx+i] = p[i] } d.nx += n if d.nx == _Chunk { _Block(d, d.x[0:]) d.nx = 0 } p = p[n:] } n := _Block(d, p) p = p[n:] if len(p) > 0 { d.nx = copy(d.x[:], p) } return } func (d0 *digest) Sum(in []byte) []byte { // Make a copy of d0, so that caller can keep writing and summing. d := new(digest) *d = *d0 // Padding. Add a 1 bit and 0 bits until 56 bytes mod 64. len := d.len var tmp [64]byte tmp[0] = 0x80 if len%64 < 56 { d.Write(tmp[0 : 56-len%64]) } else { d.Write(tmp[0 : 64+56-len%64]) } // Length in bits. len <<= 3 for i := uint(0); i < 8; i++ { tmp[i] = byte(len >> (8 * i)) } d.Write(tmp[0:8]) if d.nx != 0 { panic("d.nx != 0") } for _, s := range d.s { in = append(in, byte(s>>0)) in = append(in, byte(s>>8)) in = append(in, byte(s>>16)) in = append(in, byte(s>>24)) } return in } lxd-2.0.0/dist/src/golang.org/x/crypto/md4/md4_test.go0000644061062106075000000000635312702772344025041 0ustar00stgraberdomain admins00000000000000// Copyright 2009 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package md4 import ( "fmt" "io" "testing" ) type md4Test struct { out string in string } var golden = []md4Test{ {"31d6cfe0d16ae931b73c59d7e0c089c0", ""}, {"bde52cb31de33e46245e05fbdbd6fb24", "a"}, {"ec388dd78999dfc7cf4632465693b6bf", "ab"}, {"a448017aaf21d8525fc10ae87aa6729d", "abc"}, {"41decd8f579255c5200f86a4bb3ba740", "abcd"}, {"9803f4a34e8eb14f96adba49064a0c41", "abcde"}, {"804e7f1c2586e50b49ac65db5b645131", "abcdef"}, {"752f4adfe53d1da0241b5bc216d098fc", "abcdefg"}, {"ad9daf8d49d81988590a6f0e745d15dd", "abcdefgh"}, {"1e4e28b05464316b56402b3815ed2dfd", "abcdefghi"}, {"dc959c6f5d6f9e04e4380777cc964b3d", "abcdefghij"}, {"1b5701e265778898ef7de5623bbe7cc0", "Discard medicine more than two years old."}, {"d7f087e090fe7ad4a01cb59dacc9a572", "He who has a shady past knows that nice guys finish last."}, {"a6f8fd6df617c72837592fc3570595c9", "I wouldn't marry him with a ten foot pole."}, {"c92a84a9526da8abc240c05d6b1a1ce0", "Free! Free!/A trip/to Mars/for 900/empty jars/Burma Shave"}, {"f6013160c4dcb00847069fee3bb09803", "The days of the digital watch are numbered. -Tom Stoppard"}, {"2c3bb64f50b9107ed57640fe94bec09f", "Nepal premier won't resign."}, {"45b7d8a32c7806f2f7f897332774d6e4", "For every action there is an equal and opposite government program."}, {"b5b4f9026b175c62d7654bdc3a1cd438", "His money is twice tainted: 'taint yours and 'taint mine."}, {"caf44e80f2c20ce19b5ba1cab766e7bd", "There is no reason for any individual to have a computer in their home. -Ken Olsen, 1977"}, {"191fae6707f496aa54a6bce9f2ecf74d", "It's a tiny change to the code and not completely disgusting. - Bob Manchek"}, {"9ddc753e7a4ccee6081cd1b45b23a834", "size: a.out: bad magic"}, {"8d050f55b1cadb9323474564be08a521", "The major problem is with sendmail. -Mark Horton"}, {"ad6e2587f74c3e3cc19146f6127fa2e3", "Give me a rock, paper and scissors and I will move the world. CCFestoon"}, {"1d616d60a5fabe85589c3f1566ca7fca", "If the enemy is within range, then so are you."}, {"aec3326a4f496a2ced65a1963f84577f", "It's well we cannot hear the screams/That we create in others' dreams."}, {"77b4fd762d6b9245e61c50bf6ebf118b", "You remind me of a TV show, but that's all right: I watch it anyway."}, {"e8f48c726bae5e516f6ddb1a4fe62438", "C is as portable as Stonehedge!!"}, {"a3a84366e7219e887423b01f9be7166e", "Even if I could be Shakespeare, I think I should still choose to be Faraday. - A. Huxley"}, {"a6b7aa35157e984ef5d9b7f32e5fbb52", "The fugacity of a constituent in a mixture of gases at a given temperature is proportional to its mole fraction. Lewis-Randall Rule"}, {"75661f0545955f8f9abeeb17845f3fd6", "How can you write a big system without C++? -Paul Glick"}, } func TestGolden(t *testing.T) { for i := 0; i < len(golden); i++ { g := golden[i] c := New() for j := 0; j < 3; j++ { if j < 2 { io.WriteString(c, g.in) } else { io.WriteString(c, g.in[0:len(g.in)/2]) c.Sum(nil) io.WriteString(c, g.in[len(g.in)/2:]) } s := fmt.Sprintf("%x", c.Sum(nil)) if s != g.out { t.Fatalf("md4[%d](%s) = %s want %s", j, g.in, s, g.out) } c.Reset() } } } lxd-2.0.0/dist/src/golang.org/x/crypto/md4/md4block.go0000644061062106075000000000376412702772344025020 0ustar00stgraberdomain admins00000000000000// Copyright 2009 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // MD4 block step. // In its own file so that a faster assembly or C version // can be substituted easily. package md4 var shift1 = []uint{3, 7, 11, 19} var shift2 = []uint{3, 5, 9, 13} var shift3 = []uint{3, 9, 11, 15} var xIndex2 = []uint{0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15} var xIndex3 = []uint{0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15} func _Block(dig *digest, p []byte) int { a := dig.s[0] b := dig.s[1] c := dig.s[2] d := dig.s[3] n := 0 var X [16]uint32 for len(p) >= _Chunk { aa, bb, cc, dd := a, b, c, d j := 0 for i := 0; i < 16; i++ { X[i] = uint32(p[j]) | uint32(p[j+1])<<8 | uint32(p[j+2])<<16 | uint32(p[j+3])<<24 j += 4 } // If this needs to be made faster in the future, // the usual trick is to unroll each of these // loops by a factor of 4; that lets you replace // the shift[] lookups with constants and, // with suitable variable renaming in each // unrolled body, delete the a, b, c, d = d, a, b, c // (or you can let the optimizer do the renaming). // // The index variables are uint so that % by a power // of two can be optimized easily by a compiler. // Round 1. for i := uint(0); i < 16; i++ { x := i s := shift1[i%4] f := ((c ^ d) & b) ^ d a += f + X[x] a = a<>(32-s) a, b, c, d = d, a, b, c } // Round 2. for i := uint(0); i < 16; i++ { x := xIndex2[i] s := shift2[i%4] g := (b & c) | (b & d) | (c & d) a += g + X[x] + 0x5a827999 a = a<>(32-s) a, b, c, d = d, a, b, c } // Round 3. for i := uint(0); i < 16; i++ { x := xIndex3[i] s := shift3[i%4] h := b ^ c ^ d a += h + X[x] + 0x6ed9eba1 a = a<>(32-s) a, b, c, d = d, a, b, c } a += aa b += bb c += cc d += dd p = p[_Chunk:] n += _Chunk } dig.s[0] = a dig.s[1] = b dig.s[2] = c dig.s[3] = d return n } lxd-2.0.0/dist/src/golang.org/x/crypto/tea/0000755061062106075000000000000012702772344023045 5ustar00stgraberdomain admins00000000000000lxd-2.0.0/dist/src/golang.org/x/crypto/tea/tea_test.go0000644061062106075000000000532012702772344025204 0ustar00stgraberdomain admins00000000000000// Copyright 2015 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 tea import ( "bytes" "testing" ) // A sample test key for when we just want to initialize a cipher var testKey = []byte{0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF} // Test that the block size for tea is correct func TestBlocksize(t *testing.T) { c, err := NewCipher(testKey) if err != nil { t.Fatalf("NewCipher returned error: %s", err) } if result := c.BlockSize(); result != BlockSize { t.Errorf("cipher.BlockSize returned %d, but expected %d", result, BlockSize) } } // Test that invalid key sizes return an error func TestInvalidKeySize(t *testing.T) { var key [KeySize + 1]byte if _, err := NewCipher(key[:]); err == nil { t.Errorf("invalid key size %d didn't result in an error.", len(key)) } if _, err := NewCipher(key[:KeySize-1]); err == nil { t.Errorf("invalid key size %d didn't result in an error.", KeySize-1) } } // Test Vectors type teaTest struct { rounds int key []byte plaintext []byte ciphertext []byte } var teaTests = []teaTest{ // These were sourced from https://github.com/froydnj/ironclad/blob/master/testing/test-vectors/tea.testvec { numRounds, []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, []byte{0x41, 0xea, 0x3a, 0x0a, 0x94, 0xba, 0xa9, 0x40}, }, { numRounds, []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, []byte{0x31, 0x9b, 0xbe, 0xfb, 0x01, 0x6a, 0xbd, 0xb2}, }, { 16, []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, []byte{0xed, 0x28, 0x5d, 0xa1, 0x45, 0x5b, 0x33, 0xc1}, }, } // Test encryption func TestCipherEncrypt(t *testing.T) { // Test encryption with standard 64 rounds for i, test := range teaTests { c, err := NewCipherWithRounds(test.key, test.rounds) if err != nil { t.Fatalf("#%d: NewCipher returned error: %s", i, err) } var ciphertext [BlockSize]byte c.Encrypt(ciphertext[:], test.plaintext) if !bytes.Equal(ciphertext[:], test.ciphertext) { t.Errorf("#%d: incorrect ciphertext. Got %x, wanted %x", i, ciphertext, test.ciphertext) } var plaintext2 [BlockSize]byte c.Decrypt(plaintext2[:], ciphertext[:]) if !bytes.Equal(plaintext2[:], test.plaintext) { t.Errorf("#%d: incorrect plaintext. Got %x, wanted %x", i, plaintext2, test.plaintext) } } } lxd-2.0.0/dist/src/golang.org/x/crypto/tea/cipher.go0000644061062106075000000000602312702772344024647 0ustar00stgraberdomain admins00000000000000// Copyright 2015 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 tea implements the TEA algorithm, as defined in Needham and // Wheeler's 1994 technical report, “TEA, a Tiny Encryption Algorithmâ€. See // http://www.cix.co.uk/~klockstone/tea.pdf for details. package tea import ( "crypto/cipher" "encoding/binary" "errors" ) const ( // BlockSize is the size of a TEA block, in bytes. BlockSize = 8 // KeySize is the size of a TEA key, in bytes. KeySize = 16 // delta is the TEA key schedule constant. delta = 0x9e3779b9 // numRounds is the standard number of rounds in TEA. numRounds = 64 ) // tea is an instance of the TEA cipher with a particular key. type tea struct { key [16]byte rounds int } // NewCipher returns an instance of the TEA cipher with the standard number of // rounds. The key argument must be 16 bytes long. func NewCipher(key []byte) (cipher.Block, error) { return NewCipherWithRounds(key, numRounds) } // NewCipherWithRounds returns an instance of the TEA cipher with a given // number of rounds, which must be even. The key argument must be 16 bytes // long. func NewCipherWithRounds(key []byte, rounds int) (cipher.Block, error) { if len(key) != 16 { return nil, errors.New("tea: incorrect key size") } if rounds&1 != 0 { return nil, errors.New("tea: odd number of rounds specified") } c := &tea{ rounds: rounds, } copy(c.key[:], key) return c, nil } // BlockSize returns the TEA block size, which is eight bytes. It is necessary // to satisfy the Block interface in the package "crypto/cipher". func (*tea) BlockSize() int { return BlockSize } // Encrypt encrypts the 8 byte buffer src using the key in t and stores the // result in dst. Note that for amounts of data larger than a block, it is not // safe to just call Encrypt on successive blocks; instead, use an encryption // mode like CBC (see crypto/cipher/cbc.go). func (t *tea) Encrypt(dst, src []byte) { e := binary.BigEndian v0, v1 := e.Uint32(src), e.Uint32(src[4:]) k0, k1, k2, k3 := e.Uint32(t.key[0:]), e.Uint32(t.key[4:]), e.Uint32(t.key[8:]), e.Uint32(t.key[12:]) sum := uint32(0) delta := uint32(delta) for i := 0; i < t.rounds/2; i++ { sum += delta v0 += ((v1 << 4) + k0) ^ (v1 + sum) ^ ((v1 >> 5) + k1) v1 += ((v0 << 4) + k2) ^ (v0 + sum) ^ ((v0 >> 5) + k3) } e.PutUint32(dst, v0) e.PutUint32(dst[4:], v1) } // Decrypt decrypts the 8 byte buffer src using the key in t and stores the // result in dst. func (t *tea) Decrypt(dst, src []byte) { e := binary.BigEndian v0, v1 := e.Uint32(src), e.Uint32(src[4:]) k0, k1, k2, k3 := e.Uint32(t.key[0:]), e.Uint32(t.key[4:]), e.Uint32(t.key[8:]), e.Uint32(t.key[12:]) delta := uint32(delta) sum := delta * uint32(t.rounds/2) // in general, sum = delta * n for i := 0; i < t.rounds/2; i++ { v1 -= ((v0 << 4) + k2) ^ (v0 + sum) ^ ((v0 >> 5) + k3) v0 -= ((v1 << 4) + k0) ^ (v1 + sum) ^ ((v1 >> 5) + k1) sum -= delta } e.PutUint32(dst, v0) e.PutUint32(dst[4:], v1) } lxd-2.0.0/dist/src/golang.org/x/crypto/sha3/0000755061062106075000000000000012702772344023132 5ustar00stgraberdomain admins00000000000000lxd-2.0.0/dist/src/golang.org/x/crypto/sha3/sha3_test.go0000644061062106075000000002127012702772344025360 0ustar00stgraberdomain admins00000000000000// Copyright 2014 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 sha3 // Tests include all the ShortMsgKATs provided by the Keccak team at // https://github.com/gvanas/KeccakCodePackage // // They only include the zero-bit case of the bitwise testvectors // published by NIST in the draft of FIPS-202. import ( "bytes" "compress/flate" "encoding/hex" "encoding/json" "hash" "os" "strings" "testing" ) const ( testString = "brekeccakkeccak koax koax" katFilename = "testdata/keccakKats.json.deflate" ) // Internal-use instances of SHAKE used to test against KATs. func newHashShake128() hash.Hash { return &state{rate: 168, dsbyte: 0x1f, outputLen: 512} } func newHashShake256() hash.Hash { return &state{rate: 136, dsbyte: 0x1f, outputLen: 512} } // testDigests contains functions returning hash.Hash instances // with output-length equal to the KAT length for both SHA-3 and // SHAKE instances. var testDigests = map[string]func() hash.Hash{ "SHA3-224": New224, "SHA3-256": New256, "SHA3-384": New384, "SHA3-512": New512, "SHAKE128": newHashShake128, "SHAKE256": newHashShake256, } // testShakes contains functions that return ShakeHash instances for // testing the ShakeHash-specific interface. var testShakes = map[string]func() ShakeHash{ "SHAKE128": NewShake128, "SHAKE256": NewShake256, } // decodeHex converts a hex-encoded string into a raw byte string. func decodeHex(s string) []byte { b, err := hex.DecodeString(s) if err != nil { panic(err) } return b } // structs used to marshal JSON test-cases. type KeccakKats struct { Kats map[string][]struct { Digest string `json:"digest"` Length int64 `json:"length"` Message string `json:"message"` } } func testUnalignedAndGeneric(t *testing.T, testf func(impl string)) { xorInOrig, copyOutOrig := xorIn, copyOut xorIn, copyOut = xorInGeneric, copyOutGeneric testf("generic") if xorImplementationUnaligned != "generic" { xorIn, copyOut = xorInUnaligned, copyOutUnaligned testf("unaligned") } xorIn, copyOut = xorInOrig, copyOutOrig } // TestKeccakKats tests the SHA-3 and Shake implementations against all the // ShortMsgKATs from https://github.com/gvanas/KeccakCodePackage // (The testvectors are stored in keccakKats.json.deflate due to their length.) func TestKeccakKats(t *testing.T) { testUnalignedAndGeneric(t, func(impl string) { // Read the KATs. deflated, err := os.Open(katFilename) if err != nil { t.Errorf("error opening %s: %s", katFilename, err) } file := flate.NewReader(deflated) dec := json.NewDecoder(file) var katSet KeccakKats err = dec.Decode(&katSet) if err != nil { t.Errorf("error decoding KATs: %s", err) } // Do the KATs. for functionName, kats := range katSet.Kats { d := testDigests[functionName]() for _, kat := range kats { d.Reset() in, err := hex.DecodeString(kat.Message) if err != nil { t.Errorf("error decoding KAT: %s", err) } d.Write(in[:kat.Length/8]) got := strings.ToUpper(hex.EncodeToString(d.Sum(nil))) if got != kat.Digest { t.Errorf("function=%s, implementation=%s, length=%d\nmessage:\n %s\ngot:\n %s\nwanted:\n %s", functionName, impl, kat.Length, kat.Message, got, kat.Digest) t.Logf("wanted %+v", kat) t.FailNow() } continue } } }) } // TestUnalignedWrite tests that writing data in an arbitrary pattern with // small input buffers. func testUnalignedWrite(t *testing.T) { testUnalignedAndGeneric(t, func(impl string) { buf := sequentialBytes(0x10000) for alg, df := range testDigests { d := df() d.Reset() d.Write(buf) want := d.Sum(nil) d.Reset() for i := 0; i < len(buf); { // Cycle through offsets which make a 137 byte sequence. // Because 137 is prime this sequence should exercise all corner cases. offsets := [17]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 1} for _, j := range offsets { if v := len(buf) - i; v < j { j = v } d.Write(buf[i : i+j]) i += j } } got := d.Sum(nil) if !bytes.Equal(got, want) { t.Errorf("Unaligned writes, implementation=%s, alg=%s\ngot %q, want %q", impl, alg, got, want) } } }) } // TestAppend checks that appending works when reallocation is necessary. func TestAppend(t *testing.T) { testUnalignedAndGeneric(t, func(impl string) { d := New224() for capacity := 2; capacity <= 66; capacity += 64 { // The first time around the loop, Sum will have to reallocate. // The second time, it will not. buf := make([]byte, 2, capacity) d.Reset() d.Write([]byte{0xcc}) buf = d.Sum(buf) expected := "0000DF70ADC49B2E76EEE3A6931B93FA41841C3AF2CDF5B32A18B5478C39" if got := strings.ToUpper(hex.EncodeToString(buf)); got != expected { t.Errorf("got %s, want %s", got, expected) } } }) } // TestAppendNoRealloc tests that appending works when no reallocation is necessary. func TestAppendNoRealloc(t *testing.T) { testUnalignedAndGeneric(t, func(impl string) { buf := make([]byte, 1, 200) d := New224() d.Write([]byte{0xcc}) buf = d.Sum(buf) expected := "00DF70ADC49B2E76EEE3A6931B93FA41841C3AF2CDF5B32A18B5478C39" if got := strings.ToUpper(hex.EncodeToString(buf)); got != expected { t.Errorf("%s: got %s, want %s", impl, got, expected) } }) } // TestSqueezing checks that squeezing the full output a single time produces // the same output as repeatedly squeezing the instance. func TestSqueezing(t *testing.T) { testUnalignedAndGeneric(t, func(impl string) { for functionName, newShakeHash := range testShakes { d0 := newShakeHash() d0.Write([]byte(testString)) ref := make([]byte, 32) d0.Read(ref) d1 := newShakeHash() d1.Write([]byte(testString)) var multiple []byte for _ = range ref { one := make([]byte, 1) d1.Read(one) multiple = append(multiple, one...) } if !bytes.Equal(ref, multiple) { t.Errorf("%s (%s): squeezing %d bytes one at a time failed", functionName, impl, len(ref)) } } }) } // sequentialBytes produces a buffer of size consecutive bytes 0x00, 0x01, ..., used for testing. func sequentialBytes(size int) []byte { result := make([]byte, size) for i := range result { result[i] = byte(i) } return result } // BenchmarkPermutationFunction measures the speed of the permutation function // with no input data. func BenchmarkPermutationFunction(b *testing.B) { b.SetBytes(int64(200)) var lanes [25]uint64 for i := 0; i < b.N; i++ { keccakF1600(&lanes) } } // benchmarkHash tests the speed to hash num buffers of buflen each. func benchmarkHash(b *testing.B, h hash.Hash, size, num int) { b.StopTimer() h.Reset() data := sequentialBytes(size) b.SetBytes(int64(size * num)) b.StartTimer() var state []byte for i := 0; i < b.N; i++ { for j := 0; j < num; j++ { h.Write(data) } state = h.Sum(state[:0]) } b.StopTimer() h.Reset() } // benchmarkShake is specialized to the Shake instances, which don't // require a copy on reading output. func benchmarkShake(b *testing.B, h ShakeHash, size, num int) { b.StopTimer() h.Reset() data := sequentialBytes(size) d := make([]byte, 32) b.SetBytes(int64(size * num)) b.StartTimer() for i := 0; i < b.N; i++ { h.Reset() for j := 0; j < num; j++ { h.Write(data) } h.Read(d) } } func BenchmarkSha3_512_MTU(b *testing.B) { benchmarkHash(b, New512(), 1350, 1) } func BenchmarkSha3_384_MTU(b *testing.B) { benchmarkHash(b, New384(), 1350, 1) } func BenchmarkSha3_256_MTU(b *testing.B) { benchmarkHash(b, New256(), 1350, 1) } func BenchmarkSha3_224_MTU(b *testing.B) { benchmarkHash(b, New224(), 1350, 1) } func BenchmarkShake128_MTU(b *testing.B) { benchmarkShake(b, NewShake128(), 1350, 1) } func BenchmarkShake256_MTU(b *testing.B) { benchmarkShake(b, NewShake256(), 1350, 1) } func BenchmarkShake256_16x(b *testing.B) { benchmarkShake(b, NewShake256(), 16, 1024) } func BenchmarkShake256_1MiB(b *testing.B) { benchmarkShake(b, NewShake256(), 1024, 1024) } func BenchmarkSha3_512_1MiB(b *testing.B) { benchmarkHash(b, New512(), 1024, 1024) } func Example_sum() { buf := []byte("some data to hash") // A hash needs to be 64 bytes long to have 256-bit collision resistance. h := make([]byte, 64) // Compute a 64-byte hash of buf and put it in h. ShakeSum256(h, buf) } func Example_mac() { k := []byte("this is a secret key; you should generate a strong random key that's at least 32 bytes long") buf := []byte("and this is some data to authenticate") // A MAC with 32 bytes of output has 256-bit security strength -- if you use at least a 32-byte-long key. h := make([]byte, 32) d := NewShake256() // Write the key into the hash. d.Write(k) // Now write the data. d.Write(buf) // Read 32 bytes of output from the hash into h. d.Read(h) } lxd-2.0.0/dist/src/golang.org/x/crypto/sha3/register.go0000644061062106075000000000063512702772344025311 0ustar00stgraberdomain admins00000000000000// Copyright 2014 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. // +build go1.4 package sha3 import ( "crypto" ) func init() { crypto.RegisterHash(crypto.SHA3_224, New224) crypto.RegisterHash(crypto.SHA3_256, New256) crypto.RegisterHash(crypto.SHA3_384, New384) crypto.RegisterHash(crypto.SHA3_512, New512) } lxd-2.0.0/dist/src/golang.org/x/crypto/sha3/keccakf.go0000644061062106075000000002330012702772344025046 0ustar00stgraberdomain admins00000000000000// Copyright 2014 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 sha3 // rc stores the round constants for use in the ι step. var rc = [24]uint64{ 0x0000000000000001, 0x0000000000008082, 0x800000000000808A, 0x8000000080008000, 0x000000000000808B, 0x0000000080000001, 0x8000000080008081, 0x8000000000008009, 0x000000000000008A, 0x0000000000000088, 0x0000000080008009, 0x000000008000000A, 0x000000008000808B, 0x800000000000008B, 0x8000000000008089, 0x8000000000008003, 0x8000000000008002, 0x8000000000000080, 0x000000000000800A, 0x800000008000000A, 0x8000000080008081, 0x8000000000008080, 0x0000000080000001, 0x8000000080008008, } // keccakF1600 applies the Keccak permutation to a 1600b-wide // state represented as a slice of 25 uint64s. func keccakF1600(a *[25]uint64) { // Implementation translated from Keccak-inplace.c // in the keccak reference code. var t, bc0, bc1, bc2, bc3, bc4, d0, d1, d2, d3, d4 uint64 for i := 0; i < 24; i += 4 { // Combines the 5 steps in each round into 2 steps. // Unrolls 4 rounds per loop and spreads some steps across rounds. // Round 1 bc0 = a[0] ^ a[5] ^ a[10] ^ a[15] ^ a[20] bc1 = a[1] ^ a[6] ^ a[11] ^ a[16] ^ a[21] bc2 = a[2] ^ a[7] ^ a[12] ^ a[17] ^ a[22] bc3 = a[3] ^ a[8] ^ a[13] ^ a[18] ^ a[23] bc4 = a[4] ^ a[9] ^ a[14] ^ a[19] ^ a[24] d0 = bc4 ^ (bc1<<1 | bc1>>63) d1 = bc0 ^ (bc2<<1 | bc2>>63) d2 = bc1 ^ (bc3<<1 | bc3>>63) d3 = bc2 ^ (bc4<<1 | bc4>>63) d4 = bc3 ^ (bc0<<1 | bc0>>63) bc0 = a[0] ^ d0 t = a[6] ^ d1 bc1 = t<<44 | t>>(64-44) t = a[12] ^ d2 bc2 = t<<43 | t>>(64-43) t = a[18] ^ d3 bc3 = t<<21 | t>>(64-21) t = a[24] ^ d4 bc4 = t<<14 | t>>(64-14) a[0] = bc0 ^ (bc2 &^ bc1) ^ rc[i] a[6] = bc1 ^ (bc3 &^ bc2) a[12] = bc2 ^ (bc4 &^ bc3) a[18] = bc3 ^ (bc0 &^ bc4) a[24] = bc4 ^ (bc1 &^ bc0) t = a[10] ^ d0 bc2 = t<<3 | t>>(64-3) t = a[16] ^ d1 bc3 = t<<45 | t>>(64-45) t = a[22] ^ d2 bc4 = t<<61 | t>>(64-61) t = a[3] ^ d3 bc0 = t<<28 | t>>(64-28) t = a[9] ^ d4 bc1 = t<<20 | t>>(64-20) a[10] = bc0 ^ (bc2 &^ bc1) a[16] = bc1 ^ (bc3 &^ bc2) a[22] = bc2 ^ (bc4 &^ bc3) a[3] = bc3 ^ (bc0 &^ bc4) a[9] = bc4 ^ (bc1 &^ bc0) t = a[20] ^ d0 bc4 = t<<18 | t>>(64-18) t = a[1] ^ d1 bc0 = t<<1 | t>>(64-1) t = a[7] ^ d2 bc1 = t<<6 | t>>(64-6) t = a[13] ^ d3 bc2 = t<<25 | t>>(64-25) t = a[19] ^ d4 bc3 = t<<8 | t>>(64-8) a[20] = bc0 ^ (bc2 &^ bc1) a[1] = bc1 ^ (bc3 &^ bc2) a[7] = bc2 ^ (bc4 &^ bc3) a[13] = bc3 ^ (bc0 &^ bc4) a[19] = bc4 ^ (bc1 &^ bc0) t = a[5] ^ d0 bc1 = t<<36 | t>>(64-36) t = a[11] ^ d1 bc2 = t<<10 | t>>(64-10) t = a[17] ^ d2 bc3 = t<<15 | t>>(64-15) t = a[23] ^ d3 bc4 = t<<56 | t>>(64-56) t = a[4] ^ d4 bc0 = t<<27 | t>>(64-27) a[5] = bc0 ^ (bc2 &^ bc1) a[11] = bc1 ^ (bc3 &^ bc2) a[17] = bc2 ^ (bc4 &^ bc3) a[23] = bc3 ^ (bc0 &^ bc4) a[4] = bc4 ^ (bc1 &^ bc0) t = a[15] ^ d0 bc3 = t<<41 | t>>(64-41) t = a[21] ^ d1 bc4 = t<<2 | t>>(64-2) t = a[2] ^ d2 bc0 = t<<62 | t>>(64-62) t = a[8] ^ d3 bc1 = t<<55 | t>>(64-55) t = a[14] ^ d4 bc2 = t<<39 | t>>(64-39) a[15] = bc0 ^ (bc2 &^ bc1) a[21] = bc1 ^ (bc3 &^ bc2) a[2] = bc2 ^ (bc4 &^ bc3) a[8] = bc3 ^ (bc0 &^ bc4) a[14] = bc4 ^ (bc1 &^ bc0) // Round 2 bc0 = a[0] ^ a[5] ^ a[10] ^ a[15] ^ a[20] bc1 = a[1] ^ a[6] ^ a[11] ^ a[16] ^ a[21] bc2 = a[2] ^ a[7] ^ a[12] ^ a[17] ^ a[22] bc3 = a[3] ^ a[8] ^ a[13] ^ a[18] ^ a[23] bc4 = a[4] ^ a[9] ^ a[14] ^ a[19] ^ a[24] d0 = bc4 ^ (bc1<<1 | bc1>>63) d1 = bc0 ^ (bc2<<1 | bc2>>63) d2 = bc1 ^ (bc3<<1 | bc3>>63) d3 = bc2 ^ (bc4<<1 | bc4>>63) d4 = bc3 ^ (bc0<<1 | bc0>>63) bc0 = a[0] ^ d0 t = a[16] ^ d1 bc1 = t<<44 | t>>(64-44) t = a[7] ^ d2 bc2 = t<<43 | t>>(64-43) t = a[23] ^ d3 bc3 = t<<21 | t>>(64-21) t = a[14] ^ d4 bc4 = t<<14 | t>>(64-14) a[0] = bc0 ^ (bc2 &^ bc1) ^ rc[i+1] a[16] = bc1 ^ (bc3 &^ bc2) a[7] = bc2 ^ (bc4 &^ bc3) a[23] = bc3 ^ (bc0 &^ bc4) a[14] = bc4 ^ (bc1 &^ bc0) t = a[20] ^ d0 bc2 = t<<3 | t>>(64-3) t = a[11] ^ d1 bc3 = t<<45 | t>>(64-45) t = a[2] ^ d2 bc4 = t<<61 | t>>(64-61) t = a[18] ^ d3 bc0 = t<<28 | t>>(64-28) t = a[9] ^ d4 bc1 = t<<20 | t>>(64-20) a[20] = bc0 ^ (bc2 &^ bc1) a[11] = bc1 ^ (bc3 &^ bc2) a[2] = bc2 ^ (bc4 &^ bc3) a[18] = bc3 ^ (bc0 &^ bc4) a[9] = bc4 ^ (bc1 &^ bc0) t = a[15] ^ d0 bc4 = t<<18 | t>>(64-18) t = a[6] ^ d1 bc0 = t<<1 | t>>(64-1) t = a[22] ^ d2 bc1 = t<<6 | t>>(64-6) t = a[13] ^ d3 bc2 = t<<25 | t>>(64-25) t = a[4] ^ d4 bc3 = t<<8 | t>>(64-8) a[15] = bc0 ^ (bc2 &^ bc1) a[6] = bc1 ^ (bc3 &^ bc2) a[22] = bc2 ^ (bc4 &^ bc3) a[13] = bc3 ^ (bc0 &^ bc4) a[4] = bc4 ^ (bc1 &^ bc0) t = a[10] ^ d0 bc1 = t<<36 | t>>(64-36) t = a[1] ^ d1 bc2 = t<<10 | t>>(64-10) t = a[17] ^ d2 bc3 = t<<15 | t>>(64-15) t = a[8] ^ d3 bc4 = t<<56 | t>>(64-56) t = a[24] ^ d4 bc0 = t<<27 | t>>(64-27) a[10] = bc0 ^ (bc2 &^ bc1) a[1] = bc1 ^ (bc3 &^ bc2) a[17] = bc2 ^ (bc4 &^ bc3) a[8] = bc3 ^ (bc0 &^ bc4) a[24] = bc4 ^ (bc1 &^ bc0) t = a[5] ^ d0 bc3 = t<<41 | t>>(64-41) t = a[21] ^ d1 bc4 = t<<2 | t>>(64-2) t = a[12] ^ d2 bc0 = t<<62 | t>>(64-62) t = a[3] ^ d3 bc1 = t<<55 | t>>(64-55) t = a[19] ^ d4 bc2 = t<<39 | t>>(64-39) a[5] = bc0 ^ (bc2 &^ bc1) a[21] = bc1 ^ (bc3 &^ bc2) a[12] = bc2 ^ (bc4 &^ bc3) a[3] = bc3 ^ (bc0 &^ bc4) a[19] = bc4 ^ (bc1 &^ bc0) // Round 3 bc0 = a[0] ^ a[5] ^ a[10] ^ a[15] ^ a[20] bc1 = a[1] ^ a[6] ^ a[11] ^ a[16] ^ a[21] bc2 = a[2] ^ a[7] ^ a[12] ^ a[17] ^ a[22] bc3 = a[3] ^ a[8] ^ a[13] ^ a[18] ^ a[23] bc4 = a[4] ^ a[9] ^ a[14] ^ a[19] ^ a[24] d0 = bc4 ^ (bc1<<1 | bc1>>63) d1 = bc0 ^ (bc2<<1 | bc2>>63) d2 = bc1 ^ (bc3<<1 | bc3>>63) d3 = bc2 ^ (bc4<<1 | bc4>>63) d4 = bc3 ^ (bc0<<1 | bc0>>63) bc0 = a[0] ^ d0 t = a[11] ^ d1 bc1 = t<<44 | t>>(64-44) t = a[22] ^ d2 bc2 = t<<43 | t>>(64-43) t = a[8] ^ d3 bc3 = t<<21 | t>>(64-21) t = a[19] ^ d4 bc4 = t<<14 | t>>(64-14) a[0] = bc0 ^ (bc2 &^ bc1) ^ rc[i+2] a[11] = bc1 ^ (bc3 &^ bc2) a[22] = bc2 ^ (bc4 &^ bc3) a[8] = bc3 ^ (bc0 &^ bc4) a[19] = bc4 ^ (bc1 &^ bc0) t = a[15] ^ d0 bc2 = t<<3 | t>>(64-3) t = a[1] ^ d1 bc3 = t<<45 | t>>(64-45) t = a[12] ^ d2 bc4 = t<<61 | t>>(64-61) t = a[23] ^ d3 bc0 = t<<28 | t>>(64-28) t = a[9] ^ d4 bc1 = t<<20 | t>>(64-20) a[15] = bc0 ^ (bc2 &^ bc1) a[1] = bc1 ^ (bc3 &^ bc2) a[12] = bc2 ^ (bc4 &^ bc3) a[23] = bc3 ^ (bc0 &^ bc4) a[9] = bc4 ^ (bc1 &^ bc0) t = a[5] ^ d0 bc4 = t<<18 | t>>(64-18) t = a[16] ^ d1 bc0 = t<<1 | t>>(64-1) t = a[2] ^ d2 bc1 = t<<6 | t>>(64-6) t = a[13] ^ d3 bc2 = t<<25 | t>>(64-25) t = a[24] ^ d4 bc3 = t<<8 | t>>(64-8) a[5] = bc0 ^ (bc2 &^ bc1) a[16] = bc1 ^ (bc3 &^ bc2) a[2] = bc2 ^ (bc4 &^ bc3) a[13] = bc3 ^ (bc0 &^ bc4) a[24] = bc4 ^ (bc1 &^ bc0) t = a[20] ^ d0 bc1 = t<<36 | t>>(64-36) t = a[6] ^ d1 bc2 = t<<10 | t>>(64-10) t = a[17] ^ d2 bc3 = t<<15 | t>>(64-15) t = a[3] ^ d3 bc4 = t<<56 | t>>(64-56) t = a[14] ^ d4 bc0 = t<<27 | t>>(64-27) a[20] = bc0 ^ (bc2 &^ bc1) a[6] = bc1 ^ (bc3 &^ bc2) a[17] = bc2 ^ (bc4 &^ bc3) a[3] = bc3 ^ (bc0 &^ bc4) a[14] = bc4 ^ (bc1 &^ bc0) t = a[10] ^ d0 bc3 = t<<41 | t>>(64-41) t = a[21] ^ d1 bc4 = t<<2 | t>>(64-2) t = a[7] ^ d2 bc0 = t<<62 | t>>(64-62) t = a[18] ^ d3 bc1 = t<<55 | t>>(64-55) t = a[4] ^ d4 bc2 = t<<39 | t>>(64-39) a[10] = bc0 ^ (bc2 &^ bc1) a[21] = bc1 ^ (bc3 &^ bc2) a[7] = bc2 ^ (bc4 &^ bc3) a[18] = bc3 ^ (bc0 &^ bc4) a[4] = bc4 ^ (bc1 &^ bc0) // Round 4 bc0 = a[0] ^ a[5] ^ a[10] ^ a[15] ^ a[20] bc1 = a[1] ^ a[6] ^ a[11] ^ a[16] ^ a[21] bc2 = a[2] ^ a[7] ^ a[12] ^ a[17] ^ a[22] bc3 = a[3] ^ a[8] ^ a[13] ^ a[18] ^ a[23] bc4 = a[4] ^ a[9] ^ a[14] ^ a[19] ^ a[24] d0 = bc4 ^ (bc1<<1 | bc1>>63) d1 = bc0 ^ (bc2<<1 | bc2>>63) d2 = bc1 ^ (bc3<<1 | bc3>>63) d3 = bc2 ^ (bc4<<1 | bc4>>63) d4 = bc3 ^ (bc0<<1 | bc0>>63) bc0 = a[0] ^ d0 t = a[1] ^ d1 bc1 = t<<44 | t>>(64-44) t = a[2] ^ d2 bc2 = t<<43 | t>>(64-43) t = a[3] ^ d3 bc3 = t<<21 | t>>(64-21) t = a[4] ^ d4 bc4 = t<<14 | t>>(64-14) a[0] = bc0 ^ (bc2 &^ bc1) ^ rc[i+3] a[1] = bc1 ^ (bc3 &^ bc2) a[2] = bc2 ^ (bc4 &^ bc3) a[3] = bc3 ^ (bc0 &^ bc4) a[4] = bc4 ^ (bc1 &^ bc0) t = a[5] ^ d0 bc2 = t<<3 | t>>(64-3) t = a[6] ^ d1 bc3 = t<<45 | t>>(64-45) t = a[7] ^ d2 bc4 = t<<61 | t>>(64-61) t = a[8] ^ d3 bc0 = t<<28 | t>>(64-28) t = a[9] ^ d4 bc1 = t<<20 | t>>(64-20) a[5] = bc0 ^ (bc2 &^ bc1) a[6] = bc1 ^ (bc3 &^ bc2) a[7] = bc2 ^ (bc4 &^ bc3) a[8] = bc3 ^ (bc0 &^ bc4) a[9] = bc4 ^ (bc1 &^ bc0) t = a[10] ^ d0 bc4 = t<<18 | t>>(64-18) t = a[11] ^ d1 bc0 = t<<1 | t>>(64-1) t = a[12] ^ d2 bc1 = t<<6 | t>>(64-6) t = a[13] ^ d3 bc2 = t<<25 | t>>(64-25) t = a[14] ^ d4 bc3 = t<<8 | t>>(64-8) a[10] = bc0 ^ (bc2 &^ bc1) a[11] = bc1 ^ (bc3 &^ bc2) a[12] = bc2 ^ (bc4 &^ bc3) a[13] = bc3 ^ (bc0 &^ bc4) a[14] = bc4 ^ (bc1 &^ bc0) t = a[15] ^ d0 bc1 = t<<36 | t>>(64-36) t = a[16] ^ d1 bc2 = t<<10 | t>>(64-10) t = a[17] ^ d2 bc3 = t<<15 | t>>(64-15) t = a[18] ^ d3 bc4 = t<<56 | t>>(64-56) t = a[19] ^ d4 bc0 = t<<27 | t>>(64-27) a[15] = bc0 ^ (bc2 &^ bc1) a[16] = bc1 ^ (bc3 &^ bc2) a[17] = bc2 ^ (bc4 &^ bc3) a[18] = bc3 ^ (bc0 &^ bc4) a[19] = bc4 ^ (bc1 &^ bc0) t = a[20] ^ d0 bc3 = t<<41 | t>>(64-41) t = a[21] ^ d1 bc4 = t<<2 | t>>(64-2) t = a[22] ^ d2 bc0 = t<<62 | t>>(64-62) t = a[23] ^ d3 bc1 = t<<55 | t>>(64-55) t = a[24] ^ d4 bc2 = t<<39 | t>>(64-39) a[20] = bc0 ^ (bc2 &^ bc1) a[21] = bc1 ^ (bc3 &^ bc2) a[22] = bc2 ^ (bc4 &^ bc3) a[23] = bc3 ^ (bc0 &^ bc4) a[24] = bc4 ^ (bc1 &^ bc0) } } lxd-2.0.0/dist/src/golang.org/x/crypto/sha3/xor_unaligned.go0000644061062106075000000000207012702772344026316 0ustar00stgraberdomain admins00000000000000// Copyright 2015 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. // +build amd64 386 ppc64 ppc64le // +build !appengine package sha3 import "unsafe" func xorInUnaligned(d *state, buf []byte) { bw := (*[maxRate / 8]uint64)(unsafe.Pointer(&buf[0])) n := len(buf) if n >= 72 { d.a[0] ^= bw[0] d.a[1] ^= bw[1] d.a[2] ^= bw[2] d.a[3] ^= bw[3] d.a[4] ^= bw[4] d.a[5] ^= bw[5] d.a[6] ^= bw[6] d.a[7] ^= bw[7] d.a[8] ^= bw[8] } if n >= 104 { d.a[9] ^= bw[9] d.a[10] ^= bw[10] d.a[11] ^= bw[11] d.a[12] ^= bw[12] } if n >= 136 { d.a[13] ^= bw[13] d.a[14] ^= bw[14] d.a[15] ^= bw[15] d.a[16] ^= bw[16] } if n >= 144 { d.a[17] ^= bw[17] } if n >= 168 { d.a[18] ^= bw[18] d.a[19] ^= bw[19] d.a[20] ^= bw[20] } } func copyOutUnaligned(d *state, buf []byte) { ab := (*[maxRate]uint8)(unsafe.Pointer(&d.a[0])) copy(buf, ab[:]) } var ( xorIn = xorInUnaligned copyOut = copyOutUnaligned ) const xorImplementationUnaligned = "unaligned" lxd-2.0.0/dist/src/golang.org/x/crypto/sha3/sha3.go0000644061062106075000000001327512702772344024327 0ustar00stgraberdomain admins00000000000000// Copyright 2014 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 sha3 // spongeDirection indicates the direction bytes are flowing through the sponge. type spongeDirection int const ( // spongeAbsorbing indicates that the sponge is absorbing input. spongeAbsorbing spongeDirection = iota // spongeSqueezing indicates that the sponge is being squeezed. spongeSqueezing ) const ( // maxRate is the maximum size of the internal buffer. SHAKE-256 // currently needs the largest buffer. maxRate = 168 ) type state struct { // Generic sponge components. a [25]uint64 // main state of the hash buf []byte // points into storage rate int // the number of bytes of state to use // dsbyte contains the "domain separation" bits and the first bit of // the padding. Sections 6.1 and 6.2 of [1] separate the outputs of the // SHA-3 and SHAKE functions by appending bitstrings to the message. // Using a little-endian bit-ordering convention, these are "01" for SHA-3 // and "1111" for SHAKE, or 00000010b and 00001111b, respectively. Then the // padding rule from section 5.1 is applied to pad the message to a multiple // of the rate, which involves adding a "1" bit, zero or more "0" bits, and // a final "1" bit. We merge the first "1" bit from the padding into dsbyte, // giving 00000110b (0x06) and 00011111b (0x1f). // [1] http://csrc.nist.gov/publications/drafts/fips-202/fips_202_draft.pdf // "Draft FIPS 202: SHA-3 Standard: Permutation-Based Hash and // Extendable-Output Functions (May 2014)" dsbyte byte storage [maxRate]byte // Specific to SHA-3 and SHAKE. fixedOutput bool // whether this is a fixed-ouput-length instance outputLen int // the default output size in bytes state spongeDirection // whether the sponge is absorbing or squeezing } // BlockSize returns the rate of sponge underlying this hash function. func (d *state) BlockSize() int { return d.rate } // Size returns the output size of the hash function in bytes. func (d *state) Size() int { return d.outputLen } // Reset clears the internal state by zeroing the sponge state and // the byte buffer, and setting Sponge.state to absorbing. func (d *state) Reset() { // Zero the permutation's state. for i := range d.a { d.a[i] = 0 } d.state = spongeAbsorbing d.buf = d.storage[:0] } func (d *state) clone() *state { ret := *d if ret.state == spongeAbsorbing { ret.buf = ret.storage[:len(ret.buf)] } else { ret.buf = ret.storage[d.rate-cap(d.buf) : d.rate] } return &ret } // permute applies the KeccakF-1600 permutation. It handles // any input-output buffering. func (d *state) permute() { switch d.state { case spongeAbsorbing: // If we're absorbing, we need to xor the input into the state // before applying the permutation. xorIn(d, d.buf) d.buf = d.storage[:0] keccakF1600(&d.a) case spongeSqueezing: // If we're squeezing, we need to apply the permutatin before // copying more output. keccakF1600(&d.a) d.buf = d.storage[:d.rate] copyOut(d, d.buf) } } // pads appends the domain separation bits in dsbyte, applies // the multi-bitrate 10..1 padding rule, and permutes the state. func (d *state) padAndPermute(dsbyte byte) { if d.buf == nil { d.buf = d.storage[:0] } // Pad with this instance's domain-separator bits. We know that there's // at least one byte of space in d.buf because, if it were full, // permute would have been called to empty it. dsbyte also contains the // first one bit for the padding. See the comment in the state struct. d.buf = append(d.buf, dsbyte) zerosStart := len(d.buf) d.buf = d.storage[:d.rate] for i := zerosStart; i < d.rate; i++ { d.buf[i] = 0 } // This adds the final one bit for the padding. Because of the way that // bits are numbered from the LSB upwards, the final bit is the MSB of // the last byte. d.buf[d.rate-1] ^= 0x80 // Apply the permutation d.permute() d.state = spongeSqueezing d.buf = d.storage[:d.rate] copyOut(d, d.buf) } // Write absorbs more data into the hash's state. It produces an error // if more data is written to the ShakeHash after writing func (d *state) Write(p []byte) (written int, err error) { if d.state != spongeAbsorbing { panic("sha3: write to sponge after read") } if d.buf == nil { d.buf = d.storage[:0] } written = len(p) for len(p) > 0 { if len(d.buf) == 0 && len(p) >= d.rate { // The fast path; absorb a full "rate" bytes of input and apply the permutation. xorIn(d, p[:d.rate]) p = p[d.rate:] keccakF1600(&d.a) } else { // The slow path; buffer the input until we can fill the sponge, and then xor it in. todo := d.rate - len(d.buf) if todo > len(p) { todo = len(p) } d.buf = append(d.buf, p[:todo]...) p = p[todo:] // If the sponge is full, apply the permutation. if len(d.buf) == d.rate { d.permute() } } } return } // Read squeezes an arbitrary number of bytes from the sponge. func (d *state) Read(out []byte) (n int, err error) { // If we're still absorbing, pad and apply the permutation. if d.state == spongeAbsorbing { d.padAndPermute(d.dsbyte) } n = len(out) // Now, do the squeezing. for len(out) > 0 { n := copy(out, d.buf) d.buf = d.buf[n:] out = out[n:] // Apply the permutation if we've squeezed the sponge dry. if len(d.buf) == 0 { d.permute() } } return } // Sum applies padding to the hash state and then squeezes out the desired // number of output bytes. func (d *state) Sum(in []byte) []byte { // Make a copy of the original hash so that caller can keep writing // and summing. dup := d.clone() hash := make([]byte, dup.outputLen) dup.Read(hash) return append(in, hash...) } lxd-2.0.0/dist/src/golang.org/x/crypto/sha3/hashes.go0000644061062106075000000000356512702772344024745 0ustar00stgraberdomain admins00000000000000// Copyright 2014 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 sha3 // This file provides functions for creating instances of the SHA-3 // and SHAKE hash functions, as well as utility functions for hashing // bytes. import ( "hash" ) // New224 creates a new SHA3-224 hash. // Its generic security strength is 224 bits against preimage attacks, // and 112 bits against collision attacks. func New224() hash.Hash { return &state{rate: 144, outputLen: 28, dsbyte: 0x06} } // New256 creates a new SHA3-256 hash. // Its generic security strength is 256 bits against preimage attacks, // and 128 bits against collision attacks. func New256() hash.Hash { return &state{rate: 136, outputLen: 32, dsbyte: 0x06} } // New384 creates a new SHA3-384 hash. // Its generic security strength is 384 bits against preimage attacks, // and 192 bits against collision attacks. func New384() hash.Hash { return &state{rate: 104, outputLen: 48, dsbyte: 0x06} } // New512 creates a new SHA3-512 hash. // Its generic security strength is 512 bits against preimage attacks, // and 256 bits against collision attacks. func New512() hash.Hash { return &state{rate: 72, outputLen: 64, dsbyte: 0x06} } // Sum224 returns the SHA3-224 digest of the data. func Sum224(data []byte) (digest [28]byte) { h := New224() h.Write(data) h.Sum(digest[:0]) return } // Sum256 returns the SHA3-256 digest of the data. func Sum256(data []byte) (digest [32]byte) { h := New256() h.Write(data) h.Sum(digest[:0]) return } // Sum384 returns the SHA3-384 digest of the data. func Sum384(data []byte) (digest [48]byte) { h := New384() h.Write(data) h.Sum(digest[:0]) return } // Sum512 returns the SHA3-512 digest of the data. func Sum512(data []byte) (digest [64]byte) { h := New512() h.Write(data) h.Sum(digest[:0]) return } lxd-2.0.0/dist/src/golang.org/x/crypto/sha3/testdata/0000755061062106075000000000000012702772344024743 5ustar00stgraberdomain admins00000000000000lxd-2.0.0/dist/src/golang.org/x/crypto/sha3/testdata/keccakKats.json.deflate0000644061062106075000000177217612702772344031332 0ustar00stgraberdomain admins00000000000000„ù;¯¯oŽŠåþƒŽ-€—‡:ã…ÄäÀ‚lø’Œ2ÁßÝ= Љ^á×Áþï½XxYUO±HþÏü¿þÿñÿø¿ýËÿü¿üË¿üãßþ5ù¿½þûßÿùïùûéþïÿ÷ÿçÿoÿñ?þùóh½~Ī6UÆ¥‹òälaÖ< »H,0_>)I­¶ü_ÿ×ïúÿ·ÿïÿÿþ.ø?ôÿùoÿñÿÇÿoÿùûþñ÷ÓÿßþŸŸ_0gÓ/ŠÖtw95+øò¡?lΣž“bJô’gÞ_à__Ðýë êŽB\qrç˜×@0 —ªë5mÜ2ëó¨æBcÀFùøÔ¯Oxxõë#ð¹Ç܋ӌ<ºW]¨ÌQÝO’ÞÖE^ÛF#ü"‚Þ×Gà¹ÙO,’¹Åç<H.$0Tktv‡ ×)Ä!+jI½ó>Ù`ú¤·o®â+É„Š̘ó¸¯ô£¨<ò­'þñ!ïS™„‡ü²Å~}Ê­P3tHã ؆ ‹Ü,Ä~NÞঙ¡(à_Ÿò-Q=*{Kñëc¼Þ ÑeýÌ´%xVüFš–‰º„QkÁÓÄpGóãcäS¬ˆaÈÝλ{¿>]{Æ@<Š‹_<Ü[ÔrÃÊxŽAï>põýøý”íËwôü ’þÄGCxÀõF;Þp:‹%*ݘ&rZ×録ÊÀ×}¿#Õ¬‡.;QÊ&¿>iE¯)%Å 瀒öiNÈ‹ó’=Qy0>agÀ_÷)åݱGDdŠ\zÂýSG8æÜlÍ”T†%ðª3A®J9/×ÖÇ—«_<üú¨OQoîŽôÜÇlï9üõYòÚöÕq/å,Ïmº ¼ì aE2Æ?—×VóñYñ)o©}ÜG@ûn}‡†}˜Ù öæ$ebW]Hö8!€—ØÆÓ³x@Ä…qЫô¥+„O¥§=%c"G¢cÇæzºï7h±#±ƒ"†òÔ.á$‘Á9J¬¦&õ¶œ&kôàË ?EÏ-nØ£­‘Ê%¶$•~Êß±xEûv×7}¸néUY÷ܼ(ïD̵yúùuô©ÿK"·WÝ îë{ˆ©q`D?Û?Šaí­¼Ýc³‰˜³ÚW­êÔÙí¨.²;hNÁïóûüSs” žEØ=ãùžXŠí¬9¡éO“uxÒg>Ä>¢atØ.ððU?x×:]ˆç‚à׊Ÿòç«pZ Úgz¶O(4ÎÁvç§ïÆ´ä‡á–ôzäÒQÖ•dÞØˆ¡Ö×7¾Ï÷a¢ÎÓ%¢ø …HWé„aîÏWL³]²‰E’4™[Ä/}BNŒ©ª&íš±K+}}¥ÐgàÕ}{ûXVñ2ï‘[½ñÁCê [ùÃÄ#XÙ y€£ŸÆ¼—ؤ«äÄYäÝh’áaþé6úÝ3H18<TÔoÕ}MäAn‚Ú³‰sùí=z`΋w‚ãš<xHž.…f¼Ù>¿ôóõŒOûÍ^MoÌ{ûºòÖü=«\.y¬”¿ÃmÂA‹ÐZñ-Ñâˆa,!O$OâTÄ2íÝ ÜÓ¯oµïîbàrc‹P³hœÑ º˜=Íuäšiü~Ɔ¼—øJtZ‹èí±P®W{çza6I«1Ï•Ý-~ú’woN¦JLÖõ’bö²=‹EaI/áçÛBwÕ&ìZ> d} V¬`žZå$^°"KK…yÄ_ßôù½ÛU@&qö˜G¯ 4”Û(ö8—ߥrÿôUbÐ?·&É*¹×Ì[É !B¢špfT/¾f.€Ï/Λz<\ .¨^b#˜Üc)|‡œõø=ÜQ{4»¼®78¾÷õÝßc9œ_ßĨ÷]£u_!šA”ð>¥äã§WÖå²?¿Üù½i´Ss1¼·2Ç^8ì…ã¬@%\Qzä<_^GüýC¹y=äNjŸÓ{‚>ŽéÜäR@—t]6; áýÔ8—½²ñk<â3­,*m–£ FÐY}a~}:Æ×ûõíßÃ?p¢«{!tÃÎ9ç¤?Ï0tvî­ýŽB \#²éçæBS]ì*¸b’LXš£åy-€/ÑV±Ñn&j»úç×ûgZ{W‚%hsÚ’Ý%DçG> QÄ4˜à®™¦¶›¥~oÜ-ýyNø?žâ…푙ƒº8èW@°7Ÿ›¨ïC]·uÀ,Œ–[mzã¦v"ú5ÌÆ…­Li6n4þìD bœc õÞx¿!xçþ*$ =×ôöQ$êÔò³x_|o%fý°ø2_<Øy¢Ü\¾NÂh¾nûæLöÝÑÑìŒ$ÔÂûÙ›*‰"@ä9wÄYŽÓÀÐË{n;¯„ïÓƒRd¦ø«†ïE†Ò¡¼mŽ7PmbOÚÂÛË-Tdà9¦ M\‰Opî´š–üε—‰]ÏúÌgæ-„–+Vóƒ2ÓZÜZ6ÏY©üªâ{÷Q4}wKEÜk“”À†W¶­‘Ò“(·CMÒ]Ù|ñ­ÔUÎû馇k‰E¾ùF¯\ÅàTq™Ä›ïÅy Ê»êú³éú¬ãóM?;ѰloÆÑàêNÆÏR‘“E ¶2÷áṺJŠé9Ë5½ø9í6£=}Oƒß-Åúë+i’®eÞxgoó`Êü3óÄwFJ Zµí¢ÛçZ·AªÂiòüݽ~GÛIy°Ó39Z‹vßÊûY §ƒ>¹}dÈO3wšsËd•/‡wÉÇíxbòë0¼O§2î£zÓuéFõãuT½E5…D0ÎÐÄö1–_ðø½«ŸÕ´líã$1¬Þ#Ù·©–¯3œÝ †X"@"Dò‚ïü³šï-ŽCíV-Ÿg<Áy/";Œ1WÕzšÞ&ôrEæ«jH;‹eÈà÷Ô&_ý|ûy†“Ç<\Ï9G™¥S!8|<Þêeè‰ ä¯ }Õó½÷±¬L¤mJãgjoß{ø ®TbÀ[u¶ÇG77H.Ÿà¨70øR¼§åû{8c‚4™ÐʯÅÝ ÊŸŽÍR£ÓŠŒ˜«¯Í¤ÌgEŸ.Ðî³A¦åy(«+ûȹÞãbg‹·9†CœÊˆƒÍS#.‚S«T„¦²Ÿi¥ë]PP%s§—¥í™*Æš1D%¡yÏKd¨ úL+ÌŸ~¸oYàzû lG!¯–ŒèBxèÂÌØ»EöU`'2hç׫›ÓTåZ§?µåeE®nƒåÏûÃS)y]´¹¥oè9’†éÂ'SïÓ˜ ˆÙ Ÿ—Òîcyzhýö¨ÎǶçÅT–Â+çhZ]©!”CQI–åËù~³¼. DxF‘¢›hɰ„‰Q‹‚•2tä«.ùN$.ôµ·½šjÈq‚ÐÅž7ï±ç1^’‰ïmk1•øV³_Sj²„¦ÿªÌVpDÙ騢Ì"#[ç”®)aÙÄv:\fèWeúé'¡87Txw7ùîêD¡Q¥n'Ë{¡VHüÉlù´"À+›bjr2}Å/)û6´:aH³[:˜éµô#lTÈ–[aN2§#8¾WX6Ÿµ}ûF‚bÒ–öî¸;öˆ¡Ñ¸Æ'†à*)²¿rè-y‚kV }p’°‰Ò`»Ød[ùû|ôòÝ>eEôëv)3x#Qú5Q S¸g0|UgŸ‚ö8ÍHp4è‘ ô;ÄÂÔÃÍ|QÒ=g‚o]üÍK¹¸c¨>óŒ”õUÔ…d‘àDÕÏú,¯ üÍn‰ ëÞ)¬"-÷ƒÁ¤ÁWøh.æ¾êóïiÂ/+ñãõ›’CÓ˺; z{J–l=à}" ^•~¸Lo¬íPŒÂ7«ßôÚxô *½ˆ‹Ÿ=ûœ!©ßù=¯ÖÇ–$çD Èg\s¯ëa¼j‘ï ãÓUjCýÕðW`ãŽ~N•‚¶qíX™‰´Ò:fda28+½ö̽§¤ï)hGcÛ)æŽÄ…ÍÏÞívJ›Ž˜tZÇ-7‹üL*ZM• ý¾˜vuí¯>÷à;,ÊPŦ½N…SmŸËb³ /+ÔÙÒÄJØä¶]‚Gç1l®k} Üfæ’«A焇/í~oã<•£m*qzJ=2I—PM‰ž’j¤´0*P}Vùé4‘„QûØkÄP6nRµáhœ;[”ËL³âØ÷íE×{Ìð®òîÕÔØöQ¸ ¶ëOGß#Ï¢Ò®z/*òìÒ¼x0šU”¶žc$´Û}Õ‰úÄŽJƒk`Lö":·¦‰rî{†$Ë£S6^r®j&usXsõ!ïf{B§I”ébܽuô$Œ~º«fûÃç‹,Ô:Æa“ÍÅfÏŠMl}çmƒÄžG|UJŸî³ aˆ€Úš”`9ƒúç´Ú«÷‚Ä i¼G•™ä­ÀVD»Ù/FÆã5Ô©ÆQƒo ¬gÎÊÏyîÉ$™¡ô˜œ¸ImÙ¾>{îô`°ðÂdÃнبOVùÓ‡`ú :2['S:ÝZrÝ£ë8{$úN…Þ(Þú+L»‚®gó4´—R]«¢6Ò³°5¬t4™2Ëy•UÛ`„æzoõõYu¿éDQx´ŒS+>òUíût¤Yr­|º^bøÎá {.·f‡âü)ð¾ä­†§®‘O;Ö*´Åž“ˆÓº#%éJºØ]«Xœ²=ºŸõ>7 žèZ .žLyss6CŠÄUÁ]Ë»—˜—Ÿõ~zÓnu£ƒ u_4¦1!³èȼjŒlʇ¸í=»k)†KK°yŠ7ÐÌ w[6Sfv…ŸM©VçÏŠa¶Ij™Ì–lÞ™¿¹ó³ʼndˆ äìÚ¤O=˧K=Ô’žŽÛ¬aÅ˺F‚gâ[é~3ê7þ–c¸ ²I^ذÖ㮵rIMî­IŸz+ò¢yW°J¯K³ñ÷Ý¡ÔZS•ȲÆ8ëô¶ ®GòÕ1³·Nwq̧ªõÓ¯¤åòTi᜛i}ÒÉ_¾LI[+ Ñâ®L‹kÕN6} ‹å^S¹ ·>:tÛÄW×!À&a ¿7QU’]þ\– J æ%0T4É0Šf©çX[ÃgÕöé\†j‹ T‹icîªzNœûvƒ ›4¥Ïz¤:QT§i ­˜aÎ Ø"ætì9Âî°rN¿¬ˆc…§ù³-¡ E†0ƒm€·«mUäãv2>QÎfÍ,‡¯ºýÓÃè&qª’Œ [˜B.WãùB™Îãµ÷|P=”ݬtðõ;ØÌÐFdóχg“ÒϹ›W¸¯~çÉ6Úà¤æÈê ÈBìáC‰Inâ†Cë·¤-ànŸ•'-|öR2K†Qvê>GtsæTBª¡ |‚©6c®s8·#X,÷lq¶<=ëUt©•Zt“žçZ‰Fhô¢`ùïÚ»›KâÈ›¯ŸÒ4¤†¢ÀIn*MBV†õ3­qÕÆ¯Úã;}ÖX<¼‡sð^R¥ß‰Ô«§ÖÌážIÂCñr¦¦˜„¡aÂDH8ñAÃñS:gqnpZ'Lˆé¿«'ïh= ð¡—™«ÍqBbÌÀØ4꜑GQaüQ½À§ÃXëЉMSô Å'1‡EO¸ó¤ÅÄŽ’KLOzs3-HOø;ÌzI ô(KË|X}Z2W‡_ø³áú+hœ÷{Þo”§`®u4ÎHÁíì:¬E€›•zz¥æõÊñ«~üôº Ò\/ÈÓFÓ©»nJ-÷ÖS¹à4Ï¨ÙØãLdlÅelÜG=—÷êMÏŠE²- ìÕžˆH½Æ®cœ%ÞÒåÚOדuË8y˜ÐÕg7¶°Ð(Ô{æ#»è ;ž¸c_Ч롮_¸oTÁ›=R2Gì0î})ZÏŒ:y÷¶R…jŽðþ4Î4E|qÆÃÁE#6‘@agIGkÑ7ÉqÉÁs˜ ð³ãI <WÙ«@‘ô,ÙoD9+‰ìàÌtS–>1øô¿ëGo·È=ð8ZDÆË<¤Ü§§)íÈRö±Ý©=ÑqØrYDÃwÉç›u ÃúºÞÉšE£©LO`-ÛõO%Äl—÷á<{aPÜ—n—O©L–É­ÂëÕ>~K4ú…:aÖò3*ykdüj*mÅõé#Á~GXÌWÕAc—ÉÒo™‰î‡Ø¡+óíùØ&!yYÅIéÄñ[äãh»kZ£}æîQù3ÿxÜðø‚KY¾¹÷Æu ×龂¦Û·>i‡U_8¼OOd½8H•£Î>ÆQñÞèÞñ¤lUŠ­MôC O*ØÇÇ}¯žÅ6ñó”»U%cADyy}\¯^Äh?{ïfà”Æ,æ=0Ðú—bÕGnÏŠžPØU°LÛÔ*b/+$†R`Hg~!!ô­ˆv3åÎÅÎðo)§ÎJyÙÎäznŠ€ä¹oV=;dN–)š ­†_i¹‘¿ NëxM‹{¢eoªTš²Y0oŠq@Û,ß/,dõMú[3°\ó0ÄT}Y´Õ§º•‘‘8еý……~úd¼³N_Lyįu„»_£@{¥·œ;l–Éí [p†n-¹Þø>¢ ƉèðÉ7gkûžU–÷ݱÓxš™B’Äõ»£_h\’rAð&_h M) n’¤¼œ”’7Ï´ ,Þ°»Ç'ŸŽ‰\CŽxºC¥ïŽ=${w¬ö|zžl!¡Vc¼„sP­»æ rl*/L£èpĘaPÝ`óìéÈðtZcw€Òž©•ÛÐx9ú{#ëÀË®²u,"ëÉËÈÏÔ“v±x%.QŽ¥i[¾ð0ýÄcw¢+Ñ"b›¶EÀÍx†AžY'¢­Žh¬jÉék­Ö瀽$é^ïKÒ“òÔ+„Íጠ™Ý¦­5˜?åœfbÛ«@Ëôü™+(HJ¹xƒCÎé5×¥™EJ=läRÊk2ìÑýBÄ?]´RJ­d›“ïr©1fM“öLzØHæIG—D@CA§%…Z†äª“FêÔùSm+õ÷GÁ³Uñlï„}™xJŽZß+ó¢y>‹ žùû>ýÖ¹'Hœ@Ž›ªO¾¸—=½kö¨‹†Ø… k¾0‰O?…½$Í5Fµéì,W¦E:•»åp¹*OeEu)ɶäÊ»Ê7å`µ$À¼—D\3R8ÜñZ¢J æ§vܽ1° ï÷ôù:¶Šö"ÉR‰¼ÑuºßC¬–Øö9²•Wà(¨(|:kÕM0ÞXÄ˶{,d66>’R¾o'tèô­fÕ¦¤ç¦=¬í®™B³êMz¼5Ü7›ëfÝù&ã)H©i``Œ0ŸÙ°¿N@ n¬ŸžBü.ÂeTÂæqÂ=~øb¨˜°¤r´¯I`Áè—ï©À<"n¸YÊóê¨vÍ2‹²ÊÁµI#¹öŒû¥àeÅ»(Ÿ=ëȧ”©žGË+¬ç§lð£©2ß?»çóRG¹‰7q$d+›­{ í m<=æËáÍ×ûV%ÚŠ,.yµ*ø“qûB?ÝV‚l§+ J¬õU&$”;Ũ !œ¯Õ·—émK¾¸›’H¬Ñ¤ LØ_ØXûVx³?àäQi(©z%C]']ˆ}ïÙ¥êg'RúôÝy*¯–Ü+ŽË›PÂ<½[ìލCBP¦ð;c£6ìÍ,#Ivîw}o|6Sì:¹D‘Bq»/Êõð…c¥ÔŽfI½¾xÚN­«×øüIq{þöš› Üë}4Yæ±K[ øòÅ‹xÄšHÅ³Ä MŸ^ߌ4ÁñÜA²CWå¨ ½):à6ÆðÍHœ žP¹x‹ûc‘ç ºIׯÑ;ð˜D”è¥<˜Õ½™ê¤Ð=¼à‡'xÛ×ø´¦H°¸&GD{~æ:ºÞ#‰—ë"³ïZuº[ÐR%½8ãhåVÙÃ!§®¾ðyŸ^ì† c)ÇÚ<‰s½bÙãYþÜšì]³V#ÛÖèÝSñ’gÓ—¥rÀ–)~,{¨y÷²Ö¬RñTœô¬VKJG7\–r£Gú Ý<±äEêh1ütå'n|ð„»ŽEÙß2¯´©¸—ÕÕó4ˆâx<®Ÿ}ºòÔ»Û{óĪÍï^¦1v’äiÑèyKŒ›xy¤õ°"È û€N:WŽœ*W"¦œžâëœpËz:'÷¶¢”@[«ãšñ ĽÀ’n" íßyœ3R¶s휷Öx4"ø wÊÅž’#Ä ˜»~zè'FF>«4&.*ýÚ,¹"õ8¼ch>„a½"Œ–NÈd0Ò, X9>²X0æ1[#µF«%BÈÈ7¸L§/”LÙ§r2 ¨­“Icà+:îóòx›í"ï'Jjþñ…øxI)ÉŒG¾å0ND^T„¹©wõ$?'JÕO§V~~D±V8Çem&ï­ ê‚£ \bk»£Æ”½6ÝG[á|ÙE¦9š0xi%0¼\z=±ö ‚ -kçÙû;/½N¶s@­àª¨X0¯©0à¡2ÇRÔŸí¡Ûmá MUOw4ÚwÖþó¥:P‹½ÏnoŸžý ÉnVf9Qš,€••l•³=ù°žM8un’¸ŠLÔ¡ŸGÞÊC²çT ¸àþDâ•2hIGJKé$‡M»Ùc«•¦ÇÚu ÐkYjÏ‚ßõ5CnæéÏùbŸ©N½Aê][È%"dІ[;Hs’1ûV”º7øS<í»×­¯L¨CŒÜV.³¤£î<†ø&€†éµE×óëòó{x¼o¦ž³É»jøIÎÚeΆ¢Ü´À0™Ë¦à¼ðxû¤2yÚÀ–è©{ë/õBü…ÕâuÕÅC—Ãpè¤`W‘+q^GÊáÑw)ùú x?±úôqõösQH°ºÐ)®š'étÌ=‘/CC,ñy¿@öÅ¥“6ÅHÙÙÚÉÇm¯Š¶Š¾N5pÜŒ%I“ᘂ·èóL‚ ×É+ÞÑã7e$O‹…ö§Wùr©”úë˜PP x ŠÐ=KO< . \k?sS|:zùˆ>£·ŒWò–ü:íñùŸæç]¢¯õøY*ël¾NÜ©©´kiÞð¢7œªÒÛ ø-3²? Ù˜5-AxGWý„e»v«™«ÉŽâÐOlˆ ®JO”û7^®C…ìZ@~ÿYdº`‚·º¹˜ò˳ >½F<[U.ýñ£Uè½]ÆÂ|›=A‡Ds­Î`–;x¼B~bî»±¯÷ꥑo*²ò ç*ƤËÙ6!þ…\ΰ½Â!‹§ÑàkE–ËwXðš®xOW"“ó\UáÓÛ¾/Ц»}!šBúâÜLÈñé,ó½èq€%t†SÙ€ƒ#éŒQyp³˜¶SMá9ÚŽÔg+ ”q7ƒ ïä‚oDŒ®–B,¶çy5§6m½Ô"]öÑ–«£‡÷r7ŸAúÑ‘þì¤;v³o‚º¹Jýº9ôt臢ï:z'búR>±úÄ.§¡TƒW±IãÈ|5ÞKIg€pÜ@tΑ­ï±[]v€« €KSO‹Ëm>«Z¡QI*Š´i6x€{2 30„Kp¹Á…¯¼ET qï•“0e  ¿ð|Slï§×Ù50Ùì³×æ'ìõŽÃQíÝ=ƒÌG{\N Ýüfuò ½ï«åâÝe8i÷z¹V÷^¹ÅÛçý´çØÏœ¶wpÙœ4Êj©¬NíA)æ"Á:Q­º­¥³ê«¾Zö[W棷Ê|·î‹Õ’})n`‘b5© ëRrRzfz Ê1ѽ¯~vX÷Û«õY ͘Ý7Iõð¤-òƒ'Ê‘ZhÚ4ƺó‰ß÷”Y•*´ 8õ¦Wh*+ À¯áa°YÐî›LRæ‘Gq+ˆª}1P/:œdˆüAÑL´ È…ÉùQÓZ´ÉоtxpËqÊUyõ€'–¼›Ëuá-ÇËè?o•n—Ë8hó@ø…`1{–³“áÉu½ô^¼Å‚KÂ×r„A_~_FÙ!Y¨SrçÒ£õ™ÛøFsšL—«½º,Š’©k”T„ËUíÁÔÕ¡'4"j›9ù:ü½0·‚bÔ×)ehJ,(í-ƒ®êò1*J£¾€Èœ ƒ÷J’:²£ 5¡“Îñ^üÌÆo€.&l«G^³âW…„¯1²&µJÑRê†ß·ToÝ÷¢Yù¢Ø‹¦çÖƒÏËÅ’š­ÎCcÓ¹Þh¥7ì’!6ù.â ¹ÇðBB… ÷±¼ÒÒÆ3 ªèÇZ ÒUF# ã ƒdš(@)ø`¹ùäe°*ï‚m¦!K"úNé…HÉïÝvÝ¡ve¬€) ‘û–9€ùSjp½×uÏâ„ÝŠ>g² O÷º:ï 6RL-@EïA³½ÞyØV#9û §Uf§ªrÊ]R _1%4 ¸9 .“{³?º´•ˆ†| æÒNØ–ï…`?¦C7Jì ¹Dë%áõ`Ù×܆äDº µ<ºá({ÓÜ™D»Ô´¥LóZõI/o+‡ÂÜh$¼ªDÑ–ýû^û˜[•^Ž«'ƒ“<“õ¡"tàð{ïW8á+­ÍlÂv‡?Ñòy×<*êÆíc¢7²ƒÛæï½wD ž"™âò¨„^õðÈÈi€å­aËØS"zÉ+¼¶àO§«^ïÏùͯô¥=vëH^Ì~Yí4,¥Å/ŽVzVÅßøX³á'’ŸÝ%Ýx¡Õ:•HKÕÀÏ2•éÍ ب^Ð׉‹WaÉPø,韪6¤Ñòó5À>´%n~ƒÛ\úlª÷èÜâÞ–;ös†²@6ïÜ2’Mi4bÔÖQÐ…<›{sv¦ûzŠ*瞨ÿžN¦ˆ^uŸtºÎUò&-‘† ”0=ˆM€·NóJœeý KüžN@­ô]LÏáиµ§¢qé;7T_‡Ët8§ñw ¸¢¸Œ4qÕ«t©WÏt7HŽ´ºg•ð½¨U×Ï2—ãAhûµi<AV™·`€€ÛQêàz´éçYVޏé9Áo¤£”Z!Ÿþì8KîjÓ{œV&ÑIoÁj º.¦à’û!dÔ«ôþDóûŠ|ÈF-ÔÅÝ/ßy‡Í!ö‚G9ÊS­uwez¼ÅèM9…ùк2¸„ËC#À°ŠÂ.©$F¯±78Gh/ŸûÕQtïé(Ä=èe‰±òm7HpÉV-¡XurÚ)>2Yì9õÓ3šæoÔ”JWàŠV_4§¥ÏäCéGWʆ¬_x~ߗŶÂ"r^› ˼™Rç>æ=V3&ë{ýR|'º¦gžë©Æ9 ÇÈ‹ Öw锂)¤ò¶°Š3+dzë¥kj^;éT Úù1/_¥ ÌUØs®pÓìÎKÊ·$y…l­‹’PAã!ûóß׳eØ&§(¸Êñw(LûTŸít?y ZĨªŠ£ð…è÷¥Zß6vˆËÞ­c•À¼×¥»Zíe‰=;/5¥‘/jl'¨¢·|¯ryýª‡uêŒß.¾•Ѭ0Êay@,OuÄv_ ÒfXHÖ ó1ÃÄÅ*U•rê¦Ë,JmÁKò‰%eDWœ+X•j°lO”`÷‘f2["#×S¹“•’ÜÆŸ¿¡ÀÄ«´Æ‡À ÷´•ÕBÎχi%Ö}¢åcüìo¾âøÞe Å¨ë3W¢Þ'Ðöœ:d°òqùEIdm§OðsŸ4~Ê{0¼Þ ^A ?[Ð;Œ¬M¸Gåy±†‰‡5¨nŽ 1o˜ýf îa\ãœÞK¶°}§AN³Ñ*ÌŸÍÀ¤€d¡>l ùóŒq~áú3EÄ $Ñt¨Ã &áç%þp§ôÒSÑH½Ÿ½’}ñ…2Á§’Easa[ý5ê ?壠À:ÒvZº„G”m8õòðÍDÛ1ï¤ÐñZ7M­ñg<'Бó˜ì~.Æï÷ͳ".Ì»ÆD.M ¨4\]qµqI‘Í>Ç{Þ¸¸‘¦ µŠYäÐÑxe‰4H¹×?s°¿õg‘³\=ï)<Å·¹Ëd£#Å™(Ÿ8ö<ÚÝÔà—{;zzî*U¹ÏR<·ÇúQì«íw0‹€Î—˜Ð…/…¢l,VïTÁ’éñn\!V/1¼[“»žmiZÊ×óä”;”ô ˆ«>x©Cõî=yüÆ4Â×ùA4H&*ÊÔ{ 6Ä8ÔõH鉽“'?‘®¢ë%ä^Ô×ñ²,M¹ OÙ“«|ŒÎfs²ˆs¿æÏî7YˆÓPðl AŠË‰ö£ FQr¡Gþ"N5aÊÿ Ê¢³ž»”Ç+WFˆPúÔµÚJÝ-…=ç½Ã}¤ŒÕoÛ3Žž¡ò8Q²‡ÇîË,Àz‡ŠJãÆ…}Éî7 (øN‰è¡XEí=â6s.Ël†QéÁªôQ¦ù…u?˜Ð8#ô1¬€×oßfoÁ3®„¤5æÐ“2·åÁþ…õûìƒ6"érÉ"éñ;c\Àá—ï¦# ‘aƒ4Ã1l9ƒÄ1Éz¼”ì˜NÃ^"|¨ÞºÄy<¶Š!£uÞ,9•×ÛÍDõ<“@Š‚Ci\\…²²kĽú´«Ù} ‚k”èBwä)¾&)ÍÈ2ñØÌ»>´™³Ÿ^½E~sO|Þm—Ô{8PbzʰªZu ™¥ï‘ÔÚòÙ¹£ž>†£Îõe'>¯©GfÇXö^/m¡¼ši;Ö<»WžÄÝ\s¾´I‘Ã)2‹¨2„‘³3%hBÂKƒÏc£ôf€–š‡ó•¼QXÎg̯Ù¹ECØUØd ÇÝmoNV#—ÒÀö]Ñx/­ -Â'šP JXkjdÖƒäÎp¶õªA•^–á2…#Ï ®Í•G¢#Aó)(‹ ÉOÌÑ_kìb?¾}Ô£¾çá#㤯¢`à= ¬FÏûÂÜôsÁÔ+îWm­Þ ˆj² ñ¶D³N®ĘÞVë3sP¼8²µŒ§ÌYƒ—žöt_ŠYç ½ÚFs†TÞlGl!#óžvjWOo@Y\"ö®YÝËÂà–Š×D¢9&Å›­72]¡Ùù 8_]½¼pïí:Ê•°®€°ø­ôè3¿{*È ÑM‚ ŽÐ ×;®:ú½ó}¡îŸÓ3Œ®×“&´¡¸Û!vƒÁèŠ@:í²Æi{œúàAaõ‹MäAs”†0ÇYΩ’÷¸ÛÃVÝ{óˆ03ÔQÙgAr±˜(Øïiõ ÊãÛžzMªdDƒ>‹\°{Û4`ÏßD&»ÁRf,hfÒ@Gß#‡tÈÀÙE½Ÿ¸Sf-úX½ß7 Ù>}o0Ú:ò˜çUM>$ŒÛÏŸ=Tøý ÐkÞyϦgwf£·èË hJ´I j u?1á\ïa^¸=ðNÝyâ>oðAñ¾×ÀÄ"sØÂ(úÆî9‹ ó{ü$Õ±GBÊxNΩ=—sÜ,X=T 7žu -Åô<å Hè $Ÿ$¢’$Ä'PÕ°@ïùÒÏnÚ2ƒfk8V‘ad°Jû†Ì·hÅ ©jwâ yøl§©O"ÊS±¤{;V-w4Þ³'Ñ>ɃÛÚÖÖNi¼¢ÄߥÚœúR\ÕÎSdU]AõÉ—¨Ç!gÉÍÎT\ȯ®£+3d(á–„î½lUÇ-Yät;j€-ö”‡[Žª¼5¯ž˜frÉ¡”‡èÙ3oÒ´†¨M+ïkg>aߟA½,,êµ69iÏž-fNºœ÷“§3Cq ¹ùÞ;³oð?;+,gÁ‚<ã(€žÒt«Aê\ WòºdE`µ +4­ÛJ<À“mz{Àø\äàDû™†ŒhÚ>4 ΣÄ¡À£Û 9“Ý‘—XØ´ŽDzu§§œ³â/Û0ÔÒ· ‚¹šO¥:°¤Iß›ÔáæôFy»ÏÑkð=jxÜ–0•’-…#¬¹R*?]'Æ»OÕŸ÷ƒvܪÐ~þ®ò8©h$kLeæ~ÔoíÓµ„ÔƒÐUf]áë¹öÁn4ÃÉŽ1TdbŒØÌ&w‹÷zS uÈ”1Pê)ÆÙãIZ†„¨šÂªbÉr¡=®Èm-HŸnÝXÌÊä¥lHm™5•Yj6Ä2å›}/íêÝ9e?½ôC .J#- ]žM†Ç‘½Ëù¤)«™f@Dê;xÊniµ@f¥’r=Úja7nìð…:„¹q}@Ÿý–J§¬w\U¶6f („ÐiM¦µNFθSÏ]ebãCŠêž18ÖØ+|A..>T8(2øfé¦Ô!½€Œü:%t.™¿îè Wn¬—¥z ¯”°Gž¨œÔÝS®§Xó`Ž×Ië¹ÂæŒéèj0û½…'º±Qy›p0¿Y…ްšTpEÀTÆwúö=ñ“»x-sºÞò,œ[;ÃÜM2+¡…c¤qú9„IW1 :‚báVö;ŸH6Ç¥)-tx´€Û€–úVì=Û¶ëZM;'q9{À»DÄ#4lõêé#WäÑz$a”%àiJÐØE¾õ6†áú!+nÿ¢!˜­Žz˜fn¸Ò¡…„Ô¡ôì‰+` …æ“ ó7 ŸíxݳÀÕ58SXz‹`õµe…µÍ°­“1åš Ÿx1\p;šBW?ç }cîh†ï„Œ†du1@´P_kO@¼ìö€ü&Ä? aš‚ŠÌ¡tGÕ–²§é(ßý#>[9¼‡°Œà”ÏÄ_=ÐAOÍZ{û&%ªô\VëÅzâÙQ'À\¥<¥¦ª›õÒwE8 ·Èè%šB\Ž-»M±ÅX`^Š¢æ:É£ãÍ á-ý¬J-[ß>TÉS©÷ä½qЙ•{n#lÜvaAMêZ¶â„kíKOœQ*BKÔl‚t²ÅŠhÒ[5a~‘2‡×åÅÌ5¥x¡9YÌ/ظ±Ì‹0Vàü‹„ï=w9nTÎ,¾ iÀ3 ×±ÈS–ÒCx±qýÇPQ_Uö´Â¸“¢ÌC|ì¹ ¢Íz.ÌÌýtÑÑgE€ÔE.˜ žÑà zÅÚ:Rå"ØÂܬ2–áiß¾%’Îâ"¦IÑx¾KXDó¢yò¶LÎZúÔƉ:Mûi'Å¡²ñDbêrŠßÏY|Æ,'Ù_giZöF_;¨ ‚úI ~¶÷KÝz“ªªIDàø´0R˜š¶£2ÞAή]#7Gäó}˜Ý”â1A¦ÊÏCI¸Äº`P` 9™±Š–.Œ×&ö$øK6vGMð\®¯ìÌìRn³ŸkHSÞ3 # ñ6‹ÇWOD›•&ºÒë8·øU¦oz]E¿óU{Ô #Ô/6}ÃÞ1‡"­3l¬e4¨üÁ¢£¥£i´ˆ<’ ØÁ<ÂE ãK}Ì:ŸÄÐ÷|^õò°ÞA4örçeо-ã^O=§t1æ÷€Õg÷maW[‰d£€—Þ>›Z`í'â´£¶Ä÷Úž¸L–@Ìa9+‚è“'ú¨¨pû)/:<¿&~f­E™À"ñ¶‡Ùó4ïu5%¢jVú(y‹­¬Xçö¼WS²@¡ 0¢Ã<>³%¥ÀfÎÆ›h‡Yö'5!g$Hòt_žº#=5´êçT·AdIº{€5ë4ßÔ|¶|BµBôn%x¼©Ï:§vB1…ðFߺ j;x…‰„çR¨;¤+XZøYs_¯ÃàÖ¶º  \dmfå>µðsê’ •&¾÷’/.„_që=Ö×tž^ÓÒù¢íEíxï«|îa ”ë^§Î¬œHÃ>ÊÁ¥ NyWOÓßUGÛÑ@ÇÚ{>Ëð8—èfˆâg#'ö a2²nçó›ÞAdO´Ý}NÔ2,/Pltd?ÉáÏæ¯ìª±ßÛxQ8¦hÃXϺÖ:ÅZ/ß=ˆ7ÏEmÙc»õ†ú>Ð7g0ç¬ùl  ™YK€¼X‚a(¶,í"%/r¤ï=´'•ÛQøz÷Nòa¥4ö‚Ëm…CeEŸÅŠ/ðž­òR4û˜ÿâ¼3\8y^vͨà’Ëž på³Íz9±ÕRÚÌÞU~ªÃ’«÷Ï~“7 .boôˆiâò2îú6ÍÅ"5ýÔZÁ'=ï3l>Xç.ôâ¤GÛ­Ýe.œc²¨E£¯uš=1N: »Î4÷b“íÑ—¼=Ö-ë}wØ‘ÅÕˆÑwZÜÀKàæÌ, YŽlµR=­zÇç‘X3­‰»cï^×h@…¤U,ßRïÆj«õÃ)ßWîC8p«èkÁ:ÉÓ):ÌGï4äU‚&R¼[Õ¹¼ß ÉäGÓá÷:ŸC½¡÷ÂŒ„J$Ìr%]£’ <¾ÍM¾—ób#eûìT'’Ôžé0;ãZ•©ÏxÝüØ'‘.”7å:¯fI,¦è´Ä/G‚GÎâ ä–%tùÒáŽÎ V @¤½…W¸§”A„Ç:ŠŠ£& »™„ «¦&©ß»èTï¢12%©†Ož3€e”´  æ¾0Õ¶ ¤vïmí-9‰^1Ï#…ÇÑ•ÆÏb •Qôâuu”¾ØçÛ’c¬/·¢}çÞŸë€yìðY9z¾÷I‘~Fg-~%(Ïôùö=Ë·Ð|\~í‘f Ò¡042TF5žÝ†’,LX®œqfᩎxJ˜†e*äˆ[ùsœ}U)B‰úÄ,ÌC·…GTÀsÂc*¨A)xûüùÅy߯Öx Ö†˜cšÄXN½4šZ15Ó²V¦jŽŠ’ű%RJ‰xSÅ%mn˜ˆ'ˆð^ËO’ìΓ< ì!Pîñ^yÀ#¥hÄÆDIuØq}{ýMÒgHè6ó—/Ò²$‡• ³(*ÝÀ¬‡»œ•5§ãx:Þ îœ¡â‚aBR¸ˆ…cà ÷jï<©9sjÜ#€¡¨,Ç} âúv²¬·¦jÛ䯂Î&©\¸¨ÀCÜ/á¼Q·õ…¾™Þe–.ÎÀÑð}ÃÁY¾¾Ùà$ç9[»‹¡s ¤Qí­ð#íÌ'|>‹]%Ò°‡ó~ïÓzj³^U&¸âñ²¾¢#äzÛozÑèAÉ»±9ÁyuÈ–3*Úòô ëu”v*3‚aïu£—Áñ¹†“éõÕ{ Ûò´©9úÆwß]00ˆ×#¡§t®íÄ[(uÏqµ,º9]BŠU|½ØØ©FàùæŽÜ5[¼·Æõ3ïyèüùG„kå‹ |±{–… ~O´ÍÛ!j²Ý¿È"ø ¯/‘ÌHOõvæ!ÛñZ,qà–™ìx¬8G®ój8ÚºØv¸H­ÀšŸ*é{1Ð-3ÔG„gûšß‹|µá24²juGAÌb3›%Y]O1Ž“S¬¨/Ȉ¶ÈÔ´µÏAÔà]盇›Ú4Ï<Úä¬ÊÙgܹ8‡WlͤúHÉ9D´Ý]HákÙD†…Š`OY¢k!8 üE:.1à)EŠVÙƒa*®!É.´ØÈ­½p€Øyßt}ÆŠáUé êK U:Í{Á£¡ Ö}L™9Ý{ºÆë§±ª†2ºanîýb¯Ü ¶3]‡æ &¨äÂ^{Ð;V5-Úô›Ðz<»ÎFÖ‘Áu¢T´9•.*OÓQ@íÚÒ8”b^<[+'¬óu$¶Ê2&d¤›Ì7Bhï]¸OéÍÁ“7<ÊÑF‘g¨íUùügÀè´"TVmó˜èíÜãÝhtLðGªcž@>eŸ„ágÀðGÝâ,ð„C‰ÆÎpm]9©Ü¥E*•¦^SòÑ ÒZ¨Â´H'EÂ4¤ÛÔ›VÚ}–§X+fŠ)¸"ûUæÚœ´®ࢡe‰.Rç<ÓÚ žC#Àkó|h|ö]Šgsßæíîó†ŒÝváË{-xò†ÆÉg¦»b @g€0)ú¤KŠ4PjË1ÂËË].ÊÒaÃ&0mÉà"ÍÐ~Q–MIˆž`§×U†q$°¼’ZIœÎ¦Çølë“2úŒÚ¯ Á0ÄxÅè¹*nøm-“ŠáEb§#+»0æ’×s…#nNNÏÆ&à—ª°4†‹:œÝ¯.z ¥õP ®m͆‡ ÅVu2z·ƒÄÏêbêe[ðŒ.Å2ØÎ²†$Ì)wMõê•8ò¾è¤ Ô@¬Ý@ý¬ÍVcÈ-7¼Þ!² ¾tŠ302"R%<ëçž¦á £‘)еql?ßY“¿OòÒ¡èÎ4>Ó3Õ˜ù6â9¦îÒ½ù$?C‡`ÙTY/Ým=² ì¾B¿yp±P¶ôLt^?ëQP¯i²A}Á 7q {7ó܈Q„åñ•ö«Q–]Iqruí³Z¼á$2ï\O¹Ql|ÌgÃj2CèÀö´s:Å2 ½V~ÝÔgïˆø©ÆñÛˆ=ÚŠçÄ£TŒì^åÓÃÄÝ~¨×ߘYI¬=-O5¬½`=Z'0‰Ë_´ñD†Eñ›'¢±Øá1­4ÀŠÚ@‚ý0½Ý÷“¶ŸöÈ1Á'¢¸NX˜Ïˆ]«éîíÕ¼ÜQqÂõ—¹öÆÁ(ádÉõüÐT°‡l¬pë±Ó™¼ìR7ç"8 ÀóâÕÒ#‚Ó¼ÞÀmO8b¼P¡Ç¼ÒËÏ£ŒÌPû^n¥MOôPdFº’ðÅó™x’•±ìB58 3i¹2 OŠœ't±+ǹ™‚’Q¦D„¤•|ñ©ÄO“ô™ŽÃ…‹×HÏRm1þŒÀ”ZÛ·íqY8‹á›¸ï#HmÔ iÇHšŒ¨Ì î)WX ¨«DÛiƒ×æËCÅqɧ4ûlà=Ti°×³U‘1½kG¢Û÷õôuè¡6ÏÂÎ:ÕºsÞ,N|. Æ!0ÖK®œ¸½«ìÒ²\¥›žÖp¥£Ì´L°†Ýoë)%¥ÒRÝ‚tç¯bí”Ì@™ky–ªØ‚˜ztP]\Lç‹lÑyÆ.K¿¨{º“¤Dó¢Ÿ×ƒRÀ×&ùÀu+fž=8˜‘Àì.ú¤N>#I§ép"IH:š:)€ús5‘gÃë'ÐDyÚ°Ö+Pï) ë­ÁËX·X‹›7˜êÞÉÏX±ýY%Ìh¦P°nž¯xb-4¶Á[|:¬š[ìµ³Q{¢‘í™›lW†‰‰i#mÏ$}öŠÂ\ckg GQR&‰_è .bV’^Bš…íÚ,¢…+àŸÑôž™4ÝⓜԚÄîbÒ:}ïgž´¾D¶PoŽÍDfx¯œTªxµ}ÐJûð´å;Oêg89Ór™V{„@2ú6BÇÊ*Ï®ÐPh˜‹P¡©Ý©a9Å´°iöüÌ÷|èž €!D柽®X«=ë€õ<.RkF™"vdï'ÎÜáÝ/ŸašñÞk{/]¸Ï!¡IÔgÞŽxR‡¾ç ÷áõ®°’¯Ôœ•rA1ûã2–[Ó+|Ú:ð@AD­wOBa.ˆºžÆ¼6·{]É-ï%f^Èý´MchÂXŒ‰aë²TÎ73"ëoº€X÷¬ÝÉ‹’¸£â“>£OÛ”òަM­c¾k7ô«¢à|›~†³‰hЧñÞÁúºR:†•s„˜¼Ø£Ç)dqMú´æ5@”îl=cǰ¬zA§…ÓQé'n‘Ý#©…®Ü6>ìRÊÑ8¹õ¼_Ó¡tŸTŒ€Ÿ3s3Íš›c=t#År‘~µÕ$É-o°e¸lµ„QÁ}…ÇTœ Pq)ÅÌü @3k$àŠ xõŽ1ƒ»tXAÙC 1ý‚…£6™Îß&~èðI öMSZwÙ1cñÐîݱí󜸌6÷æã&€4žˆP^ìê Vâ"}/÷yÕkN© ½«öƒ>†% Ñœ¬&S9±+S\|¶]ç¢&ÌSºí‰çñ!ã휃Îx§&,>l¸´ŽËÕÖ\•Cïàt¡X])®9’ZZ‡ wªa;|rÛµÅóž%÷Û§M(ôºEzFé„0+(½Ò¨<,BûEcxYaÇþ¢Ÿ¼7Mz²ôà4µ‚Œ_çø+• ëÐà™‰ {ûMágtyû„*!Ùt‡èÞ;?–õ."¹2.©¶ÅmI¯J FQ^{—w\jŒïèáö‹{i ¸\„œë¤•҇ï2Ë öfFn°ê»p‚ƒ¤HwU9 Ï>ƒwT³{ð0žú‚ÌŠXw;4d(Tu¿1Û¾#lÕš{®ObÙ…ëC8wN‡”êfj‚ƒg^–Hz-ò÷ÁQP>Å òÚ³0ºé–t 1q¸àq(ìd3+€ zÌ5¼¢è|=³RýýC?û`º¨áœMÎE¤Þí†%gEªá‰R`¼p‡öÜ\-µßÓR·ËŽ„£ëö墷aûˆŸTpÉÙ°:Åðy÷¼*Ö‡X.×Ää[Ђ]Œ‚gà 9LO{A‰Ó§½¸_\ˆŸkÀù²+¬á>‹”Þ„âóÚ·ìx:ì‡Ó?ÇöÔóü!ܳégóêúáú[Žæ^`#³½^ •/¾Ï:þ,W-쪡´XGWÜÒ‘˜{§@éX m:Å;©Ty‰Âªå‹EîãïÍé“…Išrõ“¶‚ǰž"1÷ž»€,@´òdÄ;|À÷ÀBœ€{«tÙÆ£ã¥lö)p$“ö›ª¶¤d° ÓLŽ}˜§ÂF¯ }.5ëÍ8ZirØœtj X†[Ä=ׇ¥\º^SÔÍX˜d‡î\“½lQxöZŸ%˜÷¾&YÿI¤Kï„÷sðñSk#ê@Œ–·*‹bÅjÞ•tµ›·}‰ŸÁæt¤©´ƒCÞµ’)Pô댴á¤"Cãƒ¢Ž‚})ÁÁá©*«¶…teûz‹„×Áy°·Œ^6ØÄA¼}t4z„Ïcýéæ@ú¼'¼÷„“w¦Ñï·Y:“‰¢]V¿MNræLãÚ°¡J¦`1ìëË.i°¯[93ŸXk;ß`®QÍ•³ Þ0a±U:È‹ó|± ŽB®‘Þ)vRòv ÷Ýp¶4¨Qü¾‰— dW0!.\Ë…Aõã¨uŠÑâF¶yiËEõm­LŸ§ÏE©°v<¾"ì\õI ]NE/0,†7šÅèñ^­À‹‘…¥*ÇÈ>µTEDðX55d£—Ú™®¢Ñ÷B§ ;(D²^+ñ;ÜMzG#øœ– ö‰G]Æe ÖP\D’Us®Ò«FåA ½}YÖ—ëW‘§áðz¡‰âÕäAÔ˜;Ë›&5çÁÎ\¬w` °wa¾ÏžÖAÛ2ô(ƒÙ&{Z®¼e‡À[“Н¦ƒ”æk'|Ä úD¬Úh¡†wˆ ƒ„ÎËèBØ¥Ìkq© àˇ‹¡Þ72ÂjA:g ²œúÀVEï‚f Xû¼0<¼¡‹Ÿˆ54RÓxùÛ@tÌ{jÕ&ƒ?cÏÊx¾5 Þˆ„W>Ξè³sÝq-Ñ)ŸÍè'ü{`| rãC£WÖ¶‚Î9 "×´–±Mž¿·ˆÚ[I´U À€VÕG*"—ªôÐݦü ‹E_yaƒÖ©Ë<;&×$(g?‰‚÷ªÄù²|ÌÏåÝBJ(:CËž¯¼Gj›GÝo)†kØÖø+7Õ„yÔkz ¡È~¦FMLŒoïæZù‘-Mšj =æZFÚ’™}}ïŠÄ³åÊiÄͲõž‰ÚÝÉO³G•^âÉ"G¹¶çaÈ€ëf—Lc@2'B…[Ÿ„¾÷i¶L¬e<[¦Ju|<™â‡lÅ╊ {öDÌ%£ö¦€%Au ÞEM¨GïA/פdß{Õ[>ƒPžã0Q †s͉/OÛLÇq9Óý½pm®M½§q±@¯ƒ\½GNPŸ’¨…ßÁ£ò¿šÛ‰Ë.(°áGAÁºpîuëþfJ-äY÷l+û#—|ò(Q²mˆ% áà4‹><9ÈçëïÉTНvQûæ/J)èAƆ±»Wxr:k0»È<Ï*mvÐTÒæ9ôÓþ¤T>£PqÜ–“óæ´ò:ú+Á9É囇™íÊUP‹=à™âjã­D¸Æô˜ôé©ÈŸñ‚¤¿õi˜)}Ûü¢3â= À’ã+žÞ+ð¼Ö!g5U7.|Â% ­ø @Z8U]K|…“1R¬B‰w6_äñ,#z:ÆäSMxôê-BÁižâ ÀV×S ™Gª 5v*Xùl íТ“\žØ­?Œy~s5ö^ï/R#Í g¸÷:”È’<ФJqâ´ XhÌá,Øæ“ù$U?CQ†óÈ;vàõ¶ˆ¸·SµNàï>Î`š™ég‰VP&úÒŽ-#Ìu#žé#Š?+l K£º,äG”pýÌíÆm,íÁ‹ÍÇ%f{öŒjª&N—Óµqf?IÏxG5üÌNñ†ËB(±œô%ák½M{e XDÚFÛæÎù”ʹ4oæ=/Ob;¹•¿µñz„p«R­Æ ¡fêâUfÙ±ÄÈàn"È‘OßÏxtò¸Þ<âÍlWf¯ÒñVtÌÑiHcáÞ±-g³ãoZ?ãѾÁFKHWí}ÊRöˆèBCë¨íôÁŒùØRvª.–bë£*àMÖÌ•0Gܨ{iõ„w–ñÂêiÊÁž`‚aRq Ï¡ F.›éÅáNÖkJ6k¦  }à,1¬ÈþÞÈ9äðLF/¤|öÊé¨JàJÓ+ˆSÞØÌ’÷ãÑq—×>N+ÁÒáˆS×n `´[îêØmBaøÎ¯<©cÜE-ç*ìíHF•?ÿ™{­XìnL,ß$îBçc¨7ˆ¢ŠÔ˜÷ž&º5}kúiÂ-aÄËÓ9£c2ç6(kŒÌeвq"Ï€Œ‰kMP¼Ï¡tñQkš £»NÀ³_\“UR\ saÕ1 Wc=ÑÇDµ6bWªGϱ­Ê$z ëk'UÓœ'“_nMEH†ÅK#ÙÁÄsk‡:‰z|mú Ð›Þóçfûü­¨œâù m¯–vw¼÷à†eæ o^ír]§×Šû¶ÙQ !ÖzÌ¢ÊéO+v$èÈ|¡ORÓ6¢]Ï®fêmúh=GÙ}[÷I­F¦)ÄSˆÊJ+èT~AZ8#í]9I/ÔÆræM¸é™5Cýé½CByÎÆâd ÝI/¤†ò±¡ÞêÛ!è+Q-f}5/vÁÐj&aßøå8LÕôë¼bëV¸‚[J‡«'Ë;c$¦÷‰{ÆðøéÃí÷\\A®»vÀµ©žô^(3Å›Ú0ÐBÎ#:,ë×# €}Û$x•èkD­‹ý Q5ÐëÞó /}Å víšúWØÀsȲ˜·úPJûù5)üEp=}¯™È¹È-Î:  gßX?IzVÇ¥=öMðg JÉاO“©]ú:Ûø€®…Ã鲊ŽÐbÉxß3—ñz®]#¬4œB÷ÞÉ£õ”‰'r ¬Ñ$¢XJ@bÍ_uJ¸, ‰YØ•°¾XÚ0â½Au•f,iA䯂ºö ¸¬™×1a[Õ1ˆ| n|(z9R<ìz®§£VócŠ”’ìxhI7Ç…†¿QElI‡‘âÄ:tÍšG!*îÅ%ÞÏÃ`(ÜLAágffòèEì 1;ÎVO ½Ž~P—+häp¢ A°øI1~ï ´«Vmãe˜ðæhƒXbJAø3¯W¯kO2lƒÛ÷щ²˜\Sº?aS¢ós vK—H‡CØ2ð?{ÈYì’×,¦æbÞ°uúpL“áðLØbcº(Ý¥f($@vP=•2$lúfh¼wŸê“¶•ć§ Kœùœ²VT±QWc—œ —–X›%*ß5‰’¦•Ý!Ÿn¾Ü]ì[TÞ@Ã(<ÈЮY¹êžX1í!Ô¼`âŸF=HËî¯ÚûMÍ|=93c_z˜±Ÿc!™W¿çŸ$ÓgÈ:l!ï3ãp{6o¬2´þI´ºÊÓךÄP¯N_%s]Ø“¢É+Œ¿W6Ù t÷Iôû^háîFÏ1®r8/ƒlXÌ,TVÓ±…&|ƒIq$_:Óé™xðLç»X‚” ÛÊìB1ºÄ-¹Ïwä½íg¸c¸sOY™ÞŠi¯ºC¼V§BÁ•]À„zŒí®’w^Zzt]:H1i±a­Cå—Ú:ɧÀ14X%ÏÔ){´OåT‘Ǽº‰Kj`ƒh[ÇëÂ:„Öß yîDV2îTùÕ5s™÷D(¡$"±ÿ¢c˜{X^"gQ¾W9DÛót·«1HÏ×éðMµRmºÇB0 eù<¢¼adYbŸ´ GÎ À>®} tųr÷Îo`-&T9»Ó¨‡¢ã‰SaPPŠXK!£PØ úUÉÛXÚd‡h*¹Þßiy²ø"¦Ö®ìͳ;'.B*:>I‹ÎäGônF †Y® AO&¨9žÞ{Ãy]¹´³EÞøªI3•i­GÓËDjyNƒ›¼ë1;/X—ë Ç%²­½Öaö¨9É'`¯ŸU[Äó–ªã"K÷‹ì}ì¹…Ÿr1sCFiox)ü’# ÄŠì‹O²å;ŒÍ ]¾{,Ön…bÆlÍ9H†ÇtC*/©äQR3¢ Jô=ãsb½Ý×+ kp~ô\BEY½‚/éÉ–6)CðA{T­j Ä8ÀÜ;/.Eéì·ûääÑÚÀd=µîîáTÐîÚbÜÄKJ04]…ɲ1?u„=p½G¾r°MhlTáaЭL(¦ÔË~Ö–¸råùHóãlˆÙNW&aãæ28& ¿Mßb”_t?yÚF­gë.às¬êåhÏ ±PÇ_IPp½'Ÿtëg,ãEaqÝ*iω˜G‚Ò·háÌmé§åUuÊFÞ{™C ¤Ä 5ŒÎHù\™¯¸ à-Ø‹vˇEš^Ïã‰p Þ=ÌW¤ñ”n0¢n{ž°==‘ DÝ ÎŽx‚¹W”7L£c'Wmg)F ¬!t«¹8P΂qb7ÐÙ\a“]A!¡w¾èxnY¡J”ȹò´Ã²fOK”fÒ)ýA`©Šd‘Ѱroš£ò©ô r{ŃAíÜ_„÷¢xîèwÌ{LK(χD²ðØÃOOJZŸ¹õ'áFß÷a-(ë¡Úñ`{ ö¸ $¬ñ ªëaP9ÀˆW¯¥²6Ù®gu‘cÙç äe¦‰ëI\ò¬½|4a Š×›¡Bw¾U €”iŠ .»¶‡“hø'#ºWÏÌãb)[úTêÁ0°ôºTk;ÐäyW“¥e¬È+P U†÷4õ ñU¢Èé„Ô(Y4 P)LÁí‹MoZ¨$ É;˜ \Ògñó§w!KÈÒ]<|Ý ³:Ôõ¤ÀY^b¤?êü&ý3´õÓW59dÒÓÎ¥’ƒ€Qqç’¸†í`ǯŠ:§¯z¼åú‰«çÆžKiG9W%¥¤àŽº¸nË6Ù¹XÊ`Ò@ ¢ÑtsÜ*ž,V®×Ë®×:iÏkíøÀ9ŒƒãÝÙ¥/ÇÙÙúKæfWu“¬.$åŽ2¾±PkOâ²Jy¼µªŒÇ—ŸsCD‰T3ÜAÐziÎÎÍ3e1è8v¬K¯Ê@D z[l+Š1Ù|=Þ.érÂûE;ÌÌ P(œ€” où”‰¼{Òa,æ°ÍéáÄŸ´Çg|óòQ¯ò41¦[2r”TOìhÉd¬‡³Óþ‚×TH‡¹·&–0¥*dŠ5LÓìúâÉiµž-”Xvšw“¤^”‡»xv´E¡Ê½UU3a\Ž£ZÇ-&}Bå˜ÌÄê*r·5)|Å­³A=1)„K"Gî5=)ZÞf=‰x0l‹ÃS싼S% ÷à޹õ×ZÉÑUE{iá3´˜?zÕ&ZÃ09ê òÞBžö3—uâl^¨ŸCš‡Uáù3D}¸ñî!ŸŒ±ˆVh¥ô-Ê„+é|ïÉ>ƒœ Â{z¬¾ö«¡ûDi¢ÑûÓjŸðÁŽ:›½®çuÍuÎÅ:ïõ» ~ y&=P³¬it®vâéÀ0瀎ìo\Æ ™‰4›r+Å(íVójT¶Óú½0›ái{÷¼t-±n¤ûM½}#´A5ï‰øó}A^°Ù^öLo¹x])óÍÝ{S·£³Ï÷! „>·ík¦$#³ã .2’œ}Š…,â"/ÝY;ú„kLíÄØFýí&fñ ï „i?—ß«˜ÓìG7BøHœá&ߤ–{á¹0o6X³O|Rß‘.„_Ò3|5¯–­Ý“'œvÒ:kP^3ÄXL÷„d ‹Ä{Ê žgŒ£Û™qj2Hˆ,Që¤iÑ.²éã1ÃÞÔ¦83° ½±aö˜6ksA©g wnnž>ĨÕô´´ë…%=h/Ⱥg(KÏ÷âž¼iîPUá22päó½rÝ-ÈU&^\ tKxØ UÌ͆£Ýއ¹§9ý¤`ÝÉÒnåIŸØ@ˆ8P#Úw—È&ù…4Œ7]´$=*æŸóúá“~BHäñÖû­‘?ƒó¤ EÁç°WëÄôI>}†;°m7 +W˺'¦ÇÝvNGT(/¯ë(¸‚1 Äߤæƒ&+¦…²{HýËé9¬A±Ò6¤$3š$U‘çô3é½e>sàó^²P#4v< UK®wþÒð°…ÈšrÂOO”Þõ¦fœ \Ã%T °4×ÃT4™§á5H(§Ç®zÂþì¢O}—®J^uÄ›%*§hÙMõí÷ðºòÆ5÷ÝÆÝ…×¬TS޼™À»¸É7cVÚ&/Cdð*s~f{ö^C€ Ú}¥Ò팒 }M]ê‹ïlÐæ}Óÿ½›sßx /« =æ4Ê+ùñÃ2ë!_s…•ÙëL‹‚Ž|B9¯œ2´ÖŸ°nYït-ˆ•¿ÔÜsÒòò2,lV eÙŒ“MÈ4€ã-s–jyŠXAú Cxoí.«YSo-8цhêc. Vï—Ä$Ô|±(˜µ^(“X™óûi½‘ŽC„sCjK}‘V½ÓÕÝz4`$UÜ¡•¦mš‡P8ˆê\™qס‰*B¨füÄkÛ¨`9:Ž Ùü6ë­éÏ»Zr§¿Éöjq8¨e¡©ªÄ{]a6Ó£|¹A?Àßû:‰´}•¹n/È™õ!Æ[ 3:‚)kF10·±¦Ô‘¬U!Ø=ž~´¸„Õã9[§\õ¹<ì@Htça‰œù ¹Hûªç+U½^š¤z¢cik–%GW¸P«á†´¡l(á|¦s_½ic¾lÌE¼Äó¶xxÝN›EÏr¦D—”ý=Û…XE(…^pUÑÌ­ÃInOb›xK7·O‹ïð¥Ñæß{9oÎÅUgïñCà ÖæPΛÖs/ï'òZp]uÎÊ£A×\SÎMl= !O°ýÁÞú 3Þc‘q8c {*<3JÐ3ûŒáJÛ†¦‹êÉÍ»šµ†äu­Áô´<Ò«£¸ÖV‰‡=Spg=Ä-¤žõôº+cg’JðíBó;(rÇl`]z‹‚µ»¥=‘–×}Güƺ+bëÄ{ Åãj²ßÅÁ’ŸÉòÂ[)ž­^Ë:þ|Ô.­^ S–›ßˆˆ-8%úvâÕd¼yõKMÊ¡+ =¸êô&VtÑâº=³_ÃÓ™2UJ¼yý)ýÞõÊiµDº .U®ÝŠ…Ã,#ÙJ™œó;ãsFÐma@Uð=šÑÕ(zµP†Èuš¦P©½ØÏ/]©/4qž¿“9©rFa·óEá5=¯´mm÷ŽpW¯* à1:!Û!E©«Þ{ ±€¶DÚµ]#ðµnv{!P„û›ÚfŒ¨Ééx"‰ÂLˆr;°r„D^`xfÄúу ¶2Þ‡t —Ï€‘`¬¡ÕÂh‡˜Wf‹’HAžÑ%'Wºþ¼ãƒ -·n¾mÂ÷ŒêBWŽa:qÓ|ë?EÙ<ü‚ áyà -ÌtdBh¾Q–âHàÔ²4F+"LËj2˜ËxÚT#³«jÎÅß1Ã’·Qø³M|(T£lÅGÅ^¯Fê¢-°Å”8y³*wVÖW8VÓ‹ú(¬Ìë]úÙ±ô)Öֹ㫣ç 8×µÅP6´ò›°EÚŽù‘)ÑÕSÏ2™YùVø¥Î Îé%Š òÃ5’Z· 7¶î²ÒԹ܇úÌžQÁÓ:tDt¬Ë8+ª‹ì)âäZë9|}s‚6Ô%W±/ë§$C_û?SD®É[¸×¥Û/»@=Í^‘”{‚}FÄ›±ŒÇœ\//k,9eù‰­èlùú+K(è„õÖ®¦Ée,2€V$g~÷8k¹¹p,}$ÚVK_pºž«&*K#¹D_EÚSH³zB”ÒèÎÍ£ÙíºŠJª¶ýðm$ÂËô N*#TI©ìñËsà—2e¨÷,ÁÑ¢J+(S€´^')žˆ™bx åÕ¸—¦šç yžº!ØÀáµqK§=xVLAEŽ\½eŠ5kDØœ"¾²íïõLgúÛ>b#î†d‘VòŸ#ØCV•.O t{á/ê…÷ÙsbÐô8×Ú_ϧü3,äƒºÚ "³ÄÌ1:-‹4ð~[ó˜T½od "»KA©dîP´¡È˜UÝ2^‘ªEßLLžåÍæ!M»¨÷Â%OE‡Ê:èzÆú=›®·§åÜ™}‘{¥ˆ^×w¶ïÕžÛÖL{ «s”ÙœÎ¢–uU¾hr•w”ŽÊ$¶VZ쀻Æ|ß’ðÏü¢uÆÐïœCÜ=¡ß *ˆ‰¥ßv3^Ûr“‚¯㺌%;·Ú¬ – Ãszu…,Ë\GTœÄÈuš=T–å‚áåèVT=OÞÈ2£wv1Ý()6c®¶¼=MKÊ×q¼]޽,"óržêÌkÏŽxaÍEÂO2Tø¸#Õ³°G3†õ=š¤ã®Q—]ÓÇucÆdIg¹ÑEÎJà†:WOi¥qTSgŒh¬#¾Ç=¸]~0‹]Ï+ßém³B« ®¾ý9hZÙâõvæ·T½€8iÕiØBËv~‡Ë“ó) ü •¥Èï¢ygìÁÄŒƒÒGÁ,”§öª }ø=}T™Ò#œçoÄ·¥G¶áº¢«ø†ï.Ðh08ΜH虽ޛ ûˆ•Ȥˆ°_3{ÆŒFÍ…øÖ’/c¾»¥’CO7gì+ƒO·ŽKÂ)£JÒ`‹¢ibÅ“!Ü$¦x;LO ²7Ë Õ£—fħI,ÆöP,ùõ8 ±`“$19iï-ÖðÜ5J2®5H8aŒÀc¥xƒèåôªÍ3…•=(é…ÌyãîÏsTkvŒ<}.²ÒtÎG)z‘„l“϶AZRÈy?^û”½ï[äÞŠ&Ï‚´À£•öõ*!PÒL©mN["ubäÁðÂKæk£vdy.nâ¹Ú¾­—Íô¤uŸ¼A½¤쇪—%8GF.~4 lý ÜNß{4Ï-ïE4G`¯‹oR*L–¦Jò{øB%˜Ã8›žx,K BYÏN?:ŠEÈÀ 4—Ó2¢· Å/8¸§ïK ØlB$‚x üõ¤€ST f©‡jðž&aDqM‹$J9‰?‚e|MDÕPýVòêŒSGð93œ´Ö¾j‹OLÈ÷s}»tÁö&Ìg8±ë¼p²Ÿ±ƒZ¹ƒ ¢Sà§0ø3h¾±w—ýª7…ìÙÞà¾#(ã}nâµÒî‰w+QPâlù´è2º¸uõe,·èK²†ÃÖ 6Öm©[L¿Ö|,M貇øZ`½x_ÛNh&°:FÇS^×—â£äzæ²LéðÞã̓zsšÕb;ÒTè2³ëÏcfwW5“¹iu²XI°:•:='¼o&TF}¾xyÃXYÕw%ñ:ÐÝ[ ,&Ànê±ïxÅè„ÒHÖpÄÔÞð#z.`5{6ç…né¾t`ñì6×gIcôå.ÚŽ/•ËjAØÔ ‘7,zÀ”ü¥lý½m÷ø”ÆûŒœ»]å7—oR n@ì4lÏùðNqŸ9‚ w™µG¯ŸèÎ<–ìî”¶{Õ.ב!B—þÊó¶†{ÍiÞ¤„“n…»Ó&¤ŸeF/ §nT?¥+Õöy‰>Iø+˜E·Ž¤t ÕßdxE"ÆÊݼ¼+E_$_³Õ•ã‡)ùop”Y›ŒÒ¯ÙÀáàaòÃÚÕ,èzI:Sš¾@G…¯ÚZ^yac?·zñjºo8……%‹Ž% ŽúÒ åˆ_€& üP±f:¨Ö#Õ¨±&Dë TŒÕ³zUP-ž-x(g òæ[þ)}Çû²WÚú¨Ü6UËP2ðÌ~ƺ\0g^kI ³yB£•NŒÚy̰çBl‚î=KÅÑ/ó½ó´¥ô哌Q_G-T÷¸jØ:ŽwÊÀœ¹T“e\îM:ZC²ûvqOü ò2¨[8ÎÛtx l-5•·*JÜmç¸L¼¥j¤bŠ ‘ sø çmÔ½G÷·O.¶òô–‘›g5lI* g«žâ½t¼lç÷ ZB„ÁŸÉ-ÌãÕ‘\Þ}z¥öˆÎñ¥z¿Z^ïø9›´gÓ4h•§³u¯®¤ØÏaS¦uϵQu}‘uô{\•Ï:ÔEcÌÀ|±ÂHÎÎÝï 3ì­Û¶ú¡ -¾Ôð—->‘Á>³’a àãèýBÁ&f‰ü­)úayî8]ÐŽ<Ë{DpÙséï1 jD…=>?*Ì=¶­z2ݱÈsõØù.äÛ›âÎ-;fD«SΚ¶«­‡†m‹9¤âæ ýÙJµ²:º掳sòYU¹ÖšÙ*ZÕŠùÝ oŠ2´Õ)`M«B†ôà^{¾#CÛì·6G}ÇU-’hk¦ ä¢À”ÚƒCÎþK t77ô^A?:w-·â™é•×îW¤i˜~*Äß¹C?éQ„‡ˆ"Ï<|݈8'½ !U´¤P°l)…nÐ0_6ê¼ Ëa³{"¯ë^ ñÞŸy[ŒÞ+ ïéŠB.U¦GwÜ¥;«Éšz S\ýpa\±Ø_él‹WAè@>¢y4‡&‹µ(†WB¹ªGãštêôÒû2»²_Ú ÊǼ[(O^ž#¥˜™Àò^ ¬§w6Š“8†áUrå«1]CŸìóÇ<Ì)1ävÞDüÖ’ áa é²Ç^Á>(MôâÌSñuÚÁ6WÆâzÍ[dÍ—Û®.¿[ŒÖbŒFÔ™Ü<0Yya’—ð˜+ꥆzåñ¼o‰}GS³°%(£dÑJ‘º7ÇÙÚS·žY :¿Œ‹ìj~oŒâèÂæ8¡îPv*ZG¦ê{nðÁµ¾Ê> ×öÔjjéo-HÓà±Oa+ÎÞ®1>’s'œ=ÒÁ½1»várty2 ’ÓAþ,tŹMWoíud“¸e>Íôs‡wt[â¬Ý¯8++ËEŠ9/ÚHD=Ú’Øc豜¬F£©)SbxÖááqîƒoó€Ò©u›,33"^ÌœÇö0sšU¿ÅpO§¬³¶Îc ü%’|Z¥¯ -fžœ‰ÓE[N@Šw¼º¨K‘¾þ‰†Ô8jôœb‡6‹W¦¼‘I §Am «7ƒçd²_$-@™cÈ9ø½kÓ%í²ZÆi–¯gE­*)\¼ï:슘±G“¯%º±ÂxHd2üñòKÈŠ5;lG벊›`˜ìñ= -‰|ÝÍ.I xÎ ‰G˜]~0qŽî-¾` 2‘ˆšb¹!~}e¥ã¹5¢Ü‰—*ÜÒ@87z«‡^—7µ]YäÈÌ;ò¢±ý¼•Ç”´Ÿ3цŽÜQ&p ì;/bYdNÔ}–É&;Ôšö}£5xŸRyü¶ áÏ1o·aFkâ­ÃYeL'Ƙœmš 婎æ«>ÔJpŒDJe£‹b©nëtÙÅXäÕDCø\tG.ƒí57DÍ¢†u†ZœJ¢¨^£ÞëæRÆD¿zïÅ¥æ%jòU?BÚ;áhµ>ô§N*,âцˆc\w½±^?xAkÊd! ™É¾EÓø’ƈ/â%ÞªèÝ›Á'‚½o­•°(S^"`‘›§‡%y‚CH3É"$éЦIÝèk`ˆ*‘|²aDP[݆ëá]ÕE·è<ãŸq ™!6<›=ƒBë#¸0¨‹ÆÆ !“&ó×À³ŸbÁïƒ~[cûø v˜:Îó{1ÀOtVá™”?0Ø{þ¬™¹ì‰Iáµ%º†¾ç’\®ün3YB2“îIHÚh) ‹òì2Ve¿Çíɼ;:2!šáê¬Ú$d%»!@s¥›]##š‹¯Â@ÕkÑ^{ÌÑm>Î:d|¤íþn”’Õ¹¡Ù‚Ž^2zu‘-á=c»,¥6Ûd¯þƒäžM–¾F¾­5ª“*Ë’4?á§ó¸Ûvé••‡Ã‘z©×)eÍŠY =ö[|%/¼;äÀÈŸB[ËHo½´š÷µ#ì_r9³.!Bê K˜œ ,•p|N´<:â¯=„<èS.ŸrIÍwï¦%‡ˆÙ1Wò^øØ+#¡í“XöØÈж¹«¤k5áa{7A€v¯{Vµà=xJ=;7,4ŽÂ«ùÚÇé °ÛØJмID  `Kɦš":Ó‚æRüX‚…".9Y06 Uç.Qï’e]ÌÎÒµµžÞ"OùRÏÄôUºÔÌt/¤¥/ŠœãÒøÆ­>Eáá!jG¬á8gxÌE„<ó”ãaIPð $óR)çÔ„G5 £ôÓ›Rs7)nÇá|pâØWÛô¼B5L,÷ÔE¢ô+ä´× Ù’ûóê2—Ójb:ï­7¦ÓzŸmФãí‹%Dð…øÌgÀ¸L|½µQ6+‚¥ ¦ò ’9ØE KÖRúœqÄ@jšá•csgÔp•/…`Aµ IR¼­ApVw½•µÃE»yËùpÚcýú^²rçNav‰øòˆÒ!s•»î•)0[82NH=BcÇÍL«DÙv‚*iäÔ}°¹-I6 7× ÇRœÂHøÔAë5Iõ@fr ? “)Q½¨7ÈvoAßkJšTÝNáGK¬/¤¹•„¼n˜6 ïõDU€?@*¡zÕ¢ó¼ÛSK¢²_¸oÖ -&$6-¬ýk¹Ú ì²`«QmŒ£äu{¬ íb2r!©ñ ö§dø3êÒø#{Ì­x4¡}ëЇL¤’È*Í¥˜™<:ÝÀqZI9B©éÝ ×g «e‚ avùBÛÀ“Ìé1¼Ãë¸ö–¬Y…`æXÞÈ› ªHÕy8ærKGš:‘÷†cŸ;Â9•öÈùúÞr³ƒVS7•s^<~¢ ïâ\YÜ6.—;y7¦8eQ&oq(G¼MÇ–€dàÎã—µ…kŸÀ¼ïÆô>C¯,Æ„¹Ûuf»-Që9póKžì!…‡Fù,=-…´ó%%’áöµŒŒÕJ6ŒË!„°À\«DؼÇMØñ’oo(«+^îS`.#tOšŒgï«¶ñX^Tš”Qõò¨k__ôwo8#©rúÝÉ-4T{ÆÑBQ’Þèx‹€_f–Éaå£WÛ‘Öã|9¯}ƒ1EEÓ m¸„8Õïà‘xEì°ƒ?E‡WÉËi4~t—+MW)R)ÉMÖt†5†8t‹Ñ”SŒEÀò7v¥_ÎQV4\ q˜ôýœ•"Fé|N6gÕ Ý¹þÍBi¯ŽG$ÏÂ[#¾g%ùŒ¿í¦YOÙ‚Ýz¹|Þ B31¬hÀõ. „¬~Ž+º›pzál1×yk\ăý'éuÈE&G¥^¬´Ót¶§EÙÃ[oÙ©#"Üà’æeà»H2žw9׿-1ahvCô*|t¼:‰îsŘm2ÆêÁ¸O90É^soÑEuVCªºÔyœq½B7Oy„èbÓÆ-,%Ï=4`S'ÁY@k—AȧÑ3YTÞZ'Çq³Iùžw­ ¿©ÖWMP{õÐú¶ƒNyb×8ì÷>¦’ÊGeñÝd žBœ»»ã”ƒABŒyPDbù§pô;ã“K¤Wö(¯‰‰-ãE¥`u£ “Ñ,€”:q8†6ÉÙJ7y\Ý{å4¢ËnÕÄ,°ð=~Ä/wN‰Yb©Þ25FûxL3€)[¨‰Ól~Ø)ËýVŽE¼fæ…É”µLzUûë6¾£÷8ÞÀ<yan*û $ø Ž:ÁI“wܧz‘ÌÈÇ{<ª©%lzGáT.MßÖ>µK±^®yñ¼ÔÕÆ^Æœ4lë C×Ñ®b¯hµ¹¾¹q6Óbœó¶».ÅGž¢uVÆîõR¸ê˜ƒóžî¤ËïUÞù ¡OÛ°¶Ó³k"ƒ×x5EP(Kš—P&FßÒñOéÜ\Nw Eåç{k«ô$枉a¹íð˜ÜùœM‚’ ©.Ñ[Gj޳pÞ'âu‰GµÇ·%Z {¦h Á®ÏåYî†+À Œ[ ¨›§Qëcó:åwv&ÐÀáZ`VPçeÒé=+ÅŠ¸]aÓ–-U‡íX÷ƒšuç‡< ,6ÜŽ+°¦ÜÊË¡íqkºPY½+…æJÂãj”rvzl©þä™E÷ØÅt·ï‘” Ká>ß%«z2†ÑO#w±³¦1F-ŒºXR °H¦îùOß¹T ƒ(òsµ0ÃæP¦r¸¤ƒc^Ç;µ–ßáØ>Ãq¸+;aÜ0„<ÂsÒÝwË¢ZJÞÜ«ÁÐq´&~ƒéÐNÆG§¸o2W¥ß!ÂðZ'„J¶ ½å×0ý*iôê¤jƒ‹ÅåXÞ˜<î’G‰™òÔÞ° ˜ +¤ß›GÇSÈØ\–e Jj•¦®/Ú; žB+áàÉÄðMHmañviÃÀU« Ey“rgbe‰æË»Üy/”æ t|¤pËŸì1¢{ñ"æ9b"ŠÖ–%¹g®o >ÃRz™˜Öšs€KPíc¢î3z]ÍånoÇÝd¸—æ e²=·pkh¾("}]d§:ö´à jW7¯ø ÌÏÊ 5®JF-TÖ©Ñ,“F™lC¯ÇyyÖ˜Y=Žw-"^bÝpê7F²ãó@º¤zNšžÙeN>M©(êê›sæZ=îxl˜!—hsƧ ‚‘›pg1’ˆ¬ÂwíS@Ù–\òÓ@p$¼ÍÈZêÁêª:²¶×y¬æ RWØñÂÃ6Oô.ßäÕº¾§ˆêÒŠ–L miÀº/ÛQ-â4xòÖã¸÷m%Ä.°"`]«J=€”g‰ pe9>þÎ_ñË=D”µ7{ˆè^ƒ‹6‘HÍ€LÛä ÌQ““=I7^öóæÍ®ø¬ X…ŸnøÓáã´éÝÒeU©´A nð¢ÿ”Ãgtö¾ÃS»n÷Ð dewGGíÎâçJUj©¢Ëî¡Ç½z7oÒ8Lâz.TÕFW[„Ø‹@ÆáEcïìÛ4–Éf|V—¡PÔ½/ß‘<4­zƒ5¸*ï1•O-&²ô#D)ŽW@ÏE“ÒyÚeÔœj_½÷ˆCÔº·_¡¿yò|sùNƒŽSP%-S‘Ú1v“Æ– =™‡råaÙ4ù˜w3âÑë;4Õ| U›ýÚ‚âew«÷–¨Ê°ú“7\‰¹ žÎÈìføwѸ®!Èž¾‹#ŸÝx­¹Y–¹ºË©dûSD©ÑÐèiH|ü’Ø#;«¹NOÒi˜óƱ…Â@‰~‹è3Doö€…aßEEpðyãxWɼ),yž.oMð¥8+¼5·cŠ :BÄ Ë–õ vb!cdB!Ê’uqER(ä­Ý3—"·7.¦©“¦/}Gljæ…XÊ“zÏD=Óa1sÞàE IÌ.âR·ß2j\Y÷ëe/V:_ÖÜÀð²uöéÍw–Rñ(ªø´ª¦ƒDeYM·x†Î5“xgxÀÃÞ3 ²xÅsIŠ˜vFe! Tï¦0üø†·ÖC}$ºüd}¼[D¦= ^FÁaì]–™kþi˜ Clã˜;YôÑÏ8 qÃòPÇÙ§}Uôˆ ½ &cyN׎-I`‰¦çSFø½kæì·‘Z÷ž43k¯Î5ÝÙ¬»¿âé@º=83цfiô8Îá$Ö°¬ILGwLhïÎëpÈ¢6 Ñ×T‹rûúUÂ\=è¢%w»yž8/{ÒÃ⽤»‡» Ãè>Ê|4-þÔ^—dT‹©TŒÎœ˜‡ÊùLd"Õ]^õ*8Y½€*›ã™Ô£ÄÇíu¡YÀã<iK£äøÒ£’D½^:ä*¢Å­¿…»vGó.ME¶½‘× ùòá`úðLïÓª|YÖ9¢Âáæ÷Ñ£×›y‘é6WÓ{ÐR±•~ÞÑO“ÿ@•%/3%Š{ƒôæ_N \5•©z‡Œ—Àûö#ú Ö€FsÆDNóÜU£Y|ù‘B×þWË·©ý ¶‘¢ž=Ê^ˆC¡k%~‹µë™å=¢ëõ\§+£AXÓ…LúøaCžù.í8%§Å6tApè®R政ó|»žÖÝÉ»þ–bÓ^ÞöÁƒ°U8_ÏRA$mH O6pÜGƒê¹ž†!ØB$ö-¼–2 µ¨ÉYQ½1WôUÒz —ç!Õ½ˆ/_,È(’m.žZ^Éó휬ID¼í`|ý_x²Bëy‘D]ÄmŒÙkI(ȆÔc^+*¨šÏUþ’’èùÆi$G¬Gh?åQ9‚©‡T˜Ûæ¨ó’^¼ü”Flv“ zÐÇ é%Ñ*.Ž4 °Ý_èRÚ3÷BÒŠ4š&O¸”…ü ¸³ÜLÊPçé ¼ v6 $F4`‹J½—ÓŽzÛUpÑïi™KX¨?\q7/ãÞ*ë}¦x³Y‹2KÇs•‡ö¨g‹=D¢ÍS-x1ØEU‘MÛ±7D}#Sƒ¤žÝY>nKXo¶Ñ yqWóPö|+تçÅ>õzölÚ1²FC¦`AÜÞóÌdy¿—5°†ˆEs±âc:.9áZ¬⤵ðæ±(Š„(ȾzUN¯˜ûåmÉZ ÆÄ/1EÀ±Ù©`ydG, ¡HÄrø6iúù¹7ô§˜Þ÷žúY7¦ÄíUÆËh“JWm†ii삆ó Vœðç/Dgd0œ¢¿¼Zžì8S ìÜî«ÓÀˆÖ^ª×”|o(Eo%™ÀÄîÍ®Ì=F̰\Põ|†bªK§3Ï›OÌ^àÁK€Ù48šg‘¤ÓÒc¾™ÅɈ†Q¶æƒ1sØÂóÌm«E8èz¯`|žjÅZZºÔ1_tËÃØ¨q{37 áˆ3y>v[™í¸QŠ’£#.¨«ä¼ùsgXixshIDk³Û-Yˆ¨ãbt= ‹Ým½#l¬×®vób{kµÎÁi=ÉéÎY-²¨V%wÂ8Nô|ÀÈØËu “žÁ3mïo9}Æn±¼0¼îÜ{,Ó´{ð(ªwZKŸÅ&ª»xê¾ÈF0\½—’ú¤ßz›=ATuêm/×í<žÙy¨V|ÚuÙš»lä X¼r‡PïbÇk |2·3›Hq'çΔ¼jU&d/’Ê´â'ž1æ„àzRe³&% •.¯ñx•®nÄô»Í‰jlC¤'\ð†y“•E9®¨›ÊpÄS´jÔ°ÐoùíÐòt²;Ù(ßλbry ¯¨xIÁ1ý¼G‡ ü|­l’²pÇòaá’ QÓy݉¦Ýª…Æ#êuŽŒy ~À?ýi®4]^2¾ÍE ªeå ][p¯‚SXI•¶û”|px‹:;D@•yÌ4<àA¬€5£ïÄø2±Ê0ÐûµpPprÝdF¹%šg@ _kº=@,@„yý”8 ØÑ‹&)½òQ‡î;×—ýÞ"èÅcD\{mÖHu2±¢V§‰Ø§ÁTU9Ìçñ´N_ƒê¸ 2¦ p¿ŽºyT.Þ„NÖ~r8…¦2mžÈRÒùæ*Á«sæM”¸½ôÙf_½÷^¹ä{gì 6 #`ùÎ9XÅÍ]5N÷Þl‰x t‚‰Ž,Ý‹Á´ã…ƒâá’ƒ€ìS¢B7o dÞ—þ|APX‚6[¯~Þô›lš‹P xxbÕˆ¸¯å…5¯½'2/ ^äòɽOIéûlyí(ÍþvŽÜ·—¬{G(É ,ÀؼZW[6VÛXŒ8»jij_¸¼¢yÏh˜ïAU¹;…(=iVfqC Ͱ|‹!bûpåÍîsJ|D œ7Ô/m\ñ B†eÌ%ØYO<½|BÊ <3S~±ü¦&“Iý€Ñ&e<Òí­K!Ž+µ£hô®LÊÓW÷èONœ€ún[žXFWZ›Z§M¼Î²÷ü¶ømdp:Ù3ì•0Öƒˆv×ÙĬוoQñ]=‰ ¤k ¸w >ÑSï%ŽT¼r_ÇË~7'ýâ=:ä Äq×§¡"ˆ›wJÏý0ŸEÙb¢(,†ÏtwŸJ@ð#¹³Ã.¤§anúÀm´²I H ör½·åˆJ°%²³]OÊ­S©ôêDøÍ€(ìtš#¼áŠÇ3E·¹í‘)«A pN””I· ,0&kµ¨w$¤ÓúØhïÑ¡{Ö¤n¤žÜÀ`¯˜HÇ]ªäAÔ8è/(ŠjÀ8f;¢™wòdSÓ‹  @»Þà°å áì‹}åïçþ‰Ä¥Æ'P|4„j7¤ÞÉí\(–z惧QkŸ²òÏx>þG}è‰éªl' ÈqÈA_ö8kF ⎘ú ¢!á2±Xå;y;d‡GaÃv9o#ᤎnjݠ¨E4••ÖE‡X%ŒšòIsµ …=«*aªÐwØnK=Gý*dôÓËu‹„éÛˆµG›"²ùÌ*y£Þëo6yÄŠ˜´"üdšPÌ¢h1¶òE΋Š[>Kz+¼Ì4ð襗£øð¶j:R˜ã݃t´üW[Ìr˜¹;B‹óH(ëÂ;~¬Â`ÏTÅ%‚¿Äð½G÷»YNÝ·§¢à›j´Ï)¡[÷ø½xØ×È+OŽ+Úrd·j©õQ=×Îs‘¦6>ñÆ}Ë8éK£<¡‹rã/„s¥‰1 GA Ç2o2; N•s5³žÆÀ ¦<4°yÀoSs$—%BóÀüƒð*Ïž³kt’U xÙ®ã"y£¡Nsö-ƒ¿"\x} Š¶Û‡¥ž½”yÒ7÷†÷‚FD* <ã§ú”Žpú#Å!€1|ÆcÏýø‘=ÔRmd›'rĆ]íºðP²ÜsÛNhYyÞézŠù@ŸÔ¡©®)ÌÊÏÙ0¤Û»E…0,÷ŽO$1,!à:(^.»W„¾:ŠOyágŒsÊ*£”Zæ «Þ'µº£ÚSŸÀŽn5ˆ¤2ÌøF5?ÖÎ\Z¤môug›³ÄâvÛ~:Mg× nÄÃDhš vSàÞ“KöCSOŽ¥¢;™Ù9<œ=EÚ7Ž0™œÐðõ"ç©£° š§P¬àyæâCo¯–±RèlÒªð—0ðX÷Ìá‘¶<Ûxi~€Ùuý’dsádêÑ•× ªì ëµá²æ‹4V|Ʊ™¼íü@£°²@Sq–»4P냊3uÝ‘‹²}Ø×c¡·¯I´ѵ‰5îH,ämM:6¬\ÄÏ@¿µÈ‡´ýxù´@@Dzu±‘ãµÇhdô4| Œ>½\¯#D²¸ìƒp^D+¹* pÉáH¼¯ð=v+Á€}Œ]•©FÆ•ÐâYÈà‹þÞô@±šWæ£c–£KRK Åmè)ñ¨¸x¹.ÃS¤IŸêúX*°uQÕ祼ÓȈccÙ•™\j¢á°še9ñ~žj°XÆ™×Ãç„h¨ªb¦†Rè“züpt®±§X¨.÷ÉðsŠ·XÊ$4‹Ï•K®PÄÌ6£Ñ¬—TF$q•,ÂÝã7S|âÌ ' .Ëfe’YÎ68GåùJTïAU`‰Ù¹áæ?±½KЊ´^zmŒ–h4¿$æxòXÆu1j[|ÛVnf‚Æ Þ>|”¨ßûŒöŠF‡a˜º¸o ò*'dä¶#ê4Š^©½j´s@T” Y=Ñr-LÃá{üÜ=ÛÊ‚"¸–Œö¥†zî¡'’Ò¨Š" ‚Án`·O².ž?L´T§‡uÖx8„ÉyÊ‹’…Á‹ôSx[ÜžÁŠ;^É›\,pÐ~1XðZŸT"TlDz«Ú˜¸$ùð°{ö¨°‘ƒ³Ø'M„E‹ S4´€ø8²,KŽ|îP°V‡qpWJJlb%äÃ×õʳ9OýÆâ £ñ­ œ ÐeŠ×ý<ôöÉ;Ás¼))}Q¥ˆ‚¤ø‚Bɼîx„CúäiÞ§ÈX?}LÕ·'b®–Pú!:‡gGÇæaâc¾¬×=áúL¨”d3Þ3Æ3™çI6ðlÔäÙá›»L‘KYг<T—Íëwehè›Ãðä1ÔTŠ—:4T¾‹ê’j¸†÷2‚*^½îáÕÍ*™ª¬€7J `Bý– p̸ú^ã«Çf“¼wçô »è°˜÷iÄ*éMnÜk›ÚR–j“wÙ5>/j+ùˆûaw]ìB#¾Õ0¶ k¨Ãq‰ƒ6µE \_Ž&%Å»Y ‚áʃ Pd×о•²e*¸'sœ™Átœ6R —nHIdxÇØk%ˆ…?e¦@F4XqŒ-¸pg‡ƒé)¸¥²ÃõfAy>eö¾ã>’[HÓâ,ƒ~ᯑ—9V´ŠeÕ9Ï… ‚ÕÀ%ŽÇ®m^pu¥V!•œÊ®tÊhÇóQÝá1†"ââ÷ÌØšôrÀ#r`´‹¼²AÏ#íÉÁ¶Ñ¿PïNyÜC¯ð‰Úc’·,ÞÈh –`uT°= ‚Õ.¯=RŒ8€üZnûF¸|/Ä÷vAÁËNº"ˆsÂ@|Ô  Ûž6’¥âîÏS‘˜Jˆ½ æ‡Ý/»ø>)™°rœ×ëÇÞìJ§ßRÓÏ  ÈS3ñV˜¥º|w´³§B©ìÎéÙ;²[®a¦}VéËŠwùÁòõú£dO¼ÚL®é–À£µ‰Yá}!B" àíA#’:I-Z„ãnNYÍ,'{ö¢'c}zê fUl4Ú^>¶Èz…N5áØymAú ѹ5¼–âÍ—ZóºA÷dÒ/‰ë]RꉖTç°`‹!¬>€¥BMíhø˜ 2çÆÉTÊá‰Ï˜GYbUw¬í«8wÜìÑêÇèü<‘ï¾-2DIìkÔ±›x!¯Y˜ö²“: H¸h€Zo '9Íî¡“º¸ûïœæWŒNOêÁ#"ªÊ ‡2©åñŽÈX/–ôŒÐä[lþék¡ñž š¼€£Ì¨À7µG«.¯CÎG!êÖj}–ä5iÑ0Vì›Vïȹûv£°ÉBí(NÜØŸs=´ªÐ¢=hÏNe*‰–Èl>ųzÒ¡Z&‡Áx÷VB(›÷n`firúkæcÛè©UÒ{’P  /=}DW8óhˆgb’oÎRÙ"Õ“ùòÑ¥ÏÔø¢¢Dx › `4lBá{½”-v2Fañbßz sœ›öº”Së¤çP/!@zÈx_ânŽ5›Ö3nA(s[ã}|¾ÆÏÏ­Ù™RžíQÕŠEdíôÉâ±Ñ¦CóèÏ3¸°mP[€ˆråù½µžbð+~4'[ôò9‰^›2>L2w|í4:ÊÏÅLž¸A.§s1d%ʃ[´ð³=ˆe–t•¤\ˆE¸ïìù•§à½gKÈéW¿çF(yÆ#=^,ò,òÊ)ʦy„µû"sîø§àüs@Ðr…á0’ÄW/¼Êð‰½zÃÖinž©Ÿ¾Öç…&X,œTÙÔœä›qsðˆ™õ&Ð*oÓc'.u}Ux1Ö–x¾¹,þ2uFi#¬ÇëUÖD¾I`š·7iZÞ‡ °(š»ŠÈ†:y!¦ˆ2ݦhï6_Œ H(bÔ¦¢Vݤ3‹€\L@½F‡Á$f©@a_Tõ‹ }dõV䢳à–j†‚epWFV–<1w˜º#Øq¿×·&±WÌø°ÖƒÄíÖÑmåªÅ̵l½ÀC‘:XçxÈöªÖÚÕøPAkGîØõ^Z–úÎI»l!¢Õ­¡qü^áJ® M%kùˆg¼éç'øðNlmÊÆµß U}J.èSr è yìI‚ÎôÞl—€×’ðH xÖ Fzyu”´h <ÞF‰R‘û@ÒèË>| 3¹Òð u%œš9OmˆGžìâ‘ó•—²y¾–‰÷PÉÒˆšœîžÐ’¤m*øhôîãà#´PàGêïHä…Ž'zS(âFAyÁˆ×`Œte¾ fÌïÜ6Ók×3C4 ö†‡ñÄDJwsx=RÓý–á²—Ôê®®yÚn"]@•sL6ÝqÞ;‡;Ù³Ä|kåq}ép¨sò Dw•m5ôU,Ü J)†ÖŒM‘A‹Ö3|.ü|_8r½­ØA¢,Þ|’#‹sŠ# Çk¶xÓ,ZÊîœ ]×¼MÇ45OC%Üù4 ÕŒ–YNѪ™GOà í"­R)d 1.tT«ÔñøÜÄkx‰€yq£ ¿GŠñ&±)Sa=ÛÃé+zaºe¨/°ÇUpä­õK©ú”½Oéé-Ãôõ$&S¬S–À2•œÀI»q˃¸B:Knï*éËdÍg"ˆú•ç À$*°8ÃNy˜3ö[+€£&¾†B¹i†q¹2h†~Œ­ì‹IR‚‡cëeçQW 'qp·}Ç£YýH¤ØÕ¯ŸÌ8î³-¤¬G™m,s289Ö{ýÆYËåõnd°»Ú-Œ¿¼;¶šeo"ÐVêgÙâ!¸›µq¹ÉÓ[Md«kÐ$ %{‘0"oÒÏÆˆ8ŸwcÙlgâV{áS^VcTo,,Ciì‰Øž)b/Pxá.Û9ÁÏšëÜ1µ¿d·|/Z†Ù¸3ÉVµýîçåÇw¸F{"ç;q¿dõìi2RÕËÆðOñ1}7\T»6xÍ™WÌÀÂaýtæA` ÍäFŽë/ f U|øª ²ÞÁ²Ðý“!*°¸J S{íc¨·ïáŠ*"”¢0övŸß€Vû â˜ËŠ™ûN$¶´±Ð;@gZÄç4°Óaˆ¼\VÒÃðBɲ¦¼8fÞ¨,ìFð0ËK÷"Á–§«ïñ›h{òÞ_¯$ ^¡È“z‹¬ÖaÌR@ñ^{CÏ32¾|ï*|Ì“µ¹Ùôeíf[‹Fã>NZ)3hxç³ &‰ýÚ¥¡9úaM·¢\ìv½[}ê/·WŽaq»uŠ('‚£Š º;Tçê^.€—ÔÓjÝ_ò‹§›qül&}ÆÂÓÅÄÕíqk pjª´‚ËÕwÛ…÷9fpr:F?ß›¥œÀwu‹ž¥Õïð rÙ@£y¢{)>Ƶ%îR-b~j&î%°áÔ/8§êZ^Er;³³&&¡@¢°ø1ë碟ª¶‰ñˆô»AǦXí¾YåM–ƒœwékHIEûfè½Ð)óXUFƒÞ³gá™XÕóÄÞ&Tåƒç1¦¯èœ3§U Ÿ×Kè ¡§d#nØïº¤Ì =Mh‡|Üð‡‡³rLßäC’DN¿»Ä; z™-¦ÍWи$ª†ãh×$üRè¤Çí£7˦÷ZTºÓ‰ÁfbÏtRÊúmÙ‚ -“;X ÞÕ1› ›Å4©ž¦ÔjìË íÝÊý?þÿüó¿þ§8þñoÿšü_HôŸÊø÷ÿ(ÓîZÏëpÇTŸ‰&(Ž*8ܽÙÇõâÒiò•Ãùã—âüT&À¯ç¡f.‰=l€<ìrÀVÉd¡$Te½èP%N3Q™9v_cÑçLÔýsÑÇXº*<×;¤@7n§XJòNéJw·ß>¿¤5Ê/L¾SòÃ߉©šˆŸì«á³ ä‡}èÙ`‡ª†”Xƒ¥ÊÔ=|[¾Üã37á¹ÙOlZ\¢ÖIºÝ<ù¬_ê®’/ ®À[\‰U»Sj¤÷ñ9ß´qûæ~~HM½¼·;0Hˆ/–íîÍH-½š¸ZÑ4\·)K½· _îúí­„‡ü²Å~}R.tµ‰ÍË÷E£¬·§ä4ìIB!*>uö^‰²äÁFï[ÊzUö–âç’‹tä{l¼×MH÷gö ϲùµÛ¶x¿ÄW¨IuÍOëð 'ù5br·óîÞOy终Ké-—k}#o¥ERÄåÕÃîg9(¯úá1¡Ê\}½5ý”÷Ëwôü ’þü°p×½i¯2ÚI§pWY0 ×8ìÐ÷3c,¡ÕÍÀº¿ð2ú~wªY]v¢”M~æØ,?÷a \Â4’"låê¾´~{.þ*^_²Óqð#z"_Nù)ùݱGDdŠ\zÂýSgÁÊÙÃ÷¼*0=Â3a}ΤÃÐ 5 ׆˜ßƒ0~=6±ûõqŸâßÜé¹ÙÞ'r¿wL§§2›9bK’õZµ`†oeÜÛÁ$Ù¥wæ—{KŸŸÏ@jwÀо[ß¡áŸØä°°' †m›¼@ï’+c’¶fêÍ’¾æ¤GÚ¬9|­øÕ|à{P¶§dLäHtìØ\O÷ýÑѹö¹ÉeÙ¶\ÄN¼“ €>­?ÃŵnW·pXEþlHŸ¶Å {£5R¹äÁ–¤’ülã…©CxûžNöÛ²–àÔq!îRÐUîØxcˆ)öèùd§|}%}¾“K"·WÝ îë{ˆ©q`D?o^mk],zÓêÛdû"†R+—Ê-0Ú)¶jH*wž†Úçwú§&)<‹°{Æó=±ÛYsBûé‰m…´w4þº9²ÕÀ²‹/ »X±â‰Ù^ E'i})¾§Å }ðx¦iû„Bcàlw~}ë ÞÊ­†g¦÷ÔD$/!J¼]àæ°`‰æÕhïÆÀiSúúÖ÷ùŽLÔyºD´Éã*Ý€ð"LÂýùê𠶯fȧ÷=FSÕ>×wBX±ì§ž¨ZÓB†ç|}­Ðg×}{ûXVñ2ï‘[½ñÁCê [ù­Y\Å•yBÀGV®‡œ•Ń&ïQ¹€]a£g×§Kéw"ÅàðPQ¿U÷5‘¹ jÏ&Îå§gåÀòQ˜¨mP öö„ˆÓœeÔVÐf’í£œ°J½÷ùÅŸ¯l|ÚoöjzcÞÛו·æïYårÉcE ü‰r½-™%XW°×Y%R—Ê)í­¹(jÁ@ èO*úˆyÑ:@?¯âöÝ­ \nlñj3ZA³§¹Ž\3ÿŒt𠝵õXO_Cކ1G@=´g|nÙåÈU$Ux {Ÿ~æß äÁ›“©Ó°¥F½¤˜½lÏbQEÒKøépq"Õ"“Oµš§ñ<œ%õA<1š5};ªO‡KÕj 2¾¾;èó»·«€Lâì1^h(·=Pìq.)¾K=äþíËújû¬L®ÝeÄ…ƒÞQÙ°eõÞð$’V9þ!… B…[û}Qüüò¼é ÇÃóBEt²€à—´0 _ßÿ½^€ó¢ñë›õ¾k´î+D3ˆÒ§”|üôÊÚ¢\~vÎ2FªÁ"‹k5zCزÃ/VnC<[=AyBFØ/?+àïWÊÍë!w’PûœÞôq|Hç&—B¸¤ë²Ù ï÷føšDfßFÃä+ˆ¢¥Ë&<x^O­Ô%kŒ´=>¶ï|²À‰®î…Ð ;çœsþ<ÃÐÙ¹´ö; pȦþ½6Ë—p×O5<ò½ÂêGÙ–46A¼–2 ô„×i„‰û» ÿL‡ïJ°mN[²»d€èüÈ'! ˜æÜ5ÓÔv³³ÔïM ¦œ¡ÄòÛÄè™6غ(ÇÃTz (c›ÃÝxX!oœ’ó¾êø^•ÄÑu[ÌBÀh¹õ؆¡7nj!¢_ÓÈl\ØÊ”fãF#üž%ÅnaÙ{8‘ÞfjÛ$XTwƒqòÃõ†- Ó+N>+³÷UÉ÷veÖ‹/ó•Áƒ'ÊÍå+á$Œæë¶o`ÎdßÍÎHB-¼Ÿ=.D ]÷ÞÑHÑ`õM ¼Vß‘­(h+Û¤@19ÉÔXõ¯Z¾2J‡ò¶9Þ@µ‰ Á¹ÓjZò;kÜÝpœõ4÷-`Ô{›Öí¨bÙI~( ;b&ëý髚ïNÑômÜa,q¯MR>^Ù¶VDJO¢Ü5IweóÅ·RW9ï§ ë‰Ôö úBpTÒ%X¡‘]«¾À|ï“EJmvÅòcaúTÚ÷ÚçÙ‰†e{3>ˆWw2~–Šœ,Jð°•¹ÏÕURLÈYv¨éÅϩܟ¾¨»žçBVAîë“rBWY¤ð¦%û”Û<³©±zPšŸ™*¾³7RêPЪmÝ>׺ R…N“çïîõ;ÚN*ȃžyÌÑZ´ûVÞÏšæH½å¥ÜÄV뎸y#öVxq)´/vϸŸQVPj—*|%\†O?ã>ª7}P—nT1^HÕ[TSHôãü˜HL1lc)ñßû}!×IÇ¡D¤é†ÊYìLR=íáiLs[Ô¬SoË]QËíáWUøé µ[=´|žñ罈Pì0Æ\Uëiz›@ÐË™¯ª!í,–!ƒßS›|õÓ#¼Ür€³^ÚW%èË×½öîù¥ôÊ6Pᡱæ;± _uѧGXV&Ò6¥ñ3µ·ï=| W*1à‹­:Û㣛$—OpTŽ|)ÞÓòý½ãlÉ#Ê7Ù ¢— ãKJ-’`Þ2™ţt:ÍgeŸnÑî³A¦åy(«+ûȹÞãbg‹·9†CœÊˆƒÍS#.‚S«T„¦²_µA¶ YäÜ©¨ÂÓ'Iη=oAÆýXÄ^óX¶ )%ÝúWmüé€ûø–®·ŸÀvðjɈ.„‡.ÌL€½[d_vB ƒv~½º9MU®uúS“h¹0U‰Fé©¶Ò´^HÃ3 {žhÊwïx&í«º÷é ÌÄlÏKi÷±<=´~{TçcÛƒóâ*Ká•s4­®Ôʃ¡¨$Ëòeˆ|¿ÙCö5Y£›™ [ d”<ÎJrØKVbHfˆ «ž•4oFñO‡”ï”áAòàB_{Û«¡) †÷']ìyó{ãu ™èñÞ¶S‰o5û5¥V KhúÏt‹Õ“÷Ç+å]HI¸—ªX9ŽdÏ(hÎ"ýºµÞƧ>õÓUNBqn¨ðînòÝÕ1ˆB£JÝN–÷B­ø“ÙòiE€W6ÅþÔädúŠ_RömhÿvÎÑ›h‘(¨Ï/Ùü5€S¢&˜HA8"„nïóâþ®ñÛ_“¶´wÇݱ—@ Æ5Æ81WyÄH‘ý•CoÉ\³탓„M”ÎÛÅ&ÛÊŸZ!εÌÅ5¤šqªQHƒ™ÕŽ‹©Wåͬ³ìé¯*íÓiЧ Ž=2~‡ø@˜z¸™/JºçLð­‹¿y)Wc Õço`ž‘²¾Šº,œ¨Ÿýß¹‚m#45VB©¨ô*†R¿ÅdI_o#ÞçICµÙâ³ú÷ã—•x‚ñúMÉ¡éeÝ‹½=%K¶ð>¯J?\¦7Öv(Fá›Õozmß=GÐýª˜>]j.µ5)ÁrõÏ™µWï=‰Òx*3É[;­ˆv³_ŒŒÇk¨S%Œ£ßXÏ"œúÉò@>ÉÙ½××6¡*ݬ˜ Ù,ž¯ºJ¨l“<ëy_5ó§_Áôtd¶N¦t"ºµäºG×qöIô ¼Q¼õW˜v7]Ïæih/!¥ºVEm¤gakXéh2ÿ|ËÕXݧì!>…šÇV@[ã!o[¢8»r6{§ZŠpü«ê÷é\³äZùt½ÄðÃö\nÍÅùSà}É[ O]/"Ÿv¬;Th‹='§uGJÒ•t±»V±8e{t?Ù¶š%ŽpË´ÉÚGÝo¸_°Ciq¤]æñK"æ§‘ïå›Ïº?=l·ºÑAŒ„ºŽ/ Ó˜Ytd^5F6åCÜöžÝµÃ¥%Ø<Åhæ„»- ›)³ ;ȇÂϦT«ógå{þ$³)ó -Á Þ;,$ш¯eÏ>aÌ":ß¶XÒÔO˧›=Ô’žŽÛ¬aÅ˺F‚gâ[é~3ê7þ–c¸ ²I^ذÖ㮵rIMî­IŸz+ò¢yW°J¯K³qÎ :%øp_«y)ë<¨dµI:¶Só*1½£r‘(´ç߬맯IËå©ÓÂ9#6Óú¤“¿|; ˜’¶W¢Å]™תlúʼ¦rAo}t趉¯®C€MÂà÷urj^‰øSÆPB|*×LðšÆ÷áVËjå ŽŸõ;8#ÿL)öép†j‹ T‹icîªzNœûvƒ ›4¥Ïz¤:QT§i ­˜aÎ Ø"ætì9Âî°rN¿¬ˆc…§?»‹´Å®^ºï< Ò°¸YÜqžµ…€÷ˆ±dô >Ž¡OöýÓëè&qª’Œ [˜B.WãùB™Îãµ÷|P=”ݬtðõ;ØÌÐFdóχg“ÒϹ›W¸¯~çTžè¨ƒwBl[QD0Þu€ìÌ7i©ê—€VLÆ=o^}"ðÜdðÙKÉ,zDÙ©ûÑÍ™S ©†.ð ¦ÚŒ¹ÎuàÜŽ`±Ü³ÅÙòô¬WÑ¥VhÑMz"œk%¡Ñ‹‚å?1P ‡!_Zýó9zIœä¨–È`zÏŒbžu¾[4£óâù|ñæ k,ÞÃ9x/)ÈÒïDêÕSkæƒpÏ$á¡x9SSLÂÐ0À a"$œø áÀø©?³8ƒ78­&Äôß(¤Ïi™Î=Œxg|˜Ž¡¶f»è°Œè<Ø/EcÊå­âFÈ ŸNxb­@'6MуŸtÄ=}àΓ;BJ.1=éÍÍ´ <áï0ë%1У,-óaõiÉL\~á#̆믠q^ýô²Ô÷p78êéR³ùXÞ¬ö³$G‚}î{Y†yàæÞ[ü…~zâi®äé £éÔ]7¥–{k©\p šgÔlìq&2¶â26Ë{õ¦gÅ"ÙöjOD¤^c׃Ç1Î’Foéríýª@hê½N3ô*{¯^Šó"h­h“Áy=¤£/$èÓQ׋Ç/Ü7ªàÍF‡)™#v÷¾ ­gF¼{[©B5GxÚgš"¾8ãá࢛H °³¤£µè›ä¸äà9Ìøù:ö¯téÔGãð™¡ca7j@U¸ˆ[È Ž …t3ç‹OŸ¼~ôv‹¬Ñ±£Ed¼ÌÓAÊ}*qšòÑŽ,5lÛzч-—E4|—|¾YW:Üh¡¯ë¬iQ4šÊðÖ²]ÿ¾¼_ŒöF—Š‹h™öØVò r°Fä@aŸ(Ùó); UûBƒ?3kù•¼52~5•6âÆúô‘`¿#,æ«ê ±ËŽdé·ÌDw€CìЕùöü l“¼¬â¤tâø-òq´Ý5­Ñ>sw‰¨”ßY…u¥B ˜œWBÌ€'§UYÚæ˜G¦à’§¦"O¯¯B²¿ðxŸÞÉzq*G/|Œ£â½Ñ½ãIÙª[›è‡žT°Žû^=‹mâç(w«$JÆ‚ˆòòú¸^½:ˆÑ~öÞÍÀ) XÌ{` õ;Yμ»W B÷$·ƒlÁ¸µL äzãûˆ6'¢Ã'ßœ­Aî{VYÞwÄNãif I×ïjŒ~ÏÝ‹’ÊÄ”TPÄňÃbŠ6sƒ¼x·|f¤A9Ë …>QùtVärÄÓ*=xwì!Ù»cµçÓód -°ã%œƒhÝ5WcS1xaE/€#Æ ƒê›gO·@†§Ó»”öL­Ü†ÆËÑŸy¬x@òl½hZ“A±ŸÜ+F ¦ˆ`"ád¥àl*XÐ/\L?qÙèJ´H€Ø¦mp3žagÖ‰h«#«ZrúZ«õ9`/Iú£×û’tĤ<õ asø#hgf·ik ¦ÃO9§™ØöÄ*Ã2=æígK›¯’bÑ,höú•™¼~ª¯fQP=êÜqÛ¨Hü ÿtÛJ)µ’mN¾Ë¥Æ˜q4MÚ3iè `#™'] –j’«N©SçOµ­ÔßKÏVų½öeâ)9j}¯Ì‹æù,&xæÏND©Z;ª>Ýøò_‡i¯ À‹Á‰Ð(çÁ.=l°!¡úÂ&>}ö’4[ÔÕ¦³³\!˜véTî^”Ãeäª<•yÔ¥&sØ’+ï*ß”ƒÕ’ó^qÍHápÇk] ˆ*%˜WXœÚq;ôÆÀ^(üt`:Â+u®È¶TÞ¸nƒ¾8wë ‹ºfAr/rzè(|:pÕM0ÞXÄ˶{,d66>’R¾o'tèô­fÕ¦¤ç¦=¬í®™B³êMz¼5Ü7›ëfÝù&ã)H©i``Œ0ŸÙ°¿N@ n¬Ÿê:À5|0õn÷üùY^ÞœæóNæa¥67)_ŸŠŽùÄçÓ‹À<"n¸YÊóê¨vÍ2‹²ÊÁµI#¹öŒû¥àeÅ»(Ÿ=ëȧ”©žGË+¬ç§lð£©2ß?»çóRG¹‰7q$d+›­º21C¢<[F´g‘tÅ,mc_Îc¼½Ã;J=Êâ¤/„ðÓ•õ!Èvº² 4ÁZ_eBB¹CÀSÔwlo4°§F<3«Ñ1.²ý•På5ÜZÏT‹¼Rðlx­ãSŒšÂùZ}{™Þ¶ä‹»)‰ÄM Ê„ý‰QEE•º4=<å›:˜Ê¬Þ30É«| Iw·–#E¼@Øö…}úó<•WKîÇeˆM(ažÞ-ö GÔ!!(Sø±Qöf–‘$;÷»¾7>›)vÜ ¢ÇH¡¸ÝåzøÂ±RjG³¤Þ _ “Ε#§Ê•ˆ)§§xÄz#ç#ܲ‡Îɽ­(%ÐÖê¸f<qg/°¤›ˆBûç|ºeräiä¢ë1o#3Â`¹@÷ Q³]ê\>Píüô(ÑO¬Œ|ViL\TúµY>rEêqxÇÐ|ÃzE-É`¤Y°r|d±`Ìc¶FjVK6„*‘op™N_(™²OådP['“Æ>ÀWtÜçåñ6ÛE~æ& ìxƒOðxò5XEº:Æ“vk©­Öf˜Ä iéãY!ŸÊÒOGW~~D±V8Çem&ï­ ê‚£ \bk»£Æ”½6ÝG[á|ÙE¦9š0xi%0¼\z=±ö ‚ -kçÙû;/½N¶s@­àª¨X0¯©0à¡2ÇRÔŸðé£%T¢C)ˆŠ‡¬ꀨut¡M쯼-™|d†u,¿ð²Oo…d7+³Æœ¨MÀÊJ¶ÊÙž|XÏÀ&œ:7I\E&êÐÏ#oå!Ùsª\p"ñJ 4¤#¥¥ô‚ ’Cˆ¦Ýì±ÕJÓcí:èµ,µgÁïúš!7óô§ËOæ³f1B1RÍ2 Ò¼#7:Ђ«°—c©N6Çü3Wù§Ëƒ?Åо{ÝúÊ„:ÄÈm%á2«A:êÎcˆoh˜^[p=¿.?¿W€Çûfê9K𰫆Ÿä¬]æl(ÊM “¹l Î ·O*“§ l‰žº·>ðR/Ä_˜ñV!¦ÞÈk™ÞWÙÄ÷¸=»æPçU¿Wëáù£ù}böé÷êíçþ¢`u¡#4R\5OÓ)*è˜{"_2††Xâó~ì‹K'mŠ‘:²³µ’=ŽÛ^m}j>à¸K’&Ã1oÑç™A¯“W¼5¢‡GoÊHž %ìO/;¡E £`7oò£˜­gÄônŸH*]Ú{˜Yݨ}ýà.¿P‹Oç/Ñgò–ñJÞ’_§=>ãÓü<°Kôµ¾?+Ce­Ñ׉;5•v-Íû^ô†SUzÛ‚¿eFö§!³¦%ï誟°l×n5s5ÙQúé‘­qÁUé‰rÿLå‘é^Xvq¾ùûµtîs $¹''6›S>Eú„^ÃÄ—§Ù÷}F<[U.ýñ£Uè½]ÆÂ|›=A‡Ds­Î`–;x¼B~bî»±¯÷ꥑoÅéKª·FGú&r$pov­msKn?D&.5ÚL|Ò‚$èò§:8fqxÄ$¥³©¢ÀÇ/9ÍðÓèþ]ÛË\:~ôм+Kàu%f6O 27ʦS£i4ˆèvß7ÈB‡ùÃq×Ä_%õ+ ð±—m¶Þºð $¶ž$­´ŽËt¹&:¼vƒª8€›7]À™Îäd‚âŽ1c$|¼<Ä–›iaAê)SØÚ ž±mMbaÎíyø{S (Ö¯ò=EŸÄ ÈK°„‘Ò6ÄkÔÓ–2ì×­ïœ>Ñûì},Î]sóº ” ×& €V—vA.bÌ–ÞŠ Ë>[0C± udy/Ñàià»Ø+}¦”Ä}–/n…ò5`+Cߺ‘•ãUDzÜY7ât ƒØÂC+¿µŒ½J‘ûJ„§Á2³ËѨªš¹sœ‡Êù¾ö{é‚ä¯;Õ3€á ?ÖOÏ3ºâ{ˆR9FÔ€û‚+$â´¯Ÿt±Ã®ºvÉ`¬ƒfEÈ*¿,„L¥ Aè5êá)ñh›£R»fŠÓ?_}·Ó-™ÛOdò]UŽôQ‘•o8W1&]ζ ñ/•ˆ˜—™r¢–©‰Ÿv\ßrä¥\mTcßVн @‘"ØþBðû2jºÛ¢)¤/ÎÍ„ŸÎ2ÏÑ‹XBg8• 88’Ε7û@‰a;Õ‘£íH}¶’@Aw3¨ðî@.øFÄèj)Äb{žWsúhÓÖK-Òem¹:jpx/wó¤ýÌÆ—y°!„Öù EÝ÷h_?œØf^T¨ƒ¨ ÖÃÔ9Cû…¡Ð'†9 ¥¼ŠMGæ«ñ^JÒ8„ã>¢sŽl}Ýê²\U\šzZ\nóYÅÐ JRQ¤M³ÁÜ“Q˜!¼Xª€Ë Æ(|å-¢Rðˆ{¯œlä€(c…ø…ç›B`{¿7·&”™±k¤F!åsC“y*" L–Nèõž@­¡ø}}]¼» 'í^/×ê¿ ,Þ>ï§=ÇF€|æ´½ƒËæ¤QVKeu‚l‚H1 Ö‰jÕåh-U_õղߺ2½Uæ»Åp_¬–ì“Hq‹Ë@¨IPX—’“Ò3Ó¡Pމî}5?ÕXÂîHÄ ÃÖ»Ð98Ü3•¾‘Á#cNîBÏÉ8Úo>qüž:â"«RE‚v§Þô Meø5< V Ú}“IÊÀ<à(nQµ/êE‡“ ‘?(º“‰¹09?jZË€6Ú—n9N¹*¯ðÄ’ws¹.¼åxýç½RÃírm¨¿Ä¦óyèwjè…>óÚD§Ûwàž‰¬7Ñ KíÆ8˵?¹Ú’ß^öDHê”ܹôÅh}æ6¾Ñœ&SÇåj¯.‹¢dê%•árU{0uuè ˆ…ÚfŽG¾/Ì­ õuJZÆŸ2 J@{Ë «º|ŒŠÒ(‚/ 2'èཅ’¤ŽìèBMè¤s¼¿°´MGÔÕǯ±3áhLÕDéÁÆ´öÜhº?.R!óûì3ß7aoÝ÷¢Yù¢Ø‹¦çÖƒÏËÅ’š­ÎCcÓ¹Þh¥7ì’!6ù.â ¹ÇðBB… ÷±¼ÒÒÆ3 ªèÇZ ÒUF# ã ƒdš(@)ø`¹ùäe°*ï‚m¦!K"úNé…H ýD“uÜÝ/³ßøš×“ É*”y0áãÀÞF$µpB<ò86¥>SwÐ'š{]÷)¦ ¢÷ Ù^ ïÆ‘÷‰ègJ7^hµNåÒRuð³LezóÂB6ªôuââUX2>Kzǧª i4†ü|g °m‰„›ßà6—>›ê=:·¸·åŽýœ¡,Í;·ŒdSµut!ÏæÞœé¾€†¢Ê¹'ê¿§$òQÎT`¸ö#Ž-äk)mWh·Výˆz–¤,¿0Åïi4ÐJßÅô[{*—¾SqCõu¸L‡s§À€+ŠËHW½JÇ‘zõLpƒäH«;pV ß‹Zx-ðœ!s9„¶_›ÆSAd•y»¸¥®G›~že创žüF:J©ò™ýÞÒ.¼]áÇ×YÜÒ36G£»«d›ï¡; ojy{­œ6}¡ú} ?ä£êâî—oŽ¼ÃŽæ{Á£å©Öº»2=Þbô¦œÂ|h]\Âå¡`XEa—T£×ˆØœ#´—‡Ïýá‹Ê(º÷tbŽô2‹D„Xù¶ƒ›N$¸ä‚¿«–P,‚:9í™,öœú…ë²B=z) jðŸ³Ð»§‚çÃÅ. xônbHuÞŽÝ©~âú}?_sØ ‹Èym&,ófJû˜÷XÍP˜¬ïõKñèšžy®§ç€#/2XߥS ¦ÊÛ6Â*ά魗®©yì¤SA,häǼ|•.0OTaϹÂM³;/)#Ü’ä²µ.>HB \‡ìÏ! õ]±X/¥c7ܘêYèFÜXÄ™î3¥zk›%îŲßw}Û@Ø!. x·:ŒUó^[”Fð©9*O={ñ,AXí)Æ 8 æ=>iÌ Èb]±¸£É*sH*¡`ƒÉ¤뫞áŒ$ÐÁèwx˼¯ps›QÆ[wqA‰o0ºI½-±Ñ¦~k>úÓ 2gl \‡éyd2¸oŸ´^ú²ÏQŸ›.Ô›žé”âOl?û–„¼Ê¤>&Õ’‰£Pt‡¤ôrLÉ´Dd7D‰éõ=¡«|IÈ0Ë‹*ƒèŒI]a½Þ4Lzc¨U¯“ÔûÂ7`ô…¤*FJz+Oéx‚ò›kmÛöÍh-í'zX=kŽyO^¶;üÌ­(½#fš´å»@óTß=½µŒ º´yw¥ëøÈn± ¿Ð•ïÆTÔ¢b)êF/!ïΟÝãbö‹—À;L«Ç¬ªwâ@“¯kza`]^Þ¼¦k¯‡›Â¤ôÀ”£0âuOdäõòİŠ+ð äºDÕ!¥XÆ7a€=|kc·upËÍÔh™èž®Î¿ðYÅóZ’ò"^$¤Æ†òtI qy^…6l†ÌË :S⟞«ß½Œq½ÞÅ‚Ž0Q²C­Ldèå¶p×p^1lª¡¿÷`¥pPžX ɉ¼Ë@»|¾ª¨]Ïï÷ Ù+®gl±ùØ÷¹¦ˆàCÜFà•Ì~<®¦‰E¶m 0u»ð(hƒí@í!>cxøÓ{%Žjç^êîUȵ4䢉h¯×LË¢;\º'p>­"ïïIÁ¾w}â›|›ÆÆSP^k+U{O0Øxtuz C6Ýå:ÇCM)‚L¢)!(®Àº¤Lï*å–÷¹õqðœ"YáA ÓrÉuDÓ0žŸ jH‚[²ì¾Ý•e~Íã»2§!Ž2®:1Çgñ€ç\)Ø57H=Ûz7¡2±PcqwÕò’ý^«=u:VàãOŒý{³Ö…¦²ÏŸJººÃ;8«˜abqž6á܃¯uÏß<œvlêǯ¤v5ƒ]­¸¦@¨å$VU,Ð›Ö ‡!¨Û«`q…û-r=î}/ N,†rl,Y^ô˜˜BV¡Ô{&ëº>¦…½C?gÞ4_(I~]‡†zøú¬Ôö¦ŸXû…s|ö<ñÑŒ¨Ö'îôŠDÕ Ò<0Âî¾ye±Ù㥒lj½Rikáu¸d‹–wGn êmÍëIÉ)d(¸#¦èöQÄ-|“MêI«Ì1Ëa·ù°…ÒZm¤dr‡e+m$öÉà¥mf5ËISAÂ[c3Q¿ý…´V¬¯Ó&ÚÛj÷n™P2ö³Øèm1Ì Ù“´åH|v¿ÚË{:v^j K#%^ÔØNPEoù^åòúUëÔ¿]|+£Ya”;Ãò€Xžê:‰ 쾤Ͱ¬æc†‰;‹Uª*åÔM—Y”ÚÜM=‚—ä! KÊ4ˆ®8W°*Õ`Ùž(Áî#Íd¶DF®§r'+%¹ý{jŸ}; ÷¼Àß…â©ðmµ£_°;+ÒH«@ŽÄ·m@û…5~öA_q|ï2ÐbÔõ™+Qïh{N 2Xù¸ü¢$²¶Ó'ø¹O?å½^oP¯ ÀÀŸ-èÆÖ&Ü£ò¼XÃÄÃT7GИ7Ì~³P÷0® €qN ï%[Xˆ¾Ó §Ùh•æÏf`R@²P6П—À8¿pýé!i5è¹[ñă^¦t ŸòË Vr;”;ª£×=\ñî}¡Mð©l‘FØ\ØV:ÈOù((°Ž´–.áeDN½<|3ÑvÌ;)tc<€Ö GSküÆÆ tä<&»Ÿ‹qà{ç}ó,‚ˆ ó.€1¤K(* WW\m\RäE`³ÏqÇž7.n¤)C­bgV§94G4^Y" RîõÏÞèûŠ )^ŠèeÌjj xFšò2ßô¼`+­"îäÅüÄû³7Ò¸ÜÛÑÓsW©Ê}–à¹=Öb_m¿ƒYèt¾$À„.|)ecÙ°z§ –Lwã ±úx‰áÝšÜõÌhKÓR¾ž'§Ü¡4€ O@|XÅðÁKªwï™Èã7¦¾Î¢™@2QQ¦Þ±©$Æ¡®GJOì<ùé'TÃ¥fÐYºž½+Ö×$MÝ“°CW•e"ôê!°£T|!Ο]r²§¡àÙ<‚—íGŒ&¢äBüEœj”#þA–Eg=w;(W®Œ¡ô©kµ•º[ {Î{ ‡ûH«ß¶g% £ÒƒUé£Móû¾9AÀQûÄ¡ÕÕBG`wãVŽnŠê½·¦•êÆ{]/²¾0ŸýòÑF$Cî Y$=~gŒ 8üò½Ât4Ò l€f8F‚-g8&Y—’ÓiØK„Ï"õÑ[—²1ÇV1dô Î›%§òz»™¨žgHQp(‹«PVv¸WŸv5»Dp]èŽ<Å×$¥™B&›yׇ6sö3¥8´AÑcT®?KÛáò¥qYõx+ë!€ýÞkoH3ÍÎq‰O¥ËgçäŽzúŽ:×—ø¼¦™cÙ{½´…òj¦uîXóì^\ytsÍùBÒ&E§È,¢ÊFÎΔ  / >Ò›ZjÎWòFa9Ÿ1¿f ä aóT2šm¦´­ÉWò…»Â§Ã઼2ëB‘“6 ÃÔ7+ïI“;GÛN‹†c¶0 žædBHí«”qÕ€ ÓG®,#Bz¼ñôlškÞT›GĪð{ˆnéx‘Ó#É-GòªD Püä©ñt#1n o]k öªmnÁ£‰ÛíW·°¨‘g^<û|mîùƒ_È÷êÐŒ¼‡×(åî·cŠ‹Hòkg“iv!ME´YüùÏnª¤§Þè©‘*(‘ÑOkGBEÃ&›gÍ¢ü¯žèG¸p„"‰Ú†Ò¸KÔË[ú¤¼Þ‘ò)¨Â&y8îÖh{s²¹”¶ïŠÆ{i=Hh¶8Ñ„JPÂZS#³$w†³­W ªô²´—)y6`pÅh®< šOAYdèg_%Cn¸4T «Û•LqÈq$ç@áÉ}6 ƒòØ_¾ñâ/ìM?±L½â~åÐÖê­€¨&«oK4ëäšAŒémµ>3'Å‹#[ËxÊœ5x)áiO÷¥˜užÐk¡m4÷gxAåÍvÄÒ‰1"1ïig¡võô”Å%iïšÕ½,,n©xM$šcR¼Ùz#Óš¯€ÓùÕÕÛÈ ÷Þ®£\ ë ‹ßÊ7Â7ÒÐ#œÍ iè]«£ dš*NZÏÝz*17ô }ÿì°žy`t½ž4¡ÕÅØ± FWÒi‡5NÛãÔ «_l"º˜£4l„9ÎrN•¼Ç½Ø¶"èÞ›G„™¡ŽÊ> ’‹ÅDÁ~O«WP—ØöÔkR%#’´ðYäÚ€EØÛ¦{þ&Š0Ù –2cA›0“:ú8¤CÎ.êý¿„ó\ Š£sh4<Ñ4Á 73®Ôj€YšŸKri§á´´ôþñÙk…/Ðo °Fà÷l:pv'a6z‹¾¬€¦D›” ¶ÑP÷SqÁõæ…ÛïÔ'îóï{ L,2‡-Œ¢oìž³˜0¿ÇORÍq{d!¤ŒçäœÚs9ÀÍ‚ÕCÕpãY·ÐRQLÏSž€„Ž @òI"*IB|U ôž/ý|žèuB«gv(gwû:¹#bÅ›OëB@ï?²°à³í¦>‰(OÅ’îíXµÜÑxÏžDû$nk[[;¥=òŠ—jpêK pU;O‘UuÕ'_¢‡œ%7;Sq!¿ºŽ®Ì¡„[º÷²U·td6Óí¨¶ØSn9ªòÖ4¼zbšÉ%‡"S¢wfϼIÓ¢6­8¼¯ø„}‘v€‚»«Exëd«A¢# ‹›>ÁQ¡tm—®Ùèñ€r蛄Ï ËY° Ï8  §4Ýj:蕼.YXíG Më¶ðd›Þ0>98Ñ~¦!#šv…Mƒó(qG(ðèvCÎdwä%6­#‘^Ýé)ç¬ø Ä6 µô-ƒ`®æ“A©,iÒ÷&u¸9½QÞîóEô|·%L¥dKá+d®T€þìÅý ýÑöÉ<^b©Â·"…J±Åöª`èÀK—GŸ4 ~¿º–zºÊ¬+|=×>Ø&c8Ù1&ŠÌCŒ›ÙäN`ñ^oj¡™2J=Å8{û2•NY︪lmÌ8P¡?ÒšLkŒœ!p¦ž»ÊÄÆ‡Õ=cp¬±Wø‚\\|¨pPdðÍÒM©CzùtJè\2!~ÝÑA®ÜX/Kõ^(aDú†+ºp´¼ùySÉ˸Þ4b†¦ÌŒ¤·=Ð5« ˆөʼ\X£¼¶ÀéTÄPÙ#šöò©6sÃãÇé Ä8"•“ƒ¢wŸƒŒöòÊÀ@¨ÝÀÓÐU¾×ÙšÔ[&òhLFý%‡½GŶo›®GöNêly^ @n O]i>ØGaï“ýlå¹¥g ÅmyEÎôòÁu’Œ«`ÞÓ\vÞÓñ÷PÜ2±á5/×¹¯#c¯â“¾ò0žP\LE@—’Ç 1Jr™ã$Õ“QÒÚ”5I×-^R÷VG€¤| òØ1¡‘ª‰—fê!¸¥ëNa±#³rÒl„–Éâ3`·Ø}ÜiŽRÇýâ)3¼µÐÐ9œg”g|õbLM÷+<¼{*ݹ·jtf”ßMÝ>›ºÙ®Ã«8¦,b% /£‚Ä¢a œÞräðPq†ãW\L.ŠÂxe‘º‚®ú€nMÄÖ%R»0- ÔØyë…¡SÚJî°ïëÐAæ"s ´‡¶(,%‹%xÏÆwlß< ¹ Ÿv«hT"ÅWw<«¾l4kìbB Ö3™â!ØE Þ­?í cwƒªÂJß:ñH˜…g¢×FYk9HdݨYd³d;–|Òâßgd3é=̇<(úx ‡’ö }ýM #Ááá³Ú3¦:N…½jÍÆ¯\ª½çšÃ!LÇ:–8s¤šU(ú®YXnò‹*HN*ÃV%²i¡—ïDoÜCëEQF=&”œPkC*z+À4 BL ÔHö †v>­“1åš Ÿx1\p;šBWõó½œßC¶¸Ó2‘Ý,‚Þ‚i³re}·¨-Ñí`yfLßÄø'1LRP‘9”: ƒç àRãén$*—$å¬È9ËÀ6»Ãž€ É>ê†<謕‘"·…7VެDæÐÆÈ‰!ïÜ”îÒðž©Ï<´‚çTà >ÞnL  ¼gÅ,`3ÇYžµÌFzÖ(¥Ïö&àr¹µWxm±©½Öóe‡†÷“¡ÇÔÇ¥õ*^dúóñéQcY@3² ¢µlÈsgJ—ùmeñÙòá=„e§|&þêrxjÖÚÛ7)Q¥ç²Z/ÖÏŽ:æ*å)5õPݬ—¾+Â1hp>DF/ÑàrìlÙmŠ-ÆóR5×IofoégUjÙú¦ð¡JžJ½'ïƒÎ¬Üsaã¶ jŠØPײ'\k_zâŒRZ¢f¤“-V|D“nÜ ¨ ó‹°U1y£´€ /e¶a èžE'åÖ+ôeƒ"8—Ä¢Ïyá{¿^Ž•3 ¤‡oB0 èu,ò”¥ô^l\¿À1TÔW•=m 0î¤(ó{n‚hóƒž 3s?]´AôY u‘ &ƒg4xƒ^±¶ŽT¹¶07k Ì€exÚ·o‰¤³¸ˆ)@Rt#Þï’VѼhž¼-“³Ö0.µq¢EÓ~ZãIqh€l|‘˜ºÜ†â÷‹´|Šå»–Õ·#˜{ø**Ü~Ê‹ϯ‰ŸYkQ&°H¼ía¶À<Í{]M‰¨š•>JÞbk`ëÖy=ïÕT ,PèŒè0Ï,BI)°™³‡qãÄã&Úa–ýù†^k´lÖìu,'>Åd‹í fªÖÒC èbA‰)L!Á´oŠ>£¡Ú!z·<Þ€ÀÔgS;!Š˜Bx £o]е<‹ÂŒDÂs)ÔÒŒ,-ü¬¹¯×aHpk[ÝP.²Î6³rŸZø9uIÎJß{ɯ¸õH ëk:O¯ié|Ñö¢v¼÷U>÷0PÊõG¯SgVN¤aeÈàRP§¼«§é画Çíh cí=ŸexœKt3D?çîZPwkÏe… ±-ðN1s~ýÄ.çú@—q¨]:Yå›o’ø3$Ä+»„jì÷6^Ž)Ú0Ö3‚®µN±ÖËwâÍ3EQ[öØn}§¡¾ôÍÌ9k>hCfÖ /–`Š-K»HÉ‹é{íIåvT¾Þ½“|X)½àr[áPYÑgq„â ¼g«¼Í>æF9ï Nž—]3*¸ä²'(ÜEùl³^`Nl5¤”6³w•ŸªÄð£¤Çêý³­xƳ ± ¦¡[ ‰ZEô†¦VКž]‹ÇC²°òIÓûŒ ›Ö¹ ½8éQãvk÷@™ çã˜,jÑèkfOŒ“È®3ͽØd{tÇ%oφuËzßvdq5bôÖ7ð¸93KC–#[­BO«Þñy$ÖLkâîØ;×µFPE!éFË·Ô»±ÚjýpÊ÷ÆÆ•ûÎÜ*úZ°NòtJ§ÎóÑ; y•à€‰¯ÇÇVu.ï÷â3ƒõ*òÜ®Ô\¬xs¤M‰4Çßä35?nº[IŽ›’?…ÝÕ'Qò})Û'`§:‘¤öL‡ÙתL}ÞÀëæÇ>‰t¤¼)×y5Kb1E§%~8.?‚@ÈöH3éP*£ÏnCÉ&,W·8³ðTG<%LC2rÄ­ü9ξª¡D}bæ!€ÛÂ#*à9á1Ô ‹¼}þüâ¼ock<kCÌ1Mb,'Œ^M­˜šiY+S5GEÉb€Ø©¥D¼Æ©â’67LÄaDx¯å'YÉ]¼.‚~U)SŠoIý”OšÕ£jÃx$†¥êÝø&ë3Lt›ùËHiY’ÃJY•n`ÖÃ]ÎÊšÓq<ïwN‹PqÁ0!)\ıa…{µwžÔœ95îÀPT–ãŒ>q };YÖ[SµmrcA g“T.\Tà!î—pÞ¨Ûú _‹Lï2Kgàhø¾áà,_ßlp’óœ­ÝÅй‡Ò€¨öVø‘væ>ŸÅ®‹?‰ØÃy¿÷uÞWÈa|ç6š™ZôN÷6Õ+›¯äñ‘ªÛì«èZ¯ù¤Ë>c…)G=Å»#ƒ¢'’ƒy½æïå¦l€ÛÖKŽ­Ð*i®Ìƒuõv!~ð.ÈZ¬Y]¶Ü•G†X ñ¢ ?câf Mg7š‘uÑxÙ3É:’X’™¨Û©¯Ô]˜Úë- d:îmËmHåÛâ[­!<ÆÃ•õ]©~´Ã6ö W$üÕaCÜjâ%òWèåæŽ&%†@"áï÷¹jpé’%­ÅÕ¦ÖG¯‡]ÁÀ‘­ô|o|0 ›Ãý“0ÿ¥‚|­X }•âóÆÖáâ >ñ€€>‡Â9ZupŸV„•0â<âòçIYÛÐÇÚÏË–ÐNd½ª^KÉZµè°\šZ–õnœ':“Ü÷ÐU¥Åºv_U=»|g~oWEo›ØnßnU^èâÕÀîË5¬¢“w“9‡·ucÀÄŽ£¬eÌÓÅu¦Wø–8ïðÔwxªÏ¤£"Zôg&dšSB¯4¹yæž¶bdi£Þâý‚Ÿªó5!ïcÎã©”¬ïLßQCâ½:™Ù÷©Ìkx“FxÇ˯ë”hòøá-j…>ÆÓ~sx¦0üŽB·Â&|D!GÈõ¶ßô¢Ñ;‚’wcs‚óê-gT´äéÖ ê(í:UfÂÞëF/ƒãs 'Óë«÷¶åiSsôï¿»``¯GBOé\Û‰·PêžãjYtsº„«øz±±SÀó͹j¶xoëi@ŽÆË­ÍA+ƒœgÏÍ}¿Õ2#!Œô6eç8ÈäT?I#ø ¯/‘ÌHOõvæ!ÛñZ,qà–™ìx¬8G®ój8ÚºØv¸H­ÀšŸ*é{1Ð-3ÔG„gûšß‹|µá24²juGAÌb3›%Y]O1Ž“S¬¨/Ȉ¶ÈÔ´µÏAÔà]盇›Ú4Ï<Úä¬ÊÙgܹ8‡WlͤúHÉ9D´Ý]HákÙD†…Š`OY¢k!8 üiö®Ÿ­Ìù9*qaw>¾8ÁMcÙ÷ÇæN•ñ/!VÓö?†W¥+¨/-Té4ï†&X÷1eætïè¯Oœ^@ĪÊ膹¹÷‹½ p+4Ø>Îtš7˜ ’ {íAïXeÔ´¸+–j;ÐoBêñì:YG׉vRÑJäTºh¨¥7O^ Ütrð(GEž¡n´WåóŸóX½•4à1;Ï%…î‚5|çž•éÏìð™ÂÓÖwŸÄágñGÝâ,ð„C‰ÆÎpm]9©Ü¥E*•¦^SòÑ ÒZ¨Â´H'EÂ4¤ÛÔ›VÚ}–§X+fŠ)¸"ûUæÚœ´®ࢡe‰.Rç<ÓÚ žC#Àkó|h|ö]Šgsßæíîó†ŒÝváË{-xò†ÆÉg¦»b @g€0)ú¤KŠ4PjË1ÂËË].ÊÒaÃ&0mÉà"ÍÐ~Qçˆ~Ô(6‡$0õ¸ÑùÞ£ó(&ÚèÎÞRª~¡Ï²u´>©£ÏH¢ý  CŒWŒž«â†ßÖ2©^$v:ò°² c.y=W8âæäôll~© Kc¸¨ÃÙýꢗPZ¥°áÚÖlxÈPlU'£w;Hüü¨.¨^v°ÏèR,ƒí,kHœr×4\«^™#oá‹NÊ@ ÄÚ}ÔÏÚh5öÜrÃë-" JàK§8##"U³~îiÞ0™¢XÇöóÝë2dw‹H ûCj KL©U¼€Ãð”QÂâ=I—˳Oòø3œ–M•õÒÝÖ#ËÀî[!ô› eKÏDçõ³ðš&ÔÌzǰw3Ï€hÀEøQ_i°eÙ•'W×>«ÅN"óÎõ”ÅÆÇ|6, &3„lO;§Sì!ÃÐkåYÐM}öŽˆŸj¿ €Ø£­xN=LÜí‡úpý™‘•ÄÚÓòTÃÚ Ö©u“¸üÙï$bv»[Ó^>Å´‡±ÁÑöP‘ïõºÛTzLÛ2ÙŸeÔ·m>ø´M–ˆ >ÅuÂÀ|FìZMwo¯æåŽÂˆ®¿Ìµ7†@á'K®ç‡¦‚=d“`…[Îäõ`‡º9ç@Á‰ù6˜¯¶Ðœæõn{‰ã… =æ•^~ed†Ú÷r+mz’ ‡"3Ò%„/žÏÄ㬌eªÁQ˜IË•ixRä<  ‹]9ÎÝÈ”Œ2%"Ì ­ä3ˆO%~šg-Œ*h¾FŠÞSÔ{ì 0ÒÕ°q/†rÚÓU ƒX±ùÞ}ø}|©:!íI“•Ä=å ‹u•h; mðÚ|y¨8.ù”ÆaŸÀƒ ¼‡* öúq¶*²#¦wíHtû¾~‚¾=ÔæYØY§ZwΛÅé€ÏE€Á!æÏ’ɵƒ·×ƒb•]Z–«tÓÓ®t”™– Ö°ûm=¥¤TZª[ðƒîœàU¬’(sM#ÏRÕ[ÓAª‹+‚é|‘MÃ!:ÏØeé…o vâ% U7š&F  AOv¶ùÀ#\¨Ê¥dÍç¥óI¡|F—NÓáD’t4uR4õçj"φ×O ‰.ò´a­W ÞS@×[ƒ'–±n±7o0Õ½ ’Ÿ±bû³J˜ÑL¡`Ý<_ñÄZ:ilƒ·øtX5·Ø…k'f£ö6D#Û37Ù2® 9ÓFÚž+Húì…¹ÆÖÎŽ¢¤L¿ÐA\Ĭ*$-½„4 ÛµYD W@`¥é=3iºÅ'9©5‰ÝŤuúÞ/¹F¯ŒLßYÎãÀ²z›^ÖÈŸïe‹^,µ BÀå«û1úbδ\¦Õ!Œ¾ †ÐÁ1¤²Ê³+4Ôæ"ThjwjFØCN1-l†=?ó=º§`‘9Ág¯+ÖÆjÏ:$`=‹ÔÚ£Q¦ˆÙû‰3wx÷Ëg˜æ@F¼÷ÚÞKîsHhõ™·#žÔ¡ï9è=Bx½+¬ä+5g¥\P̾Á¸ŒåÖô Ÿ¶`æšY#ùs'%Ÿi3qÏŒÃ}ñˆÞ©·UOf='˜FM•ÖS@ËO">‰Ä¾iJë.;f,Ú½;¶}ž—ÑæÞ|ܰ€ÆÊ‹]ÁJ\¤oƒ€ãå>¯zÍ)U¡wÕ~°ÂǰD!š“Õd*'veŠ‹Ï¶ë\Ô„yJW =ñ<#d¼sÐïԄŇ —Öq¹Úš«rèœ.«+%Âu"GRKëáN5l‡On»¶xÞ³ä~û´ …^·HÏ(f¥W•‡Eh¿¨"c /+ìØ_TνçÁºk4q«ÝWlƒÎ™7Óà ¨d˜—ŽÛàœ‰ïÌ7•Ÿçíª|„dÓ¢{ïüXfÔ»ˆäʸ¤Ú·%=¼*)Eyí]Þq©1¾£‡Û/î¥âr r®“V;¾Ë,/Ø›¹Áªlì ~ "<’"ÝUå(<û ÞQtRÍîÁÃxê 2#(bÝíСPÕýÆlûްUkî¹>‰yd®áÜ9Rª›© žyUdX"éµ\ÈÜGAù_0 ÈkÌÀèþi°Tõz›(ßmóUU.; ?^ÖÖ.Õ& }ù˜¶_/Z½O2C?ûdº¨áœMÎE¤Þí†%gEªá‰R`¼p‡öÜ\-µßÓR·ËŽ„£ëö墷aûˆŸTpÉÙ°:Åðy÷¼*Ö‡X.×Ää[Ђ]Œ‚gà 9LO{A‰Ó§½¸_\ˆŸkÀù²+¬á>‹”Þ„âóÚ·ìx:ì‡Ó?Ç|JG›Ø,’£õ†bh²Tðqê1°ÓÁ„Ì‘nk,m†/:¾ÏIþ,W-쪡´XGWÜÒ‘˜{§@éX m:Å;©Ty‰Âªå‹EîãïÍé“…Išrõ“¶‚ǰž"ñg>. ­<ñð=°'àÞ*]¶ñèx)›} Éd§ý¦ª-)lÂ4“cæ©°ÑãkBŸKÍz3ŽVš6'–á±CÏõa)×£®×u3&Ù¡;×d/[”ž½Vàg 潯IÖªhõvôèèkÙ mŽ¢OHB਀Pó±i ÓxÕäYÛ'¡ø€NGšJ;8ä]+™5@¿ÎHÞA*24>(ê(Ø—žª²j«1PHW¶¯·Hxœ{Ëèeƒ@ÄÛGG£GHñ<ÖŸnÞ¤Ï{Â{O8ygýx›¥3™(ÚeõÛä$gÎ4~  ªd þ¾ì‘‹ñºE3ó‰µF°ó @áÕ\9Ëà [¥ƒ¼(0Ï›à(äèb'%oÇpß gKƒÅ/JZnJÊ`>$9au’`obñݦšiì~ðh–ó€µSä“RúŒB}.J…µãáA£6“y<»ENOŸè†“Nõ”ôñyd'àªOÊHxèr*ª°xa1¼Ñ,@÷j^Œ,,U9Fö©¥("‚Ǫ©!Ó͸ÔÎt¾:ÝA!’õZ‰ßánÒ;Áç|´±O<êB0.[°Þ€â: ’¬‚œCp•FX5*Jèí˲¾\¿Š 8 ‡çÐ M7¨&¢ÆÜYÞä1*=è[È ÞúùNýUY0=fBoE=€ŽÞË#'úlP{³Ý£=˜Œ¾IýÞûd/cVAÒ2©Å{Cg²(á2e,¯õôiø:ʘq¢˜ûåcRsìÌÅz {æûìi´-C"<¨‘m²§EáÊ[v¼5©øúQ`:Hi¾vÂG ¢/AĪ jx‡Ø0Hè챌¾!„]ʼ—Ú¾|¸ê-p##¬¤s– Ëù¨lUô.hÖ¸€µÏ Ãúø‰XC#5—¿ DǼ§Vm’1?Ç/ÊcÓJ}j}áÔ¦Öþ|¨&}@=…꽄ïg<@§õI+Æ#ˆÜÁ8äÐ蕵­ sN‚È5­el“çïm¢öGm•0 Uõ‘ŠÈ¥*=tA·)?èbÑW^Ø uê2ÏŽÉu' Ê™ÅO"†à½ªq¾,ósy·ŠÎÄвç+ÀæQ÷[Šáš¶5~ãÊM5aõšC(²Ÿ©QãÛ»¹VA~dK“¦ZBσ¹–‘¶df_ŸÃ»"ñl¹rñG³l½g¢€vwò“XY"¯®IE}4ç­>°2J6v¬½ëºº89Ý„àÍObßû4a&Ö2ž-S¥:>žLñC¶bñJE…={"æ’Q{SÀ’ ºï‚¢&Ô£÷ —kR²ï=‡ê-ˆA(Ïq˜(ùæÄ—§m&ˆã¸œéþ^¸6צÞÓ¸X Œ×A®Þ#'¨OIÔÂïàÑ y_ÍíÄeØð£ `]8÷ºu 3¥ò¬{¶•ý‘K>yƒ(Ù6Ä’†F€ppšEžäóõ÷d*ÅW»¨}óµ Ä QÕwûЇ¯‡¨5ëB²®Ø/^¯ˆRy]íf\<ü¤V>#SqÜ–“óæ´ò:ú+Á9É囇™íÊUP‹=à™âjã­D¸Æô˜ôé©ÈŸ!ƒ¤¿õi˜)}Ûü¢3â= À’ã+žÞ+ð¼Ö!g5U7.|Â% ­ø @Z8U]K|…“1R¬B‰w6_äñ,#z:ÆäSMxôê-BÁižâ ÀV×S ™Gª 5v*Xùl íТ“\žØ­?Œy~s5ö^ÿ^>t5‰ÓܶˆmÊÑX{}Ýjöbø9e¤ùÊyÞùwŸÕÏð”á<òN€x½-"îíT­Óø»G„3˜ffúY¢”‰¾´cˈs݈gúȇâÏ"ÃÒ¨. ùQ#%\?s»1@KE{ðbóq‰Y Æž=£šª‰‡ÓåtmœÙOÒ3^ÇQ ?³S¼á²ÐJ,'}IøZoÓ^‘¶A͹s>¥r.Í›yAÏË“ØNAn%Áom¼ž0á#ܪT«1H(€™ºx•Yv,12¸›räÓ÷3Fu­3úZÑ­Q] Cwoo>@/·{Îe|½²þzGe!ø›Þϵo°ÑÃÒU{EŸ²”="ºÐÐ:j;}0c>¶”ª‹¥Øú¨ xÓ„5s%Ì7ê^Z=áe¼°zšr°'˜`˜Tès¨…B‚‘Ëfzq¸“õš’Íš)hC8K +²¿7²ÅÁ@Î#9ü“Ñ éŸ½rE:ª¸ÒôŠâ”76³äýxtÜåµÏŸK°4F8âÔµÛÆmÀ–»:v›P¾ó+OêwQ˹ {»’QgåÏ?½I¡nð|uuž-£È;¹nÇÞ€J?g¦×ÖÒb_ø&ØôÓœZˆ—§sFÇdÎm QÖ™3Ê +dãDžך x!žCéâ£Ö4Fw€g¾"¸&«¤¸æÂªc@¯Æz¢‰&jmÄ®T4Žžc[•IôÖ+ÖNª¦9N&¿ÜšŠ ‹—>F(²#‚‰çÖu õøÚô@¡'6½‡gÏÍ÷ù[Q9ÅóÚ^-íîxïÁ ËÌÞ ½ÚåºN¯÷m³£B¬õ˜E/”Ó_¿·d+ìTc[’Ó‡gÁJoøií\k Þ›ÎWbô`£#>)öÏh5…x QYiÊ/H g„£½+'é…ÚXμ 7=³¦qh¸7½WcH(ÏÙXœ ¤;é…ÔP>6Ô[};¤}%ªÅ¬¯æÅ.ZÍ„#Ì࿇©š~WlÝ WpKépõäaygŒÄô>1cÏ?}˜çÍ7:‰JӨ׀™-dùH¤ÞcC­À½w0eÈyÀê·vpŠ;àôZ¤_ ©ÈóÛÍiÙSÞ[ ~ÍQ~C1ïwvðÀ×5o„EÄ‹éרx^š]h©9“Ȭ¥•Ò˜­RÖ”ºÕž¯-ŒºQ‡¿1âŽ*.DÛòPFH‡ºTéÙ2ù´ßsq¹îÚצzÒ{¡<ÌojÃ@ 9è°¬_$öm“àU¢¯µ.ö+DÕ@¯wzÏ3¼ô7صkê_aÏ!ËbÞêC)!8ìçoÔ¤~ßgyHÝÇÕ¬Ó™›f¼iÎhÀ·3Á[k9Eç<ù¾‰öÏ\-™ûôi2µK_gе0Àa8]VÑZ,9ï{æò ^ϵËc„•†SˆàÞ;yão´ž2ñCN5šDK ÈA¬ù«N —4"1 »ÖKF¼7¨®ÒŒ%Í#ˆ\âUP×—5“à:&l«:1 Pƒo CÁE/GЇýAÏõtÔjž`L‘R’ÝÍ"鿏Ðð7* ˆ #Éà0RœX‡®Yó(DޏÄ{ây …›)(ü¤zNU¯eÞæ`s!TœÏ«rÌÍwÁÃn<Ò+}•ýJã±,–õ'Õø½ÓÒ®Zµ—aNÀ›£ b‰)áϼ^½®=ɰ nßG'bdÈbrMéþ„qL‰ÎÏ-Ø-]"aÈÀ{üì!g±K^³˜šWˆyÃÖéÃ=0ML†Ã3a‹é¢t—š¡Ùuh@õTʰAèCš¡ñÞ}ªOÚVž.,qæsÊZQÅF]=\r6\Zbm–¨|Ô$JšVv‡|ºùrt±oQy £ðL C»fåªCxbÅ´‡Pó:€‰x´<{BLKJQ~U°üÈÙ‘à<\ãU«åë.jìþ$›>ÃØa yŸ‡Û3°yã9Rágm†³Pbè>GÌEÓžRŒ;)SgâÔW+‡­|ì´£Þ+®³WÕ<6há‹ìQ0&k-ÁÃÝ=EІöê­åŒd/)Í“îË%0[7·P~†ê ¨´ÝéÍÞ˜î,P£\%Èï àæåÌHH,‰0Ûd‚V»²øeuíÍ•T»‡9?nðÌiíwÚ¬§r(º.Ø‘p¶/Y­$'xÜž#%ÎjZ÷ç„Ó/º£jÏÒ„Y^²{fZ'°L+ c9@`•Ùó3]¡ñ#8ø¤›?cYL§m`=<£pÇeà€¹2‡œ\›âz¦ÈÏÐW/Üaå‘bÌeZ H›–±@ëc¯Ã¾­9 H–ƒ×5‡ smnr/ß*õ”¯dÎX¯?‚|NÙèñ9ƒÜº¤½åXSÈçlÏi‡î±Í m#<Êë‹Ùžæu³¸{šƒBB ƒL/!Þ$ãl–>ÓÌGGÐþüq_c‹Ëû³ª¶3š¨”Kãzˆú°ÊÐú'á…àO,µ†kwÜâR­·½×TÝA–ÑÜÏõaº/ÀNë“ð÷ÐÐÂÝžc\åp^Ù°˜Y¨*¬¦c Mø“âH¾t&¦Ó3ñà7™Îw±)A:·•Ù/„bt+ˆ[ržïÈ{ÛÏpÇ0pçž²2;;½ Ó(^u‡x­N„‚+»€+õÛ]%ï¼´ôè$ºtbÒbÃZ‡Ê/µu’O1bh°:Kž©S:öhŸÊ©"!Žyu—ÔÀѶŽ×…u­¿òÜ ˆ¬dÜ©.ò«kæ2î‰PBIDbÿiéŠáìs)…OçÞjsMµå3«e-%ò­ @Ê{ݰõ ¾)÷OÊM÷X†¡,ŸG”7Œ,Kì“ôÈØÇµ"®xVîÞù ¬Å„*gwõPt³X¿†…ó\;ÅÚ{c²™ZAx£e,ƒ†Â²±3¤ÖTîÐnfˆ2ž–mIáåÕ=ÃEžp 9h±·ZÉ· ¢/uå0éÒS'áUN×[˜e¼éçØOÌ1!³­¬DG¯Sz½¨g•`Íl'.øOmo¦ÅįG.ǼÎç:ʃÀ*bÞ挅Œ ¥Of#–yäAÛ( kñé#¯÷I½F:šåƒbKe—0)4±ƒÀhK¨Ayp¤)iR¼O«ôµ)Ëî0ê 2úÆø,r$e%¼Äç¬.r,û„¼Ìt q=‰Kžµ—& DÑÃáÚ`3TèηjÁ‚2MÔe×öp² ãdD÷ê™yR,eKŸJ=–B—ª`m'š<ïj²´ŒyŠ¡Êðž¦$¾JÙ!%+#£*…)¸±}± âM •4y³ëOú,~‘?“ ×XTÑÀ3Ï)} ï†û ZäÂG#–×d“%Ú7ùŸá®Ÿ¾ªÉ!“˜žp.•ŒŠ;—Ä5l;&xUÔA8ÍxÕã-×O\=7ö\J;ʹ*)%ˆwÔÅu[¶É®ÈÅR“b 刦›ãVñd±ît½^v½ÖI{^kÇÎaïÎ.}9ÎÎÖ_27»ª›4`u!)w< ð…X{—UÊã­Ue<¾üœ"J¤šá‚îÔKsvnžÙ(‹Alj ø³c]z•P"bÈÐÛb[98PŒÉæèñvI—Þ/ú;Ö/´ÒdóØp:Y¦5};½‹œø¸V'¦=Sóí<ÔïlŸ1ÏËG½ÊÓĘnÉÈQR=±£%“±ÎNû ^S!@æÞšX”ª)RÔ0Mo°ë{ˆ'§Õz¶PbÙiÞMzQîâÙÑ…*wôVUÍ„q9NŒje·˜ô =tD”c2««ÈÝÖ<¤<ò·ÎõĤ.‰u¸×ô¤hy›õ$âÁ°-O±/òNQ”4܃wzçv×^kI$wDWí¥…cÌÐbþ`èU›h9 Ã䨃Ê{#yÚÏ\Ö‰³y¡ü÷ž ªÉñq3¥ªdɘ֊!5°ˆ^ÁZ56ã¾tÍ/|>-@7„÷ôX}íVC÷‰ÒD£?ö§Õ>áƒu61z]Ïëšëœ‹uÞëwüòLz0 fYÓ.è\íÄÓ`ÎØß¸Œ2h6åVŠ/PÛ­æÕ¨l§õ{a6ÃÓöîyéZbÝH÷›>zûFhƒjÞñçû‚¼`³½ì™Þr7ðºRæ›»÷ ¦nGgŸïC8}nÛ×LIFfÇ'@\d$9û YÄ=D^º³vô טډ±úÛMÌâÞÓ~þ3ó—EÉ9: _½¬,åµ.ÒôWÉõ±¨y-ør<ÐF¶ËnÇïSøýBø%=ÃWójÙÚ=yÁi'­³å5CŒÕ¨ÁtOH¦°H¼§ âIqÀ8º§&ƒ„¸ÁµNª‘í"›>3ìMmŠ3ÛÐ&ai#±6”zÆpçææéCŒÚXAOK»±^XBЃö‚¬{†²Ôù|/îÉ›&àUQ.#gA>ß+×}Ñ‚\eâÅB·„‡ RÅÜlH1Úíx˜{šÓO Ö,áVžô‰ „ˆ5¢ qw‰l’_HÃxÓEKÒ£bþ9ïŸ:`ø,Åã!؇¸qFµ×‘$0IT©ûÀOŒãSôÁ´Ý(¬\-래nwÛ9Q¡¼¼®£à Æ8,“šš¬˜ Ëî!õ;,§ç°ÄRHÛd’Ìh’TE>žÓϤ÷–ùÌÏ{ÉBÐØñ€V-¹ÞùKÃÃ"_hÊ C6>=5Rz×›>˜q.hp9 —P5$ÀÒ\SÑdžZ„× ¡œ»ê û³‹>õ=^º*yÕo–¨œ¢e7Õ·ßÃëÊÔÜww^°RM9òfïâ&ߌYi›¼ ‘Á«Ìù9 $Ì‹(¸nT3Ñh¾ iˆX†Æ`Änwr$ûö¡ï]ŸûÆ«yYMè1§Q^É–YÏùš+¬Ì^gZtäÊyå”É µþ„uËz§kA|¬ü¥æž“—'aid³‚d(ËfœlB¦o™³TËSÄ ¢ÐÇÂ{k/pYÍšzkÁ‰6D{Psµz¿$&¡æ‹EÁ|¨õB™ÄÊœØOët"œªP[ê‹´ê®îÖ£#© àn ­4mÓÌ8„Ä€ÂATàÊŒ»MTB5ã'^ÛFËÑqÔHÈæ·YoMóg.@T}-TâÞ¸m›:‡’T•ó"êƒ'ié²¼™[ù‚°~ú‡DÚ¾Ê\·äŽÌúÀã-‡Á”5£˜‡[‹XSêHÖªìO¿@ Z\Âêq‡œ­S®z„\v $ºó°DÎü„\¤}Õó•ª^/MR=ѱ´µFË’£+Ü (‹ÕpCÚP6”p¾Ó‡¹¯ÞÆ´1_6æ"^ây[<¼n§Í¢g9S¢KÊþžmŒB¬"”B/¸ªhæÖá$·'1ŽM¼¥ÈÛ§ÅwøÒhs‹ï½œ7ç⪳÷xž9&‹yu„¶[þ¾ñàbèÓ·m7ÍöËÕ{Ê}[vjS2 (é•a@©Ç§ÞgDì¢$~÷di{Ä•=$Ÿà°G²FfEôíÁHÇ]'®®ò™rI㻊zæŒÜ¾Þ°·ÅÙ!}rle«¶ÙH7À¾$Ϻ}á:¦$ð˜÷XëË šIâíp2F(…p‘—/ÍHiJJžJ,Þátê–ñ+7âÇåZlóú&ýìNÕó=¦ÐÐA–° –æa}ˆMcz@‡ãŒOçâ…4¤¶ØX]ìš­Ã…¹å.Y-Þ"iOÇžçK›®jVÛ·oÿT\6Iò‰ýVµ¡B:ºñä!”ôMc¡P.w43yØ[›Wµõ¾ïû"ŸaqPks( çMë¹—÷y-¸®:ç åÑ k®)ç&¶Œ'Øþ`o}Š…ï±È8œ1…„=ž%è™}Æp¥íCÓEõd‚æ]M‰ZCòºÖ`zZHéÕQ\k«ÄÞ)¸³bÈRÏz zÝ•±³I%øv¡ù¹c6°.½EÁZÝÒžHK Èë¾#~c]ˆ±uâ=Ðâq5Ùïâ`ÉÏdyá­ÏV¯‚å >j—V/© ËÍoDÄœ};ñj2Þ¼ú9;L=Rö ĈQx¯DÌ{+»çiq,ÏÔ¤ÌÔW@„¯Ká}ÊA¿w‡§rZ-‘.¨K•k·bá0ËH¶’E&'ÆÃüÎø\t›EP|ft5Š^-”!r¦)TêF/öó‹EW@ê Mœç/ÆdNªœQØíÆ|cQxMÏ+m[Ûý…#œÄÕ«ŠxŒNÅvHBêª÷H, -цvíC׈|­›€À^áþ¦¶#ª@r:Þ†H¢0F#¢Ü¬!‘Þƒ±~ô`‡­Œ÷!ÝÂå3`$khµ0Ú!æ•Ùb€$RgtÉÉ•®¿Ñ5îQÂèé¢-ML8¶ÏE;QUñðfñôžÏ"Ú· üSÏWhaž #Bó²G§–¥1ZaZV“Á\ÆÓ~¤™]Us¸(þŽ–¼ÂŸmâC¡e+8*öz5Rm-î äˆÀÉ›U¹³²†¸Â±š^ÔGa},Ø`^ïÒÏŽ¥O±¶Î_=OÀy¸®-†²ù •ÏØ„-Ò¶pÌL‰®žz–ùËÌÊ·Â/unpN/Q‘®‘ìк]¸±u—•¦Îå>ÔgöŒ žÖ¡#¢Û `]ÆYQ]dO'× XÏáë›´¡.¹Š}Y?%qЯ‘ísN«Øyò¥ )w \%vÞ µ„ì0Pfa–I~–ö%oÆ2sr½¼¬±ä”å'¶¢³uæë¯,¡ Ö[G¸š&—±ÈZ‘œùÝãp¬å"ä±Dô‘h[-}Áéz®š¨,ä}9hO!Íê QJ£;7f·ë**©Úö÷‘/Óƒ@8©pŒP%]¤²Ç/Ï_ÊL”¡Þ³Goˆ*­<¢LnÐz¤x"fŠá1”Wã^šjžƒäyêj„`‡×Æ-öàIPX19npõ–)Ö¬asŠøÊ¶¿gÔ3éoûˆ¸"EZÉá§(ÅUvknà=ÁÕ>(DªÂç[ÑÖ‹Ù®oŠ­ÂÈŒ~ŠÂ?C¥A>¨«½ 2KÌ£Ó²@3 ë·5IÕû¶A"²»T”JæEŠŒYÕ-ã©ZôÍÄäYÁcö™è7ø0§4‘Ô ¡•Ü3¦ITÛå Rš¯£+ƒ¸¬dCs)gRŸK̽rÝØ…_\-t¯žo‘â¥"=ÙeÅUXÜ;ñÁaSŽc®m‡­z{³$ŽöXÁT‰¯UÊ­à`9°ê µÈW{|Ü\*FûX1ŒßÃÊœÎWy“gy˜khÄ>?g gͪ3Û3_Tšõ+ÕW¡# e·^ò­U˜“ŠÆ}¯£ƒ>eñXtß‹{u®ïYá»7j]Z'¹,¦„#åølE©TZU\:öÖs¡HÀä7D:5$PØQØaD=–¡XX¬'[|ø¨`Ý—`”jâdóžûœk¾g°IdŠNûžC„«÷krèÇc£/…Ô/ ì…¸§fµ³¹Ó¹Óß_ù KP°G"µ9º-m‚íyùî‘M»Ps.Ëa Ô®&öóJ[49fT5(²p~F™šŠ»©ÎɱËÄà ›ïeœ½‡˜+½À äY/Úâ~¡þ -u=Ê`©Ð55¦0_ó2·%›Ö“Ʋ¨á§3Ì{¯÷K ßA³ÙÂW°Zý91ÛpV™LÇݺ‚áËÈ1ÁEp…™¥—åÆdDTúúÌÞCIƒ3z=G³|ûl&ÁJ±c’E𞤈?W ç—5«¦‹=&§,’É››µ\‚ÓŽÍæ!M»¨÷Â%OE‡Ê:èzÆú=›®·§åÜ™}‘{¥ˆ^×w¶ïÕžÛÖL{ «s”ÙOÏÐÚê‡1 /Ö½;nõÚc“è…hèy#J­tþÂæ[þ™/R´Îúsˆ› G#ô»"A1±ôÛnÆ c[nàRðUc\—±dçàV›ÔraxN¯®e™ëˆŠ“¸¹N³‡Ê²\0¼ÝŠªçÉYfôÎ.¦%Åf̵Ӗ·§iIù:Ž·Ë±—EdÞAÎSyàÀc#¬¹HøI† w¤bVàhÆ¡¾G“ÔaÜ5ê²kú¸n̘,é,7ºÈY ÜPçê)­4ŽÊcêŒÍ€uÄ÷¸·ËfÑ¢£ëyå;½mVhÕ#¡ÓÕ·Ó¡õs¹…<Þ·óŒQ³Op¥‚¸§Ÿ“ռ܋@qŸóŠÝ|ð)ü Ÿ¥Èï¢ygìÁÄŒƒÒGÁ,”§öª }ø=}T™Ò#œçoÄ·¥G¶áº¢«ø†ï.Ðh08ΜH虽ޛ ûˆ•Ȥˆ°_3{ÆŒFÍ…øÖ’/c¾»¥’CO7gì+ƒO·ŽKÂ)£JÒ`‹¢ibÅ“!Ü$¦x;LO ²7Ë Õ£—fħI,ÆöP,ùõ8 ±`“$19iï-ÖðÜ5J2®5H8aŒÀc¥xƒèåôªÍ3…•=(é…Ìyãîϳ—ò>0¸ˆ;b…Ê\ÈI–ÓÆ Èjerª?› ¨\#yŸò ÷}û|ØSÑäYx´Ò¾^%äJšéA µÍiK¤NŒ<^xÉ|mÂŽ,ÏÅMg†“ÖÁÚWmqà‰ ù~¯ìO®0²„°OÒŸ¡²JeHÓ=‘ä©Ñx‡Œ"³Xö)þ ¤ïEìÝe¿êM!{¶7¸ïÊxŸ›xm ´{âÝ E€8[>-:‚Œ.n]}Ë-ú’¬á°5Cu[êÓ¯5KºìÀ!¾X/Þ×¶Z  ¬ŽÑñ”×õ¥ø(¹ž¹,S:¼÷8Eó ÞœfµØŽ4ºÌìúó؇ÙÝUÍdnZ,Vì¤N¥NÏ /› •Q…/^Þ0VVõ]I¼t÷V‹ °›zì;B1:¡„t#’µ1µ7üˆž Øc ÆžÍy¡[º/X<»ÍõÙÀã_)Y…Œõ‡ožA®{5‹¶C•ÞY;£©mŠhÓW¨ŸyŸÑt·«üæòM*¡Á ¨‘†ã9ŸÞ)î3Gá. £ö¨ãõÝ™§1ðÂÁ’ÝÒv¯Úå:2BhãÒ_yÞÖp¯9Í›”pr²Â­pwÚăô³ÌèäÔê§t¥Ú>/Ñ' àb³èÒ±‘”N¡ú;b€ ¯HÄX²;ƒ—w¥è‹dàk¶ºrü#%"ã Ž2k“Qú580ò–ª‘Š)&D6Ìá[$œ·Q÷QÜ[Ü>I¸8ØÊ7Ò[FnžEÔ|°%©$Lœ­zŠ÷Òñ²ß3\h >&·0WDry÷é•Ú#:Ç—êýjy½ãçÙ^Ûµ'l³‡¬‡F¯µmgÊ»¥ÝŽ,F#EÐ#ʤ0yø)ùŒ«C]4Æ ÌÈ!ŒäàìÜý:ÃÞºm«?€ÚÐâK Ùâ9ì3+Æ>ŽÞ/lb–Èßš¢–玳ÑÕíȱ¼G— 1—þ¢FTØØãó£ÂÜcaÛª'Ó‹–Ãf÷D^×½â!¼?S·½W@ÞÓ…&>\ªLî¸KwV“5õ@¦¸úá¸b±¿ÒÙ¯‚Ð|D7òhMkQ ¯„rUÆ5éÔé¥÷eve¿´”y·Pž¼Ùçy˜SbÈí¼;ˆø­%ÂÃÒe½‚}PšèÅ™§âë´ƒm®Œ7Äõš·Èš/·]]~I%=ÃW‹@®‹1nW¼å‰ ¼Ò‰vãÓëVPõsgþ–ŠÑw„5 [òˆ2J­©{sœÝ©=…ðpë™Õ ó˸ȮæIñÆ(Ž.lŽSjáe§¢ud꡾WáöX\ë;¡LàrmO}  –þЂ4 ûV±âìí£á#9wÂÙ#ܳk.G—'"9äÏBWœÛtõÖ^G6‰[æÓÌ?¼ÞÑm‰³v¿â¬¬,)æ¼h#qLôhKb¡Çr²uŒ¦¦ L‰áY‡‡Ç¹¾ÍJ#¤ZÔm°pÌ̈x1sÛÀÌiVýÃ=²ÎÚ:)ðgNñ8*~Šd›K!ÓïzcbææÂsÅÆÀ÷wÁΉýS,þfã¨Ñs6ŠÚü-\™òF&œ>µ-¬Þ ž“É~u’´eŽ!çàsô®M—´Ëj§Yü½žµª¤pñ¾ë°+ @`ÆM¾b”èÆ ã!‘ÉðÇË/!(vÖTì°=¬Ë*n‚a²Ç÷€´$òu7»$1à97$ `vùÁ–àHg€ÝÆV‚æM"z`ˆH[J6ÕÑ™4—âÇ,qÉÉ‚±QÀ¨:w‰|—,ëbvÖ®­õôyÊ—z&¦¯Ò¥f¦{!-}QäÏÆ7nõ) Q;b Ç9Ãc."ä™§ K‚‚o ™—J9§&„8ª¥ŸÞ”š»Iq;.çƒǾڦ—øàªab¹§(… _!§½NÈ–Ü_›Jl‹9bN$´¢Ñv<3;f¸œ•E4<ŽEsd~ô-œÏ ô9ãˆÔ4Ã+ÇæÎ¨á*_ Á‚j ’¤x[ƒà¬îz+k‡‹vó–óá´Çúõ½dåÎÂìñå¥C*ç*wÝ!+S`¶pdœ,z„ÆŽ›™V‰²íUÒÈ%¨3ú`s[’l@n®Ž¥8…‘ð©ƒÖk “êÌä"@;~&S¢zQoíÞ.‚¾×”4©:»Â–X_Hs+9yÝ0m@Þ뉪?~€TBõªEçy·§–De¾p߬AZLHlZ4Xû9CÍ“ÝTá ƒ¢€1l‘J0{øš«§ØBØV§ö:>¥ÃŸ‘˜ÆÙchÅ£ í[‡>Ü`"•Ä@Vi.ÅÌäÑéŽÓJÊJMïf¸F8Y-3 ³ËÚØžd–Há^?ĵ÷p°dÍ*3Ç ðF¦°ØlP¥@ªÎÃáÑr¨Bçy‘Å­Å`ú”kCD쨬ðvW¿zŒÆÝAʼnO\O+Ü2ä¥ç>h™£Õ ~:)çÅr¨‰³œ¥³pÏl|\Ö½¢b£Só0—[:ÒÔ‰¼7ûÜ Ω´@Î×ïô–›´šÊ¸©œóÊàñ¥`xçÊ↴q¹ÜÉ?}‡m­O3’± œŠžÅc*sv³‡»9“Xä&[LÒæÝŸâyŸáXcÂÜí:³Ý–¨õ¸ù%OöÂC£Ç|–ž–BÚù’ÉpûZFÆj%Æe‚BX`®U"lÞã&l‡x É·7ŠÕ/w€)0—º'MƳ÷UÛx¬ ¯ ª@Mʨzy Ôµ¯‚/ú»7œ‘T9ýîäÀª=ãh¡(Iot¼EÀ/3ËäÆ0òÑ«íHë‰q¾œ×¾Áˆ¢¢é†6\BœêwðH¼"vX‰ÁŸ¢Ã«äå´ ?ºË•¦«©”ä&kH:ÃCºE‹hÊ)Æ"`yŽ»Ò/ç(+.Š8Lú~ˇ ÞéÃË£ ô%ÚÀGY§õ² KÝ9û%˜œ’no¡™V4`ú …BV?ÇÝM8 ½p¶˜ë‡<5.âˆÁÆÇµë‹LŽJ½Xi§élO-Š ³‡¶Þ*²SGD¸Á%ÌËÀw‘d =*îr®Í[bÂÐì†èUøèxu7ÜçŠ1ÛdŒÕƒqŸ r`’½":çÞ£‹ê¬†"Tu©ó8â0z…nžò ÑŦ[X>Jž{hÀ¦N‚7²€Ö.ƒO¢g²¨¼µNŽãf“ò=ïZ~S­¯š öê¡õ)lòÄ®qün^+¯x˜jrÅ×HT¯é•»>EB»#ãE?( Ò² –÷=œëw`Æ'—H¯ìQ$^1[Æ‹J#ÀêF'&£Y)uâp m’³•n:ò¸º÷ÊiD—ݪ‰Y`á{üˆ_.(ÄR½ejŒ:÷'ð˜f;S¶P§Ùü8°S–û­‹yÍÌ “)k˜ôªö×m|Gïq¼yòÂÜTö%@Iðu‚“')î¸Oõ"™‘÷xTSKØõŽ©\š$¾­}j—b½\óây©«½Œ9iØÖ†®£]Å^=Ðj?r}s'âl¦Å8çmw]НH<ª=¾-ÑJ$Ø3¥@«hvµx.Ïr7\aÜŠAÝ<}ˆZ›×)¿³3 €×³‚:/{NïY)VÄí ›¶l©:lÇ2¸Ô ´¨;?äQhd±ávÄXñ€5@àT~Xm[Ó…Êê])4WW£”³ÓcKõ'Ï,ú¸Ç.. »}|  TX ÷!ø–(YÕ“1Œ.xê¹Ëˆ˜5팱 0jaÔÅ’Z¨€E2uÏúл ç虂9ÆAM˜®Z0 Ok ¤ B™'SXÏ;ë}ŠÈ>Ct¸+;aÜ0„<ÂsÒÝwË¢ZJÞÜ«ÁÐq´&~ƒéÐNÆG§¸o2W¥ß!ÂðZ'„J¶ ½å×0ý*iôê¤jƒ‹ÅåXÞ˜<î’G‰™òÔÞ° ˜ +¤ß›GÇSÈØ\–e Jj•¦®/Ú; žB+áàÉÄðMHmañviÃÀU« Ey“rgbe‰æË»Üy/”æ t|¤pËŸì1¢{ñ"æ9b"ŠÖ–%¹g®o >ÃRz™˜Öšs€KP«ËP(êÞ—ïHšV½Á\•÷˜Ê§Yú¢Ç+ ç¢Ié<í2jNµ¯Þ{Ä!jÝÛ¯Ðßoï*™7…%ÏÓeà-° ¾g…·ævLTGˆXaÙ*g'f2F&¢,YgQ$…²AÞÚ=s)â|xãbš:iúÒwtœh^ˆ¥<¡÷L´Ñ33ç ^4ÁÄì¢!.uû £Æ•u¿^öb¥ó…`Í /[gŸÞ|g)¢ŠO«úh:HT–Õ´±eu‹g(á\3‰w†<ð0ì=Ó ‹W<—¤¡ˆ9agT¢@õn Ãoxëa=ÐG¢ËOÖÇ[°EdÚ“0àeæÀÞe™¹æŸ–¹0TÀ6޹“EÙÏ6G/ØlâPóÅíÅ›“c^´T‰ÊèQ…" Si¼÷)'üÞ]söÛÈG­{Oš™µWçšîlÖÝ_ñt Ýœ™hC ³4zçpkXÖ¤ ¦£;&´wçu8dQèkªE¹}ý*a®ˆž tÑ’»Ý< Oœ—=éañ^Ò]‹Ã]atHe>šj¯K2ªÅT*FgNÌÃå|&H2‘ê.¯zœ¬^@•ÍñLêQâãöºÐ¬àq‰´À¥Qr|éQI ¢ÞG/rÑâÖßÂ]»£y—¦¢ ÛÞÈë ƒ|ùp0}x¦÷éNU¾,ë€QáðaÓ{ŒèÑëͼÈt›«é=h©ØÊH¿Uá¯i´ô¦ÉÅ^æˆà5j©ŸKv?‡Di$ÏEÅyj„Ÿ‚¢Ïh4gLäÔ1Ï]5šÅ—_)tmàÕ¸|›Ú¯`)êÉÑ£ì…8ºVâ·X»žYÞ#º^Ïuqº2ä5]Ȥ6ä™ïÒŽSrZlC‡î*eNù;Ï·ëiÝܸëo(!6ˆàåm<[µóõŒ!DÒ†”ðdÇ}4¨^ëi‚-ôHbßÈ[a)³P‹šœÕ[pqE_%­—pyRÝ€(ðòł܈"Ùæòày å•<ßÎÉšD @ÄÛÆ×ù…'+¸>IÔEÜÆ˜½ö˜„Ò‰,aH=æµ ‚ªù\á/I¦T\ÓtËåNŠ ­åà ¢i¦£ÜšÓ‘×å͹ž¬‹Ê§¤ø3г›TЃ>^H/‰Vqyp¤i€}èþB—šÐž¹’ÞP< Ñ4y• ,äoÀå€`R†:OåU°³a` 1¢[T꽜vÔÛ®‚‹~OË\ê„ÀBýኻy·øðVAXï3Å›ÍZ”Y:Ƙ«<´G=[ì!mîȘjÁ‹Á.ªŠlÚŽ½!ê“™$õìnÌòq[šx³É ˆ;¸š‡²ç[ÁV=/.ð©×‹°×`ÓŽ‘5j2 âöîœg&ËCø½¬5D,š‹ÓqÉ GÐb¥'­…7EQ$DAöÕ«rzÅÜ/oKÖª`0. ~ŠÊ¦A ŸJ)làÖ’.ENI’k‚8í.­Gy`È£àSüÞ{ûûÞ{?ëÆ”¸½ÊxmRéªÍ0-]Ðp¾ÁŠþü…èŒ æƒSô—WË“g äƒÛ}uÑÚKõ‚’ï ¥è­$s˜Ø½±Ù•¹¡Çˆ– ªžÏ°BLuétæyó‰ùà ,@r!j:¯;Ñ´[µÐxD½Î‘1OÁø—°·ªŒÂne«Js=åÀ{<µ1hD[L| nÊcw ¨ý),ÑÏ\õuv‰,€*ó˜ixÀƒXkF߉ñeb•` ÷-já" àäºÉ$4ŒrK4Ï€@¿Öt{€X€þóú)q°£3MRzå£Ýw®/û½EЋLj ¸öÚ¬‘ëd*„c5D­N±Oƒ©ªr˜Ïãi8¾ÕqAeLAà(~uó¨\¼ ¬ýäp LeÚ<‘¥¤óÍU‚VçÌ%š(q{é³Í¾zï½rÉ÷ÎØl@GÀòs°Š›»jœî½ÙðèYºƒi9Æ ÅÃ%Ù§D…nÞȼ/ýù‚ °m:¶^Ý/iùp¾è£¬ˆŽ: FV­´Žœ#yÃògîs[cïýÎWú>[a;J³¿Ý…#÷í%ëÞJ@F²‹06¯–ÁÕ–ÕÁ6#ήqÀì.¯¨DcÞ3æ{PUîN!JOšU§YœÆPC3,ßbˆØ>\y³ûœQÈç õKW|ƒas vÖO/Ÿ2(Ï Å”_,¿)…ÉdR`´It{ëRˆãJí(½+“òtçÕ=ú“ƒg£ ¾Û–'–ѕ֦Ö)ÁA¯³ì=?-~œ@ö {%Œõ ¢Ýu61ëuå“kË¥#ì²SÄí|JZ4àÓDì´A{E§yÓ~Ó<„F ïXúi9†ÍOߺ*IÈÂäzý.Es ;„q+¢E^ƒ0 7Áí ŸXI÷Ô§¸ì3¼/ÅŠOÍÛÄò>Qñ]=‰ ¤k ¸w >ÑSï%ŽT¼r_ÇË~7'ýâ=:ä Äq×§¡"ˆ›wJÏý0ŸEÙb¢(,†ÏtwŸJ@ð#¹³Ã.¤§anúÀm´²I H ör½·åˆJ°%²³]OÊ­S©ôêDøÍ€(ìtš#¼áŠÇ3E·¹í‘)«A pN””I· ,0&kµ¨w$¤ÓúØhïÑ¡{Ö¤n¤žÜÀ`¯˜HÇ]ªäAÔ8è/(ŠjÀ8f;¢™wòdSÓ‹  @»Þà°å áì‹}åÏ~æ­âé¶lMér)µkÃz 2láÈovô†·€-L&K·{—Æøñ? „ž˜®ÊvЇôeó±f"ÏÑ ê.‹U¾“·³Avèq6œa—ó6NêáøxÌØ-ŠZDSYi]tˆU¨)Ÿ4W RسªV¡zA}‡í¶ÔsÔ¯BÆ3w!ªýêRÝy•†ØÜÅ^`]#àáx+ëòÀÎ:{HXòÜ»Ó'[G‘—Û;ƒ­\>¬}lþä%V©¥=l³l--¾{Tú&«Q»"o¾0¹G»xˆ’Ywú˜ÞÌÆdU‚¼Å­W=mÁï51À¸uš7hÐ`âs·}Úëý²'v‡p L§ÒÅ_6kqvl#g“?@®P}¡’¥¤Rñè©–Œo ì3Ðs" x=h¦¶÷‚J•‰Ùdúöúkó3F‹cÆW«Ì¦åÙê|’‚‡Â¯Æ( ¨à H×øúu”lã¦V­& ¬=FA_­|2HX.†§Ò«¬CÆ©ØB½Í8‚-‚6×GÇÄ%ÈÐC%?7òD®9ËW¯˜®=Ó@^÷sÇ\»ÄÈK•Öæ],ÎYÆ ¼G /=±|ÔUæé®µ,•9r¥€®°»Ï3Àªà¡TÇ„hðª\1Ïó@Ÿ–.G{)>~§þH”Žm ‹ÇU®eìi¿p›¥TCp礌¶¤ºÅ¥žØ¤7m-7 õSb­í:é™jã]àrq‘ôIM˜µTMœÒã±áÚ7ߟÑ]q§÷é¥ä -Þál.ø›mq¸°Ts—¹u~sÙ˜ ¦ö¨7–Ô©SðtNò‰äAËf]¼ìMNfƒfyÏ%ÍŸ^ù;榀WRtuD@½‚„ÌU¶Øo@¬npß›bnë©ÐȈ%…þN ñ¨'^ @L…OmqˆQš’e6PÖúñr=ã‡v¬ó†dPËÄìžvL¼$ƒ¤¹}:é§—!ê )Ò·k6Edó™UòF½×=Þlòˆ1/hEøÉ4¡˜EÑblå‹6œ·|(—ôV:y™iàÑ#J/GñámÕt¤0=Æ»99èhù)²l Ç”"›”Ø[/ârŠŠ¸ä®süàÕ¼æŠT%è,$ÕÕÏð½—÷»YNÝ·§¢à›j´Ï)¡[÷ø½xØ×È+OŽ+Úrd·j©õQ=×Îs‘¦6>ñÆ}Ë8éK£<¡‹rã/„s¥‰1 GA Ç2o2; N•s5³žÆÀ ¦<4°yÀoSs$—%BóÀüƒð*Ïž³kt’U xÙ®ã"y£¡Nsö-ƒ¿"\x} Š¶Û‡¥ž½”yÒ7÷†÷‚FD* <ã§ú”Žpú#Å!€1|ÆcÏýø‘=ÔRmd›'rĆ]íºðP²ÜsÛNhYyÞézŠù@ŸÔ¡©®)ÌÊýŒû"™€³YHø|YLbÊÑA‚Qecõ‚‡d]'-8à§Ì>ó˜9e•QJ-s‰Õ ï“Z]‚ˆÑ€Gí)O`G·DÒ™ f|£šŸ ëNg.-Ò6úº³ÍYbq»m?¦‡³ë7âŠa"4MP»)pïI‚%û¡©'ÇRÑÈÌìœ Ξ" íG˜LNèx‚z‘óTQØÍS(VðãØLÞv~ QXY ©8Ë]¨õAÅ™ºîÈEÙ>ìë±ÐÛ×$ÚÆèÚDŠw$ò¶&V.â—Ь¡&­ëÑäÔÛ ¤Ùr–L’ø<58¬Í”×nެ•ßB£Ïà/×ë‘,.û œÑßÊCg® \r8ï+|Ý d0`cFeª‘q%´xÖ2ø¢¿7=P¬æ•ùè˜åè„ÔèAqzJ<*.^®Ëði’ħº>– lD]TuÀy)¯Ç42âÁXv%A&—šh8¬&DYN¼Ÿ§Ú,–qæõð9!ÚªªØŸÉ!€ú¤?Ý€kì)*†Ë}2üœâ­–2 Íâ³Gå’+1³Íh4륕„‘I\%‹p÷ø ÇŸ83ÈÆIÇ„‹Æ²Y™¤A–³ ΑFy¾Õ{PXböDn¸ùOtï´"­—^£%ÍOOSháJB& .w<䵬g·aOw^jvtÎ*®Ž¸}KísP4: ÃÔÅ}«hW9!#·Q§QôJíU£Í˜¢¢¬ÍꉖkaßãçàFèÙV6 Áµd´/%0Ôs=‘”FUa v»}’uñüaj¤¥:µ8¬³ÆÃ!œ€HÎk<¨P^ì”, ^¤—˜ÂsØâö VÜñJÞäbÁøƒƒö‹Á‚×ú¤áaÛøÔC*q&вODR?€;Óc‹<÷¡b;–]ÕÆüÃ%ɇ‡Ý³Ÿ@…œÅ>yh",Z\˜¢¡ÄÇ‘eYräs€‚µ:Œƒ+¸:PºPbk,!¾®W–˜Íyê'0mŒoMàl€.S¼îç [õO¢;fƒ ýØF< ÃYùÒ8™) Œ1&¢ì§ØX?}MÕ·'b®–Pú!:‡gGÇæaâc¾¬×=áúL¨”d3Þ3Æ3™çI6ðlÔäÙá›»L‘KYг<T—Íëwehè›Ãðä1ÔTŠ—:4T¾‹ê’j¸†÷2‚*^½îáÕÍ*™ª¬€7J `Bý– p̸ú^ã«Çf“¼wçô »è°˜÷iÄ*éMnÜk›ÚR–j“wÙ5>/j+ùˆûaw]ìB#¾Õ0¶ k¨Ãq‰ƒ6µE \_Ž&%Å»Y ‚áʃ Pd×о•²e*¸'sœ™Átœ6R —nHIdxÇØk%ˆ…¿äö<*‰^¶ˆø=L‹B¶©@§ >„'óØœ™À…OŽ•d¹kh¶GƒŠ­Ð¥UpxÃH[†Íx÷¹ ì£B³Gl¶6«å'²éù¦ž=è]gŠ EÀiÜ`‰L®>|¶¦ÅYýÂ_#/s¬:h˪sž «K'\Û¼àêJ­B*9•5\é”ю磺Ãc E:Å!Åï™±5éå€G&äÀ2hyd‚žGÛ“ƒm£~¡Þò¸‡::^áµÇ$oY¼‘Ñ,Áê¨`;{«]^{¤qùµÜöpù^ˆï!ì‚‚—tEç„ø6¨@·=m$KÅ]þ)¹ÌHœ¨( ¬W®W}ž¼¡‰æ×û8¥DfÄ$ÀPËóiŸ}JN?G…€"OÍÄ[a”êòuÜÑΞF¥²;§gïüÉn¹†™ôX¥/[(>ÜåË×ë’=òj0¹¦[Ö&f…÷…‰(T€·=ŽHê$µhŽ»9e5³œhìÙsˆžŒõé©'˜U±Ñh{ùØ"kè:Õ„cçµéƒDçRÔx 8ðZŠ7s4^jÍëÝ“I¿$®wI©O$ZRÂ,†Z°ú– 5µ_ ác.Èœb$SQ(‡'>ce‰Uݱ¶¯âÜq³G;¨£óóD¾ø¶È%±¯ePÇnâ…¼faÚËNê, Aà¢j½1œä4»‡6Lêâî?sœx?Å4u–nL+w),Jþ««z__•Š- øè`>äoÑù§Ï…Æ{6hòŽ2£ DßÔ­º¼9…¨[o¨õY’פEÃX±o6Z½#ç^ìÛÂ&µ£8pcÎõЪB‹Rô =;•©D$Z"³ùÏêI‡j™NãÝ[ } lÞ»™i¤É鯙m£§VIKìIB‚¾ôô]áÌC !ž‰9H¾9KeˆTSLæËG—>S㋊ à%l*€Ñ|°q…ïõR¶ØÉ…]tÄ‹}wêe0ÌqnØë"PftL­“žC½„é!ã~‰»9ÖlZÌ ¸¡Îm÷ñù??·fgJy¶GU+‘µÓ'‹ÇF›AÌ ?ï¡ísŽ…‹;)™Õ}*”¼`¡ž(?âÁ”79³Ð Ÿ²³ÏñÁõ‰2ç{Im^@osûÄÅ$‹¸É0À™›ÔM¦á`êinFóãqÚ´‘âØ6yÒŠ2¹¹©ÏHDÁÄtz8t©€¯T[‚›‹Âj¾1+§ Ï+Þu‰×1±·wÀN×7HvXœ¯"žÞËŽ|l¾¸ºð°=Rxù ô0M Å®¬)Iß$AÆ'¨¯9K«kH°ßó¡ynÙb)ÑD.#úuòíÈ*ØNXH>½+Øãã)¿âGs²%A/Ÿ“èµ)ãÃ$sÇ×N££ü\Ìä‰är:·C6P¢<¸E ?ÛƒXfIWIÊ…xQ„ûΞ_y Þ{&°„œ~õsn¿»‡#Õ§òÀ°Þ÷ªz³UëæÍ£3—'­8ç"qð)<ÿ$´\a8Œ$ñÕ ¯2|b¯Þ°ušÛƒgꧯõy¡  gU65'ùf@Üìƒõ q»ut[¹j1s-[/ðP¤Ö¹²½ªµv5>TÐÁ‘;v½—–¥¾sÇ.[H‡hukh¿WÁ‚›™—/·={Htôq´HI«nÛ”ƒ‰ÅN«G¼b€³ûÎwAŸÒK@gÈc÷Ht¦÷f»¼„GJÀ³^À0ÒË«{¤¤Ekàñ6J”ŠÜ’ž@_öáK˜É•†g¨+ àÔÌáx lC<²ðd÷ˆœ¯¼”Í3ðµL¼‡J–FÔät÷„–$mSÁG£w'É …ò?RG"/t<Ñ›BŸ0 2È F¼;`¤+óU0c~ç¶™n\»ž¢áºEÈ&[ToO¸ñ=@›­'ê¾2i}a몼Ä̯žÒ9¿×{}ÞT©I“lA©”R|ÀT¯uê µ&¹Â+@“q£A- 𭆇¦ˆnÝæ"¤MÉn|›Í©ª8NXPò šÉóì§ï4œ/iAÍlè«J¥GGÝ’‚µðÝ¢+Ö³²Eÿj¸ð9\·¬½Òæ&aFÐåzÄ~Tºj²®ŽË/ÙÃã™KMÎJ¨Ð¼4‡”v©yònpãnr°ÙQN€}cï1e¶4÷»õÝlÐç*©€hæU;y‚˜‚%:˜´¥Îñ2)bI'#'5é8*.ïì*Ÿ˜zT4¦˜%®€ÜœI[Bê+œs,NÀ:˜{ ”x-q*Ø1â²­D¯Š,Zk+)T×ÝiÔÙ+ÜžúZîà^ÀÖ@@®“XHO'Ö;ˆ ‹ö¹&Ìçã)ÜSEÚoJž]ƒî-]¸ÀκäSÅ®ˆ‡*óJy¤Ü2txî4 L<"2‡ð XÍ;dN5~7ûžÜ>{†X~¶ôS~LáÒ·£ѬÓÈô0^C\ØÇ{ 4!öª:]ëá·ü>Ç ç<~dÑ]ònk,C`î•ê=Nš·kOô Sp±ªEÄ ¤Û¶õ‚!­NjoÆZ+uC½Ð“Š_ôY–?]ö|P5Ž&±±Ìì¨i"§s,£ V²9GA·{e,¶u%5hÎï¬.aQ»#çå ½,Üdc~™ªee8ìTú!nU/SÓƒ x¦Ã`½´íÔØ/ª±¶Ÿ7¨É6¥¶ïðJÙÃA~lb`-*‹0žåMðÔïBð]c=zÑã4½+Þ”'ìEé¶Ìcl˜`Ï_Êðñ•·J/ˆ®¬œßÖÊâ•Ĩ=‡LÐNOh‚Cª×³2À´AY¹øû^ñÐ(È»5‹{Šù RÛF‰M;‡"ø^QÁ"ð§ñsàHÛñg/º[´ ç*ÅcÈbRy†«»Ž#¨åñ‹u{±±iOS¡€í‘²öÓw»ÄœÝBáø4¨ô1ÄÎÍQfÒ6¯O‚½áÃ!FA<1уÒÝ^Ôt¿e†D¸ì%µº«k^†€¶›HÅcå“Mw\£÷ÎáNÄFö,1ßZy\_:ꜼÁÑ]e[ } wƒRŠ¡5cSdТõŒŸ ?ߎ\o+v(‹7ŸäÈbÅœâHÃñš-Þ4‹–²;§ÂFWÅ5/@Ó1MÍÓP w> h5£e–S´jæCÅÑÓðGB»H«T ÙBŒ Õ*µD<>7ñZ^"`^ÜhÃïÑ㤯ÞŸµ¤™{r=.Òg‘°ž/€¡%²1®àMÇΗŸ¤÷)A½e˜¾žÄdŠuÊX¦’Ø"i7nbWHgÉí]%}™¬ùìQQ¿ò⼘DgØ)sÆ~kpÔÄ×P(7Í0.WÍб•}1IJ°ópl½@ ì<êŠá$Žà¶ïx”#«‰»úõ“Ç}¶…”õà(³eN§1'Âz¯ß8k¹¼Þl ÖcW»…ñ—wÇV³ÌàMÚJýì1›@<w³6.·"yz ²‰lµs šd¡d"FäMúÙçó®c,›íLÜj/|bÊËjŒê…e(=ÛÃ3Eì /Üe;'øYÓc;¦6Ãã—ìâ–ï¥SËð [w&Ùª¶ßé/‚fùMí›Þ`ÙGÜhw •ÄzÓGHÙíqRÌ-´Óá¼O2}7bT»6xÍ™WÌÀÂaýtæA` ÍäFŽë/ f U|øª ²ÞÁ²Ðý“!*°¸J S{íc¨·ïáŠ*"”¢0övŸß€Vû â˜ËŠ™ûN$¶´±Ð;@gZÄç4°Óaˆ¼\VÒÃðBɲ¦¼8fÞ¨,ìFð0ËK÷"Á–§«ïñ›h{òÞ_¯$ ^¡È“z‹¬ÖaÌR@ñ^{CÏ32¾|ï*|Ì“µ¹Ùôeíf[‹Fã>NZ)3hxç³ &‰ýÚ¥¡9úaM·¢\ìv½[}ê/·WŽaq»uŠ('‚£Š º;Tçê^.€—ÔÓjÝ_2lÄc!J¿²ba‡ÒyÄTÏ#gr‚ëdôñ±l¨²ö§ ßç8ÂÉéý|o–rßÕ,z–V¿Ã'ÈYdæ‰î¥ø×N”¸Kµˆù©™ »–À†S¿àœªkyÉ=ìÌNÌš˜P„‰ÂâǬœ‹~ªÚ&Æ#Òï›bµûf•7YrNÜ¥¯!yü%훡÷B§ÌcU zÏž…gbUÏ{›P•žÇ˜¾¢sΜV-|^/¡'„ž6’¸a¿C|è2s€ô4¡òqÀÎÊ1}“Ij9ý^ìï0èe¶˜6_Aã’¨Ž£]“ðK¡“zg´Þ,›ÞkQéN'›‰=ÓI)ë·e .h´Lî` 4€xWÇl.l>Ó¤zšR«U°/ƒ¶w+·þW.üçŸÿõ?Åñû×äÿÂþþ©Œÿßzd+§Iù“}gˆ`ãBûšžK ¦@ff¼kÅYêÝpNÊfCvFÒ—SÏ®´ÄGàËC?• ðóz³kÇö¸çUñôÃepä§þÂîtY»‚…ÈqnÁìZ:#Ç÷,sD÷dÖ:¬™½µrõú`ÎuÒPð”n!¤Îu ÔìVÁŒßÒ—{}æ8<7û‰íU«zî!àç"^È*!ÙÕžïáäE Žf5¾»g¹ V]$GúzÝövùÇç~wüÆí›ûùÁKÏGïøÑ°$Ã61T ö*Éèa“`vj. ã:5êK¼#)¬½sð$€FFK"‡øøàïÞ@xÈ/[ì'Æ:C;à§ï¹X¢L^žƒ°×®„‘yGÖ³ºÊºòÂë2y¼¹q†àÞdG!{ß}}ò÷SÓ¨²·ôsãü¢·| oÚÒh2™ ý¢S«aS—ßF‘²§?Ô9´€¨Òr·‡cŽ: Š÷47ý gÑOcr·óîÞ¯Ïö˜º×åWOoRƒ´·EòÕÔEk¾§‹ÊÚkÀïôžÇÈäùÞ-*Üc;µ¸çaM_³¼¾O¯Èwôü ’þ ÊÓ‡csJ½ÓT£o×é!§Ãéf¯õ“ fc¶°Í: BÔ…àiæéª|úb¿ð6úö Õ¬‡.;QÊ&¿>veŽ$°¯_.Ôx‘ÙÁ¥°Dšœ9F%w9Ì”ø>A³ G­ç胸ܩ(Ûñ…¹>ÉݱGDdŠ\zÂýû²âÚ|ÆWT‹þ®©0N‚àxâÉŸ©Ô>î€#  }·¾CÃ?‡Êv*o“–‘k£ô‚œ¯ÒË Åyìl¾#€Ã^y&ø¢ÉiA¦4dZ­òÍÞMó‰|5wø^|ØS2&r$:vl®§û~“à CLÒ¨Ä;·¶‰«Nóv,«|õm*¶ËF5ºÓ ^?n†ZåkÕ“«^{UOB¿jÀÏÇË-nØ£­‘Ê%¶$•äw̪Åj…ŒÖ«EH#[J †‘g9Ô@®ñ¼ÕvÍîtÉdÛcKΫ·o%W-_µûÀ'ôùŽ/‰Ü^uƒº[¬ï!¦Æýªãv—ö˜IPÈßB%=k¥#}ï °›µøÊ+ÁTZŽ l²Ì\öçl[1Ï¢^ƒ÷µ–YÔgŸOZ(<‹°{Æó=±ÛYsBÓŸŒ¸û†°‘u9ÛìƒÖp Qh£heß'ŠÅ.ÁVׯ)lÍcSx¯æ˜ oXkI½™¾*áÏ×í´´Ïô mŸPh œƒíίZf­ä=RyD½ê±ªvÏ_ø=‘õ:>BŠ·96´^ —&»O§ILú™ôsÈ|Ñ©Ÿµ¼Ïwn¢ÎÓ%¢ø …HWé„aîO×zXÖ5¯Ä)mV,Zo ½Ip²²[ÝòÞó­(XÕðrºÇÂæU pÝ1Üu¾xù|ñ ûöö °¬âeÞ#·zデÔ¶ò3Uç™à®®I&µè>FmÀ¨IËÅ›.‹ì‡\…Gþ`Ä33ÛìhA‡è0 Qìâüa¿Ï7£ß=œƒÃc@EýVÝ×Dä&¨=›8—ŸžŒÚ/íl½Ò6‘[BLkèÜe k­ùgƒtö#¥ÊÏä © R8ä^fÜ6ãJïÏŠ>]`|ÚoöjzcÞÛו·æïYårÉcE ü9²#F¾kÄÉ£=™-Ë-yJyíd”îêkç/¥1ÞDûi>†.v-'éÖÉz;eò«&ûîö.7¶ø5 Æ­ ‹ÙÓ\G®™ÆFö <@ƒ'¶æÅU(5 woo}Œ‘‡Œd|}ÊMªóª’ŠÄ=Y×5GÖ-Âwdú:?µçß äÁ›“©Ó°¥F½¤˜½lÏbQEÒKøUWø­£=í>ë[ÃÑñ‚ˆÇ۹÷.&ë0Ånߺái(‘ê «ÐÍÛ­©}A}-EEx_u}Öµ]dgyôº@C¹íbsIñ]ê!·þôò™y ýÀÂçžô•¸Ã…eë¥Õ Ž£–ïºÛuå5¥Í«Ù¸Õ%aßm’ï‹ýgeyÓA‡ç%„Šx²B7Yû¸ÒA­ñ”¬{¦ütÂÙ3/zFS®K[ ªû@Ytó•uŽƽ¤¬"Aå 1È©ÈiM*[àF¡þ¬íÓ7¬ÚŸ«^lÜ4/ÂÓÎåj³çâ »¤° …?«c;|Åhó´¦xeFO=\~zemQ.û³¯•—+ßr£ß‘£y’hvAg¹ 3ûPWjØò‰ÂöíBЫ°ñùó¦='Ž®Û:`FË­Ç6 ½qS»ýšFfãÂV¦47á§»R_{¢§!ê¼  ÁxèàÍÅL{SÈÔ‚r‹QÎòXdâ)jG¨TÓàÑó8ByvEŸŒê§ûÌúañe¾2x°óD¹¹|%œ„Ñ|Ýö ̙컣£ÙI¨…÷3¿Ç›ìéÈ! ï-wmÏ“¥Ñex-ïÁe܆ æco@HSC2‰Zu<|¨ª¸öteËì«Vûô!¥CyÛo ÚÄž´…·—[,¨ÈÀsLš¸ŸàÜi5-ùåtî)¨ÂñP7s¦D²“ì ó-EF×#On"1*­Ó–I˜§Oú²¨p ™·”_Õú§#M߯ÆR÷Ú$å#°á•mkE¤ô$ÊíP“tW6_|+u•óö§7Q B*ö‘?*¶Ms¯Â^§x³›Cª,1Šs<:¾‹";ÀY˜‚£XÕ!D˜Â·>ëýô¦g'–íÍø \ÝÉøY*r²(ÁÃVæ><;–Í)ú”sZ;%àI˜ÎE3³ÚM&Ôr^‹íÌã·Ô£èÅ—¤m›5ècnF_Ç÷l…”:´jÛE·ÏµnƒT!„Óäù»{ý޶“ ò`§gs´í¾•÷³æy˜L/Ñ8ªú:œ“ŠL ÑV¬†Tºe: TÇ+Œrb ª¸mY+Êß5¬#Eiô°¿¯7ÌðéWaÜGõ¦êÒê!Æë©z‹j ‰þ`œ3 ‰)†mc,%¾àñ{÷ûBk0Æ•g¶¹–.”X…Q©ªr±÷HRõH_lH”t¦ÓÞ”G{Û¥Þ:kæÀ§§—ÌûU5~:—CíV-Ÿg<Áy/";Œ1WÕzšÞ&ôrEæ«jH;‹eÈà÷Ô&_ýô°ô{©~'Å[õ6§¢ŸÞβ;ejKÄs¸vñzþ(°8X LC„ÀÚCß4òÓ¯ºéÓÃ,+i›Òø™ÚÛ÷>È…+•ðÅVíñÑÍ ’Ë'8*Ç ¾ïiùþ¾1ˆ£Œyv†(q”õ:»Œ­³;»˜î•ùEÓdG†æBÝ ˜©èÕ#²yf/cì³òO7k÷Ù S‹ò¼G”Õ•}ä\ïŽq±³ÅÛÃ!NeÄÁæ©Á©U*BSÙOÖe P†^=¾‡nxia#‡{Ñ ãÅEÃè†úÀEµ ^½(kvrÆã§äáWíüék€ûø–®·ŸÀvðjɈ.„‡.ÌL€½[d_vB ƒv~½º9MU®u?SJ[%¨ºãT0n´Ú{½ÄÅÔ:RM¢ýä‘bOµLð-#lΘÈ>¼Â1›Š4¾Iòûªþ}:³1äóRÚ},O­ßÕùØö༸€ÊRxåM«+5„ò`(*ɲ|"_ýf_¨“r•sð+Üœ§®§вË]RkK‘˜BÁíêïáXÔÒ=­Gv×¢>okåÝÁ|Õ/ß)̓äÁ…¾ö¶WCS@ 9îOºØóæ=ö<Æë@2Ñã½m-¦ßjökJ­@–ÐôŸnÏ« ò.Ñ{Ï­7kñ™Ý±6Ô_­?p6îèçT)hë׎•™H+­cF&ƒó°ÒkÏÜ{Júž‚v4¶bîH\ØüÂÂ'ßñ`"cÐbwÕ öTÖ8óMs³…%"÷¥´¡…˜S?ëemö¸ÊyŠ#%Ñ©þ>°xðe¨bÓ^§Â©¶Ïe±Ù†—êlib%lrÛ.Á£ó6×5‹>n3sɌՠsÂ×v¿¯‡ƒqûR.¸zžódZžw)«ƒ…Ò<È‹°éwùožCêú%7É%Ö–½°Ø}¢ú^Jã|¢ñ阑„QûØkÄP6nRµáhœ;[”ËL³âØ÷íE×{Ìð®òîÕÔØöQ¸ ¶ÿÌQÊw ÂÙ«nW`Ðiך‚M‹<éÙ0c³X/ƒa¹*²5ñrTÞ±÷õ{.-ç$ô…êw‚>* ®1Ù‹èÜš&ʹî’,NÙxɹª™ÔÍaÍmÔ‡¼›=ì &Q¦‹q÷ÖÑ“°ß·XŽ™JÆ(Y׸ׂ‰Ãp÷æûÖ ¼–w(’)—ÃŒúàÝÔ` ƒ½a|•í>z,à‰Ó_ˆÐ§‹nÃE" ¶&%XŽÃ >2íÕ{Aâ†4Þ£ÊLòÖN`+¢Ýì#ãñêT ã¨Á7Ö³g…~f­`ócB´oÀ‡¨°¨—}ˬ€¡µ2øbKr7õáEbïÌí£`; —ÓçdýøÓOaú :2['S:ÝZrÝ£ë8{$úN…Þ(Þú+L»‚®gó4´—R]«¢6Ò³°5¬t4ùçôi…FUŒXÈ&‹²½Ø¸~TÛ—·ÇøÞŸ„nÙjÖ¿ëßIsç­ºÀ^–&ïâ¾PyŸÎ:K®•@× @ ß9\aÏåÖlàPœ?Þ—¼ÕðÔõ"òiǺC…¶ØsqZw¤$]I»k‹S¶G÷ÓS*™¶32£%ÖÒ5[ð¹ŸZL…3µ2â6qùˆ–\Bd€c(ííú·ZÞ§ÇîV7:ˆ‘P×ñEƒÁa2‹ŽÌ«ÆÈ¦|ˆÛÞ³»–b¸´›§xÍœp·Ea3e–aùPøÙ”juþDFäæh›l˜_IIìU”Ž /I-œÜ)[œUX<9^$–m )Ž­Í:ƒë<\ÅÂ&Ì× _ÈȧÛ>Ô’žŽÛ¬aÅ˺F‚gâ[é~3ê7þ–c¸ ²I^ذÖ㮵rIMî­IŸz+ò¢yW°J¯K³qvfÁäcŒ[™„½MÝÉ!À¼ô‡Úì’:g‡§fVJ™ ºUHçÝd®Ë‰–#×6úé»ÒryªÇ´pΈʹ>éä/ߎ‚¦¤­À…hqW¦Åµj'›>…E€‡ò¯©\Ð[Ÿºmâ«ë`“0Ÿ‰G×/¤_ØHm^=BY°ž’XX6ˆ>QTôS[ Æ!x­½ÏláL"Ä_é“¥3tpä/tìÓ Õ¨Ó:5ÆÜUõœ8÷í7iJŸõ.Hu:£"¨NÓZ1Ü"°EÌéØs„Ýaåœ~YÇ OvíÂágbÝcäj…TP'ˆç6{=p©99y¯ s,à@·«ðÞsO`Œé§inÏÅØ ×>_–z1Ý$#NU’1a SÂåjZ›ã•û¼† |:õ‰µþÕ›¦èA‹O:b‹ž>pçI‹‰!%—˜žôæfZžðw˜õ’èQ––ù°ú´d&®¿ðfÃõWÐ8¯~zÒ#®D~ÃÕ%ûd;³QÛÎTr.×Ì!€4FÏÒÓÓ¤‚#Ž”·8ü:Їb^¬Ü§š?={ƒ4× òt…Ñtê®›R˽µÆT.8†Í3j6ö8[q÷QÏå½zÓ³b‘l‹{µ'"R¯±ëÁãgI£·t¹ö31*õsÁaÄ4×Ùד¶±‰{uù”LñNûÞJàN$JÁtpR•¦öÝ´ qs µëæ'RôéÞ¨ëÅãîUðf£C”Ì;Œ{_ …Ö3£NÞ½-‡T¡š#<9‹cš"¾8ãá࢛H °³¤£µè›ä¸äà9Ìø™!O^áä¥ÚNÔ G’}vòÖä-ƒ̼|†Uº v WÕŽÃ'ÀÒ\¥†«aü‰Õ§_?z»EÖè‰Ø€ÇÑ"2^æé å>•8MùhG–¶íN½è‰ŽÃ–Ë"¾K>߬«n´Ð×õNÖ´(Me xkÙ®¡•„%2;~ûðŠ ƒ/_À#H/¥ëÜHt™tYžÜ[2( x•o»M«Ƀôîb,ÎÈ¿•ÅŸŽžµüŒJÞ¿šJ›@qc}úH°ßóUuÐØeG²ô[f¢;À!vèÊ|{~6„IH^VqR:qüù8ÚîšÖhŸ¹»DTþÌ™ü°VÔ,AvÇQ“0TcÔ¡êÐ¥ûx †<.€®0-LÔÝ &È}Ëedo¥öYôÓÃ/¼Þ§·³^¤ÊQç ã¨xotïxR¶*ÅÖ&ú¡„'ìc‡ã¾WÏb›øùÊÝ*‰’± ¢¼¼>®W¯b´Ÿ½w3pJcóhýNæcpæo)¨À$áVô*„ŠzÝ2^'Pð3”¸*¤"Bà™7ýšTÊrÝC ;=úA ãcË|_ˆ }+¬ÝL¹s±3¼Æ[Ê©³R^¶3¹žÛ†" yî›UÏ™“eŠfC«áGZn$ä/¨Ó:^SãâžhÙ›*•¦l Ç›bÐ6Ë÷ 3-뎜™»}ZçҢ彪‹…õ44 Ãrêhù•ÄxÈÅ ×`Ч-¤êÊ׉†|a¦Ÿ~ï¬ÓSñkánãWÅÃ(Ð^é-ç›åCr;Èœa€[ËA®7¾hƒq":|òÍÙä¾g•å}7Aì4žf¦$qý®Æè§—­ î $AÁ½ÐCx'zþ„@wä½"`{]eøtîhS<ÞÞ2»ÑEQDZ44y¿OÔ>¹†ñt‡JÞ{HöîXíùô<ÙBB ¬Æx ç ZwÍäØT ^˜FÑ àˆ1àºÁæÙÓ-áé´Æî¥=S+·¡ñrt~âæ}®ê¸îº[ÈJg¨aîmñ!ÀÙ¤Ùä½—*ÏM¹Ø€±_p6zðn ‚%Ån¦Ÿ¸íNt%Z$@lÓ¶¸Ï0È3ëD´ÕU-9}­Õú°—$ýÑë}I:bRžz…°9|ƒ´3³Û´µ†Óá§œÓLl{bÈa™ž?sÁ vkžÔÉíÞˆc€Âiœ Ngƒ](êCiFð’=ï¨%8#wE+\¡¸¦`ö/ä¾/Š•Rj%Ûœ|—K1ãhš´gÒÐÀF2O:º 2 :-)Ô2$W4R§ÎŸj[©¿—8 ž­Šg{ ìËÄSrÔú^™ÍóYLðÌŸ™6’«XOhKZ×éшJˆqž#&¦Lø™ñ¨¬½a²“Raà˜‰°;ا·aŸÉãû {Iš-jŒjÓÙY®L;Št*w/Êá2rUžÊŠ<êR“9lÉ•w•oÊÁjI €y/‰¸f¤p¸ãµ.D•Ì+,Ní¸zc`/~vˆ!Ž£KT“ÄÆ¥Óõ]:¶Çž #+ή뺶aq¬YõÌHÈE*£'HOàKyú}µ¬º æÁ«“xÙv…Ì¦ÑÆGRÊ÷ ò„¾5ìÁ”ôÜ´‡µÝ5ShV½ B·€ûfsݬ;ßd<)5 Œñæ3ö× (Áõóåž=›9}L@aõÞ¹<Û{t½æùü %} û*îqà %¿°†ªàœÌ EC2zôÎ}â÷½í0ˆn–ò¼ºª]³Ìâ¬rpmÒH®=ã~)xYñ.ÊgÏ:²Å)eª'ÄÑòÊëù)¼ÅhªÌ7ÇÏîù¼ÔQ`@nâà E ÙÊfû99¾Z=ºà·Pz£±4Ù.A(ûÂ-ëqèœÜÛŠRm­ŽkƃwöKº‰(´o\v ž<ÃÙô¾#„QñqûFñÍ‹•Œn÷§‰L‚QÕ÷"À40[²û„|ß¼Ø/,E?±4òY¥1qQè×fùÈ©ÇáCó! ëa´tB&ƒ‘faÀÊñ‘Å‚1Ù©5Z-Ùª@F¾Áe:}¡dÊ>•“a@m L;ø_ÑqŸ—ÇÛly?ÑtCÄ$Ðk}îg>ÍÕ]3V¶ãŒ‘q‚ŽN]˜ øÈ)o¦d%Ó„ o!–¸Û~wœï+²òó#еÂ9.3h3yoU]à[Û5¦ìµé>Ú çË.2ÍÑ„ÁK+áåÒ뱈í°giY;φÜïÜyéu¶jWEÅ‚yM…•9–¢îÏÞãb|2`BÃNŒñÒpEÜáÞ­ùó ~SÇs¼lüº:×§q¼17äb/#€§_?q,‰™ùTç÷Ýù’ݬÌs¢:4Y++Ù*g{òa=›pêÜ$q™¨C?¼•‡dÏ©pÁý‰Ä+5dÐ’Ž”–Ò .H!šv³ÇV+Mµë ×²Ôž¿ëk†ÜÌÓ_ˆÞܾÃ~ÆÜÔñÒŠu©„Ì^†4Õ,ÑõÌõžÐÙíY«øÒYEy¨í{v¦{¡0iJþ9Ù|_ªÁŸâhß½n}eBbä¶’p™Õ uç1Ä74L¯-¸ž_—Ÿß+Àã}3õœ%xHØUÃOrÖ.s6妆É\6ç…ÇÛ'•ÉÓ¶DOÝ[x©â/LŸj>TÉ”'äÛëQ™›…¡Ç47ýÆôˆUEœEÈ2õÑjÝÛ9z '»{`—N†>1ýìGêíçþ¢`u¡#4R\5OÓ)*è˜{"_2††Xâó~ì‹K'mŠ‘:²³µ’=ŽÛ^m}j>à¸K’&Ã1oÑç™A¯“W¼5¢‡GoÊHž %ìo/m6êÅc‡ÔU­“«ÜðkZRK‚;`䬿YZ੹ôj*‹k·×=ù²¦ê¥~¡ú} /Ñgò–ñJÞ’_§=>ãÓü<°Kôµ¾?+Ce­Ñ׉;5•v-Íû^ô†SUzÛ‚¿eFö§!³¦%ï誟°l×n5s5ÙQúé‘­qÁUé‰òÏÉv5·ÓgÊ‘d?wZªÆUÇè¨xÕ¸„™u¯»ìM=ãWíƒh16½',µq`ijUåÒ?Z…ÞÛe,Ì·ÙStH4×ê f¹ƒÇ+ä'æ.±ûz¯^ùÆS¦d¥&=ï^¶¿Ó7Å“}ë3èö^Ûëힸ}Ó„\ü¼ÍÒñ{B%ïQ>›_È:­À{A|¾»8‡þ\¥'¬”%Í'1âÆ!‡‡§äª¬ø`A ïj¢ŽêÚDë/dñ{R2‘¥¡•ÁÆ}¢%&|÷PUpÞÓðu éSœ¾¤zkt¤o"Gçðf×êaÑ9·äVñCdâR£ÍÄ'-H‚.ª…c‡W@LR:›* |üâÞÈx™Ó ?îŸØZ¨£/< 䑼z¹¯¥¬edO#’3¶öê½§´ë· Ü)JƬ±/c|åfLÚÃÀÒ/¾°%øtt˜ÅTDDÜ5ñWIý $¼Gìe›íƒ·.<(‰€­'I+í€cã2B®‰¯Ý *àæMp¦39™ ¸cLç /±åfZXzʶö‚gl[“X˜s{^ãþÞ´ã†îÒÆ=}õ(Œn²Íš7‹œH1†ZÆ•—ÅâI£]ðΪæÌÓUnr±”wj÷>Ñýì`},Î]sóº ” ×& €V—vA.bÌ–ÞŠ Ë>[0C± udy/Ñàià»Ø+}¦”Ä}–/n…ò5`+Cߺ‘•ãUDzÜY7ât ƒØÂC+¿µŒ½J‘û™º6]ÙNbë Å™Èäñ£5¦mƃ]2d0CÏ.áKDÎð9öòu~³Ì‡_ø²~z®Ñ5?Ø‹@”Ê1º Ü×\!§}ý¤‹vÕµK¶c4+jDVùe!d*eB7¨QïL‰GÛ•Úõ0Sœþùú{¸nÉÜ~"“ïªr¤Š„¬|ùŠ1ér¶Mˆ!éóJa;E`Íu‚‡'EJÔÄœ§Y@¨W;™Çãæ oçcm!ÍJéûôÞ÷ÙÕLwûB4…ôŹ™ãÓYæ9zÑãKè §²GÒ£òàf(01l§šÂ!r´©ÏV((ãnÞÈ߈]-…XlÏójNmÚz©Eºì£-WG ïån>ƒô£#ý™ÈÔºø8¹«.omÓr…»ÖŒÎ ¦E@Ž;ÀD_ƒ_¿0°¾ å(’¶§¥Àq÷<÷Óƒ…>1Îi(ÕàUlÒ82_÷R’Æ ÷sdë{ìV—àªàÒÔÓâr›Ï*†VhT’Š"mš àžŒÂ áÅR\n`0Fá+o•‚GÜ{åd#‡Ì@(Ä/<ßÛÏÜ[U2c Nד¾#,cûVf‘Íj×hM‡PHÇ”9 ÆÒ…l[JÞ…ÄM<½!H£/”õ³Ó-Þ]†“v¯—kõ_…oŸ÷Óžc#@>sÚÞÁesÒ(«¥²:A¶A¤˜‹ëDµêr´–Ϊ¯újÙo]™Þ*óÝb¸/VKöI¤¸EŠe Ô¤(¬KÉIé™éP(ÇD÷¾šŸ8¯×64máB3)°õº& ú‡4g8Ð,`ó?RߪȎäHÝïH®ì¶¦ÏŽdœ?qþžÚâ"«RE‚v§Þô Meø5< V Ú}“IÊÀ<à(nQµ/êE‡“ ‘?(º“‰¹09?jZË€6Ú—n9N¹*¯ðÄ’ws¹.¼åxýçýRÃírm¨¿¦ÜÍ£ %!ÂJ‹TBB»Áâó0¯t¾µ;äb{×—w5Fá.¯ô¢ÉFÕìÅ#xDx“_HÛg÷cO„d¡NÉK_ŒÖgnãÍi2u\®öê²(J¦®QRy.WµSW‡žÐˆX¨mæxäëð÷ÂÜ ŠQ_§”¡eü)» ´· ºªËǨ("ø"s‚Þ[(IêÈŽ.Ô„N:Ç{ñ»¢)¶˜D¯ZGCð¶´36ÞYgé˶vÕÎxoöÄz“÷´6\ÌYy¨—O*ßóûœîü{9ÞºïE5²ò;D±MÏ­Ÿ—Š%5[‡Æ¦s½ÑJoØ%Clò]Ärá…„ Aïcx¤¥gTѵ@¤«ŒFÆÉ4Q€RðÁróÉË`UÞ7;ÛLCþ–DôÒ ‘ú™ë’^bžú”Js˜=Æ]Gj3=ëb=ðx€›ô ið\‰óá€õF°U×¶w"%¦ùz}¡ô‰ö^Wç=ÁFŠ©¨è=h¶û1Ûj gô´ÊìTUN¹KJá+¦„†7'!Àe`rOcöG—¶ÑЂoÁü@Ú Ûò½ðìÀ´qèF‰$—h½$¼,ûšÛœèQ—¡GwãOu“o¼Á¸V•”=Ûç€Îníp4,p :pŠ€Æ†1Òno^zvóƒÛœWËb‹gŽô0<Çìo‡ÏÞø˜[•^Ž«'ƒ“<“õ¡"tàð{ïW8á+­ÍlÂvKjæó®yTÔÚ;ÇDod·)Ìß{ïˆÿì’éÆ ­Ö©@ZªÎ~–©Lo^XˆÀFõ‚¾N\¼ K†ÂgIïøTµ!ÆŸï¬öÑ -‘póÜæÒgS½Gç÷¶Ü±Ÿ3”²yà–‘lJ££¶Ž‚.äÙÜ›³3ÝÐÃPT9÷Dý÷´¸»%Ú¼ò.¹Âe/%ˆ›ˆä†êëñð¶8}c4”ó I’½Пö{´y‚#¨Óñ…9~O‹ Vú.¦çphÜúR.}§â†êëp™ç4þNW—‘&®z•Ž#õê™.àÉ‘Vwାµ*ðZà9Cær<m¿6§‚ È*óv p;J\6ý<ËÊ7='øt”R+ä3ûé-Îo±Þúƒ5·Æ°çO%Ÿ{ñÁñdʉ°Ö´‚ùe4Èj‡°3="u6éuC0_¨Ógç<ä£êâî—oŽ¼ÃŽæ{Á£å©Öº»2=Þbô¦œÂ|h]\Âå¡`XEa—T£×ˆØœ#´—‡Ïýá‹Ê(º÷tbŽô2‹D„Xù¶ƒ›N$¸ä‚¿«–P,‚:9í™,öœú…û`Ã¥Kû sí]DNŒ )/¹Ö3;‹C(@`4@ã0Gæ÷*bò¸Ê «e}Œ¨²]âq~áΟ=tYÌa+,"çµ™°Ì›)uîcÞc5Ca²¾×/Åw¢kz湞jœzŒ¼È`}—N)˜B*oÛ«8³B¦·^º¦æe°“N± móòUºÀˆÛÂlX¯;HUå/äßg7Õ· „â²€w«ÃX%0ïµEi‘š£òԳτ՞b ŠjNÑã“öÈ :,Ö‹;š¬2‡¤ 6˜LŠ °¾êÎHŒ~‡·Ìû 7·e¼u×”øã¡›TÐÛhÚé·æ£¿°Ï.ä^¤Çîè6 k¡Ë^2¾QÀÒö±´Yéưôwæöî@ÜÁŤ‹]N«@ ?±ÿì«ò*Kú˜lTK&ŽBÑÒË1%БÝtv%¦×÷„®ò%!Ã,/ª ¢3&Lt…õzÓ0eè Œ¡T½NRï ߀ÑZª)é­<¥ã Êo®µmÛ7£´´Ÿèaô`¬9æs¤|wXž¸ ¢ƒHQ7z yp~üì³_¼ÞaZ=fU½š|íXÓ ëÚðòæí4]{=|Ø&¥¦…¯Ãx"#¯—'†U\ €_¸ ×%ª)Å2¾ {U­ìá[ã»­ƒ[n¦FËD÷tuþé<uo«î5añ ?>Eµ@ V5¬²ãçÓ"”SäùÔ/ì½ôF"K̇MŽ «/›à ýëõ.”p„qˆ’je"kD/·…»†£ð²ˆaS ý½+…ƒòÄjHN”à]ÚåóU @ízÞx׸¸OÈ^q=c‹ÈÇþ¸Ï0Eâ6’¯döãq5M,¢°mKp€©Û…GAlGØrhñÃû™vÊ,5–óàŒ¹'‡#: I%<]LóàavŠÇé¬6lö`N8PO'/@ЊC ?6yù™ëí{—+¾É·iìa<åµ¶Qµ÷ƒGW§Ç0dÓ]®#p<Ô”"È$š€é |¡KÊô^ RnyŸ[¡Qç` Ï)Ò™´0-—\G4 ãù©¢†$¸%ËîÛ]Yæ×¬1¾+Cqâ(㪓s|~¾|¥—«(ºæ¦¬æaù‚4ÐqS¼›;ÿÀ…sM¹ÒSu˜€(ŠÓ<[¥Ë7ð´6âÓ…ü{šµÖ…¦²ÏŸJººÃ;8«˜abqž6á܃¯uÏß<œvlêǯ¤v5ƒ]­¸¦@¨å$VU,Ð›Ö ‡!¨Û«`q…û-r=î}/ N,†rl,Y^ô˜˜BV¡Ô{&ëº>¦…½ó{‡#šà‹nÔkù&wÜÜ; 6ªÃÞÞ`G¾—Í:¥“áÒñ¬m!Ÿe‘Õ!ô˜Âåó¼OüÓ‹4 ‘)ëi‘ï\ê³ çÑ÷Þ²aë“@ð¼‰f™bY(-½{ý6Å×D^ =…Ç\„ú:×ÕÏâÙ€0´/ë Vî ¸p÷ƒqy.Eå.¶ÉX²©ûº/é8mÙTÇÆÃâ&[Ñ3‡ÇÖ]gó€ä¾ÐßSo“Öd?y‹9 -$/)BUKÕðue'½!-=åm[¿®ä9›ó0ƒ  ‘S±wšþÅC|ödñÑŒ¨Ö'îôŠDÕ Ò<0Âî¾ye±Ù㥒lj½Rikáu¸d‹–wGn êmÍëIÉ)d(¸#¦èöQÄ-|“MêI«Ì1Ëa·ù°…ÒZm¤dr‡e+m$öÉà¥mf5ËISAÂ[c3Q¿ýÅŽK]dRét3‚¬] hྎðÑ.3ç•´„z,y{7[*VíZÖh%L|vçÚË{:v^j K#%^ÔØNPEoù^åòúUëÔ¿]|+£Ya”;Ãò€Xžê:‰ 쾤Ͱ¬æc†‰;‹Uª*åÔM—Y”ÚÜM=‚—ä! KÊ4ˆ®8W°*Õ`Ùž(Áî#Íd¶DF®§r'+%¹ý{+áÒ—âØÇ÷ã¡Ö.ïH6É{ª”)Xs8´ü|¢ºÉøñs›#(ô‰Ó+}¢âê/ÕAM¿¸ÀÏ>í+Žï]ZŒº>s%ê}mÏI¡C+—_”DÖvú?÷Iã§¼÷Ãë êò³½ÃÀÚ„{Tžk˜xXƒêæó†ÙoöêÆU00Ωá½d Ñwä4­òÀüÙ L HêÚ?¯çþûn îù ãÍÃàëØ.EÔ„ìbbËÌÒ«±¼'ãðÆÙ}¨&Ò›'“…¿Ø ÏŽ]"°¹°­þuŸòQP`i;-]Â#ʈ6œzyøf¢í˜wRèÆx­ަָ3Œ èÈyLv?ãÀ÷ÎûæYæ]c"H—&PT®®¸Ú¸¤È‹ÀfŸãŽ=o\ÜHS†ZÅάN rhŽh¼²D¤ÜëŸ=cËÕ¼}x†à~ÖŠã[¨³ž¹Ç"n–ÀÌ%Œå8¬-Mïid?¥=óVŒ>ùøìÝ´»©Á'.÷vôôÜUªrŸ¥xnõ£ØWÛï`:/ 0¡ _ EÙX6¬Þ©‚%ÓãݸB¬>^bx·&w=3ÚÒ´”¯çÉ)w( èV1|ðR‡êÝ{&òøi„¯óƒh<”©÷@l*‰q¨ë‘Ò{'O~12…ï=z憗¢ƒpµVõ¨ßSzýÞztD… ‘š¦é¹? âXÚwue‚ûÐBÌÆ¿áÏ.>YˆÓPðl AŠË‰ö£ FQr¡Gþ"N5aÊÿ Í¢³ž»”Ç+WFˆPúÔµÚJÝ-…=ç½Ã}¤ŒÕoÛ3Žž¡ò8Q²‡ÇîË,Àz‡ŠJãÆ…}Éî7 (øN‰è¡XEí=â6s.Ël†QéÁªôQ¦ùp!rJѬZg«Ó–5ž¢DŠm{wR™¶KKu·ZLjÖ[}(‹iòšo±„Þ'ﳟ?Úˆ¤sÈ]X$‹¤ÇïŒq‡_¾W˜Ž€F„ Ð ÇH°å Ç$ëñR²Cb: {‰ðYD >zëC6æñØ*†ŒÔy³äT^o7ÕóL) ¥qqÊÊ®÷êÓ®f÷®Q¢ Ý‘§øš¤4#SÈÄc3ïúÐfÎ~¦¬à<Ú!ò,^ÏX,ì: yA™-iØµŠž7ÝfGë)>ÄäX£Í·„| )ÄØ/|¾X‘ÏÎÎõô 4u®/;ñyM=2;Ʋ÷zi äÕLëܱæÙ½¸ò$&èæšó…¤MŠN‘YD•!Œœ)A^|¥7´Ô<œ¯äÂr>c~ÍÈ-Âæ©e4ÛLyòø]ð=EÓ­ƒ÷ú™¿§Öð êA{‚{;Šãï¿C4òaX•aå=Ôb7£Ý™hI&!DTˆƒ;Oô´#)Š_¤SK¿÷òEÞ\}ñ¢ðé`¸*¯ÌºPä¤ÍÂ0õÍÅÊðkÒäÎѶÓb€á˜- ˆ§9™Rû*e\5 Ãô‘+ˈo<=›æš7Õæ±*ü¢[:^äôHrË‘¼j'Ñ?yj<ÝHL§è[×Ú‚½j›[ðhâÄvûÕm ,jä™Ï>d›{Gþà3J( ¬»'ò3U`éW‚WÁ¥óì‘…2¼»ÄTZUÈŠ,<özyx¼éQk#x÷ÉÌg·WÒSoôÔH•”Èè§µÀ#¡¢áG“ͳfQþWoô#\8 ‘DmCiÜÆ%êå-}R^ïHùTa“<wk´½9Y\JÛwEã½´$´[œhB%(a­©‘Y’;ÃÙÖ«UzYZ„ËŽ<0¸b4W‰Žͧ ,2ô³ïÃ’eå¸Hªš•Í[`ª£8e¯ÜP©ˆóÍc0¼óF°“ÒªÒ, "_ ›U¹Ï9Åô“ÁÔ+îWm­Þ ˆj² ñ¶D³N®ĘÞVë3sP¼8²µŒ§ÌYƒ—žöt_ŠYç ½ÚFs†TÞlGl!#óžvjWOo@Y\"ö®YÝËÂà–Š×D¢9&Å›­72]¡Ùù 8_]½¼pïí:Ê•°®€°øýr²âF°8óõÄ{Y¥=Ê^4HÀ£’˜´UÏȽbOÞX"ž©¿§TR:ì=ÓðôsnñÏà™F×ëIZPÜí»Á`tE vYã´=N}ð °úÅ&ò ‹9JÃF˜ã,çTÉ{Ü‹ía+‚î½yD˜ê¨ì³ ¹XLì÷´zåq‰mO½&U2"‰A ŸE® X„½m°ço¢“Ý`)3´ 3i £ï€C:dàì¢ÞÏ×Ãñ„I²V´ÚKPÄT(²2#‰ª)­w¥Iop$»çå[“d}UÅâ úòb>ù‰Ï, |~Ph€5ï¼gÓ³; ³Ñ[ôe4%Ú¤µ†ºŸŠƒ˜pˆ®÷0/Üx§î98Ñ~¦!#šv…Mƒó(qG(ðèvCÎdwä%6­#‘^Ýé)ç¬ø Ä6 µô-ƒ`®æ“A©,iÒ÷&u¸9½QÞîóEô|·%L¥dKá+d®T€ÊÏ„í‰(ŽãöRìE žOw¬€=v}¹ÍÙà«Ô†r^Ú}ÑPS\Å*ºõøAOÛ'M¨ßo‰®%¤„®2ë _ϵv£ÉNvŒ ¤"ócÄf6¹X¼×›Z¨C¦ŒRO1ÎOÒ2$4@Õþ9s– íqEnkAútëÆbV&ç(eCjˬ©ÌR³!–i,ßì{iPïÎ)ûé¥ZØpQiièòlŠ0<Žì]Î'M)XÍ4"*P¿ˆòÀ€`Ç-Cvà‡ÁŠãë´AÏ4Áwº‰¤ÊY†PºžX=¥w}´Æ«ªS)Áü Ã9>‰¢ÏÜ@¥SÖ;®*[³Bè´&ÓZ'#g܃©ç®2±ñ!EuÏkì¾ *|³tSê^@Fþ@:—Lˆ_wt+7ÖËR=†×JØ#OTNêî)×S¬y0GŽáËÆ$€õ\asF€‡tt5˜ýÞÂÝØ¨<'ËU—+GûٟƦå:fÝ úi¦Î 2;KÓD‹eÌ’ ÓÔržKÍÅ ~¶Ad»Þh¡|RÅŸaJ Šz:+µA)—¹ö9¢&ÅúrÀbUNJ'$z^õ?Æ÷A%žÃãn;Rr¬³YRwÕ$6ƒi:éÎ8jÂG:´¦\êÚóK¦i²w uT€åfE|ãiñêÌJ r8t;PP1 ×3ùuG¦bnXЖþâ^þögxp@ÔŠt gÔøÈ¸/àD½ù$ë}†‰`~³ a5©àŠ€©Œïôí{â'wñZ æt½åY8· v†¹šdVB Ç: Hãõs“®b@t$Å­ìw>‘lŽKSZèðh·/-õ%¬Ø{¶m×µšvNârö€w‰ˆGhØêÕ=ÒG®È£õH,Â(!;KÀÓ” ±‹|ëm ÃõCVÜþE×Uï9Ì€®-—¥<—N©¦b÷®À$8tl+^ÈÚ•1N3"Ç׃¶,ج¬åòmƒï3V¬{¸z g Ko¬¾¶¬°¶–çÇæÊ–rÐÀ(/:ÝU÷™Ùãî«Ôz|<Œ}éÉÝ:*)²Znß)–ÑÔ.M„¢;ô-9ÎeÉ.{aºãXT`š•}#’ãó®S!Œ°@ƒ*Û¢VtÑìÖÛ¡¡ãŠùÙlÜãQìr«(ÙùI³gve{¶T7òå5lëÐö½tË‚+¬–=ë˜A–W¾ä­ŽâÉ*‚3“å¥þÄb? “Ï€qƒ±€é¼¥ÛŽPñĩ˯.éº"¨„Õß•="}à ]8ZÞü¼©äe\o1CSfFÒÛžèÇšÕÄŠéTåN^.¬QÞFÛ àt *b¨ìM {ùT›¹áñãtއb‘ÊÉAQ‹»ÏAF{ye` ÔnàihŠ*ßëì@ Mê-y4&£þó]‡¿&õˆÎè±zu1,;¶-â.ë+bC¸Ý°äé"À®«~™Ë«/1ê=.·oKÔϨ!‘KPz¶PÜ–á‘WäL/\'ɸ öá=Íeç=Å-^órû:2ö*>é+ã ÅõÇTt)y¼£$—9NR1%­M0@Y“tÝâ%5|+`uHÊÇ C©šxi¦Þâ€[ºî‹02+'ÍFhy ,>Vp{€ÝÇæ(uÜ/~‘ö ŸŠ4W4ðÎÕÁ©;¨ØƒÊI.SòM²3ŠfiLWÕ^¯ˆ¡öØY¨¡‘1¸ÙC¬OÒì3t˜í:¼Šc É"V²ð2*H,¦Àé-Geg8~ÅÅä¢(Œç`Q©á` (àªè¦Ñ´A«=cªãTØ{ ÖlüÊ¥Ú{ž¡9Ât¬S`‰3GªY…¡ŸáZð‘…å&¿x ‚ä 2lU"›zùNôÆ=´^õ`ÔcBÉ µ6¤¢·L*Ä´@dbhçáÓŠ1S¡©ð‰Ã·£é tõsëò«éæ”1¼âœÞm!FÎy8ï/P:“ß.’9ÇÔÑFZ.öÛ%‘ mÔ]Á½oâü“8¦ )¨ÈJwÔYÐÁsp©ñƇôN7•K’rVäœe`›ÝaOÀ†‹duCtÖÊŠHƒÛ« GV"shcäÄwnJwiø ÏÔgÚ ÁsªáŸwDTo7¦PÞ³b°ã¬GÏZf#=k”Òg{p¹ÜÚ+ÈN ¼¶ØÔ^ëù²CÃû9Ÿme=#”ô+ß7¢XDP8Íj`É.gU€&ÌÒL‚ËOíâ‰<‚¶Ç¬2p ß2># ¼‡°Œà”ÏÄ_=ÐAOÍZ{û&%ªô\VëÅzâÙQ'À\¥<¥¦ª›õÒwE8 ·Èè%šB\Ž-»M±ÅX`^Š¢æ:É£ãÍ á-ý¬J-[ß>TÉS©÷ä½qЙ•{n#lÜvaAMêZ¶â„kíKOœQ*BKÔl‚t²ÅŠhÒ[5a~‘7§çP:¢}—.O’,éI ¬6 ¢]³„ßS)í1…{ÅmCH|ä§Ö«R·Pv¢Úb{_ä!|ßOÊq£rfôðMHF˜½ŽEž²”‹ë8†Šúª²§ ÆeâcÏMm~Ðsafî§‹6ˆ>+¤.rÁdðŒoÐ+ÖÖ‘*Áæf ”° Oûö-‘t1HŠnÄ;ð]òÀÊ šÍ“·erÖ&Ð¥6NÔ¡hÚOk<) ¯ S—ÛPü~Úæ†mÌ›ÇøCÁ iG~SöVæ-˜.4J¨:I³aYcÐu´Ö亖™8¼VD¡¶Oúð3¦\êîЛTUM"ǧ…‘ÂÔ´•ñâpöpí¹9"ŸïÃì¦2¥P~~JÂ%Öû€kÈÉŒU´ta¼6±'Á_²±;júƒçr}|Å`gf—r›ý\Cšòži‰·Y<¾z"Ú¬4Ñ•^‡À¹À¯2}Óë*ú¯Ú£^¡~±éöŽ9iac-£)à÷ÂØ£Î=®Æ’ýQÀpáÄTª+ ®p°)CYÛVÏ$F¡  £ÊZĪk&d½Q)…òOé{_Rõò°ÞA4örçeо-ã^O=§t1æ÷€Õg÷maW[‰d£€—Þ>›Z`í'â´£¶Ä÷Úž¸L–@Ìa9+‚è“'ú¨¨pû)/:<¿&~f­E™À"ñ¶‡Ùó4ïu5%¢jVú(y‹­¬Xçö¼WS²@¡ 0¢Ã<>³%¥ÀfÎÆ›h‡Yö÷~òÁrPÓJQ´CÓ˜Bgâbð3Û•Xžyæ·ôZRIß’ç1fÍ::™+`®„V}Sø]ÕÑ»•àñ¦>ëœÚ QÄÂ[}ë‚~¨íàYf$žK¡îf¬`iágÍ}½C‚[Ûê.€r‘u¶™•ûÔÂÏ©K‚tVšøÞK¾¸~Å­÷@JX_ÓyzMKç‹¶µã½¯ò¹‡R®?z:³r" û(C—‚:å]=MW=nGkïù,Ãã\¢›!ú9ïY+'Lcsô½Ë¢!:¥Æ0±ÌW;0†ä“ôxœr ÍÍ_6½9~'Y lr8â¸öj>Iäϯ쪱ßÛxQ8¦hÃXϺÖ:ÅZ/ß=ˆ7ÏEmÙc»õ†ú>Ð7g0ç¬ùl  ™YK€¼X‚a(¶,í"%/r¤ï=´'•ÛQøz÷Nòa¥4ö‚Ëm…CeEŸÅŠ/ðž­òR4û˜ÿñ¼3\8y^vͨà’Ëž på³Íz9±ÕRÚÌÞU~ªÃ’«÷Ï~¸.ã yCãg¡d䨔ŽÊÍ·M-Nê§zöú.L°ŠbaÀpÓoèúâ1 ä˜89Ö}Óø>ãÌæƒuîB/NzÔ¸ÝÚ=PæÂù8&‹Z4úZ§Ù㤲ëLs/6ÙÝqÉÛ³aݲÞw‡Y\}§µÁ ¼nÎÌÒåÈV+…ÐÓªw|‰5Óš¸;öNàu­Q€TQHºQÅò-õn¬¶Z?œò½±qå>„󷊾¬“<Ò©sÁ|ôNC^%8`"Åëñ±UËû½˜¦@z&Ô=/Ûèe4pA±PM©Qœ·´>/Ü3Ç8¦¥´YXr}æIo.ªØà\¤±?‰”ï£ØHÙ>;Õ‰$µg:ÌθVeêó^7?öI¤ @ åM¹Î«Y‹):-ñ Ä‘à‘³¸¹e ]¾t¸£3ÅÁ‚iDoáî)e!Å±Ž¢â¨ Èn&!誩Iêwã.:Õ»hŒLIjá“ç `%-(ˆ¹/Lµ-()„€Ýß{[{KN¢WÌóHáqt¥qƳØhå_T^n–¨Ûql‡Çké¾+±uJUeó‚»5¯,Ûê:®¢rTä3ÃŽ—»D3^ìä{ŸTêgÄqÖâW‚òLO‘oß³| ÍÇåGÙÉa" C#CeTãÙm(À„åjÀùgžêˆ§„i¨Q¦Bޏ•?ÇÙW•"”¨OÌÂ<p[xäA<'<¦‚t‘‚·ÏŸ_œ÷mlbmˆ9¦IŒå„ÑKC ©S3-keªæ¨(Y ["¡”ˆ×8U\Òæ†‰x"l€ïµðOƒ}ËB…CnÉÖΨ·Ðš›EͲp°äÞ㜖—¡{ÜnÚ}Osö£Ÿk ë¤Û7™Ÿa§ÛÌ_¾@JË’V‚Ì¢¨t³îrVÖœŽãéx'¸sBX„Š{~„ Iá"Ž +Ü«½ó¤æÌ©q†¢²gô)ˆkèÛɲޚªm“ P8›¤rá¢q¿„óFÝÖ^øZdz—Yº8GÃ÷ gùúfƒ“œçlí.†Î=$Dµ·Â´3Ÿðù,v•XüIÈÎû½/Õ&÷Û—öv°XéhJîú=@«öŽ­yr’^ï¶$ð9(ä¾J¼KTZ„Õ@íML‹ï·iŸ±Ç”£žâÝ‘AÑÉÆÁ¼^sŠ÷rS6Àmë%ÇVh•4WæÁºz»?xd-Ö¬.[îÊ£C¬„xцŽ1q3Ц³ÍȺh¼ì™dI,ÉLÔíT„×Nê.Líu‹P2÷¶å6¤r‡mqÈ­ÖãáÊú.‚T?Úa{…+þê°!n5ñy+ôrsG“C ‘P~¿O,l>d/9f=<wNr׿¬TÇ%REiNGï¢_&.(w4Wô¥©^]åÊ'¡þ€JùZ±ú*Åç­ÃÅ|â}8…s´êà>­/$*aÄyÄåÏó² ·¡µŸ?–-¡ÈzU½–’µjÑa¹4µ,ëÝ8O t&¹ï¡«J‹uí¾ªzvù:ÏüÞ®ŠÞ6±Ý¾Ýª¼$ÐÅ=ªÝ—kXE'ï'soëÆ€‰GY˘§‹ëL¯ð-qÞá©ïðTŸIGE´ý~£ V\DÏD™K*1S=1úN4,[-6øÅºÆk•ö&TšéNÐ a×O#øtŸ>ý¤4¾£Ä{u2³ï=R™×ð&'ŒðŽ—_×)ÑäñÃ[Ô }Œ§ýæðLaø…n…MøˆBŽëm¿éE£w%ïÆæçÕ![Ψh;ÈÓ+¬ÔQÚuªÌ „½×^ÇçN¦×Wï-lËÓ¦æèß ~wÁÀ ^„žÒ¹¶o¡Ô=ÇÕ²èæ"t )Vñõbc§ç›;rÔlñÞ×/R1¶hQH)CØýé ©iX “EEn”V² Œ§¯ˆr³ãa–=ŠeSaö~™ôE*Ág(z}‰dÀ@zª·3Ùžˆ×b‰Ë·´ÈdÇcÅ9rWÃÑÖåÀ¶ÃEjÖüTIß‹n)˜¡>"<Û×ü^ä«—¡‘U«; b›Ù,ÉêzŠqœœbE}Až@´E¦¦­}¢ï:ß<ÜÔ¦|æÑ¦ gUÎ>ãÎÅ9¼ dk&ÕGJîøÈ!¢íîB _CÈ&2,T{Ê] ©ÀIàϬû&ŠôJVÏVæö’ï.„ÌÓ‰ì½ZÓ³·Wí‰9êëOTùm°)èó=KfŠ8V]ŠoZ?ãÑðªtõ¥…*æ½àÑÐë>¦Ìœî½]ãõ‰Ó ‚XUCÝ07÷~±Wn…ÛÇ™®CóTra¯=諌šwÅRmúMè@=ž]g#ëÈà:ÑN*Z‰œJ •§é( vmiJ1/žŠ­Œ“Öù:[e2ÒMæ!´÷.ܧôæàÉ‹›Nåh£È3Ôöª|þ‹ØšJsöĵTÀ‰{±L\ÖrY‹‹7w|æ*yC³ê²‘ÂÒÊn»úc‘-ø$?ƒ’?êg'J4v†kËèÊIå.-šP©4õš’nÖB¦@:)¦!ݦ޴Òî³|8ÅZ1SLÁÙ¯2׿¤uí -Kt‘:ç™Ö¾Pð†X›çCã³ïR<›û6owŸ7dì¶û _ÞkÁ“7 0N>3Ý:„IÑ']R$ R[žˆ^^îºpQ–6iHi†ö‹Úй­»”•qnŽB¼g‡4ˆ„p6ÊÐaÐ73íö9ÄÅó(\z`wnW¤ä3‡×@ßÔÒgdÒ~ †!Æ+FÏUqÃok™T /;yXÙ…1—¼ž+qsrz66 ¿T…¥1\Ôáì~uÑK(­‡RØpmk6®ÕFvŒ¤ÉˆÊ âžr…Å€ºJ´6xm¾£U§ép"IH:š:)€ús5‘gÃë'ÐDyÚ°Ö+Pï) ë­ÁËX·X‹›7˜êÞÉÏX±ýY%Ìh¦P°nž¯xb-4¶Á[|:¬š[ìµ³Q{¢‘í™›lW†‰‰i#mÏ$}öŠÂ\ckg GQR&‰_è .bV’^Bš…íÚ,¢…+ °Òôž™4ÝⓜԚÄîbÒ:}ïÉoÈAêè|ãøÀGJð¬)çV2+S„ž´Gº3BðSduRÚt9!Žl+ü$Y?CÖ™–Ë´Ú#’Ñ·Á:8†TVyv€†z@Ã\„ MíNÍ{È)¦…Mðçg¾çC÷T !2'øìuÅÚXíY‡¬çq‘Z{4ʱ#{?qæï~ù ÓȈ÷^Û{éÂ} M¢>óvÄ“:ô=½G¯w…•|¥æ¬” ŠÙ7—±Üš^áÓÖ "j½{ s±@Ôõ4æµ¹ÝëJny/1;ðBîÍŽš©SQªLî+L·y»æ&ÍÅ«WÙÐ3ýÄkô)†FŸÀÐ@<ºn{Àb\€ROä“f£O»–òަM­c¾k7ô«¢à|›~†³‰hЧñÞÁúºR:†•s„˜¼Ø£Ç)dqMú´æ5@”îl=cǰ¬zA§…ÓQé'n‘Ý#©…®Ü6>ìRÊÑ8¹õ¼_Ó¡tŸTŒ€Ÿ3s3Íš›c=t#År‘~µÕ$É-o°e¸lµ„QÁ}…ÇTœ Pq)ÅÌü @3k$ñÑHR‚M¨f-ÑÀL­‰<`³"›åàb|à)z©æ-Kg]tÁ/keÅÝ^fÉø!ï÷{vø$û¦)­»ì˜±xh÷îØöyN\F›{óqÀOD(/vu+q‘¾ Ž—û¼ê5§T…ÞUûÁ Ã…hNV“©œØ•).>Û®sQæ)]öÄóxŒñvÎAg¼S6\ZÇåjk®Ê¡wpºP¬®”׉I-­C†;Õ°>¹íÚâyÏ’ûíÓ&zÝ"=£tB˜”^iT¡ý¢ŠŒ1¼¬°cRÍЯ@SäÛ¡*xÎÕëu qÃêC €#2ÁEâz8\Ïo@H­éB…·—•¡f˜á›êÏöö U>B²éѽw~,3ê]Dre\Rm‹Û’^•Œ¢¼ö.ï¸ÔßÑÃí÷Ò@q¹9×I+‹ße–ìÍŒÜ`Õ 6vá?I‘îªrž}ï(:©f÷àa<õ™±îvhÈP ¨ê~c¶}Gت5÷\ŸÄ<² ׇpîœ)ÕÍÔϼ*2,‘ôZ.ä  |Š/äµ f`tÿ4pÞ„K¾–Í]µ‘ÜØz¶’­’àHõÈCÎq„k;(Ñuí™R ôËT6ö"¹ù$;ô³O§‹ÎÙä\DêÝnXrVD ž(†À wxaÏÍÕRû=-p»ìH8ºn_.z¶øI—œ k S ŸwÏ«b}ˆårML¾-ØÅ(x®Ãô´”8}Ú‹ûÅ…ø¹œ/»ÂnQá³HéM(>¯½qËÎVz,›Û]BÇ®hÕÚÒÔº¤±9x5çå MRKV_]ø¾4Ë¢<<¾I&惧Ã~8ý{=Òx˜O÷AÀÓ’d|¦¶^¶V8‘AÁø· PŠ#;ä%ºÚмæ³9Ú'bÙ7q¾ÄÐï}ÑÍð}. ðg¹jaW ¥Å:ºâÞöxŒÄÜ;JÇ‚XhÓ)ÞI¥ÊKV-_,r'hNœ,LÒ”«Ÿ´<†õ‰¹÷Üd¢•'#Þá¾âÜ[¥Ë6/e³O#™ì´ßTµ%%ƒM˜frìÃ<6z|Mès©YoÆÑJ“Ãæ¤SÁ20Ü"vè¹>,åzÔõš¢nÆÂ$;tçšìe‹ÒÀ³× ü,Á¼÷5ÉúOÂ)‡ØÑ¨ý<æ›Â‰hl©uíe"יּè.Q¦n©¿sÍ ´‡ù2¹²Ãú%Ô'áøÐNGšJ;8ä]+™5@¿ÎHÞA*24>(ê(Ø—žª²j«1PHW¶¯·Hxœ{Ëèeƒ@ÄÛGG£GHñ<ÖŸnÞ¤Ï{Â{O8ygýx›¥3™(ÚeõÛä$gÎ4~  ªd þ¾ì‘‹ñºE3ó‰µF°ó @áÕ\9Ëà [¥ƒ¼(0Ï›à(äèb'%oÇpß gKƒÅ/ʇ_Ø3‰Ö|™1˜o‡gùaR%Í!YmÐT5À–d[yÞD MŠáSõæ~eSÁqôX?)§Ï¨Öç¢TX;4j3™Ç³[äôô‰n1éTOI_‘Gv®ú¤Œ„‡.§¢ ‹ÃÍâôx¯VàÅÈÂR•cdŸZ*€""x¬š2ÑŒKíLWÑè{¡SÐ"Y¯•øî&½£|ÎGKûÄ£.ã²ë (®"É*È9Wi„U£òˆ „Þ¾,ëËõ«È€Ópx½ÐDqƒjò jÌåM£Òƒ¾…¼à­_¤Ã{.1 Á¼{Oyÿ@Aß|*&ÒÀ9O|†\òŠæ½yØ£†»¦÷i©{ZmËУjd›ìiQ¸ò–oM*¾~˜Rš¯ðƒèK±jC …Þ!6 :{,£oa—2¯Å¥6€/.†z ÜÈ«éœ%Èr>ê[½ š5.`íóÂðð†.~"ÖÐHMãåoÑ1ï©U›dÌϱ¬Ë»ãÏûTдÂJ‰4ýÏ+ÍZ_÷â9CòÜ^Jz’ùHŸÄ+4ÎoÐm{!~çýýÖù3¾Áø@äÆ! ‡F¯¬msD®i-c›<o3µ·8’h«€­ªTD.Ué¡ ºMùA‹¾ò­S—yvL®;IPÎ,~1ïUˆóeù˜ŸË»…”Pt&†–=_yÔ6ºßR × °­ñWnª ó¨×ôB‘ýLš˜ßÞ͵ ò#[š4 Ôz̵Œ´%3ûú Þ‰g˕ӈ8šeë=´»“_Ä»™éM£KP‰y ¿¥ë‹§ g¯ŸÍ¹(Òy´Jð@ƾ' ÏG{2a“‹;Œ>‰ïÓä™XËx¶L•êøx2ÅÙŠÅ+Aö쉘KFíMK‚ê¼ ŠšPÞƒ^®Iɾ÷ª·| ¡ <Ç`¢ çš_ž¶™ Žãr¦û{áÚ\›zOãb0^¹zœ >%Q ¿ƒG/ä5>~5·—]P`Ã6‚‚uáÜëÖý%Ì”Z ȳîÙVöG.ùäQ ¢dÛK=ÂÁi}xrÏ×ß“©_í¢öÍŸÔó½÷ŸÝ^ûJåðÆîkUÅ4Ã\o·'ž¥†Â³=,“§&º{äûrVeërÁÝ5uÍx¿©—ÏHW·åä¼9­¼ŽþJpNrùæaf{†rÔbx¦¸ÚøB«®1=f}z*ògø éo}fAJÆ6¿èŒxσ°ƒ„äøŠ§÷ <¯uHãYMÕ Ÿp (D+>NU×_ádŒ«PbÆ Çy<ˈžŽ1ùÆÔ@½z‹CP°Cš§8(°ÕõTBæ‘jB V>h;´è$—'6Aëcžß\½×û‹|AG °7¡ÐP1Æ#‡”7yå'cR“Jl‘º0jd¼7¤»)X«/­¨v={6PÉòI¾~†» ç‘wìÀëmqo§j6Àß="|œÁ43ÓÏ­ Lô¥[F ˜ëF<ÓG>Ü–FuYÈ)áú™ÛÚX*Úƒ›KÌ5öìÕTM<œ.§kãÌ~’žñ:Žjø™â —…Pb9éKÂ×z›öÊ@°ˆ´"¶Íó)•siÞÌz^žÄv r+ ~kãõ„ áV¥ZABÌÔū̲c‰‘ÁÝD#Ÿ¾ú½®éMï<ßËG#/[öXWéÛĉ€ïèuéã7jÇWæÞÂÞÊbá'Tt`œ/Moû%Óÿóö 6zXBºj¯èS–²GDZGm§fÌÇ–²Su±[Uoš°f®„9âFÝK«'¼³ŒVOSö “Š}µPH0rÙL/w²^S²Y3mèg‰aEö÷F¶8Èy$‡`2z!Ýà³W®HGUWš^±@œòÆf–¼Ž»¼öùsx –ÆGœºvÛX£ ØrWÇn Ãw~åIã.j9Wao—@2ê¬üýœçÓÝôö©PöM·ß2¯Ìë|˦šn}ª›+Ëf°$4tCéB¨J¼«ú4ÀÉÛȾçyÓOóGh #^žÎ“9·DqXcdÎ(€®mŒydL\k‚â…x¥‹ZÓ\ÝužøŠàš¬’âZ˜ «Ž½ë‰>&š¨µ»REÐ8zŽmU&ÑcX¯X;©šæt8™ürk*B2,^ú¡ÈŽ&ž[;Ô)HÔãkÓ…žØôž=7{ÜçoEåÏgh{µ´»ã½/0,3Oxƒôj—ë:½VÜ·ÍŽb±Öc½PNI@ÂXŒÕ#Ƥ8“ÞØy&š j€Ë;¢=¨ºgó°kÚkŠºè¸EBA8ÔLÁ6>%àŸÑo ñ¢²Ò :•_ÎG{WNÒ µ±œynzfMãÐpoz¯ÆPž³±8HwÒ ©¡|l¨·úvH$úJT‹Y_Í‹]0´š G˜Á7~9S5ý:¯Øº®à–ÒáêÉÃòΉé}bÆž1<~ú0Ï›ot•¦Q¯3[Èò%H½!ƆZ{ï` Êó€'ÔoíàwÀéµH¿R‘ç·5š9Ò²;§¼·ü<š£ü†b^ïïxM˜å8¯PXùPV¸N9@¹²E¨Þ#싮Ί»g7f³’­ÁïÔò!mb \Žš©Š ¾CàÖ¼Ãôwí…²ï ¥¼ ÑX†WvLŠš9 lÁ† ¹oÉgc<³€£š—nGEb)ô ï›Êxlø¦ªhpÞ1ÐnÀ8îõ¸çxìÓiçØŒ9EßtŽ—Zw ¾f¤• Q=¯VhRI|iïmh&!½÷(îÅžt=×±;–ÎÆÊ.ÛCŒ÷ª»(‹ŸÌ£Á-ö’ÖŠgü<ŸøÎò´Öè¶<+,è\)«eMCz‹ Ðhp÷s0kxxL{1ÞÄYÄ*ŽÕéïY¾a%r*Î*ÍÒhÅÁ#x®Éw/,Ÿ—¿®Ï³ìƒÏ8(Ù)šÀ‰lþjšÉc‚õÅRº4™Ö‹ š‚œÌw:äGȧæÍ‚°ˆx1ýÏK³ -õ!g™‚µ ´R³£UÊšR·Úóµ…Q7êð7FÜQÅ…h[ÊèÂéP—*=ûBÆ Ÿö{.® ×];àÚTOz/”‡™âMmh!ç–õë‘À¾m¼Jô5¢ÖÅ~…¨èõNïy†—¾â»vMý+là9dYÌ[}(%‡ýüšþ‚ãS]º”xË1MI mÏ|Å« ö‘^lˆÛI ¦5ÅM[ñZV´Ù[æÏbï²o!|ÔÌ}ú4™Ú¥¯³èZà0œ.«è-–œ÷=sy¯çÚå1ÂJÃ)Dpï¼ñ7ZO™x‚!§ÀM"Š¥ä ÖüU§„Ë‘˜…] ë‹¥ #ÞTWiÆ’æD.ñ*¨k‚ËšIp¶Uƒ¨Á7Ð¡àÆ‡¢—#ÅÃþ çz:j5O0¦H)Éî‡f‘ts\høPĆ‘dp)N¬C׬y¢â^\â=ñ< †ÂÍ~ˆµu%™·fv°ä‚e[‘Éñn¹Õ#k×öñ¼—âöš„,xn5’A+÷Ë=5‡O)à÷NP»jÕ6^†9oŽ6ˆ%¦„?ózõºö$Ã6¸}ˆ‘!‹É5¥ûÆ1%:?·`·t‰t8„= ïñ³‡œÅ.yÍbj^!æ [§÷À41Ï„-6¦‹Ò]j†BdסÕS)C¡i†Æ{÷©>i[I|xº°Ä™Ï)kEu5öpÉÙpi‰µY¢òmP“(iZÙòéæË ОEå 4ŒÂ3 íš•«á‰ÓBÍë&þÙ ®ç˜Ž_¥ö£Q‹B§+„{sGèQ²§úèª õa™ìD PakqHíÚË«‡ñÝ è3,¶÷™q¸=›7ž#~Öf¨1 %†îsÄ\4í)Ÿ“2õ(p&N}µrØÊÇN;à½â:{UÍcƒ¾Ènc²Ö<ÜÝÓXmh¯ÞjPÎ8Aö’Ò<é¾\³us åg¨ ‰JÛÞìéÎ5ÊUÂüÎn^ÎŒ„Ä’³M&hµ+‹_V×Þ\Iµ{˜óøû3ÚœÖ~§Íz*‡¢ë‚ hû’ÕJr‚Çí9R⬦UppN1ý’CPæ4PUXH>/`~»šåÆsÏqˆ)˜®äF›MiV|òéàÉʺ= ;”vF²ƒdxTßràÏØÇiÛ#XOÅèÜq8`®Ì!'צ¸ž)ò3ôÕ 7GXy¤s™VÒ¦e,Ðú˜Æë°okA£’å`àuÍ!CÁ\››ÜË·J=å+$™3Öë„ ŸS6úA¼GcÎ ·.io9Öò9ÛsÚ¡{l3ÈEÛòúb¶§yÝlî‚æ ¤à ÓKGˆ7É8›¥Ï4óÑ´?Üרâòþ,Š…j†íÁŒ&ªåÒ¸¢>¬2´þ)螺-È`>BÜÌx[O(˜?îó)Ë Þ0%Ãs¤+09eä‚`<é àšJùÄûháîFÏ1®r8/ƒlXÌ,TVÓ±…&|ƒIq$_:Óé™xðLç»X‚” ÛÊìB1ºÄ-¹Ïwä½íg¸c¸sOY™ÞŠi¯ºC¼V§BÁ•]À„zŒí®’w^Zzt]:H1i±a­Cå—Ú:ɧÀ14X%ÏÔ){´OåT‘Ǽº‰Kj`ƒh[ÇëÂ:„Öß yîDV2îTùÕ5s™÷D(¡$"±ÿl{Zxd½ÕOÔÅ}•lÈgD#ÅÓ/R0qÈÝêÁ‰<+jµ6 ´Ú ·ló 0ë¶€¬oIø§$L÷X†¡,ŸG”7Œ,Kì“ôÈØÇµ"®xVîÞù ¬Å„*gwõPtàÊI”çC ͳ!f;]™„›Ët☀ü6}‹IP~æ ãb9ñ³’Ä'ãq¹ý´Ñ "YÞ;¿$ÀGS#°ò$¼×âa̼9ë>B? û”…~ÆK^·Ñ­’öœˆy$(}‹ÁÜ–~Z^U©lä½—9BJÜP#Á舔ϕùŠ›Þ‚½h·|X¤éõ<žÇàÝÃ|EOé#ê¶ç Û3ÑÉ@Ô ‚àìˆ'˜{EyqÃ4:vrÕv–ò`ÂB·š‹Óåá,'v]ÁV0Ùz狎ç–%ªD‰œ+O;,kö´DÙa& ÒÙ–ªè@ +÷¦9*ß™JÏ g¡±W<ÔÎýy¨²Ùp+<"ž56ƒ4Ã’2c%¬"N¯…"í£ˆ`ÂgÕ±ô°™Vñ2ôͻǺÝ7üíö4›}´ L¬K„jăí€Øã‚’`°Æ'¨®‡Id@Aä#^½–ÊÚhd»ò¬‹ð™Åzø5¬(œçÚ)ÖÞ“ÍÔÐ Â-c4–!µÆ Šp‡v‹0C €€ñ´|lKâ/¦€¬ì®(òÌ€cÈA‹½ÕJ¾}}‰¨+‡I—ž: ¯rºÞÒÈÀ,ãM?ðÀ~bŽ ™m`%:ÊxÒëE=«ƒ8hf;q©Àj´x3-&~=r9æ ¿[ɑǪ¡<¼í'’0,uÒ‰Ô\=ëžO7O:‹æ±]\ÏžZ…›z•CGº½â{ÚßÒðÏÈéC³|Pl©ìÒÆá … vØm Õ!(Ž4%MŠWã)c•¾6eÙF=AFߟEnƒ¤¬„—øœÕEŽeŸƒ—™$®'qɳöòÑ„(z8\l† ÝùV-xRP¦)‚ºìÚNv¢ácœŒè^=3CŠ¥léS©cÀÀÒCèR¬í@“ç]M––±"¯@1TÞÓÔƒÄW‰";¤R£deÒ`4@¥07¶/6A¼i¡’€&ï`6pýIŸÅÏ»†7q-<¨Õ7Ĺëc»¡D䩿Œ rµt$fÐÔŠ¶¥arbŇ6#Ö·:U^Æ·8üÓ7ž¾ªÉ!“˜žp.•ŒŠ;—Ä5l;&xUÔA8ÍxÕã-×O\=7ö\J;ʹ*)%ˆwÔÅu[¶É®ÈÅR“b 刦›ãVñd±ît½^v½ÖI{^kÇÎaïÎ.}9ÎÎÖ_27»ª›4`u!)w< ð…X{—UÊã­Ue<¾üœ"J¤šá‚îÔKsvnžÙ(‹Alj ø³c]z•P"bÈÐÛb[98PŒÉæèñvI—ÞÏÛg?š]Åž°8á}oú-c\Ée[’ÖÃÙUópx5x{¸G¨;—žK‡E±Nзw„~zGùü¹OšÓ-9Jª'v´d2ÖÃÙiÁk*$ƒÈÃÜ[K˜R2EЦé v}ñä´ZÏJ,;Í»ÉR/ÊÃ]<;Ú¢PåŽÞªª™0.ljQ­Œã“>¡‡ŽˆrLæ@bu¹Ûš‡”G¾âÖÙ ž˜Â%‘£÷šž-o³žD<¶Åá)öEÞ)Š’†{ðNïÜÎáÚk-‰äŽèª¢½´pŒZÌ ½j“-‡a˜uPyo!Oû™Ë:q6/ÔÏáÕPàFûâå£ ¢½®2â»x~ö:u ù8"[Þ¤WƒÇêRX4j»‰«öщ¿N;šÏáUà3jº!¼§Çêkð°ºO”&ý±?­ö 쨳‰Ñëz^×\ç\¬ó^¿ËàÇgÒƒ5ËšvAçj'žsè(ÀþÆeœé@³)·R|Øn5¯Fe;­ß ³ž¶wÏK×ëFºßôÑÛ7BTóžˆ?ßä›íeÏô–»×•2ßܽg0u;:û|‘@èsÛ¾fJ22;>â"#ÉÙ§XÈ"î!òÒµ£O¸ÆÔNŒmDÐßnbŸðÎ@˜öóŸ3Ë¥^@°øãy'¾fµ¯R•ê]V£1Éå…ÐîŽÁ%dŽfø­Úq©±&¶ŸµÔΛ(@[ø”~GÓ~IÏðÕ¼Z¶vOžDpÚIë¬AyÍc5j0Ý’),ï)ƒxRœ0ŽngÆ©É !n°D­“j¤E»È¦Ç {S›âÌÀ6ôƆIØcÚH¬Í¥ž1ܹ¹yú£6VcÐÓÒn¬–ô ½ ëž¡,u>ß‹{ò¦ ¸CUT…ËÈÀYÏ÷Êu_´ W™xqÐ-áaƒT17RŒv;æžæô“‚u'Kg¸•'}b!â@hCÜ]"›äÒ0ÞtÑ’ô¨˜ï—HÞ’3Ý. Z££ŸŠy#E¼'QýÜÀ™Ÿ'âÙ-¡¥ò “8[ð ÷lw¦yŧHè3¤‚h»QX¹ZÖ=1Ý8î¶s:¢Byy]GÁŒqX þ&54Y1-–ÝCêwXNÏa 2ˆ¥¶É %™Ñ$©Š|<§ŸIï-ó™Ÿ÷’…¡±ã­Zr½ó—†‡-D¾Ð”†l|zj¤ô®7}0ã\Ðàr.¡jH€¥¹¦¢É<µ¯AB9=vÕög}ê{¼tUòª#Þ,1P9EËnªo¿‡×•76¨¹ï6î.¼`¥šräÍÞÅM¾³Ò6y"ƒW™ós–Á«°Ñ{hÆ!wðë—nÏÍÒÁǘñµ¼7. öâ.YN8¡¡&ñ!"«J Ú¾eò½+ußx /« =æ4Ê+ùñÃ2ë!_s…•ÙëL‹‚Ž|B9¯œ2´ÖŸ°nYït-ˆ•¿ÔÜsÒòò2,lV eÙŒ“MÈ4€ã-s–jyŠXAú Cxoí.«YSo-8цhêc. Vï—Ä$Ô|±(˜µ^(“X™óûi½‘ŽC„sCjK}‘V½ÓÕÝz4`$UÜ¡•¦mš‡P8ˆê\™qס‰*B¨füÄkÛ¨`9:Ž Ùü6ë­iþœk´¸39¼Ý1òú9ÍU/½{T$ MjiÎÆCÂÍÒ8Ýï8‹PˆòÍ£d¾¡®QAù ë§ŸxH¤í«Ìu{AîȬ 1ÞRp˜ÑLY3Šy¸µˆ5¥Žd­úÁîñô Ô Å%¬wÈÙ:åªGÈ%àa—B¢;K4àÌOÈEÚ'P=_©êõÒ$ÕK[k´,9ºÂÝ€²X 7¤ eC ç0}˜ûêmLðec.â%ž·ÅÃëvÚ,z–3%º¤ìïÙÆ(Ä*B)ô‚«ŠfnNr{ãØÄ[º¼}Zx‡/6·øÞËys.®:{ç™cB±˜WGh»…Aáïmj<ϸSM7ŠK¥›Ž’ 6lywnFÌ;l¯ú Ð4ì5 &Ñøh­ $É|Jå}FØ.JâwO–¶G\ÙCò {$kdVDߌtÜuâê*Ÿ)—4¾«¨gÎÈíë {[œÐ'7ÁXæ±j›tìKò¬Û®cJ9q_€µ¾ ¢™$Þ'c„bPyùÒü@€”¦¤äI¡ÄâN§n¿r#~\þ¨Å6¯oÒÈîT=ßcÚ d biNÖ·lØ4¦‡t8Îøt.^HCj‹ÕÅ®Ù:\˜[î’Õâ-’ötìyp¾´éªfµ}pûöOåõh“$ð—X*m¸4OBµ½Éˆ Ý dàÁ¤# iVóª€ûô#ܧÃ+o†ÑÌZ8rÁ¹¬<ß;ë§Xä3ÌjmÎeá¼i=÷ò~"¯×U眡<tÍ5åÜÄÖ‚òÛì­A±0ã=‡3¦°§Â3£=³Ï®´}`hº¨žLм«)QkH^×LO É#½:Škm•xØ3wÖC ÙBêYOA¯»2vv ©dß.4¿ƒ"wÌÖ¥·(Xë±[ÚiiyÝwÄo¬ ±"¶N¼Z<Ž &û],ù™,/¼•âÙêU°|¡ãÏGíÒê2µa¹ùˆØ‚S¢o'^MÆ›W?c­wJ 5"N©ZšÕZ›?\/6d çl–=tÉ=´ÛÏ‹Ùú¬)àHr^¬E/g\¬ð§\ô{÷z*§Õéb €ºT¹v+³Œd+Ydrb<ÌïŒÏA·Y„UÁ÷hFW£èÕB"×išB¥nôb?¿Xt¤¾ÐÄyþbLæ¤Ê…ÝnÌ7…×ô¼Ò¶µÝ_8ÂI\½ª(€Çè„Pl‡!¤®zïÄÚmh×>tÀ׺ Øqì…@îoj›1¢ $§ãmˆ$ 3a4"ÊíÀÊyá=˜ëG&|ØÊxÒ-\>F‚±†V £b^™-H"yF—œ\éúS0Åþ¢ PgÞ“B]¬ï‡¯MhÈa–Ðy0xo°Ã%B€8p½óù¨¬"Œîôø~ Æ?óªQ¶â£b¯W#uÑØâJŽœ¼Y•;+kˆ+«éE}ÖÇ‚ æõ.ýìXúkëÜñÕÑóœ‡ëÚb(›ZùŒMØ"m ÇüÈ”èê©g™¿Ì¬|+üRççôEùáÉ­Û…Yiê\îC}fϨài:"º ÖeœÕEöqr­€õ¾¾9Aê’«Ø—õS2@à#—‘`ëV·ÛvèŒrÞ‰¾S‡á®ý:¥F^Vl‡¦fY9J‰ û»«Ã}JÆ>£îÍXÆcN®——5–œ²üÄVt¶Î|ý•%tÂzë×@Óä2@+’3¿{޵\„\8–ˆ>m«¥/8]ÏU•¥‘\¢¯"í)¤Y=!JitçæÑìv]E%UÛ~ø6áez'Žª¤‹Töøå9ðK™‰2Ô{–àè Q¥•G”)À Z¯“OÄL1<†òjÜKSÍsýâæ”&’Ä#´’{Æ4‰j»|ÁAJóàñute—•lhn"åLês‰¹W®»PâË«…îõÀ³ã-R¼ô@¤'»¬¸ «€{'>8lÊqlµí°Uoo–ÄÑ+˜*ñµÊC¹, V¤yãj›KÅh+¦‚‘"ã{Xù‚Óùj#o2à,s Øç—l(œÝ*=yË}—µ®< ®;Jî}8wÖ\#¼g»<ürm¡ #¦ÕøPg=|õ½ ú”ÍcÑ}/îÕ¹¾wf…ïÞ¨uiM4žä²˜Ž”ã³¥RiUqé<ÚXÏ…"“ßé<Ö@aGa‡õX†ba±žl]ðᣂu_P€Qª‰“Í{îs®ùžÁ&‘(:í{®Þ¯É¡¾R¿4 ° àVœšÕÎæNçNå',AÁ‰TÔæè¶´ ¶çå»G6í@͹,‡)P»šØÏ+mÑä˜QÕ ÈÂùej*î¤:'Ç.ƒƒl¾—qöb®ôFƒ_d½h‹£ŸÂ±ÞSÌí2¬‘I¬Ž±D`O1¶—bæaI“ iv½·¯žÐDd%ˆ¿Á/á(|áf _Ájõç4ÆlÃYe2wë †/#ÇX @Âf–^–“Qéë3{% ÎèõÌòí³™+ÅŽ=JÁ{’"þ\ž_Ö¬š.ö˜œ²H&onÖr N;òÄmæ;8œ8ç7Ö9ÑÖ’믘‚]ª¡ö<¤âpçÞKàyõº‰Ó"µ”ö?MYŸqÁ&‹™:)CË-Æ‹§ù4›‡4í¢Þ —<*ëx ëë÷lºÞž–sgöEî•"z]ßÙ¾W{l[3í®ÎQf?#qvÔÜÄÚJx€W>1%γv$>C„»©¸«M€éeäÉþV•=ÀŸÍÍ›µKÓoéøg¾IÑ:cèwÎ!n‚ÐïŠÄÄÒo»/Œm¹I€ HÁWq]Æ’ƒ[mVPË…á9½ºB–e®#*Nâ ä:Í*ËrÁðrt+ªž'od™Ñ;»˜n”›1×N[Þž¦%åë8Þ.Ç^‘y9Ouæ5‚gGŒ<Œ°æ"á'*|Ü‘jˆYX£C„úMR‡qרˮéãº1c²¤³Üè"g%HpC«§´Ò8*©3F4ÖßãÜ.?˜E‹Ž®ç•ïô¶Y¡U„NWßN‡þÀøx__4ñû3Üš*Õ‰¬ÊÛ+||u%c£T‡c=ð8­Òöêù¡lµúàÅ“ðµOñàg8.E~Í8ã` f”8âf¡<ͰW]èÃïé£Ê” à<#¾-•h 8² ‡Ð= ]Å7|wFƒÁypæDB7ÈìmôÞMb1¶‡bɯÇIˆ›$±ˆÉI{o±†×à®Q’q­A cì+ÅD,§Vmž)¬ìAI/dÎwž%£ÍbÂñ¢l_à«×ÛeÌÍŠ¨Q‘¦EÓ¹wgî—F†#b{ $»I"qô¾Û½ïÛõÞŠ&Ï‚´À£•öõ*!PÒL©mN["ubäÁðÂKæk£vdy.nâ¹Ú¾­—Íô¤uŸ¼A½¤쇪—%8GF.~4 lý ÜNß{4Ï-ïE4G`¯‹oR*L–¦Jò{øB%˜Ã8›žx,K BYÏN?:ŠEÈÀ 4—Ó2¢· Å/8¸§ïK ØlB$‚x üõ¤€ST f©‡jðž&aDqM‹$J9‰?‚e|MDÕPýVòêŒSGð93œ´Ö¾j‹OLȧ?sOCµ¼T+€¾–{ýö=Û›èÌóöëœSof(m; ôƒ÷NZZÄÌ…_Z}ÏYÊŸù½ˆ½»ìW½)dÏö÷Aïs¯ ”vO¼[¡ˆ‚g˧EGÑÅ­«/c¹E_’5¶æ`(°1°nKÝbúµæciB—8Ä×ëÅûÚvB 4Õ1:žòº¾%×3—eJ‡÷§hÔ›Ó¬Û‘¦B—™]›à0»»ª™ÌM«“ÅJ‚ý€Ô©Ôé9áEx3¡2ê£ðÅËÆÊª¾+‰×îÞJ`1vS}ÇC(F'”nD²–€#¦ö†Ñs{¬Áس9/tK÷¥‹g·¹>xüSBS"fÄ=Ühkãø “S’ºÌ–OBNÊÒ<·ë5ˆNUN̤Y]†FCæ§„ÞgtÞí*¿¹|“Jhpjd§aãxΧ€wŠûÌd¸Ëè¨=êxýDwæi ¼p°dw§´Ý«v¹Ž Ú¸ôWž·5ÜkNó&%€œ¬p+Ü6ñ ý,3z9u£ú)]©¶ÏKôI¸XÁ,º…tl$¥S¨þŽ Ã+1V†ìÎàå])ú"øš­®?äHɇÈxƒ£ÌÚd”þ‡¶ÃÁÃ6䇵«Y"Ðõ’ u¦4}"Ž _µ1´¼òÂÆ~nõâÕtßp K1J@õ¥Ê¿Mø9¸®Ì€‰ôy9U[äŽ^)vì»sVìÈkÉ O¯~ 1EüÀÞ3rAp0| dÒk4-ß"òOé;Þ—½ÒþÐGå¶©Z†’gž8ð3Öå‚9ÀðZKÍ­tbÔÎc†=btïY*Žîx™ï…˜§-¥/ŸdŒú:jù ºÇUÃÖAp ¼SæÜÈ¥š,ãroÒÑ’ݧ°‹{âW—AÝÂqÞ¦Ãak©©¼UQân;Ç}` ä-U#SLˆl˜Ã·H8o£î=¢¸·¸}’pq°•o¤·ŒÜ<‹¨ù`KRI˜8[õ ï¥ãe;¿g¸Ð"|þLn)`¯&ˆäòîÓ+µGtŽ/ÕûÕòzÇ/ ^–reTï<ó¥ç=óf«51zK÷+1e|˜9摎@ÆkëåÁÇýd¶{/^è·Œä3NuÑ30_l ‡0’ƒ³s÷;è {ë¶­þFhC‹/5üe‹Oä@°Ï¬dø8z¿P°‰Y"kŠ~Xž;ÎFW#´#OÄò\6Ä\ú{ ˆQacÏ s…m«žLw,ò\=öG¾‹ùö¦¸sËŽƒÑꔳ¦mÅjë¡aÛb)d¸9h¿A¶RF-¬Žî…¹ãìœ|VU®µf¶ŠVµb~÷Ãß›b…… m5@ XÓª!=8‡×žïÈÐ6û­ÍÆQßqU‹$Úšiù(0¥ö ä³ÿlj["ºŒI¶y )·¼èˆ,-›ˆ¶|G˜G¯6+’ßÝ)Óò˜™_¤0¼Æìc•HîO!ég°>ŠðQ䙇¯礗!#¤Ê‚– –-¥pâÑmæË¦Säc9lvo@äuÝk!ÂÓ•c‹Ñ{ä=]QhâÃÅ¡Êô莻tg5YSdŠ«.Œ+û+mñ*ÈGt#æÐd±ÅðJ(Wõh\“N^z_fWöK{A9ð˜w åÉËóc¤â¢3XÞ«aƒõôÎFqÇ0¼J®|50¦kè“}þ˜‡9%†ÜλƒˆßZ’!<,!]öØ+Ø¥‰^œy*¾N;ØæÊxC\¯y‹¬ùrÛÕåçˆ/§§Q9ÞÓfý(ÓG_㥓ùópAV|P'󊫊'ô £èÅ Pé°Sµ?„ôï“©}Gl³°%(£dÑJ‘º7ÇÙÚS·žY :¿Œ‹ìj~oŒâèÂæ8¡îPv*ZG¦ê{nðÁµ¾Ê> ×öÔjjéo-HÓà±Oa+ÎÞ®1>’s'œ=ÒÁ½1»várty2 ’ÓAþ,tŹMWoíud“¸e>Íôs‡wt[â¬Ý¯8++ËEŠ9/ÚHD=Ú’Øc豜¬F£©)SbxÖááqîƒoó€Ò©u›,33"^ÌœÇö0sšU¿ÅpO§¬³¶Îc ü%¦BÁºð:å£xù 7ڵ˸_Í<Ó"idïT-ªÏäAAšÛÜL&{Þ{¾U;öÆ?ÅäŸa;Ž=g£Ø¡ÍߢÁ•)odÈéc`PÛÂêÍà9™ìW'I Pær>GïÚtI»¬–qšåÀßëÙAQ«J ï»»¢f,ÀÑä+F‰n¬0™ ¼üòbgMÅÛÑú¬â&&{|HK"_w³KžsCAb@ÁÑf—ÌCD\„£{‹/Ø‚L$"…¦Á£XnFˆ_A_Yéxn(w⥠·4ΞÁê¡×åMm×A92óŽ@EF„¼hl?oå1%íçL´a#wF^ÔlàßÏ6÷lìÝL$F {0²"èãK—¸ƒ+q.ˆ¸™Š‡é€¼-嘉ÃMÆ0d)«Ž5ïÛ›ü3vç¢Äñ%³bP®V÷zWÍØ¯ìÄ( ? é×qûeT1vݼ|Üûš^tø‹n%‰í XJ‹¼«l°JX|vùHMGÕÅ`CÙ­¤z$b}U3w°<1°%ŸÉ³Sdc ¼ÔÙœ.VbnzïÁQO•`œu\Jz(휒PÃ; ˜ÛË1°ã6;Öòç‘RZÖ"¶3ïTO"N´=´X:ÐJ¹’¥õÎ!¨òlPÅ×ì:d<5ïÖkÀc>`7» ³Wëшøf„±q…“ß4=O:Xý%¨(‡Àðé^zh²ÌÎŒÃù€Ò sƒI×ÈL2—ß`F•ðP‰¹r€ô‚<®êGõäX3~ðø à\¾a-wM£ùàÒfíz¯Ž ©ãÁZÖCaÂ¥ØÕ ¹l‹(€èˆé™2ðë•Dó–fÙ¥rEÃÇ;ýúA½adU¼Y3Á½i1ˆ&èòBo5û(¨_Sâ™Öΰ±æˆÉs©§9þ•ž¶Ú¨³šXÍ2kSÀÈ<ÀÕFvÍb²°<­"Á¢ñ[“×ÏžS-ÇÛ,Ó@EÒõM•­à‘8©×’ýହØÖŽ5ÞQ–ÐyÇ?%ÅÎO¯\Àe+dÕ<œk *ß³]ãÈpšb;:šçîȰPØuƒ^sâ>O$ïSRß6c!ü9õí6ÌhM¼u8«ŒéÄØ“³-@¤<ÕÑ|ÕgƒZ Ž‘èA©ltQ,ÕmŽ"»뼚hŸ‹îÈe°½æ†¨YÔP nÂP‹SIÕkcÔ{Ý\ʘèWクԼDMž¢êGH{'­Ö‡þÔÁI…E<ÚqŒë®÷1Öë/hMy‚,D!3Ù·h_ÒñE¼Ä[½{3øD°÷­µeŠÂK,róô°$Opi&Y„$ºÂ4©}M Q%’ïqU6Œjb«Ûp=Ü£«ºèg¿DÕãÍk›‚ðæUC‚OW»À£Ÿ(À¬gª˜Ãu·³Á·ð¤;mŽ:Ó·¨ð3”[[cûø v˜:Îó{1ÀOtVá™”?0Ø{þ¬™¹ì‰Iáµ%º†¾ç’\®ün3YB2“îIHÚh) ‹òì2Ve¿Çíɼ;:2!šáê¬Ú$d%»!@s¥›]##š‹¯Â@ÕkÑ^{ÌÑm>Î:d|¤íþn”’Õ¹¡Ù‚Ž^2zu‘-á=c»,¥6Ûd¯þƒäžM–¾F¾­5ª“*Ë’4?á§ó¸Ûvé••‡Ã‘z©×)eÍŠY =ö[|%/¼;äÀÈŸB[ËHo½´š÷µ#ì_²ÊôÉÊêjÉW Àu']MíOâµ$œ¿š÷"1Ek%Du‘·ÕaQ¾¦÷*‘î [ϧ¬>e•šïÞMK$³c®ä½ð±WFBÛ'±ì±/¡msWI×jÂÃön‚í^÷¬jÁ{ð”zvnXh…Wóµ%8Ò`·±• y“ˆ"À–’M5Et¦Í¥ø± E\r²`l0ªÎ]¢ß%˺˜5¤kk=½Ežò¥ž‰é«t©™é^HK_9Ç3¤ñ[}ŠÂÃCÔŽXÃqÎð˜‹yæ)ÆÃ’ àHæ¥RΩ !Žj@Fé§7¥ænRÜŽ Âùàı¯¶é%>x…j˜XD!èWÈi¯²%÷§_åÖ;§È Q‹‡zÖ…f;¯#Œ°\0Kb„¢n[‡2Wî1B¡(½‹±:œ2®+ÙüÖgPŸ¸L|½µQ6+‚¥ ¦ò ’9ØE KÖRúœqÄ@jšá•csgÔp•/…`Aµ IR¼­ApVw½•µÃE»yËùpÚcýú^²rçNav‰øòˆÒ!s•»î•)0[82NH=BcÇÍL«DÙv‚*iäÔ}°¹-I6 7× ÇRœÂHøÔAë5Iõ@fr ? “)Q½¨7ÈvoAßkJšTÝNáGK¬/¤¹•„¼n˜6 ïõDU€?@*¡zÕ¢ó¼ÛSK¢²_¸oÖ -&$6-¬ý’Ö5^Ûaœv äàS*z„íQ€õœwr€Ò§f+&¼óòpi+õ©õ8j ïzúw+äÏÈNãì1´âÑ„ö­Cn0‘Jb «4—bfòètÇi%奦w3\#œ¬–‚„Ùå mlO2K¤Çð¯âÚ{8X²f‚™cx#SXl6¨R Uçáðh9T¡ó¼ÈâVˆb0}ʵ!"vTVx»«_=Fãî‹ âÄ'®§•NnòÒs´ÌQ„ê?”ób9ÔÄYÎÒY¸g6>®  ë^Q±Ñ©ù ˜Ë-iêDÞŽ}îçTÚ çëwzËÍZMeÜTÎyeðø‰R0¼‹seqCÚ¸\î䟾åÏW`¶ð.ÚÓt«ñ·ÜÞì ½‚©­·iãm“ÏwÌPü),ÈK;ÃÁˆ÷)®÷Þe1&ÌÝ®3Øm‰ZÏ›_òd)<4zÌgéi)¤/)‘ ·¯ed¬V²a\&!„æZ%Âæ=nÂvˆ·|{C¡X]ñr˜s¡{Òd<{_µÇÚðÊ  Ô¤Œª——@]û*ø¢¿{ÃI•ÓïNl¡¡Ú3ŽŠ’ôFÇ[ü2³Ln ó(½ÚŽ´žçËyíŒ(*šnhÃ%Ä©~çÄ+"`‡•ü):¼J^NÛ ñ£»\iºJ‘JIn²†¤3¬1Ä¡[´ˆ¦œb,–縱+ýr޲¢áR ˆÃ¤ï—¼@ĵºÌãø ¡Ž>Ž~±=Ã-L""¼Ì7˜à(C»µ¢þZžy'õÌí§¼ä3Æ·o˜f=evëåòy+Íİ¢ ÔO ¸p(,²ú9®ènÂQè…³Å\8äi¬qG 6>®]‡\drTêÅJ;Mg{jQ™=ì°õV‘:" Þ(`^¾‹$é)Pq—pmÞ6€f7D¯ÂGÇ«“¸á>WŒÙ&c¬Œûd“ìÑ9÷]Tg5¡ªKÝ˜Ç ‡!Ð+tó$÷Hˆ.6mÜÂò!PòÜC6u¼‘´v$€|ú=“Eå­ur7›”ïyךð›j}ÕµW­Oa;è”'vãgsLßãA‚ 4QÜi5 DÅÙkAAÒ~YG’—j:D Yã~ìÜpÁðxdøDû}7Gýôøäé•=ŠÄk"FbËxQiXÝèDÃd4 ¥NŽ¡Mr¶ÒMGW÷ÞC9è²[51 ,|ñËÅSb–Xª·LQçþÓ `gÊjâ4›vÊr¿•cQ#¯™ya2eí“^Õþºïè=Ž70ÏC^˜›Ê¾( >ƒ£NpRã$Å÷©ÞC$3òñjj Û@ ÞQ@8•K“Ä·µOíR¬—k^œ£yïuŒÉ«F8)bƒ}KÌ?%vs9Ý1•Cœ ì­­Ò“˜{&F„ån´Ãcrçs6 J6¤ºDo©9ÎÂyŸˆ× $Õß–h%ì™R U4»Z<—g¹®ƒ0nE€ nž>D­Íë”ßÙ™@‡kYA—=H§÷¬+âv…M[¶T¶cÜjZÔò(4²Øp;b¬xÀš p*?,‡¶Ç­éBeõ®š+ «QÊÙé±¥ú“g}ÜcÐݾG>P*,…û|K”¬êÉFxQd©â¯Ÿ½|IÇ»px¢ï[Ѓ”,¼2»é|Q r`•®õWÖUìÕ»&’võ'¤›òL+0¡šzY‰Z%jIbÂWüáÜk:f˜7Þ³ku˜ôžÐÛíV¿£Ü“:ŽuKÄÖŒYÌJ‰ÐÎÎÆîg{âžìOïżu*uî— TPâ]^5²sÇãJçš=AÙëC˜ŸM³v¹Q‡§MøtŸj3g„§195Lmž Ó ‹lÊê®+BX¢Ö‘Jó@vEün+7°úShñüŸ•j&\•ŒZ¨­S£5X&2Ù†^óò¬1³zïZD¼Äº'àÔoŒdÇç!tIõœ4?<³Ë.œ|šRQÔÕ/6ç̵zÜñØ0C.ÑæŒOA#7áÎb$Y…ïÚ!§4€²-¹<ä§ áHx›‘µÔƒÕUudm¯óXͤ®°ã…‡mžè]¾É«u}OÕ¥-™@ÛÒ€u_¶£ZÄiðä­Æ1pïÛJˆ!\`E ÀºV•2z)Ïà2Êr|ü¿â—{ˆ.(koö+н/l"‘š™¶ÉA™£&'{’n¼ÌI¼Øäˆ¹ÒGÈVÈ_¢®îmäúÞjÝ}íž»…*ˆÉtG=ݳ™Ô äé4Œ½öφÃçà}‡§v+Üî¡ÈÊ5ÚÅÏ•ªÔRE—'ÜC{õnÞ¤q˜8Äõ\¨ª)Œ®(¶±ŒÃ‹ÆÞÙ=¶7h,“)Ìø¬.C¡¨{_¾#yhZõkp=TÞc*ŸZLdéGˆR¯€ž‹&¥ó´Ë¨9Õ¾zuo¿Bóäùæò&?¦ JZ¦„#µcì&5Œ-z2åÊòiò1ïfÄ£×1vhªùª 6ûµÅËîVï-Q•a%ô'o¸5rA<‘ÙÍ+ð9î¢q]C=}5F>»ñZs³,su—SÉö·ØÄÃ}åêB )WªO,g>2ŸskAÂè^=’g丩â(–¼qlAƒäYàÁ°Ë¦Æ·ØàsØì þ‹ŠààóÆñ®’ySXò<]Þ›àKqVxknÇAu„ˆ–-ëìÄ,BÆÈ„B”%ëâ,ФP6È[»g.Eœo\LS'M_úŽŽÍ ±”'#ôž‰6z¦Ãbæ¼Á‹&’˜]4Ä¥n¿dÔ¸²î×Ë^¬t¾¬¹áeëìÓ›ï,¥âQTñiUM‰Ê²š6¶¬nñ %œk&ñÎð€†½gdñŠç’41'ìŒÊB¨ÞMaøñ o=¬‡úHtùÉúx ¶ˆL{¼Œ‚ÃØ»,3×üÓ:† ØÆ1w²è£ß»ÍàˆzNÉ)›zk‘4e•k+îe“À3.ˆtSMüX@(-«¶¶Ì€"î¦Uò§Üð{÷ÏÙo#µî=ifÖ^kº³Yw=ÄÓt{pf¢ 1ÌÒèqœÃI¬aY“.˜Žî˜ÐÞ×áEm@¢¯©åöõ«8„¹"z>0ÐEKîvó$x¶jçëC*ˆ¤ )áÉŽûhP½ ×Ó0[è‘ľ%·ÂRf¡59+ª·"à⊾JZ/áò<¤º7Qà勹E²ÍåÁó@Ë+y¾“5‰@€ˆ·Œ¯ò OV(p} /’¨‹¸1{í1 ¥YÂzÌk@Uó¹ Â_’3‹Ý>Fdt¬3î÷ðÊ" <àÅ’Ïñå̾ûzœ ûub œ rM¤¾“áw™•Àñ)9þØM*èA/¤—D«¸<8Ò4À>t¡KMhÏÜ Io(Ðhš<áJPò7àÎr@0)C§ƒò*ØÙ00Ñ€-*õ^N;êmWÁE¿§e.uB`¡þpÅݼŒ[|x« ¬÷™âÍf-Ê,cÌUÚ£ž-ö‰6wdLµàÅ`UE6mÇÞõIŒL ’zv7fù¸-aM¼ÙFƒäÄ\ÍCÙó­`«žøÔëEØk°iÇÈ5™‚q{wÎ3“å!ü^ÖÀ"ÍÅŠé¸ä„#h±Rˆ“Ö›Ǣ(¢ ûêU9½bî—·%kU0¿DÇ£/d‹'ß:?ƒ{¨KíY§bI:ïF_‹±”˜S)þ)ÓÓèöÏ[×bà…ž†ÊëvøÝû¾<ëÆ”¸½ÊxmRéªÍ0-]Ðp¾ÁŠþü…èŒ æƒSô—WË“g äƒÛ}uÑÚKõ‚’ï ¥è­$s˜Ø½±Ù•¹¡Çˆ– ªžÏ°BLuétæyó‰ùà ãèÔDÞ‘tUTãdt ½Ëóa;½Þ&J€Ý¥¬­ü–Ýçø –†×Ûaeš¶cEõNké3£ØDuOÝÙ†k ÷RRŸtâ[o³§£"ˆJ N í庀Ç3;ÕŠ @».[s—þ\ŸWîê]ìx ”OÆcàvf)îäÜ™ƒ’Wí£Ê„ì%CRYÀƒVüÄ3Æœ@OªlÖ¤¤¡ÒåÕ#¯rÀ5À˜~·™#Qmˆô„ Þ0o²²(Ç•µqSŽxŠVú-¿ZžNv'å›ÂyWL.à/)8¦ß÷èPŸ¯•m@RîX>,@r!j:¯;Ñ´[µÐxD½Î‘1OÁøg“çæ#Ré€Û{ÕZƒ–„~°ú<ºhü‰Tí:d…ÇÝæÓYæ§;5ÒîïùíÌËœ7ŸÂýÌuoQg§‘Ȩ2™†<ˆ°fô_&Vzߢ. N®›LBÃ(·Dó ôkM·ˆè0¯Ÿg;:cÑ$¥W>êÐ}gàú²ß[½xŒ‚k¯Í)°N¦B8VCÔê4û4˜ª*‡ù<žÖ‰ãkPTæÁdAŽâÁQ7ÊÅ›ÐÉÚï@¢°ÀT¦ÍYJ:ß\%8`uÎ\¢‰·—>Ûì«÷Þ+—|ïŒ=@Át,ß9«¸¹«ÆéÞ›-ñoN0Ñ‘¥{1˜–c¼pP<\r}JTèæ-ÌûÒŸ/ KЦcëÕýô¼n¹¾=©t{ÉheÜQX¯OÝŒçáA98¤Ì; \µãŠóî̾yôÞ5B¥xq>ƒ©çõ)=}Ÿ­¶¥Ùßî‘ûö’uï% #YE›WËàjËÆê`‹gW8`ö —WT¢1ï ó=¨*w§¥'ͪÓ,Nc¨¡–o1Dl®¼Ù}N‰(ä‚ó†ú¥+¾AȰŒ¹;뉧—OH”g†bÊ/–ß”Âd2©¿0Ú¤ŒGº½u)Äq¥vÞ•IyºóêýÉʼn³ÑPßmËËèJkSë”à ‰×YöžŸÀ¿ N {†½ÆzÑî:›˜õºòÇɵåÒvÙ)âv>%-ði"vڠƽ¢Ó¼i¿iB#…w,ý´Ãæ§ïE1k½¦†SiÀ<>ȧ}XJ:2uX´gǯ;YQn®Î&£'ß$Ñr\0 ;~ϳö9\,ÅŠOÍÛÄò>Qñ]=‰ ¤k ¸w >ÑSï%ŽT¼r_ÇË~7'ýâ=:ä Äq×§¡"ˆ›wJÏý0ŸEÙb¢(,†ÏtwŸJ@ð#¹³Ã.¤§anúÀm´²I H ör½·åˆJ°%²³]OÊ­S©ôêDøÍ€(ìtš#¼áŠÇ3E·¹í‘)«A pN””I· ,0&kµ¨w$¤ÓúØhïÑ¡{Ö¤n¤žÜÀ`¯˜HÇ]ªäAÔ8è/(ŠjÀ8f;¢™wòdSÓ‹  @»Þà°å áì‹}åÏ~ɯ³ß#";„~Á2šñÆ}Ë8éK£<¡‹rã/„s¥‰1 GA Ç2o2; N•s5³žÆÀ ¦<4°yÀoSs$—%BóÀüƒð*Ïž³kt’U xÙ®ã"y£¡Nsö-ƒ¿"\x} Š¶Û‡¥ž½”yÒ7÷†÷‚FD* <ã§ú”Žpú#Å!€1|ÆcÏýø‘=ÔRmd›'rĆ]íºðP²ÜsÛNhYyÞézŠù@ŸÔ¡©®)ÌÊÏYxåÚ¸ €|°œ22Ãtø\ªs°¯Å-¾XW<ˆ|˜NÀ½ADÀg¡¯ÞImÓ· ‘>ó 9e•QJ-s‰Õ ï“Z]‚ˆÑ€Gí)O`G·DÒ™ f|£šŸ ëNg.-Ò6úº³ÍYbq»m?¦‡³ë7âŠa"4MP»)pïI‚%û¡©'ÇRÑÈÌìœ Ξ" íG˜LNèx‚z‘óTQØÍS(VðãØLÞv~ QXY ©8Ë]¨õAÅ™ºîÈEÙ>ìë±ÐÛ×$ÚÆèÚDŠw$ò¶&V.~Þ? «2&SÇa§U0JK)ž(Ç«Izó4¯ã'8¡$”.ß…>2¦€a*ÞÜ;½˜û"}&r½ŽÉâb°Âyý­<ìžý*läà,öÉCaÑâ - >Ž,Ë’#Ÿ{¬Õa\ÁÕÒ…›Xc ùðu½²ÄlÎS?±8èhc|kgt™âu?tTò /—Ä…îõqÈÃó„d³çègq+ðL—HÆ£”öq-“ȆFW3¿Üƒ‡A0›´Í§Y?}QÕ·'b®–Pú!:‡gGÇæaâc¾¬×=áúL¨”d3Þ3Æ3™çI6ðlÔäÙá›»L‘KYг<T—Íëwehè›Ãðä1ÔTŠ—:4T¾‹ê’j¸†÷2‚*^½îáÕÍ*™ª¬€7J `Bý– p̸ú^ã«Çf“¼wçô »è°˜÷iÄ*éMnÜk›ÚR–j“wÙ5>/j+ùˆûaw]ìB#¾Õ0¶ k¨Ãq‰ƒ6µE \_Ž&%Å»Y ‚áʃ Pd×о•²e*¸'sœ™Átœ6R —nHIdxÇØk%ˆ…¿ä8o¸^¸yn-­]^©Û¤í-=êRÈ9i•³~ïõuHRÒ¶@{š{x‚=€eã#û”ãû[x”ä¹³¼9†ås“Tß¹>~–¤é‹Yj#-Ï5Cb.Äœ<À©(•m±ï¡×ã XÈiw¼Ö\Gv÷í!ÌMìÈÅ|À>7hl~;†”û‚Àm¬§'üì©‹Y¨uaÖ3|¤¸Ëµ9|o Ñ™bxkïU?O7iŒJSÕIØÚt€,:ؘy:]ŒoÐßžá&qà˜B‡€!L½4¸ ¤»?$ðbÚ„zÑ]­<úùœ?Õ=#ƵlQ;؈U¢­rí"6!À€TlÕ~‡÷–<º˜œry3[Qh‡ÞPU®¤©8 ¥p¿(+ ¹•wS´`¯´²U ò›ðñQˆ9Æ\tÌ€ À«…±Ýñ–¤²Þ'6â¢ÈTØw{›5Çàe0¤ËsI~Í®pß¹Q>Úirº«€ CôàÌ.|r¬ Ë]C#°=Tlu€.­‚ÃFÚ0lÆÛ¸Ïaš=*(`³µY-?‘HÏ7õìAïê8ƒPÌ`(šNãKdrõá³…4-Î2èþy™cÕA«XVó\È X \âx<áÚæWWjRÉ©¬áH§Œv<Õc(Ò))~ÏŒ­I/<2!–A»Èë ûô<òØžlð õî”Ç=Ô)Ðñ Ÿ¨=&yËâŒÖ` VGÛùØÓ XíòÚ#ňȯå¶o„Ë÷B|a¼ì¤+‚8' Ä·Aͺíi#Y*îþ<ñ½ÁSRu_õˆ’ëžg—YO6´5\£³ösÑCŸ+r÷+‡î8j!}a-ÐBÃïü¨Ÿ£L@‘§fâ­0Juù:îhgO#„RÙÓ³wþd·\ÃLú ¬Ò—-îòƒåëõGÉžyµ ˜\Ó-Gk³ÂûB„D*ÀÛƒG$u’Z´ÇÝœ²šYN4öì9DOÆúôÔ̪Øh´½|l‘5ô j±óÚ‚ôA¢s)j<x-Å›9/µæuƒîɤ_×»¤Ô'-©ÎaÁC-X}K…šÚ/Ðð1dÎ1’©(”ß1²ÄªîXÛWqî¸Ù£ÔÑùy"ß |[dˆ’Ø×2¨c7ñB^³0íe'u pѵÞNršÝC &uq÷Ÿ92Ay̼ )‡3ºò‘ìJ°_gêRCªÊ¥#*à{oÄ^ä%º©NÉÁ#m)ç b/s¥oŸTÿôÉÐxÏM^ÀQfTà›Ú£U—×!ç£uë µ>Kòš´h+öÍF«wäÜ‹}»QØä¡v'nìϹZUhQŠ´g§2•DKd6ŸâY=éP-“É`¼{+¡”Í{70349ý5ó±môÔ*i‰=I(PЗž>¢+œy4Ä31É7g©ì‘jŠÉ|ùèÒgj|QQ¢ƒ¼„M0š6¡ð½^Ê;£°‹Žx±ïN½ †9ÎM{]ÊŒŽ©uÒs¨— =d¼À/q7ÇšMë„· ”À¹­ñ>>_ãççÖìL)Ïö¨jÅ"²vúdñØhÓ!ˆùô§Wìê° ˜?õ€,vˆ­ î~2wG×INzOœIžj‡saë«MöêÜΠ쀀ǴÝçñ)KûoŒPŸ(s¾—Ôæ…ô6·O\L²ˆ› œ¹IÝdF žæf4?§M)^m'­(“››úŒ4á@LL§‡CÇ‘ øJE°õ!¸¹è€@!¬æ³rÊð¼òè]—xÓkq{ìt}ƒd‡åÀù*âé½ìÈÇæ‹«  Ù#…—Ÿ@ÓÄP<,èÊš˜ôMd|‚úš³´º†û=šWà–-–Mä2¢ïP'ߎ¬‚í„…áÓ»‚=>žbð+~4'[ôò9‰^›2>L2w|í4:ÊÏÅLž¸A.§s1d%ʃ[´ð³=ˆe–t•¤\ˆE¸ïìù•§à½gKÈéW?ýÒ’Û£ÏV4»Ñ³•½úâÝÄ™ˆš5÷À+¾”à®Þ‚hóv]¸»{"5QåS˜þ9èh¹ÂpIâ«^eøÄ^½aë4·ÏÔO_ëóB,ΪljNòÍ€¸9xÄÌúh•·é1 Œ—º¾*¼kK<ߎ\™:£´‰ÖãŒõ*k"ߤ@0ÍÛ›´?ÍïCXÍ]EdC¼ÓGDˆnS´w›/F$F1jHSQ«nÒ™E@® & ^£Ã`³T °/ªúÅ…>²€z+rÑYpK5CÁ2¸«#+Kž˜; LÝ츉ßk‚[“Ø+f|ØëAâvëè¶rÕbæZ¶^à¡H¬s ªâ8aAÈ 3h&ϳŸ¾X9ÉXbùêxh #ùÝáB>P |®C2ÒùfeJ–erí!è[)7ËÄŠø!Nø~Š[Ö^is“0#h‹r½Nb?*]5YWÇå—ìáñÌ¥&g%Th^CJ»Ô¨G“ØXfvÔ4‘Óˆ9–Q+Ùœ£ Û½2Û:ƒ’4çwV—°¨]„‘óò„^n²1¿LÕDz2v *ý·ª—©éA<Óa°^ÚvjìÕXÛÏÔd›R[wx¥ìá ?61°•EO‚ò&xêw!ø®±½èqšÞoHÊö¢Àt[æ€16 L°ç/eøøÊÛ¥DWVÎokeñJbÔ„C&h§'4Á‰!ÕëY`Ú ,ƒ\üÙÜo@"ÞµŽå·î{ã)p’Ĩ¦ — C彨ÔjHâЖf Š3®âÛ?ñs JÛñg/º[´ ç*ÅcÈbRy†«»Ž#¨åñ‹u{±±iOS¡€í‘²öÓw»ÄœÝBáø4¨ô1ÄÎÍQfÒ6¯O‚½áÃ!FA<1уÒÝ^Ôt¿e†D¸ì%µº«k^†€¶›HÅcå“Mw\£÷ÎáNÄFö,1ßZy\_:ꜼÁÑ]e[ } wƒRŠ¡5cSdТõŒŸ ?ߎ\o+v(‹7ŸäÈbÅœâHÃñš-Þ4‹–²;§ÂFWÅ5/@Ó1MÍÓP w> h5£e–S´jæCÅÑÓðGB»H«T ÙBŒ Õ*µD<>7ñZ^"`^ÜhÃïÑÈ/Ig$åÕÅK`KTÙ–^ÞqÅg >}ËõÜÑ jw/™ Ÿ0qIø™â,•r ’öñ~J”Þ§Dõ–aúz“)Ö)K`™JN`‹¤Ý¸eˆA\!%·w•ôe²æ³GDýÊ‹ó`Xœa§<Ìû­ÀQ_C¡Ü4ø\4C?ÆVöÅ$)ÁÎñõ²ó¨+†“88‚Û¾ãQެ~$Rìê×Of÷ÙRÖƒ£Ì6–9œÆœë½~ã¬åòz7²X]íÆ_Þ[Í2ƒ7h+õ³ÇlñÜÍڸ܊äé-È&²ÕÎ5h’…’=ˆH‘7égcDœÏ»Ž±l¶3q«½ð‰)/«1ª7–¡4öDlϱ(¼p—íœàgMuî˜Ú _²‹[¾—N-Ãl Ü™d«Ú~§?ïæÎ7Šƒ+ F{¸.Zäéh¼”wÔ/,d°O@vIy­2âQM?cÆKÃx$v47ù)R¦ïFjw¯9cãŠX8L¢ŸÎ<L¡™ÜÈq}à¥Á,᱊_5AÖ@"Xz¸wÒ!DW)aj¯} õö=\QE„RBÆÞîóÐj_AsY1s߉Ė6zè C‹ø¼ƒv: ‘—ËJz^(YÖ”ÇÌõ€…ÝÀ¾ fyé~B$Øòtõ=~ÍcOÞ;â«à•¤¡Ã+yRo‘Õ:ŒY (0Þk/cÈáyæAÆ—ï]…y²67›¾¬ÝlkÑhÜÇÉB+eÍïÜ `vÁ$±_»44Gß#¬éV”‹½Ó®w«OàåöÊ1,n·NåDpTQAw‡ á\ÝËð’zZ  ûK¦H>­ˆ¦T…,ÅÆñüõeN§=ÇQ|Çs£'c^…®œ«Ž ÎÒÓŠi;¡¯˜§Lv¿Ûýû—89£ŸïÍRNà»:€EÏÒêwø9‹l Ñ<ѽãÚ‰w©1?5“aרpêœSu-¯"¹‡Ù‰YŠP QXü˜u€sÑOUÛÄxDúÝ cS¬v߬ò&ËAΉ»ô5$¿¤¢}3ô^è”y¬*£AïÙ³ðL¬êyboªòÁóÓWtΙӪ…Ïë%ô„ÐÓF²7ìwˆ]Rfž&´C>nøÃÃY9¦oò!I "§ß‹]â½ÌÓæ+h\UÃq´k~)tRãŒöÑ›eÓ{-*ÝéÄ`3±g:)eý¶lÁ–ɬïê˜Í…ÍÇbšTOSjµ öeÐönåÖÿÊ¥ÿüó¿þ§8þñoÿšü_éŸÊø÷ÿíŽT㌻“8#[ÚKÔ¦Ñ%MtÃ:œPß-‰K, N7>“vHE)Bâ<<¹x¸¼ñ€š³Eü#&¤txÐÄÅ•§‡ôCÜŸÊøõ 98®ÛK¬”IM2¦ó[™nÖ¥]8Ê6Z ¥wI+9»Ý6£U,D¯Þ(²èµ®ƒ„•ƒ 1€vSEÄfÈG%Ÿ3c÷¯J2!ÈUòÆ›@“7Õ¦VB@L¤n†Ï2¤Ëëµÿùâ­÷h€hÇ$›‡nJ'ÆPOdÅkàk޳ž7&ɀܕ|O'Í.‚é“"爈ê^Û½÷¼1é`@Á›SLPÙ€¦îÁÑ©¡ó+¢!p ìûÓÛöíã~áÊ)\L$57Ö*•¦âõQÌwÅs³ŸÜÌ«Ws{¢å„Ãzï ²`ˆ±| ù)û¼~ʃïr2(É ëîÈCɱ>š«£Éóî4ͺ•µ*æ­÷ð±¢å;üÊ,߉¥qûæ~$þ#ý­[(˜Ö!š¾ŠÁ¥ ÍWoñºõj1)”c´ÒÞU£\,·`ÐΛN‚Ü”Bˆ"¶Ž}€7ïžSÛGAß½ð_¶Ø¯’?© ¤,ۜҤ·‹ƒ&Ù$Þ}t/b;æGì›ÐS<†b¢–ÇÞ‚•=06Ï0îøFÇáÓªv°Õjv9¸Êºý*éÛ ôªì-ÅOž;¸Îx»å¥Üíãk|ç•»Sk“À@Ùá¯cU=ܵôUéL—¢n½…5RxTÇ75C-Åσ`õ8b–äÝGQòi ˆaÈÝλ{?ÓÀ˜ÛèÖ 5hÊ×=h«Ýk ¯ñ–áz÷HMh‚ráuñ“›G+ìí\Tïüæ±Ö+‘nqo­@F¦ÃTñ+$êú(Kß§×å;zþIHš8r‡`k ±&`XR¤G¼Â6Š·h•‚¾ƒ@1zòrŒcÜT‚€«Êå êU),°KÞèê>æUÎL³5.¯]»YÑuûjGFß¾§šõÐe'JÙä§ST¯Ð±V8B‰°ÃÊ ãu÷'ªåGRK_‘ßݾÆí—Ò{p(ZLlkШ^A©§ãx‹gl袾¯Nûi»cˆÈ¹ô„ûç;³6[†í ßs}O\[È­ÄCU»; ‡êÆÇ«ZGoÅ#H¶p4ÓŠBGÆ6¨Q÷L&Só’›]ÉSS>ò¯âü³¸Üé¹ÙÞ'rø«¼“9 ¡ ·ÁÌ 5RcJ–JÍjtôòEàää™;ê±ità` ÛEc\Ï*\êl…ÓŒœ„ÁÙ[†£‚§ÆÏ“9^?ïòâÓF¤öqQí»õþU C"£m ¿çãéÈ Õ ½ ï $é\YˆA3˜vZžW¤öY\ÝãšœtB~/ZÞ©ß›q€Bé—•ã–cÉņiøÅ§£¤=%c"G¢cÇæzºï7‰òšì5Ïé8½“›ëâ©b[´Dô¤«¼¦aˆô¥óóÂÀËjX„ rCBì8Ñ@¦]Ùתêõªr¯ù¾jÄOsá7ìQŒÖHå’[’J?mÀÔˆ5…D°È9}û^[½ó~½)ÂY¯ ûˆ®èÔUr€Ú½ èÄøA»¤0ú)Ý‹Àhå.ñ®>äÑñ·ÆóU%}úÌ%‘Û«nPw‹õ=ÄÔ80¢ßu¢¢³Ñšà³¼€†>ÔæªÉ™j¥ç\4@>;/Îü¥Ìu çöĉÍTO&<¼1ñ+Ù9íËÓÃ}K’ó¤ÚŸu~ZŽP*xa÷Œç{b)¶³æ„ö³'†¾·Ü¥¶DHoCçvz…‡¹ŸÂ!“«„É QßHœ²Í¸d>åpð|"ùÂʺRâ|ñ±mîyA¹SxÎ%Í~UÊŸîã´´Ïô mŸPh œƒíÎÏjŒü^ûœ`²ºø>¸Ã™¤ŠfO²„Óvõ§0»À3]p |r^e]eID$1 G-vùJ \ê«Ö÷éC&ê<]"ŠZˆäq•n@x&áþL;§‘O…¬Ñmu’˜|è7«iÛGµ²ñ.3>dNçz ¨Øm³u1=vËæ6]ªDÉþLÐcçgµ@xôsDÿÎ@¤*ê·ê¾&ò 7AíÙĹàO†ÆÄíÑ+£G\Ý+(‡m’Kµfg´Ã÷V6½š*}ôAÄí£rO Y¤›¼¬÷p̨_FÚX¼"3÷M2Ã„Ç GŸºÔø´ßìÕôƼ·¯+oÍß³Êå’ÇŠ@ùÓ™ã:'l“»´ìZQf!ԇشl jij’2c^N¹È˜ÂŸ¼ Ù»2A¥*è‘ÒÅ$Ú÷0 Þ‘‹¶]c~ªÚ¾Ó’Ë->BÍB qF+èbö4בk¦ñû/³À¡/RÎä8&ðì½{‘ ˜TåLë­°:¼¸·øL:ˆ2°F@¡˜ÐÎØ¼½§H ¥Ñ©Ï —­hçQ|ö]ÿNP ÞœL•˜†-5ê%Åìe{‹Â(’^ÂÏT…³Jt­×ÔÖ4%ÝÒ 3gAáºïÕfMK™<Œ$H6œ¨³™u¢íÈ×K¾/¡žÞ &eÖ^š«8غÛáû¬;è³îí* “8{Ì£×Êm{œKŠïR¹öe%׿)·ázÒ7oÖ%-gÐ,—èðàžš,Î[¼6Sfã7JŽžq\¡Åvkö®IgÓÜž £U(™œrÚŒŽÒ¨À0Øç…>+Ï›z<íÇ wûÝhFo¾ÇL;mZo#šjšcìŠRKäµIøA¸Heµ¬6<¯5=9ÖØ*r«ËvèºnsàÇd{%âïç´HˆL׈§ð ç’Y›P/…£ŠÇ¬Õš‹Rà+åÁ Âpà™šPãL{qlwot±$—I™+½ #â-0nö£O þªŸ>½΋ƯobÔû®Ñº¯Í JxHŸRòñÓ+k‹rÙŸúOa{t)¾ðW!2¥¡¥Ñ¨Š@½Di€é]tiÛc „V ¾è÷Ø^½•:=ÎǺ½:™[¢ƒÏÆ{œ£;Y6ûþv½Pn^¹“„Úçô€ ãC:7¹Â%]—Íhx¿00’ä2&ë§MVóÖDe¦.š\]Ͱ¹²žª«'§×Lö‘dJÇB¶Û4S»< Ky%­yÃéaÙ_¼OÿNtu/„nØ9眃ôçà†ÎÎýÀ µßQ„kD6ý>m4Å–!ƒ#¥ åñ]”™R¨?å'@›ªjkçÛ”1ÐÞ‘æúä ÞDi¬îR‡®=»ªI‘˜&—Žj¡CIíüDáÓ ý] – ÍiKv— ù$D!Ó=1Ž®Û:`FË­Ç6 ½qS»ýšFfãÂV¦47á§"(CZ¯á8ÚÏҵߌ’bZt<¸.F®¾Ê¨3²“jƒ='ë ›KtrX™Ù•îjå^÷^ªžqš,E8 WKk‚BÜw_Hè§;Îúañe¾2x°óD¹¹|%œ„Ñ|Ýö ̙컣£Ù™?'§¿'\o¸£âs°©b¬~ŒÂÓªàEtÏÀ5³x4ò`•)°D㽤c5¸¥²Ÿ2ôË ÎgÅ‘žæð{:“ïLo¦¾°°OŸT:”·ÍñªMlàI[x{¹%À‚Š <Ç´¡‰+ñ ÎVÓ’ßY¹®mB}žð#Ðp°–à }$}w±ƒ¬óLU6€HÑ °Êš×n4Ð\¥oŠöˆ%U«Ù_â€{ywLŒ(²¼˜ýBÃ?³hú6î0–Џ×&) ¯l[+"¥'Qn‡š¤»²ùâ[©«œ÷³‹Fòsy¥=ãï‘^UUª8¯Ï[W+ÕnóÖºoœgê¬Â¨@Õçþ\n#Ë©TPøâYå‘"aÇ`š¯ |âñéÏN4,Û›ñA4¸º“ñ³TädQ‚‡­Ì}xx®®’bº@βCM/èçySúb0ÓîH£¢ rƒÎª«AIÈç`Õ…p¤=p£*‘‚ lZ”ƒ« ýdé*¨ïΙ¨f*;‹X‚=_•âÏ\ß³3RêPЪmÝ>׺ R…N“çïîõ;ÚN*ȃžyÌÑZ´ûVÞOLBU|8êÕöÍD¦ABõÍ;'N”Qƒ$ó|¹!¶¨@;;ºÚ°4YP9±&Bx(Ó·Ê7·#9}ª(c¿ü”áÓOøêMÔ¥ÕCŒ×RõÕýÁ8?f@S ÛÆXJ|Áã÷®~¦¯¬ÔŠóCŸ£rç­pO¹w× „–<ɨy‡XìaºÆÚ'DSG3]¥XùêÞkÝ–zz횂̆ï–2™¾PÁOgu¨Ýê¡åóŒ'8ïE„b‡1æªZOÓÛ‚^®È|U ig± üžÚ䫟+ýTIR³#©£#Ýß=²æ&wËN`*£Åe ­ QŠAeIÎô¢,â}ÁÖc:QJÝ ,\ê©‘Æ¡¨[,_¸Ð§ÇZV&Ò6¥ñ3µ·ï=| W*1à‹­:Û㣛$—OpTŽ|)ÞÓòþé-ÖãÆ–˜ÅZlŠ´bƒ+Éó’4½ºLßK$y°\èO-Þ6&N"z"Dî ¾)–€[²Z0¡mpÒì¼'~iòjZðð™O·m÷Ù S‹ò¼G”Õ•}ä\ïŽq±³ÅÛÃ!NeÄÁæ©Á©U*BSÙÏÎLX³³Ï_'ú©ˆ«ZMQ¿Ç‚ÒÔ“&y¶OĬN`ù9NI‰,r®™+^‚‘><¯)‘é:·ؒµ§š_Øð§ïîã[¸Þ~ÛQ«%#ºº03ön‘}Ø Úùõêæ4U¹ÖéÏD[¢¤RÁOC=9`ÃŽ”¹y¢xåN<õuð}¢Æ’jû‚.K•8FF@gLRü¨E—¤£$ÙÉ¿V#‘¾Lˆ/tÞ§3³A>/¥ÝÇòôÐúíQm΋ ¨,…WÎÑ´ºRC(†¢’,Ë—!òýVÏk'¹‰´î!Hð I£ŠÂ3¨¹£¡IÎg¤iï"K˜¸»úQÀ“h¬zz¸x×,v÷LõÞ=·˜ÌÀaÜÎpÍdh+øôbùN¹$.ôµ·½šjÈq‚ÐÅž7ï±ç1^’‰ïmk1•øV³_Sj²„¦ÿBÈß“1Õd˜ñ8_ï:Û–¸²ä^ã‚°ÀÂè3¤>T–QngQ'"#†h­8@ew7Ÿº«"JQE"é7)Z_é§+Ÿ„âÜPáÝÝ仫c…F•º,ï…Z!ñ'³åÓŠ¯lŠýý™ÇÉô¿¤ìÛÐþÙ¹hšUúmÇf©ÞÑ DȘ¹„y§‹ã¦óÒѾ·«È³u-ÂÒÏGÙÙIj:4AÍ:)>W†Š® ÛiП}ûs‚bÒ–öî¸;öˆ¡Ñ¸Æ'†à*)²¿rè-y‚kV }p’°‰Ò`»Ød[ù ¥.E„ëTÖ§|º,@Ýh\ðœÚ€r‚ÌÑjf«yÒ.p——.D¨æfóÍ`^ xAhf¡Ã  1ykþ…’}:5Úã4#ÁÑ G&ÐïS7óEI÷œ ¾uñ7/åâjŒ¡úü Ì3RÖWQ’E‚õ;îq’ÇkÝ?,~~j((Ù]Éí¨ª„çú2Ð_xóIzÈiIÄp×Ã#HOœ#Éõw˜:Ö>kïÊzïùÙ†Þ¬Ïã/œüÓ³Ç/+ñãõ›’CÓ˺; z{J–l=à}" ^•~¸Lo¬íPŒÂ7«ßôÚxô *½ˆ‹_Hq´åÂ9 ÅÄP8¤ÒÓ¥ÒCH޽¼Ñx³ƒ” 1!Û+ Óì ³Ïmbà ?xÂ\ûúy Yír/ä绋O÷® õWkÀ\;ú9U Úzĵce&ÒJ똑…Éà<¬ôÚ3÷ž’¾§ m§˜;6?g±ò´¡sÁÈÑiª–ÒÐby-éõ,ôõ"=j!eßMõàDÒp‚ÔGÕ±·¢=¶¤ÓO7,íZüòø0-IÎu{mõ}`õà;]/ÊPŦ½N…SmŸËb³ /+ÔÙÒÄJØä¶]‚Gç1l®k} Üfæ’«A焇/í~_ÿKz÷ˆO´ÖÁJQÛnò¹Zâ $ª?yׯWs˜,²ˆh:-gr%dÈ£+=B穊\Fi­¸0ЪH ¶“cí'ZŸŽIµ ¹FÌeã&UŽÆ¹³E¹Ì4+ŽýxßÙQt½Ç ï*à^QMmop …«`ûÏœ‰è]š´ÏS2ò3LóbšïËL²iVíè2·£WÆ÷0,èS/uß©"™OZ§XTßÚ[>ŒÁ_x¡~O(G¥Á50&{[ÓD9÷À=C’åÑ)/9W5“º9¬¹úw³‡=¡Ó$Êt1îÞ:zF?»!ÜóðÎT†uRTñ)Q)5ãz¤.AõÇ,Å ÔdIÂÞ  ’'M)ÓÑÌŒ±#FNŠÚè jË ðŠ~,Ÿ £O—߆‹0D@mMJ°‡A}dÚ«÷‚Ä i¼G•™ä­ÀVD»Ù/FÆã5Ô©ÆQƒo ¬gÎ ýÌYa/\9®-ó¡ÊÛ§¾àG‘wc 8ï-Ÿ0Õ¾ÊFv³¤M«7£Õpj^ ž úH|O aË= i@…¡4ÀN}bÆŸ~ÓOБÙ:™Ò‰èÖ’ë]ÇyØ{$Ñw*,ðFAðÖ_aÚÝt=›§¡½„”êZµ‘ž…­a¥£Éüóm–N¢¢àõ ³3©ós@ŒdxZ”²òÎvZÛª]%ÖøôZÄ­ÍêÚ°D·ÕäÒƒ/¹/1 Ú D€SÌ©=¿P{ŸÎ?K®•@× @ ß9\aÏåÖlàPœ?Þ—¼ÕðÔõ"òiǺC…¶ØsqZw¤$]I»k‹S¶G÷{³p‚e­Ð_¿%#œ(ÉÝf `ó}F5GdïQç‹GŠÍOoò…#ñöJú>j/ÛeÇÀ 3z™ÁDœ>{Ÿ¸}ö€ÝêF1ê:¾h08LcBfÑ‘yÕÙ”qÛ{v×R —–`óo ™î¶(l¦Ì2ì  ?›R­ÎŸÈµ=º’;líALx›ÇÒ ±,’a²ðfÇù¡›×ŽÌWÕ`iÜ$êfˆlp®¡3¹AZƒô=¤E\ÔY¸‰/ä¾/大ã6kX±Æ²®‘ 䙸VºßŒú¿å.ˆl’6¬õ¸k­\R“{kÒ§ÞŠ¼hÞ¬ÒëÒlÜ_Ø ŽŒÌØ`h¹Õ¾d?š¨—s1·ºÞkXà}Dm§ÛGÆ›Ç!ƒt­¼hg‘» á…ÆKkk[aŒ±*:‚õ/ì¾oÒryªÇ´pΈʹ>éä/ߎ‚¦¤­À…hqW¦Åµj'›>…E€‡ò¯©\Ð[Ÿºmâ«ë`“0Ÿè9Ò3(d)]¬†v™ª‹Ó¦‹]KZUCÇî8õ¨¶¹èŽˆ7TWÏË6§÷ ËHÈ&H ËŒói¬DMA‰|¡÷}µ4T[\ ZLëÔsWÕsâÜ·{dxܤ)}Ö» Õ錊 :MKhÅ sNˆÀ1§cÏv‡•súeE+<ÍŸxO«™2æ½Í n# Â§ÑÔTÁ:ŒEAÄý“CNá8*DôÔ•\œA#—»½ö5ëk¹à‰¤x˜Q€ü}ç|ßwNºIFœª$c¦„ËÕx~À„P¦óxí=Te7+|ýN63´QÙðlÆó!ÆÙ¤ôsîæU#nÀ«ßsqm„¥YQÈ Ñ-’³7 «3P‚\!¾JJ@ê7{} Çî6:e ‰³ðª9¢fƒFk ^F¦UPí\Žè}"ø=9Èà³—’Y2ôˆ²S÷9¢›3§R \àLµsëÀ¹Áb¹g‹³åéY¯¢K­ Т›ôD8×J4B£ËϪœ>åböŠ !ÀçÞ4w›l¼<å;>BX)•+–ÅÚÜÙQ -&v0R p~á4fõøm<´HÞEà'°‹Óý…a|O†5ïá¼—déw"õê©5ó€ÇA¸g’ðP¼œ©)&ah˜Gà…0N|Ðp`üÔ€ÎYœA„œÖ búo¹lÂï…Š€^æ¼K¨ÓúhýÑê[ô_‡ÐÚcîO,?ûÌõ£·[džˆ x-"ãežRîS‰Ó”vd©aÛØîÔ‹žè8l¹,¢á»äóͺ ÐáF }]ïdM‹¢ÑTæÏ°–íú§2;ã@K+²üLûO­šÔ+FàG¬ï=mÖ3Þ2£ u†Ö¦ë<Eõvn_727^»rèzsÆ>ºÁ¸ÎÄ ô¸/4¿¯ÈYËϨ䭑ñ«©´ 7Ö§ûa1_U]v$K¿e&ºb‡®Ì·çW`C˜„äe'¥Ço‘£í®iö™»KDåïÞs¦hg1éϤ8ß2hGç¹æºl‡¡/ÁÀÊÛvÚµ„£A;ÂTÌíñHí×'€1VfïÙÞÏž8 ¤'®¿/<ß÷ÝY/Rå¨ó…qT¼7ºw<)[•bkýP“ ö±Ãqß«g±Mü|ån•DÉXQ^^׫W1ÚÏÞ»8¥1‹y ´~O6QÞ†Ðá`Ç…%J]sAʬhÊšT9h¹l÷n¬ÏRZ È8ñø61!(ÐÚò] IIVšºbuÚ®ƒ>ñúBTè[¡ífÊ‹á5ÞRN•ò²ÉõÜ6És߬zvÈœ,S4+Z ¿8Òr#!AÖñš÷DËÞT©4e³`8Þ〶Y¾Ÿ )Ë8!M*Âv)šyuÙcà ÑÕÎLò(mç®ö! °áãÖÇx³Ãã½F®Í‚´ñØ+èq t9Á4½'Â2_˜~ß¶ãuúbÊ#~­#ÜmüªxÚ+½åÜa³|HnÙ‚3 pk™@ ÈõÆ÷m0ND‡O¾9[ƒÜ÷¬²¼ï&ˆÆÓÌ’$®ßÕý|û{/K{ÒÃ(xÀŸ*¼B;à–‘±mâ~ÎjÈ‹(Æü,•·5R²ŠA.Øi{2³Z]à‚üÁºžû½ÉºžànøDÕ?»<×#žîPéÁ»cÉÞ«=Ÿž'[HhÕ/á”@뮹‚›ŠÁ Ó(z1fT7Ø<{º2<–ÀØ ´gjå64^ŽþÌóÉ‹ê£wcÑ67(*lUX´Œs«dÔdìÅ{‚ÉBgÅq ¹8¶×o¡YÕ¶,M[ɶñ±¼~§i¡K­_¸š~âº;Ñ•h‘±MÛ"àf<à ϬÑVG4VµäôµVësÀ^’ôG¯÷%éˆIyêÂæð FÐÎÌnÓÖ L‡ŸrN3±í‰U ‡ezþÌ¥Êb‹íT{¤÷M žyvO€](>]3(‧yè¥H«âï\ÕAwǹ9×éZd5ßu´.p/¹Á{tœõÙ­¾/î•Rj%Ûœ|—K1ãhš´gÒÐÀF2O:º 2 :-)Ô2$W4R§ÎŸj[©¿—8 ž­Šg{ ìËÄSrÔú^™ÍóYLðÌŸn ‘„]XŒ©[jã4o^r™tT×Ëwû0€5§!ðFg” ‰I Y¿Ò€lÁ}ÇÒQ¨$­ŽÁ—lrùb¾°ï›Í^’f‹£Útv–+ÓŽ"ÊÝ‹r¸Œ\•§²"º”Àd[rå]å›r°Z’`ÞK"®)îx­‹Ñ@¥ó ‹S;n‡ÞØ …Ÿ ì ÑŸñ«|UFx¬c…ÅΧu=r&ñpûðŽŠI8/ §ð€%L ‚O"Mê@Þ Úö(ÂôŠYøBÏÍõËkõûª_ũ7V'ñ²í ™M£¤”ïä :}k†Y5‚)é¹ik»k¦Ð¬z„o ÷ÍæºYw¾Éx RjãÌg6ì¯P‚ëç”`P^¸LÔ}1Ê`;xÍo‘Ý^¿0›ŒS`ÐËÓgcg#¯œJÚ{žÙóZÞD=¬.3,ýó)ŽÀ«©G×HÜŸø~oóÌ#↛¥<¯îj×,³x «\›4’kϸ_ ^V¼‹òÙ³ŽlqJ™ê q´¼²Áz~Êo1š*óÍñ³{>/u›øpCGB¶²Ùú§÷6_-“ˆ¾'“óúPn‘—f½Ç/v›j™ Ôaeç ÀKä0kŸñãhY0dŠP ¹A‚&µ ègfVÌLÛüºýSÁøÙÕô!Èvº² 4ÁZ_eBB¹CÀSÔwlo4°§F<3«Ñ1.²ý•På5ÜZÏT‹¼Rðlx­ãSŒšÂùZ}{™Þ¶ä‹»)‰ÄM Ê„ý‰q.¯ŠöÅ›BÈåFVJU’Þ^¨|Ó6¨àÉG×ÉýŽñFW5²`Î8±yÜ®\ƒ@=…;[í9â)¼½ŸHû÷æêÝí½ybÕfˆw/Óˆ;Iò´h ô¼Î%ÆM¼<ÒzXdŠ„}@'+GN•+SNOñˆõFÎG¸e=“{[QJ ­ÕqÍxâÎ^`I7…¶üº*§6C.šrì=…RK§÷À·"ßõÙãW24û–¥ºMlÎLç)FÌø‹äÞ£t?=¨¸!Ž6öpÝ7Sõ™4D?±6òY¥1qQè×fùÈ©ÇáCó! ëa´tB&ƒ‘faÀÊñ‘Å‚1Ù©5Z-Ùª@F¾Áe:}¡dÊ>•“a@m L;ø_ÑqŸ—ÇÛly?=„Ô«é-Í$ªYYr/#bÄ{NƒV9Ø(í.‡CÑ ®b­qóÎz%ÔÞuWLv ôBënPªêë"X šÀñoeëgGT~~D±V8Çem&ï­ ê‚£ \bk»£Æ”½6ÝG[á|ÙE¦9š0xi%0¼\z=±ö ‚ -kçÙû;/½N¶s@­àª¨X0¯©0à¡2ÇRÔŸ dy9àRå¦AÞ2uœÔÉê†]5¿&~zG4aJµušø.í¢iUîØ¶ÉÀ%Aø9¾ñ éR¬×]©Oí oûì¯ìfeÖ˜Õ¡ÉXYÉV9Û“ëØ„Sç&‰«ÈDúyä­<${N•€ îO$^©!ƒ&t¤´”^pArÑ´›=¶Ziz¬]ǽ–¥ö,ø]_3äfžþÌ|7’Ìo^ÙE¥O!uûaÔQœ4‘6*+=zFÜå¦`¡b÷<‹ ç•Uµ>ÎçÍwZÁYˆIyLlFØÑ ñ…¸vIð§xÚw¯[_™P‡¹­$\f5HGÝy ñM Ók‹®ç×åç÷ ðøÏО³É»jøIÎÚeΆ¢Ü´À0™Ë¦à¼ðxû¤2yÚÀ–è©{ë/õBü9£¶CWÖX 5–šõãšõA4Á•·ºÐðŠ-mùeÜÉІ¯µ8:¹E£ø³AŸ^÷Í`¶ê÷‘6¼Ý Züsÿto?÷…« ¡‘âªy˜NQAÇÜù’14ÄŸ÷ d_\:iSŒÔ‘­ìqÜöªh«èëTóÇÍX’4Ž)x‹>Ï$z¼â­=ÍÏ»D_ë+ð³2TÖÙ}¸SSi×Ò¼àEo8U¥·-0ð[fd²1kZ‚ðŽ®ú ËvíV3W“Å¡ŸÙ:\•ž(ÿ¾™†å•Ùpœ¼\OAŠ´™öí €ì,ºXÂ3 vi⯒1//ö¤T ®e3™×v–uÀ™FͶ¬ù®±8Ìp~ànð>fijUåÒ?Z…ÞÛe,Ì·ÙStH4×ê f¹ƒÇ+ä'æ.±ûz¯^ùÆS¦d¥&=ï^¶¿Ó7Å“}ë3èö^Ûëힸ}Ó„\ü¼ÍÒñ{B%ïQ>û} (º–ÈÇIªÚA Œö,ÈeU¡Ô õñ"BD×Qpa˩ک#m­ø|ôØ)}BÍdó¡É»¡ÅÊ&맇åú…<~Oš&²4´2ØX€¢O´„Äïª Î{¾n4}ŠÓ—ToŽôMäHàÞìZ=,Ú ç–Ü*~ˆL\j´™ø¤IÐåOõpÌâð ˆIJgSE_Ü/sšá§Ñý{H5Îó·4Ähån\·ìEBndàÅž¢Ë"/›¦—άE‚'"Ö2UµÅJ i¥_F‰ù‹CJ6‡[Noü {‚O·A‡YLEDÄ]•Ô¯€@Â{Ä^¶Ù>x냒Øz’´Ò86.Ó!äšèðÚ ªânÞtg:““ Š;ÆtŽ‘ðñò[n¦…©§Lak/xƶ5‰…9·ç5^àïK ?}ò”·j‚©aÿmÏtu°)5—é×ëp¼Î@ç¶WÝ…YîoI§GžË°‹EÈZÖÒbý)bul+¸Þq|¢ÿÙaûXœ»ææu5(®M@¬.í‚\Ę-½–}¶ `†bêÈò^¢ÁÓÀw±WúL)‰û,_Ü %äkÀV†¾u#+Ç«ˆô¸³nÄé4±…‡V~k{•:!-"÷sn:±Ë@IsZîÖp”J¸G™ÔDÔcLJçÙ_ñppdBÍ„ªk[(.hÝ®£#Ùµ”S«Ýˤ<„y—ì§²ó…?ë§ç]ñƒ½D©£ jÀ} ÁqÚ×OºØaW]»d 0ÖA³¢Fd•_B¦R† tƒõðΔx´ÍQ©]3Å)æ{·Ó-™ÛOdò]UŽôQ‘•o8W1&]ζ ñÏ ÈN,Wå!Ó`oÔíè˜eóÄžè°XªËž MJ ½á#ŽÌXx‡}â!aÀS•½7G§¼ª\/€Uá9ž9+}1ð>»®én_ˆ¦¾87r|:Ë¢sŽl}Ýê²\U\šzZ\nóYÅÐ JRQ¤M³ÁÜ“Q˜!¼Xª€Ë Æ(|å-¢Rðˆ{¯œlä€(c…ø…ç›B`{?½HAz5-Ó‹„äY\7RÈC,Íš^bîÈn´Gê @sè /‰ðƒ§­)}¾‹ÛasNÍ|®úÌÝ>;±~vâÅ»ËpÒîõr­þCÀâíó~ÚslÈgNÛ;¸lNeµTV'Èö ˆs‘`¨V]ŽÖÒYõU_-û­+óÑ[e¾[ ÷ÅjÉ>‰7°H± „šT…u)9)=3= å˜èÞW?QK é˜8ê<,á:ÔWðÔÊ!#ü :ÃNż8ÛæíÛ+À¤vz §OL8ó)¨u‘9åuQQmª¾ð³%e½ÆO¾§Þ¸ÈªT‘ ]À©7½BSY~ ƒÈ‚vßd’208Š[ATí‹zÑá$CäŠîd¢E.LΚÖ2 M†ö¥Ãƒ[ŽS®Ê«<±äÝ\® o9^FÇ:¨Ôp»\ÆA›*ÀωŒ8âa2"@½<¼=|1• € ÉXFéGhË  4FÔ=œÄ«Â1¼CÒ©#—*×Ë9â,c¦uÃø¨î‹ ûìÎì‰,Ô)¹sé‹ÑúÌm|£9M¦ŽËÕ^]EÉÔ5J*Âåªö`êêÐ µÍ|þ^˜[A1êë”2´ >z[PÚ[]ÕåcT”F|‘9Aï-”$udGjB'ã½øÅÅh ÔC¬jÿ3§pq1Å 4“T`°¼ì3ˆÇ·%®bö§™6…¬èK5j-¡LµºÄƒÑÔ‹ÇÅÔDQ¾€" ðÙ§ý{Ã<ÞºïE5²ò;D±MÏ­Ÿ—Š%5[‡Æ¦s½ÑJoØ%Clò]Ärá…„ Aïcx¤¥gTѵ@¤«ŒFÆÉ4Q€RðÁróÉË`UÞ7;ÛLCþ–DôÒ ‘úù2’ü °z“; /m!†®x0÷‚¸F—È%Õ¤âÄsðJÌ,TuêT?=É£-[wÆuUw÷ºÍ§c~oÈž£(Óg¯údc¯«óž`#ÅÔTô4Û‹áݘ‡m5³zZevª*§Ü%¥ðSBÀ›“à20¹§1û£K[‰hhÁ·`~ í„mù^xö`Ú8t£Ä’K´^^–}ÍmHNô¨ËP‹À£»ñæI¢söp1îÞ €*?÷>× VÞˆ%©`"8!†ºjdV®'>:t1„8ÂJhNÛˆž}+\¹¯5›ÚVñꃇÏÞý˜[•^Ž«'ƒ“<“õ¡"tàð{ïW8á+­ÍlÂvKjæó®yTÔÚ;ÇDod·)Ìß{ïˆÄ}Oî1ð¹™ÄEóø>‚ŽDC‘[3£z Z•/çŒÐÀO÷žØ{/ëÏ!Ùh ,ëáÈž¤ºPì@‘ö'7Ÿ}_B^e R“jÉÄQ(:€ÃRz9¦äZ"²›ÎN¢ÄôúžÐU¾$d˜åE•AtÆ$ƒ‰®°^o¦ =1T€ª×Iê}á0úB R#%½•§teͲíé™ÍPÔv}3â¢OÆíðIK1 ;‹ªè(ÚmØ|±#ß €'.¨¨EÅ RÔ^BÞœ?»ÇÄì/w˜VYUïÄ&_;ÖôÂÀº6¼¼y;M×^6…Ié)GaÄë0žÈÈëå‰aWà.Èu‰ªCJ±ŒoÂÞCU+{øÖ8Ænëà–›©Ñ2Ñ=];LeÊò>š¼^d™|G~uÜþ¶l^m—CòÓ¢®(ßI4ÎÍe1¿! Ê””mçç>¯ ˆÏ-žr%úÊwjÖï,À¸^ïbA G‡(Ù¡V&²Fôr[¸k8 /‹6ÕÐß{°R8(O¬†äD Þe ]>_ÕÔ®çw‹û„ì×3¶X€|ìû\SDð!n# ðJf?WÓÄ" Û¶˜º]x´Áv„ ‡öŸ1<ü™ ‚"P¢9­L ÝGȮ߹uÕ»™©”œ7]¯ïúMK˜RU?Lñá4÷ÍE¡ÜzÕ¯ûŵ•g©ƒJª«@Â+AGÏ/†ì{W/¾É·iìa<åµ¶Qµ÷ƒGW§Ç0dÓ]®#p<Ô”"È$š€é |¡KÊô^ RnyŸ[¡Qç` Ï)Ò™´0-—\G4 ãù©¢†$¸%ËîÛ]Yæ×¬1¾+Cqâ(㪓s|~¾"Õ»™Tí‚àœùÞ®èížk?qwWû³3hK‡àk.^ÁÂ鎵ÒÀZã·ÎJÞ´œÁ‘ä^/ûU“›6]}ö ÿÞXëBSÙ‹çO%]ÝáœÕÌ0±8O›¿‹ð îÁÎ׺çoN;6õƒãWR»šÁ®V\S Ôr«Ç*èÍNk†ÃŒHÔíU°¸Âý–¹÷¾' C96–,/zLL¡ «Pê=u]ÓÂÞù½C[¢ã%á&QnfáÕà¡‘T™Öʦ®žô}¼.þ.ÆWæ±½`}À7ê~€,ËʳG/f[QC!šlGîÝktðºO–üÓë4 ‘)ëi‘ï\ê³ çÑ÷Þ²aë“@ð¼‰f™bY(-½{ý6Å×D^ =…Ç\„ú:×ÕÏâÙÀ0´/ë Vî ¸p÷ƒqy.Eå.¶ÉX²©ûº/é8mÙTÇÆÃâ&[Ñ3‡ÇÖ]gó€ä¾Ðß[tÖ~KÍ[di/£Gôq`MìÌ“§/ÅBЩÝâÙóJÁä'­—Kxbâpß=²(u§Â9³0mêxLŹÀŸ<Ågf͈j}âN¯H4PÍ ý¡Á#ìî›W›=^*ɦÖ+•¶ö^‡K¶hywäÖ ÞÖ¼ž”œB†‚;bŠnEÜÂ7Ù¤žt±ÊܳÌv›[(­e‘ÑFJ&wX¶ÒFRaŸ ^ÚfV³œ4$±1†0õÛ_LuÁ07·©T%¾Í×÷üF™ Ë[m- óé3Ê+%¦²|ÆÓ56Ù˜i§,|ãÇC6h÷¼Åìê¦ÛÉž.L|¦‡ÚË{:v^j K#%^ÔØNPEoù^åòúUëÔ¿]|+£Ya”;Ãò€Xžê:‰ 쾤Ͱ¬æc†‰;‹Uª*åÔM—Y”ÚÜM=‚—ä! KÊ4ˆ®8W°*Õ`Ùž(Áî#Íd¶DF®§r'+%¹?ÝO,r M Ô°ÊžS †³ Šäb¾© DZÕ«AqgYhŠ¥C¢ô–×ÂpAÊ|ºmEDÜ;Oê•$½G:-ÑXª_\ágŽðÇ÷.-F]Ÿ¹õ>¶ç¤Ð!ƒ•Ë/J"k;}‚Ÿû¤ñSÞ{€áõõ ŒùÙ‚€Þa `mÂ=*Ï‹5L<¬AusyÃì7{uãªçÔð^²……è; ršVy`þl&$ õaÍŸŽó ÿ9ÕªG»ùx¾×›b1Ú°vkÃüO"ÄkWañ•hÍi*•WéX3vçBl?à¹3H•F픾ϴ^=”qÖO¶è3Q”H#l.l«¿Fä§|XGÚNK—ðˆ2¢ §^¾™h;æº1@놣©5~ãŒã:r“ÝÏÅ8ð½ó¾yAÄ…yÀ˜Ò¥ •†«+®6.)ò"°Ùç¸cÏ7Ò”¡V±3«Sƒš#¯,‘)÷úçµoúÅ>|mñò•ŽAðmÖÓ d¾Âï”w¼üHŸœs¡NÁ;pXÉóBÑ5§Ô…BLJÆk~}²Ö盂÷É×g¶ ÝM >q¹·£§çþçÞû,5Às{¬žÚ~³8Ð è|I€ ]øR(ÊÆ²aõN,™ïÆbõñû5¹ë™Ñ–¦¥|=ON¹CiAŸ€ø°Šáƒ—:TïÞ3‘ÇoL#|D3d¢¢L½bSHŒC]”žØ;yò‹1j¿'z‚Öys8»J¸s[Ô“ï±ÈHÐÜ$’Ÿ³¹˜/‡Ê°©…ÄpÏì[+µ¢‡GÞòЖyÓÞrÓûæcü™2& q žMÁ#Hq9Ñ~4Áh"J.ôÈ_Ä©&L9âäYtÖs·ƒòxåÊJŸºV[©»¥°ç¼× p¸”±úm{ÆQÂ3T'JöðØ}™X¯ñP±@iܸ°/Ùý†ß)=«¨½GÜfÎe™íÃ0*=X•>êÑ4¿8ã\ô”ó8s\ý H`?=ÕÇ8()&˜æâåE/‰žƒŠIñ ½6a4’fõgE+†¹ªVŠ‘1É‹êñc~ÍÈ-Âæ©e4ÛLyòø]ð=EÓ­ƒ÷ú™¿§Öð êA{‚{;ŠãÏ ’É^m“[ïˆ:u0Ø Z!,_ä”N5ð5œiê{GhZ'bÏH£\ñÚŠ¨ZB´—Ç'É7Žd¼C"ªU¸v¡]èñ¦ðé¸*¯ÌºPä¤ÍÂ0õÍÅÊðkÒäÎѶÓb€á˜- ˆ§9™Rû*e\5 Ãô‘+ˈo<=›æš7Õæ±*ü¢[:^äôHrË‘¼j'Ñ?yj<ÝHL§è[×Ú‚½j›[ðhâÄvûÕm ,jä™Ï>d›{Gþàs^]µ¬SË W%â›OpHf-³ÌÃWœ×kŽÔ‰»µÐku~&MÚf!@Áóš*¡‘éÅ»‡î8J–}4÷›¹Ï4¢¤§Þè©‘*(‘ÑOkGBEÃ&›gÍ¢üèG¸p„"‰Ú†Ò¸KÔË[ú¤¼Þ‘ò)¨Â&y8îÖh{s²¹”¶ïŠÆ{i=Hh¶8Ñ„JPÂZS#³$w†³­W ªô²´—)y6`pÅh®< šOAYdH~&Isšë,XKŸÜH@è `ãºFzv®à¦cw74bÍ"G ¯‹ö¶ž´¸á‘¿{Z@báü^²aìeñšªÖþâÎô“;ÁÔ+îWm­Þ ˆj² ñ¶D³N®ĘÞVë3sP¼8²µŒ§ÌYƒ—žöt_ŠYç ½ÚFs†TÞlGl!#óžvjWOo@Y\"ö®YÝËÂà–Š×D¢9&Å›­72]¡Ùù 8_]½¼pïí:Ê•°®€°øýòò°ï{±T¼u‘yí>+ø*a¨}– ôøôR’ú]ÈÉ”T–Dcj4ê>—H cÈ*Z­E¡÷d'–k¥W…€xSle¿ØóÏ„â™F×ëIZPÜí»Á`tE vYã´=N}ð °úÅ&ò ‹9JÃF˜ã,çTÉ{Ü‹ía+‚î½yD˜ê¨ì³ ¹XLì÷´zåq‰mO½&U2"‰A ŸE® X„½m°ço¢“Ý`)3´ 3i £ï€C:dàì¢ÞOç4¦¡Ç‡Åüâ`î1¨DEVìDœ’æ°tø+±QXI©g„œCÈ.Ñó ôµ$©5±,;ª É™ùª-Û¼Sât÷‡äû™0ã3«_ ß`À;ïÙtàìNÂlô}YM‰6)Am£¡î§â &"‚ë=Ì ·Þ©;OÜç >(Þ÷˜Xd[Eߨ=g1a~Ÿ¤šã"öÈBHÏÉ9µçr€›«‡ªáƳn¡¥¢˜ž§< Aä“DT’„øªè=_úÅ`Ø4)èâ;«»Ãë|a¡²¬ÉéØ7ú$HžPœ¾ÉwkïQƒ' Žö.×Ó:~øÖÎpwß‹@6»ûÂGåƒAøŒ-©O"ÊS±¤{;V-w4Þ³'Ñ>ɃÛÚÖÖNi¼¢ÄߥÚœúR\ÕÎSdU]AõÉ—¨Ç!gÉÍÎT\ȯ®£+3d(á–„î½lUÇ-Yät;j€-ö”‡[Žª¼5¯ž˜frÉ¡”‡èÙ3oÒ´†¨M+ïkg>aß_$ÎJ˜oö¾<ò8ª½Ú.Îlßèœç—pÆ­Æ#TÕ¹[³/º$M‡ùÎÍfc½ÅžИš)Z†‚‚&-ÞÅo? ,gÁ‚<ã(€žÒt«Aê\ WòºdE`µ +4­ÛJ<À“mz{Àø\äàDû™†ŒhÚ>4 ΣÄ¡À£Û 9“Ý‘—XØ´ŽDzu§§œ³â/Û0ÔÒ· ‚¹šO¥:°¤Iß›ÔáæôFy»ÏÑkð=jxÜ–0•’-…#¬¹Rú3Ë0guR¤§A¼¾B¨}é°Žç¸UÁÜ0¯ÂSCŠ(K„/ÞéÓ¬^͹èhƒVæýÀžèå¹§"#{'¬„*k«‡Õû¤õû-Òµ„ÔƒÐUf]áë¹öÁn4ÃÉŽ1TdbŒØÌ&w‹÷zS uÈ”1Pê)ÆÙãIZ†„¨šÂªbÉr¡=®Èm-HŸnÝXÌÊä¥lHm™5•Yj6Ä2å›}/íêÝ9e?½ôC .J#- ]žM†Ç‘½Ëù¤)«™f@Dêg(½¬'ZOÉAý‰— $Í«CÀòº2ÝsÍ‘qgSéÇgÔë)gõZJX2P¡ ]V#²”ˆð­¼9 hØàÌ©µåXŒO"é3×Pé”õŽ«ÊÖÆl…ú#­É´ÖÉÈ÷`깫Ll|HQÝ3Ç{…/ÈÅŇ Eß,Ý”:¤‘?A§„Î%â×äÊõ²TáõöÈ•“º{ŠÃõkÌ‘cø²1 `=WØœà!] f¿·ðD76*ÇÉrÕå ÇÑ~Q)uõði ôA3ë+Íñ*U¢È"5Pƒƒz¸Žð¦€,l÷6¡¢³jò=+`6‘ )ºîãy¹~Õ{&”þI%F„)(êé¬Ô¥\æÚ爚[èË‹U9)dèyÕCüß•x »íHIȱÎfIEÜ!T“Ø@ZP¤é¤;㨠mè@Òšr¨kÏ#,™r¤ÉÞÖQ–›ñw¤Å«3+5ÈáÐí@AeÄ€\ÌäOüՙйaAXú‹{ù;ì ûÒfBRš”–rßqÇÎb™œ R°Jõ­J¥Í ÃõžÝV9ÆEítc÷kµ¨GA›JM&J“‘Èè·dßd¾Ï°ÌoV¡#¬&\0•ñ¾}Oüä.ž@ Ä€®·< çVÁÎ0·@“ÌJháX§i\ ~aÒU ˆŽ„ X¸•ýÎ'’ÍqiJ -àö ¥¾„{϶íºVÓÎI\Îð.ñ [½ºGúÈy´‰…C%dg xš4v‘o½?ˆ²âö/::¤ÉÞE”ëãDW~¯p,¡Vd°ÖôÞêÆiÉfÙ…ÅÎ d>K‚§~°({;>žªÇX¨aÖʳX[ ßt~ÆžuÏWÔàLaé-‚Õ×–Ö6ÃòüØ\™ÃÃRšåE§ ê>3{Ü}µ€Z±ï#=¹[G%E¶CËí;Å2šÚ¥i‚Pt‡¾%ǹ,Ùe/ Bw|‹ L³²oDr|Þu*„hPe[ÔJ‚.šÝz;4´³`\1?›{<"Š]Ž`%;? v؉5~áK¯¼uíibk­â.ÃuvT¢½]$6¢6?7¶$zJx•ý´´{6X=XX“­–´0Ùu•oBå3Ý`,`:oé¶#TÕfnxü8ã¡G¤rrPÔâîsÑ^^µÛxš¢Ê÷:;Ð@“zËDɨÿ¢Ôžê›îöòæÀ¶&g½•ÖDñYm{¹±çîÙÉ»ÕaÎã@›·èX]ížlÑÆârq•¯±ÔêÕ¾oNus>)ÕÏ($‘KPz¶PÜ–á‘WäL/\'ɸ öá=Íeç=Å-^órû:2ö*>é+ã ÅõÇTt)y¼£$—9NR1%­M0@Y“tÝâ%5|+`uHÊÇ C©šxi¦Þâ€[ºî‹02+'ÍFhy ,>Vp{€ÝÇæ(uÜ/~‘ ÷0‹¡—\Ù'ÍUäP¡èLxê½ÝÑÞ‡ð4¸ûe°»)šÙËÛ.æò€]»3íEõÝ|Ô oP¨B¨£Ì¨£„á“Tû Ef»¯â˜B²ˆ•,¼Œ ‹†)pzË‘ÃCYÄŽ_q1¹( ã9X”EêF8 ¸êºi4m[–Hí´,Pcç­†Ni+¹gÀ¾¯C™‹Ì)ÐÚr °”,–à=ß±}ó€ä6|Ú­¢Q‰_Ýñ P¬ú²Ñ¬a8°‹u ZÏdNˆ‡`z·þ|«b’xõ®#ý¢á©ÖÈu¾ÐÁ.s 5ã$¤”S Á·LƒAé¶•ïÍ8{°1ã+œÌ ‚©~úê†<謕‘"·…7VެDæÐÆÈ‰!ïÜ”îÒðž©Ï<´‚çTà >ÞnL  ¼gÅ,`3ÇYžµÌFzÖ(¥Ïö&àr¹µWxm±©½Öóe‡†÷‹ÚZ_|¥&v·Âer:³‘VÚž=x8ë¾b°3³K¹Í~®!MyÏ4Œ€ÄÛ,_=mVšèJ¯CàÜ àW™¾éuýÎWíQ/ŒP¿Øô {ÇŠ´Î°±–Ñð{¡^ô„¬¤ýuFаœù0qS0%‰LÑ;7ÁN;ixNÅÐJ»í9 >EcÄàýFQz–¥8êÞ!ÊS=&Sþ$˜¾÷MU/ëDƒa/w^íÛ2îõÔ“qJc~X}vßvµ•H6 ˜qéí³©Ö~"N;jK|¯í‰Ëd Ä–³"ˆ>y¢Š ·Ÿò¢ÃókâgÖZ” ,o{˜-0Oó^WS"ªf¥’·ØØAÁºu^`Ï{5( º€#:Ìã3‹PR læìaÜ8ñ¸‰v˜eŽBÞºì³ÏÑ0#ôi ”ðÝ#ÊU¾¦d̶š«ôs~ª9Œ—è1žLpò¼æŽúA%ÁÂc:ÈŒ~°CªôMñg´"T; DïV‚ǘú¬sj'DSoaô­ ú¡¶ƒgQ˜‘Hx.…ºC𱂥…Ÿ5÷õ: nm«»ÊEÖÙfVîS ?§. ÒYiâ{/ùâBø·Þ)a}Mçé5-/Ú^ÔŽ÷¾ÊçJ¹þèuêÌʉ4ì£ \ ê”wõ4ý]uô¸ t¬½ç³ s‰n†(~öá0ÏyÕïàú½fiÕÀΧJ6þ 2Åh6 U;Ü1 {Αúƒ`A¨;zql°Ò¦ôPp• çÏ$ZÙê¢ñÛ¨ù3dÅ+»„jì÷6^Ž)Ú0Ö3‚®µN±ÖËwâÍ3EQ[öØn}§¡¾ôÍÌ9k>hCfÖ /–`Š-K»HÉ‹é{íIåvT¾Þ½“|X)½àr[áPYÑgq„â ¼g«¼Í>æF?ï Nž—]3*¸ä²'(ÜEùl³^`Nl5¤”6³w•ŸªÄð£¤Çêý³sú{?9>4‹@ -z¢2‘ª ‚ª(š Ô^+œ0Ú’úÜjY†ÒûT š¦’ZFBŽüÕÚ9WP`sG¯ŒÃ'Íï3nm>Xç.ôâ¤GÛ­Ýe.œc²¨E£¯uš=1N: »Î4÷b“íÑ—¼=Ö-ë}wØ‘ÅÕˆÑwZÜÀKàæÌ, YŽlµR=­zÇç‘X3­‰»cï^×h@…¤U,ßRïÆj«õÃ)ßWîC8p«èkÁ:ÉÓ):ÌGï4äU‚&R¼[Õ¹¼ß‡ƒÛ'äáöÜÂz)ý½\~UÆBd&Ó¥€1=DåîñÔ(Á=ZcQZN{9/Ç#:J¢¾é§ •tü޸Ϋ¦=¦þ$Z¾zb#eûìT'’Ôžé0;ãZ•©ÏxÝüØ'‘.”7å:¯fI,¦è´Ä/G‚GÎâ ä–%tùÒáŽÎ V @¤½…W¸§”A„Ç:ŠŠ£& »™„ «¦&©ß»èTï¢12%©†Ož3€e”´  æ¾0Õ¶ ¤vïmí-9‰^1Ï#…ÇÑ•ÆÏb •QwŠ­‹Xá+’MÈ… Õ6 „³e¯(üÑ>Åw/¢£_ÂŽÝDä±:>Šãcˆ›FÕÌHî‰ÃC"xõ2eãå'ÕúÁœµø• <ÓSäÛ÷,ßBóqùB¶Gr˜H‡ÂÐÈPÕxvJ°0a¹p>Ä™…§:â)aj”©#nåÏqöU¥%ê³0ÜyPÏ © ]¤àíóçç}[ãXbŽic9aôÒhjÅÔLËZ™ª9*JÄ–HE(%â5N—´¹a"ž Â{-?É&}‹ ƒË*ñØg¦(„·8œz (™ì \ìDZžÌ]4Úì±ö¾’iÜ•#>1¿ÅÀ]/ÁÃràW]Ue¥))ßd†±n3ù)-KrX 2‹¢Ò Ìz¸ËYYs:ާãàÎ a*î!ø&$…‹X86¬p¯öΓš3§Æ=ŠÊrœÑ§ ®¡o'Ëzkª¶Mn,H@ál’Ê…‹ <ÄýÎu[_xák‘é]féâ  ß7œåë› Nrž³µ»:÷@ÕÞ ?ÒÎ|Âç³ØUbñ'1{8ï÷¾Ze’’Uq8…Re0(˜Â9ÎÈÐÒ¬ž`¸ª@ðÅ{}ç²o:‡¦`‹=Û¸ÒšyÛ)Læ—¥”§%ÜN'þI·}Æ2SŽzŠwGEO$ózÍ)ÞËMÙ·­—[¡UÒ\™ëêíB:üà]<µX³ºl¹+: ±âE~8ÆÄÍ@›În4#ë¢ñ²g’u$±<$3Q·S^;©»0µ×-Z@ÉtÜÛ–ÛʶÅ!·ZCxŒ‡+ë»Rýh‡mì®Hø«Ã†¸ÕÄKä=®ÐËÍMJ DÂßï»Èœ¼o«ï‡nÖáù°p²²é¶cð$x¦ÏÞ¬ ;Ezd6O Q_†iA‰cô“ŽÝkÁrK²AìX¹ $D’t7yßÖ´RA¾V,†¾JñycëpñŸx@@ŽCá­:¸O+ ‰JqqùóÔ,ÈmècíçeKh'²^U¯¥d­ZtX.M-Ëz7ΓIî{èªÒb]»¯ªž]¾Î3¿·«¢·Ml·o·*/ tqj`÷åÖÀFÑÉ»ÀÉœÃÛº1`bÇQÖ2æéâ:Ó+|Kœwxê;<ÕgÒQ­G?ßø£kÐ鋨·¯Š_ `=MMcÕ}&"tSäÑóÊ=¡EËËNqbv÷ÀÜqAE;E‰ Ç›N×{réÛÒã;ªI¼±W'3ûÞ#•y orÂïxùuM?¼E­ÐÇxÚoφßQèVØ„(ä¹Þö›^4zGPònlNp^²åŒŠ¶ƒ<½Â:A¥]§ÊŒ @Ø{Ýèep|®ádz}õÞ¶iƒéÈw³æ7>C½r›Ñ‘=¿iÿŒoëÒÔ—ªtš÷‚GC¬û˜2sº÷t×'N/ bU etÃÜÜûÅ^¸lgºÍLPÉ…½ö w¬2jZÜKµè7¡õxv¬#ƒëD;©h%r*]4Tž¦£€Úµ¥9p(żx>(¶V0N:XçëHl•eLÈH7™o„ÐÞ»pŸÒ›ƒ'/n:9x”£"ÏP7Ú«òù/âûÞ Í¾a5F0rÛ••.~}‘g¾*ƒƒ·v…‡\J3QÎÍf§Yï4^<óv ¿=óõF¼Æpð.“%šœOâñ3Èù£nqx¡Dcg¸¶Œ®œTîÒ¢ •JS¯)ùèi-TaÚ¤“"aÒmêM+í>ˇS¬3Å\‘ý*smNZ×pÑÎвD©sžií Ï¡`ˆµy>4>û.ų¹oóv÷yCÆn»¿ðå½izʽޠƒs  ´i…qTϪnY"é"]%}xj¸VÂçF®±ÅÞvBn›/“;GÔ‚|’ÏŸáN°lª¬—î¶Yvß ¡ß<¸X([z&:¯Ÿõˆ((€×4Ù >€`Л8†½›yîDŽ(ÂòøJ{„Õ(Ë®¤8¹ºöY-Þp™w®§Ü(6>æ³a5™!t`{Ú9b€^+?È‚nê³wDüTãømÄmÅsâQ*Æv¯òéaân?Ô‡ëoÌŒ¬$Öž–§Ö^°H­˜Äå/ú“Ù@éd¥£Yøa ½£”Xí ŒT®“Híë%EŒW5ªpäMñ|€{z¥­Qp¤eÎ8ƒ`¢¦ÒAÛGf¾½vê}ßô?ø´}–ˆ?iŠâ:a `>#v­¦»·WórGaÄ ×_æÚC p„“%×óCSÁ²I°Â­ÇNgòz°CHÝœs ˆàD€üÌ‹W[hHNóz·=áDˆñB…óJ/?22Cí{¹•6=IÐC‘éHÂÏgâqHVƲ Õà(̤åÊ4<)ržÐÅ®çnd JF™fVòħ?ÍÿñÆÀ¦¯®3ñ+åqz¯m­r)»œ.\YÔEÅ ‘û“"°4Rzôtm˜zጜöÿO˜ãV„@½4{È÷?’%Ç#ýÌé?AUÐ,òNÑáˆWöí7€ïãimÔÉÓŽ‘4Q™AÜSª°PW‰¶ƒ§ ^›œ‡Šã’¬o–6ðUŒ›)[ÉÓ»v$º}¹YÐסçµyvÖ©ÖÓfQ: »!„Àqêsí Äíõx±J.-KUºéi W:Jô–¬a7o±¾|©o_Ý‚tç­bí”Ì@™kÚó,U=°1ôèxuqõ`:9²ßPˆ¹ìûyбI\Ž eØe¸h÷ƒ'éÐ9­SiߦK¡„ï{í¯ïH]0„#MÞÂVªpÞÇ Pù²¬-^Å‚q~Ïè×i:”ø$$Mý)€:»šÛÐú ô{yÚ°Ö+PÌ èzkÀbëkqéîmÄFŠíl•0£™ò‚tó|ÅkßIcð>@Ö!ÕÜ"ª˜ÚÛlÏÜ$˸2¤HLLicWôÙ«æ[;c8Š’2ùˆCq³ªði=ÐKH³°]›E´p|¤ozÏLúÝ"KNjMbwÑÓ:eþ…`"ù™â…C›7iŸpó+H}!¼(`i½‰E–¼J¦Þ¾EÝÊ¡Ün»£ŒÑ*PŸÛgo©BY s§CqÚ¿‹Ÿ~†À3-—i5~OFyƒ tp _YåÙêÁ¢z¨Ð¯Ý_ÂRŠia¿!Øó3ßóyÇ*†™tÆ]±6V{Ö!ëyTO­=eê‘#y³8Q‡ws²ašÃ³G{ÜÆœ.ÔçÐOÔgxG<_‡2;èñCàÞÒç+5g¥TPD¾A¸„åÖ Y[DÔz÷$æbá½.Öns;îJjaN̼Ÿ÷÷*•ñ`b¤Þó¸)"I‘m eaMkÚn2Y‰“«m†UvôHŸ¸ÙBug2>¡Ž(ÕxaZ×êVPZ´‘YlÞüÉÀÞç:òŽz›Z=Ft×nèWõR€’7ý gÑ=Nƒ øàN}]_:†•S„˜pì=¦”gqý”µ† Jw¶î±‘cXVqG¼ÓÂé¨ôÀ·Èî‘ÔB×À jHò )¥hœÜboîw(Ý'#àçDÔôfÍͱ]àžb¹Hsmuã“$‡lª[-yQÁ}…ÆTœ Pq_Š˜ùAàͬ‘ÄŸ‡†¹÷С4*Ò‰@£^§÷ø‚%qÕÖ{ÙÖç^¬žÁÖÌììQT£" ‹½Äž1®”Y‚Âξ!%äaN§'WšãŸ>!`ßôKë.;",š·{wdËž—ÑæÞtÔ`&"”»:ƒôQ=åœË^ÅM)U¡wÕ~°BG°ï…hNV?S9±+S\dÛ®sQ¢)]öÄó`BÈàsÐïÔ„EƆKë¸\mÍU9ôJ—«+%Bu"÷¤ö­C†û«!;d¹íÚ¢a¶¤æeí‡ò¸[¤gô<ÌŠ—^i¯<,B›£êaxYaÇþ| Ö·œˆiqSÑÕ”°Ürá&™¢^mH ºðæetò›îÝãó#™QïzO®ŒJªmq[Òëò¡(­ñå•!ßcÜæ8NÅ¥xH¹þ´²Èáð/³¼`ofä«8ÈÈ…üDh$Eº«ÊQh– ø^t¾šÝÆ`õ™±îvhÈP ¨êæ1Û¾{ت5Ç®,1üì•ÎÒ!¥ºéõƒ6¯Š K|z-‚Ëp/^²"Á€p»`öF÷Ï‹­»Ðlõæu™Âë,¡lnÖ0óæÁ"Œ¡]â @ô:n<KsùöÓEMàU»ŠpdaØtZº§OˆiÃÞ÷1è…~æ„tQÃ9›œ‹H½Û KÊŠTÃ}!ÀáÆn®–ÚÌZ àvÙ‘pïº}©oØò#– *9Ò@1tÞ=\Eʈårýèù´`¡à¸B=Ö^ÐGéÓ^Ôâçp¾ä k¸õ Ù"¥7¡è¼öÆ-;OH“lnwÉ;rE«Ö–~­û46¯Fcƒq8ç¾É×R«¯.|9Ͳ^Ý$=¢Ö!?œöŸÝý À^j‚§¶ñƒõÀZ²ÔÁ¨¤ÅgÚþô0×LúðÉòó\L ë0®…žÇgp‚pÈlØ}|ì’*†ûŠÞÂSÄûâ@ð}p¶\µ°«†Ò"]qoHc{bî¥cñHÞ¦¿à“JNR-_¬ç>Î'hþüY˜¤)U³´0ÁzŠÄ³»€,@´Òd2Ð1Xˆ? Þ*]²ñèà”Í>Фg§ÍSÕ–/ lÂ4“bóTÈÓõCŸKÍâG+M ›“N ËÀp‹ØyìÊXJů‹ûEÝŒ…IvèÎõ3Î}lÜ Ä–`ÞËýdý'ˆçI¨rä]³üLT¼*7r”mÂ^_ø%ì67خɈéÔÅÉ Fºã/ŸMnØ¡J Ò‹®õdä¡M»éò”vøïs>èH¿Ò ák}¦ð ¹3Ò†vðÕ34:¨×Q°œžª²j«1Pø®l¹·žÐ:8 ö–=Î;€8^~÷Fïá öXgݼHf¡=JÚ™F?o³tz&ŠvYÍ›”ω2´aCõ™‚ů/¹P¤Ábp·Rf²Xk9Ý`®½š+'¼¡‡EVé æÉ± Žò\#½S줄w —o([Ô^ü\ϱè6DXVèa&äø¥IHÅóvb9c 7hÞpXzì|}xnðv0ðm/{¾Ý˜ê{¨p.à A© ÛOï3Jö¹è+¬7j3™G³[Ï+‹nØ£§S=%}tõ<²pÕ'e$ÜÍÇ÷FîíƒXºŒË,P\Ä'« çT¥VJ#‚zËYÖ—ëW‘§áÀ½ÐïÅ ª CÔ˜; O¡>†¾…¼ ­_(´ÓàÑ>0}¼N’±ž[©ZQíI0§†à{ç¹³EEìÌb5ðÌú‰¼®¶QšvÛÑ{Ñ›F•«l¦<‹Î…‡ß(¾ß³—0« ßÒS æyg²(á2e$ÜúÿIѧ øÑu”áD5'ÓSû™‹Å {æËÆZmKУ 5²ýŒµ^¸Ò–mM*ró L)MnÈ@”D¬ÚÞB í<2Œ'ïŒIFyÂî˼—Úºd\ õ¸‘R‹§s– KɯlUô.Þ¬QiŸ†‡7t‹XCãë7^ΈŽy¬Vm’1?kg†ÊjDã]î’F‘ 6%¡‹¿\z‘+¸Ú}%ÏäÄÏØ{§ü´œ‰/›‘$'JD2½ï"ò½]ëTרd|×ñ¬ ëûAô/a| rãB£WÖ¶âS>ˆ\ÓZÂ6agÞ Dí-Š|o«€­ªï©ˆ\ª>Ft›òƒ.åò­S—a;z®;ù œHü$b0WˆÓeù˜Ÿ ßBJ(:=‚–=_a~j›÷ºy_ Õ ­+õ« ó(îÇ¡H~¦öúÑ#ä½›k$~¶oÒ4PK{Õ¾-™Yî3pà«'ž-WþF|ÀÑ,[MÐîN~Þ)Šyû :ûÀ6SXÌc!9¢ç9Zί™NÄ¢uœ«¼QAÉ>Þ÷ê´óÍÞf'jUøyÏæ=Ýí{×ÁyË ÜÇŸ0˜?—=Ò2š-S}ut4™â‡dE╊ {Æ"æ’Q{S@’ º|ñ¢&Ô£÷ —jR²Ù¡zËb Âs\&JÁp®)‘ó´Íq—2ݙõ©6õXãbáapÇsõ9Ae}¢~ü8„™¸ævⲋ lˆßF¼ ]8÷ºuç„™R‹aëžm%çç’,üb%Ûæ‘¤¡=~ðppšDO’}Y¦R|µëµïϦjÔ>eQY–+?VZ‘{ κÃŽ½Ïx9i\BšÚÄ©Iƒ>ŸéE‘§V©®÷ŸƒÒ=hî' õ˜Â[e‰ý;rÊgä,ŠÛòç´9­´ŽÎ%8'¹tØٞ¡TµØž)®6>Ъñ®Ñc"e=¡ÁNt^Ÿ†YRÆØ&ŽÎf ÀŽ'OŽ®hz¯ÀóZçi°ÕTݸ`Ð •€B´"C€´Pªº–ø %a¤X…>"ÜÙpäÈ£YBôtŒISMàÇÅ‹ó¡`çižâ ÀV«„ ?Õ„;¬dh;´è|.,6ñÖcØo®Æ˜{¿W`ch—Ñà^>÷Q x­Ü‹I ÕSŽaÇyÛ…ˆ>9¦%Wvz¡ªÝâóÒS½U6P„›qÀéDÇŠfÈæ°´9¾ç†~†Ï §>r õ¶ˆ8Þ©Zà|ü2eЛ™i¶D+(å´#ˈsÝ6åçóâÄ7†¥½º,$~/ášÍíÆm,c“©Ä,PcÏØ^MÕãtù»6Êl–ô î¸WClvŠ7TzðËŸr>äÖÛ4.ÁzOÛÞƒˆms§d}åTš7ÃñØËó‘‚ÜJ‚ßÚx±ÐC~¸U©VcP3uÁ•Yv$12¸›rϧïg …æݨü„BÈUI:˜ô¦ÚbÒ¯6ÞZUë>“À5bë.¦³Ü~CvG“Õ×q í /‚¬¡Ñ¬±m®MeL¾y|ÆÐåÁFKHWíe%)ã÷Þ…†Ö½¶S†ó±}Ù©ºXŠ­üª€6MH3WÂq£ŽÓŠ…v–ðŠ5å`O0Á0_Q Ï¡ÊŒ\2Ó‹Ã,î—dÖôâm(ƒ“Ä"9óÈÀsÉ!LB/|7ÈÆåŠï^•À•¦W,1ˆ"AÒáˆS×n `o¶ÜÕ±Ûä…!Ÿ_y¾Žqµœ«0Þ} uVÎþs¹ ¾Ë€Ä|7@‘Œ¥ì€J¼&æ Ëïåç#UâÇxwõîÍ\¾'tÛõÛH!¼ yõÕ½Ò0)ÜËŒò—Fù Äôs¹ ´„=ZšÎ“9·DqX#$Ê(€®mŒaƒgô¨ÖÅ ñJùµ¦¹ºë°øŠàš¬>ŵ0RƒÇ5Ö}ôÞD­Ø•*‚Æ=vl«2‰Ãâ"í|ÕoN‡’ž_nMEH†§=ÙÁÄsk‡:‰bº6å(ôÄ~ÌxÆnÆÔç¼¢rŠç3o{µ´»ƒ™Ã2ó„6ž^íR]§×Šû¶Ù½˜‡Xë1‹^(§?W `ë¸Ä&ÛæÛgñR¦ìù&ÅŠíÎæ2’ÊÎ!¤«V¼WA+oÕm ß¾˜Ä¡=uö.(BîHʈآ5YäŽî÷IÄ?£éâ)De¥t*q<-œŠö®œ|jc9ÃnzfýÆ¡áxz¯Æð¡°“‘ø3î|Ró’ÉPo•wžHô•¨‘r Ç.ZÍ„#Ì _ŽÃTMsçY·Âܾt¸ba,˜^3òŒ¡ñSÆ‘ÄwHÝ>Lçk/”e–—Â5ðFc ¸ìè)jæL€‚æò>ŸñÌ‚7Õ´ïfqTP$ö…²ÐòT“A"OU½Áá}ðÁÛ ØN÷z\žçx,ë´SlÆœ¢o:§Ö¯ÙÓʅƨ®•7©O|ßohæÃÇÌ/ŽcOºØu쎤³±²Ë6ă¹ºëeÀðÜ"/!­`#ödñ¥i­Ñma+,è\©'VKš†A¡Ñàîg—)ÒMÑ*­s˜À‘Ts†ÈÕ²q‹mG)’Vån-À:mCÏaåCiâ$”´HaÑÒ¦óU €jÃ=c[|=mf ?óÃg\•ìM D2皦ç1AÊg±/]ß3-ŽŠ79™|tžßC:5o„EÄ‹inlyÒ:4™ô¨Ö—óÊgpMÉXVÖ¤×.}mtð®…ÃßeÕ»‡ûœ€–Ù\‚{®]˜VN!‚zï„Çy´XéÑAN5šDI ÈA¬9W§„ËÚ{bv%¤û6ìÑÞ ºJ–4 R‰WA]{<¸¬™×1![Õ1ˆä7:½)r†žëé¨Õ<Á˜zúòÙ1xhÖ“nŠ çQElI‡‘¢Ä:tÍ~!*îE%Þìa0/ÜLAáÁx(“ÄÙ×£oFѶGœTmÄú©aZ±«Hy³×£ÂçC9ÀXUÓ‰Ëa*hšžÜd#šu°Pö–ÓÇú“ ~¿©jW­Úg˜? ÍѱĔ‚p6/.îÚ“ Û öåw"ö IL®_º³Žé{ççä–.‘‡°ÏÀ{üŒ‘²È%¯ILÍ+ļaë”qL“àðLÈbcº^ºKͼÙuh@õÔ—!aƒÐ‡oæ÷.«²´­$2ž.ì£Lö—µ¢Šº{¸ÏÉpß>Ò&‰JÞxýDŸ¦•Ý!nrn€.ö-*m až dh׬\uM¬˜ö<Ô¼ G? 6æðbßÞ® 7§Q$¿¥˜Êc ó±vŠuku0´QÊâLܱ-ë8Ÿ×Çö€Ÿ¾UEp~×R#ûζнùËû ³‡-ÏûÌ(ÜØÀ†Çs¤ÂÏÚ 5f¡ÄÐ}îÕ›ö”"ÜI™â8§¾Z9dåc§ À\Tg\Õ46há‹äQ0&k-ACÝ=õ  ‹WãåŒ?ÈÞ§oXº/÷Ùº¹…ªƒB¢¾íNoòÆt'¥*¡@â3€Ι‘Ø'Bd“ ZíJâ—Õµ7WRíæ4ÎÔà™ÓÚ|Ú¤§r(º.Ø‘p¶œ¤V’4nìøg5­‚z„r½Ÿ\R&ö*_…ïÔX w«Y°SbÔwã"‡pHçi[ë£Ã&~,* #d®æ8†¯öŒˆÞ³SÁ0Öçî6Ì/e/æ“ }ÆÚ˜8Êÿ¹‡Åx*ön`À—€æÊ"prmŠŠM1ØÐW/Üa…ŸbÌeZ H›–‘@+ӯþ­9 H’ƒîšC‚‚¹679N^}=å+O2g¬×ùɃÿÙÐèÁüÆœ@n]Òx)Ö’Œýí¼c²¤zÛüòúb¶§iÝlîAsRž<‚AŒô8!x’p6KÙ4“ß=hggêklqáÿGòj†ŒaFÕâå¾q=De¬2´þ fÓi6rAÌO·ÕïÔ6Þ7úVYäaõdñÕ8aFå—8R6 g](ƒ„3Bè"D–VP|©£ñè-ï;·ðwÀE w·ÇŽq•CyφÄÌBUa5[Þ„oÐSIN§GïôL<ˆG Óé.öAJ<ÛÊly1ºZrØw„y› w wŽ•”ÈÉ_ ˜FѪ;·ú+x(¸² ¸‚PLØî*y祥÷N¢K_LZlXë¼òKm¤S Œ˜7X%lê/{´OåTñ!Žyu?*©÷¶u¼.¬CÞ:Ï<Ͻ€ÈJ  z~uMTf@=úPñ‘ÿ"£*ØO†hÊžN=MœÛ·Ñ3Âì€.%å^ÖYJ[LÑ„ÉÆ­‡8‡¼×6 *ÝVþÒ¦…ÓZ úÝà™4Á¨Ûû&ãŸdL÷H AY²G”7Œ,I,K zä ,S-¿HxW4+w|~k1¡JÙöz^t°ø+Œ/E¬¥P^Ø úU oìÛ$‡èWr½¾Ó*²ÈSkWÆÃÖcGâêá+::I‹Î$~oF †H® AO&^S°óP^Wî[Æl_5‰#zeZë‘ÿã%ñµ°¿ÁMÚõ˜Ò£¥&=¡¸D²5n"š“dãf«¶zPì –ªã"ûîš4a•÷ØÎžKï›ñD’ÖÅ勆'‹7àÖ5„O82Öé5%^ÏyykÏØlÓK¿±ì"`©Î# Â*þF#ß¡wK>&±vc”3fkNñdhL7¤òò•ðË×DGƒƒhƒ}ltþDo—; cd Îï±K¨(©WBãåcÙÒ¦1¥#:h {«ZB#Á ˜›`çE¥(Í»< 'üÖ&‹eÔº»‡RA»k‹p/ @*ÁÐt&ËÆüÔöÀõøøJÈÁöC#{ÝJÅtâõ’Ÿ5…%UN¢°Ïibʆ˜ít¥'dÔT¦Gžß¦oÑ”_l®ŸªÀÑSrÊ2£“^…‹ST©Žx¾wèmIÏQÚRQ澌·"6œ¸ïÅ:;Ƽ©íž…»`Ø®P5_tüd£Ÿñ—…Æmt«¤='bø Jߢ…Cµ¥Ÿ–WÕA*ÙóÞËœòôQC¡S ¾dW¢+êÀ ÆÑnÉXOÓ‹=X„bðŽ1¹žë»Áˆºía!c=‘ DÝx”Á‚¹W//nèŽ\µ¥0Œ@XCèVSQÚCaœ£ÄnxgWp…ôì z'G»e …ê{‰”+¬–5{Z¢ä0“øÒÉKUt ëÙRêMsTº3•žAÊB#¯`ÔÎßï»Ô«;Û²w}‡ÉÊw¬çl¾éð,øX¦ùœQ{ °ô\õÆÛËXÑ–"]™gâ@½ýÞÊh»­îçû ÂM>ZP&Ö%òj‚a{ ö¨ $¬‘Õõ0ß3xñžŒxõZ*i£=Û¶¬‡lëá×°¢pžk§X{<&›©¡o´ŒdÐPH6væ©5Æ«wh·3D€2ž–L¶O“1deÏpE‘fæ8†´¯VÒ-Dô%¢®æ»ôÔIàÊéâ}#³„7ÍàÍbŽ ™m`%:JxÒëõzV â ™íÄ¥ýkµà™¿¹ó†ŸOyAA\ÞJQgH­|7ˆÏ7Ûd°÷fO•ßÕ³{Ð%ªÁý.½R÷úhaEÛÌ£/³µÞY=¶ÙtR»›§±Æ=W d@¸ßtü3û¼Y:(²Tré£pB;ì¶„ê†{š’&E«ÁJX¥Ü¦$»C¨'Hèã³Hm/+ÙI]äH–äy™é@âz>*ak/MˆzŒCµAf¨Ð¼jA‚2ý"^—]ãd'2ádD÷ê™y¾Ø—-}*Å0$=]ª‚´ý¼Éó®~––±"\ ªÌšzÈ•(²ótBjôYÙi°7ðJa nl96A¼ßBåƒ7y³ë,}?Ü%>Îaa¨Ó¤oÈr_[Âø-x‘JÔ³‡þx˜ $Ý­€!œ» Úñ_£oY…Ѓ‘Ø™¢‡HË/ùÎV®šœgÒÓN¥’ƒ€Qqç’¸†í`G¸êu<œ&¼êñ–kWÏ=—ÒŽrªÊ—’þÞÜQ×mÙ~võ\,e0ß@ ¢Ü{ÓMq«x²X wº^œ]Ü:iìµvtàFAÁwvéKqv¶ÎIÔäªnÒ€Õ…O©ƒA&0À7J`%.«”Æ[«Êh|‰"J¤šàâÝ©—æìܰÙ(‰Alj 8Û‘îãJ(1$èm±­(Â$ó ôàݧK ü‹IÓùÁôsß~]úÜØßÃ(~õ¶ºrâ7ñšíò *X—­c§©7œaÑì+~ÆšMÓ'J¶X/Èp|œêÀB¶ùûÞú9{ÊG½ÊÓÄèÝ>{Ž’ê‰-™„Å8;í´¦òdpiˆzkb¦T…L=E Óô»>F<9­Ö³…ËNóîg©åá.žmQ¨r÷xUÕL—âÄ^­Œã=eyŒŽˆrôÌá‰ÕUänk¾¼ç+n ê‰ùB¨$rÔá¸K½¥mÒ“†![š"_¤zQÒp |zçv×^kùžÜ½wUÑ^Z8F-æ ó¸Ú¤@Ëa&GT˜Gò´Ù\ÖeÓBùÏù°Ð­ÕBè¯ùÞ e R`ûhz‰oòÞu+cqd:îs0¨•É0>$Óï~ój*/Y”Às¬¡‘*]cLHÀž-}ø ÌZ€nÌz¤¾Æ«¡ûDßD£39kµOø`GMŒ^{]SS‘sóeä™ô`@Í’¦]¼sµO €9t çqHïð€f¿ÜJñ…—@v«y5*ÛiÍf34m|ì¥k‰u#Ý<}—GÞÆ«aqöåx^°Ù^Ʀ·Ô ´®/“çŽÙ`êvt–}áž@(»m_ÓËgÏìèÕ³'9ËŠ…$â"œî¤}B5¦vbd#‚λ‰YtB;aÚì?;W‡‘H.Z E ¢¶‘‚ô rh/m”>{‰@M™Þῆñ~-ùøÑýBÔáO…BÿçíµÐÃ'³a©.x-udô¶ŸÓ*»ñc$ˆõ|hˆQÎ- ç‘\É31äf‹N†'“7üÑû Ñ`Ún/¬\-ëXL7ŽºíüÝ{…Ây]÷‚*ã°@œ'5úYÑ[(,;Æ×|XþØa 2IáÛ~)I„&ùªžç4›ôÞ9Ðyï³P{häxðV-©øœÓð°å=_è—†dtzjO_oú`ƹ Áå\BÕ<’¦bLE“aµ¯Á‡rzäª'äl}ê{´ïª„«#xö¼ò-»©¾ÍŒ×•76¨¹|w^°Rýr„gïâ&yƬ´M8Cdð*sà÷ûP-¥ìÀj‘ÀSÅ~ËûR€ú覡<Í€¦æ~ mn»Úu§Øh-sP/šŒŠŸCŒ^“Á¬òÖCåªÜzߌ¾ßšÝ7¸„³ú¡ÇœFy%11–YÏÈó5WX™½Î´(èH–—Ãå/“@k…tËz§kA|¬œSsÏŸò`÷hš5Þâ>¬wÈÙ:¥*~H%àa—òDwK4àÌOž‹´O zr©êõ¾ÉW,:–¶ÖhYrï wÊb5Üðm(J8Ý€)c.oL= ËÆ\ÄK± ÞwyËZx‡œö6·è˜sxÎÅUgi؊ļ:BÛ- ߨÏB¥ 1\Iõ$/ø­·gdcÎÔÜX£C³Gw)Ý.%?Wf…:W‹GEìuKo-&"¡K^³^>0—ËÍ…ôêOJÌŸù¨^>âcÙ·=âJ’,8䑤‘Y}{0Òq׉««t¦TÒÈWQlNHíë {[”Ð'7AXæ±j›ïÈ÷ [·/\Ç”Qâr€µrÆ{3ùh;ü!B¸'§ùÀÓ7%%,…‹w8ºeÄåöˆ©œ_‹m^ߤ3ÈîT±ïÑÛ $ ‹GÒ” ¤¼dØoLÞá8!ë\pHCj‹ÕÅ®Ù:\˜[î>«Å[|ÚÓ±çAÉiÓUMjËpË‹»ÅoóIà/LBdlÆn yL[Vò‚:_íéf=¦WHDÓ¹9Ê ºï¹âõ¦>ºñr)V17’—¤LŠpÈâ7ï-ÈÌ`Hjv&b’ϰ=¨µ9/ ‡§õÜË›E¸×U眠<tÍ5åÜÄÖ‚òÛöÖçA‘á1‰ŒÃ½0V¡™Ñ=³lWÚ>0oº^±L¼á«)QkHZ×LO É{zu/®µU‚±g î¬çdËSÏb½îÊØÙ|%È»ÐÄõÜ1H÷ñ¢`­ÇniO¤¥äuß=â±.ÄŠØ:ñhñ¸5Ù|q°ÏÏdiWŠf«WÁ’CÇÙGíÒŠéµa¹ùˆØ‚¿DßN¼š ®_œžgIë O…—+¸»ÍàðXÎ:.Ò›€ï½’L÷åxO°ß uËøF„©9êòéÈ3 7™)ÅDê»-Äq…oNúýv}*§Õéb €º¯ríV,f Ÿ­d=“£!â3:W Ý&Tß{3ºõ¸Ê©NÓ*u£›ýbÑðõ…&;ǘÌI• ¹Ý˜o, ­éy¥mk»s8ÂI\qUúC(²Ã!O]õ˜AbmßÛЮet@nÝì8òBxî<µMQ’ÓÁ"‰Bô0åv`å¾ç†Ç0#Öü&|ÈÊhß-\²ჱ†V {;he¶ ßS¶wII•®?Aån6 LÐc9­³g=èσ!¬^ƒ-Ì€Nb*³`«ØÅÅ“µöôà\ Ä­~#ƒ³4‘è€î †ñÌ&‚Î.k甂b\y ÂŽôšn”¤((µ,Ðê=LËêg0—ÁÚüT#³«jÎÅùˆ`Ÿ·½p¶Md”W£dE÷м¸Fê¢-°Åô9"PÒfU!®P¬¦×ë{a}$Ø`^|égGÒ§X[çŽ\÷Øp×µÅP6ZéŒLÈ"m Çüžé{W¬žeΙYÉ+Ä©sƒsz‰"ˆÄ¸ödç­Û…YwYiê\.£²Û+`­CGD·AÁºŒ³zu‘=õ(©VÀz¹oNÐæuÉU,gý$5ˆ¡heKÐ/]¶«¨êèÉ̈¶÷Ûwq­KSw¼òÝ D´ÔývyÊàÞ«àÇÅG–p¸¶IÈê£øÍX%çe%¥,±ØŠÎÖ™¯sYBA'¬·ŽP ô›\ÂzЊωø˜Â±–ê!Ž%¢DÛj)¥ë¹j¢’4>—è«ÈAc…4+–÷RÝ©i4»]WQŸªm3òF"p¦Ç¡|…cUÒE*{üòˆSf¢ õؽ!ª´òÞË -î|Š'b¦óòjÜKSÍsðyžºÚC°Ãk£–Nc`‰VôâÕsÜ ê-S¬Y{›RÄÀW¶Ù^Ït¦óö=²GÝ$Òú~¡Âv7w™îŽ\Gx‘}PÚ1àÔSaÆM,‡m"+Ü,yJi0ý²ro sõ°†&Jc¸™ç½vY%ýŸ²¦Ñ€øJÊ?Qùg(7H†ºÚ‹÷Ì3ÇÞiY  †5o ÓSõ¾mˆì.}%s‡¢ õŒHÕ-ƒë©ZôÍÄäYÎ&ò™hdD¢”~Ojï¡•½ITÛ¥ Чo˜®£+ãPYɆæ&¾œIe—˜ãrÝØ…_ \-t/Ï^|ÁéøXvIqV÷N|pÈ”âÈ„jÛa«xoö‰£1)˜ê£kF¹,x¤:øZ„ÇÕ˜ŽšJÅÞ2)¦‚=EBf¬ä tºÚÈ› 8ËÃ\C{äó³ëÉ›±ûŸÈXV†|Èi1'¦z£Ö„ɆÝq$¨cMìMt6\ØI„ôÈCËÀxÒ{Ó/²<ÇWÞ—)¢$ï“U¼OVL¢ËÇu®ÌgVÈÇ£Ö¥5Ñx’Kbúp¤ÙVô•J«ŠKç½åÀb— ˜Ä󞓆 9 9Œ¨Ç ‰õdë‚Ý+X÷} 0újâdóØ}Î5™ 6ß3EËìáêÍýšil”Sžú¥a€q(€[QjV;™û;÷÷ÿ'±Ä òH|õÚÝöm‚íyùî=›vxM¹$‡)P»šØì•¶hrD¨jPωíej*î¤:%Å.=}°ÉœqÆŒ˜+½@ Ï/²8ÚâÞ/Xé¹Ë/Í:JÉm:Œ0Ä1$&jÜ|@‘Ýn@#;GÏyˆm‰[j[‹Ò‹zsî-Ú†;‚Ù+%gæ£Âæ7Ú~Ÿ¹Já;¨7Yø V«³¿1"Ê*“é¸[W0äŒ#\|®0³³ÜèÙ{¯”û̘QÒàìqÏ=ƒYºe›I°RìØ{I"x,)âì ý²fÕt±Çä”D2is³–JpÚ‘&®ÞfòÁáÄ9ñXçD[kH®sÑ r©†ÚóŠÃcN áb„îGi‘Zú–XSÖg\°Ÿ‹EÈLÔCË-g#„ÅÓdͦyšvQÌá’§¢óÊ:t=cýئ‹÷´œ:³/r¯ÑëúΖ¹ö4ȶfÚ]¢Ì~Ñâ Åæ*’µšÉ·˜TzÑ#oÐ<\˜›3žhPmºŸÊë#¯Úⵡ…e{îÀÈ`¯^`®"TŒò¯¥ <Ñû¦åŸù*E댠ùœBÜ=¡ùê *ˆ‰¥ßv^ÙR?*x ¾j„ë2–äÔj³‚Z.ìë I–¨î½¢|TT§Ùóʲ\0¼ÝêU ,zg½}ŠM˜k§-¼§iù’;Ž¶Ë±—Ddø ‡Ug¸<(b €1Âšê ±d¨ÐQGª!faŽfÌ{¨Ìoòuuºìš2Õ=Ëw–]ÏI$¸¡Îë[i¦×#šëˆÌÔƒÛå³hÑÑÅ^ɧ·M ­zOÞé*ïthý¼ë ”J)CÑÝ@¢øKáãö+’Fˆ²+¶§ª LC K —(ÚÜ{ÅZRVܰì ó) ×äNÓ>›hæ¦Åq}€ò‰ ?Ã{)_4màŒ€1 @Ì8ècpÄÌBaÍ0®.ô!fåW™Ò#”ç<âÛR‰F€#ÛpÝÑUtCwho0(Îü=y7Hämy–é{&õÞ67‘ÇaÌhÔ\ˆoíó%L¾ÛWrèéæ„}erâéÖqùpÊ^åÓ ‹zÓœ‹&C¨-ž˜âíÐc}½É$+¯øqš=:ÍGbdŒbIÜãO ö“Äzôüiï-ÖÐÜ5J®5HøÃ;&}ÁƒèåêÍ3…”<^>™óÆÝû9»¤ÅY”'ÊE7>ç ¨d°ô• G Ü,Mà îhY(2Ä÷zç‘)é*¦Ý½YxH©F ÍûÐci5cá;Æëû~[ÆžŠ~ži÷VÚ׫乀>Íôx µMiûžú#¤ÁðÂK¢k{!äHÂ.nâ¹Ú¾­—M¥uYxP/ß 6£êe Î={.~oÈ š!ÜN™ù »åqôHSöºøæK…ÉÒTIbF• £ìÇbà±$ e=;Íï^,BÆCs9-{w¡ˆƒ‚zúNQ°ŠÌF!D" „sO*ø‹ Ô,õP ÚÓ|QÔïM‹$JùçKÈýÞ«€j^a¤ÕAçDpÒ:XËÕž˜¬?{"©="[ =x«À‚ù| QãY9’NßÑŠÚ´¢ß‘!€‘u˜cE;§˜Kãj-L¶;P²rÅTð<¡<ÚO`ôè™#öî²¹zSž±í .߃2Zv¯ ”vO¼[y N–¬õîAFµ®rÆR‹r>k8lÍÁP # Ý–ºÅôkM&é‡.;pˆÜëEËm;¡š@ꬴ®œâ£ÏõÌeé¥3SŠæAñœfµØŽô+t™Ùuö؇ÙÝUÍ$ê·:Y¤O°žú+õÇþð"¼é¡*¿ðÅËÂʪ¾+ î@wo}`1vSL¾ã!/F'ôá»ÉÚ1µ7Äï± “aÏæpè–.§‰g·¹² 0ý^‘g†” Xžœ Ú{¹ÒÜÄù\¯@üѸfüÿhàÙžPÕ}-*«,9ßâÞ,¹ © —fE²ƒ$²Ô71þŒö»]å7—<© n@íÙiØ8žÓ)àâ²9‚ u™À»×u´~¢;Öäî/m÷ª]®#C äm\:—çm õš¿áI xþ¬p+ÜýmâAúYfôRêF5ë»RmNôɇ ¸XA$º…ïÈž”N¡:ß#€ ¯HÄX™gwœw¥è‹ÏÀ×lu刑"%‘ðG‰´Ÿ½ôk2p8`lCb¬]Í.Ω3¥é /â^!WA —66»×tßP IÖ»G(u¯ôݼñ Ð|¿&»ÔÆìŠ•ÎÌØnçÅËðHbæôR¹Ä9dÆLÆ”¶@Õ§ Ë7Pi…Ó(·óX*B‡„$œxýæI†º<ŒÚ÷Ì?‘)-g¯´3ú¨Üö«–yI@3,ÄFºT0g^kù@góäVú#ÔÎ#‚=—G&èÞ³¯(ºƒ3™CÌÓö¥/dŒú:jù ºÇUÃÖAP ð)Qn侚,£rï§£5OvYa÷į /ãu Åy› „­¥¦ÒVE‰»íõ)‘A>³’aàãèÍ¡`³ï9¯)úayî8Ù»y;Â"–ÇïÁeCÌ¥3 jD…1ß+Ì=²­b™îX¤¹br~¾‹É{SÔ¹eGA„huJYÓ¶bµÅhض˜ó²@Ü´y¬”PK «£{aî(;'٪ʵÖÌVѪVÌïX0œyŠ2´Õ_ÀšV…ÌÓƒsàöä{†¶Ù¼6÷úŽªZ$ÑÖLž‹½Ô„œçä¿ Å«a–¡Îp±èÊŒ &èµ W Àˆvì<“E«ù YA[ 3õõ~Í´¤o.0ÐÂPß*i6}BÓÏà/ÂCD‘f¹礗 #¤ÊâíS(X²” ~·h˜œýNu8žåÙñ€w·<š‡§+G£ÇÏ{º¢ÐćŠB•¿;êÒÕ$M=)ªf\W,r.mñ*H~ïFøÍ¡Éb-Šá•¼\Õ{ãšïÔ§÷evesÇË&Ú-Îó#|EõRÌL`i¯† ÖÓ;ÅŸ8†áUR%×À˜®¡Oö9 QJÌs;ïŽ÷ˆ×òcÉÓ%½‚e(Mô¢ÌSñõ·ƒm®„7Š›¶ž5]n»ºü¢wp0`ÚÉÜ$”ÔjÞBÚã£Jh;ºØÝ÷ò \5²¦•<$QÒ8¬Q']–¸pÑn¤¢¼Õ£6¼ŽÖOjö¾+€YØ>({I¢•"u¶sä̓—öðÕ¢n¿ ÇÌŒŽ™óØž"J³j^ ÷ô—uÖÖyô¾ó‡ãeÆPgs¼z—`>ˆâçøØç|Š4»F*‡R[‰ªV¶Øq^ÕîFš¶óNÏ%\„íôø¹ ¿—&aûXé_Ï'6ÿ,q¯Ñs6ŠÚœ ®Li#óœ2ÚVoÍÉdsä[€2Çsð¹Çצû´Ëj §Iœ¹gE­*_¸xßuØÕ @ ÂMº"”èÆ £y"“áLKœ Š5;d÷벊úÁÐ3¦cxZÉÝM.ùðœ  î `vùÁ0"â"Ü;^ä ‹g")o<Šäfäô••ŽçÖˆR'^ªPKÃùѓx°zèuySÛuð‰hG "#B8ÛÏ[iLŸ6;½·a#wö^0pÔlàÝÏ5êO©ZK1±.§pÈFM—cÕ„7æ`äµì!Uе³ r¶ÉH®¨!ÃsjâdžvÜïêtÜD4 ÜôA¶3ˆi~sû¬¹(qtI¤/W«{½«flž¯ìÄ( ±„4wS3¼Œ*£"À®N¦^îÇ=ÒáÝú$¶3`_Z,à]eƒUÂ"Û%?5MUƒ %·’ꑈõUÍÜÁòÄÀ–d¶S$#xx©³9]"¤4¨3ý6š*Á8블ôз7rúä50ØaÀÜ^޵ØhÜ‘–³GJiY‹ØZÌð 4¨ žDœh{h‘t •R%IëC¼Ê³A_³ëñÔdÚ-nÀ#: 7»xf\ëшÈ3BØ€¸BI<ýØóìï÷4a'b'=cÒ3»‡BïdÄ—§œÄö<Ä)¡þg]žÜ»] ºÅb{xêhIFQ_’4+ÄeŒsÍ3Þ0¿þŸÊ7¬å®ßh2\Ú¬]ïuÀQáë`XËbz¸/v5Þ\¶E@tÄôLøõJ¢yK“ì¾rEC¦æf(BRÅãÈš êM‹A4Aw½Õì{ñšû%ži1P†5ELžK±æ8/êcmµQ'5±š%Ò~#À«äšEÏÂò´ê nÔ¿5áfceo¡(x³LŸÞ¨oÚ¨lÄIqK6ÃYS‘­ið½àÇý8ÏÛö$zbêpž/,ÂYDê™wKÅÍ.§DÖF ?C§ŠŽa;Q& >ú¹R/ïV’¡6¦•#>è»`¬RñSÚ= &b qB*?€:t4óð\Ã*y¼êUð|™Ÿ«º(">ð¨®4»áÏüfÀŸä˜x›°.oêvf´&xÎ*c:1öÀäl Ð_žêhrõÙ V‚c$z¼T²wQ$ÕmŽ"»ëü¼ú½yÈ.º#—AÆM Q³¨¡ðº†ZœJ¢¨^¡wS)a¢_1s\j^¢&M½j~øöN(Z­ÕÁŸ ‰x´!âÕ]/7Ç[Sšx¢™ä[o9¾±GÁ‰·*zÇ3È"ØËk­ëeŠ'Ösóô°|žàÒôdòé¼+L“ºQî'@U"É|ª²aDP[݆Šqï]ÕE·è°QüBGW|ó†Ñ¼ÇvtØ cEPÙnxø^õ詘5fkl.O1½†Gœ]‹V¯wà‘§hvUù»j  )k!w±OtøY¬-„Ʊ}ø v˜:ûqÌ‹Î*°I9ƒÁ;[Q‹IáµÏKt evI*WâÛL’ÌÄ|Ç’6ZŠB¢4»„UÙÌÔžD»£#¢©NªýäY‰Àn<¹ÒÀÍ®‘ÍE®0PõZ4n¹w›L¹ò ù)E»ó¾$ujh²x÷8 ½ºžíÃc#»,}m¶I^ýÿIŽñl²”é¶ÖP^TY–¤ù ±S·1véÙ++‡{ê¥^§/k®PÌR“ß"—rxwÈá{Î m-#½Åi5+îk÷°±ƒÂZuU#ä’£ƒ#Ø'­ï¦ë àpÝ0Ü{-]l£´y)þò]­°PÒÕUg–àøÎ»¬Íû‰è!âØÒgSý":ÓâÍ¥ø‘É‹¸¤$ÁØ( T»D ºK’u1;kH×Öb½Ešò}=ÓWéR3Ó½–¾(rŽgøÆ7n•…†æ½vÄŠs&ª÷fX 0KâÝ@í+¥œšGQ H(ÍzSjî&Eí¸ ” 'Ž}µý8‘ Õ0±ÜS¼‚~…”Æ-¹¿à“ôR>Ï1lJ7µÐ:•Ìròq^vx;ÙÀìœ š ¾C8[ÒäðÞAöîpt‰/ùPfAìmïqÜ4Y<Á'áO¿á}‰‰ËDî­²Y,m0†H¢ }€T²¾°¸ÊèsF©i†WŽMQCU¾/ ª-ž<ɼ5Nêî ·²v¸h7¼”ŒÐë×ÇIJ;…Ù%âK#ú ^Ñ8U¹ëγ2" GÂÉ)~h丙i•(Ûþ J©uF6·%Ÿ ÈÍu‘¥>duÐâ†gR=™TÐŽXÃdJT/ŠÉŽw”¹_¾IÕÙíâ·”CšZŸƒ<¯zÇ=QàG øJ^qµè°w{jIT ‡ûf ¾Å„Ä~‹k¿è)–§ÉƒÉâ¡`.Ìèn>yJ;¹@OLmi^ÂÞ{Déx¶d¡ÏÁ ¦&ËYlÄ¥A ¥„L…¦iÌ6PàøáÅ1}Ò£ÏJñÆù ´â½ í[‡>Ü ÷TI¥©3“F§(N+_޼Ôôn‚k„3Õ2A0»äÐÆ6ð|f‰ øðš!טq°dÍ*3Ç ðF¦°ÈlP¥@ªÎÃßR¨Bçy=‹[y/Ó§\"bGe…°»š‹ º/â%²¸žVò;¹%ÈKÏeh™{ªÄ:)çEr¨‰³”¥³pl6>®  ë^Q±Ñ©É ˆÊ-ßÔ‰0Ųû„óWÚ çëwzKMZýʨ_9å•‹¾ à‹s%q÷q¹ÔI?ç^9[½x޾P™ŒÒO¦£xj–qñ” Ì[V¤ž\…Q0é{ýâÄmš„•1 ú5¼ ë¤Gl—/“ W«l°ÝÖ?ññg¹Å˜0w»Îl ·}¯õ¨‰“&{ž£=&:KOKyÚÉùŸáöµŒŒÕJ6ŒËÄC!¹V‰°a¦~ØÁ I·7/«+8w€^`.!tOšŒg/WÛx¬ ­ ª@Mʨzy Ôµ¯‚/:e䫜æ;9°…†jϸ·P/ŸÞèx‹€_f–ÉaÞK~\Û‘Öãt9ܾAˆ¢¢é†6Tò(ÕxEì>gE®¤¥´7~ï.Wú]¥H¥$õ³†|gXcˆónÑ"úåa= aÇ]iι— —õ(Lú~Þ&dGÇEÍŒW•¯é•%àbë“k§÷²¢z¬ƒÔ•¼€ÂØÃhBT%Iê¡ !#eÊJ³­Ê¸X2™Ó¾ê˜òÉO>kFû†i+y@[/•¯ 4=‚ XxÍA…óÂ!«ÙqEwî…^8YÌu€CžÆÕ£ˆÁF¦ÚuÈEzŽúz±ÒNÓÉX-êAf9lñ*’¿Žˆp}˜—|‘Ï@z TÜå\›¶Ä„  É Ñ«ßÑê$n¸Ïa¶É©á² R`>ãzïœz ì]Tg5ÔCU—º1x†ð¸ÐÍó0?yïbÓÆ-,á%Í1©?ÁY@k—Á¬Œè™$*¼ÖIqÔdR¾ç]kB<ÕÊÕj¯­Oa;Þ)Mì…ýè$`A×( ¹öL¬ß`%\Ïa<êp;R1yæ¾Ô*Ah¬M:H7/hÊ7±”ŒÝ^÷oôZël?% è ÝW3®|Ÿõ»p Ë%>.ã‰×ï>² ŽJ{€ÕþÞг7 ¥þ(CûÉÙJ÷»çquÌŒrÑe·jbXÈLŒðˆsAqçôIì+^zQçÎLo°3e 5qšÌ;e©yåHÔž×Ìp˜LY{À¤Wµs·ÑÝc¦àaá07•å( :ƒ{àOò)î¸Oõâ3{>ÞãQýZÂ6^ï( œÊ¥I"o-«]ŠõR {©«qÆœ4lë A×½]Å^=Ðj¿çÊs'âd¦E8çmw]Šü<ªF)'L–ê,l}ÔcÐݾ÷|  TH —|KôYËF°:Eîb'fM;a,ŒZØë"I-TÀz2uì?ç ÁX¥ŠKÏÛ ¬zŠðäbºÎI¢cš ­_( ž‚XE3/eª%W’¹ëRꘜo ¶Å\dDg €“=ÀïþkŸ%$Ü•üaÜ„ðÃó§'º|K¢/´ôyS¯Aǽ5ñL‡ögtï—'sUš†Ö:!T²m/qÃ4W¾Ñ;¨“ª *—#á1aê~‰™ÂjµJS W΀öVH#}8x21tR[õh »´aà*‡ÔåEy?¥ÎÄÊMλÜa}s:>R¸å,{„è^´‡yŽ˜H‡¢µeùÜ3W‚¶Ù°ôq&¦µæà¾P4öÆ=)wÚý.ã^“i€”8L{ÈÃMŠ1þÿ„ŸuD``2ЦPXºqÞ‘°J˜0‰òã8|-¬ na»iDO{õñJš'¯WI«{]'£+Ž¢ÚD¶á(ÖÓÞ¤A}2ôï:’YúLt,Uc5+Ã}Œ[%Šf]P0£­ïTÂNQtnæyGš: *Ù¤M"NðB䌔zê‚cÏ{Ð\·Öóœê˜RÜ'O êYª87'ç;Ú…Ãe6²x )YxevÓÉQr`•®õÿ³®b¯øú=iWg9xº)üÀ´ª_Ï éâ{­µObÂWœqŽû ÷ìZ&äc–Ç»Ýêw/÷¤@£cݱuc“A_"´““‘ûÙž¸„'9ëq G¨¿R§æ}Å%øòª‘œ:˜*jöe¯a~At2yéÞ2ŒA/ÔžÌv t4È<­šÈ{ { ÏuûvCq6$j§ x˜^¿j xàÇ ï©¢=¦yê]×®ùûþŸÅ„­ü¡fÂUɨ…ê½õ×h –ùFéÙ†^ÓÒ¬‘zíZDpb øk{²ãÃø@º¤zNšÏì² 'YS*êu5Çæœ¹V;fÈ%ÚœÑ)¨`ä&ÜYŒ$"?«ð];¤”P²}.ŒÄNo3²öõ`uUݳ6îç"Î=D”5ž=Ä t¯ÁÅ ›H|M€ô¶ŸƒEMNöä»ñ2ÿ¹šŸ;?®t‘4mc‡RÐó£·Áj•åUtí7Bµ•à ÷)‹¾'·mPYvÓÊ/ž”VÀÑJmE¼÷d3¾;²ÃgEñ¾ÃS»j÷Ð $%wGGíÎ"v}Uj©¢Kî¡G½z7 àŒ‚ÃØ»,3×Ì~“T*`GÔI¢üìgwîMfÛ[=/Ðl~`úÈLINnÀÔŽó¼Ë­RYÜro ¨1¯Â†>@ÈMqžþtt`$Ø•eãÜ©øMOÞõ´îNjÜu^‚—›ïçm0„­ÚÀùzÆ<ħ )áIŽËoP½ ×Ó0[?‰å} ¼BRf¡59+ª·"à⊾ú´8áò<¤º7Q€“cAnDñÙæÒày å•°oçdM"<@ÄÛBnFâð$…WáÈ÷ºµf¯1=yéïYÂ<õn@U󹊇?ïËÉb¹ÆçÑüªæÕ¼­»«1< ½³2mΛ¹«‘wôVÜ3„©w &#i‘ c³ë]ªg3ÚŽVY*„¿B-Ùâ;ú$IŸU†Ü¤â1ôÑBzI´Š Ã=MìCwÝ×ͽðéÍ †7š&,T JòœÜIŽóe¨Ót¼¼ r2 |„h@•zœÓŽzÛUpÑÌZæR',ÔWÜÍ˨Ҷ ÂzÙo6kQf߯\å¡ñëÙ"‘hsGÂT Z rQU$Óvì QŸÄÈÔxRlwc–Lm kâM6O8 îàjeÏ·‚¬z8.Õ‹#ŒlÚ1²FB¦`AÜøÎif²<„˜³Ö±Þ\¬ø˜ŽKN8‚é ñ§µÀÃ$Š"! ²\\勨9oKÖª`0. ~Þ]°¼ÇBSý¹.Àtà]¤ž“1ó ]ŸÇF@¹Ÿ-ñ¬½D ¹,ç3Ÿ¤³¼öðжžW¬ã¥X V§ÛO”ü}waëÆ”¸½ÊàŒ6©tÕ&˜–Æ.h8ß Å gç‘Ád8Eç¼Zšì8Sx>عÝW§­½¯¸!^Òñ¼½•$J;›]™+Ç„˜a¹ êɆbªûNgØ›NÌ/ð€ G6 î [äÓÓÒc¾™EIˆ†Q¶æƒ1süÈÂóÌm«E(Þõ^+Àø°jÅZZºÔ]t clÔ¸ñÌB8¢ÀLžÝV&“ñÛKÑçCè@ˆûNT„Trx¬¬4ðZ¾÷Öf·-Z²QÇÅÞö€.v·õŽ‘^»Ú ÇöÖjƒ¿õü¹¾•d,‹Þro´kC=†Ó§m6Îç›ubXé7ûXÔ€ OÕ.ðÍNU×Þ=tHÆHõ¶²€J]Ux#ˆòÍò³Þˆå…áuçv“L¿íØ~Q½ÓZÊf/6QÝÅS—#Áp ô8%•¥y½ÍXGEõúëm/×í<šÙaT+:€íºlÍ]²ç X´r‡P|±ã5P>L@íD&RÔI¹3%\í£JÉKæIe Z‹gŒùCp=©²Y“’†J.~4^å€k€1Í·™#Qmˆ… xˆ6II”âÊáµQ¿2ñ­5,ô[â·4äþl”n ‡¯è¹0×+Ú§à˜~Þ£ó ü|­lòeáŽ%cá>—÷ú×hÚ­Zhð{½N‘1¬àô æÌ@ËÃ…9•Ê}Œ`oìô´;í”õñv¼²:¯F=Pxk²ËêyŒG{'½$@Ž\4°©; Ù{œ•2Wgý¦èg®äEÆ÷,àU潡G X3Ê'F—‰Uö½oQ '×M&¡a”Z¢iš[Ó±æ5ë£, G'¬7ùÒ+ùuèò¸r6ó"è"®q›5¾À:™ ¡X Q«ÓDìÓ WU9DçÁZ'ŽÜ :.¨Dƒ)H‚EAQ7üÊÅû¡?k¿9ˆÂS™6O$)éä¹JpÀꜹD}Ô^ʶÙWÌÌå’Ìgä 6 #`Éç¤âæ®§{<[âÞ`¢#ûŽc0-Çhá h¨ä ûô½B7o $ZNg_’x›Ž­W÷³ƒ;7(<¾QÀNî=WË3‹ˆ`ZBêD£ç&ÚLón ûÂßPZf¡ôó£ñ¦Ø¯N/hGOu-œ?%ºú^åÊŸ«¼¥Éywážûö>ëÞ‘—€ „Ï ,ÀȼZW[6VÛHìQvÕˆfs¸p½a¶7DÇPUîþBô±4©N“øC Ͱäűe\áÙe‰ü^ÈåÍkNWäAȰŒ¹;ë ÖK–§J3óbÊ/–xJa2é©óØÛ|üt{ëRŕڽhô®Ì—§;\Ç?ÊF @åÛËèJkSë” xÜYÆì'°E¼‘AéÏØ°WÂH"Ú]g³¸+yÓÝ}(Aüäλ|p𱄹)ƒÛhe?1xZ°—ë½-÷^é=l‰ìÅl#דr'ëÔÄWzu"Ä3 { æ5Á×)x:'É"yÐr£Yœ½‰@IdÐ$Ì.iÎzå|”mý¸¤ÞÕ½g¯Wð!Q•-6¯ˆÕ .óQ[O…FFìs.t>D.PO¼€˜¨>µñ…ØKÓg™ /kýh©ØˆÑŽtxž€ j™˜ËÓŽ ÎgonY`@'ýô2DÝ"!Eú6bߦˆl²Y%ms÷x“ ?Rļx+B,ÓÅ,ê ÆVr´ápTÜÒ¡h\>^é¤%züø½ôrÚVMÀ¦Gx7G -?‘*ÐYAˆŠ3B‰qòtl²“…² ­ì¥`’¾$Xo¥×"¨/‰«Dè-C°gFâRº¹6ð{¹MÛDÞv\bjñX^}! ø¾ ùÀÝ,¥.ï©(ø¦Ú[v‚ÆLcèÖ}~Œ}´ÂrTÑ–#»Uû Pù»vž‹ôk£o\^¢ÀIß7Jº(7Î!”+ý±rz,ó&³£àT)W3‹E0N(0…ÑÀ†-€xRs$—$BóÀü‚ƒF•f ÏÉ5:ŸU xÙ®ãâóFC¦ì[çzpû@m·KØ8eXúfãxh/Þè€H„ÇÃàñô‡>¥ã(Ÿâ<€1d£1v?âgŒZê¡dÃ"÷Á°³«]%Ë=·qBËÊ󤊓AYêÐT×fåg—G@×x#-R™â‹käL‚0¬d=ôÿÉ WÁ4ix aB¹G‚ÖÃÐ%ÛÒc=GÀH@ùYkûÙå\BË4õeÊÄãO¦ø>ó¨ùË*{)µDñL¬ÞвÔê>ˆ=àמÂt;ºÕ ’vHT0ãÕÄ.¤;¹oñm£¯;Ùœ%µÛ6ëôcœ]p#®&ò¦Ôn ³$X’šzRì«w23;g‚‡³§øæ-#L&%t° ^$Sž* ¹ yÊ‹<Ï\dtðöj+…Î~ZÎÙèLºgü´…mƒÓ ü³ëš“üÉæŸ<ÈÔ{W^'¨²ƒÏH¯ —49ÒH‘b3iÛ‰A£°I _Q–»4¼V†Š3uÝ‘‹gû?ÆBo¹Ÿh¡k¿§¨q÷ÄBxkÒ±aåâçýh©aó®IÔjìuÃC49z3+4ûT^ !mцzÎÌé‹IÀ ÈØ',˜öâÌì2‹Þêò!_èȬ­ïÔóþ†ú>‹“\¯#D’¸,C8-¢ó £Uîs¸'ÞWÈLn2°LØ…Q™jϨZÇ^V‡QPUJJlb%$#wqYb6婟ÀXt´òšÀÙÀ»Lñºü™S«ÇÖš$n&(EÇâ®ß±bò-3e{Ç¿¹Ê{ffè³`ü8õÑÝ0¥¦ 3s¤u6µ?\r(èr´WÁAß9•ôs®ªúöDÌÕ>”fD§ðìèØ/SåD^YSQ(Ÿ1²ÄªîX[®8wÜìÑŽ×LèÄžHǼõ QûZuì&8„›„Þ^v¾þ`ToàµÞNRš£=uq÷ß9–øqA€ÆÕ¼ËpÌ»]‚*GÔ6Í ¨Óìmç¦b!õŒ­²ëM•P9y‚œ/%tuA lZs×ÎDëÝ÷É7Zÿœ³¡Álƒ&p/3ª@§öÞª wÈù(„@ÝzC­Ï>á~Zo+–g£Õ;rŽcy7 û¹@¨Ý‹“7rv*F« ­—¢íÙ©ôJäDKd6âY±t¨–ÉáDÞñJ(ƒ’yïf¦=MJç&:²žZ}Zb,  Êéé#ºB™‡ðæÑLÌAÒÍY*¹@¤šb]ò»ô™_T”è /!SŒ¦ƒC(dî}Ùb'c/ì¢#8–ïÔË`ˆâܰ×E ÌÞÑkôœ×û =d¼À/q7ÇšL‹Á €ZJàÜÖh™Î׈ýÜšœ^ ÛÞ«Z±ˆ¬>Y<²·éèôgž]ƒ¸"¼tô[ƒ&•)–î{[ž~©:%÷GºÃÞËÙPêPÉ‘Ó «Ô·Óo<œœiáH-&:¬z„ï1ÄLʱñ'[û¬_öPY”(™óµyaÀãÍ퓬Gý œ¨ŸºÉ4Œ@±æf41¿M)Zm–V”ÉÍMe{šp &¦ÓC¡ãø èJE°•Ü\t@ V“GĬüex^yô®KpÇ4ÆZÜÞù»¾Ág‡å@ÉÁzœÉd¾¸ºÀXH)´Ä=ô&æcAWÖ”À¤o>ABTnÊÒêš'ØÌ>o¸À-[,%ú=—åCäYÛ ‰‡¬w{t4EàWÄoN¶$'û½6%dÌgîÈíot”ØÅLXÜ —Ò©ídÃK†[´ð³=ˆ%’t•|¹õpùŒýÊSð˜M`RúÕ/¸RqЬÏ.s6ýù“I¢4i™ÔnÔˆ§³ ¢idË“ –u8MS`À'£v]Í]ú2›ùmo»Z¾FuÖÚÒåö²?áúgÓr…¡°'‰\^eÈb\ß ˆ›~D¤ ˜ðViû1=!€ñG¥®\e€cm‰çÛ1K✩3ú61Âzœ°¸²&’'‚ÞðÞ¤±´â2xÀ¢hî*"êä…˜ò{/ÑmêíÝ&ÇÈ€„"¼QŒš§©¨U7éD" WPÜè0˜H*PÈUýâBùY@ñŠ\tܾšyA2¸«Œ‘•%,æSwvÜÄûÁ­Iì2öÁz­·¼Q¢¯žû@>èË>ä„™\i`C]IMާ@6FXvqï=§+/%ó ä– fÔgiïõówÇòöIÚ¦‚Fï2%Ø“A ¥â§Î÷D8t<Ñû…"² !^ƒ¾+óU0#âsÛL7ª]Ï ÑðÝzH&[¯xO¨‘ðÍ‹:…¯ÌDZ_Øz‡*í#".ÖÀwṈ×çý*õ€éÉa>[ÐWúR|ÀT¯uŠçµ&Æs.@“q{ƒZà[ Œ¦ˆnÝæ"Oû%¹Ñm6¥ò«¢8!AÈ 3hzžg?ç.ø ¦CçÏÄŸ½Ú«ŠG|H ‘`Á¬,!Q˜š÷ŽI)kŒ=}4™¾*ívÄAÑÈ à!p5Uë4ª Ì'ü(?ð>€ÏrVԲƥDý„A[”Š;<ò{¥«&ëê¸ÄIl.59+¡ò†ÓhRÚ¥†…opãnr°ÉQN€|cée¶45ß:C7ô¹ŠC* šyÕNž ¦`‰æÛR§à̱O'#'5ßQT\ÞÙU²˜zT4¦˜ÕK\¹9“¶„T.œs,JÀ:˜ã…—x-q*Ø1â²­ïqÕ³h­­|¡ºîþFLÁ±ÂÕ×r÷¶rý‰…ôtbñAdX´ÏõÃdO¡žª§ÍSÂv º·ïÂvæ©K²*vq ª —ÒÞ“rÈС¹Ó,0ñˆÈœ‡<`5|H”jÄ7Ë,·llˆ¥‘ágû~òÍÇ3šDtϣѤ‡·Ñe2tÉû¹%QLóìåa½Mz©§¹·&¾O®ý€iô°Þ.`,R¹iíe¾Œ’¾ÎesÿæûYÓœòˆŸEw ÜÖ6X:†À—ê±³?ÍÛ5=Ã\¬j1(é¶m½ ˆF«“Ú›±ÖJÝPï{èùЏFúâY–³.y2T£Il,9jšÈiÄɨ€•lνx·{e$lë JjМø¬.aQ»FçÉã,Ü$#âLU&Y »†•fÄ­ê¥×¡Øt¬×ámûklŽj¬mö5Ù~©­G;´RÆ8HL!Ö¢²ãù ¼°ú]òõ?ŽÓ»â ùò„¼^`º-QÀ&;§ ]yû¡ô‚èÊÊùm­,^IŒC8d‚vzB?81|Å=+ô6^–ÇA.þ܃;rwzIÃBnOJë¾íhÝÊ&#wAÜa“Y|´£{ªï=`–[~b-¨šÏìí™z l¼€+6ÅíÔþŒŸ…-mÇÙ8º[´ ç*ÅcžÅ0¾ò WwG8PË#ŽuãØØ4ÖT( 㧤ÍÊ׸ûˆ²[^c8²Æ+e‚ع¹‡Yo›Ö'Áxèp¡ ž˜èAén­GjºßA"\ö>µº«kZ‚€¶›HÅ#¥“Mw\{Ìçp'âðFö,1y­<®/uNx°@tWÉVC¹bánPJ1´flê´h±=Av!öåp¤â­ØÁ÷°h“%G3^Ì)Ž4­ÙâM“h)¹S*ltU\Óô;zSÃ*áN§­fo‰ä­šèPqô4œŸ¼]|«¯²å.tT«Ô¾GãsÜÀ‰€yq£ ¿«[_&laÇÁk`Ý+ÂÄêÄdS9óm4ìC™´‘|ŽV^gc=VȨE³¯*Av® 8ˆC²‚%—ºŽÌøhcq&}~üIXo ¦¯'1éÅúËXz%'°õ¤Ý¨e¸B:InïêSÎ$M6~ï5—å À$*8ÁNy˜6¯À½~t …rÓãreÐÍ„­ä‹ù¤;ÇÖ ÊΣ®NâàÜöRd5?‘"W¿f™q\¶-|Y ÷2ÛHædps"¬÷šÇIË…{7²á¹Ú-ŒsÞYÍ÷{ ­¯Ù˜È‚ÜÍÚ¨Üê ë-È&’ÕÎ5h> }Æ‘0"<égcïQ²waÙlgâV{!‹)-©ª7–¡4öDlÍÔ#/Pàp—íœ ¶~L:wôÚ 8ÉÅ-™Ó_ËÐ Yuæ³Um¿Ó_ˆ_­áÿ—Ù7Õ7L£ì1ÿÿ˜ö|}(†—8DF±ÿÿóG ja ÜDtR‡n«|8î¸Oí‰Ú=àYX£Þ§k0Ÿˆé} T»2à¦LŒ+" ¡0‰faLy3¹‘ãÊà¥A$᱊Œ\ý ‹ð=X’ǸwÒ!ïX\¥„©qûê-3®¨"BéCÂÞîóÐj_AsY1s߉˶?Âì×¶f5h_Ü x@ÈdÉá ¯Üÿnø÷’œMk'Gë쬨Ojò„øýÁÐ"²wÐÀN‡!¾}e%=8”,kÊëÅ zÀÂn`Ä» ‚÷„Óý„H°…u•ùñD¿1æ£wo%ièð EXŠŸZ‡½'ÌíerÞ°y½Kæ«ð1ϧýú™rÖn¶µh4.¿|B+eýøÜ `vÁ$±¹]úEÖt+ÊÅÞiß*«pn¯ÜƒÅíÖ)¢œˆUTÐÝ¡B8Wǹ^R¬Õº®-ÖËk0¤fDA=òè±×´q–õ€ìxEŠâÆ/÷a¤7Éx»H²“çtW•‡:w±”îJà€ªMwZù,ªí®é3Æüùœ{ùÒ1š}o–rùê=K«ù_Ù@£y¢{)òõ¥×¥Zô«™Ìs- §æx9U×Âùzž¿çôž&&¡@¢<ñ{O^.ú©j›Ø‘ætlŠÕî›Õ·ùä çÄ]úòsRÑò 1‡N™Çª>4è=c ÏĪãM¨JöS.:™Óª…ìÅ =!ÄÚH6â†Í‡Èè2s€ÄšÐɯ àWúbú&Ij_úqìÒÛy —ÙbÚï —DÕpíšäq ¿8£eâÙgzÜ¢ÒNl&öL'¥¬yË\Ðh¹ƒ5Ðâ]Ý{æòÌÇbšTOSjµ –3h{·rëÿæâþýïÿ Çüë?ó¿ÉÿIÆ¿ÿ¿pÛES%¯û9Ù(*°˜‚¸¼{åït¯Ú} S7ûRuôuán†;W<„×W»7”꺀—œâëùôE§'î»È[zRÞíöšÞ´Rùjä%IV ¦ø„q û“!YM~.E•s£s™ý$Röª¬º¹$FžÏE? Eh¯Æ®Ã„z)H°‰Ö“Ö—c*'Jç©wwzXOœ,·sª¥8rfÍ^îÚî±uÁu†©ÕâMj0Æ\ÙÆØc/ ÕÀ¬Ü‡z4{âò¼|è›=ÚÔW@Å—pìöžÂ’3y ÷®wÃpQ†¢ûÀ#5iÏvx¯-ïPÞ«àöÇ9U­ˆR9¬AãŠq=çiMÊ@‘.ePþŽðè¸Þ´ÄÛ|¹[Š/í°pö½p< z GËBºÓú°BüXyÜãV ܤ>õm µkç=ʼ#õ…BÈ»V'(¡—o ŸÍí‚Ö­Q=$6Âá$mà•—&û`í¥e4gȶÈpÈÆ Î@ÉÆøkYïux™¿ªð”¼(Ÿ¾#{=·%ö.ÇöˆymÓšÁîͺ®æ;kí^2™¬Õ%äw˜‡>i{3ÍmeP²e*^w<­ÍG»ëy>÷ÖŒ;€^|E(o‡@Šù-c±¤Ê;Jiæ ÆœfAšI •Ê0“¥6ŒJ|v€¿Ú$Ïp§M¬âûÅ׋õPλ§RÎÕªZ[¯Hx¯C£e‹cÕ©²rèy>¼!_F+^Âå2)•µyQRLc/@u­õIÈä‘öKM:À]}ÚÖE©­Q¸m9 ïˆý½ÍR$ñG&h¥ÎAÞÆÌÏá'ß(¤n0Àä³T弚™YÀMºwj¢vÖQg™ò$à(:¸‹‰tÍZ}Q–M¥6ê)sñàÆÛI½‚çðÌi¤*æØÈ!bÝKdœ íœ C¬‰úÃ|̯ɳ˴$§^ÝéŒJt&G÷ã3Rw8ŠWó®ñåš(ïmóÄ¨è‚Æð\.CãhiOŽÇ,ª”ñmÕ+5*±¼·í2IÇØk F=° „j~-ºYú8Ÿ—?Óä÷Æ9ø¥½<ƒ7OW?¢2Ñ]R¼;ú+Ï­C MÍÇr´¹# Õ¶@žH®9bFîÇÅs±–[H÷jzÏÚal“©”(è˜õ:@—> >Å(›}¸@ÊeÊÞâOò@$.¹MCFgâ¬Hž%©läYR‡ëy)¬MëÖkIݽҫ’ºYÂ[ƾ©- ‚Ê2½ˆðJ\!GIb-pÞ˵П T)­lkÝ {Ž¢ÎæfqŒXÙÞvðpQ€Ä¼&¨tÉ#YiÚÖcw˜¶¨¹ëŽÍIüK’î¿$èP¡ªPÐ|²ìÈK&nøðäÝfÅ­?ÏÞr||½Äí|Ô»ü’ÙtÝå]gÙäíY)lßÖÁ\Ÿ¸ÕË{âI®·ÏðÕ±=Iç0©RÙ'®í¸i¨uJ:ö’CR€ŸÛ(ùÆJÌ Õ‹VoïÍQ•,~§CJ’úÀçJL7ʘ‰•ˆµuŒC!1Ò4ß%ŽŒe²Ñ´m¼šcSp¶==IðÞ+SëÜÒ¦çt|o`9f™É{˜ôI> ÄtºƒŠ6IJö<£,Ü”£ÓÓdÙWN9s¨…žÆgñ¢ P¶?~‰ Á(|Óº(Û¶U¸3´UXo*Û¸{_DvG™êqpÑY¶X9Œ< ¦YšºLÅž{Çn™Š4;ˆLè"9(wY¬”¢çöªòøÖÅ’­´A‚} =<„^42ÅŽ›ðî ‡\iÇÀlÉC%5jÍÜòV|hÅ(:L„½Ú×Ör/ÈhÜšÆÏý°¼^ƒtÆÒ“ ¶sОœ4TíÆ ›”Uy:|‡ˆu£e”6nüèú˜æ6«ÀarZ ÊS"À´3DÔ:Õ÷òÀǸüxÊ´u?”Ї #Àò†yï$:Z…Ž3ˆkã5Tˆo’kArI˜G$yG0F“ªgZA_gsÏ)9qÖ½]‹Û“·µ¯ŸÎùÃI¾¿ž3þý%ui2«F–˜?¶ëN(12Ié}‘3ÉãfN oFn†ÌŸô¹?xºò´×ôöÔ#e­FYÓ®lŒ0^Ñ XE6‰²-› ”|þÈÅ ÷p-wÌQ}#t,ÛŒ‡íü½Þ¤Õ  >¬|’ëXbWÖu·ˆ¼tܯ…ÊÝø*@וœA‰¨êB€–uÜÝù½|¾N Ü™] €ADÃï­­‰×0fÖ ©ó§ˆ7ÐïìFÐÞE'æ¨H¢fÀwDúŠq³y`'Q]8¯258=Ö(([B%¶)*»Ó‡I8i»åü@ÉŠÏ(´€œW` …XYÈ MBÔ Ã0îëaßûìVn \·žg±*‚Ëž ¬=L9Ä‹©3~ÏôÚ8ßÓ:¦+1óh¤ZÙ·šîw©Ù.×ýÖ@ ·Šv¹ª®×°^º/°òféà¶±m¬ºÞ‡BUݨ™ jyûæUн,¸ÞãåXªjôBÜÎ`jO0Ó>ŠWvåk ^R$ã¬rÝÖP¨¹  *Cr™ôÜ!CQ©vAD‚œ<±Ž‘µ‹Ã1/'ïz×Ö#þ(ß,׆kM¡ŸX…ôãæ7ô–ºEHŠóéËPŒ±eê§Û,q—+ZІ¶÷4¯ãj%Ò†Þð“¢½çIK”%síUnl¥[‡–úNŸº…´&êì‚<%&úÀä{çfÎ&%[á¶Öumƒ yCP°ŽÎÝ«×]Bðˆ®úÉ,Ã#>Äjg‹ó `&H!'ý\„G…ŸÖcSpñ‡$©5Œ¦#ºSeèyáÛðD­ªØç‰ŒÅW©Þ˜FopÄ<‹+oàIÍë+^\`ÖgþK¼åAL•,‚?i‰À!S¤µuM'^,R¡ãNeKÒF©:IT]tóºO®š\IÊCk·˞x’†ß8½[ˆ¼â£çúpÉÌ„Ž`Ÿ·]£¾ç˜€ 85ë=2ÒwýÉ›=mE(PØÆã{»Myc×#ºÑô$3ëƒïlè,ú"Ül„—Ô¼Aúb¼6ÆðA‡>Ä-N§nòTjÀ}ÍÂ$8n—@Î ŠnÀ}ôº[I”¼% ÚËywÕŸáâð>$.}bÅgmËS0ÐÐXFlnÒ¥ê² jéYÞWÏßäf’ wFk4X^Å]C$¼E•1By9_óÉ÷nððq¶Ø_¤ø¸i«¥t£¤0o9n¼ÒkÃwƒ-2fNÀ[šgàš÷néx†¨-s„·¢c_`¤µHVv¿vœAs÷Cƒ÷FAa©¢ï†-ŒC[,Àæ¦Uzî½Ê¼4àÐ'iðäMPЦÄöAfE ÄPè]/èÀð7(>…¢®Ž³ðdEËus弌×å¨54ˆØ¤ªf.ÀªÈt‘ÝA t©y¾ÝÌ0fBغÍAzKŒéÍÑA9iQ†>ap°.$©p·ÆkWvضBº„ší4±²Ìm€àµ”-|eìú)Œ\¾a^)“ôŽí*|Ü‹S‹¯cR鑦äp-öšäÓ¨r‚“›ŒxøðP­ãYd„Ƙ#û­5KÕÝúË'ŒÁ.qt0“ØAGí;7ï,cü}`€ˆˆ™æÇŻʒu¥‚ÞtÉ·ÛÛy‹Íɺ…ÈØ»/8ŒŒtàÑ‹í[¿™æo'‘÷ÎãVü¤Gr«aZ+Fîí€ (‰º†Ì4î+–È1€S¾ôXéÞß…zn%Wf®5iÔõ–rf½`´øéâKÔ›¯M*«c×^&»A«áH­5RG½¼n(@mñÂeê6PYìëmܶÜ:Ö“ù%†zL¹»^s^v CM“ÐéCÁ›€©J;çŽmÛÕ r¦+Lá!WȘ1§÷Äš¤‘Qø~8¤ëòdl$¼è™-„Ñ•YZHq)2Àa_§ð:Ó3z‚ç[ï*…IÉ5²Êd“µ®áT’–CÔú: úéè+ê¶—cˆ… Í㬂Ó+V¡Êôúº¢Nj Fô¤Ó:^ÌñN]·"#¾öçð éÝÛ½^j‡H˸lƒ¨†(9ÓG£%±SYcÐ…Í>PýB1 _·¿Ý½¿X 3{’.oÜèέ9$obÎ]³ù=·9bég©àÙv¼°(ŽˆjD¹‹¡ h¼+ùâi$½–¹+ŽÀb+wÀYÃÚ M3Šˆóõ¾çŽº+áÐ ¤2WE…Ï ßöÃà wbª†b¯¼ˆ°ÜqØ’s‰a*¤©ó›Íeën:Ÿ·uº>áyµtìøN½ôª¹Ñ;ÊSÄÆmŒ9™ž)#<y^4¶ 7,%Pc ‚°Ãü §^™©Ïys /òÀ$Ä{xˆÏ„æÂC—×v¯ yƒ¥Y³³¾ì Ý>ã€38Ô Æ®ËYÃg³í;D³2Œ·,ºÝLµW ª6z/²v¥+Ÿp½—þ¨±ÑÈahj W¶oû™#Ì=orñr…Þj'Þ­Jµ¹ƒ˜ùJ y¼=2%·c¤™ÝALyºÛK÷E„â\ZWŒÏú88ì– Tgg«‘¯Ï²S?#–˜®v8%µg6aކÏ(A^ÑÈ#ˆ¦EBí~™CÑFÏG ™Æ0ƒzwÙØ´)Ù/§Ô_Ó3²^3º^ª©>slĸâ'¤å›y8G¸âBD¶•«xIm;­¤p¦Y˜Wž£CO@Ø{°GÑ›áv–=—@žö î;ÄM”(ºw—[Šn¼ŽŠJÃdO:æ‰Z^² Ž—jš°¢üÅ '±³ é_°à„.°p-<¸Ú2Ó^é ª¹r²_‘²v±Úë冰‡¼´8|Ѳ;ÆDD¦øJO^ÇŸ¸ˆ4¤S É$Le*‚ΆˆE-£ûÓ×6¶ïÞ^3äÝS p õ"rFpŠžé•v(SNÉ;Ô»Ã~C¡È­ÕÜ!mù­ßJh»¶¿lœ¨Ôp¶ÓUîT~{o Z.‚9U¡EâŽl8%3\©ïJ­Øa€ÛžÖ9 ¤­Ð‹–¡V7wßò ŠJÙ3xx·”¢Õ¼~ËAઠÃp>•S€®Sò&WÏ»¼P*Q2LniN 69ÄÁwov NlW„+2Ù !æuS¶øD‹¨¼bª“î׎üØY«„KÉÌ68µh2§{ê­ËÍÖÀk¤k¥¹›žè567­ˆ[†âp”w­Ä!¾Øæ"l ‰âô$NCiÇàúœ®{æâêòè]â­ÎOÕó@Û~L"üD,+C‡áÁkÇ×–n¯iØ%ÂÓE§Äˆ¢ÜYšœK]fEÍÚ4˜l ï\Äø‰Û3ž8È2À§y»8¸s¡4˜SðôÈ9"gý¹®ùПŸpºìÁ˜¡ ¤Œ  ò‹íË¢d×Kì3[{fµ®;,§Íá,‹!@ÝõúªùHL'æA¼ó˜&ˆ]õC¶>´Ú’•e„çžÐÛ¬üòU—Ê£{SÀQÆËÛ2Å(â !ÏœÂR¡i¯ Ô¸Ù»?—bÛŒyB¹‘‚²ø¢Æ4¬ÊA”ÖC#P~_¸ø'.¹;Òs7³½,rø/q~hÆW›¾m0 ŠçÓò¶†àÆ^ݯÖÁ³â«ÛCC³ÃÚÀ¸¦b¨>e¨•ÃÀQ1ªk8ÙüéÃøÖ3¬š¸†Š/YH‚ÏŸ¶z†ó䦖¢Gôs }›z`ž‘ï@t E‚ö1¦…O³6`xËK |eg¢Ð©iðRÓµÐ{ÔrJ^⣜…J!ê '}\O©AŸx@ß ôÊl® p´ä=Û©”‡W¤[‚ è£ú®æÙ]ñµ¤ñÁ7í-é¢ ì½\£Ø;ïç™èÉXa‹˜–ÍBÌ2¶­hå Œò Ô¶žÃø#ˆ©ÆB/F2Ú®= 6ÚPW=誋ðHóqy%`FËÁud×05ƒ®PË3GÇrlsKßëË×{²'ÔXI-ëXäñyäSjÄ󮇇@:oD8Ï`¶Zn^Ø;‘# t½5(ã|1ûï-_>(©‚ z¯òUà¹;JeÇÃ%¡°¦{è0¹\NÌÅOœ)éì]N#nŠZ3†©‹M 8Þ–šÄ8„9Š‚’Þ' Ñ.hÒ¼ÛµN"x[Îeh‰é$I¡2ÔØØ ¤âÛ2Äì¡xB˜ýÐ/9Õèàs%äŸó$^,YŠ@n“K{ѹV_Ã$„"W•>¹ÉÜ7 ¸3·àÏB"Õ82M¯ç¥A˜ª*}ðúÅ‹Ôòë€#  å[ß¡y³öqO.êI/j#µ8†¼&Šl ¢¸y¾Y›zmÆdó „¦…îøIù=®CÞä …6Oðc57²šâ–Àak˜—˜Õ¹›M–­O½ˆ_Âa¼’„[PÅ×d(N±j´¹  «'¤Ä†ö0w|°ˆúPµí.q(é]‹ùQ7ûy˜óØ=ŸA$ôÇ37™ÄDIv3‰¬’¢-ˆi”æ !z $`/¸1ÞŽˆ»‚Ía¤²ÐñJ{À­²¿)aŒ^Ikk ýtÞ4ÇË—êL÷‚!zÑ•ˆòÊq ˜Á±YºÏ Ö…¦(© >‘@Lk,ÔãõmÞölQA4õðJ’ÇïVº-›”šU)Ûám#8¥P‚<8h燧¾gÍms BäûôyY’NOÜ¿‡g\{/DG›ã:X§Ã6ž¤i½¢âÙžTÄ—1¨ò\Š|ö dJähPýF/OÍ[wÞ“|¯eRKL®ûJùŽöª¥úH@—îÍ·BRem;1 ¿6‹|&ï¬ú" 4ˆLl¯ã¿„4i…·wç”ýhiÀÊ(¥MÚ°ôáÜÔ½3æ}$0´UÛ4óªäª^F<8J© ïÞ>Ø|åpÔþûÁöš†ŽZ°¼Dô-kBŠ%PóÚ›|H®²(Í$8oJ5§o¯ÕzÏ€pÅà¦ë\©JʱXq¿€Aà/aÒXÉ‘#Ñ=Ç~źü÷Sä#{¸ÖåRÌ 7ïqlãÈ=#˸Ž6|´§Ï, æ©™ B*Í…æÞ“Jt¯ˆ€ï[­šLœd‹’‚Àv/•v8^d1·Ý¹F“FÏ™vº¨òWÚ·ñH8ŸêÚåô®WѨù> ò‘8:HamcÿEˆOÈFª§‹ ò)©«Ôô6ò³#¥Ñ!¢Á®t1 g+“‘fᨙé|ÔÏÔËÀ"ÓnFγ¶‚$¸…a˜j*K> ôzVÙ…‰íèlGrgÖ(gMt’C©i1*Âs1)&OŸE²äÜin·ÃIJ8 Ã,ô«Ë9Î'“J;üÄʽYˆÌFß½W Ǥ¥y‚¯±øU~ƒôeÌkqÃÅhÔW°%©$)36ù|ÝuÎYW¼ŽÐ@ÃŽ'$ç»ûÀÞtG^ûkv~éhoOžqóˆrÍë0æé΀­ìò;ji|ŒªEYAðú:C“A.ß+LÂùæAR·Ú³x2å ÁútTb<e{8„¨ÆåáËa讵+„ˆ:¾>Fq´zÔô sL¹ÜW/‰3Ü´ÇK¯ kº{F,J ùø^¡Úéá@Ĩ”[ÜzYð3ÒSvox¢áÒÍ>ALœÌ …¼å„VÒ&ã¾À{­rj"Ù·{ø<ž–ã@Sšz‚î*Ч-‰bÏÄQ‰$ÆrH¦’8 +ë4д^ð-À4ì¤$LÊk0Áô@€)ßãíçê'ãËnrÔ|CÔ‚Ûwû “a‹ï.RñQó=«|%´HZÅçé eVqøJÆCÎr®‘3agÞú$׊½\‘÷VbAª}œ\áõÎÌÍUŒ“€"ãâÜõ¨0¼ ×’HíB¢"FDš‰qÕCÊ9*€0†C}ÐO uA‰ÚÀýáy §L.rea§9î]^ ©cÚõ£3šáO½Ç5áitGK&¯ ±Œ°ICsìQ¶Y!M²Ñ‘ð H$öX½HŽTr2ÃIb,´ñ`ä¨_j«çœc-ŽÓÃ)m,ÏèÎKÝðúR†àK™K"7®nPw‹õ=ÄÔ80¢¿œy —Cå8ÊÛ¯@rÈžê)‡Ë³˜“j{£éÏXšri£+íBìUaSúŽ%ÅÀD¼ª>‘tu‰íZ‡öÎR¨,nÐ7›D¼N²Ï• ‰7 ä‘-˜”â€/Ç4:·`0UqZXñq·²£ÖâÕq¸àƒ”õ;P{ÝÞœ/ GâÕÖ¡2Æ+o×»6oT(Š3‘”Ë´Œ§Râ½v¬’ Í^f¨ [Dvò žÛ*±/Ú.’ïZΛàªHÂxUÊžW/_DêöÈÅ2æ!àJêBà1ß/¡gÝœ'·}꯰m†”yŒÅ›ånôÉn¹´Åcã±kôd¬Ù:œ•›7ñFžÙ·54ƒ¶gžÀ‰U–úµöK2.­~òVGa’aýià‹bŸÜЩDšÎ‡ÄÆ|^$tC\GµÊð¤'uBFW 6]}ËãÕ³ KB¶šlCÖŽÃpÇuAHYôb,Íc¼g„%ËÙN³êŽëôVöûsÇ÷W) k[à¥n*Ü+´¸èTšÌJîËYÙ' ¬ï’ûå£ã‡ƒ×CËrûHÀ®ÈœìDëZàArg°>Ù)|,†’ôÚmLä&°PT“ ï!ì5R&âуú;~(2jKÛÀÛÔE½+/yÎ,ÓÞôhç(fY?H%ë69Ã^s‘¦Y,úéŒ9#” žEØ=ãÉ,–b;kNhú§4£´³Au úlرwjˆŽ¦²r·aƒ/âÞ­zá‰LXNâzF<ú‚uß–µÀØŠŸdˆ=X~ªU]Úóåˤ6¯ìÝMûòÚêU4G±f‡p×ÈË iß:{Õ|#oûŒâÓõ¾{íåªØ12L Å–Ãíìí¯,pðœßùœÆÙÓd䪓â*ƒKN€CÀ[ÑX–åµ›¡zJTRÔ„µäÞÐÖiu–]Æóô½õ˜hÃ{ØB ¼9°ý¬¸ë‰vŸ¸Ï mész„ÐùL-«ð)½ŽÊͨ•íò©òyÓaí~ZÍÍü`#Ùô&'^NÆ)’Û¶[lCÒ¡ÇúÔႊÐtäŠÏ4|º¤= ÞÈäæïSâM‘ ÕMåCμX´Û“IˆðÓ|€E°á.7áþP9JΰÔz]OàíÉ¡B¡wú0kk¢ßc$§nNê)âE°ê­UG*’J´‚¥h)E±ôtΜ Ë­ånw¯æÞ=Ýz(¤ní]œ}kyǨ#`ú³§²úõØ…×eŠÔ(¶MX½‚Œ'KƒÃê€Wš@¢6gòø•"]È´ˆ<†Ú5XÅJ¯·8Ææc6B-÷B šÓõ›™ÁGÔóp»|é顱“±ä=O±LŸA ­©ŽÈFtÀÚolmÅ2Èý’æé—4N‹AËÀo¦iû„Bcàlwþ|=Rû!¡N˽Niº{÷ž³Ý;ãÖdÈ×ÔÚ(ûPK;®ž¦5NF“ø{CÒ>m×ÇçBûB¤¸ƒX»û]Em+GÀÊ8Ûƒ]Yö›ôŠÄkŸ*rs(K’ú¼º‰GãE¤PǭݼÖ^ÓÑ@«Ïhðš(0›DP’µPž¹Ô ·îó®G†ºÂS^æ0\(ÍÜfWï8C“¶¦·á“—®°°•Èex¶{¨“ h•ïòz=”ü”U)©6a:Ý^Ú{ü8ÙÌŽN&‰_´´˜=–’0ÃäLÑ­Îŵ=Ï}‡ç ÔH곸Ú)8_é«e7`»cVg`'wv ããæVy®á›/€-d¾¬aþ²ÆDýM—ˆ"C ‘ð«Ò /Â$Ü¿´ÉjtÊòz üÎÝŒ²7qaµI3 Noc±.H†ú/ëŒèã^0;5uPR!„ªyj·¥¼±°%¶¹ÂCüES+“c\êaji¼§Sc5ü:ò†G©j5F6Éô ëEë³J|#}£Ïn/ß8¨‡[Š¡ª²dJçÕI“Ãæ™J²‡c†ÚÛ)2ð¸‡9õ©ÕÕ{o9ãYw¿5`B×Ћð|¤!è¡R›’ñ¸ÑðÌÃb´wâùùÕíöSÜÙ¬›Mx>u†¶ï‚±iÐö ¾€,35g³Bš[z‚è°HÞ•“’Èì=Ï<Ø­¦<{Ϧ§q%Áoámô¿‘D¡½g7ìñHõ—“ò¥6T0¹s2›MˆŸBe•Ö5Gú5”>ïÁW Ï.¢Æ(E«/²®¹GŽós|“]¢7>íÊËþ|ø#}}°Ðc N™:¥÷“î)6Þã õ›¾gcþl_f”«Æ U„hÓ×>ƒÝsWk%Ùv­üÞÉ—9TG-ï¹RIè‚çÚ—‹„Ú{&‘ @K«vŽò6jä%Ï‹$µnRZ‡8/·qÔLjå±psNQ3cÞ*™¤>°± §:o ä÷ê-…öóœX@¥Êö8¬§.ÏÞž…å ¯zf ½YÇ2õðEâ…æXrâ;{6àHKP.ÐÏû™¢Y½¸R¸w=PŽ)®Ä+VjJðj­½¦Uk#«$1 M dêTjN1î=$LãÕnS](RAAìiÁ×&­ûH‰`æMr"µÓCc‘ac>9\‘*ËÀÊÆ~ܸ Ryò®½ºîl1:åÎ\—,yPù3gíÍÏ:©Ê>ˆ|H¦.åÅÄB+´©  G´m71$/ÄBWrGmYWh:x8Ù–ÆÐ;<™Iï­úl.&¯@X>½þI£í!ÚÈ©ÆEê]k†õaÛFÎrr€¥ußê–øƒAcÁgž}»Ï×óË…/o–ãÅÏ9Q¿U÷5†Ü5¶‰sÁ¿ÄÙ— §(Vàæëý‚Â䥯a›½g £žâ çzdß1NBœ?Mnà·¶YǬ7 Adô V…t¥" a=ê5wj¯$µ6?¼B^íj ׿N „g…÷@Ï·3‘uÞB‰=MyIµÆ‹¼*®Ü/û€‰%ª®Š¶ím»óxä® IoWª Sõ@Ðr½:âLdv{[n`¢œB¹J×®j\0q½«6ë07ŽÔi’lç7Pôâ­¢Þ: xD?m²©~`¨'—蘭© RööÍT0³-Ñ–‹¯.R—ÃD ¯R`ˆ»€?Œ–^E%ƒëà‘ )Ø.¤#Ä~¥\Ÿ?¿Ä´âš§uŽËRká˜â1e®)ñ&—ú³ÛÊØ£Õ Ä>C3MÚMÆF¢•¼Ô t•ÉVVWBÊxÝKø@&Hô2/ë¬uÈÒ3°¥†Ø,íÁ!f°Ú™*ÚS¤·V¾MQœu‘;ôbë^[÷³ž ¤@ÝÊ—9ú”¦uì½Èb1¥¨¸ +ÏRŠÛ+•¥5¸Ýw”ùF‡ÝÔ©vÝFZQÜ KQrÃrWvŸ41!ÇLÏHø”„cʶØ<ìP澚ix7trîŽCÄœ|ÇÈ0$´$ àñžUŒó¾=}Ô¡î¾p+M¯pÔRùî‘Fòƒ) ²Þ^ ßA‰ÉÌWŽq;ºY)¥u|ûVÝ?Åñ/qƧýf¯¦7†y¹+oÍ™­r_ ?E üËÇSCdå­7«. 4Bý`¦ž@uNÐ5ÊÜK5 Xã¥ÍÚº`‹i¢g£ìX˜Ê`Î¥ËùpÓ4h•¤Š†RÚBu¥9—’{ M‘ª±Œ2?d¼™VÓ3|ËÒ Œ/†£Ži§ç˜_‰¨z£<y™!×Çu‘¾ë%¤¬o¥K2âÐw‹Ü%Aqr—ûíÊŒ®×ì=Ìx AôôË—r‚×ÐÏ—à-¿=€t~IÂÎb{ôPîWˆË{,œ„¯8i¹UD™f³U(ö$v…Ž8t¢0ØeÉÓTØ›FÕôá+}èš—çd‰ ]râ|lbôƆvQiA.²‡û1êÚºÑp³a‚lÁ´m )n<†y’j”Ý’ìí:êOv"ª 0zÖu¡!´¨¯T'­´t@ŸkÕë»òP|+o;€X.ÆÊ ±R/Bæ.+8æN=s±)¢ì) ÞyôPpLˆÞjì1Ð!íR€¸Æ ÝÓˆÓëk±‡Pµ¬æh@8Çïjº'F ÅóÒàœ_¢Ù{ü¼ñ´àpð ¯=Çy]y¶j«äBŸ>!bq¬(_áUŽggàI}`b/™š…™ûÙL!¹ YÏ˘Z6Ý,ëù̈ª9ñ±äãFõéxÃ^gkq$wˆt£nåÚ.ïurÁUã½áÔNÖØÏW•é—9bàrc‹L¨Y4þÐ ºÞó4בëGã÷—:}3©ðä!z…'«».·]˜²Jc©\ ®ÛÙJF-ÔóÊ·Eï„õ ñå8Ð"å9&(i 6ÚÆÎžô Ƴ3.^}…Q‡ÕŠÉ;ô’²Å5–÷6úº½=òÔ—‘HP–J6}ê€øžîí”­ŽÎ¤S¤,˲êq]‹H¨±gÜB*Ö«¨È¢ðéW^W†¦¸›Ý«~;tpPÏAýá² £I®ÅFC¼);"Œ~ÑýtÛhóE« ùø$ëçà³|ñmô2Õá¹’@`´ØÈ„;L˜ëŽÔêmr'š/&ÊsÖ\‡óvœSDŸ&™õ2b{+IÇŒF4ï²_^7ÓâÈÌ<µ×Mi«hð~ÑJ|RK×ßãy—ˆ@ä0ûͤ(‰Q_O€[XÕXù¤-]$‡-ÓËŽun´v<Ç æjÄëÇ-Jʆå2]­è©>ÝŸ˜FDùž=ZÓéÑÑSÈè-'j¬2£©v¹A¢„0*h¸õr{èn* O““É|àX‹¬âɃy3i©SUö&f_¤^(8µOTä6^ï)·ñã~^ø(Uë-Í>µ-·-«y^艂 >´ó³8]»„é„·N œxÎH+pöÕ€{Ÿ®Èµ?Î’¬X’šdfi Q/eñjŠÞ)í’–µ¦8ÔÅ 9¢&ºE4¹ÆC¤Ý/uœ¿ÔIž“©Ó°¥F½¤˜½lÏz¢0Ф—ð—;~SP׌K/˜]œÇŸ±È …êãqÅPe -í£"Z¼º×ãïð•VÄ!WÏšZ‘ëÙ ¾‡7¢SLÉÙý */½#.0¥·ˆG¨„ºUL]Qˆ±áÑx‡SžYH%."׈ÔH,ÎMkÇfè™áŸ–Ú ‚®Ž =õ|ØýÎÉÒçôî|¡dùí•NXȘ* ‘³[dbD©‘¶³ÒÛÑ w}/Ï3¦!8$ŽÅ6xU@É$|)2Àë-8|¯±çâ)—Õˆôa§Ç¬d¾«àz»Î±æÁÂÛ/ØXŸ Ñ-ãæà^|¬£&#}qoƒÕõ0'jÅóˆ,È+à=§×i²ê¢gàõð8Ç ä‹SHt(ÕÔÑhÍ_•›”DTXuî (‡:!ð«W˜x¥xR_î}º³]dgüÞèu†¾6Å%õîR_ë_ò(·C½ž­ä@tÉØ±…’½†‡ûtøˆ.*"г–h›|V¨š6´DX¹ØNˆp‚å¬ðžÐ¤?WX1]„§’„¶Uù˜Ú–4ŸÀ]O _Ž™èŽ„(Éhѳ5…}]S¡V7Þú%3‰ßÓò‡\t@Ö;U&¶bT0 P,@5f^/tПɘ-ô=ZÛlxœ€P/qº%ÔO"¡w†‹¶ŽWÆÏ½)L@):°q’ú1±,¨Úàð•b´ rΕÙ{F^ÉÎ:b»>qgo„_×£.u¢àÏÃ7÷RCçž7E©Y¥^²cJ )bùábóSÌG gÒeÅ/ŠÍãõH?g%e}"°8Ou¼ó5í™pùLñ¥¿v™»QE¼Ë7é!zlñ@ºy„Lx»$¦µ:Ÿ¾‰uàzÔlª\”ô€^ÍVVL³JøHB§­+¶“Œ¸9;9Ñ:Q(²$WoÐÙëõÕH´—±ic•˜c„Éž¦¶2P ­'sîal)Ž%¬Æ3ƒž€T)}ððÙë¾h0…ðtµgªÐK^KS|s u³ðÄ¥¼ Š”+2úí\\¨U AA¤© ogÜœæaý0~ìk)fx¯ßRÖ®˜:FbK¸ãjùNa!òëôêÅiCd—4kÁSy_|Ê“7ÄoÞpB¨ˆçSè&kW:¨µ7%ëž)ò—=Ôõâ®&üGÜÉ d7èZf†N/Ų([eÇ ~ã+‚m@S8uÛWBBœXÀýÒÁ ðìð,[Ò:À8Rå¤<ß'8ÙÊ3ø­Š#c<Ü!S!å}F­'ÁOÂ=ôíùƒp S~Ëó(ºj€Ä0r²0¦v"¢±ª#ŸR–6Ì¢¤Ê¦®m^”É%Šð „µ¾&ä#é¼j3œXe¼TI=¡Ë°^&„0ú%½éÝ•h¦lw¾½_$$Ù×î­Bía*YXFƒšûú¸=_vŠš4:¿¸Õ>´cØFé1=UoÁò¥#KѨlɼm c!ïX߬ZĨÓ¯¿ ÌÐuÕªƒ£ƹa¾{,—þš¸ñå‚zÌ2Ó `» ÅjÜÄ‚ÝÒRž –<•[Ô~“r8þRk ƒ =áC0ëišŽ°GÁù ºE¨nýQôœK€àãJ>k>³kµç|& 9]u>Ï™Ôr‰÷ºÆ¼|vTÚ‹–ÞÐñŠhxVÁÅHuuÁ¢Y"šæª ï…C¢ÔH¼ì9iÛ'2¯›¹“‘ò‰ÊÕxQÆzÆ2«ZXt)fŽoS I$-LêÈ,H®¢)ìúlôÊ=‡ºw¨õZm|[¦‡m ¹Á|ï_†PY›•¯?šë*Yã ƒ€ñá 7D”eV»hXÞUßöø—=Víìj§7ýµs_ µÙ»¸Â.)ìƒÂ?õÙ¤ÔFÎÎÄWÞ‹rüô¨$s®?§€½~žü·qKg¾€*Ù´µá|7Q‹öÂL«–ƒühíçCñiž †n_Ó¦s×–áKòÕN¬'Éý°QÞ£'àSH£/ÀwLCºR¤°¼C݆0– ä9Ç>žW3>^SÔ@OÍ\Þè‡:¾1ša”‹]‰Ò~[‹µÔ-×o¢x˜E³Uj1 V\Þ¹µXm“ÇFÈeÆÝ¡fl§ì®? âÕQ?ŠŠôx–0ᆖ£ø –¤á ÔÃx³N¦ú5H’6—Ôp+œ  ©š”¹tSÂ@ í5Õ ²ä–È9Ê“ðÀª€Ô" ª=xgÍT¼T< ¾ÚÝ~3‹á(qšT=‚ºé0ìç»úÄ!ëÂÂAd‰Ç5¡¸lA  ŒVÐ0O¸¨bí€õàò“ÆŒ Ó#Z@'顎0HˆKÈVïÇä·Tb+ä³Y4øˆ§ÐÔw"_ï RìdºS;ûFp±ŒÍ™%{ˆF¡4ú  ”´uD%zÓ¯n4ɇHÕDÞácE$xã|[vø‹¼n‡«Ÿ>—ðyp:0™²éÒÂÓèžd‰œÙµ´i=s.õ¦ãhNMä’å= Þ|®‰þØ/Fa†êÑ­¼ð“˜ÊÇ"ˆ®øFõ¡·Ýàä‡ ]¾1ñ¥ê—>—-ôÄ$#¶ÙÉ"-YbÃï0ГMàñ#Û+ç÷—?b:¹S€òFäìlÄzE§¼äÖðËõ)L¯tüÝ;oÅ7{î"ñ"4'×$Bf0ÔãÍZz:…’"Ö{(KDèåKºŽÄ•¦ÀÅ}+Çd“—k>P²ÈOp„.ÊwW%JxÁÓ3Áɱh\zäI¤:¶ñ:žžŠ¼(AçAØRðzæ`+éÄý‘Ô‰³ƒ:L-0Á`Í–Î1±de&oz!fE©3‘ ªè-ì”àVt_9¾§º§0ÛG0P["´æþ6ô=…ô&¸Ÿœ Àˆ9Ù(ÌÕv)“!z©¡êL¡Ôt†DÖÎ&ì¡X|O¶Šfw\d [F`X?ºša„+›=¥Á¢xUpù4kW!RÇš:F³ŠÜ¶(^ã†JͬI$£ »¼Ø·s{˜of21èZ1<+­AÇ!^Ï•ÏsËáÆ8ÃÒmNíwRD çU çB /äXo6 ?Ñp%9Q=ÈÖB®q›¢é—2«„ú(3kz¬Ûô¼î7Éû²6%=maÇ^THòzD ÁhÄP‡aÕ¾çÊUö䌄a|n4.2ñµ#««æ£~{Û2äìDáµ };Vn$«Ü&;OƧPŒÌ5œ£DóPÞ"€6ª“é„ffàV_k«Œ<§žÃÖ–Ä*Í×pϲSA6ÖXb?§â/à¼hüú&F½ï­û Ñ ¢ä )+å»ÇzemQ.û—@˜]Ï‘îi¬\R`aå“7 •²=~3t'à]æ€{«Ù`ÄÓúºNøµÛœ€Bb›ë†9sÕd ù¼Kñ€©Î™Ø™£Y€ÔwåWÔ³jïT[¸F„מ•Ü38yN¯ðI=Ë{/˜ÁÓå©j¾8dkÝÆð§XO9²¨šL>Mb±ª‹‹¾õšÃP™§vŽ/¢f:–!t :PrðŒFˆ^Hë`ëQ…ÍnVãd~C¤ýÊ8³…‘7âéNî"(¶ô¿~9Äa4¯iŽ- #E¸'zúe>@ÍÔ]K^±î. O.ØfÄ{8ˆÊòÜA•¶ÞBø¹Ÿq«‰j$wû½^z§+Ëp‘¯íšŠ#ž9x‘0̳Iº$rµµ–«Ì“è¬GƼTSìù‚v­Aå)×%z»Œí#_Éž8àÕTaj/{œoŸ…xøØ²ß¥«k7‡¹?z!ô"EV4½yôeã•çvRCDMw«ôЋ®•°>1—›Ùw\b/Uµip_+â\pG Æô>Dè÷65ìCÉ:°f˜`V¶T-ÞKŽE ‰­mC*]ú¼æö2ÉL¯ xÐÂõc ¢d2k윕p×s=ãx¶.” L%‰ˆÝœ=*÷ŠÄA 憱¡c÷uÊuϘñ|¸{• ü”µflfsσùè}u}ýÖCî$¡–˜}éÜäR@—t]6; ÿœ‚Ú(i{çiaäCV>×Ò£ ê4½}AŽ ¨k’$Mô´ ·_•T¤`ˆ›Ç¬š/ŽX³ƒžšÐ*Â#+nç–u”sSY-z¦]¸)ûP° ×<®+Qw@hË;:ð(£ èábW¶ÎffÄTXì7ViÊ×4$…‚¬¦V:½‰é¹åehŒ°[Yø¢€ñªO…Óðiн‡Z/m¥ú<(º‘UîfEæŒ9Ú@} Ǹ¡½€õ’0,ÙŽ{PÖæÐ’B£{ß\H¿GµÚU(vé«4oˆß3ŒÔ–˜‡çOzvU×—Ù¯¢î¥‹ÔNt+ðœáKõ¢w.>ËŒÏú& ƒña9‹D†çÍ/…o,qp9LýtØ—I7•¨&;±S´^0ä“#w¦ jD>’3#؆Ì}p «—/%_)¸Ù335S*"˜|þø$¿}›‰ÑoxIq 5#Pdñ˜#–h"’i?AK@1'¦÷Æß0yPa!“¯z[g¶zcëá£=ôަôЧÉÛ /#ô.*¥WˆÂµÔçéŠPÆ÷P«;œ°‚÷ª,pXåÜ­÷Ax­°äs%‹vá /Öq ^¾!Ú£÷Š‹Vâ]N ¼ƒ¾–Í1S#r/Üã–I³AÒÑ)ÛÌѤ:¹F_QÊ[QÃé.…ó™=T&µ,{”/PDïË"£/‹”…·_ð@µ‰ °´…·—[,¨È;¦ M\‰O¼Üi5-É?'#Ë·Ôg £fYLHRmþˆÓ—ÉU—ÙÁí‚îÈ9¦‹¶ûÝ#ˆy þ&´²»JŸr3šLá…SF¤ šq^>ËÉ6Æœè3ª[C““ÀE'Ñ IèÚMÐ’Î^ ¶€WÈì³Cï^ZŽâEK/œ"=Uµ ¥®>{ÒwŽ/¥LäÊf Œmc/‡GØ»Ò/=á¸$ÎØ)Àdšƒùi÷®ÙÛí3 •HäÊó¸Ùe™¾å¾Âa‰]‹™uktËÁ>PBkÆ~rˆ.«¯”d¬ZË3KÄ€P¤ÉVyqF©u¬{‰j<ŒpMs/^²ƒ yp¹‹h–Å»}ƒ¼¦¦¤Œ/{ƒ’-ÝâÙµvpiBB`³J¾=âm‘ìöZv%gŸ¶Ê^Îw®Ð6¬ ®ÞGåÛw›‘=T÷ع²w¯Š‡xÌjÖDûL‘«éxàÙ¢¿çg2¹Ü FµÎï$FÁIÛè(>Evw+ŽkÜ*ÄuÓË®4†qxÓfsQ–³-œ:y9аb`áh÷¨_d½|´¢¢sʺ"X9¸\T™¯­Ò\¬“žÛ j¬+À!—Ê‘)$ÂëÍ¥å\ž‡@¥P»j),º°Ô°’´MùrKÞ`­Vxžáƒ×zìrÈoXjLI5gJr_7/Öž¼G¦Vã%¦!Ï}iäð¥QÑômÜa,½^›¤d›·²m­ˆ”žD¹j’îúÌy¥®rxÿò”h;«g"½©šà*êE/¦¦?)AÇGfÁS´X `pã‘>Ä”™éWúF–òX{€»È+tçœ9óY[Ÿîí‹§/sEWWžõùŠ7ÁHžX&¨[˜¯o²ÆÓÙM½Ç®Y‹\Šä†p&yNÙ@1à8³;ý2Žü¹¬2Ãe ‘WÌ0á>@ç1‚á@¤k¦@•ÌÒÉ)è+½p]DW|>“žR¬¢Jc¯¯«½Üí Äm’, ¨Q®5àfŸLˆÉ¶Nßቬ6M'o¯\qêá¶Õ€G#Ç!>Í @‚0Œ{W·ÎD>²]ç×#h}v¥FàO od,M±ËK…xVÒ…Õf— ˆz¯Ö‹Ùb¡âkH·~ÔQÑQ^'W#&òðz`Ë .éX©$Óì½Úk÷A´TOÒŒ£Â o ¸mç ebÒ¯‘Þ/·ìÆH¼Ç§Pר›èÊ-„mÔ¨o ´Rü½ñ½¶Ìœ•j÷d•\(g²žûÃLài&¶i[ì”…¢ÉØnyâé›CG=Wò|à²W!S‘#‹2_s&Õ>}*²£ÝÍ6ôº3a7~R.µdq¶Kµá`çYbm½6ç+ôÈ5ÑÝÀ÷…e‚¼‡ìꄵ%,ð$ñIt1”=7È-9´|”hûxÊõv_ å˸ùôÈ¿uà„VúÊHË…ÈR.ÇëUÖ´€ºúlæ ÞÄy¡¼0ìÕ3†ÞÚhŠˆa (6}°ÓnÁt< ©ŽÊ@ï?Y’\¯Ö‘»´”kºÛ—N­ð^æ{šÛâ—²0|\ µ| Y^€½§%«O6¨­áˆº¶€£ŠMqÍõfa-ó™Ÿ6Õ{b:+Ön.‹eQë᳂J­jIà‡ÏÄŠ´ë±<§ ’Uòƒ|ÕSôxxí2·ÆÎŽ78©y¦&ØòåЪž ˪¶G&<«ÍSKšÑС‡ó%J–Ðö81‰‹rÔP¨#ñê\ênöTè)Eå™ê@”>Ãä¶—LÙÎKµC¾ªþì%`ÒúÎ)\´¿JFÙ:÷GJfˆ”] Þ–}%ùÔ}\:|µÝì„ÙK{®1qŽY¼wÍ ”ží5ÙÍ£E¥ð'¥ªO•-s–CÑH^;ŒOÓ=¬*ëj¶p[xÙÀDº² ¸>.^#¿#ž™zü$°ñV¤v~Ø‚‘o‰‰ŸRÙZîKÉŠ ˜@—KúÖeÝŠÜ¡7::çÙÉôà©\1;Äëß• Vª™g6ÊA²G¼¡>É+’䱚Ô}*JLbiÂï•ð”ð»ë}ƒñÄô‰µÉ@,¬ ú„ Ý&ž˜<¸4ò—Ž¥ë8á…ó->LzÀ_&…½>*ž>¨K7*F î©âE5…Dgü ‰)†mc,%r¼ñã«?'%”*˜Õ$·góTž¼Ú)!£T;®ï1¦•…w†%‹p[¢Õ»{¸Gµ,¢g-|É~ 0EldH;¤~OŠ,Ë#•XÌß´ÕF â.'<÷´½Hz¼ˆŠ§óÚÔžOq-³Ã&¬We829#ôã.áP?›*ïÙ÷ž>´Òq|é˹u=.2¤¸í‘Â-Í3tê=2 VAÀ*|€³’ŽâGKU×Eàb)]¦QïèQ¢°¦ÊàÛ»Ú¹×ê&S¯0@Ö^r[Õó—ZNÒÄpÀ–TzZÁ\¯ŸÒ M'ëÐë 4RËžH_ÓÕ®¬¸ÛªH,´Äpan¯“ð]Üj­êÖ¼Sà³Ië w“ƒaq$8p€šë­¹[ÊZsFí¨Òwo¬Ö½z7…S„˜‹ÝdšÚžŽGLd÷5• éx¶”rUÚG‡ñ*¾c,éÅR· œÚí-ÕÜJïu‹¨ÇÎ$2Â"‘S€ †0~é-‰¾wlûÞ¯FÔÏuœµ&EW&Ö:Ø|FôµÀ8ô*‚l•R«Š.uÏÃÙµæç$ZD&ðt¶è94øiãêó³ÍE:Y—g,¨‡aÒ 5yë<§ãܽ¨­HÃt>Ü5¦\tÖÛƒDBæÍwž/÷ñæ6¼S«Œ0 z4=âø êÕ=Yd3b¥/•¾Tr¨Ýê¡}ç,8Ì¡ØasU­§‰7 ÷UdrUCÚY샌Ǭ6ɹ½‚‘xÏŠÚ õ”±ÁôÌm=‹]÷²¶´}Ëפ }wôÆ|éV½Ž\vͳÂÉͱg*ÏÐ,4ÏâT_\KE˜è ßé}-*L -7¤ži˜ú¢Ÿì“áÙ­+ŸN4u-ñÔ“‹iñ¼Ø’UÞ¬c ÝäÁSa+;¢‘¤w^šÍ¾ÖjeÏ(ö‰÷Ùº ¢¬×ëôR½Bª_ ¿JzºŒ/_7ÕCÇ9ž§lLøΑݟ҃Êâ#*ÊwͬýB¬ë¹Iƒ6ÀÃu°&®µÍ( !öÃŒhf£>FK‡×?ìÎÝ¡až² ¡êÙ>¾ðg%­-yò­¾8IBj&CÊå<.€½ÕŽÅmÉN°kz°ºæSÒUŽ& w;@˜É‚%_ËcÐÝG«¹·¼ù–Ý+ÁXdÂ;¸Ì×dé­ËLÌp-ú½ÁlÍZ âöµrÂØ÷+oq™—6ê-õËd¨0QÍyU(¤•çN0¶¾,bçø|'‹éuC;ÀTn{;•¢ 徯 ˜ëÐ,¸y2AYþ’¡­‚D»óù{Õx§eK£Ɯˆ¦ÍŽË;³àDˆœöšâ¶§ÈpMràùî@ÛH¹h£©7WG‘8â¡6ƒ7í;ª›¾ö•|¥&ŒžÕìÓs”¯ù\-+rɃøzÈPn„‰×ü5¹Dðå’ee"mSÚcSãefdÈ…+•ðÅVíñÑÍ ’K•{ |)˜µ|çý%“²£šDÆÕÕÍÁA¿@¤ÑW Z›'`0ÏÐCÅok’ÅqòZƒ}/CžòÞajª4Xq~o;]-ùVyä”PW#îê-×e­½½°G~rSÒ#@‰è°  óPšº†»lë2ÑI»e» h©9†‘ø<0½;wœXu”ÉuĵÆ@Z&·3êä°¦i¶’²Â2¯½÷¸Pž¨¦k¶Ÿvƒ©<€ ƒBÊ9_˜ËîÔ”€ {;"3JœÄÊq%ŠPK¹ ¡6¢,]Ae‡÷@vr!½Dr|›R˜I••VóU†%l‘j€mÚ ãÕ;u.#‹‘… Gw«3‡ea»Í¯Â³:a-€˜ià×–‹ÜÓßùòɯZ~bIs!8J5}soÈžqÕ¼â¬!æ\f^zán„+õšOž¦ÃU"Ϛƈ›t¼˜ ~EJØjʯ&<^í¼~òòä±X©¸ÒhïHÀË*Æ©)®RÛ£|(çuCì©¡¬kÏéI‡ïk\D+tæ‚çOÐ-µ(„7WÐÂf ¸m¸Ý“Ä÷ iðFÑ'6¤9÷Ù&œðÞ-¡¶a ׈F}éÄü¥Ó{ôžA²—Ò.?a=´æ=ªó±íÁḀÊRàòM«+5„Â0•dY¾"ùïéIµ…äu¡6[•¾µ)ÓN29ä‡1ÙÐài‹öTõypÜÂ- 1û„ql#‚¬W±?"ÓË à‹dq9ØÌ™xX2²3~ô+烛DcP>ë‰Wðøq¥¯ôõ-FÉøq ƒd :-]$@´ú[x²†*-«å(éÍ€È+Øu}õ¦À­!´„oâžFd.sÀYhÝÍ!˜h¾§S©¤Ô5)pÂnbº0•âží<(·ô“ÆMLÊ}Î5rµ‘NkÇgZ xÑ¢ß`° P®é5"ˆÉ+0|àŠëªëQ4ÍáíVI¨hò¼…©Ç—šB/µª‹”æµ2n»_Ü¢!¤ LiÜ9Û¸‚-ïj3¯d†k‡Ï—Q-¾¼Ä÷ðŽSOx³ÇîÅuÑããá.ï°`Ã$ž7ïì½Móº~p~õ2ÃŽŽrž®gÆØú{.B[Ø)HWD:F¤ìŠòð=WŽ~ØËï¯.pÄ΢æÉuKwH¼4¬ÝQ}Æiq*« åMøð …_TÜ“Q7•¬EGêDŽbd5/X:[á­â:U/!sbLã‘0Z, „ÖÄužYM E #úÈöÐ…½Ù¶BÌRÔµ‡!bB7þØ ½oŠútKE°™£S)Ugl¶’Ùæ¼)6”Ÿ–úãC¥±p›8‘BúòIèË'õ a¸PnoãšjÈqgAèzž7ÌÏó^’‰ÞÛÛÖzTâ[ýüšR+ðIhúßÛ:ò‚H@GyöœuK žKq=xwgœ¦Ùhì”c±PEêꆅ:‡Âi.GùRÇŒ;Ü›.Id¦IµË÷n–Ȥæ=…Æ  YtÙÉN( ÑÊq?}ÑRŽÚóLÈqð–âz͓弅ž¬hëÞ$s»4N#7Ÿyn.* zìóX8ðL—e5øå;ÊÜRMtI€ÂZO¯¶Œ|¬/è)[.“V…·É²xèð”g jðÐí»÷æ 6c0ÝxÕ§‡wI$Né¥ÞH#›¨4¾ÌåÙšŽèH“M;^3XÚCçsÀåAÄ])Ä(Šgz‡QR y.^:m{`>‹ÔM\¸Ð¤KhºFÓL\ë§Yh•l¹s4Šò‚ØWèi¦øX¹2 ÒÊ$ÒèEjP²÷jì•¡>GÚºkî_QÄ]zÝâÄ-¹œU)“Ë úB…ý•*?+\“§q§Y³®‹c÷tšöåÙvª8q²&û•{{v‚vµÌ3—©—e^…hü„Ûò.]À•™çmÉóÎBs ·¬m++›t»˜apŒóŒÓÞ¥› „¤Säú‚? ›Vœ¬`²ipIÍæ•>ÍAdÝfÙµê‹Styâ¤.ò¢ƒP÷½çM©sVr$U¿›Q;B{¨ÜÓ5>y€Ü¢ÓŸR·v’Ÿ<ÇQ0/ÕÍŒI¢《ìÒ†or‚;´|°Ðo:W4ùJ(âÓ¨ïïã ŠI[Ú»ãîØK †Fãc/1W߈‘âs.‡Þ\³탓„M”ÎÛÅ&ÛÊ¿”Ú2~¹¹H÷É{Á¶¤½Wëñ¤×za$l°I„é®Í-\@2И»w§\hoŒ·-VòZì0Ù½ÉPf¯Ýcl²Î‡®`(ºñ )㘂"ý| ;_•Dö4Û£ðaÓÙ¬+Æ[±Ò”Ãû¶k–>— šÛ ;é P!uxAùÞib¥ jhîégy÷`ú €e+áÏ8çãzƒZn·ç@nAA½ª!4¦ÊÆ¢Ú¸¡sjt¯ß“: "ÐZ* ¤†™[ÕJUö-Ýt%.™ªÙ6¨4~<- Ü–mÓŒaçÍ~ùSÖ×îû 35ð.=ó!S¬§liúŒé=€nˆ@¨HÞ Ž ô;¿ÌWŠÏs×úµ‡*lè«"&Rñ˜“7‚ŽlÑ#’"…E¶ƒ—afÙwæB$H‘…´MlÍ>ÅUMΦ^Ó(2fF£®¬4þÛÁ„ß—R¦_J¡ñK3 b2æCdG=¯ß»(éž3A^çᔋ«±Õç<0l¤O¹¢.$‹'ªþrJá½,éÇ#”]¥›«©}%¯_¤AêÖ†d'M$e_{xÂd›…ëê=`H÷àŒÅÔÄD2rÞ3ÞH†7t²¯…}0½¦l†xnàcn ‹Hìôd(óEßÛqOôó¤k²`4žn¼òV×z¦Œm=Ó¢¢þí…ÐPã4鎜”ƒ6’!r xPa%l5Aîj¶¿4o*nÞfì㉷êzB®¢“:.µ5‹ÐÌlBæú@BžÅ‰µP4ï—/#@V< Љî]wÄ˦Ã&)=0†«<:gƒŒp)3W1GÚ£p.rÌd§[•IÖsÀÌwd^M”"Õ)âE6´«ë¾ÁŽQj¯Œ,:ä`sÙÞ)5ÄD‚Ânœ’¾@VL|câå“NÎç÷DH¢¨Þ£Ü@´¡|²°ÕÞÉ ¼nÝu AuuÅÐ8i%é®cñŠ5¯6¸ÍS;z£“=jüÑŒ±öbt¾ì8Q1ºÔÀ.í\F;÷ªV&Aôšjèˆ 3  h4ß~ás‘á¹/ß¹æb:å´„P¡’F³:a£(ár±ÝÓ¾³VGnHðR`a€Z£m\es·%ËcÝäèØæ;%\a~u LÑsøÀ:^¾ÄöË¥½RPªxÈ z™ëçÌŽù4J™ooó¶^½¾|Hâ€6SÏ^‹¤rÃÅß—SÎ_N_Vâ 7OÉ¡éeÝ‹ñž’å³ð>¯J?ÜG<Öv(Fá›Õ<½6½‚Jqñ§T¾ˆ “€ñÞ¶Á– dÓÁÛ=TÂ'DGë¾içsyA™µ&›0¨1Q8ø–‚ßó£²(òbO.{Þw£7<62žmÅxŸóÔÂGþ£3æ9®ê0:ê*[v©ÞCJF·†Q¹ÉÔ%É$vD jªŠöWËFÆë 8œd£Y^s"ª‡õ¦&mø°JªæmÞ0»æ­Z©¨–÷ö0[EÓÆ£õJ§w"9çFÕX;Ó™iÝÙ3’À®·;æÒNI¦l°(ùÞH=ϺîÞúH«–^·#À ŠØk4¯¶wU÷ÌI@™IÅõ½*¦”ZF­˜‡÷€pk*5^hs¡m.ê`"äs4|¹/Fr4‰ '=s®/[°U^ ÌqfÙY5vrtjøÎu‡é,En̳XPËŒz×/µ¦Æ¯õ5g¢^Ô¼ƒ Nyenv*#k–#jÜú)UЗTµ¡ÎµÁž½Žf§JA[¸v¬ÌDZi3²0ÆJ¯=sï)écíhl;ÅÜ‘¸°ù˪—pb×wU `Úî‚Pˬ稘Ë÷ìÄâÅ98÷ô¯ò´Ýs¸=/õ>26‡Ô”»‡…#ö‚i Œi=°Ày‰/˜qÈÎ.×5Ì×Y+†ýAN\nÛó«:×LŠPyMÛùŠÞÛ¤Á'0·yizåñËq’îÌõ½w¦`X¯ c%‰ÂNòÜ÷è]qdásWu-W~ίUjÜ©ƒxM¡bÌÇ@ʼh96Öct#Öƒ¥^Ud““2©à+ÀøÊŠ¿”¨\îÓæ|þäU€§å¹cÕ‚²òmÏKá"#M‘Û†[©29†7{Yáq&ÓÀHïDôEÄ Àc|Œ´¨£†¡‘–êà…!–ÆŽó¨ºkvÛ"¿]‰vîÑ|,½-Ë”_uçcŽ™—´`áæîˆ©€ùTq‰1Ý~¥hw‹¸g0í¯˜¡ƒØæ.‹BdZö¼rÙsÅzàdJñ’XÆÐ"ÝÔ«^Ѥå’#‰_y]ÜpZ€ò£Í}Ň³QöYìmA`»¿:›ÜÚ¦LÞì!³´e™†×írBóHû a݅âV0é>ϸG¯ŸÈ–uÏÚå%jŽëóŒFí}n±&¯^sðòy¡“àló³¦+4´5ÑP6#˜aNy÷F[8‹Þ\« ÐKÀz°škð¬A’;+ÐM«Tár׳ÜTÔ‡U ðe•-ÊPŦq§Â©¶Ïe=³ /+ÔÙÒÄJØ|m»Lç1Ï\×,ú@^›™Kf¬rÚ þ¥•xC±P5¾iÓuxVo |FÐ;•%d^”Ò`£\ô0Lðä°FlÙ#kåh,±|ïxëEÚ©i¤nÁ9W_¸´f9.‡ÇÉNÊ:½~¸ÁǸbV±Ø¯ ŽÙAÍF´Ù­Ùg„€¬&ö^D¾?9©ulK†WòäQ…™Ììi9zÝSËs­X“›n–-™gcuK‚v%•B$m”IAÙæORêø’XÖœ6ÕÀ‘Ùï¡ _àÎETãkEIµœe¾Ô÷´ˆÜ—¢•ã1¶&‡Ä (dÄi„c"Üv?XŠn3g”ç¨5D~c.®ÏäFuºÍw9S6¦¡0àÊSû¨¥íÞB KXŠDM¯U_–_É,´Í¹S§ÚÒ¯’ªˆ·ÝÓHª–(K÷×Q®Ù¾ ét U»±vƒät õF<¬&o\ùEA›0W¾{¹ä³×ov_Šk=r/çñ袂¼¥ìà’®áëª^ &ÌÂÕ…iyâÜháèÃâ’£*y…¯­/ è½œ›i{Þd J_ŸS>°cnáW+ƈP“ÛÇÕ;€˜bê X<žžZ—Dó2£” <„Xw î|:•@&Ô§àL¯Sˆý“¼!^)樳Kc²¶³Œ’ÈÞü„”0ç,V¡K\’ ¼Ó€\Û,8>µò/­" £–Ÿá«s@Ù¸IÕ†£ñ×Ù¢¯Ì4+îù½å³=¢èb~ø*p¯¨¦Æ¶7^ …«`»þåÕÀ² ´P Þ)7”¹¼õ Ð1+µ®M¤GT28R]Þoë8ºunýŠÑCðaˆªb›ÑPÌqÖ³02ïX£Ò›xýBýêæapS Ù ´>ÄØ¦¬])UC$Ázó‚€:æ]![½œ7‰à$|ç³9“«±hý«Ñg÷(£ÒoàI‚óH ]ÅòŠ^ê®ÙÃ÷¨:ßP hœÅËVWcv {!Ý‚lìxqÊüÞ(1 Ð&®iºƒ:<:½öˆÆÃ0ß>ÚzlkbâIAn'µÏ.Fy9¯,ªƒŽÎ2Þ9©Wç6ÙFDZ¥½"|ˆl· »ž¸lùÒÚ»ã­M=ãYt„ƒ1„G(Fšz£Ôµ4“ëÍôLO\-¨¯Ö’P|«2ˆTtÇõQªÚ!¡±H9`¼íöªË2A¥Þ5|±·}î‘Ý{¥½ýÈOºr{W1Ò­‡® v]D¡;,žR#¶©JÖ*ä¤Ò$Ü=uªG­“†ÎH uÍÏžã‚=}](“;ï ÕÜ)õ¼ˆn¦HO’Nì6•ÜA´2 ´"é!£èc½ ñy‡ø0/JëP‰ºÄj¥C»h9ŸÆé¥S̽[JÞ}öøqK§º:5´—ùK(ºTÞ{N.‹ýRÑÄ=Û±Ò½éåƒ!–ÉéÁV7Ï!F·ÈÊó{1_^¡~yÕ~T¯Æd/¢skš(çÜ3$Ÿ0>#xKþªú‘º9¬¹úw?c¡Ó$Êt±×½uÄFù—X¸¹2'ÌÊv/\TÜ\Jª‘Ffîm½Ä[å‚k@ã›Ã™tAw o”3≈:Ñ[šŽT«Ìš#¢¦|Èñ´GLÌ_¹à °ZÎ9yXk«Ð[’”SªÌ©¥0Ú|$¨Y&¯óYŽ?Íà¾QB§²Qß…µÔvap†ÁÍ©—(>îkp"xëbF*ÙU©ÁvÄâô08ÀÑ*"%0Ì;ƒexàèqÄÌË´G¨eM¾;%í÷\Ð%F+£€§ÕnŠ+—Ç^¥0¬ª<­½¥»*™Ì ì-%ëc×xd-óšz- ÀBÖÂ$½õ¢Á*„TyŽe6=f.îä( ”"žU`Ø ¿ÎàºN‘W³"ÄÓÊ9¡wÅão3°×:Ýù5f‘XAvôŠ­uØuƒÞá«x&yÝ ßÙ8tÍÓe—QïädQVô—#´ ÷œzÆŸ:'._.ÒP=:ÌQ ;œ¥ŒY‡V®)ñ‹‡th[T”shöÎé*›_¡oJAwüê]CysŠ@úô9ZYH’¼§»è"Ïy)IÛeÝ@s±Õðh|)a“ RÄ»ž¤C9I;‹›e€­ó [Ê7HrÊýð5ÊôAO«>CÓ¿Ó†ÚÅõµr&^"[lï4ÑM]F—]¡ i³BÙöv¾ HVލ~ÐCöä6¼ð­ÜÜ—XÄ_bmÃE" ¶&%XŽÃ 2™€öê1#HÜ3Uf’·v³"ÚÍæn¨S%Œ£ßXÏ"œúˬô|6,™] Ö/i&,ù-Ñé!n&áä]ùö†-ÓˆÍt°ÄæR6pÖ<ouô)À#Ø}ê=4[²ÏwÌH[ü]Ç#6Æk¦O³ì$(÷HyN ‡)A¢µ‘ ‘ZÔmš>+ȽÈhoÕª³Úó¦ó-ŠÑÌæÇu‚nT«¤Ä¸üÐßi›²E)Ù‹ “Ò#Y}ª>Ã×iU7V®Üpr^‚N>—æ´ë@îz†Ó¸™A!þy*ÚÝ_[è“•yW’O…6ià7Ó¬oŸïsÁ,gì}8¼xûÌ÷LÖ.,Ê0É9ÓkI‰¨¨ò@]l}GM¥£Á‹R…`Eݬq™Â2ù¥+œ=NUµFÅ×°iºeÀOj”çq!9â«–Nb{œŒ÷ž2N<ìkãe½7ôàÙ>77†ÔB¡4«B°À…`‚"÷ñXЩÑr§À'ã4=èÙ./g-ÊÊXŸ·½`ð€,æ}8›æŽªÁ›t+Ÿï+, W ¼§:u‹Éi oÊŸX“øá[©ÁÕçê±u©S%K©ô*½Á²,¹M=±Þá­Íˆ(»âå€Â>hä`|ˆ–oÐYœiâI3yàË׃©oXŽüˬG_fÁ4 :¾gÒ‰èÖòÕ1]Çy3IôÊàQ¼u.L»‚.¶a í%¤Tת¨ô,l +Í÷þœ´æ2<”²x4JA_ ÍÊò¨,7@F-žï¬9¦0 N>UŒ—LON×FËÙŠ¦9!…^ˆGq©:Úô³q•¢— %:1X¹ºÊ7IoÈ.ÞËuÕ‹ö™°jÑ“´3ïö[”P l*t§é­žgéýäI¬»SoUgû»µå\ùŠëÑBa""lñÐZ1kz°O³»Ü¥á2ó!•]˜ôù¤ŒâÏä×rØ&OuQ³MjÄÖ#Ÿtï¸ÁÄ×ÎKç¢[0UÄQ¯ñwæÛ@Ëxùö”x†Í©ðœë-í,ÇS”ÑÊrwM EË'¹·#Å:fïFЍ+tO“–AˆUµ Æ£S«y×1œ„NWÕǵY† ¤™„TãÝí¸»¤²|ò^€1ìÛ(Ü_¬Óú%_:ñ@^f–u{ô?]WWRèž`sÈôÜ¥›çL­”$Š`i zn¼k0„^Šª»¥Vz†8LØ,wÔÝoÕß mÉV+oC½êRÚÔ®{&¥¸Z‹r½ö°˜Æç‰›)¡þôNéNlÄ’ˆ­çøu™èi’\/€óW¦½ô^¤e y ¯)ã.˜ÕSã÷‡’ÓrI:ÔöHÛfDiÎùÅAc6“½´™.CqœÂÑ«äòªPVšîíØÚ§mÀͼr \…'A,déK-†/µfɵ’ t½ÄÏá {.·f‡âœÞr¾­V׋HÖŽu‡ m1vqZw¤$]I»k‹ÓgL÷—[×¢JÃC^ž,GßøTg ˜r38.݃¶{;|“˜.Ìoði,DgNˆArïß,ÖîÞ·ìsr¤­ÞÆ.H®3…õ4Xp¸Ê+Â}•v•`Pdðž‚SãØ¥”y•16K Yƒ¬Rðì‚ðÕ é„¿âе‡õžÅ¬p<{ïLââB(RZìeáêªåuŸ‚™îÃPÁ^L¼VÍ–ÚÖfɈ”3}Yù€Wmã±ó ³b«¯ZÑä\±ÊÆ£”Î\ræèŒÇØ«/^$ð{SóÀ€`J%ËŠ²^d4Å Úô5ˆ»B ô»~áZ@Pì'×Ð/µÆïj[óqÎØ†‚7Nf¬ì–…µÈìÓrßÈÆ¨µuO¯\Ï(U’‘¤OÅLã<ú ï%EQ¹‘1¬P*4¶‡o2õÄõu½pK@™¡°óç4ú¢Ç½Ó…D/<ëðd‚•#QœÆF‚¹¨xo9LF6Ÿãó Ì’RL x#¬oh†Ì1ô)#J£WÈêîÖ&á,zGn‰ê¼Üˆtζ ¢=¿g3mE4p¨dM²Ëj v®³5NjÉñz¥Ÿbê)’Nµ“¾ÒKé¨8ÏŽ›I¦Ëá÷ª#M“Ðñqc—¼{gÏm‰`¡UÜF¥ëî‚ ®—ξ5×$ëü8z…Wö‘öQ…áZ³œ¢QìNN½¸ÖH;#bÜËZÓ`rðQ– ´M›/¹D¿äbÔ’žŽÛ¬yŠ5–u) lâ[é~3ê7Îûb^Ad“pØ<-~]kå’š¯·&}ŠW„£ß®`•^—fãþe׋cržÛü4ÈO)[Øo´¥iõšh]z4"¡ ³ ½öÓ# Ö®×L¸ñ‚ˆœÌÒ¯Eßé4‹” tq[a-3‰Î*ËÖ 9éëÐ3Oõxáò`-Žæ©RÈ)„¨í¦¿.MZ*GƒÓX{1ÅæÆ‹GÙ!!Ì$†ƒ½ó¨Qp‡_ÄIn‡¹ 2mãz{Æ¥ôÛYör“UH"žðŒ±ôÞu¤{\<Õ-òÀ@m”¨Q¯çpæ\óV`¸ÍEƒïùí¿ºY}xùÂò:ÁV“Æž£XÉÃ_”n¡l_YS_yR‹ÅJ옗áÁŒ}`½Z¤c ÃÛNB˜üØ"¨žåE›ŠH–p*™œàÑË'ktq¡RÉïhˆ½OÂÅÉ‚<¢Mx‹u‹ë¾EC¶âbïÖJß3¼'m–fûñôe\9oÞKó+e¥”V?ÒÇu õª='9‚Zµ¸½è€=’Y‹ô½‡¬ÅLÐG%¹Åëuƒ”e¯Ržq„•…µ“³7ÝŽºÅÈÖcv*×çoƒxXŠ;ö„ÖôŽž&L&vœÎcª;§rÝîç…戴8ãÖu½—:ò&Ää]=æ/»”¿ì’–ËS½G ç±­O:9'ï(x`JÚ \QˆÖëÊ´¸Ví|¦¬°À( xMå‚ÞÊt趉\×!ðLÂ@þÒ ÛÛ•_ᥠ¡ á “ ™‡Ìð²ÈÜàÓæ%BsK¿×y¦l^³‚Ö6ýv*¬=lj)hçÔ°šÝ˜+4¢JœÐÅW˜!`=¨ÞnvÙ‹¼'[ Ó+Xøðw„±6ŒÍ{2èOD ª6¸y¶  ]‘ûÞ¥#F\Ÿ”Ä>S{Å…ü€ÆAª=¡z W†gëÄ{sdöÞGxJއ#JG×ݵ=q‰»xô€S²å4¯YÛ-jïil•€Jva´Šœ]ÓlòŒå;Î4ő瞷4¡Uë€p ëô@*¸ rB¸FN¯fó [ʤ;pж„ý=ÃÑŠ˜whxƒ€ÆÙ÷®Ù&Pct\Ôš×Ýd€Pg£-×M|FBì‘=wõ°çÔëk&B¡8‚;PnwÏkJíqÒ»…ŽdxYÅ·coz˜<Ö9@¡0Å*¸©Ÿ Ó¦¿×"ø ÇàL^G>õ³¶ÁdªZ >rbÇòÎß­æAËNàÁ¾¸´G$ɱ(Ïïl2w¤ŒvÛÝ•¦ð% Ñ‹ÙâëûÒËèK/CµÅªÅ´N1wU=§—Ë»÷‚ ï5iJŸõ.HuúCEP¦%´zæœáYÄœŽ±#ìÎÓ—ÓœqO5ÿôkòùfN½I :·ECÄ·(óÔe m«nÀªÔ§èiÀ»×ó¶Õ¢´:Œ6`»náèšOäá_ê‘Tëæq KrZ/FîË+WLš®àpbÖµ<3FGå– Ú)ä ß„éGùê6y 7ÚOŠm—QKUI5鲑6kã'æZS>¡L [¬Ë"w%ìe~ùåðåÝäCœª${„-B.WƒýàB™¿5fT}nV:Èͧ›Ú(‚ÏðlÆ“ãlRšýu¿U£×€W6 ¦ •lxŒÜá’l…ÁèÀ’“ë^•È2{Å`9ª‡ñjw—ÎpÐätpTš‹ÈÒ#†œ² yöP湆@ÚÓTèè¾àAYÖ)u"¯DãÉE1Áçó.¶L»P¯ R õ ˆ t8Èlh äzôø²¬ËqÃå\Ò“}©ÏøûïÏÚQÇvؽx¢ØÎê$°&¨¡tÍpÝœK-!w'´(V ÊÕ ™¤\±°Å#=Ó ‹. ' ¥>¿½-x Þ]ðF)˜çQ½ƒW£”-Û'IÁÐÄ€g‚×Oó9ïžh ‘Ñ“.6µwðš÷꩚ó@ôˆk 1gqU½gÃü´¹Ú´“ÍûÎÎ&l—&7Zj;nÏ*ï :öÑœd¯OÖgȇ´$žŒŒd"Ÿb˜ ]mac•R–ÇK•Bm–œ™ŽºsŸ×–Î>Z,¹6 ä¥Z,«ží¼1æsÚéíˆ ÖLU`Þ»#Ý{Õ Ž‰qXö‚Z}ˆ‘'h˜tÌ‹«v8óÑ€Ô¦°¥Owª{ïiAµ _®5¾@©06¯K£­aˆ«”\önzèÜ ž‰îï(C@ML Â#ãÌ -âdK¹Á("g]§±ŠÝ«Ó*´Òx8:‹ŠÑáZUp×—2.2Œ«ëîô†ð¦!Õ¬yôÃ:#ó/ÁBÙ8%³dˆ‰²S—ÑÍßK%¤¸@LµsëÀ¹Ázrl‹³åéY\Ñ¥VhÑMz"/×J4B£Ëÿ4,ÈNøqëé6J‘Ö½Q¼‡ã8¬ wL:L 7ï"ßäIåm†_ì»R]™´ £SéToŸöŽÜZ4œÀ/ËgòàFМ_Zdá@µŠ Ò ð Ä’ !^ÝvG¢žÉ3 ~|éΰn.iÀZjÁ«ô„ÔI‹ {â”ú"h_xƒYÛ¹‚Û1Ï!Jæž|1燀ÝGB-tj3×fòÆA=© Ìß3½-œì‰„zë¦,ø¨¶á^SG ál6¹š@S3'EQ óœtGXŽØ×f¨<~ÎÏÜ'+EÒ²…ár@ØH/W!íùÓ.ë½3àó¤ÊN}Žlñ[‹mPæ’åŒ#ÉÛ®Q[CjOƒŸå¼óöy“ò\S'LH(¶zœû‚F“;ÑDЬε™— –1p“´®YÈ…pÍ¥?ŒÛg=@ºrv޳ëüÈz Œ¤OCøm°³÷*ê5¢Ÿ=-|t@bAR>ñ¦.uáñ¥Ê&m¡ƒh7k@­ùDMÏ–â­€G‹çxøeGRS#î>ˆ)ô‡;Im -çÔ0m²ƒÆ€`\KÁKy&[O¤º™©× {6Û=5'E~HøCrw#½Võˆº¶rz Šœ°Ê¥;VYJeML³ÌØ ' KÃí¼rÔ¥uw:NAA&õaÏ—a¡_†µaã1ÎsR¥ß‰«õ{ážIò†‚s¦¦Ƀ†a/„‰pz öXtÎâ "Üà´N!¦ÿ­Ø Áâð{Mû€SÇ£ECÚÕzZ˜+2Ñ!Èt‰»øv½ŒBÁxœ–yLh—Â@tœžCü4–¤‡tDË-pcV®|ݯÆñ!ŽÆŠ¡†ÙkÆô³ƒUZ0=i‘I`šY°qB£ºÛ«*xxe(ÂÚÉð¡]×: ŠÍ€ ýJó9£š>Û»wóÈÝ4fØ‘™ T£lgnÈü…’ zh¼z‹¡;ˆŒ8…&+t@Ä@uF‡.ßf-,Û68iµiÂo´$pEŠ&dXωú²"Ø ÎO0Å«¯ŠÓ¦£=•%žäjJ¨‹u>i¦iê“]ȼ‰Ú{iú½jpÇŒÅøK±kýY›¦èA‹,1‡E¬ îoÒbbGHÉ%¦'½_?Z‚7á|˜ÅIˆ)KË|žú´d&®Îãð‘÷ ×¹ q¸ò/ÇŠ°hGýR^ï\ù®S(·_?ƒ4 $ŠyÍuns)dQ˜KWí’ vÎ`'®%Tr˜ya† $Û´D ‹.9]‚ Fi jŽ[±XXôZL[=f·y’Að=Åb|'ø¶ 9ð`u¯,HÝ£qµÀê-Î>ö€¦ª’~É<ÙQP°G…Åݼ&íâШ¨!m!Íõ=h²w+éÇT‘I‹í„Œžåâ‹å–£tœ¨™>ótÓ—ÒMÎ9y½'0æl³Avºúâ½k4ÞzÑ"}û¢ÌêžDºÊì„û¼*}H¢³ºeO[Ÿi¼i±p¦àp…H%ÀÖÎ3§Ù5«WÃF^ù(aÒ=‘ ©†€)¨t÷Ú¶Ñ‘ËhüºÀÃd8£•à‚¸omƒUr«†õ¨Œ5CöšÓãæ´x¤Ò¹Ï€`ŸÌóŽÔBB >-b™æ“ŠÂv õ—-‘]‡fGª‡Ž®äÅh<ªHÑ Vøžž¡ŸÚH¯åS²}8¾ÊÅ•)ëQV†Åí4ôúé)Àypþ r‹:;_åN¢_ -OuáIO_ƉҾZ*@'Ý=éƒq˜DTSYV{B¤ÜžÑHLg<áóäÌØ¨“眯陔‚К ¶ kHý³xy‚´8´3Æãµ`õ@.NønyÜJÀL“¢‰¨ ßž¾Ü©G_Ž!}9¶AšëyºòÐtê®›R˽µÆT.^Ì4Ï¨ÙØ{™ø°÷aã2õ\OÏŠE>[Ø«=‘âÆ.~1þ$xérí/É -¥ë:v8EÊÛû6bc ‡·gbó­§F¾˜jX zù†ÇvËMà ÐÈU.Þ„ ð3€19¢-èÆˆìì{¸^S—¨ú˜zŒ‚Óè)¸Û£j—±l±ÖÏ,ÞDDÍš<­ŽHAW©c¼…Ý*ãw*F@G8/ƒÎœ ÆøYØ[_Å«ÚHQËJǸ„'§¼”†Îa7Žêgà šëSñ@Yõªå©BuJ·J©¸ö˜¬8“M[½³Á´ƒ6zÜ>`-š[¼Ís€ Žâaõˆ3Œ]šè4xÙwgÃW¦¹U’ø”FomV¡hù,RëÇ…"=x]dÔp8!ô÷juÐæU…Q3OAaE¼ÔÚ {Ã(pÈ´‹-Ƭâˆî9¿­×(ñ”"xÈåå¶’Úª·_Hì„OÌ4ÆÉ›á%¯*ò\9جê§é¸$ „ÆüÜÖ5äÂfUÛ¸’ Û·qKæMÞ [zpfÁœ%èV”š:+¾çê´Y†@«c›^•j^0U‡§££9pÉ‘ÒS^ë8r%és¯=ðó¦{—-â¾\Ò¼ä Ât´êÈ~\Öw¸ý& Oß{F%jrÔµŽ33,°vYb–OÈñLãõ¿PìçPJ}ÎW|‡,½õ˜¨Wº/67úÕHD;Çù’ŒàK2ÔõzãîUÀ³Ñ¡GJæˆöz9…B‹Í¨óíÞ–CªPÍžÀœÅ=š¢wqöæÅ+±‰ ;K:Z‹¾É—/ÞfüiÙ`šgøssR™uÇsC+‘|ØhŽl¯<Ú¨§°7^?uÛçúª‰keH$¹–߇WìòxB›yÎ6_›±IÖ¡û=/+Ö)™±¬z– ̤´™êûÂq!5÷“'Ì.ÇðLw*⚪¨2#'·9On^*ð®OÉ@ æÙÎP½Ê¡³Ê›* ES>vAßÄí©||ÖSÕÙ¬±¡ñc)3ZïÞ0•¬œ8«—ÍëM(r)yÈWÛT5´Ëh§²ånýxS¨}p:„å3U rbÞm-›lÑt“¶x¼3ŒÒ·F²V@—@õ%˜'ÆóÑyøÜâÙ¥½µ™}ŒÍR OÂΘ4ü‰)%Þc_„:¹C)ËGf™:‘^Aî’9ïÉÄíã”á˜gÛØòt¬ Ci1…—pá`#éQ0ÙlžÜÓg¼vÌ P$MgÍ7ÌU¥^m"‡±ErÀwÏÁèÊ[*mpŒ7¬wZZŒÜž®˜¬ÀÉ]íÖ­B›¹o”}y¨w6ñ=æl¢®áÉæìU¥y\ÏëPã”¶K›-‰Û\(ÚØ0/DÝäŽá¾GŸ„x«Ä/Ñ&îQ °^k%ÆNA®>þÔìé—fYûب„×È×TÚŠÛSV&Áæ#¬÷®ªƒÆ.;òIó¾Gt8ôº2yϯÀ†0 ÉË*NJ'îñâ»mwMk´lî.•ò—gºM®þÒžŸk$½"T#+cM̦Æ}U¹ƒ}Óg16˜ÁG9l€§ì¹Énú”eE^½1¤r‹¡ÁØg¯`㉡Â]AOè5f AœË«GŒ¥nÂ1Mƒ‡Þw¹Ï¨—»Í2ìõqF í=Ú%ú¼Õa˜ßcSR±Ö»1­rù¬/.ñ(‹Î{¹·²’EÒ‚KLkx‡¸F "9è p¿Ãèr¤˜N€ Ðm¸Ç ‡<¯{µoÛ|®ñ)&§‚#Ô æåë$,ô¶9¹¹ª¿F5ÂÞbà‹™gÎ=·W‡#v–eªR¹7ÐÏS²€wØ–ë‘hAÊ€ ª0úÈÜvïp&Û%rF†©ÞCzíP*7 ÖµCí&ï¨vÉp‡üvA½f^ó1GØc}v„§²µ|õòqÀŽ[&D*)¿U¹s: ‡:b…ËêÃX1QäDBm‰sͪÎçTO/ š=T¡Ù¹7Ë ^&XǺ¦õe¶Œ°‚º&WÓ4ôHõ±Yž9 ÝŠwåt$Ea‘;“›–ñD5®E:ñ|2éæµ†ý ¢É¦QB—,×gÌ_ž=½8H•£N{QÁ<ºwoR¶*ÅÖ&šQ“ –ŸÃ½>.¶Ø¦Ç>€r·J¢dOQ8¯ï×AŒ6óÍÀ) X 3hÁŸ¢ÝÁËÒzH<“y2U,צµom¨ŠÈ”íÔÍ£JÝy¼êBÕÁÌÙ^Ìã0ÓŠÈÂGb¨Må¦6Vö½’Ômõ@AâÃI{x‚qá¯Ûüš’+‘¯¨ç¶c;8ƒö(œÚHb–¿1çÄ3xP602ì»×Z ¹ÉÚD$ꪽ=éaÓDÉ^äHÊÌ¢Æz«i½VeúÌŸeÀ\Göq-c¼ô ©ôz êk5ƒÔl²ÀNI=LBùxñðUWoEC"­a$Ù’IÜ,®IB>ïrØbn w[ý^µS€à›æ‡cÄ!¸éš#1ü¤ç /hˆh$ó;`!âaMŸJï±õªöHÂy@ܼZm¨±šwU ³'žp$O"ìK»*°àZW¿V¢ñô{0þ̪ÖÎ^ k‡=lyÌVæhÙïœh$´¤uÄ_Œvûé°4;9>±u{HýÞ)m‹úçžϪ…㨕ª©‹èîó¹Ûæêǯ*äÅ–"¿º™Fª¡÷êîäŒßä›ö8±”H6w§ÊYÕåŽ7;@ÚÆêç<;êä|r@gÂQîGÌ7MŠõ¸Fµî$5HD%Á«=åÜÉÍ$%Ÿ [‹õ=²æèÛd ëÆƒë™dN¢×µŒÊW¦þVR Y5ÅuÙ{äŠÌW¢0>EúžÐÚÍôu.v†×xK9uV gû#×sÛP$ÏåYõì9ÙGÑOÁÐjÇ‘– 9uZ75.ñT©4e?Áp¼©‡ÚfÉ™& @,h =tô[¥3P±¶’¸Òp£v<Àœv^l¹Ø>’¼$œ‚w‡¹gCº+Ä£½N8ÔÎÔü.­hEÊBá 2ôùꤓÑdIù”9OfÛƒ:xÁ#íVLhMXžò¸I_AŒbâØ&-}I{)ÅWÑļiZÔrKLƒÀƲyöHð¨»cͳýæµl®C§ª¤[ Ú¦ô ¡5¡ä>ïæwd¢ïaÁûé”Ñ{~U7OA3åji¤æ!#¦‹Õk_‹¤;,€}¿Ëm’ñâ¥<= !ÄèÏö½·âË“Ê÷JJìªqqˈšYû3@í[‡Óˆ«Wº ý´ršêJ€«ÍÌÞ«Œ’P‰sU±z¯†¯ßÜh÷ñxj¦spoîlµhÃòùîòspŸ·g4¢‚%j¼©wó˜!ϳƒGÒÁw™4$ðá²B»xš5k€–ÔKòÖ:9 ’V˜}ÐüŸ¾}DI÷´,À¢’Ý»<*E`nÜr£§R^Ct˜úÀOºE‡ Ì„¦ß>z(í"‘¯ü ñ3‹|›…ð‚Ïç ÓÍ»× üI‰ÍºJj ÕàÊŠœzkå.ÂksY~÷Äé$pRÌZ+öÒ/Þp¢ÖÍì(IÃ+5mX{Až³J‘œ[Mî½D»,vzÁ[OIeðË4…/Ó‚Ï:}1…éqëÈë¶ÇUo ´Wz˹ÃfùÜ>‹—a€[û‚\o|™hãáDtø$ÏÙä2[eyßMÐsO3SH’¸æ«1úK5Gjä2ÏÝU'ØÄ>_¸×йÖ5”Ëñ-gÁD¯ZLXüA Ì4Ù=ô7ÇÞ¸8:˜qo–üA¶½3Ë¡0«Ù|m/:ac1›¯vO‰®ªåñ«ÄšIM•gWg{½iݾ º'[c‰ÕôôÄrÝkƒHÇc¤y¯O‘@¢y¤vJ—ÅÁÒzi($¸ër{û] ùà(d—¤ÑÈTÖè…h`âÇò¤{¦ycí:B¡ ¡·É+w’w{bê¸ 7‰.˜èÛx/äõdjE?piÛ‹Úð'Ü›ÏýÞøî>£‡„ê%Ùý8jpâxonÚ³-·ºXŠñWnKnínû¨T/…¡”[žÄ«^°—¹\u†xÓ–§k]pχÎMù]ódqÚ0 Ê:1Q#+À2/ãÈ”CWqSØ{² «¨ûhl£Rª`ܯ ¤xÄ"æ„•–…yžûë¦f¸Z)~ŠÏ FP Þkò†ªèâ)‘=Æ5Á‘޲£:`2;»#ãëæ‰7ûr¨CIÁ{ÑT$×4šWM8)Ž(_±Ï’gê{sq*}—"D7jyÕÖ¶Ê\³Ÿ06@ZP1¡­lÒ ^MXt{ë2œDiªÊa­®Ýñà°“@-³]KÙC+WÄõS x6¢RiªæÈÏ.§ŠíÔsMhÝ‚\“ÎàÆV)O?Uó/ÕðÕ#žîPéß=ÉÞ«=Ÿ–-$´Àj N8%кëWAŽMõÀ Ó(z1f¨n<óìéÈðtZ{î¥=S+·¡Á9:¹Öy‰î[ã=÷‚¶|ÕÌtôÄøŒ%«J&ŸD„€±Â΋ç'„Uè!óäÍ+¦=£5àýe(q×ö©ºá‘ÉY¸‘t¾d;›¤âx×’Ë®‰±Á*eN…hZά’¡þBìÞˆÒiïqž¬"x±ú#mÁ]Œ&Á'ïp3)çE>Zɹy¤Ã%šÄá¢É ^bȤu’­ ó>¢Š2ÍܼàL§Rã1¢ìµd0ýÂaíý=gXl~›jYgäÒ·-ïeÐßž¿¼ÔÒÍg”y÷tZœ€¡¯ !¹ìFªÑ“ÔÎë`ór«0óΓI^t•š«€7;cWÎf`« ÕÀé¸fiœC¢Œ7ã˜Ûnúx4h™ÅÁ²‚/b ì.›&MЩýAØ&ñF´ -Isï·â$uhÁ¤sÓÛ25ª=‚õ ¬H;Jh€œcåæÚã"¾Ü7á<²/¶Ø‰šsvSˆ|Œž›ŠÆó¾•©×¸ñnÂ@:££ VçL^Ð…Š:U£¾—@ìAôÐÊë'ϼ@Éwïm"n€_‡wÀCn O­h¿qÏâ1@Õ[±FÐK5VŒÆ‘×õfÅÔAéRž—¨¼ZhprJ@‰µâ{d¯¹kÑžÜ+°Lài;ÓþzV„s"H¯ïp0›½ÂÌÚHµ}¾\3ýtmw¢+Ñ"b›¶EÀÍÞÌa³ND[ÑXÕ’Sn­VvÀ^’t&îå$1)O½BØœwƒ´3³Û´µ†Óá§/§=Û«À–éiɆ 9 €¨ïá’{>‘ÉNcRDmkÈs…ÄT¡¼Ç­£•,À+­ŽÇñ2™«\#Âú€˜á݆ "RÛ£&]aWÉ9•à:Ka-‰ðMÒÛ"ˆ}0¯2É£U°(u·‹}µxô¼wÚ±Ú£¢jWó; gÓi¸ÛþŒPFí¢¬‰™ Å: 9YøÌ+Ž „âA4A{5·náþ´ªŒ}u"mÙA¶Ð±_™éG{ÈXá!ûÑïFŠmn“_æ.´ ˜ Oçs¾¶V®DVº&PüPÜGTÔ6—v4wüÂm$Ò:’‡m–Šà)<~ú`ƒ–å;k—÷"ܰò) @*OØO)ÇH2ÕâÈò2iA<ê˜!À ¨'’›ëáÍ=óöæQéå­Z³â ÙÈ¥È× h”<ý FC­ŽlfŠTDµ¨Ü&.¹á©‘Î_Im`D?\3E©…|ï^ÎEb»4qè\jð<~ âgGH ¢£BÂsÐÜè¿Êa`Æ¥s\ÃTQ5™1öHñk•)3œ‰p#WÖ’Á~øX”é­rl¸Fò+ÝÎ+xàav¬MÍ]ùlº¯¹m…O7$í"sGÝ"DŽWwOâò¥)>´+ƒ§ !¨œiÉ!tI‚”RN Œ\ -ÀIÖýò@ÃÐ'·§–ßÄKÌåÅŒ"OöÓ÷V÷z MÆ|“Q,¬Ðãux‹qÊ{1ä“úÆ·Ìè Ç ža]ˆÖ¬ñ#© ¤ËòÖ‡U³3,öœS7´Ö2_y¥À!”2CAK›GÛ;ˆ&ðO ’NM ˆ)[ßPÊs{ã]óòÁ!˜ätºÁt€6ôY×"†5¾†V¹q6¬Ú‡€ö×wÅ_¶}Ù{Iš-jÕ¦³³\!í(Ò©Üq”Ãe䪰ʊ0u)ɶä _%O9X-I¼·—D¯f¤p^·.D• ÖKí¸â10þK·`Z¥'yÇü@é­0,ŠŠà‹½¸r®sŒ0 íHõaZ»g<¥Çòåõ¼x>=ÁvÐÖe÷“]íºžkpõë;n„0læmT="éá‚Ã&eãç(}V÷,ÞÛéçýYž í+"h!}£ÖNi«t1Äõ¨ÒS‹¦.AÃ:l¶•„E“´KD„5™02@j†îöG_Š’øIÆÕÈ2MÔg,ë8")Ë–ÜÉ‘£ÞAÅ©bª›Ë=ïn~gåvâÌã˪Rp€×H…Œ¦oF´Lëf¶sО±È»jé‡iI¾á'OѰêú,z\±ú?'zºÐò¨’V’†éµ™?Œ·Í¯mŸ\ÓÜi²¿³’•éÀ³³¬.¡ÄG ϯ7ž[³>YÌ÷‚ëVÕ>«÷|‰¤f'‡“Zš‚ÑÁw­††VbÒ¡WUô´o%H|%Iu¡õÀBÞë°k¸‘XP‹—uuÛ^ÇóÙüeŸ¬Ad"2?ÒFYËët0’Ù&ö‡oÃiöC7øœÜê&Þ¼±: ζã'd66>’R¾<ø&tè”× ³jSÒsÓk»k¦Ð¬z„øm Àë›Íu³îäÉ`)5 Œñ‚÷Îlžs' Äk¬¿|ãûp;o´|Å^sæ@ò§«6’}úÞ¨©J¢Çî`¼çþ¢ ŽñÎb¹$í ^ÒMNçœÐسÈx’OlMÅïHžWDF¼MÝÈ›Ž¤ÂÉ(õ‹Žg6ÓØ™uöCð[ˆ°cÖ©ÊÍBN#‚Þ§{ˆ€ä Y3oR/|ˆñ-Ó:qð{-,›•!(¨!õ|pÙ¥9:-Ë_g1yhß“"èêvÑ"²†ªBÜE„}Â㫼ʲX½ø|sÑý‰õSÊ¥4 ÛÛ»ç9”}ɃFð­â=¶Ö}Ѽ\Õ¬ÖVJ˜šË -"°%Îçp^â#ôdƶ|G¡ý¸Ðž¦ÒaCH×…QªV±ŽM#q¿Þé°‹¶ˆ×±O%ñeå)»D3Ñ0qdÛUôóVgxõì½L}oÎìøŒŸ íÊkÒKå!Á†hÏéˆÜ}£ø:[Z“ëw±t+¸ˆã² Ðeºï¡’p0¡^Ñ3´HqRšÈÇ2– ¤Õmñ¼úUËH¥óKË,Ée^¯H¼N(•Ù÷ädŒ®k;¡úyI=[Ð çb˜ ê㖔ͤA³­tüÐÏouîi@³Ã²ß2h¹t\Ožˆgà –6f£¿ÜI+€öE- 3¯ F*6([;T‚H ƒ—¦h.éó¬4_[YCf Š•p`­\ª~â«’v–I‘MÛ^Wkžž‰Ô0íœBÁË‹á:}Û üÉZTÅÂÒÖ…C›÷Í×Ó^¿J¦™‰ÑÕÔÛÆ@pýèPXJ ´²]x5Œ“ü*¤wó°p®Þz”»âH#À\ƒ¾ñÞƒÓ¸z8ÐlÛ´¼)jD{ønYtá!X¢…’\¨»òÃX)»…<éN}}3ª ‚—ýAi‚µ¾Ê„„r‡VT¾g<ØS£ž™ÕèÙÎ%Ty·Ö3õË‚7`{·jŒO=Ô„—ÜêÛûˆ·%9î¦$k4)(ö/ãä|» S†”³fò°ØCº·cFàÞt.ŠÒ¡3$4†¦ :ÖRiâ,çkpË—žˆ4ü2ƒµ‹°ª™t(«)Wð½R09çtªìl3ì·ÕÆ“”ØAX¯ 6bÉUáa‘ x1Ü󺽄s„sºÁåj¤éX‚zb,e‡äøkæDwГgZïžÐ*æ¹8Â<2qrŠ\…;v·¶ydä¨}!KÞQÃqãPnÉmˆ;1bÌÎoq¢Q©O ð¥]Ff äÃ7Ì­µv jŽV·e7ÉTù^c¾—µ 0=+z#­—ÉOP–N:¯ M¦èRY2‚¥ü S#|õ–­‡Õ„c…}›¯ø5½5“`–ª§ÉÌWÐSï"} ûU¿e²T„˜u¾M/íó¯²5ßeÀ-*{=¤Ï‹ÚðñÎÙORÝ¢7¢g˵ƒDeŽçø^I0fmÎ[íÐ…¦1xÅÞ´wk$:bg)¹,t5ZPšÄùU€]²,™>§ù\¶(âR ²­° ŸºŒ²p^E.»@îVjÓ‘Р÷ hììšA'Õcª7Àk¶nœ¨°:„ô6(o«ç“q­'$ÀcqÌ›V˜¤ý‚póЇAV€²@$Þ½Üh²­©·["36öfÒ‘&ÜïX¾Œ#þ2nX…kɽâ^bÓJ˜§w‹±áˆ:$eÊã³gÔ†½™e$ùü5_ÏfŠ]çëÑ{H¡¸ÝåzÈáX)µ£YRÌá‹§íÔÚ¹zì,õÚó/åîT b!”€!¶ù˜82L…•D·Î*(™4ó ¢i BÊÖé›Q ¬gï"ø!Â)D%Jýˆ0×(´~Ž%¤†€­‘\w¢EÏŸ™&\Ÿ¯Ç‹öÍ1³I~ï¼Íµ¶¬Pëuòòáë½xÅôtœÖ z^k°ÜXùA§å®Tª–ÉXv^ÎnAumšXÛ—«ÀÞÀ»v.¥wŠ{19¨/ÄêÓÐ)ú©ñ8^›Î¦*Ž®>·æ×ê!í­ku3?_7ÒëÉCñÆ{ò^B>2óè$ÃÓ’]4ÄœZDBÕí3­êÀº.…qf†Úìή^j2“Lâgwùʦo©8¡k–¼ –ûŽã{ÛBŽ0DjZúÚÖ¸N‚cmäÑ$q¦a‹i'û6^‘ò XBo;>³œF’£(²¾eXèYynRƱŒ” .®©TnîÍÙ›ÙMÎÔfƒ$ÑšÔxŠÝï† N`Z Š%…Ëã•ßÓÂ[2JiÕG<¶¹þBl ï”LÀË쌎°ù´ôöZN„ºžo‚^ÓTj“‡Ã¸ƒ .K$ŽTÔ[}h‡fAðÛÜ)¯…×[ÂEïFÒÕ€”àÛKÈ2¢¥ÂÁ&nØBô‹F]åÑgÍu­®R±ÐN]ãçª0ÐÊSúÞ!8» ³eààÉÈ!Ú¾]_j¡ÈZt7…Øö§Ãss‘ªc]_¾yÁ@g9·îj!zyf êÁ. Dª-=t89,œ÷ÊkKÎÞ¶£W“ö*œjù*óTöTFt¦â˜„KÉ€¾|U3R!ñŒýeT6C‚*oH[ó‘&Y  Yê­´§Ãô{„•Ó»¢V©®…pŒxà7™ &¯ÔØìÔ;3Ÿ„<¸GçNší†..{kvÇOðæZÎZWåÅ“Ærß.±~3 D3àÂE®KA×y9À„™[li•ò:go£¯äuÈfeÛá Š,›–ë jPÚÒèÎY¬…qBFm‘yÒªä^bg;¶Œì>/œyÆ^á]’È:A=L.šdrA`òéÌBMÒK¯í*-­ga3•¼ÙF¾Z¢š&”`»… áÃEêt¤ÓŠhuÅrû@³Ê=ÂÔŸÏ`ÝC d ^â#9~|9˜ÃÓ®÷ v./»mÊÐÈc4d.§A<c¢¹f#΋¥sØÛ¼†ÔA&’Lºœ@ ™@¿œcørÎ ÆRîi¿IœëËÏrvk2¾œ÷´ŸmÞ±Š—°5N_–ÊÁ³Lñ{²‡šwœµf•Чâ¤gµêXR:’¸éಔ=ÒèæùK8RGóèÁ_Ò¹÷ <6÷©Ê§Ï%8ì -øqÜKÇî4ÖN²GàêÐËÙÝH@¸¸—s6M 6d’äâ åw {±ÄòÈa[I^]ãøŒÑgM_1´î¯SÄãÚc 2NýejÎ5íH¥èÇtCŒYy]$P:o_ub<ÏV<öF0sÅh>wðx×ÐÌ JYÀZd”qƒ^nô6{Ês0`F|C«‡_E\=ÅIÓ³‹„õ§(¥Ý««ÑûÖˆû©(¶‘>ÎYnæB¼^WòxóC2žVáÒkè ŸËa\°í9™òi|%º¨ýXYûa‡«*¹=-9yFê wËú¦¶èÞä!¼!¾>©„ä nõQ,}ÏÃ÷0áˆê £®Z^ f²‘Ùñ ÎKŸ Œà çý4ùÊÚ+ŽÌаÒÛÚÝæã“³SåF‚;²ö™N"âÞd{oŠ›ü¼áAÒƒ5 È9êàr%ˆx‚œ{Û|L²Ø»oêΠûô±®+Ô£ó$ù·>-r"åÀÆ *W"xG¯Ý iÜ·äNRã$c*Íxó=Ç{Òè€ôžâôŽø ÚyKÕ¼•ƒ#sp9À‚)Ú$Wà€ÌZ’7ÇLî›®t‘e~­àdÄhês«hk$ì4§D&ð%(ÅnÞ»»¦ÂMÔ¡Lœ©”rÈz]½x”ó)I·Åw{<,Vm†xÇ™Fô°“$O‹–@Ïë\bÜÄË#­çý¸-’ç:é¯räT_%bÊé)=½‘ó‘ײ‡þòõ¶¢”@[«ãš½Aˆ;ãÀ’n" mùË:‚óëôj&ãÕÞñ듽µÓäwÅVù’s‹óªKÞÔI«pÓ\ã=ôä$ â•#“ÈêÐñŠhC—’´~ÙKÕ“‡û¢u÷Æ¢Ïcè^ºS:hÄœ©Ò‘K(l©šŠ‚Š\ö˜+±=¥—¹a°"hêvnyœáØvt¸ ‰ x”/Öc°•vL°¢ÐEŽÒèe—#yÅ嘉ÚÄÎs€/}R…+_/·¦)rW4d•µöl”wQâ>HÂ|ÏèEPξ`bry2)·Çl=¾m9nÓæj(X }Ìاë5ùtIÑG¸J€ß•°jT³GKÎnŠ/Åé\t¦ö&RX¨M«Š?¾™wÊð^r(F,—Þ³…«‡µÆöL‘(ÅBX täbÓ %ÈÆÉó^¼Í¼$3À ŒÉc⺩wyP É îÁ5Ç@®Ø¦*Âȹú0nVZ•ç`V¨sCpõ”Sƒ0ÜèJg Þ»ÖI0ζ›ÄtK}¯Q·g Uü ‡`ã•Ô—u¢ŸÖù¬Ò˜¸¨4·Y2¹"õ8ð=èwóôŠ0Z:!ó‘faÀʽ#‹{oÌÖH­ÑjɆP2’÷Ñ)‡’éó©œ jë|ðHc‹îõyyðf»ÿ¥ÝÁò¡ó¼·^ržYö xëŠ öqѾõ쇞:Aë%ss\pä(vk£,,'dí ò”´úIÐë º†X ¶yLu+¼÷øJÂÍ€ÏúiGÆc»—@¶`©HÖà$¨ÎãíÆ+viRœT9΋¦Žg&÷bôѾ¹FBͪêöR‡spLrÔªiTVaè½ew¼^Ú+v¢EdÅ’Uæ—K³ÒLJâ£^€B Á–†\Ï,ç…“D<ñ³{ÏEVùÎ}b) V_Xö=Î> }”7+†èâŽ\ÎÇF[=ð¶:Ôð^¸tÄtVÐí0̆åk&™çS;ó¸ è™áÎ%_¸ÇòÊÒ›Q¤á,~1üVuŒئg<‰{ ¡²î’‡´ÚÊÒ0AÒ«rro µA@ÍÓƒ.ÔÒQËTš Ž<„Ô[Õn¢èC©B6ˈi–Žg.:ë"ýà¥ì¶MBœø1ÃD/0L`íÆÂx+r¶Î بSBUw™ÈàˆFÉO^¢¯²=mœnˆ3ë͚ȓ@Ûë'uëŒPÏÔŽÆeAìÑ´bKÐ9¸ÏNB—i9)¥bmAz] é N™¾:Æd•íör³kyø"H†E·!`¶H‰\ybŸP½‚€@Zàª-¬yï9*ℽÜÇvÝô¨ëàK;å/íô±Q¬ν2ƒ6æT]ptKlmwÔ˜2nÓeÚ —]dš£ ƒ—Vóö•^El‡±A¤eí° ¹ß¹¿%î$l;ÔŠW æ5o¨Ì±uÿò=Þs@åž±½€ìl”aê ˆ¦»7ŠH ßÅ,âZ¿ŠÌ”c³§K±"qñ¥ "GsÜ,üõ;Blí]Ñ\•ƒRn–Š9á§,ꧤìÛŽWêâOœúô•€-pFuqø{hÐêû€¡ühb+éùÇî¼¼ Ö€$“ÁÄÆ¦8Ãòéîìæ áwŒ6¶¬­|Å,\o¦,¡°\r»æ‚Œv¯&Ýq(kÍr:-I[`Vyö0‡"-¶ã¢•=DnD7Ó›±¹·¢:¨¾$ ãï)šÅ³cs˦¸¸šÝÀ˜ñ!VºÆ)ƒ%«Ú'‡Ï”%®QÊô¦_ëD¿Ó‰àzLïP¸ôŠüœ%óM»<›UÇ6¤Uçé±/ÚUî…Ô>¬ç•CÚ7ÜãªåFÃdÛk᡾ª*î/ðV -Xç’Qi?{ؼ=Lg2¯‡¥¨ ñ!Zdáy·sƒ?ua›ìî 6+µr•Ro|ªó¤%Æš·Vx¡mëùs…ݾÛž´†.ž½ »œäáww-`€xl…Z£¡!Ò¾Ôv¥|¼ó»¿‹pÛ¥î‚+s¨;sh&yûÂM_¶ªúS:{,îÃÕ’Å5ó\Â@oÌÉGkîãáDÛó€"[¥:æ?öÒ‡I݇1È]'ûÊ.î0®VvXO!INôÍYºGîçtgôå’ݬÌÚ{‰êÐdOŸ’­¾lÏwXl`N›$®"uèç‘·ÂHÆN•€ î,\jø@H:RZJ/^A¾¢i7ãgµÒÄO»îôZ–[<¾¾~›yú—x¢&Þ«Àdþú`ГšùêB¨ˆaõõŒÙmòƒQQ.ô"²ÒÉ­\Ÿ•cäå»<'¸}ÞŠijutML›o#¸»UP¯O½ÆÙß[PL•4hÒ¥[nÏx–IíÁòša[€h•Œí{ʬå Ь$µzFDÀ‚G­­+½„FJÞòµãÔjL'ðc·q? *i"~|ýø)¼dxÊeM}hq‡{1§÷AóXÙn>^n×¢M÷$ ~×´ï¼±M^s"”3猹:‹Íu ³¸ƒ5¢$Õ(*ê/öÕ¨+“ Q9wõj%úXÖ6ðZIñ‹ Z}•okÖ0s½¥¶;Àmr¬KÉ“M¬”ÌÊìÇó”ð©>ßm„#²„ ³z¬Ài–±!ˆÄ%ò–ãb¨ åÍ+q9ê`xá…Tå`k&E´ß è8¯4ÔR+ɾK#É•X°ÇîÁÎdˆiÀ‰B€mt|C+ܹlò°ÁÚoª™uŸ¨*ÚOS+’”ÛÆ•Û¶cðƒ •¶X}zmã•WùDÈ$³–ê27î¬L — |T-^Úɬ;Í–gu”UÀIVòàZÅÈreIL7ó²[-‚ ·éЮn‰’®–=\)ì{/È`êI¦y‘ïMhˆÂ„i¦ßpŠBRÌ"5[>|X%‡ç7†ù%žÃ—xà¬xÚwÜ­\&Ô!Fn+ —Y ÒQwCï&€æ·EÀ+öëòóã¼· ±DöæÀç‹K'mŠ‘:²³µ’=ŽÛ^m}j>à¸K’&ób xчM‚ ×É+xˆñˆ§Œ„µžPÂò_ê°¹N—¤ßk®åéÐ>To•½y³*W47¡…]÷ž8ž(.PƸõQˆ‘ÞÓ Õ¢E­ˆDì86ùŒTiਘj‹‰Üͪ\òå•P«G½I}VBåXN›¢á°Ô70dÊ<ÐãZfpõŽïHÑïàΜD˜c1»ž¼„U¹~f‡N¼ …oSÓ¦m==”Á$ƒ‰Ó X´+•š_ #Ëè ‹¢„šÄfXÆq2¦?-X…EKªŠŠ¬²áR3c;ì~ºzçäUdE:£H,ùNüù‹ã½Äfy£#Eõ‚mwI@gÙ´êÙȵdCVØy‰–‹[úm)ö;ŽÅ]-×ðò–Îh ÑÎÑ·¼Þë‘çy9Øe2\t‚b>Jžh€s¢U‡fÁã•îë^RnqŠÂ–~R/±\¢Ò–£):Þ…¯ÆÖÖy@œ< Ñé3µ\Êk„× ”Ù˜/( ž¿l ,'‚åpq£@ÑÙÌØwbl’ï̶ƑêaEÀœ]œËf:]éÔT0U`¿CâòJ|ý²|…JmÓðá*æÕP¼Tìz*Á(»?žS”œHFqvir„¥”Æ1’ï ælt.¿Š¾¹ä~”>¨ˆšâ»Ïø±?Õ·Á€}H“¬${…ððÅòº >ŠÃŠ:YLo!ØÐ·N¼¹'®úd01Ï—z¡_ê•(…ð>¼^òë4~ç<>ýØ»D¹• ü¬ õélr'îÔTÚµô[àè §ªô¶ƒ÷=|β1kZ‚ÀGWÍòd»v«ß«&;ŠC?=²u WpUz¢¯ÿtïê' ÈëÄãrÀë2ySË’÷Œ#A®)çüOÀ¦0!¹´,XXÓé™Ú˜æÛ%êZD>9ïGUç“. ð”Œ<¦Äµ!ÒeÏÈîÅ«¡=¼žF3[|Vüf†IZNF]†ßÈi ±øM¾ãìíiâ.[=~ ×§ï½.ŠJtÀL‡†ó$ö$| •J£´ê1" [ðžºùëzt¦’"ó@ÑŒ;óºô“ó f&860¨ÇëÚä8°8RÒ{ðX߸®;!ÚÚ”Ôð=•Ù›)—è°&Б{þÔîžë«x‹–‰AŽ”§ÛPX2ÝÖÓàMÓݹŒ»tå+É™“sTäׄïÚ°\xñvUÑc‰‡î~þ¨ç°†]¹¼Œ`™#‰ í6OF9€Ð[%Ù书¡¹ŸÕM¡Q!9ÆÑ˜<§š¸Ð|(˼¸ì7bîCm!üÔé0ž{÷Óí¸µõµ` ÆÀ{"M#Ê—\¥4-r¼Úþ›Ý²ŠˆÕ‘·VIä@"Ÿa^ñ«Ês£óWL!ÀbSVš7øN-6/y‚¥â5W­Á±²Õ¨z!a¤™¥è³¾%NªF‘«xêí+g?õH€,¼@½GxÛ ¦o¦uTô­eæë|ÙÛUàγ-Ž"âãwFëîðç wijUåÒù1­Bïí>,LÞì):$škõf¹ƒ÷VÈOÌ]b7–{¯8|ƒõY©Ig;ŸòÔ›ì[hœA7æ6îힸåiB?Þ,?*a¦d›¿'>­k(|SãšÝ*^‹¶¡[vãJ87¦eyo¿H€'âÏΠÔžBv4³-ùÆë¹ïËzÓ¾ËMÏ|Õ)|;‰Á5®D…ÞI±œƒ#ÜÖ¼wGbÁûÂÄ7ÂyÙ”t7=‹¥‡–ÜÞ°›DºHÑ$´§Ck?•5]¯gY\‘:áNn0MtŠù¯ã ÕJ;ç)Ë–áªá+œ(qâ@•—þTjåáˆJ‘¡ÄEKÛåvßâ*icGÚÚÝs'U*p.'« ]W)“wko_<]¶½8ÜDA7?5Ì4¢dÆPئ´¦æž§Üȧ¼ÕyW{ȶñ$µà¡*¨è¥AX›áŽUÁ”­1ßöè3§éš˜4±7f級¬…r¶çΛ¸Bt©Àù )µŽ•GÜh{fŽ•\’ÁÆüÉñóuZ¥N8¼9+&X”‹iPÌ'å÷<€¨t£æãsáƒ3¹ŠnyžÓ‹ŽSê¶z/G[a¯2ŸXr\ ²gÙ.Mèfz@˜Ógxˆ Э·DyÆQú¢€“´ ‡6SKäEN¼q¶ãäë;¬òÑ*Zk“@JpMzÊ/f5ƪ™NÔ¯ L÷¢ŸRu5ÄÝw¢EÜYvâ<¾Ú4ÝÚ›>¢šÔdzQêB)“þpg ‚²!&ÆéIBÕÈ¥ ˜!Š(î­5r! >£ø’éK>4‘¥¡•ÁÆeÑ’&ïŽQUp˜5|Ýhú§/©xŽ”'r$pov­‹¶È_KnÕcÄG¯Ôh3‘¥IÐàÞ. GR:›* ïÇñÈx™ÓÌcî?í[2Öž÷â= |ËOoZŠPêÅÀ#Ýw: tŽÚ{/¯µ­"ŽŸ7­£É¬Ü—‰–³¾ ´zœ€ˆŽœ'^ í%y1Äæ9èHÏ^ÅÁƒ¬²¨±ºçÐÔ´Šk2V‰øœ¥–_•¡?3{Êåð^¬?TP¯¾y–µš›º“¯Å«.$Í,EêÁš) „ïÅQLâ"V¦ZÇHh¾B6 |N4CsÚ|#"+Ò}…nä¢ëÕðAñЮ î¾%ÚA‡ƒZE}•ËÔÜš6‰$ ¥Ì‘Ñú”¤÷zÞÅSÅA}§¦ÙÞNÀOO¼ºŠNñ^°¬Ú“×.ÜýœGÁ¦+@SßDfRp×»`í#ƒ×þŒì2;/Ë¥ÕHÖ3:Ó25<Ð"Zê´Ü…DÔ8)fs‰ j’„VŸ6 )sTzÈ,ÚCÚ…‚Kõ)ò:$"ŒÃÇ9ô&~¶ŒÆƒ£%û‚›!`å2Ä2BEyó«ÝRD¼Sa¢âÜ¥a;ê~€UË”§†'Näc:ÖuÓëÄäF{.ƒ‹Þ› í&*ËžÈúà¨vìã9wŠ¿|j늣¯²5ùEVƒ=MP©šqÕ¤g áa÷ziS ÇKL]]RÞ¤%C\ë!áäÓlzŒq$ܦk@|yÃR»ü‚z¹C}íÙúÅn;ÀYù>ØSåJC^ˆ^i>°Š'˜ ÞûU'™×;9­›ƒõ„jð™‹M¼RdâTuš`:ž eV£íµÄÝ¥Ýc-ɬ|Ç ok-'R–lž¹ö… ×3&àynÈò8N>õó/ýúžøëšîj4ÐW¸6t°º´ rc¶Ä+ /Hž,Û‚€Š]¨ãæDÖ@¾Ø+eSJz}–·B É Øú oÝÈÊñ*"=î¬q:íØ£•ßZÆ^¥NH‹Èýå£Zõ» )åä´ù*b†‚ƒ™ø¶ ë¾Î&ÂâÛpôxA5/[ãàÆTJñmÙ>M9öëÚ×Û­& ä4…Ît!½} ì´Bk›Ð¡wFéÌ:03¦$Õ"¢®L“tÔía…<!ÓωâõÑTFêÛ¬8 †ìèt»•¾K ŽwïÉÛÇŸçJHׂë3}hO’ZõU—áH°5m3†SY`òT¹ž]Á{„°|+>½F¢â¦¶ÇÆîÝ Îٱ݅ã0Z‹nY!—u°v¨Ë;µç–Zm¨» :Ð%Ù/ÿž~ùF×@a/Q*Çè‚p¹!^…Dœö5K×sØU×.ÙŒuЬ¨Y}œ…©”!Ý F=ogJ<Úæ¨Ô®ç=ŠS,LfÆítË÷ÚOd’¯*Gú¨HÈÊ7üU=Lºœmz ¸Í¼²xJñd;Y€ƒsFsϦ°±ýÉ;|ÂÍOucEÓGjèù«HàJ²‡¨¡ =áTZFA6´üÞÀ½b ±“ê ‹zÆ´´Ô8çËú”ü‰åÖ³FÅó ÒðGÓäÉËá¯X!%­#ùá»}QEh,¯i¥·_ÃðH#j0íÃh3Cj@Ã}ìÖpEôÊNO›‹5§©²ò.t©NB=¯÷<²:;ßðf7)°v6×ÛE!ØtN,÷°´}Q±7*ø`ÖOƒÒñ¸7‚Žo±'˜_ŒŠ`§—†¤Ѷ å$q¿­cr†f*ÚÇrž V#¢8Å0ª“nwGì±yé󤟾—íöൿô§ÎA Z,LÜmȯ:¥NgJ‹.YnŽ¥Bk°ë½Cmt~áÒ’^Xô¡èɽPa±î:ÊYbëy†9~Û7Œ†½úuêÎAÔlèÜ=£Y_Zœ'Ý'²¶ŽÙ2chÍqTƒELïá–*¹¢ŒUkÌnô;„GJÎþvTÞ‡ oHß -¨EwÅH§Ä)VT…>É5Y>×èò‹òÖF•g³6@ECNÛ/œªÊ†²ëzl6Þ:g‡ù˜÷ºù¼s|Y‡‹%è 1écº¨Í6Ð8Úe°¦zrïè=U¦Šš¦ŸÝ|£{ýàšW8n:µ.e}˜æyo¯ÕËG‡8,ÃÊ}¨Áñ\a Ç5)ø5¼U+ŒIàí9›ù*uHt¤ …¥ð!•®R.âC[õè~›ý ¯¿® D†%X Ê—ÇÜd ¤Ó)j\Áa‰à¦p„cÎAÔkx˜FMOý ñ%ã[ª¸ñÐÉ(Ùç©#{ƒCW äR˜'Dó8å±±ŒÖøê€:êúùsóh™õ£‡fÆÇ÷Œ_Ùªse ׿*GðL{Ö¸ì¬'FZ"ª–ÕÓÖÓèb ¦%×™¥¤¬nÃaóhRšéöÜ#˜ñžž•Qtr©šG…+»¤YpNJzŒ‹¡G—:¦FÕlU™w4uj_”«_ÓYé«cy²¾ÝÄÓJZx/ë¸À—(ºLçºÇ£}gÚlãH¨fûÉÔR¤TUZq[PWIŸNWÓ¨S ;ç€m ‡{Èo“®,.3R޲­ A²°ç9ZC“.à«ÙÞèºy¬|(a`¶o‡Ÿ8ðô܂ԼX·Šz2qäýh÷|°„¨n¾¾çv±¸Tó–߀ —€ÞÑ.v7ä*J ­Ú`œ1Æí1¨é;Jx8!>{+}sLÝÚzòh^×¢oꊿy ‡çM i !Ã9ïµS²_¥s:çÓÑá¶7#J‰p6½#@®ÚÃÀw{æJ'È…áá¯Rßñ<_Çq¢¾ú•ÚôDq++ÜŠÀ щÙñA”åÎÁó3u6Tz¤o:óËBçÏ©p¼u™£Ÿ>>D1Ž&öFëAö2B±¤~V硱é¯x´ÒvÉ›|‘CŽpH¨ôòS. -m<£ Šæ§"]e4ò`\aL(öõ;ጧú–‡`gûÑó’ˆò)qˆ”Ð_’/çc ­D§|/zO8_±’ªc RX6UCΈ։µ©¼ÊéF~¾¯ÏPtÏvx3œïc:Š-ÞPnŽ“¥¬‰5ÖÙ>¾jð`¢ì«EÔ¤}î¡ÈåX3}úJU<@15ÀžXõÃVä^&…Î;Jn‹iÙ˜à`¬´:Ë^œ+—0Zu/rП´kÉI“½.RT{¼Itôø-)îó¢p©ç€aĉ»ýDwµf=ë™r¾”—¢¡"¶z#0-ËTºúL÷¹O4r”ÚF pÄŸø‹xX'¯ )‘øÛaÉ zÄ<·óºŒ©±æš†K.iRj¾,8ªiŽIÞÒŒy×Ñ•8W¸ÉÙÇê#x“®X>=JLœºLF‰ÕGžåæ—aSüÆ6V÷½ÓQæRÚ|PgâË¡5(´Œ†²š9cª‡×Z2uÇaFQõ (nš«ùD€^hhôiˆÕú¥Zò§Þ¬!)ÃÞÍ(¸:ˆN&Bj÷jH¦§£,?$ì0\nÎw-«[dh0,/îå³dU9´èÖvà©+Œpä+A«‹—l4«ÇƒShÚ;GÂGäò¼@圃szú "Z½—˜‚[˜ýNÇÚÊJª±Ás²†Ð0ìQw{Ň>‘ð:…Ïxìœ ÉÖ]_/¾ ZØLצ©Ž@ÂÃ/ ƒ>5Üëê<l¤˜Z€ŠÞƒ~Æ1o7†±­Fr–¡§Uf§ªrÊ]R ¹%4 ¸9 îƒGîiï9Ó¥­D4´ /˜H;a[2‡`3À£C7Jì ¹Dë%yëñd¹_’1ujxt7þåáíC–¤.w÷Æ+·4` -V€‚¤Ñ§sEï\Cü€0ŸUL?’ÒŒõ† R -ÙÇ}µ*èSU{€vhÜ/·š`ð A¿g°Ø×úØ#ü½ |&úÐðMQ§ï{þbWÉàµ#§>­âç2yÒ³xD;ž÷ʨô&Dª°¨ç * [÷3JÆjþž»¸a$ïC”5Õ€âuöÍÞÖzhÜVµƒ S~Ý„n× .Ç&—²÷LÜ—Qôù!»­ó½4{çKõ&š^1 ʼnrµé ?kC¯›šâ}/^ºàÖƒtJeœWȼobˆ^á9¾Y6›LòêèRÂózZœoßE íM@ÈS Sd~$¤ gåÛbÈ3ü@¬Ž³^m¾ Â+'¤ãgÑõ]¢£=c;ñÔ·púäR¨%öa(…`f*“òÌ;Òí„\CSUz:kAþ@ß¼ív€Ð'‘¸þ,Ä™ ¹ºcÜ'õ*AQ‘[é®d"ÅÉ8— G˜Ç6 p{²¢ômóí’ž7öyu®Ó[«BÏU%ë YϳÚ`2‰GJñá¡|yÈïµö™@Π; 7j}IM-4€¢+^‰sPv‰æ³]=;MÐII¤"Ø®þ$7¶s!î#·´ù¬[@¥ë45Á¯FU)ß.ƒ½gOšÃdHcÊZ¸Y^6«qEß!ù4A+u»V 2I,èCÙlÇ 7Œ²xOªûؽNEVËí<¡D’0ÛjÊÉ+Ÿàܧˆþ%bº½…VëÔ@Zªþü,SñpXˆÀFõ‚r'.^…åƒB¶$¾wªÚFcøØwÖûhЖH^?Ü~¥lS½GçÇ[îØìÊŸyà–‘lJ£ÑCm]ȳ9ž³3]èyPT9Ç¢.÷ç«yü|G°5]¡lçQ)3’ÒX·ê ׋ŠÌêÝΣ M(9ìJz|,ÄTãšb•Þ9È‘;dA­Ï­(yõJ«[Ú -MàL؉7. –[xøõùñÂð{稴¶n¥ÈRKº—x µyÚ÷5(×¼"­tZfåzÜÏžl<Ù~e™OWó(!3gõ Qò`ã0[Ê{îmQ—ÕFŸÔƒl_ª’5ÕrºÎzýú1È‘<µÛ½F:l›C;ÚTÀbg±xEî3±fF ~Ë ® ’çwB·Œˆë“Þ%Ä58kŸk»¤kæ<ŸSrï±·ö xòÜYJ¿âQá—[ïZ1¤ë•95f7Y¼JM“0FÒš·Œî— «Q$òž>ÕÙ‡=ƒÉC¬+ži+ëG®oçÖ0žT¢'ϳ·œ]öºÓÜ­à^:ÕUÉcÈ+·Ú,Ûgàì\Å›´h}Ç1YFOküÍ ™bÞ[[qÚ¨¼•V•¬~Ç8á­lÎ*Uj­9w³·]˜Ó´D&À0`׈´ð—{\!È_„ÜáYQÙNñã9ÀC Êz–Øl«Lâ+/œ65Xo ³«Ù„28^ö=[)k‹îpYƒŒÆ{[oD_@â9^;KÇR\¿8¤Œ„YRº &m¤·íMmïåÚlf}™ˆúe"€Z)_LÏáиµ§¢½R>7T_‡Ët8§q>…¸¢¸iâªWé^¤^±éniuÎ*!sÔª·ûƒÌ}ÁÚ~m¬‚ øT†w p;J\6ý<ËÊ7='t”R+$›ýùv¶d­§V™@oƒ(ƒ²LV‡¥ÈV›÷Ý…Üø(®4Â^G×>eNŽ&«´8õÇx­¼€:YáOÑ@†¬¼€õÀmÎf"¼ªªÐž9?ei¾xàP°©b[@y3Eúꇜ¼{É ¤'è±Ö¨ù®F\#mèB›K2FWóšAwÁ»<™WJ1ÂX#¸y).vâ"Ï:¶—t!F+UŸ£•Ä\×LK饔Êcz· ´áÏ­ÃrÇæ²Éx¢&jF¨Ë¡3kЀA¥pv§l« Ÿ¿ççòdÜrH/†m€­ïtyû='¢jKÜǺ]i$FóÎ2”pÄ8#","èÐ5Àž¤JQ<·[ó öòMß|˜`|É Ù†ùòõ¡Ö¶sI‹NÓ3­ÁÆ 4ñæN)\˜ðWX0]'¡Ly-å1–y+eò fì,:Þ<xå탅ò°"މ%„ìJ-k¹dëMmWÀª ¼ºÜÈÞxÉælDE,ïè£tuƒd²9Êü¡‰y}HfªÍ «› ÞT·ÏýH'¤¦0Øj÷) µ£?É2ð—+=?Hw1 ®TK4 cÌQÃ"ŸßÀp…`¶Á”¡y9:ZAmg÷n˜Ô ]}ÏßÁ»vëÕÝHEy[-Fö¼Ð˜©½åh|­ÕÀ^é-1®ÎÌUFÚìG ‘‰Þá¼…’ÏÕdTKŠTS™ .œ`¨ÍdöÛ±s/Ü©9¤7@MÇ•ônèp’úš¡sÝäJXå¨ÞK>Ʊ¢©ÓW†à2³»[ZQçqÌÄ'2“ìÀëºTá+ûY+ƒ½Mà¾÷n‰Ûž(¾émÓÐëw&½åô| ‹Ö$ò)Ì=›ß1½iÝÀG§Ì,ÞëOcÆ;cÙçª(*˜ø¸?»«Ã“0Ð@Ùj¶çêièGî–Ùî>ÔvÛ×x¾Ò7%óŠÚ°{ ¡³Ðé2Ë™Q’#I=ýXLŠ5…ù,øáÊJW Òc8Z~¥³«ˆn®IŒ0â½²§ë̺ËÑ=”"6npc!„“Ÿ=a™$î/}¹¸OÌa+,"‡ÛLž Ï”úë{oï©Ê#ëãæ߉®év=Õ8ôáÈxÊ—N)˜B*¼m„U/³B¦·8]Só2ž“N=AÛ ¿÷ö]¥ ‹*ìù«pÓìÎKÊ·$áÂg­‹ I¨‹ Áøœý/»\˜$±[“/u\âÕÀ#PW³gçcC5†OrÆP¯‚²¥ÙÃzŸˆ?áH8CIzbÐåñ¨örrDJ& ‌µv×¢ÓÎè ±._Í"Ó¥Žt€¯Ÿ= \vYYPé;…HâÌCãÀ!ò•,"]µ€Æwhä\ ü¸½¨(_· ;'I²9Á ¸8²§—Gº* 1¥~B©Bæh‡ï) cÃw¼¼Ø`xº¾z  êÇ)áø_h¬Ê¢…]më<˜É«—ÞMÌ‹ëüÙ LReYd(Ì HåŒÆiÄYÅê u·WzïÛ'~ojz…t«M(úà {"xÅ3Ò]ž®#S6$dbAÈ{@*7|…oŸWªY= †¸ÀÓcžS Žs~J¦6¸XâÂwÖYáùz¸zèaù2OºóU…ÉY!M„ oÉsÇØ70ÕSi=‡uÉA`< =Zù^‡÷ÒÄ8Ç(ì¤?°‚ˆ\sB© €‘Ãz›¥s(&cCåM¯¹Dh…Ø2oéqœìd¦¨’mñH¿×?ÃðVFoHœ<‘Îë•®ETiäô žkmÛöÍh-m=,‚Œ5Ç<Îv‡¿t„ɨ &”›cùôWzp8ö[ˆätæµó•^&аZ´…ÍöÎ3I²â1ÂÓ7ûŽ3éƒã¶YÎ eòÚÜcm#Ðöìí%<{ñ„ŠöF™ÕÍÁ¤ÄÅž°a¢G=:Æ>hö† ªã ² ÙG|3µ™æ:Ûó–¸öuÝ*K[Ÿ½Ulå·¬f´ç­4™‹ €pã,€d»ËÊõJ×wÝO›í´ØVLùdÍEÕ}¬\9q±SÐ)T Ïðµp?/Ëœtj„V± ÉîÅeš¦Ìý|ž^äb²Ÿ(9w?áº']òÖRŒ%D6ÒŒ¶/¬`v㸭¯M$‡)9a6kwÞ* Jñ¾!ÝzW§J=Ø;y’ãñ^Û6öêÖ¡0ßlg/2Ÿ—ë—KólSØÓ*(3ÏÃ!rÝ$x@^êþ„`¤¸’(¯¶¹Ýoo÷ªÙmM‰êmØdÅØ>mÛ›÷Œo[cĤ&Û` èÑãnF~’o&õ°qèDØK-±ÂÌozIò’ œuläj€yS‰ô=ƒâÎÔu[(ª½NóÕ„²•Ô’õÀ³:Îî"Â'Ñáõ °Mî†ÄA¶YèŒÇ W0›C ZsžéáKÔ$`r¦Ë’¦SO®x)i½±ó¼\ŠÌ,ïÑçtî–‹ge! }_:Ê÷æM\PQ‹ŠA¤¨qBÞœßc;~ôž_pÂÛy´zï©ê8Ð$·cM/ ¬kç ï4]{126…Iéé‹Âî°7‘‘×û&橸ÀãpÁW—¨:¤û'ŒU­Œ‘×^ŒÝÖÁíëG–‰îéêï/¥eÁIÆÛ9°å@}šl TKÒòø\§Ò^<[wzz×±‰!ˆ™ü.Éf¨¹HŒëÁ{cèÜ!.>%GÏÒyãÊE&Ò˼‡þD;+› Ãæ|û„üD‹(ƒ¬ ätJ›V¹æéå«5œ¤ $MÛi¡àÀò†rJè¦EÒØÒΚ‡ìnØ=¯èžŽÂ’_úóV[?)”Gaº‚4eBIÁ8uzW} y;ó,†×µ¼=²S©2S¤Ñ¨±¤f˜{…Ï#žYR䨱Ÿ°ô¦šJÔ3Ç2÷â½ÂgµX¯|â5Vˆccý ŽR*hÏŠ2¢ÖÍuÔú–ù¹Åpíe„ARòÊó&pͶj¶IýE²›»ZGî¹eì«lpÀçGcøZ;2‡z-ãyÎq]¾>uïZ[¢1°Ý£1°î ˜v‡}yô’Ÿ$©ÓE#ZmnùIŠøžÑ{Õš#&0Gd´ý,‰üÕÉÃ{b ÇoF€ ‰;êÙ)?blø²Ö1k©­¯K,(÷k&‚•ƒ’épÞÂôªbd4®+OÜ‘9‘H•Â; îÛcšÖ¾³˜Ç·‹ï¡ÕlÖzëŽ °o™ØZ>o•NL+bôy½HÔÁEx ú¹èã@RœË b â3}\B*NàÅ-1Ýàüå£~ïb®_,(áÈÃ!ÊçP+Y#z¹-¯k^^=ØTCgfX)«!9Q¾ ´KöU @íbo¼k\\2®WlÏb’ŸóësLAFÜFx+™Ío\M‹(lÛ`êv)hãÙ6€#²=`üKÈ!k個¹}ïÉm?|˜³òœÊ|šÕ‰F®×`¡ê]sØâ X`oÕV§Ýi(6Ȧëä×(NG;ç„¡ÅÏñÜ^¶.!¸•r&¦LK43䜨¢„…𽄏¶g¥}X·ÐðX)`VVs»ñXy±Þ Ñf¸ŽçXS2¦‚Z>f¿¾X®*zOò-“i½Í„\ÙÍìSgd‚C›n/c.ÚLFö©XL“úƒ~æ‚u, .A‚.Ø}‘OêéÊoîæÃv°!&Ä Z ﲑySj™ˆYªúœ”1köj̈hA’êHæ’JPI³Â2RhÑ€qyËË8{¹MÑúVxFýW¬8éø•åÁ¯QQl–éMOáÐÙŠïÖr]·SñréÈêåd3S™ûS¢­žð½”çB6ܰFB:Ñ7xø–XñÕÂK‹^R¤Âë(}1¯©rÈ7Ô×\bˆ8ÄÐô‹ ©¶Lg)¦3:öÀe²K6Ís`°>Wr [²†ƒÐh²0¶­lƒWwž.ö”ž¿§~BñöúÍù;É(ycOó ¿a}îE΢à@M ¥×3ߣÙÍs…Œ¼éкQÒ;ÝÖ%†hqOìÉ ºŒ¼dŸ×®M/2Ÿ88ê½¼§pk¾ÎOÙšz"[¶ÒMó‚?'H£/!M|óݦ={SP^k+U{,ÏÞèêô†lºËuއšR™DSBP ]/tI™*å–÷¹õ½ ysŠtf…-ö•\G4ÍÃóSD IpË'»¼»²ïq?ñ]ŠÓGWŒ˜{gÁðçYÞ„³xHÐbÌOhËps×qcÖÓût÷-½`~ø& ÇÌÁá59ºî{œ‹ûÐD ÷J|Ö\ö‰ej*ÖHÔwG˜Ž¸Â(ß`û]Á­†#7û@<+´µÈŽ^}ðD T†Û‚Ÿ¯[›º•B®_<å­Ø‹°‚¨Ð×–b—±y;.†'wQŽŒžé|ÝDj÷ŒÞZ2ÙZÏÙU%¨•÷Ô²ëbh׸߫Eàx¢=ž¯8—Ý íZ¼$éºÒ]¥½ñ% g¤ÇŒ#ý‚¡­æî™º–¯QÓ{Lb~ Se$ŸfÚçÅ€`v†=Xs›‡ÁjÜSOžKg?i–-ÚÑš8Ï®` ÚX±ìXÈÒ–z´[®ææMï˜L¦)Ý„ùì ,æ>,…ÚÍ#;[J1l¦fä'Ò䆢„óBT¯sk•·$D®<£°ŽÇÃ’ãaËZSÙ‘gñPE¤ãdUÚ®¾R‹9]iœä¥WB¬ËÇjiohðNb WGb‘Y ,ŸT±…lî® °ˆ¾š‹¨)™†BëV¸ž«ñ`—UÌHà.]Ÿ'‡éðe$[ëBS;«¡«;ðÁYÀÌ£'þ¦Íù"<ãõ`'·î9ã´cS3Üã’ÚÕŒçjõj*„ZNbõžŠz?§5Ãy!¨Û«`qå5ï|ů—9 N,†rl,Ÿpô˜˜BV¡³‰Çº®iáFïÐ_J.®âq¾À°1Ô<}¨P;á0eà×eÌé·Œ‡5‘Xª^œ¡©ýšnóm£(K>vá"݇4X!‡HˆÞ!Á&™z4×`ŸÇ (Þ¨ªM=íG € ±'Q/}–/ªAFÈXÚ|}PĞ߃­—¾¯ëiÎãÔ:k‰’h¼°WqÁ;Ši¬ç¢ ë5ÀÝ¡ka±5+þ^îáÅô†žb•»òÝôè¼£ª7EÑÛ¥j°.‘J)·€ô´Ö˜t££(¡Â±´c#+³8Xð!9ž{ ¯€¶¦è…?e„ââÜ–Lè´T]Š9í§ô<Ú2Ê.4½oÎðTÁRÊôÌÉ”ËaÇO´¤zçšCïN<Ö7© ØØß™††Ò¼—‡³d/úÁcU•Sè€Ë'eÜM óüaîxWàåãçÙ|æ¬}œPüJ›TŠ2±Ã^‚Á!Á·yƵß6¼ä´õõæÆ›b”Ä,ôâÆ[Œ§çx·v”˜Ž²tïñaá:P¬-RZ8ºuÁiãær)Ýr?ªV ©žFï´ë{Ñ—qÑ+œ‡¶r8Š\]Ãq»/žÐó^‰‰}æ÷VBë1r Ç"O”ãADÓœ¯®>â§[#$US*æDÁ0$†¯ìYÒÜôŸÎX¤®ÆæY™ò@²F7öêlÌŒÆ~*éŸom H|”ÅZä;—Êäo”™÷¶²‚çMô“©¡' ¥¥wܼ)¾&Â5Ä ü^*w ®«ŸÛ8 ZÎ:¨•c—×Í0.ìRTîb›K6u¹û’î¥í½çªcãaq“­è™óÆÖ]g“@r9dTî/'Ãi-ácÑíÐÆK(ñ}ˆM¤lÌngnÛ9o–ÅCÔÑ~ïòm«ÛฉQ«³E.‚ÃÑóFÌM| iõnwE¯éR#Ùc±Ðºb^³ I¿¢G%~„N9d/˽ˆ¦ƒŸú "efCèôx–) „ó./ÏëβˇÄg4 ˆ8a{Ð-ÔRN„Ï_*‰6“)­°fjàl8Â5‘áùãIŒ >†‡Þ±€ódfÚžæi]Ž [ä¼:'q4ôP¥³óPS÷F‡À2äÂú=è|ïµ#4Fîå"ÝË$µî¸Î‚²7T¶r¯¬ÇAd YU:ZÞµ£§¼í‰†I3Ý­À ±£¯Þ³3‘n3“ÞeøJ° ÉI ñî鄽öhvy»ƒõ–ÎËÇxûrÀ"9î™ªÌ <<º:áI=¼²ÐÀW1½T‰ºL"÷¢r>ÎÝ< •~ÚyIgW±y¶ÑaKe O³vNbp&‡!²ß‘Õ3AÛPª–'»s]¹Mð.ðj¨ð5i\4ÑÓ9.mËM±Øy ü3hP|ðų˜¦7 Z0{›`±~#¦&¶‘,bÍR*!‘?2ÊV'Cµ\bˆ.œ‘ƒ¼,-TxÄ{žw1‡ŠD|˜v¤esOÙŒŒx¸0¯±¤Yô]L’' –Bu¿FÔ”–Ïi2ôËIñÑŒ¨Vwâ"Ñ@5ƒtF#ìî.‹Í/•|¦Ö+•¶ÆÜá’-ZÞ¹5¨·5Ü“’Sø àŽE·"n!O6©']¬¾×³ïEØm2¶PZËâC)™Üy²•6’ Ë2xi›Yý䤩 áèYÐÃ÷ˆš÷/)G^ƒ>¤ÔDNêò¦¢ê.ò²FåéäêÇ¢¼*å`'á Î|íaU“tc àTûÐÊ{‚›Š¦=õWÖÍ"LjîÖJ~ÆÝŸqfN@À#Ž·¹ÝÁâì׬òeIT3zö_¸;•©&î(ôPPkh· >Mj¨I%ßÁEEŠ C);½/ŸﵡyMè­Âƒ×aT3©¹˜Rͧr¢HqV$é(@5O{øEr7Mò˜Ž?:÷ÞDÆí,íØ˜£lY¾Íª!\Z›åmÎM( zÏBÞôÄXU!œWõØz7fß+Ëâ݌Չ!Ë`,™ÌÂ[ÁžÙT‰V¶ƒ¯ÆõI&C˜p¢+<³–—úv­©µó=ˆHGb¨ ç$F÷4¼‚ž ;m^oJ 0M½4E}WÅ3©s…R‹OñÉ ._r>×É׬ÀˆÑªZk (ŒÄ{ÈTÚ»»„Õ0 ¦M×¾}–¨©]&t/Ê/qsÜÓ†Ÿ2×)¾“Bð¥+>$t¨˜fdYC^‹´áõL ³¹Ï L¦— CT ­ù7%䲋ÔZ×FÓ*¥¡a ß;0Ë!æËºhç]¤¹®M^vÔfƒÜáë €4é'èñœbƒdÙBãNû•Ð \1pÝ¢‡«:óZ‰ëôt= @ü2€¿¤¬½,1~¡c祲4RâEíUÄûŽ+÷­_õ<:{¼‹¼2šF¹3Oè «®“¸À.· m†…dݼwïÁÄÅ*U•¾ÔM—Y”ÚÜM=Nò‰%}4ˆ®8W°*Õ`Ùž(ñÜGú‘Ù¹žÊ¬”ä6þe¥‚¨$q´)ëëiya5Ð`VfÝ}ï!yÂSM머„ýèè€X3F#á!n¿õŠç8ör ^í;ËRXÊlËÀQº£ àê*x83¤g&—.CÒ.‹]ý8èÙÅà2À*7JZX£ ^íOóq­2ÁÅ2•~š ÞÑŠ”žjÍ‘4Ü((JcgÖ‹`™¦€Ë7¯wíù¼°”‰Å Q.Iü¤"÷d‰›éI×S$!+Ë*›¾!J$¾¨“ÅE£¤ò,àã7 «…ÃwèºÜ`‚'ã‚zÈÔLzÏã•‹¨±"H„úÓ¨7ï½2¾H ]—VeÍcq´'B„o[ÁØò#U„3A]=•û…Øñk·sõð)0l«{Î ¬Å¦ñ‚¦2ºŠ>~C¼Ì ørÆĉñ0Nz˜ŽDÏ7¼-嬢¹÷ F_®FžÏºú]‰ƒÍ,4§L62…µ”ç5.–ßT3žáæY‡¾¨VÄ»íÓW·´žk% dcñw¹MTg`ø{cH¯|Ì.tÀ´¦ò5W¸ÂÊbOÝrqô0èh¶Ðº£[øUmW;µž÷h¢#A“l V ÏO©å¡º;49OžÍ¼—V‡Nì•¶uè¥Þo‘Uy`ñq ‹÷Ú"yDô¤ìè ûåø{tz‹¡÷½¡F}hžûÄ—•H_VúŠ#óe Å¨+›+Q/ ´±“B‡ Vò+¿(‰¬íô‰Çî“öX߆ê>¶½ÃÀÚ„c*Ï‹5L<¬AusáyÏoöêãª<œSÃã|¢|ä4­Â`Î6“’…ÊØ@³ÉãÃõ/-íF,Ûå!¬±ª5(DRϳAÚz—™,ê ¹äR£TÏi¸­¥Hvõ8uI! ;QÜǤø´G¼t¤’âœk•³„ A9¡KKµ4ÅrÝã¸kCyt”TŠqgFÛ$ Ф±v‡°ý¼âEÄŒW[½)†®uƒ®_œ!Õ™Òè¼2òÔ¬DL)«°}R¡Olã 5{AM<¼YOd-wœá©‘A.¡öÈ)M²¾Iª7¦›*Pe2®ÆžF4¶à-Âò\ ¡‡"Zöžœ˜fû&ì²' Çø–û$1¬¸Îf^xHÝ“ž[…UU~+õüjÖ©º•.;üÀ|nO†iqD)¶jsOŸ]ú©Â*ðFÄ{dá s»°ñ$j\§Ú+ƒãõ us”K*ŸÖúÖ4™2–J¿° B§dÞ m ¶Ì’ðM@Úk6ݶSKš«×•kHÏ&Ô÷úƒžÅs¾¡™„Ê‘zp€.Êñ<Ñúy)ª¢Á-ÊAœ²tÃóg(ÓO:ütÉž³½yÄm­§oM‘؉E¸`ó1\ö“¶¥¡ 9Ú¸aee(v6°l*ÖŽgfâ0&™­@C(h¡¹Öª,fí!œNëo9ÎÛWž¢×þŒœ™ »NAûqQ½u¡ç¸÷‹ÑMæc\Ú ˜Ž,C{ó¥%Áçd)Ò› ÛêܨƒõÖ‘¶ÓÒ%0QF´áç!ÏDÛ½·“B7öкáhjíñøÃƒq‚9Énv±È|Þ7lD¯0ï&‚tiE¥áꊫKŠpöó¹×±ç‹iú V±3«SƒúE4^Y" Rîõ_^vÃK©ì&]‡{æøV@‘s…%Àµ-µ¸-=²‡ TKïÀ¥pÍN¼Ñ˜W†‰ÉmÝI°¡. zcDs‰†^/Q£VÓ[.Éd³U XSAr]+›øõ‰'ÙÁÓ*EÁÄ;Éí¤S¾E1ìÜ6|q®ó ª+5Pªå=xá'¢cIHµN|d™Dè5") m’ŒQîãt·ªâô¹Õ›M{‚[js8scc4¯oð <_¢æˆŒðÌÀrÊ㥅®ß£^ÛY q q|æ)n©tìûrÉ…¶á©p2 • ¶DÈ#” »7™™…î3¥ª²àZ†Me ‰r¾æÔšNÐýˆ^†ÅÉ39}&Û„)„š1€ôüŠE]lmT;§iΙ'¢õ9ôI¬Õ4©÷޽w °‘ÙW;á«Ùh3žÏl—óâzå!#¿v{L4-š©Ës¥ý²AÆ»¶ìÄ&]”@:™‚¯]Õ»ñÚœDE©Çr3ÌÂ#Ž^‰cŽö&ës3¦=EÜ"é7AFFÌhCJRô®Ã®n ¯Açi<`â;™:z½ ã0¢ƒÓ*ת?½ô//iwSã¸ïè鹫Tå²¥xn5S,×6Ìâ@' ¿KLèBN¡(ˆÕ;U°|Äo7®«ï-=à[“»žmiZJîa9}JÊâóT 8u¨ø˜M„i„¯?†èG ™¨(SÌ 6ôp¨‹I‰Åø„å/1or‡4ȦåÒPF³±Zò–¼ ÆGÐѨ¹S ,ÍETQ"Q:ƒZwf²ôÒ‘x ] 9Snªoåà…cñ“¦ÊìukŽž¬I4P}}ŽÚ´s]:þƒäH~z¯D÷½º÷ЭºKšª·}²‡Û 6ÏÊa@‚(JïC}¨DéÜICq)&*½)ô‚Ë7Œ! ØkàLJÀÉŸ‡Åu¨añªsÍEªãBÛŽ#àœ€ÌÞ8á£mǰ«²8c”B%¡=y«-¥"ïí¡ >K¼Ý4Qnxûc©âàS5‰ÑžíÙeRlù³xÕ ƒËÞ“}/ž6G”åÖÑì ¸>á9›[uªhr<îSgRGõ |Jâ‰¹Ú Ïn¹‘qá‚fZB²Î¶—e‚/‘‘OGS}{Ê‚7u…xYR)Â`ˆPýží‰I >|ꆞÇKžÝlCU6'j“¹ãñ‚âò¶ðTGm²Ã2Â] qš›^J¼ª¹w l Öîôe\…ZW¤…:ª¤=ÄG™So¤MZüUW¼”c…ÛÒ£W0¯ê-­•µ(J¶ïÙµ¶Í³¾' ҔȚ  3pƒèÏÓÀ.çù<~91* šÜÏ9 ^'=}cCXtW´0ù&* h & µŽ¾Ä|ú%æd!NCÛ0AŠË‰6ÓÄCQr!&çˆSM˜rÄyYtÖs·ƒÂoåÊJY]«­ÔÝRžç07.“>¬æmÏ8J`C}ãDù<IB‘®ñÐD3ÀÂé‘‘£ åºÚ#¢+&ŸBņ¬ˆ†< Ý+S†½)ëôÅÊv=~ê§H;…Kià\q²ç“ˆø´Maú˜I;Ã@£vébõT3¯™Hújø…UÕUºQ²Õ¼]˜ÚjÛsI|!…,Àž^R-Œj/&SøÍåhqyºW¹ÕsO ã¬]:+ä®±IöxMÆ3ÇyS¡æb€ƒóÓ‘6}”t@Ö¯ûÖïMpA“Ò•eG ¼u§çµêGZÞ÷ÄMK—w0ì]1Wô»7mcZë‹ç´¼ó-€ï1L(Û.éârߌO«½£lù2“ùËL¦H:‡Ü…@²HâÇgp'sa:i6H@?¸‡[þ@âÉzpJvHL§a/²E*¯K Ù˜?«2b¨ó~’Sy½Ý¨Ø3 ¤(^(‹«PVv¸WŸvõsˆx5Jt¡;ŠÜ$¥™B&›yׇ6sö—šáC–­„,¤XG=q~fÙÀ6t«‡òp^á"¾´ÚäŠZsxÁ=+Ûüöœ `^,A’Ûï8ê˜Ï÷DøYÂAœR]q‹œÁæµ%ÜÒh2Q-ÕšI!©p¯%Gâ7ÙÐ{²ÀR½§Cá t·ˆæ0\,  ®êx' °äBžÝ] bôp­*_½o½¡ž©¶¹O» û­ªWöšB†žŒ(Ýrö†]½×ñ@¬M¶™›ÕÌ –:dNU·MˆI¨á»c¡]‰[ž&sz.èK¯Í×ÝéÅ+W&[?E÷±3(ŒïT£ö'~xú8¡×cÝRŸlÓ‚˜Ê¤ Jð>)s» È7ÛjOQÔ­ÛØZHæÌÉDæQQ/'wƒáLú¤XÙž*ê8ŒÇsk4œÀpã{Îòò˜wPݲÉbغJÔˆ„Çtä*ˆ)iwRÂÁMÄ ×Cȯp“\¼ícçWè;yŠŸ1ٛͼÑÕcvaÛÐÌçBOC–븛jÆcÕr²×Þ>kÑg÷Ð_䩨ôYß¡TCbÁÁII_  {/ÏÊ|Vú4ŸEHìÕ¥§y—n¼4q÷'Û7mŒ‰PW"ÂñÔ_ÑóÇóNê* ßn‚˜¬_Ï ÜNA¾×¾æ—0³Œï&Ii¡;ćü{ÒúRóu+ 4u®ïszç5Ådv˘{i „k¦uîžæÙq\yÒ#è~5ç I›9/EfU†0rv¦MHÞÒ {l”Þ ÐR¿yÉ%< û’í=îg¯ECžyªÆFÍö£<áÇïXÑt뀹ٜY­ € Š¡=Á½ÅQÿÞ˜‡´wÐDÈd¶œöç{·Ð×düĸžÐõ“Q|2µH—æ¤3Œ•݉Þ Ðà-•íõÖ@•(©Ú3¯t/I¤”C0œ:‡IJ±éÅ#bÑå-Yðìæ¿ä'K) ËœÙ:ý˜åyhGÐúIT)¦Rö¹‡Hm6<Œk« {`aÇbpO˜WàQZ …ìÚhI‘ùl¥HÜ•ÓåLéÈãÕ¸æ¹É„é¹0Có)˦ gÔÔ…“,IަXF®†l@¢Qð” VeôðW¤LQ ‰)Oœ·n‹¯äù€{³; ;v†^$–­&g<ð´;‡­BE8_ó }KDuÈ®µ§íµx¬zk®HÎ3B`^p¼Á#{8¯Ctß“÷"7ÅüÙA§r^=å÷¦PIÞPÓa¾´Ë2Û~ëûÐl^ðiÂÑ Ãwµwa-×uò”ÌÀ[bH»©öç¤{wNKõ´&éø ´‹À¥¿9#Ôd“žƒ|Vð< ä°­9léFŒ!Fà­á\‰Žy܃vWƒÖ^³çiaÕ7o«GV©/¢^YTµ'\_Z󪔧…湬 >¾%ä^"»ïÙåé«‚ÉkÌÐ å·3:¸”ºã'fΛSè`Óªfä(”›ÏÑU ¨=Ÿ=$ürSáó…Ž«ÂeÖ…"'m†©<+ó¸Ióu޶Ö˜³…Á˜“ !µ\)㪦L®OF„ôÞëÙô«á©6ˆUÿnéx‘Ó#ùZŽ„«D Pü„ÕÞt#=:Ý@ߺÖìUÛܦ‰Ûm®Û@XÔÈ3¯7Ë>ølŽœá/9M%Ù—d—_6êƒV©|~r!‹NìoÖÝíàD³æ„4¥bׂ’ä=†¸wC=üÆúJXƒ3jÌæ»Vë.© æ`áEwµ¾q¸7*rRïµ×šyµsÍó©®«“αe½g/X‰š TÔÕìeîÚzkº[N=~´ZŒõ=Z¦a ?a˜å•ˆWú8¯ïáC3dõv,X20¬¥Ux+$ê”yhÔ;›3HÏ£\g”%¦9 Ë#õÙé·8Æ\ ¶£åËAÃà­ŽZbÉÓ7Ø–Íq HÕÑDƒÚfª©$$(ñÜ”äZ,À¯ÔòµY±¾äÜÝ <~+`Íž¢vO+X7ñaŒ©QuäèI—chŸÍlŠìLðj‹¡ŒS@Ù,€•á:”ÊyOß¶½ïæÖ4A¹ QÕè„qÌéZ¹ß$ËÍ-Ý^íyÆó§‡£­!.òܺ ´bTGW;’PŒ3”foë²²[×½ÏΈ»¸è \iôõuŽ;Lˆ®­<ÇcõY­œ|Aïè :×aHT±‚`c Ïá2Ó‘ÂC¯wî,@«‚Ü´·Û–ŽºN‚fjuF£¢J8ëÔœ©™ã„Ûû–îò!!E„HœÄZ.Èn¢o¼Æ;žXZÎ펤›gü)§É©¤§Þè©‘*(‘ѬµðFBEÃ&ûÍšEùÏ£h&\8 ‘DmCiÜÆ%ê}[ÊR^|¤ïTaóy8îÖh{¿|jäRؾ+Ìi=Hh¶8Ñ„JPò´¦Ff=Hî g[¯T‰³´÷Q8¾Ù€Á£¹òHt$èw úD†ä/;É`WyùñD_z:‰fº†ÄèÄÂ#ItT3Í@kõëºö®èêa²¥?ÛÇy¤Æ¯½g“%—\ÄÀ|œL–A]¹:õÐ;ó½Ðrq*`d'SDDkv#Їœ ¦¶õ&F$ù%¾Mw²îíÜNíjW./“ÀB©Z¨Cˆ×ƒÒÒÈÅõ dŸõ„™P_wbcòch / O}¯³` ]H6¸ß¢ÀnyåÓ~Ù¼¾y); i!½Kéå»ã[yÂJœ]T#ñºêÉ«¡³ÎRðÉÇ ØÈØxbaÞr\áùü5'«?xÈ/0Fª „xoh{²íáÐè%gÇâê™Ì»“‰xA*Dc™Ì£tšw¶&žóÞä¾V¦‡îÁM“Ç/çèÂV^%»Š)0I¤W6“z¼wXa5lW.$‡œÏËè¾ÜŠibó^ŽÞa’}Zøê­`6®5(í#Ïd†sÛum¦pKçZìV•öP_â3‘Õ®tàƒM}ë&5E¡:Lïê85ÚåiÏUO>=%ÌôŠ·â%Ù2[h6š?)ë1ä;_z:éé™F×ëIZP¯Û!vãÑtÚ!dÓö8õCa5Ç&¾As”†0ÇÙ—S%̯ÛÃVÝ{óˆ03ÔQŸÏ‚äb=¢x~¿@ ¿Ûžâ&U2"‰A ŸÅW°{Û4`ìëEĦTïªòÎè:VÂÈfŸ–Æë¿}ƹë³×*O®Ý¸Ì·av–ŒkAyH¼¡^$=r}u^¶5p¶ÔïŠÒvR`²hö/ýdÕUÈB›6úĵ „ãôìÕ{ÆÉc­åÎÞÕE\‘t²9½ä6°ç™j=¤C[!¼ÇŒ„s;â‰Æ¸÷ž¬çÔ£w2ã;ÒÞ\ŠmÌ~5þ†î%Y%+…xdú33ÄnÈ3ÝE¦Ý=ìnè«"·Êº,OrLëÁâS5à'ЦHi¬ CU³ˆù¬32»+ð8³}žSJ¢.t[1)¨ÜËU jÁªª°ãã²@˜6`bÐS\Ù+]àÍlÓK[×Ö})Zþ^ ÕÌ9ò")ñ…MF™»½ˆ²›¾B~„㉪þ§eÓÛžÔ)˜.ˆ‹œÃø$¿ƒA¾Me‰(OÅ’îíXµÜÑ`6–hŸ|ƒÛÚÖÖNiL^Qâ|©¶§¾ÔWµÃŠOUWP}’õ^ÈY¾~þ¨^á㺎®Ì¡„[:ælUÇ-†¬ÀÆrº5Àc}óZŽª¼5í^±˜f¾’C„)Ñ;36oÒ´†¨M«Þ×þÞÉóý Q l/ÂÚ•ï.àU4S¤d í“–¶Ñu~cOH¥¥ÌÁ¿Ý`­»‡ÇR¢¤"Ò7t"¬’w!Ê–Œ&1ËÎ ¢ÌAôôÆ vÞ™w W€>íÝ6wÍœÚìT},óJªzªp÷tdt³nà¡ 87Ý[.ÕÑ)=ÃAJ6 ÐÔ:ÖBèÙ€ÕJ4DFÑÓ̾˜Éœå ÑÀ}zïøyTêã@h&Dt™ˆ.‘·tz r1¾W*^sœØÕAñ8uZGe™º˜.`PC•ÎaTŸ+{ ­ >XН4 ÁEëP x;+O»S¶ …Ð6–Mt¬ÄºkÜ’¯Âv=Á›c”0ÉAÐqž!­·÷ø‘êsÑâa={(‡; ÒÕÍmÞÒÐÃ…q½#,›K&”DÆ,³­#Poìe cGfkÉ[Ÿn¦á@Î{!Π¾{éH¯ô5E Uà[ºdº³œc|DVælˆù_mjf†MF’$Ä.Y²Þfó6¾â·±¤xN┌тB$¤º†·C€ÚÑ?¾G ¯Vßk50ZïX"S£—k'BsL©žVnÒciïJ\É]4ƒ$Ξ=bj_%\;Ôµ<±{ò0HÅAÃh‡,¤"é^¸šÖ=;Úó~$®o$bnœÇÇlðQÿBöeÁ‚°½(€žÒt«Aê\ .á.YXm&y Më¶ x²M¼ÙEN´Ù4dDÓ®Ñ4^%îÝnÈ™ìŽpbaÓ:éÕž¾œç@lÃPKß2ˆ÷ªßÉ T–4)ó„ Îë—Þ(¼Ë¾ˆ^ƒÌÔÀ¯-a*%[ GžBæJ¨üÅ(SîñT¦á.¼‹bÖº,{=— Õ:+däa„”Ì4æ¥H¾•æ³ZÕ*Æ{Ë;svàNz^шú z½šF¦Q·„׫±ÀÔêƒx ›YÇáð±= ªnÝTÌ”'ÇGþfêFŠÑð;3}Œ†NÑj k° ,T7Ú`1¹ª_3¿¤>¶íb´ú°±§æ½y›$/.r·3œ©^‡\bya¿Az+­ùB YžÕ€GYæÁE.ð ø=eK¡,<Âbñ `‡qËz*i!PpäýöÝé+„y}cœÇbÆó.'|R†FñÕs]51B,7ÇÜ´=¡$Y$åÊÕ‰yoµ€”‡™O¹û̳Ù2ǧ%’!n̦¡H Ó:¥ {®/?  h(¬ç2kLÃO¢MUÊÕÛß4 ,?ßà͇ÄÓàðDr%ZØšÌeDZ‡=_ ¬!x|¦ ÛƒÁ§ä®^ ³ôpR5Ëciw’šá¼ ÃÆU\†ð›J@ÚæÝýl/ÓÂ_˘!ÁãG>¸*W:\¯ÆÝ­BöÊ^°®‡f /ž†¹4Rsz>£NáÒó½z TîÏ“t<NãÅ[Ñ¡œJØ$];}P©ƒÑ¬³¯•Ì®9ðð–ì à;ÎG5Ë/‚ n 6uûÉ'£¨ß³(]KH1„®¾§+ïz®}°MÆp²cL ßz±™Mî̽©…:dú0PŠãŒß$탄¨šÂªz’åB{¯"·µ }ºuc1+óå(eCjˬ©ÌR?C,ÓØw³Ìi ¨wç”Ízé‡6¯(´4tßlŠ<àÙ»/YšR°úÑ ˆ¨@ý©,h¼UžZ5‘|8“.é˜X)[Ø¥/¸¬0“ršÊo—qîžÒ ë~ÃEµUq÷ØŽZ¯ñÑ“Œv›³®à&|[ÂNæ©Xаƒñj+Œ©4 ÃÌÜd<ñ”¬¤÷©EêT·—¼1“µ—‚Æqýäí®Ag1Ÿ5íæCìãQ&18e±óÇœS3‚äg|‘寅¦Ð 02¡ÈJ×B°÷ÔJŒDžô–l½|QbKóV»Êëvá c,°É½nckÕ@ÍüV)r¨+‚ ž Ð=H‚+Nv¢†aQ»Ô4Ý Œ—Öz›öòÕ1èÁ­BÕ‚Ž·¡TØ>Ù—¾DP®MÍZÑŠ»Õ 6É¥Ü9Ä–jˆt*왯®¹®#יŰk­Ë_»?Šçixó²µ|9·톜ý&D|ZfŠ»3üå]>ÆM i#å{bOОgtÀ«“·ïŽŸg4¨Èöó“ŠÉ²ä~•.”” ñÚ!"½XPÚâŽ~BJü)•NY︪lmÌ8P¡3iM¦µNFθǣž»ÊÄFFŠêž1¸§±WÈA..>T8(2ȳtSê^@FÎ ‚N K&ô¸;:Èõ5g©Þî%ì•“ºcÅyÅŠ5 sä¾Ï `±+lμ!]÷üxE76*ï“åªËŽ£ýEi)Ao&?[Ôt©5ÅtÑ—í0Ñ >[ɨôŽó™¿ŽU+'¨dN‡Ã¼}7þÄ'îµ¹Ôxšu(½ÍC< Q“}IW!8 0 êî 5d0¯Œ^­ X”cï÷VSp†Õn•¤ ¢ ò¼ÊÛÕ%“œ¶êVÞ2·èGã BŒæ:ýº±†yJ¹ªh£uñZS8í±’ô8biÕÁ{iOw,/Ì0`̬‘XeQ‘¯StÊPø¢Yô$”FÁ#Æz,Hæp1›v{¢ÀàlŸC™€Ç=xåÊ#½ÀÑ"h¶ ™_ øÎîdë µäGˆ„»DdͶOì2¨Œñ²^@ˆuO¼gÅT¾Ž7±×AŒ7C\9ÐjF„ZÝ]AM›õò!õ¡Ît É½s}ü–€ÓTìQð¬nk•‰Z< e¹ {ýì ?z‹B@Œ‚Fc÷FAázžLb½¢+¾\ÂÖÈÄÀÀJ&³=C`¹#µUµi¸$Ѻ'Y—  bχši³›:⥔æ\ä4™®Åv쎢äqu^eô6¿yÏ×õ©k„n„9ØŽÚ¬{#Ú0ôuïMdðëëÐkUÙ¬6X%|“ÏzlK/˜RSü”÷xE ’ÌÊØt—ÏëeÕÑMoœ8D¼ä -’·‰X<»¯–ÐÛœ@GP%úISR¼Iú¤ôÑ¥SQÔÓY© J¹ïÕ²#jRl¡ï X¬ÊIé„$CÏ«züT‚=ðë¶#%!Ç:›%q‡PMzrЂ"M'ÝGMÈ´¡IkúÊ@]{˜°dÊ‘&{ZGžÜ¬ˆoð‘Ö[Y©ÁÝTFðÕÀ{ä,ÎuG¦bnXЖÎqœ/›ˆx`ÖŠPÊ(ŸI€%B29o¬=H‚®W|ûB»Ì'fRÓ×1ËSߨ‡¥d:åGÜ w\O^×z޵¯`–[‰“,BQD"x†–0îÌœõÕ³â,Í>@Hº©ÐÄ…éÐ>÷ÛaÐX€ßöS¹ldK5œÌe¼ç¼¸ªÈ]JÍS(lOž¾±¶2|¡c;­Sw8Å`  ØŸT²˜¨ÓŠXŽ®Tä´Û4Ùf¿Wï¶—'Š›ŠTmuâ!îcx6âuj}Ï“³˜=“§¨mÕüT³Xj°Ä1O×Wß5ó œÛè*¤9„%{h-ˆ  €Mt¥"L‚·÷cZ®žìm=¨ª~IlãL‚°êWhæ ü”u…èuç³7Ùú é{p¤— {Èå}™J\ŸQC4<{wcû”}Î'í2bâhTÑXíè@ã\rvEž @ F ykÀn`Pº{v5bímR9®ß<‡.W‹ÒqØg]ûÈ0÷ô=N¯°IZQ9€©(¼qxÔ'Æ$ºæ€u!+ÂCâh í 1mÞ£§øâv³%Øè!º*9Ë ƒ{í,´,\û†Ça#Þ=ZÜ;7ó|÷ÆÜÔ—Nuá5±_ItSïHÏê< Il^òqn¥žñ\Ú|bËé÷˜è]¡ç'¦ _˜Æ{<«ÐV“ ®˜úOy™ÅOî‚Z æt½…-üµ v†¹šdVBË‹uÆjv“þ… A±p+›Ï'ò™ãÒ”:0-àö ¥rŠ1Û¶]×jÚ9‰ËÃÛ%¢7B󬸎I™\ñ“X8„QBv–€§)AcùõkƧ¸ý§æ@¯Y¦Ã…ñ›pŽ‘=¶ð„¶6·Ïš|ã–ŠZ£¸ÜÉA”ñë‡ù" )N”= ß›JÄ¡‚{I"\ÇW„ Îf4¼oø­È¡{——…-ƒ•3ØÝì¬ílÙŽæ˜/„ÿÜ'&ín8 ÷PÁ4e°Î1qç9Ñ4‘xÜüÒiD`ü&E ÷“åƒSx¸€ö’Ö'#ý&Î$`;åžÛJVw4$lŠÕ…²Ý» WùµŸ7ÊŽöáÅ6¥r)j¾–ÕWºÙ{º”̈¤qœ³~Vd´Y‚7ùt¢Ê}ÚCÜ·`lÔk«Þ£!j&†“™'Ü­¦}Ë*1OؘrR<­çÒéÌÛYŸ"¸ 2Ú3“cnWÀ5cr˜`<MÝr­çìF©Õ0/ AZœ«ûm蛣é„zQNNï$™¯b˜‘²²ÒÌå:õI:W™Øâs‡'{áz/Íp9ØUš1ä£s5*/9¨öGçòš@‡N×ÞTM“jLª©j°í t:u'Ð+É×ì’1„Jo<ßø7§þÅéºg«j¼LyÒ[«Ü–Öö» ¿g®ï…‡¥ô x(n€ªËfƯûjµ˜ÉÇÞ/“žÜ­£’â³CËí;Å2šÚ¥i‚Pt‡¾%ǹ,Ù}^„îÈ‹ feyDr|ø: 4¨²-j%AÍn½ÚŸ`\½Ç6ÇoD»Á*JvþõáNé»D§ÔÉœ\ѯ¶à5V3k.zÛNCåg\®gaÂé5L•¯&k¡9QñŒ•‡z~AtâÕ®‰Þî´ð¦%gyƒ‰•ÕGµÚM#IÁ]ð…?™79Q8%¼šô<‰é…ÝécˆFÖë¥mäfÇÑÇ':x†åenÑ+s€öÁ>áeµ¾œ®Öuº ËÁÓžèeÚ=+ }ç o0¶Ë}Ê1Y®ñ)… \Kßœ€òð#¾Ó!F–'+{ÑE¤3_wßµCëñ¡A¾™yÀƒ#{Ù'¨¼°iáb4UïÅ;}i ª9ê}$y0O`™,e*êõê‹ZšòlÍÂ-Ú§¤N£;0TÎ]ä%z˜ÇÇspyAKrÆâ袼#¦—Ô'jõ=|‚ؤ£–5Rø êNŽ_KDæÄÃM;òt„¬õŽwÁX\Ÿ…2Æã½H%x…\U䎨ö´^>ì’wGº•ÏL‰’ÊÔ''³-[ߌ÷#¦Ç[VÊ OÍO)̹µïñB–ÑèÆ#ðÌ#ll¥Š§BÚ­56Ëǽv:";Äšª˜uµ¶¼€Tž]—-K%‚¿ÃÑ€êI”Bv›½:‰éÆ”ÔzsmþŠ‰Ø€ÒN—U‹—}R³f]Ì_iÚ•2ë<º‡ :Ú:ß7ð€„¥¼Qß'¨¢_ Þ`,`úÛÒmG¨`qêò«Kº®*yê|eìC¤|@0¯B¡ GËû±7•pÆõ¦Ñ{Д™‘ÄÛSÍO³Ú€žb:U¹“—ËÓ(o£ípº1ÔçM {ɪý^?~é/ Ä^Dê˵¸Ë2ÚûVBí6XCSTßqgZhRo™Ó˜ŒúŸO~EŒ F"-): Uº¹7Ñ̃èí™öÊë`‚îG;½D“”ž†ƒ=&޾\ôl¸¦$y½fCŽOƒïZµ`æåKç Ôv§-yÙkô÷DÄC"A«æˆ'Bйö,Ïæ„¿Ž¥˜¢á|-ÍÐf&›Ò¡§“¹xŠÌß³c@»+=ú©æz¤LÆ4……¸ˆÕR#Ê´ìÄ™—EÕþ^=4ãôl1¯»Gøp ¹è|n§˜Ùûñ>Æ!½RÎXÙp9Ô|âbË\‘ÎÊ@.ž´ÓÐ[–zup°¥cüj’«¢c•pŒßËÕx}ÝX†»ý Þ^Á«©I}uhý:³†ÁÁ»6i4¬¿gTå/R%r JÏêµexäù#N†ë$WÁ><ÖÜçoOÇ™QÜ2±ûí«s_LJ½Š,}åaoBq]JÞ[ˆQ’Ë'©Æ˜Œ’Ö& ¬Iºnñ’šw+`uHúîðs Ah¤jzK3ÅgˆnéºSXOäá{ú’f#´<HÙà)¸1`÷½Ns”º×¡ªkD EŶÏ[#¡B ®¥±“‚TÔ«—Ÿ¬\ØK‘b+²¿b9As²é„w÷rÕÀýÙˆ’ Rv>³µ‡O9™ÚJ½\ÍiPò'£|uo7¯Æ”™`g„9/Ù≜Vk¤;ilaqËêÒñ»çP)óø½ç·ö&m#3´9‘3 BKrÄ$ˆ9#Ò¯V±l©3îÌ3‹t–Àe^Gè&vƒbª^9PxqOÉJpªõõùp6ä¼ð·Ýó2 ]Z<‹ˆXߣ7ræJAs·`«`Cíøi&.cN[¿yÀ²ûä¹uÎí3Æ·gÁ^jçâ!8€iûæÅV60læq+™©èÞ"<Þu¥é&65šº‹3r5ðw{ïÑéƒÇެØ9MàÑïÑE˜÷Ö.­—”'¦;zÊÛèˆ~&QÀ^š>Ì>¬S–Èd‰'WN«‡„ãŽAæiÑ{d­zQܶT Aäç"/úeŒÇÝ #‚Èé½¾ gf9«… ÐÓ ‚]È{¤Ç§0^nmO ÁBë½RÅ<Äó™™BJ¤ÂÐ~ÊñD-€‡‰'5†Ç^!pIG4¥*¨¡o6u§Öê#O™ÓPŸ’× s¥~(iç •wÄþN'9¶Ò­zœ¸h@ô½m)TÔ`§³È‡ÏJÛ€Ú”±h6Âí„Ã>Q5úBÕl×+îQH=% /£‚Ä¢y8½åøÂCŸˆ?¸Çõê‘‹¢<<‹²HÝAWe ›FÓñ°}©]˜–jÏ߇¡SÚJî<_îÐÁ÷ŠÌ)Ðm_ <)Y,Ácß±åa ¹ Ÿv«hT"E®»7«¾ÏhÖ0ž‹u ZÏdNˆ‡`z·þŪÕ)ãQ³,šªÚ?¯Wàs( ¢ ik·q²£Ú &æÒÅ0«tµ ˆ7’Æ'¥_0…I³y¯¨¨Ç>}› ï [[^ øB•¥d¥ªB8äó«³~59xo‹ j+P€¸絿„tgx­™l3ÀIoz¯ç Ùò†¢9%¬¸d®VGÙjöTÕ]t›ž‰¹÷nô¥<ìçÀjÏý†P^¥g7åè=Q5’G¨óW饱ûå°æ¨Ê²<Èržá¾å¦.oÃE`b–•»©ÅžË‰“‚wl4i©©?ŠWxþбjÌ„£Åô¨¶|…ëmK-Ýf{ÏcèCà‚䘸bç’çZ÷ÁŠœ¥3áÊ¢V kòÐÙñ´º=]ˆ; GA¿ówÄ#¸r1ñâ¹ljXG‡ç *ZýÕ¥ñÀöxèØ—‹«ÀÐۙnjB[%“ÉVw¾/8¾°,¢‡s¸D-ªÏ‘ÖEa5v™ÈÄ×Ótá ª¬ £•^I«OtÇ[T“Ÿ1 TåQ>OØS=^NmºûCÎ!Ák±+ܬ¢¬‡\ÄÛóŒE5<à9>6÷{Ì,Ï$»skƒÚ„n<cß˧dDGDÞ|σØ@$ÏSUJß<íÁ˜BŒ ±¡R-hs'Æ.3 ™íÒ‡L™Ö)ä¬KpŒøh£ ¾YuøbµÌp¤÷d03Þ (¿1tJÚƒôuž@G:‚ÂC¶Ú³Gu/öÔúÙ﫽‡ Íá¦cKü½H5«P ô3\‹wda¹ù8TœTæY•Ȧ…^ò‰Þ¸‡GQFñ#”œPkC*âx4 B¨‘Œ!†vY+ÆdLßM…OpÌ+¸M¡«ú V©‡m”!›œ¥[WT$€‡¼ÍHô镺«Ì•ây7ÀiÔº®h>Ó|fÂì Ç\¯ØÛS´5I„5ÓÄ^SLVFkï:å{Nl »9±–#ð”N9²÷Èæ¼f³€B%zÕ¿· ˆ…‘2„o/Œ`Õ=º¦­[ šÖpfY¨É¹œi‹ß[£×JTèAMłϑ)'öŘáªÛ«…ð.oìgüéFC®¤2M8´U;¿KÓR+u7šz-½G¦YlwÊgöJƶ„Ÿj5À»ù‘ÏÒ\È{5˜=·íüBÔ‘À…ß²'ÞL¡#In ˜‹ GîLÙRøŒ÷ƒÈÂÆ=šgLGvM&€VÊÄ¢ïÚöõ17†ù[«¨JÔS¤%߈¡E—™Lzr«²Ë0’ÎbêÏhF W_p^rK<ó)¹Ýœ]ÝÇ4,áfqà[‘ô°º'!±m0²Q@&¶½#ÆÁˆØeÈ”—žl§ñl(S‡r¬Öú½7™ïQq‹¦Ý34;v6†Z3Ú‚7ÀëTÄn™*IË9'ò@¡5C̆0µ_ÙÉA•Xá:ä^^.‹G$~ÏoË&",¥Ex*Ÿò jßãzv}’W)Z;â«ÙCF#ôeîD¼LlNzlãˆ1ÏQ]³ ˜0@ºóVÿ„õÑ„Td¥;ê¬è๸€Ôx##ñéF¢¾’¤œ92°ýÜaOÀæÉ2uCtÖÊŠHÑ·« ǧDæÐöð%†ð¹1”îÒ¼3|DT¼S(ÌVï ØŒÀ½,&¶–ÙHÏ¥ôÙÞÜWníd'^[ÏÔ¸õ|ŸCÿEëðøE@vµ)Õ½:~N»æ¬:Os×׿IX{öäF*±A¥L<]§¦ö±sEt&¿—•-‹'Ç—$›ï¶øº\ «ìTÕ]ŒÓônÊp¾=±ÈG Ù+½‚õ ›ÈGÚ˜©¡[˜‹[´½QFr­M.y>I¾;ñJ PÊaáÕ´ñF ¹ó˪¸ÙzBô kâà‚·¤ã‰’„A¢óô ŽÕ¬÷ ™Ÿ’:8xxv4¼&ëÝ@å­ŠæÂB,r¶£–'óÎ ïʱùÙäVCX>ô¦ÐÃ;v1Z®¬Í §B³âr¨¹¦‹¸–’  ³Wä~²E;8\O•qÞÌìÐ8©7Bs9²> >ˆCÓÝ2¥XÍxºP½äfíBÒÇáï‘Ùâ+İÀa•‹ÛÊ’à—³¢'ëIî–=¤M«Œ#1@iìÓºL #çggJÐ °§ÎËÇß3q–ŠâzÎt 3( õIkè­ÀŒ°Á)ÙĹô@ð…§f­ñò¤D•žËjq¬'žuÌU +5õPݬ—òá4ø;ć^¢)4ðʱ³e·)¶Ö˜—¢¨¹N¾Ññ~Â[š­J-[y UòTŠY˜ÇAgVŽÝFž½¶ jŠØPײ'\k_bñ‡RZ¢f¤“-Vïˆ&Ý^+  &Ì_¸š%¢ØÜ’L×ÇŽUN›G]kÃÜgŸ]‰¥vµZw¿8˜]X8$¼øðÎ<\}&}µÃ u0ªg@˜A–C5¯Í—$tºyù®ÅÎÞÃÚ‘ê#ŽvòGÖØ*5‰ÓÑl¤¬Š'W|[b02Ïìí{CÓb†;úp9[Ò©ž“Ÿy%<Ò:ã嬔t$+@E2‰Æ6:ywOuÍ-CB¿Üò Q)¬ñ±ó)¾ä6=9g¢Õ&†÷¢ßÜúðà[œ2–qBª¾¥G™Ò‚QÛ}Êõ\Âä-Ý _l®šâè(À&HäêðhSƒKtŽ÷^•½(~i½â¾|þøAlˆ‹îÁ–ˆλ®{óP“ÓK÷å k €0ë YÎÜ')âØî̪ˆt×€ä§i%³ãZ1ÆÀá•Ñ<ô1¿µ©ÎQV»ñN)½«[Ø7@¥ƒo¨¢ë4±ûuêúºúÍ®yà%RAˆ+bY K°Ê@”¦ÕsŸ¨Ó‚Š`×ôŽé"~Øí{øÜ  %D AfØJG¸Ûx`x§ßœz,ÄØslúäé‹×KÝâIUÕ$"pd-Œ”GMÛQ|‡³‡k×øúE$û2f7¥x D)…>ö{¡$¯Äº`(°†œÌžŠ–.Œ×&ö$8ç³çŽšÎÀ.×÷®ؙ٥Üf³kHS›†x›¿+Ñ~J]éu/·W¦oz]Eóùª1õÂ5Ǧoß{¡Hë6Ö2šTþöa ¦qÙ *䥛à%öµ+3yz¥ëÞ)à ÚÚsþ*PéxMjlÍéaÊh͢(qãfãW¤~ñd—¸Fù%äËÚ%m~Q×ö6ù±eÕ¦ÛCÌ2tí¥.ÓÃWE½—ÜW:H½YÃ…C®ˆ Ú¹À{†kõlݱ©<œÔ{Y†$óÔùK¦ÀQ]×ù-^‘±”t‰wAº¶_ò 7ñJT Ó·î±\ H(M ¬ôc´ªy­YwA¼¥ÕƧ3PêØÑÖœ ;ô«Åháȃ*¬ ŸÇ¯À©KdJ05²dÒc—ùžeaŒRë³ì‘æ˜5?IPã\ßÜÕx7Ž c§(Jî å6“zm&½‡ÏT£Ž€‰Ww>%ø6ª8‹¢Á°÷u^-oÙëõÔ“qJ{žúìòvµ•H6 ˜½Ò[¶©…§Í"N;jKï¸Åe²bËŸ"ˆ²°(SQá6ë[t`¿¦Çf­E™ðD‚·ç= ÌÓ<îjJDÕ¬ôQò[;(X7°Î ìa®©@Y Ð Ñyo|fJJá™ùó°×8Á¯‰vÞ“ý“Øn»¡L䌩4ÈI ˆ g¢‡-¼=6È—¬nL|‹%œâmsž¸Ñn¢QÒ“Q”dÂþ™¡ÍRRµ2˜Ð¦‰]˜•.³±3}Ðp¡tÈAÕëªÝÚw ÙSw“b8Åî_€GŽlºœÇîxÒ¶ñ y`j¢Ÿ%7§\‘7fË«§¡ä$ ‹Ò(.+XAö ¢[3^›qMa4ï{ÚsSš/ö4}ÇwsƒZTÁÐÓ6 5°S´îÎe’Ñ;æ,ߺ”7®O.îX™Ë÷àyÐÝ]dzê]®Ue¥7PY([æo Ùݱoi“ÑòÙ«-®ÕN1ÃÓkØtRQ29|±õ2 _ äè!·½ëUç/XÐʉ¹<;Ûj´Ûy¨a–ÅŽÙl$oIÀçqD¼ÛyÄWj9M"d2¶K‹×pÌ­´3iMVî#–FôŒ"•³1 ŸJ+ž‡çèŠr: Qr6@M†5:WZ„~ÓP®—xAƒvO¬Yëíˆ=z8÷Ê¡ ‰wâ‘#†@Œµ*AÝH˜ð«w§8ÚûJ»/ˆ·³äfb `¶€™WiB KSÝëØ åŃb¾ãë(ž¶€·au-Ïž8ÍŒE#Ê©ÎÃócUóØÁåä¾Éw7¢fŽ ‹~~=ujÌüp˜:E€|C{BÏE×AÆøIN ‘3â7±þE,¡Ú!z·ðÛ€ÀT¶Î©EL!¼…Q^ôCmÏ¢0#‘ð\ u‡4{ –~Ö¯¯×aHpk[ÝP.²Î6³rY-üœº$Hg¥és¾‹ y\¯õ¤ä)7§×´tr´qÔŽ÷r%»‡R®3q§Î¬œHÃ2eÈàRP§ðk:_uô¸ t¬1ûì~¹D7C!ËÈüP&/ýbw4Êèʯ•SéßÛŠæy£ÖM€=oq ÚÌÕh e°EÕ‹çî5SÓ<üæÆéjVÒáQ ¼,9¥'¾*óts‚Ýaa€H(Òƒ%;jD:ÛÀ¯ùÉCH3F'!±Êƒu®õˆèT5áÆ'lúù9=k"ë‡OÞ<7_µDuõV•>àXÔË¢KMz¨ Ïúí:¸)Áµ#×»÷ôÎ;œµ‹±ø¿ì~áD»É¦N¯{#³’}P¢EjzõéÐÃC?ŽŽ2°à«Ã©æ3· ´íÌaIfC r£ïûòl•äœq ¥J±'tó(ó4‰Ù®MÂeßkº2¯ÇóúN êÝK "Kô \K×ó|„{’zkß{m{ÇóÄZÄ=bd¡L‰ [T3GÀ_ Pøf‘ÑÛâÁZ{W·†+GÐÂG¢à¼²ÕÀÝJTà°'ÔÏÅ=Àó »;J'Ž¥½Îuféù*ôA—äÉF>~è¼h5Nì;Y³uÓÏö±)ŠðãyT– æÊn•ôÈ\›jƲI¤ör¹VâR Õ¸Up}+n(§¹Nj5Áóùˆ¤^Õ!ã%Ëêœ+…Äűe`ÍJ^ª@„Ø;¥÷ÞÝ?7èíËdz7Dˆçô&‰õ=Ç>ýœc¹ìª±™78 ÇmA×Z§Xë%Cðüªª¶Ïc»•OC}”ç æüi² ´á{OK€¼žÄƒ¡Ø²´‹”¼È‘>f4–Êí¨äÞ½“d¬”Æ^p¹­p¨¬è³8Bñ…·g«o)úù˜£¦óð.œ°—]?TpÉ}ž på³ýôsb«!¥´ßó®òS•˜Ç”ÄO½ï/fC$ŒƒzÞÃôhÀ7Šðp&<.¤%ͪdÉöÑ®mámÂ<ö’g´{ É’Îå<,®!dp} vo;d’î6W:vßä(Ù˃±w·}yÈØ¯ôÝ»Ü Ð÷mIÁÅz°yï†MÞ:%’ßÏ[å’dHÕE¥WŽ\óM‰$¼îÅuŠ·,-m³$ïáK*-È]uóJ©Ü ÝWßKŽ­»˜n‚/²kx­³Ôcϰø]F=sIòJç‚öG$Š'Ó®± 2lBnó~Tëxuz Oç«ÂÌ1Ø|%ÙÃÞÒ@·ó Ø@§Qb34 יذʜfšEC‰/|=Þ9Á *_4«4cFø]‰b_ÕÛGv桨O1hÅ'ÒÂMÞkÀ¦™çHÙ‡ü”ËÆë9¢ç9И Rú0«£¯Ö ;Ee#±g˜xÞùÌíLüyO¡3ÐêÁ¡¦K"Wá[Ÿ¤ òËíÃ-pn#zZ£ù0¹ÌÜšg{—O_'™ž>SÝZVéG>ò\×õhߟHP# ¾PpÚÍ9Ÿ‹My% Ù&¥OÓÉ»ó®AYÅRÅŽx•lÌ(¯ˆSvæ&“7*â1æ]&ª ,Êéñ2¦Zã&!`¤bsàHº‹Yãå«…„sly•qQå2)Ñ2p¯(³KG'ù òOf™¿˜ÝdX]èõ’˜·[»Ê\^ò‹É¢¾Öéç‰qÒÙu¦¹›Ï˜î^ ïÙ<ݲ^¾ÃެW}§µñÞ¸ù{O²ŸÕJ!ô´êÝ;ÄšiMÜý]p×h@…¤U컥ÞÕVkÆ)ß×ׇpÎp«èkñtòM§tê\¼wħ!\ ˜HÁ=>¶ªsyÛA»æÈkÞG=>PdõÙôGÑ%ëžÝÜ’ "¿íÇ$‡4ÝÝp™!E«çÛëÍ(ŠÄsu—fJ¼’œ!òQMœ¹_¬£ö^÷ÛM~0Öö ŸÜi>^aZ#¹®©{ ‚÷¢ È |ô\ˆ°lz`lYÊ\(ô¹€gÑj•»˜P§v‹¬¢(7Ýe«¯xPÍÎUÎu»z•D8˜øÛ(¯¥ì·BõÂú܇`˜ÁÃÁdŸß@°ÆàMUÑ0Á#\öZã£^Kd'×’ ˆ’ 1ÔQËÕ2ÁÆ:éüHË_ß±Ó9ÍEy×Ü› 82™gyïz¸—3ØarŒ¥´«Ù<:%—Þ`¿$PëÈ8[EÌ)æ`ÈQ¢f·ädé/òâ Ø#éÚi¦‡ëf¯tr¢9ÈäCdÂÈêºG…«ÏUMbÄ÷l)u©ª±d•zÇ£¹6LnÒ8kã…ÌÝÄz#P 2Å{$4Á¤zg¦D.÷Ž:ô¬v^¥;V[¸ÒyÙ\†æBÑP†ÙCåÅb{ ­†ÛÝ›ÊÓj÷R^®`Yp^³<Ìåcôð%vP¢EzEvI¾e6\|«oL\õjÆ”p…iØ ãS€s¿iîµ×Úh$¯Ù1(ÇvoÁL„“«X²“7ÆËÛ×ÌUË8úMå3j ÕLh‚ã×® ¸i\+u÷ ­Ð´(6R¶,`§:‘¤Æ¦óž?\«2õáî~ü|éHߦ\çÕ,‰Å–øâH¼‘³¸¹}ºïÒáŽÎ V @¤½å­¼žÒ"¤8ÖQT/j²û‘tÕÔ$5߸‹Nõ.ÚÃGIjá“çÀ2JZPs9Lµ-()„à¹3óÖÞ’“èÕ{äÀ/ºÒ^[ì´¾¿¨85ï¥0hçMÄ©É{ò$5h.„ÔC¾`E5…J§Êq• ‚x4½*‡P’‡õÌÏ´jAz¼}QWŒ`…ì‘^Ý3I9ð¼narq}Ú¥€ð4Î^%Ñ¡IÕ-?.åMÜ O+[bô%Oý’Ë•î©?—ð—ñÒVãDeÁ½ñ#Îb¹7â4¸1'æuí ‘AËcªü¶’u ³ÐìíTÑ4+¾˜¡ËA–HFDÞu?~13 ¬ ´ôÌŸXXq­Ú^o_6ùĽóòn³‡l ¤Î ÝÔ­ŠšC{²p*Ïèboõjc+æº9#‚pÈ« q|+ ”U%TÍÑ{}Õ¯ýMßöÑ鱩ow·ë JryØ ÏɹѸ‡¹ вŒ9Bómñ¾Yh^Û^ÊZÏ+‚X Î.m!ÝlÉô‘´ÅÆ´>{ÜAb1¨täJ[ F´4½òænS(Y¢¢q Õ, 3X²$lk\˜ó¦0/¬÷Ù6¹Í)mâ:n`?’! ™,¥…X…àËzd=}K•z¦Ðtgc”ïJMì̦¤r4@´j^ $$ñœrÚËê×û®­¶éÁŽN ·’µ—<+H!”ÇBÝA»|èr, ²Â]!Êfâù°œoõÞt@òs±?Ð>/˼{ÅõI­Âµþ´— °é)¾[fK^èw¯ü!Û#_˜H‡ÂÐÈPÕxvJN§Ó~twÎÏÊœM³›u¹Üö)ÒH.ÝTð5éH38RÁ†˜ÍDÈ ŸÓ¢C?K Qd¸vß: #{1xør³<øˆa‡kÄdò½‚¥‘§÷fÏ­R^º£—ÃÞî¹HÍ Ýqêï‡Ü{Ö0«júU‰fú«®. ‘OÒ sB@½‡/5TeøÕQ+†;Áú% ì:—:×!ÃD}ï=£µZ1ènjS€‚ÞT|ï®Í­Œß½¡Ç*ÊI#áÀ1Aͨàö²má!¿ê—-OuW›•°I2ryï4Ÿä ÑKÅ`–xJÑà¤ðœ­ŽÊ,Q¦±ÝòàÌ…Eßú]úïB,EØó»áõŒëåeq*з÷”™ \Îé®"†!ŠOƒÒ·62ûH<(ß¡ú³Ç¦/žùsc!¹rð¦ 8¼–±|êY–˺„·Yì£j)ù­aÛmæœHiY’ó” ³(*ÝÀ¬çuùÓ§9÷¦ƒOpç„°÷ü’ÂE,V^¯öKÍ™Sã Ee9Î(+ˆk(ïdYoMÕ¶É (œMR¹¼¢q¿„óFÝV/ä™Þ}Oº^ކ/Ï‹—åë› Nrž³µ»:ÇH ˆj¼ò˜´3YÞù,v•Xüˆ7ÆáÖ¿¸ ËÛÜ´^§„=bêg7J:¥h“ÛС¦ã«oÙ§^.>ðÃØãŠƒ2bÍ„%‘5yRÒõkQ6Yžõà=i¸X…&To*à›z3nÈ U‡û0Þ/.$qm¯ ZpBA0¹:ì0í'H?*PáEã'FÂÝ&úKXù9šÕ[1Ã}/–Ýtû±©œ4 =V|'0äåy¸Ië~Sn·ÌñðÝÊÛÙñ;AV®òÞò¨{|ð;§ÍÒoÙ¤ ®åB6^;–+½tVìïÙNÍ‹–0—1 ŠÔå 6}TŒÛÅ»Q-«ÑUƺ$Há:/鵋\­z`ÖÍË´ç-í\Á&oB Ëïí®ä“¡(ò ß´ËÐ[H+¶™ujGˆ)\è m6¼§úÐWnB GY=ŸÖj°>9â•ЬH]MyŠûä ôxù ²ä+õéµWƒ‰ïi ¾•’yÕBìg¯Õ°­½Ü;”ßc"Y|“,­4Q¢ñ–õ]( §Pqå)Ï-Q¼åç+ˆ.œê• éòmÄs&æó—{Æêìóžw¿¨{"„Ï6à™¢…DÒ8c¢Ø±úJ˜ J5¿BÂ"±Òpz<äÐ|Œ[®âNËYW,†s]4Û’últ]í¼dÁ&çÎ'ß3z°ß³­é·¦/ŠïŽ ŠX$ózÍ)˜sS6Àm‹óÅVh•ô«Ìƒuõv!ÇÀ ²kV—-wåQ‡!VBoÑæ1Ž=zý€6 ü¹ÑŒ¬ˆgÏäÓ‘ÄòÌDÝNEàvRwyÔ^·h%Óq¼-·!•;χÜj ®¬ï"H5Óγ1.\‘p®Ã†¸ÕÄK|{¯B/7w4)1 ÿžo1=䩸q=`7/|+bÏÃìñc„=àBNç€Æx‰~M×*²„¢é3¯ D&K#æªuEM–Ç‹AQQ¶-,c `Aç*¸g½¥ä‚ÈÑŽjsDõ^Ï›3Å{–Oì¥ÉI£fÒ3­GI*D®bùêH›çAFãXñ\ǵ$ïf¿‡Z¨bœdýH%ò„Và ‰ð1UÝR60‹”J”#w¹ûTuÀôK¸iyžëë·KWàr5eá^8_¢)&‡búÉÖm?¬E—ƒ`9î‹“$Ìlœy‡÷Ú*.A@ƒ”OŸú.Ï«%Îí•2ØG>w üÄ­_¾ÕT¸Ë׋Â×>ËìÉ|'égAHl!¯™K*£îPºõl÷²“Ï•CÅËY•gO¼Hh@ öØ+’X;MF©wƒ€Œ*š ôæÅMúäð`¿Ìn£ˆažx<„´xÙ±@im=pÊ×fÁIò k˜ú £n+ç{A7£¯f¡±Æ¼¯U¤z€–Lží*^®rºuç4°\ེB?"ÎtSGE;‚v|%!îûT•½ê¥«C=~˜< ¡×Rr!Íè\÷Ë’ºv‹‰oÀ3¼Q?;ƒ—ö.Ý8XûøAòzª‡OúEpÃËzêùt³÷-ÙÚU¡Gar"wðƒ=ñ÷9•ö{¾õïY©à»V¬}•âÃcëpÁƒ,ЇãP8G«îÓŠÀ!Q #þF\6Ä< rúž6;?ÙÚ‰,®êµ”¬U‹Ë¥©}²ÞÃR 3ùú]UZ¬k—«Ší’;ÏüxWEo›žÝònU^èâÕÀ.çÖÀFÑ _àdÎámÝk¡©LK¸mHiÃ+óõ;ð¶c‚†N¡vX2ž¨VzòpŸÉ-#?-¥½6Ba“§/°‡_oÛ^F ú+WݤfFÂ|/ÊɆž’>‡1Êô|£ZËEC›LzX Ý¢< ²€böl&”ÙÐÖ¶?ií¶¬Õ&°c`wbÛÅ8jÆé Ë!8=µxˆtŠç‹O‰å $frHÀ•Ú¢öZøQ ”—'÷‚çC2 «¹÷ÎëœM–8QY8ÊÆ÷è1*œ#¢©ÎÃôhå'èh¹œï ]øB—ûÉ<àé©ÞÎ0>c¯Å—×Ò"“üçÈu¸æE[—óW¤V`ýX•”9º¥`†úˆðl¹s$×F„ËÐȪÕ½'6³Y’ÕÅŠq/_ŠõyÑ™š¶ö9ˆzðuò0njÓ@²y´)ÈY•?ŸqõrÞ*­™T)¹#“CDÛÝ…rCÈ&>X¨ˆç)Kt-¤'±Ë'zT™3TJ|ªü§JvBäj@ú­8ÙãÚW ÊBÑý¦ë»¶Ê±¼˜wXø…Dó8„Ìùræ qжéyÊÖ¬È䥂äé ¸ž>$t•Òå^¤eÖ†2ŒtÑBe›æJ|Š, õ2ÑäÙB!€« <’lO åò|ZY•‰È8½®„j‰»<™€“ZoÛMòBŸ’zO„Ì„Ã\)›6T׌óVÊ­«M |0ÃO–ÞLóD±F aÊ{Óë‰aø _†À{ñ6ÄÓ¬§..Þuj’¿Ý}Þ¶Ôv`޹¡Ôê È£­ôò½ç‰‰A¨A’ü(# ×NŸjNà^ó0/Ð ]¤Väö¢g*¶hg‘81ÄòcA/Zë;î;8yz~êHêk˜›úLMíd8æ½h3ÁˆRoçç18œLš0LÀz£¹ 4¼pì•´×ÛçXP„:à*—£…rÒNJ…Š@âÛçk“÷ôâ(­<g C$`©Ì¥_>©Ø-Úˆ÷ÞÁò'·O'pèä”ô^7_<×åq”ÓòBòŒÆ—Çð\åyÞ°£ ì¹ë¼™²3"¡²·qÌcNÔÁ"·ˆÞ:ðn‰ï—¿Õ6e !;ìmYé; D”Ò{Ãurgò”MrkÊ9 ÷É[ܹ.x>ÕäÃ;÷HFû±ÅQ¿Zµový‹Ýy«ÒÔ—ªtšÇñFC¬ûeætïèÚ[Ÿ8½€ ˆU5”Ñ sso޽ p+4ؾ—é:4<˜ ’ {íA|OeÔ´^W,Õv ß„¿Ùõgd¯N´“ŠV"§ÒEC…5Ô®-Íá…R û ØZÁ8é`¯#=«,{„é&“GùÂ}JoX8n:_¼Ñmy†ºÑ^•ìÁ{(/ïŒÃûéà;¯- ÜìBeqÂê¸>ð¸VÃ3ªëáµ1ˆ|néÑ6ƒÄ×€A%®g9f"ý4}d®Kg\D )@÷žÅPW R·4ºZ¾p‘àøâl¥V{½­óŒ™ ¶­7k?xœ›Ý×ÏËXÆÄ-Й"¤v "ÙÌ«G€3ûfy‰ ±fUGL룤š)õ8løð‚¯¨ROp®ï2+¡­ae²;²à=íåÓömy]¢×D¤¿‹gOüŒÁŠ7Ù GZ€âto5’R±2£l'íS¥N›ë¾}Žb‡ROÕ‰O¥ôTÜÌHÁ¨"4ùÔÜ ·9ÓD¨˜™÷{‘B칓8—^±#Z‡`]o5`DóMLÁk¶eŠæ÷jÓƒŸ+¾—æë[þšV«iMâu¿\j¨I±W]¨kÍlòÜìËãi ŸTµpòÂgv©ó2&Ï„Pã¶v›ï Ä£g;Ø©½J‰D˜×n„1ðV²o$hNõ6ÃPx•Ø%Ÿï%ϼ]/$ åVˆ£Ø„ÖPE $Ê6ÞˆŒ {Ö˜d³Yþà-»-‚)¤Ž§½6U—2Ôä(ä¡hôæ ì÷Ü\¦AË D aéëSÔŽ6W½êåIð „­« ±%y{e~ä“$i„ô /ê¼ÎÔ-þX^(ÑØ®íC×—TîÒ¢ •JSÜ”ïèi-TaÚ¤“"aÒmЧ•vÙ’qêiÅL=ŠW‘Í•¹6'­k¸hghY¢‹Ô9lZË¡à94bm؇ÆgùR<ûõmÞî²7dì¶;‡ïÛkÁž0N>3Ý:„IÑ']R$ R[žˆ^^îºpQ–6iHi†ö½ÃŒÏ‡„1nz«ŒßCR›—Eþ¢çíè,ìmIù³Ãë®õÄ# "~vÍ[XEo—$ «Þµ¿â‘rfËK¶ Uf8%–~½VìtÝcêËOsw¥I6ú¸ß#G)C wºš“TRЬö[3¿“ž~¬ò ª|P]ò=€ ,Ð\ÜÊ}OûYÖ¬ ¯:¤EÔ²ž¶[â]ªØ3´lTÏFíºª“f=Çä­E>H¸ÜõWå!íGf„C²"¨¦ ÀAÌ´ïì-—±¿B÷·IÔÂZÓæYxé)0:¬[ 6 WÀ¾ÉW»¼’˜*ºH›¢ë~q>ÈC~ýÔ–ˆ²:Ý·à‘«Ñ4><0Z(5–ÐTTœ‹”7Ì#ïR(Òš¼×FÒ°ÃÜÁHF0ÅTð)<ž~c ‡OÙS=‹Uɸ„;æÁùÕ¯™ë%¾!{Ξ¯JÄ«º$âyÙuë-jKj°WAÜ`9ºT«ëkœ8¹;;H§;èÞ>·¡¼ÙQ^^®W’ïL• į/Sc]c]&ÏfúN{S¨Qî(£·=‡Û›ÚF D§Xs¸ˆÉŒÖã1Š <ò=œ7׆OõÂ9U…\ß`ÝH¿® Ô¼©±.«[q §*[ó‡[ûTÄÎ_º]!”ú ŽXž§°4OŒÚ²é%þ¢W›  Cì­±«â†ßÖ>R1¼Hìt|óô¹<Ì%/v…£×/_z66 ÀãT…¥1\ÔyÙÍuÑK(­‡RØpmk6oÈPlU'£w;Hüü¨.¨8;žÅ›Ñ¥Ø¶³OCæôuMõê•8¾-äè¤ Ô@¬] fks ÕX¹} Ü["D”"ð.â ŒŒˆT ÏšÝÓ4¼a42E±6î™ÿ‰/¼{«×Lœ§Ín(Å•Âô¬¯º¹È’&ÌûòüÖרŒ:úìñ˜˜W¬ì¶“/›íM?’%6»ä{6ɹú<©á-eÇÒ§×rù#óÒž§Úc¤"ä]º´f¤G³L"üR0ªë•ÐFAÊ‘T¦ä›s®bˆx¾V“Q‘sVC —ýÉZz4ã=QЊ›|Я'3¡HJ‹*7#Êâ9Ì{I¨æuvãPT†¼¼ŠpEBY€íÔ%Œ˜³ñ*5,ÁB3R)/eËÛ¦.±íúŠ…™^T»ˆ÷ {ú»C Õ§‰I^‚dÀ­°ÒY¶x.«· ‡a³Ê+Üͪóeø39êâðôY™¬ÙÞͤEHœ†ËÚpíXeTD©tÐgJD·¢“¬zéÆ``ˆzGˆ•@žúÞ>H>"¾§Ê¥¯ÔÊT—ÕMR³è6O¹Ÿ¸å»çFƒë¤Cë­`q(ÑžÂ÷´Ë €dMÉ7žUïÖ{±øvçûËüÙC7©:Œ ²Št[™á½|ŠåZ»ˆá%¬¤ƒ w EñxÚ¤Ç ?²§Œøîù¾-‡Wy C`‹¥û:0ðE¥fð^˜r à#+R޳\ìu¦î]°qÒzüºeˆ¡ œ_à&Ü˶¹3ªë7óŒù5²:e’µj“ó=Æ‘Êéëçø‰ï£/|˦Êzén‹É2°ûVý†áb¡l‰Mt¸ÙzDÀkšlP Þ Ð›¸¿l±;Ñ€#Š<¦¼w¥=òÔ(Ë®¤^¾êZ¶Z¼yIdÞ¹žr£ØÈïÍP“B‡g¬Ó)Æøà ˆ[CtSŸñ=V{¼{´ìôF©2Øq%ëaân3*ã:™‘•ÄkyªaíÅÓ©u“¸ü‹_ir„W+Ôäâ±­å›ò¶Ø42ûÊÓOÜ$•kùà]GbgúŠS"ÞµvÜpW¾“}G(‚Üu΢>—´½DŒŽå*KÄçÖ™œàÓ©°»cÝ7ôRÉzPâÞ£T©nv—Ë÷“@â’·ÈjvÞ|wa±áiº–ç]ÁnÜ ù€·;–ïÛ2CLŠUæ0Ò8wž:CÆ#D|´ÝÍ+Z·=”ÙžšàáÉÆlŠxQ0Íóšä¦¬Õ™BZài‡Ì±y Ý$qÚ{×¶àu×éôÜÙjTé;_Ó(¦×“—¡bKU›=€¹é)š׃È+:Rª­c¶t;Æ}NFw7qœ0 Å5½Æ„ôZ¯­\âÅŒŸ?Ë:Š€ÖÙ{ásTÌ˰¯IR'–í°FŸ^“i„ô1cå»$ãà Éz„³‘’Q}„Á›Å¸sâjœ¼Þ-ç þ04f¡Ñv;|Îý)Æ%ÎYðÑ@<£´=‚*P&C’ÒçØr ç.Ò3¯³¹9Ôp@ÞØ†‘¹ä]èûËÊ‘}¢"wëCv§}{ðÈMyÜÎ\O«{нjÉ«W2C“Í6Ê`ÐÞ{whz´¥[V³55`Œ¼rª…ðžã¡“òñˆ±&ƒˆƒòp¬°ó3Ó#ב̰:޳R–½Šy˜F1u: ŠruËá>Ÿü2|ñëO"&Þ‰(®Ö&=×jºã½Î…'\çÌ5C p„“%×óCSÁ²I°Â-~NgÂ=Ø!¤nþr ˆàD€œá ×Ái^oà¶'œ=¼P!~o¥÷±G™¡öqn¥MOôPdFº’¼ ö™à’•±Ï…jpfÒreXŠüMèbWŽ¿n|”eJDÞi%Ÿ@d•°¿†L|Šº± Íýä–*½Õ¥œÅWÑ‚®#ˤS$í”ûÃ5†`ÿ%ÔUÊ{44䪨°9¯ …¡œéäêm2LŸ5ê…‘!¡œ<µ›ÍxVò Ù¨”žRÖù8Þs{¾›ˆ¡xFJúN*Wn‡v˜2žöbb ÍÑS˜9žíÉeY"¸g#¢n=ïq±]y‰°r–õÉÆ4ô ŽBñ«¦aõécÒ€¶éëÓ5y€M\)Í^ÜJк>C°î^¬7´\ Ï2K¸ÞùÜŠUˆCg=Ïð·-³Îyâ1ñâÊNwÚ]-`°“ÛΉŸíÞ’â.Û3aÙ²gqQÊOÏ·ÃL6ÑC|mYÝš@˜x96x¥cœ:™ ï±ài1cf½ŒÜ¹4äg+Ùä^•R`û€ª§â¦c©L?ÊVÊwy±-\7‰½/B¡”šïü&ˆë*Áð±ïÄaÓœU¥jš64vD÷™“ƒàAºT BñŒá>K³¬AØÄ; m£J­-a¡7Ëju€<Ð@ЛæÕí‘ZÛ©­"ƒÚÔ…Cƒ‚äWÛtýܧ_äΪEÛra}KêL¤‰`OE;ü\\-5L5ŒÂ= ®^Âꤗ©"<¢¯Eׇ“‹X{úäê ¢@—ª¾F|õåÖçT;ê^XtÕ›êä—ü °LµQ'¤#i2¢2ƒ¸§¯Âb@]%ÚH¼69Ç%Yi–6ðUŒ›_¶*>‡‡˜Þµ#ÑíËÍ‚¾=ÔæYØY§Zwþ6륲‹À{!0ð8•\;^âözP¬>—–}Uºéi W:úí#XÃnÞb¥¤TZª[ðƒîœx«X;%3PæšFž¥ª¶ ¦ƒTWÓÉ‘MóBtØžËÒ_/Ya¿J²iö#¨Pæ»[8E¸ ˆb§!|ý¸8® 8ƒì °y¨5K;ªZצ4ôl/ÑMJ¹m|Öª¾ËG¸¹:dÂY(ĸK¥Ò÷4ÌÒ¦{UäòJVoΣdcÉ`«Ôæ" †¼fø$Xô‹àNÓy‰$!éhê¤hêìj"lóÖO ‰.ò´a­W ˜ÐõÖ€Å2Ö-Öâ†SÝÛ ÛSlg«„ÍЧ›ç+žXK'mÀK€¬óTsë¹¼Ú‰Ù¨½ ÑÈöÌÍgW†/ÓFÚØ$}öŠÂ\ckg GQR&éqè .bV’^Bš…íÚ,¢…+ <¥é=3iºE–œÔšÄîz¤uÊüÂ×²Ùør<_7G….N\†ö²Šïe·½àYŒLKòîš}Ö‡8›æÅM‡dó²d§ÀS@Ψ JQÍsÁqñÅ™âÔˆ1ÎAÏdJCª„ÉÚÄDD\™=⧺GT¥ïÈL/Òü%éë}(þ\á^¦*ÁCÊNx›Mý¼R©£ã ’Ï»áz:‡‘½£QŽôsð+ © ÒIºyÚÊÛÝÀ±ôÀ‡žZ‚ÆŒòÒÜÜŽ¥d0•sKij„èðs~e‡œ Oá)3»AaÅ£¨çä’‰€Qº€Sتùb/Š`›WPö„uÝ¥"ömbŸWŸèà f¾ò‰b·P^³÷Ô;g1›´Þx.ó,ý‹zØy­Ïe¤Â ÅÊó\è¤ÓªsÁÃíy‡ìÊ»Pˆ‘XÙŒŽ­j[¥ÍÊY¦©e¤Ž&ÞLD`«§´ËÏwô’Õ¼xÙ[Þ¸B$§õÆ|²WÛ¡Ð«Ž—¼wÅÌÂ+Œ4É€XîÉeÊ›$™®XfIgç7IxvOG‹ßúë§hEÙA™ñLÃFÄC”®¸‰ÄÅJ{O7Gãe‹¥œœíݸf?.€csoNá`ãt!†·×W(8ÁØÁQˈ‚iø`„íÁ)ÊêóÉ%~›Y¦ì äݒ«ZoDÀÆÑì1:Œ©è˜©YR+ôåŠ:{4 ‚Ö¯R-ÀJ‚¨/¿ç`å/„Ï´\¦Õ˜HFyãAèàRYåÙêÍ{E¨ÐÔîÔa_ŠiaÓ<Øó3ßó¡cCˆÌ‰wÆ]±6V{Ö!ëy¯H­=eŠžãófñ÷:¼›“ ÓÈèíqsº¼>‡„&QŸáñ¤evÐcBàÞ•§ä+5g¥¯ Þó‡û°Üš¸µu€AAD­wOBa.ˆºXc¸Íí¸+_ sbvà…Ü_ [iÝP8vS¨F"Áǃî•b6¤µœNÄ72OÛjQȧ’ñ(ýQæÂN÷s.!ÀW‹¶ØŽýH»ïNöQ‡KÒP ]k/›f×Ña yö“‹·çD)*L ÌE!IÚ.Ë•çåÂ쨕Í&o¤£(oê!•l{R‚Õ¼A³ãjËÛÓ… ¡×6Ìr^„S©ëy‘7Y"°˜ª ¡6:oîM¸•®RŸ9¦J%#šå”BY§¿k¹ÛÄÁ ­‹- äJé¥X.„8€Wž·³¾Êö 6|Ë’Ø¥nuqmui¦1׬¦^ª4¬X®QA'W–.m3œÒ½·®rÀ~ª·Èðâ^ËܳxŒò¡95Ý2”.—í2Ç% 5л´ØlKÄdñâ0·vÙ92²Ã&kxYŧIMŠ/}xî—4¥;+KéÈíu=‘;ô)ÏO—£jy¸W[¡G¼lïm쾃Êž¼×s¦SÐGÆU%Žd¯|[VÆi•Y‚Ë}J CéL;iíE (æ”#¿ŠÀÛ(^á¨ÝØ?dX²w†Ñ*êÙ2#žI1ÙÒF/rétòeAµÇÀ.KŠF&\)#̨ x8¨ÜÚŠAWÏ›(څظ+g4ˆ»=P•¦ÐÞØu\w€ˆ±mš9AÏ'ÃF_ “”w4<ÚÔê±÷îÚ ýª(^ò¦Ÿál"š¢Çið>¸S_WJǰò!&{Ä/…,®IYk¸¢tpgëˆí9†ewNG¥ž¸Ev¤ºf¼¶ôy~!¥/'·Ø››¥û¤büü½×fÍͱ]àH±\¤¹¶º‘$ŸC ¶Ì«[-!BTp_yc*þ Pq)ÅÌü @3k$ñ/ˆuÚ»‡ò”.Œ¼öndÛG}ˆ±1ì¥sb€Â–¬òŒ_6A›¦Ç8b/)ŒÁfœm·ùÖ›DîpôzØ<†FÆÓ¨¼-yì5¨ÌP\›º<ìô(-SĦ‹§r4rŒkQö ø•ù¬W8LM¡}2ŽÏqvõî™<i³+j¨³X:köá •(c O„‰x{Æ=h¸Š2óœ…#RXë4rH_c9K”Ôëzô{·*ЃÄRl[f!œØJL@]Ò[-JØ2Ï÷Fó8€Ì-tÓtÜ@+B_À‚nÀ mî<ÌÃq5v4° ¾ô‡ÙœÄB¦Ñþ^Ñ9K^¸µcÕe&v²cVA‘D`Ã*úÓœÓ#™AJx”D¯Þø õó$]ØØ“„ÅÌÈþ„Øáb웦´î²{ë íÞݳeωËhsïw¯ `íMDè[ìꌧôŠ”7^p.{÷K© ½«öƒ•w–(Ds²šLåÄ®Lq‘m»ÎEMÞ›ÒhO<~¼s:ãš°ÈØpi—«­¹*‡ÞñÒ…bu¥D^È‘ÔÒ:d¸SͳC–Û®­7Ì–¯yY›Pˆ»EzFé„0+(½Ò¨<,B›£ŠìaxYaÇþE1X/êJ{úfW;° _"ðeâ>ªÈÇOí:íôM±²C©5ƒl£nQ­‚ªzEÖ^/åFÁe3ÑëâgÉTxª'ìOÛ\µvqUÇÂQÜM±¦uN?ï ']‚*ägV‘”@bq东GæÍ«Ídjqy¨ŠBŽãÞÂNgKÏ &ŽlH÷Á †xÇOå<-3j3ÀaãóIFŽ,–q(ímìw³Ò,|½c7Ë ‰³#q. êó#7ƒÌc}ÖªM5ÝÌöÛ·r•ùB«KçZ\q9lOLoPöŒ_5ÄÓób+Sµ|„Š,/jx®n,îU¬v/8¯gjGN£5-ðòÒ–[LñhZªví ÷ŠÓ=†×¦uïV!ç‡p”Ÿ#ëvÚ+2s’ÃJAi×ÇÒM7ª  ùÜØ½zäYKÁ#)Â*U ÓGî¼Ñ€5»„w^¸SVGAp™ùÖs†¦fÙ‚žæÐ’3*‘›mñ®‡$ä…EÌÙNhöæ°yûqEîÌ­]>·ŠVÒJH U‹¨gTATÜwï”𵌽†1ón®èU| nPH]o鑽»™ôÉG÷ `]äæÞ$[u2CF ‰Ös%ÉAÏzð\dŸ=µt¿E¢–& CXß¹îåãw4i;3¯œQ¹E­È…ö’”ò â8V |ŠÌweoñàømyíH¿Ãí, \ ìyZºiB ärªÖ¼(±F`´¨Âb‰÷(í–B•Að…Vb5©¾ÃN?´Œð9ñ¤Ru±ð•wyQyÐé·\*Ìd]"Ì®ü÷Z™ÚÚÐ «AGZҡߥòcêË^h10T²€7{N Y/x4èy\DJ½EâºײwïØ«¥©ï!¹6‡?2ëö³¾Ç/â¹{ï<ƒéx Ÿ‡~a|领s69‘z·–/+"P O”C€Ã8ŒÝ\-µ™µÀí²#áèº}_oØ2=–ŠWr6ObÞy÷pÕSF,—kzä[Ђ]ÏÀr±ö‚ÒKŸözÍq!~®çû\a ·¨-Rzê×Þ¸eçÉSâ'›Û]B÷\Ѫµ¥©uIcsðj46‡s&©¥«¯.|9Ͳ(ïÝä£÷Xçùá´ÿÉñþÈLSMHæÇ9¢>ikò|MWP¦-y˜2ºVžÆ¾¾Ì²„°ˆŠ.Õ`˜5 RAq\-x±¦Ç¬ ÝS뱨Œ=?Ì |µ¨}º5zggî7•ÕŠ(þ÷q“Øöb"ÑÚ¹P“¤ë¢e7¼v“«©¨ß5nÕM­áŒò«Ô*Zê>ÖÁƹ˜Ö3[K §×8"©ìålûÂOh€FôQjÊ%à\Ýt)ÌÈ¡¦$£˜Ê7ºzYJäΨ#òÈâ-Ç)®–§ú¬óL3 86wí{”-Þo=4ùù +®OY¼€lªŽ>MXd«gj–Á¸µ¯h½“A}”=j WFË ä)ê{²Ý6Fè…EsIHÔt3$B¥3I§É2õu޼™“©´Àýüe<ï}a5͸Qý¼)L­Bù–ÆOçB÷0¥òùÚãGöP¾8~À_o€³åª…]5”ÖÓÑ÷†4~c$æÞ)P:ô„6‚O*U8Qžjùb‘û8Ÿ 918Y˜¤é«fi+àë)sÌî²Ñú&#øáƒ…8Áë­Ò}6œ²Ù§ð"ÙióTµ%å›0Í|±Œy*ψß5¡Ï¥fñŒ£•æ ›“N ËÀp‹Ø!ve,}ÅÔÅMQ7ca’ºsMÆÙ¢4ÀÆ­ðØÌ{¹IÖÿYœÁÔ„ Ž7Â'¶â¢: M–í¨_º{è=ìËçaäõ2žQdçËL&]ê<Äì$¬G/¥]ìæ™]’žéÊ{«ö»é;xòÓ£ž`P§Ü‚Ó‹ ‹´&1ÂEð°ÛÖ4kNÞ$¾§àO˜3 Û.%¯ËŠìúÙ*ÏÜ:™û»„çQ¾æ¢¦ôBû-6.*.™©<ï[.]•wb ƒb€‚´¡®t¢ºXUí vBðejZGk=ž B§%Ìd zà—Šv±°[wTû4´´jØcŒÁL–¸O_ ™QyÉ= m;ƒâ{t2Ý{ú(Ÿ0Æ3ß9œ#7@ŒäÃ-èP̵ ±)¼m÷J¤Zd!Pöì׿cø”ɼÂL}(åH>• [›–‹3Ì;éV•XetÕ‡âg}Éî8{OëA>e’fŠ}Õë¸í„%^º‹-WÑ1ñ"^7öc B ³°yÑ-ôæQ¸mÁ˜4¬ÐÞÕ›FH SmB4$„L£x¤ÙBöjG‰z€+ˆ[¡‡Ay4ç:ïIaŽl²FÏfèÛ°"÷WM´1@SäÍ yñ쬼dýÚíY¸ HO·Ä›%k¸ËjH´gy¹¼ÄîþÌò"rÞËôéJdÄdÕ¬w4ÉÑÛ¸UÚT«÷Ós»X1£\µThz©Yp@ Ÿ #}ÎÇ:ÒTÚñBøZɨš;#mÞR‘¡½ƒ¢Ž‚å”xñÂSUVm5 éÊ–{‹ä­ƒ¿ÁÞ2âl°ˆƒàe:=B öXgݼHfy{,/ßÎ4ú1x›¥?2Q´ËjÞ|Iþ^¦=mØP%S°˜çëû\^¤Ábp·þkxþn0 רæÊŸ Þ<ÂzVé æÉ± ŽB®‘Þ)vRÂ;†Ë7/[Ô(þ"y¨N Ùi“ÛGP£n»ƒöj¡€I.ôíÔ£Y‰`ÛzÂ@W›…b T­ë±Ð•ë^­Ž%x‡Ç²KæÉ®ëò¤'†Œ’ùÅö;[•ÃF$ˆ2ò2ß\KŒÎ†Z¾GÜñÄ£!|cކlBD¶Å'Ò8¸²åÑ»]EµYÔÆU&K µ~ïÒÛ˜%’8ûå3K™€§ykGÏ\¾?6¥u­—µp%žYo®:³?yÆòø\¸„PK°í(¹Ñ½öëvrÒ‚,}){¡nͬ@§X‡yÞ…Y]?zDO&¤¤4·„á§“ìjø³š´ø‹Ô¥±W Ï2–&ü^Ft‘/oj½ÚŠY‡4 ö2hxQÊF_{Pê–ÞJÆ’>_ÌËÛ´f/øž=i#ÀTÑ;ÈÅH=IoFI²‡ô¤Ò“Óø¬z£› o+蘚¶T%÷ Êßš ÖK~>{eÀUO+mÔªfÊ…18ô½DФJ“xpNÁ¢¦E}YùI§Ö9ô潃qó… ÒG@é›!eø4:ÄíÙ¸T¿ºâ~,”lÝ‘•<bIÌÑØåÜÉvDʆLï KXPY¼éíÃ98‡‹|[Ï Öx²†‹¬gJ@:è0'gù³$ë»W ¾pÐïM\Tq?L”`Cënè)CŒ(ëS°¼9ÙO’ ¾HîsQ*¬µ™Ì{³[äÄÊ¢Ftª§¤ï]‘Gv®ú¤Œ„‡îKE•'^`Xx4ë  s­ÇÈÂR•cdŸZ*€""x¬š>£—Ú™®¢QæÐ)è ‘,n¥Ç‡»I|4‚ìïh bY<êB0.[°x@qIVAÎ!^•FX5ê”Ð[β¾\¿Š 8 vè…&ŠT†¨1÷'ønP…Œ]—§¥áÑ™S˜…uI`9ÜÀm8¼?·Š-¢$b[ùâÂF²ZÂX{åbt‘KøDÇ›X®^Ͼ—ÆOžÎ¸Ð‘IÈPçȺy)FøƒMóÑ"]êë'yŒ[%„²ŒJ€)>ÎŽ$Ä–˜þ0ôÁ”ÞØÉ÷G\ða0æu˜rSÍQÁegX½ŒópT³+BáÈl8c• ¨èNsTÂW/Šœ[suÃÍžj6kHaTÛ¬û½UÄw«¸æŠ{ÎxÞ¢ÁØ ˜(`xA¯½” ·dôÅ’Ïë§p¼ÏO͸5™aÔ›<|Mï½Mײ\LCiµ2`4ƒ"Pùžì)öð$[é°RD{&#yp{Èf·©4Ï_ÙÒ÷H”˲¤c²(­ ã49òÑJ ïô„F~®©ìÕçfŸÑN4D2$åéB¶0ÖBVe9ÍhÒMvlV•·Û‰Ï„T¥M…2¼Š"ã§Æ/Ì1&m«¼šõ*)Ú„…÷¹ö3ާ§²9† !]iá*yÁRŒåÅ£áÔk0æ5‹D7Ÿµ~jXêɡܒq=®“iÕR!­Àœí$•[|`//I€úÞs§€‡à¹{xÑê{iÙ8ÆîØ Aß(ûÊ”½³ ’ö‘Z0É¢H„Ë”=áÖièÓÎLï:”½‡õ^sò#5ƒ¹X|` °wa¾l¬uжz¡F¶ÉX‹ÂõmÙ!¼­IEn¦ÀtÒävB¦¢œ bÕ†@ 5o‡žaÐ?å!„]ʼ—Ú€wɸê-p##O-Hç,Aö%Sتè]Ь½‚§}^ÞÐõXÄ©i¼œ7óX­Ú$cð/–ÛÞøe– *Ô8-s¿Î[Ee¯….D5âÕÓR1uVãâ‚ È mpy[ãÏjœ8rj^)$æàõyj–/dÚ†å›ÚÙ+~¯Ÿ<Ím)«3ÒZUs¶ì¡QžÐ^A†|b—³°×ÅÀb‹¥½Ãx‰@ût-‚¦àm$C[Du’R°/š‚€ÊÕéó+†D±bé³@L“702çl¨)†HµY̧xg’9 •W)ÀÆÒ·ô–WaÕöE<%Ê{‰3š¬RÃòf^K¥ õÜ;œÏ4ÕšÞŠÈIö‘T/®È=0ªÈljÈí.mË|Üå„ ó,‰f_ÞK ˆB,CÇfª2Ï„Daæ{L„«¯ÆoÜFùáU¼¶î禖"ó`ž°ˆBÍs˜ò憌qêçÂÊLªe!^d°&e3צWoJ're€º×{}ÙM6­›)|"OW°<[üqNQ«†Û1¥8T ¼äzœq(9=°ô†‚-LÙhIç½C®@æ8”¤Àãl(2(ízý€¤#ö‘²,^%ôÌÄZ =¦ v:_‹pI@ƒ1’ÉâMÕù%D+Ù$H._\ÇìEƒ@0jCNã„[’$Av%w»Ñ)‚«õKË Ï—ð,Ôtý–Ä,‹NÔ;ìt}¢´x@ï½™‘”þdùéË0>¹ƒqøB£WÖ¶‚Î_D®iíÃ6agÞ Dí­I´U ð­ªTD.U‰Ñݦü ë‰ryaƒÖ©Ë°Ý#×$(Oü$b˜«ÄßeùØ/r·ŠþèAËž¯0“šÀæQ7/żšgkÇõ5Õ„y7ñƒP|~¦FMòÞ͵ >&[š4 Ôb÷jÒ–Ì,÷8ð‰g˕ӈ8še뱉ÚÝÉ_0s‚íaæÈ?P¦Ø†Ãf0»R®[œn3îwÀ²‘Ño–ó•„¾Ü3ÃD,+V†%(¬tÞ±¼ÝG"†Ù÷Øö!Þ{ÄG8ªTš'gjÐ\Z&F„{§0YòÑ’#ˆÇì’K½7‹Üïé „Àv?Õ²XW|w[e@× ØL3Ï%«äY’ó‚jé/Â;jÙXi·è‘Ç(¸¯#ê€N¯¼²,&žgR¢|«þbpð’VIA!ÃØ«§ùÙ³¸¬ê\tA·:M^{“ìÈ1«™Ç©0¬(µ£6ˆzŠöúM¾€gõp·#çÀ$¬šTçµMlEZgq\1/ÃëÀÆ\I{ÕɾCExó¶ Qx–‹ ¼ù<=LiÑðŒYÐs'ÐnÇ-µv²!’ûhA¯›¹âD!d_7†ò³çä6 ätïÚéâ2ÕñèDnÑ!:–^¾”XÁ¦õà3ôgtq‰¢\lYïø[¢ù‹÷žF©™ƒ¼ES>¡–{û^{‘¨ù½Gû^w†µúa,ˆ¯A?d„9žµGQ-+Þd'Ã-u¾Ý¸öÅ~·KÓëo ¨©¶‘͇´Øûµ®„¥-3-n'=4Ÿ—×­V%R(ÚßÓÅœ\ã=¨Å lÍM±³î¢WÊEç슽(A·géa‰šn˜±úRtŽ Þs[¦~ƒþ 3óÌýèiÙ›-S¥ºwo2ÅŸÕ¯TQØ31—ŒÚ›‚' ª`À5¡½½¯&%û˜ª·| ¡ <Ç`¢ çú%rž¶™ Žã¾LwæpíW›z¬q±@ÜA®Þ#'¨¬$jáwÀÄ!ÜÈkn'.»^@ÍcÚЧ ç^7°îœ0Sj1 lݳ­Ï™\’…)Q²mèI1áàôe<9Höuf™JñÕ.jßü‹æ‰XBÕ5zÇe&íͬ]qÈ!sDÏ|&ËËÕöuš?ØëWq6W‰lÞ< ”FÙ3Tà¶ ™kF;ä“’l, º<¢;o‰A\7dÂïÍc}ЮÑ0ÖL¸Ž)¡îMÓtjHMŠ^˜løHœi noK ¼5x0¸JºíÑ7+L‡eúòJàΊŸèKˆ%ˆ2g°R[—uˈ»K£I#Š^é8yðv“ ޵Mk‘«N¶Zrgm‰N‚pÒTãÜ÷Ywzv¼ºâQ´®¹`¹pâ– ‰ÌŸº™¼bëÈ1ÄCÆ!›s«*ëe(¼+”óË-! ßK¦7Ý+%z±h04¨Ñø{Øw„‰f0×õb»«®ÕV£;¶u#òtEl7)shí§ÓÝ Ýa)!ÒZ .‘ò¤gf¼ct^Ó2B·u‘Šc—·Z¾q`x°m޵>×Üèà±I/ªà¼.5LÐ'•ù&÷Ê»¥ãK`öM9Úë@ig³*8>q‹9+餙—Òk1çR}‘nì ”de&¥wQ@ ÕPñ$/«znž%9;eœà]‘<Úîy"îC=¡U̘Èc]¯l‹Ž­ïNküÎ^ÍÅDS*¾­k|cÔÜGÅ8E̤–çÖðl+?iú¢¹^Ü–“¿Íi}ëè\‚s’ûn3Û3ôUA-ö€gŠ«O ´jáÚ#~OAYOEÞ`'H:¯OÃ,H)cl?ŽÎfŒ7€$$÷®Þô^çµi°ÕTݸ`¼“W ÑŠ ÒòRÕµÄW^>Œ«Pzw69òÞìCôtŒISM`ââÅ¡@(Ø!ÍSØêb•aRM¨±SÁJ¶¶C‹Nra° ZgŒa¿¹cîý ç.K<¿WœA¾; ä¶÷¬å0`ÞákBΧ'|r©ÏͧN×tÅ Œvô¡ÄVûÀŽ)ÐÆ(GÞ&Õ wX[e?bG8¨ñ[d~máÎïñrn _Hi+]UòIK uGŸ˜Fà$q. “ÝÛ4ˆeY¬cºw„£öòñFneÝq¾·w«ØÔ–=¥òL¬ÃmOLÊÐq- ¨òy̬¢Ï¬ì†%¦ <•¾Çøêîa¿‹#¢ºJň×&J™fŠhr#8ìµy¼¨ÙÑ¢oÕ-ð.Gßw—&†Á‘Ž˜f*›]ñ‰ é‘.â€_34 Ñ;XblË=óÙÖsN«Ú ×”½3µSïѳîL39kÃÎÐ5ZÄ xfm.¹“1~ˆÉÃÙÚ¥šËG‚L„À+ïAh°æ¤Ú¨[+A 6¸Âažåq¨ßæŠ%'3{iä"ªŠ¹Ïs6‚¤Ê9Ð,´[(NYÞñD´‹¨Î'у2 Pr„î˜fo,V—ªóÙ9 âê !å~w­Œâ~ÛýÌ$OVžbÉn„œËE*RˆÑÑ0ÃÜ8là£HºZ6ísF}|Ñ`ÕáE£ÛÞDõ)ÁqÁóž›Ä‘pÀ^Ó»>ÎÓ—œ§äLñÌ£„ý!•{ÓÌ¢Xй.Üêå;6bàp{¼êâÌœN;á̤îðxž·˜o„0ñâ5=×+„U§­$·{&VžÜ{ÂÜ“ð¨Ÿ-¾#ÆÜçueVð€ìù@è³âœ'Ñfá}š¦áoó=”°ÉâEÏ™°rÎå•m7¸‡© O‹j–¯¯³B4d¯< ð0öY`Éó*ÌõE~’.gëg’É2d’g7q碧ªÚ.áJÚ%ÌÀWù¤„Þ‰l‡á,ÂB\¤û¾èÄ5t(v —uÚìqìjW“óF ì«|Aä÷$ŠMë•8ù8÷° Dg°†¢?]dl­¸ƒ@­ì3„„3A„µØd¿þ]{5¨qG^Ò¬Ä)c"ºÐÐ:j;e˜1[ÊNÕÅRleª‚·iò4s%Ì7ê8­XÞÎ>¼°bM9ØL0Lªès¨…B‚‘ûÌôâp'‹›ò™õ£  eð'1Oñ9óÈÖ‹äo$ç1`>ôBºA6.W¤£*+M¯X —Âc3KÞüFÇ]¸}bEâIc„#N]»m,€Ñl¹«c· …!Ÿ_yRǸ‹ZÎUïHF•³ÿ48ô ÚNÞ[ ¸Ô& §kîuz×Ô×g4X¨I¸×– ÌQ“˜Ã.Êã‘mÕÂû£z¢eù$%)‰./Sê-ï;ŒÄæ&ž÷öV,àâÒÀæ`A»ø0ä0ÏŠÄ|·Ÿ—‹Ê<ž U ·{†0þÜÑ4³ôÞXw–¢á+4yüBœ1ΚFÅLÊj;§1Ëç–]÷*|ÞÓL´m³‹$/m©ñ³1¹®yÏϬ …½ ú1Ú‘Èãsé \Ü(ÔSM%>yvtùæ.Ûóž&%"Äæ…Tk'ëI{‡óI+×]t… 5Ä-ËÁ(yƒ‰=s ªçF\%ùçKñ%—WSÛ–jF&{y_ù+ÆHK5J®¨>ÌG¤Ú~ø¶Yçxžs#ZŠ¢Ã "õv€è׬*c¡@¼±×Ñ98s‡±D,ßs’f“6iPÆï±¶É+d”áál"nxèÒTú¤¹´°Ÿûoz4­ ×0l”ܽ;ünBŶÞs4¼šM~Ï‹í̦µ§Çœ¶1ß“¡É×ô$J¿Í¦,ǰ©L’m H¥Oœ6qm"Vwmzù&ÔqÔžÇ;ÏØ‰”’—D‰e Õj%R³œBŠñš•Ej—½ø$Úù‹è)ÄSˆÊJ+èÔÇAZ8#/Ú»r’8ÔÆr†'Üô̚ơáxz¯ÆPØŸ=q2î$©¡äg¨·Ê;¤}%ªõžr Ç.ZÍ„#Ì _ŽÃTMsçÕ³n…+¸¥t¸ba,˜^³çóÆOó¼ßN¢Ò4ê5`f Yr‰=l¨8æƒ)(׿¸µƒSÜ'n‘æRöÛÍiÙÓ··=úEù Å ðßß¡¬s ‘+Ða'ˆÄ¸r KBi; Ó‰P …f`r¥{‘ðj%–äD¸û5éʸ'É‹÷àݱ5r»mò $?I~ùf†(³ÚrŠÕ¡ý.A*üX.$ëâ³¼%µ’ç¶Ìò¥>2zÛGˆâ3Nfå1ïŽØ gYÀlÖä‰3ÔíùPž\çë ¼ÔM-g%Þ&“(ÕP˜KôåFIæ«WIÕ”ÂΕÄÝ á¡Ñ#–¥Oì™^C©$«€ÎãéN4˜4ìš;¾|\͉öDõu7ùÕ¼}ZÚƒð)CË ¡8¶&û8½S\MJƒÏäÀÌÐ;døn˜=Û X× åmÌÓ°Qk¾z÷`«¤Z¨"2Ý0ð¬ ?}s$Ëõ0=”bñ¬,w`9š²tˆ¨I[ëËä5umw¸—÷N;ÏH°Æ+¶ò5kH6O1¯ ¨;â0ÕâÚ¶3NûÙ¥M 5ÂÖSxBûÀÈ£Q·M¬²÷Ó2¹‡›mH2[-5ï κ3ÞvÎ*I{BðM Øâµ¨‡³†ËÙsÕäß…auø<©&&Ñæ Ä~ýüÌÂùᩯmÆ)øZMøØœ‰c‘‰"hJ›œö{ˆZÖ¤1œ s AUóf¶=/îÄw_,­9P·Él㎮F¸˜ñ½×þ^wÅ8uâ÷ßK­áÃt¾öBYf¡®}Àe÷HQ3gäY™¸º™õUAÍc@é§@•!~e ÇdjEžZe’Ì»­[ÞiKîš(É¡sfv» Ǥ!ÙJKqølŸHâ+}pV†—ùI?tØuE{'QQ Ò÷î½óª½½Ù'éYo&æ‘nx‡=¨÷ºhr êÀt7zMyØë<á¬*Ðq܃â¹êb+`Ös$"‚¤îÌŽÐ+4ƒ¾©æUòª¤zH´Ðù/'ÏÑßCí_P§d,+k>j—¾Î¶w@×òÃ鲊ŽÐbɼe6†àžk~+ §ñzï„Çy´X½‰9ÖhQOJ@b͹:%\ЈÄ,ìJžr,m½½Au•~XÒoñ•xÔµÁeÍ$¸ŽÉ³Uƒ¨AèPp{‡¢—#õæ9CÏõtÔjž`L‘R’ƒ‡f‘t¿¸ÐpPĆ‘|à0R/±]³†)DŽ^‰÷{ …›)(üEu+ɶ½Õ Á-XW)¤#¢ñ#H‹.'Â"öôQƒt0Œ\;﫳$p}7€èoD ^;t2‚2©XìÐM„˜Ë£‹âñE¬ÅH8HO¯ë° G'ئÝJô5¾ˆ@æ}çâoª UAEm[ðnáÄQVZ­5†ÀoÙØSÞñ‡M(²h þŠv©y IŸwU…awWâd«+ÚÏcLŽž¥r#C‹ö’Ж紺Öôòɰ¹Cq²Í›¶P·ÀÀàÖo`"“­ªV'æ‹®u¶¢ue6Ï£“8{EYGÎŽü ø…C%†M骥Û=s*«‰H]²s:|oªuŒ¨¤g!ÈìˆÁÔð޹ÑIåd;.+!ƒµÔfH½_…Õbx • ËØ3¿šì¥â kŸ¥AÓt-Èyg#¤ï]Vei[Id<]Xz™ì”µ¢Šº{¸äÏpiéi?‰JÞ &QÒ´²;|§›œ ‹}‹ú6Ð0 Ï2´kV®:äM¬˜öj^°˜™"±;~ûFg–Î5%2;ñöæ4S™3ãpÞ"{aÖ¹v¶4 ù‹êÖÁñÙi%ääiVžÔùl*Xi»¶y¬m>¢€‡U«Pi,'ŠŽ€SËfœ¹¯{lò­6+I1×{«ÖUà.BZúÊ ˆ/[Ʊ煌çƒkQZ_G™5Ø\®—u(¦±ùŠ Ã’g›Mîõ]±Àú£+0*6ÓÇ ÈÊ4"i_s8'Aí.í`Ë­ œÃöÀDr{xìsÏÆöÁæã³GmÁ{³£mǺÞᎱ",Ê“Y-]‚Â>Uy“ôt:–Ï»ÓkKCó(_£4Óê¹5íâà[»}¸xz¡âGKÉôP؉»GkÃSïÊ7µy¥<µû½‡Üð>±&þÂú°…¼Ïì…ØðxŽTøY›¡Æ,”ºÏÑ{EÓžRwR¦˜gâÔW+çYùØiG0׫3®ê76há‹Ï ¢`LÖZâÍëîi,‚64.^ Ê'È^R–îË%0[7·Ðdž꠨´Ýéý¼1ÝŸ@¾*yÏn8gFBbIä=›LÐj×'~Y]{s%ÕîaþÆù5xæ´6ŸöÓS9]ìH¸@[ΧV’oÜØ‘g5­âõÈË £Gq vï¥5…{ŘÃzöÌI2Ä¢‚³ä.4oÖSÑÕ@øùD”-VÂó *d¨…É+cztOéäYg;eÊrÑ\SÙ;9FàJ¼Ux çËæá "#6;Ô¯ã zóe%Ñ¡‡Ù»\1yL»UôÎÆ8ì ÐkD~]· víÑ ›­Ö¹Ñ& LƒÒKiÈÒqw™Ây‚ohyä-¾ºqBŠ©LKªS‚ÀU² 'xRˆ§ïÉ\Û늴“~}ü"`}Hã2ª ¯×”µµÒ¥öæ]l¯{ÆëÚîw~ê<ëÖÉ{ ŒõeI™«K%;‰xo‹ŒW<6Òr‚M¾ 6Ì= ¥´Å..òÀ†aKdí$ÏyÝšucsåVÞIBÏÍÝ— ;«cc‡I)_iâ¹Øj¼YkÌ©´4;·ýòÎjÉ—Ÿ`s6ØsxTŽ wHyÅ]XÁgˆ‘z”Å(ÖeM—ÅèÁ/Á„Þë=Oe¡wûZOµe÷ÜTåÛ‚¸ËêlW[(ÐérXÛ\45÷O®}q÷Ò¶G°OÅèÜq¼€¹2‡œ\›zŦøØÐW/Üa…I1æ2­¤MËž@+?¯Ã¾­9 È'Ü5‡ æÚÜä8y•zÊWH2g¬×™„ Ù)ý ˜iÌÈ­Kï‹5…dÆN;tül_Ñ6S^_Ìöô[7[;FЄz0ˆAðˆÓ‚'Îf)›f2A;;¿¾Æ–]‡'T3Ïf4Q-(—Æõ•±ÊÐúO°mßU1GÑ¡2© nŸ2]yW1†ÆÕ!´¤ö[+Ì¡a|çiÞ=rœ•ÀB±[ïŒJE7ôOJ¯–Ž5³‘7ôÞÖØ¥„½óÚ­Ly$ÞX™ýÊgmp¹Œ^ƒ ÇÓ¾Ùwð"ï¶_Xä¾F]9âô<·; [šâ‘^´ålQ™Gº¯tjJàšªš_Ó>“CÃñm¥fz‰¤Å2¯ñ•îÛ‹¾Šò’º4N´x[µˆêR–¤{HML¼¡ñ*½,`ýõ¢êLYûóYT6æÊB5~ôP4”¥9×ìKC:Ài eSd°Ê7Í'8éÁFÆüad(}@lÓ3MWÄbìÓ‚Ñ/¶ÝÍÚŒbªöÊ£eù"òôÉ2àv®žF«u.tpeß-|Mö£û• £Ž&ñ<ä=ÀÖÇ~´òBÌ/žzÓ㽉'´’½3ò9Ÿœ:0yU’$ ˆ6/ e.Ÿ¿Qv¾]`zlÊ$HÃ8 Ì•êGöxŒž^÷ñÙ“Ó¾œ¤ÇÁ„u#ø7+Ã'Åê&V”‹{ßKL[D5€«€~³ïÅ\ÅæS¥§ì`x6„ #SO Jš‹8'WHëhHm“ X0HòÓI&ån¢z?DyˆxÚbç ˳azÊâlþ^0¢…»±c\å¼¼ ²ybf¡ª°šŽ-4á)Ž$§?ztz&G Óß],AJÎme6‡P €n½–\öaÞfÃÃÀc}úž?'¾@1z«îÜêT@(¸² ¸‚Pü°ÝUòÎKKN¢K)&-6¬u¨üR['ß)<Œ¬Î6uJÇíS9A$|c^ÝôJj`ƒh[ÇëÂ:„Öy†<÷"+îTÀ+ò«ë÷Ê ^O„J"Òó¿È.uCô8¡Íë†'ï,oÊÁ´¥ô-Í1ð½Á‡œ<+ö„1È6Ž[-E¸ÚiÃú%¶Z´#uLª0©#+V@ÜÛAj1$÷dÜ;½¶7wžùºȽ;v¤/ Nâ…,Dßëñâ¡TA·¾çN^á¸%•~¶V/E Ýs¸Yä¶·›:œbôEöâLî²ôbL$ú;ØxúÀ]O‘$5}\[ÜÖw¡‡"@©t`(eÁòÁ¤Í>‡ø´¸r]X)€5.±ÐEl_áCÝñ;¬Ƈ¶×4v>IÔ«³ðÄ‘ Ž|®™ùÒ¯D|³6Õ [¯àÙlJã›4àåcœkÚðý<ãwÃù¶&žA÷k7JÆæ†¹‡ØtRÖ^5mÕœñxê‘iä{o½š ùR/O L²ÒBÝLÝâ"#¦öŠÀ,nÒS– +mÞW•/ë #ʳj÷Ûu!¯Ê y.dõJ2«zÁÏÐBÜÙõ¸ÞÐÈiL=&‚É÷Ü÷=—î Àà2ˆ—ñ΀ýžìK)øäELýØ®ÖΠF³ærIg:¤“-ð½ âQ£ÀÖû&Û?É6Ý{B0Ê’=¢¼adŸÄ²´ GÎ Àò«eŠºz³rÇç7°ª/»Ó¨‡¢ƒÅ©0((E¬¥ð¡PØ úU o,m>‡h*¹ÞßiaY䈩µ+ãaë±{âôŠ ¤î¤Eg>&â›QƒyO® AO&¨_°ó¼¼®\ZÆl_5‰{Ê´Ö#ág"µ°ÓàæÛõ˜ާ÷ö58ðÓ“—øl[ç=š“dãf«¶"(vKÕq‘¥û íÝ9gäìÊ»Kš±€e ~bíÆ(3fkþ‚dÞ˜nHå%•0%õ{÷Ñ%úØÞ9=„'z»Ü+ kp~Ä.¡¢O½â9^Ë–öÓwâ´G…Ѫ–¼‘`ЉÌM°óz¥(Í»< 'Lk“Å2jÝÝóRA»këá&^€T‚¡é*L–ù©#ìë1øJÈÁ6¡=£ ƒn}„b:A½ÏÏú…%ëœDaéÇ/b¶Óõ‘<{ýÊtâùmúÖ#Aù‹mÅÒ…À{éµ÷Ü•íRä#‘W¸g{éê‘« J' ÛǾΠ¥ÊìóD€õÒÈóÄÌoËËÉ*âJa•ÓimÙÑŽ±ÀÆ.$F²åé«R·„äUÄz¦TauÓº„´³xnÜïéÓ,ÞT|•¸^!âG<Ø@-ö°PdwF7œ[ú«åG,8çz´[6創ÎB™2{îyË{§Þ ˜A{1?NSòÇ}ÈŽÎ/c_"ø¼)-'•³§/ÄÙ'©ÅDJ€+ÄM¤`v76ç!wJEhVhû=Žj$E¿äõÒ½7°S¦“Î[ÜÃ'¦,(ǽ4ûÄ&^½š[ß—¶€È@HiO.·‹C%àE&ÈAË&hÀ>àF‘Tvà^bx1˜xÖt¨ëˆ7d’zEA÷®± Õô¹Û¾ºGvóôy¼<(rc¸¨ø„ƒâ1X Z°(¾Lxf¨ E̪ʗ³DAðt;Ń›·ß¨Ú» Q43ÈîÇšÖ‚°xžáµ³Ú©dhøÎ^À\ä[ÖkiP}鞨iû>A[²©³ d—RýX˜EJÍ-pÁÄéõ¶»ò -®0ª¤èx²:¯’Ίn >l8`[í¦Çòd‚í@]ØÉ †¼§«Tì,ùÖzT ^4Ô`ùÓfb(B‚žCjV*„»¥Q,=ØKÒ–·x‚C4¿gmå/¶ß¢y;Wäu’Ò]›+G;ÛÈL7¥ù°\– hN}ç%ð’²G¡44¦P1¿Ÿ=jxC`¨¸r*ã+Œ+-6Q —U¡ÛOòɦWTæN³Ø>ÒW 4¥ qÅd2ä ½€‹–øp_½iîÝ ÅÄÀxüFÈx”{šÌU·óu`m¸)ùcdj{pÜï ¸êÄA×,¬p±-Œ¯@» '¶ÛÍÙ–¾MH kÝ4j³Á ± …Q#Ý’Ãáz ¢E¥6Ñôf^¼$xHqÅãÁÓ»4<ÖU›ÇÀ7³çÖâõ0xNF¹*ŽDS‹Òê²VÙ­P§úå|6<ÛG‡Ï©ÏÄDÑ£°¶¯Ýg¢á1&87Âi'…ªq‰Ø–ÇUè¥!wŠ*±ÏÔßUÂkâ© Óq_½7á·æ’<÷ŒºÆIQi¡) ivËP„®0‡emÅÎ?ÊlÍ— ý¬‘½sñn£/¸ûùhA™X—Õ2Ãö@콂’x`,¨®‡Id@Aä#^½–ú´ÑÈv…­‹Íb=üVÎsíkÇd35´‚ðFËž Ê“!µÆ Šp‡v‹0C €€ñ´äg?Í€“1deÏpEñÍ 8†´¯V¾[ˆèKD]9LºôÔIàÊé⥑ه7ÍàÍbŽ ™m`%:úð:¥×‹zV qÐÌvâRá ã¬Ï´˜øõÈå˜7üE÷½œÉä甊}Ï›Bßc¶ R¦åÞ§ÅÃÄǘ]@yk¹UþæÄƒÀ¯|OülhòHP݈+COr‡ÁbŽx%#dw›ô騖&ÂØÍ j¬V­‡¼Gê­s^]‹ !u(î’xöÆS±û{«ˆIƒÈh.¢}kmnÍS(â‰÷"é^\áá2Á‰uöàÞÐ(Œ÷<ÎÁ;[ƒÐ sKÁ.Sçq`¸V5„Ö7.)37óNDAA׎ÐÉÕ†iÀ®o¾·Oh™æ8*ð»! Ó ì‡yõÉ]M¼Ös‘‰E‹_ å†æDß'¸Kƒv•¡õòŒ4 ‹öðú•O/+& ¬ºË.dzz\5óÄÒ_ªgÈ ÕEÏbKVŽA¯åƒ2­),ß’÷Fly²`ÖÔƒD®D‘Ò ©Q²2i0 R˜‚[ŽMoZ¨$ É;˜ \gé³øsî.íΜØ)+õ'*bì ¸ï‘@ó¥Ô㇠ò r4gÏÆWºw’D'´«Ïð-FxaœÃ{uð¨£(ED=4‘)÷”.DÕHŽ<ŽˆÁíeZ©æ‘WEB!©Oy=—CÚ╽l>ÉLÀ´T=¦ä”¢È$UŸ÷,²Š›TB»ß†l" XVBcÕø^й°:.bvJ†F {ôðë9ŃÉWÊâwoÛ:Kv ßɶò wµ×„…Úõ¾¼HC; œáÈëçWÅü,PÆ W ßxÃf–bËȸ!ÀšxPf j,S…dX’…£:§%iEÛœeEÒŒ3? †4Ô¨Žð]ȇï±dË;–Š´y”Ý ñ”¸å1>¤µ£µ»“CZ*Ä8n=éÄñˆ{Áí[ð¼öl çðÁ+ë0 ²Gz|ZÞs•£í£Wb„)ÌXìa××E!¤³Ù‡–I¶5à[8f‚Þ©|Ãz™‰ñ‚ËÝáí-é:AT“à剗/,õd§ X‡çNõsÃÛ0Jî‡syŒáÀ“ÙYØH¼*!JeFn¥Söòy’æÀk^‚ëi&ï ƒx ÜS­ñš¤o§y¡Ï»,ÔcÛ$€{4Ïu +sßúKÛD¸yÚ‘v5SþäÞóÀ;ÂæÒÇOýj='•#áoÿœ»Y¹jrȤ¦'ü•JFÅKⶃÝ#à*ê œ~xÕã-×,®ž{.¥å¯*)%ˆwÔÅu[¶É®ÈÅR“b 刦ûÅ­âÉb%Üézqvq뤱×Ú½a/^ð]ú¾8;[ç|¯Ÿ«ºIV’¾™ÀßX(5–¸¬Ò7ÞZUöÆ÷±¿†ˆ©~pAwê¥9;7l6úÄ ãDPœíž.q%”ˆ>èm±­¨‡ùÌ7ЃwI÷%ð_|“aJ§'l¾\ÁC¿;^pv!ºøB` m_-ÀEÏâÕÛÌgû æ  |K¬¸Ÿ^­½&ö+×xiÉœL(ñÊœòԟs–ÌàkRÆ—ÉÞ` ¿®ƒÒÑ“€hKE„wNýö­xª½óM€vÙW»HX ѧñ=ïi„;pÕ‹k!J„“E%8Ì}iç)µ‹SþŽQ..I» UóeQ§õ.×tƒÛé ¡ LŠ˜ —…MwVÖY >É—=¯/Lº<Ü}OGº´ ˜'XqH `WŽáQŒnÓp™öôóÚÍç»|oyl ´t°Â=³V¨ÀXí5ŽqëÔ£èór/h÷d¬ a¬äyY÷ü,ÆÙiçxk*$ƒøæ½ÞšX”ª)RÔ0Mo°ëcÄ“Ój=[(±ì4ï& H½(wñìh‹B•;âUU3y¸/NŒje·) 1:"Ê=2««ÈÝÖ<¤<ò·ÎõĤW9êpÜÄR´oûéIÃ<[œ7õ|ñíEIÃ1ðéÛ9\{­%‘Ü]U´—޽-æ C\mR å0&GT˜Gò´Ù\Öée¿…ò¿Ç '똾Æ'£pûP0KšX#ÞP¿È¥P#8Ÿ4€AÞàœgš™à¸SäÆ9{#æõ”£ûÒ†N—à"wžE°‡ $—÷«z"Øêã>ýöi–='¸q‡{¡Ê—u uAv$ó¶z÷±µp½µŠ ±ƒ„”Œ¤ÉìUCÑ÷2`ÒÞ³uI~H‚u‰õBxuáà´ŸGÆÌT­é!I ÉQ£iq4ÀlºÜÁ²€ß ,ˆåññÐÜK”¹FÍê:¤ Ù”[)¾@ Ïn5¯Fe;­™ÃlæM{éZbÝH7OñòmP ³ˆ³/yÁf{›Þ¾nxëJ™Ö•(2ˆ‡Ñ%v«ìЬm‚ÏÕÕµçgòm­ OJ·HÌ7a¯YaCjà–(Vª=PŒ1MTÇøëõE¯XÂÕæ¦¡$—#Á&¢.T¥¤L^Wˆv×à{.¯’ÒAÑ%´Ý-¤ÃèüNDÁêœÊɳd€q]G̹žìì¢Â]èC„i΋ŠkÁˆƒŽD`Ž–R*qVdc‚Gµ†°Å”ÁÔÖöÌt³ nïÙ ³­÷†“êÚ î3颣м2S€RV³K|U…1ɤä~Lo[­#Íü½ì”Rçš–ÊiQJðŠèøŠì¸6hëÞ³ ”×óÆ|BÖ´ÃÍÓa(—ç¬W4ýÜô-âã…\! ýDYç¡Ê4*·œÙŽ`<–!É÷èܺ+mÞFm„™!lhØ>r}ì…$¤wô 8AW©É"À(ÆúcÝu¸HHzÍåP‘/¬Yªñ`ƒ”€E¸´v «°ÌŸAµ,ã•è†3^á:«à£|otˆ¬]Â`.h %VObËTû b9·‹«ÌâÕ»z 2„@‡É[š°pZcþ˜Þ8{A;´'?w¯¶ÁJ%àN´6•xén›A‘Í®êˆp;`øØ¢õJ1¼ŽºˆH·ZQð“pü^]†G6Ž(o 0Þ|"Nð…8X€¶…•«e‹éƽn;§#*Îë:ŠWñ0 ÄyR“¡ÉêÑBaÙ1Róa9±ÃdГBÚ&ƒ€”|M’ªÈÇsšMzoß;sxç½d¡FhÏñ€V-_ñ9§áa ‘/4å„á³wzj¤Ä×›>˜q.hp9.¡jHàI¿bLE“aµ¯AB9½çª'ÏÙ.úÔ÷ÞÒU WGð,= rŠ–ÝTßfÆëÊÔ\¾» ¯X©¦á™À»¸Iž1+mÎÀ¼Êø‹ñ—À¦íKì vp¡(Š=pº"UoÇ`(GŽœóOM‚C>ìDÜ]&ÒGÏáIà 9+Y Å.¿¢À!Àædn}ž¹’ÀÒȸ¨%J×èñîEGUê íU_r`$¶Â(ô>ê=POt¼”~Ædïö©w&ª»µä ¹×€jãÐã;}™¦kL'ÓwŠÐ™ï9iš‹®¬ÊM]ØÝ;8tÙ·xc¸€4NoÌ÷9vWD˜Þ¨«#’ÓKë霮gß… ³k {G÷´•RäE¯ƒ5`®A+¾Ìîmí|vÔ¡\DÂV­Ad<"–Õ¸6Bø e·() ´íq¿ÝKatºÅ G‹ðòä¶|g>4Ðs¦Y'Žê1X•‹g;/=Þ¨[?Þ†r†Ïl2(}sÛÄÍM50ϱÂé1Œá½»çOscÝvϦó¶WNlYŒí­ùc|tA”%y³öÀ´Ô–YBw¨Úm‘µ²{óp©k=Ø_ÉBõ“9ëçgqEmPóAÑÀê=}VÔ*Ù¦D/„ˆßËÜzœ”hÜñRã5ºmX½ºäö޶AJã#Ý3Þ]âyÇ$Ý ùR8èU(ð³Ó¢~X€ðêÅ{áZ ECZ"|y6%,œèé#´éÌrêÌ•ö ±ùjÑ°Š¥í™‰¼µoÆý‹qqßà ÎjB9òÊDZÌzFÈ×\aeö:Ó¢ #Y(‡Ë)óÖ:ËÓ-ë®ñ±rNÍ='- /O ÃÒÈ~ ’¡O6ãd2 àÞ–ù“jaE¬ åÐ!oo÷©YSo-8цh*¿W@­ÞœôH¨ßÅ¢`2jqè#±2 ÏO‹G:Î U¨-•#­z§«»õhÀHª^7†Vš¶ifBb@á ªG¼ÊŒ»MTB5{,^ÛFû¢ã¨‘ð™ßfñšæ_»z›¨îœa ð‹U§tFq)݃¸ZÖ´'xÄÓµ´DÄû¸›ÞR»Äú+/ˆE¹“[!’„7è=èFî$©à]ƒmò\g^¾™ÊÁšˆð­ÍÞèZ}ÍP²óžÊKÆ~/Ø×iižÉ,¥÷;lÌÍ5Øë»˜|·ÀD¹‰PŽ¶Ý»ÐDlk3²Td–†(uÒÉõ6eÛ:[º¦-”©JØŒ"!DÛ^tˆÄå¾c 1å=· ŽæK¨ñ]³‰¸‡Ä†0åEÆ…çnžcÜç~„Y-(¯HÕËâœxŒ›ñ¥j’É;•²ïC§–MíÐ4ŒÛ–ë™R ± Ö½ìC¦ ÓYÂì-B|º‘™uôÐ@ÛÔR•¨Õt“µ j)í"À’k”ëðÑí"ÊSšÆ'ªgúŽ»(òu—ºO¬1ÙÑPæ !HǼÆXàS%g\×P™’(S^tµ‹£âºÖÆWÕàÍSÎ/œ–”ΤW—ø¬nO¦ì£ ìô¾M®dV0£)èð°Q³\9 ›øõVß3‘4ÊëF×–!··EV` ðRo98§³=*õ] sSi€?— 6Ôŧ…õ·–í9‰oË „‹Ö!h‰®V(;V¼ñ¦yj©LZö•)ÌÓ{”äzyb \ÚD;„º I†‡ŒrΧ•Ÿ?ýœÇ=$Ò–+sÝ8ÈßSC ^ŠftSÖÅÀ<ÜZÄšRG²V}„`÷Þ4jÐâV;äl¾*&|%àa—B¢;Œ%pæ'ä"í¨ž\ªz½4IÅ¢cik–%GW¸P«á†´¡ÏPÂß ˜2ærñÆ´=‚wÙ˜‹x‰çmÁxÝN›El9S¢KúœÙ6F!VJ¡\U4sëpòµ'=›à¥È[ÖzwÈi´¹õŽ9‡ç\\uöø ›cB=1¯ŽÐv ƒÂGQÎ1vùRß.*âÆö^ºŸÃ\çøXŽÆjzDð »ä"cœo¬zØáh@ÍB5W'Ù|üê9‚”d­Zrk;ÞÊL7æ¼ÍQ’¢€‡7r¸‡~œ¹(»ÝTz’üž®Ô¾›#@Šwz´’pŽ^û˜*ŠÔÚ¡ìÞÃ¥Wbñ†‘uj¼òéÓA ä¹'ÝW»«T÷ཙ!Eä]ƒHeÜnÂÄíõ/’#T–½<+3©(ŸÙº½DwR’­¾ì§úʧZN×¢TgŒWÖkä£>N]nÆyL"?®‹êiÄιÉkc¹Ÿ¦—WÇ r rÝþ®ôgIJ­E®Ø¼e’‡;Ýø sË´V¸wÎU…_ØÃÞedî†õì‹]Ê#ÓâI%Å}ê}0A$ýÂZ1Ý6½aOÙÓ¸ ÷µìPkO™êú«V§ˆÂwê=)~ªàÎ&ìÈx‹S^Má3Ã= 5> ÝÛ'@…œ–läoW«*]Ÿp¹§_¡ ÛB¶s/lôœ=;¥FÙyÉ©—`à8I@ê Aop5´dÃI0Õü±Åj%ù{Ú/–Lª\k›"pœöŠ¡o5\‚yçúRvÛ V5FÍ:w‘áMjUɬÁËîÝÌ‚qÎ÷bÆÁƒBõ¥À½êõˆ%2¹™ZùžÉ™¿(ÇDz´=âú<$YpžG>ÌŠèÛƒ‘Ž»N\]}gúJù*ŠÍ¾öý]öÖËè“›xXæ±j›tÏ—„­Û®cJï½Äåkå ¢™¤·NöêÁ/ÂÂÉi~ @JSRÂR(±x‡Ó©[ö¸Üèñ+gj±Íë›tÙ*ö½G¡¡ƒO‚žôK§¼Ï°iLèpü!ë\pHCj‹ÕÅ®Ù:\˜[î’Õâ-’ötìy¼ä´éª~jËpË‹»Å´I’øç\ŽREœDvÌæÛ£Å—ýðèM̾ N1ׯ–¦eë ¦Ãçfbò"Y¨¥8hÒ“GrŸÖÑ¢³V­ô‚1%f¸ ’n‚å<7¶–9—Æ´ë~ ’<]x 4qǹó¼eqT¤_Û”g¤6@.Õ+–Ûéô~Eý4Ò*<ó©JÆ»÷ hÀ¹(-[úº=%q<Âã2å õ\˜åM¤¾§ÛÍ›{1Ë­InÍ<°ìªÝ¾|Þ³òÐvñMjêd R• f Û8ðFßD'Cfõ+ÆÙ‹ž1êHÄI^éç:<Ï|•ØÑ‹æiñ]é æPÇÅPz5§]Ùs²x°á} ¯‰°¬c”õ•7åá †¤£5l¸®Ïj#>Ã,°gÜ-kK´µßh$¤|Du]Ð3sø3ÛÛýâ±êÜ”ÄÝÅŠÓFYœÄó6E’ë§wÆ ¯¯Ô¥ ¢î¸éñ‘ÑDa¥&‰ÂgåÞ§3 [êúr˜Ê8$¥SŽÜëÁK¸¯;«$R)m¤"q†'6Ùö¤7'VÁmžgöð úXC„º+”>öAyآŧ%mføÌ0xx/&æBI^9Äc\$jä Œ„gíN”ô–M êÉÀ¤Q$æ>Š‹Øê&½ïŠV{ïW<ä¡2ØTE·@[SÎMÕu¯OÌ…¾0ÔÚœÊÂái=÷òfnÁuÕ9P ºæšrnbëñòÛöÖçwš÷ðø‰ŒÃÙ£0Vy3£=³l®´}`hº¨X&højJÔò­k ¦§…ä‘^ŵ¶J0öLAÀõЃl!õ,VÐ뮌H*@Þ…~|PäŽÙðt‰k=vK{"-- ¯ûŽu!VÄÖ‰÷@‹ÇÔdóÅÁ’ŸÉ¾^©7[½ –:Î>j—Vø¨ ËÍoDÄœ};ñj2x¸þœÍ-1ûžöK¥$>KZD¶£˜r×÷¢­×2R×_•B³‰Ø[åe ; zkJçYÚöiÞàçH= ÷¢(p@؆}¡xã²ÚÇîðð€œ•ßΪ“µ5ñU¿—¤é–QJ Ï[m·öb0úMû-µMy2Ç¡z†÷5¿]º{ªÝODƒöÅ *cðhð»Ø”b5AXä°Æ0h 2-)CšºëŽSJÈ~ÏC{³½zaîHÕf”jLš]þŽá©“LœÅ{Hbp§]ãaö^¯½ˆ|.ÏÝ=cÏê²%¼ŠUí-©*'Ýœô•Eq&J¦óØpíã‹Ü^ïÚ&S XHU){ݹAã—MÏcëÉ^03‚'ì^EF!pØ[DÓ£\8Q°À v]K²6©&¶u» 9~¹„x;¶/ØE‰Ï7—ӱﺸòy,jt”ÈÍ*OõÃUrC懷ýVÒuV®º¶2›a áÕk¨nÏ›åÀ"Éd£Ú½À¡¼”˜pØÃô÷ÈŸ'¡DÃÅMî ö(]WÉ™|›:í«&Ë’,.†ˆI[·/§Gh/—‘Kw™30F=„}}&x–³5¯·’Þ]»ùLÜ)¼·ÙÑÜkV»§PjªÒ[Yͯ¾A÷OÐÙWhaXÐñB¿}R/^jYÚC+"LËj2˜Ë`m&ÕÈ쪚sÀ_¾î=Xò6 gÛDF¡}Voਞ×H]´¶¸ƒ’#ÂË·Y•;+kˆ+/VÓ‹ú(¬ï 6˜_úÙ=éS¬­sG®#öÆum1”M†ÖwöLžEÚŽù‘)Ñ«g™sfVòÊãÔ¹Á9½DÄǸF²Cëváö¬»¬4u~W©lÆF¬uèˆè6(X—qVTÙSôòÕ XÏ!÷Í ÚP—\ÅrÖŸ¤g—êó–T7Ä|Ñ|˜³ ¬(J=ÕAjpÔÐO*Ý„ënçT ¯ØË€,è ³_9@eÏKt T&W!¶2pÍuÔ^´ÓžÑ7tSmü®cÙ[õÇCxH"\a–È êT27.ÇX[ƒ;ð:_©Í¢{‚°q<“Ç*cŠ,'ç ;Cç÷"g_ô[ËVf·PÚ·û|ñ*Ž¢J®Æ âåÛŠ&i Ì3ñäz\l*ûÂÍ„ÇAºK†Ž; –žÏéê9½h8Z H¼åáÓn²cÛÎgÅg”ˆP¯ÜPöMMeVÁŠCóÌtÙö*…b–õž‹£¼©{çKvJ(‚õÐäñ†:ˆé(EK&¼Ž Ïx¥V|—€1•s‘i8ÏÖb@ð´Z'iDmß²èc%“ÉdMèUõ¦aS¿»@KÄåF#u¦y(S<èq}êÚ^ ˜ú®@Òž€{ÇM§ùÛ¼zYU¥5ÝfÒÙ»jTk&%P¨Ã–B²žÌl°W˜t,¥G<º‡‰î B>tÆÂžïÖEØ«èYJ¤-êÝŽ§ˆÉ‘*QUŠÓ]Þ™1\ð&z‰Ç^åÀZÄõ+ž•C6mÎYY½hŠ{S+¢yª¬Ï\ ,éqÈÒ]¦£(CuЃ™Õ•–´fdá7"}Iï=¨•n4‚tÔeP¾i¨bi˜H&ý$Ýô‹ô›± ~/_q^ÖX¾”},¶¢³uæë\–PÐ ë­#¯š&÷a‘´"ù{|ü±öá+KD‰¶ÕRŽ—®çª‰ú¤‘\¢¯"Ò¬XˆRÝ_¿Ñìv]E%UÛfäDàLyI…c„*é"•=~ySf¢ õؽ!ª´òˆ2^ƒw’≘)†ÇP^{iªy’ç©«‚ ^Ûké4– °zTä¸ñª·L±fû¥ˆ¯l;³QÏt¦óöÑ3zÝO¤•þœÓ]¥½ˆjN~cÓ@œù€a à ˜“A_©ÂÒ-žM–›°lXEà—ˆ)@ÃÍÁ ÆUè/,Ræå“–x‹ è®­ÀFÃ0¨˜ HûžQœÏ“$´8’ƒ<…¶E¯ºŒÇ \Å ^YßÀk¥m`ÅóŽ~Ãå³0½-[€þLŸ“ùNì<ÕÖñÐw™„~‚¯%Ëö–¶ÓÙ‹ z²ßЭ-ò½Yuö[ÀQg< o—^±E-Ð;Æ»aáÒV2yÞ+F1-)™8<7r8ï¸;á˜Ø×]l[µ}ú ódvV ˆ’š 1,®æ4.(g[«Nìì"r*Š,y›Æ¹7È{ø,¨'ªhBÝVBæ. õÓ©mǤ¦„ËÏ"_;9#½Ü!VsîS+íô…FB@%–ˆåµØ@ÍRY $'.»ªˆh h1ö󷆛UªÓÔ¨¥¯A¹Ê½]åæÁfùå-ÅCª5.‘Êiî`nò˜ðµá„ÌöÌ dÆJŽ—þ®6ò&Îò0×ÐèùüźfùÁ±”+ é{´rÐ1n$éÍí.µÝ²c¶‹àÐä; ¸R¾ðØTÔËyo9ò¸xÜÑœ—'Yå’$½Ëx†Žf¶yßH§g?ëJœ"):¥ÇoFüMÙè2ÙžK®ÅV†ãm×ÑÂКC>é÷”ѧ߃®EsœëškÒ% é˜ `Eo> ¶ÄÂg<ލž˜å½iBv ð£YAX_/>î¬Å6rÕ{¶I‡ Üïf˜&b{ 7½!‡_8Ápõ]·ôã:ó¯Ýñ}Á¢–æ®,h=èo›Ÿ*q\Æc¸åD¤©bôz”{ÄLÚ²H5Äï^ ¯13ؽbŲõ¶;="‹P…5óÅ~J)Ƕœ ¢̵HÚ¾óœ+e Ï›ÞM ÌË» ”ÞJ¡®WJ* ðF‹Ø_[¿‡Sp¢[rmu $½}iWÕ`ÔI‚©;° Óåµ›|®ÊÒ`÷h$S$ÁQÅìnf{Ý ¾¨ÊÙ‡+puä!´†|ãXJzɨ'O¬'[|ÞQÁº/(À(ÕÄÉæ±ûœk2l€¢Ó2;@¸zs“CóåR¿4 0p«—šÕþÌÎ~?Ë“ x‰TÔæè¶´ ¶çå»G6í@ýrŸ¦@íjb³Wڢɽ‡ªEþØ(SSqw Õ_¾Ø}ôÀA 6™3Θs¥7ùEG[ý ûÆØŠ¬‰ø­6¶@/Ô9ûlQ1:@ÓÛ`‹¼WÅýŒ8’¦ ¦e ‘s¹ý?-À€Û–Ì<±á0/W+ a_5öué©z‡ò<²ž=@^¥gÁ^þøe1º¡l„á”&Z"™eÍiiIÀÛº‡x4Á…Ð/jç(§]ƒ¢½ùõÁŽª½VVïÓ(Ž×±Ù”³õ -ÄÀ]“¼Á¦Û_*¥K¨ÃÍ55C2ï»È"îÍY}¿[pA;“Ø[Zk®;_œwQoý8&]3«c¦6|#(Ú$ñ]¥¤­ôÃxZ=Ú3z(“OÉŽ©”H6ëÐS "n_ùÚk?{ilÌÄOÞ£ÉìÈxŒ+ámÈ—W Bgk,•8LܵЅñ(c9l³%ìlÒUÔZÐYpû ²âàП¬›p»pBUC°8g¹ÊÜ$à`[.·qÔÕÌ`Tõ„¬§<€ V¯æf›”DŒŠ~6C­²ÚÑýú’AZeaó‰Ë<Ù¼-ñÃl£1^·¡V¹£F,zr׳/D"YΧ‹‚:wBêeé²ú¹&=YÌc²¦žto ŸÐ{ÏMqªŸ§/ ƒÐÔ°&€r.HåUjBûÕCãôdW «š›>¯Ìa¡±HhEÀ«ÒCÒº‘/ؾ¥ý,|«ÕÙiì=›—U&Óq·®`È9öDp‘$\af‰³Ü•rŸ3Jœ÷̾[¶™+ÅŽ=Ê'‚Ç’"ή@ì—5«¦‹=&§O$ómnÖ¾œv|W´™|p8qþx¬s¢­5$×¹Ås©†ÚóŠÃcNxÃÅÝôÒ"µ”–ﱦ¬Ï¸`“‹EÈL¡å–³=„ÅÓdÍ~CšvQÌá’§¢Ce ºž±~lÓÅ{Zþ:³/r¯ÑëúΖ¹ö4žmÍ´ºú‹2û‹ö:¡ì4bìy±Eãª1X¤L =å…ŒëÖ¯°¦ðH ç¹;heœL ¤õÝ…uÑÛ ³†yqŒ|'Í6êá '±¶6E;”wïêé †¯ÕÉ8^’Å¿›ÒŠØ0 xÓ Ýo õÎÈÒèHM‰=ø¹•Ö '&_à¾$¶â ²Mòñ§Ùªb¡ÐUËý<íÛ&ž'ФRCÊH¥NäÜ0US×CRËÍ\KˆJŸ>ƒÄ—·ÓEH(ðúnÍõïË ‡ë±p½¡žè\–Ù0FV¶Yà×HÈj‰l¢þ /õüåvªNÌ ”°¿‹£$çº`õÔ¬-–{O6Ì©Eß\= ÑJ“™¨¹DX:s7g”zb®¶ÒD}£Øa:ñ¬‡]O‚XÊE®88rZß:¿K˜ÒSnÊZ]k@ùv­«¯^v»:…/Ââó7/õ¹¥À»‘g©;Aðº9Ü"C•ÓëÕÌsIŒ×â™Ý zµ¼m§‹ÚËRÓÛ¤v¦ÎÒ{ÇdwÃs¢½Æz¯Ù®/¯-­Ä‰ÁTvÐã]èÁ@Ï (Æ ti¶ËZáð4g%,š„©\=U$Ð ßš"±*ºævÝÓµÖ}¸f¢í}kÍÎÔ“áæ£$¶3vœ‘±˜t’õ‹(»Ä£‡ØÈÏSšíué›vÿ¢ýR´Î4Ÿ¿7AFh¾"A1±ôÛî‡öl_“À+ _µ‡ë2–Ï_¼V›ÔryÀN\Wødß«#ª—ô*ðÕiöPY– †—£[Qõ°ðȾ‡ÞÙõèFI±æÚi ïiZRrǽírì}"2|ê3Üž/b €1ÂúÉcÉPy÷:R 1 +p4cˆP™i’:ìuºìšò«³G–t–]äO ÜP犕VG…uƈfÀ:"óëÁíòƒY´èèb¯äÓÛ~ ­z$tºÊ;Zá¾ÆEdárîeîœh1PÑqâ5æçñ\0Ž±Þ ¦ïqÇ;úqŽü…º#xα頚,ϽÑ $V8%Lt°d×dÐlâ9 7!S1°+P­hô!,2XÒæ1JÒ²y­¼~Á’tÀKbø¶iiqGŸº2½äw.‘¯X=C€Ò÷¶£.,@#BXY Ê ÊQ¼µÃ_?ó,QÝD™1ï¹h$^JêMDoéîI’Q°“Í,,ÖqACW©Aç¡:C뺯˜e7í0Çk ¯xžÛ‹Nlh¡ ìæ:ÑY±ƒ<9qns¸ÑÏÆc8]Q»§NÝi¬çê¹wU¹—èí¾Ü©–§îÉqE‹3"è pû:ˆÚ; ϨÂå€öQâEâíâbPœëÝ–Û6ã»âæc}Y¯{½Ä\ÞMCAƒÙ0‰L^ÆÊ¸J‡c% =uòµe’“Én.{>‹¾Úê©$eÔÈû€)Pm»4"8.¯³„Zt‚‚Uåuãc,òW9Â*úØ[™ÜÆÂy¶“t0”‚}ã†2”¯À¸„†}x MŠs !œ‘œ‰CœL@½rDKrÈ4½4³Ò²p½ãÜ]¢Þd=„«¤;µšy×±P´3 e¨FY&Š&‹Ï¦„d–Ye»Š&?qGý½_ôÛÀc€˜qPbpÄÌBaÍ0®.ôyÌÊT™Ò#/ÏyÄ·¥íŽlÃ!tDW½›wwFƒñòà̉„nð=o#æaXX¦§D&E4€ÍýžÇaÌhÔ\ˆo-ù>L¾[*9ôtó‡}erâéÖqI8eTIÏ¢hšžs½É×$¦x;X ²7ùÉ §½Ó¤'öŒQ,÷8 =Á&I,z䤽·XóÖà®QòáZƒ„ÆØðS D,'«6Ï”§Ïƒ’8dÎwï/Þ_½%„…+{"ê€I$p¸¦Í29éb÷1»2”½‘¼Ñ¡Ñ˞Ƃ¾”w¬)ôúPKk:KTï% È2ÓŽ­{CŒGícÖ7ü¤‘G=m|úÉe†#Ò9Œ£f-ðÙcÙY;S¡¹¶¼Óòåiâ„6¿‰ÿÝÁ«5W{Hú â]ÇJ×°³¼&wØÝMÚ‰Äðld‘gµIM¨©`ÆÍÌÜ`}*¬(±¹l7ÚmÑÉo`HÛbß½0öÔÐCÇp.)ßÜq ÓŽ‚Ö×RMIsøBѳ–Ù|“ôµå`õ±¿x:§Òí+½=ÁYMÍhZª>èø2ߎsת—w8¥Ÿ;«a÷P”Á^¥©tq­ ¾°ð«{ÌcƒNq//ƒµŸˆwˆgГå -òZeD‚Ø[4À<ÁÚ38¥DÑ€lïEâ™\m+h¾z7=3AO6µæªæà£ó&¢eIT=¿mÑa÷¤,U{¶ž¯c,«ÊLò NžÄ\ˆ…mÞ–"ˆFàcϺ°eѪ‹8¼‰z¸+58;gF/W1¡ë @ÎØ~ˆ…ÚIЪ‘޵¯$=c^ßê¼ áŠZæwQpöVÂ"¯ãÙà=mîñÎÄ-J¢ÌD“;ZÎG.ÎÑ h\ÛX©Ë´/¢9 RTëª!ú°üi>ÒOÞ‰¿xï`ì©hò,H z ¹B”bº…4Ž6ÍŽÌžp] HÍNÐhyå…‚ŠîÁ ¬Ã8Tñke"Ü(Ïu2{­µ!NAð®vµsç(B F“&Åàt*#l¸<1ÉÇt±‘kºd‹íAEÆ!‡*0}”ÆAîf1t5†*FðÈ/W…ÕÝЩ)¼¬èfÙ¨îÆõ9ïb™—¨ð½éç·Ì½'ðžŽE±y«9n'ჾ—®HÜM8<’è€HÅûRÉßë‘#I ,x霖ùÎ= ˆrÐbÄcYKž¬Â{íÏ_–Ã#Þó½zÕÚ}R urZèRþvjßAYFüaƒF)\£ï…nûbJÛ.ÔØ$"Dj,í9”?-Òº³U±ôåž;AÔð«ì²É‚…Gv„ì·d,0ÐÒ †”,€Ø!cÔ°p(uÞD$d,Ø8ÉY}Ê‘@rÞ!=±ñ¬Àâžr‡}ÿè x戽»l®Þ2¶½Áå#({ËnâµÒî‰w+QPâÏ’µè2º^ë*gìkQN²†ÃÖ …gžnKÝbúµ&?iB—8DnõzËm;¡šðÔ1:XߺrŠ’ë™Ë>Jf~)šÅsšÕb;ÒTè2³ëì± ³»«šù^Óêd=%Áf u*ub'¼ïG¨•)|ñòæaeUß•w »·XL€Ý?ßñŠÑ %¤‘¬%xS{ó˜ˆ]Àøi<ìÙÝÒåtxâÙm®lüþ"ÞŸgÂke5[Y±¸®^ Dô%TlBV†1’yÎù&]ŒÃ»MØAŒ/êøLñ#ú++|ÂÞ‘ƒyðè>Mäaȉ½>8]wˈË0ïúMãv—¿g|ȱå¯ÕÝ©¯]SÞ£:xb³Îó¼KoUî|ûµ'àVN6ÄÕ†Âʈœ ¹y*x½UÛt7¥JRLbpÆjXLjÄ!%bBÁCPºo€^H¶< ¼)ä±»sMfÀ3_í¶òç qò´MÌíD‰¨âNíèCTÙñ#˜Ä‡jÇsÉ-MÇ–ÆÎôxSgÌÀèöH³_¶Ê&5âó°áØ_EÒ³P©°ú¡à˜Æ'Ó̹_Jï»»âíÌ%=¿Ô„}€ª'‰Dô!§DÞã·ñ|˽ýÅ^\àµ%TÌyDΛ~ä¨Úž÷Þ¬‹ÂΆo?Ã$Šç$Ä.Å µÄËz®pÆNÀ­‡es¥“ûåÂkŒî‡m$šáBÐä•T6/âA™½t jï<Þ¶"Y”5ͪ ƃ”ö’Þ˜š,šài\dxÆœx?ÕC4“h’ÝK1Ã6Þ»íl C\¬‘P›CÇ/ø&¤ò=.r±Äí JÑéÞ¾æ ä7ÍV Œ&ž(Ø,®wˆ¤>ï’aʳ›r`‰ã¤ÓæýÂÖ°Aƒ‚ò“x†/âw»Êo.yR n@ì4lÏß)àâ²9‚Ìë2:jº·~¢;ÖÏÝ)m÷ª]®#C „6.Ëó¶æõšÓ𤄓n…»Ó&¤ŸeF/àKݨf¥+ÕöáDŸ$dÀÅŠ÷D·îIéªóÑÈðŠDŒ•!»3à¼+E_$_³Õ•{Œ/R’Þàè{Úd”~ý Ûð1Ö®f‰@'AêLiúErµ=háòÂÆf·âàšî›—òäI=”€:j¥Ê¿M˜¿§¬t„2A*¬Wh!gzίîÅí”ThÚÈ K*HVÕ;%+ Póâ}ýÊBb$Àν™ñ¥Lp ^{5³@hÇ ^Qò&îáÆÙÌ6¼zj~4!3~5e‰ œã)÷¦ß[Káη%Ð ¯ZDXòé9XöJjÆ3+øèEWÄ-#_½‘Gq>Ç-²®÷nû¹/Àœ†v7kŠòÑ3ŒGK˜,ÂøPÆûáì¼DÅ…“=¶ó«ŸÓXbòìòé Èa¬BÚN´û%ÁãèN/À1Ë»¥×É%&Y‡Ëd¤E†·fwp똞 šíS‘I‹x ݲQeÁe‹çlLj׬„ä8$F1Ï+éá(œ±ÜÞiqíÉ›%ñŽé[ªáŠÕöö·m¦µáž.ä…WO¡NƪG…ï"±oqkäôCøP¤ðtû2mµ‡Wh¢À[=øE ·(ù½½—¡šÁ—¡œâÆ5t“§’ªÏøØŒÖ«Çd3ŒÑ¾§dj"ñŒÜ]òÍîkžoäýyå{ËÙ+íŒ>*·MÕ2”Þ ‹Ãc{º¯`Î0 ¼Ö’@gó„F+jç½{.ôLнg©^tg2‡˜§-¥ï;ÉõuÔòAu«†­ƒx1À§ÞË\ªÉ²WîM:ZC²Ë »¸'~yÔ-/ÎÛtÞ@ØZjêÛª(q·{}` ä-U#SŸaλEÂá:f¢8^Ü>I¸8ØJé-#7Ï"êw°%©$^¶ê(§ãeûc6\h ‘wÎ&·0üVDrß.ë•#§zsí[ïø‹ù'N³' Û¯MÐȺæN&Dq_ÂÅÞí‘7ècEA†$$%•K÷F©Ø|9Ò7NÏü̳Ã+SvÔBƒííší!s%!TÞÖuFûLÚb–´ºcæú.´Çëç›V‚^Û†RVâl'dWJhÑyYº“ÊVPKmuìA2ž-—)E@2¸jn‡önÁ^œuו¿taÔgŽx;V¾ünPú’«ðAĽΠ±Àó925Úlšv³Øc z9Ú‰{M”]õ„'¼V, ÛòV÷H†è ‚*϶¾y‚âÑÑÓ-øÚÛ6š¤šå’è"‡ì|~méVª/)¶&|°ŸœMãdÖ¨ÔÍ+çÆ‡¼j‡¼véŽMX +My#‡…¼Ç;9Ïéll<ï™R1šÓtn”2³gåÚÉ×íÁÅá¯+hû‰ÈŠ7 ±‘®ƒ½~Ñ®¨2ÎÕ¢b]Ñû8±Þ®Q’©¨ƒú{¼ŠàÑ›dÖóxó½‚Ú÷h[cè!#ùL޾À¹ç•i²/Åêñz[ê[ÐIÆHvôe¯ã¹´Ä ¯£×4›¥…v6Oé)z0<$éUãZcž¦#¥DÖ®W'!%±Åüb‚ÏñɬýJsaÌ[Ua5Üæ|BmìX<¾ªofªîÑgîÍ7õèUõ6šh5³Cóí@#/ò¼OæE¿˜ꢱ÷ཋ |!ÉÁŸ¿n>è ãuÛVg€ÚÐz—ÎÙâ9ÏgV2ìø8zs(ØÄ,‘󚢖çŽ?£«Ú±<&‚ˆ˜Kg~€¨6Æïü¨0÷ž<Û*–éŽÅ7WüœÉw1 yoêunÙ½xÑêôeMÛŠÕ£aÛb)d¸9hóà³Ò‡ZYÝ s÷²s’­ª\kÍl­jÅüŽÙ§žÂB†¶ ¬iUÈœ·'ÚfóÚlõÝ«j‘D[3m …G©=9äÏÿ‚Þ¤CŸSƒ*6EOÂ3y¿J:-­¤tk˜üªznez³Re¶È&¯io¯Ëž(àœtñLž8B•G¶»¾gA-æùŽnóAïœøIFˆÿn×ñš¯2EhU”s!°ß6µ\ 2[8ƒ„Qk° ‹†žm :W6ïàáºìªûÚž­·[gp—æ<",)@¡{‘ÂNwYžAž~ËhN¶ïm´W?Ùl2Âï0´ýíÎ+[5Mö¡jZˆœPT[=‹X}í ªžù Á4Zå½<>`G}"u¼îI[•XÌT{Pg3.‰—LÆâñzðÜù‰.Óz˜VÍBt%>É^QEʱȈ|/l¨ªôº¦$áÍYö>,yôÐÝRÑ—×Y÷-‹ƒyqV\òèð ú¡nÿŽ¡ÅÐ3(Á Íx»4×íªw…å¹—Àüä<¤tì-]¦GݹÜ!7¾gõ̃—’ºž—\¬žìé%&Z:‰äÆžø%WF§ß,ëŽômÔu5AÍd=s¤Kæ‚ÄŒH=„>X­‰‡¥yK”Gáì¥º7n,Z2zië=‰®*V{ ·Eƒjv ‰rÏÁu2£ç¨ÀoT[<|ü4†ó°ñÅë×±åf³Ð·÷¯H<øé¬[ >¡ÎÀ×o͸ T$‡½öJ—‡ƒSWzB}½[ñ½c:÷ ½òôG"Šo†‘»qNúû* ZR(Øg)…L·h˜œM§:äc9Ïìx@„»Ž[è áéÊ=‹Ñãòž®(4ñyõBõÓÝëÒÕ|šz S¯šqa\±žsél‹WAè@2Ñ0Í¡Éb-Šá•P®êѸ&:qz_fW6§qPð{»…ÂÂy~©^QŠ™ ìÛ«yëéâ$Žax•¯’k`L×Ð'ûœß›÷RbÈí¼;ˆ¯%c é>½‚e(Môz™§âë´ƒm®oè÷Û"ëw¹íêò'õ¼¦âÇJ§(ÝÝVï,}cÝ_O⥶‹.Í+³–W±ÑÏ÷Œ(¤÷1úÃXœ¼£Ï„îóhD°f‰d{È«%hòº÷ 5_.øf<ó¸\LOE¹n´koßÇLàI’¯ßŽ’ª‰Ú\¬Ú‘)aj^ìéÎÓ{]¨ÑQWå<E-¨@ÔH'›ôú—WQ!1Zø¥±·æòò‹>¾>¸J4|ªÀVœ>;øÞ$ZJ7Uo8¼ù…¹MÓm+÷p‹ètXûz­TÜÊ-3,+M¢^a[¡g؉OrÉfäºä[|$[³1•v™ƒoÊuüø¹¸çà†êrÚd Tr¾›Ú*’C/w±Õ8Æ K—¬þSîm­¬.ôÞž‹¨¦Y¹ ì1øS(±Î±(`#žA4 ¯êÍœäaÓë5»¬KåF¬È¦êògÖ×¥–†£u6G÷ÊN../3İñ(áyÐjµ˜j„ƒÊ‹<ÀÆt†ÑBuum9pãª|;ËQ¨hAV²–#œFçQËs³o Úê³ÌGïÌSu×±W(l_9&àžòu°ðÕN£4¾|qšíU‘Ð[ÈëèxF†q¤|W¡^Ÿh÷ÓÝôáu¸g>#‡¨™kH;pºpõ{Äç•2AÜ¡˜\AN÷rBUèµ~Roô½‚5 [òˆ2Ê'Z)RÇs/»S{ q‹ÍjÐg\dW?†¤à1Š£ ›{©µp‡²SÑ:2ŨÌnüáZù„2ák{*ƒ€Z:/ iðó)¬zг·k ™äÜ gtpoÌ®]^9º° ˆät³…®økÓÕ[ãŽl·LÖL?wà£ÛÚÍõ²²²œ)RÌߢDÄ="¦-‰½=–“Õ¨c45aJØ:<<Î}7(jQ·iÀÂ13#‚cæ<¶'བྷfÕ¼îé”uÖÖyÿÄþ-Z—F8¿ÍÔ~HÁOðeñr < =Vy{jˆ+¡Þ7ÔO&¥xÝ ¬Ç<¯Fö‚¨›yg„"ã’Dñ´©æyM >dÙ‘‡ër´ð0JhýQV/#Ö'h=‹ÑÓ9wžŽ—S’DLÉUu‚†xäÛ~àkZðÚOûµô"ÎÁˆ>1†çœDÀÖBç-ŠÎ~€À¨6^ ÉÕlUžÊÆèPÕûv5ÙÊxZìæD™ÀÙg{î]K‚*{c3% Ñ%Ð\€œ?tv:G‘'h‚³¸#©Or5¹YôÊFäü!Sg³ ¹Å^›qGMÜ&‹Bv™¹ö‰^VÕÆc½·À¥^¾Kh‘“hÑ^gû@úéË÷ñ½¨ƒž‹0×§ om¶ ð±L0“‘¨òu=ßÙ z݈}œ‹B•k´éøò5 ]VâT7Ô U³ê<öU ;É1º‹é'MÖܸ2ó"•­˜4VùÙ%"·qi£W€¶Ÿd%æ‚ÖÄ'ö_ØÇQ£çlÔshs^4¸2}™rʨmaõf¼9™l®“¤(s 9Ÿ#¾6]Ò.«}8ýäÀ™{vPÔª’ÂÅû®Ã®(á=,ÀÑ|W%º±ÂÞÈäÏ°Ç É ØYS±ó숱.«^Ì#ãw ¤%‘ÜÝÏ%éž¿†‚Ä€‚£Ì.?FD\„£ãEŽgA&‘BÓàQOnFèqA_YéxnèëÄK•×Ò@87z«‡^—7µ]YäøÞÛ¨ÈˆŽÆöóÖ7¦¤Íþˆ6,päΈ‚£f×Þù_ÜSíef›§—îk¢Lɰ¨© è L&sZsÉÑ=§=´nï1 »z V›…“X(°Â\³[n§²¹§&œã °Íõ.|‡V¹\òX=y£®È‚’”4ˆ¸8Èõ™1kË{AÎõúmÕù8ãpäã³¶èx’½I4íÛx½GÇÒLõÐ[ èX@|iAÃ×t¦Ígó,™«J…By’ô¾w··ÔJÇÉNq†RÐLL„gÕŽ­vü|‚`m¢÷Þ„WÖK²,Y|Ê/&_K¹7àj€2êÁ°«‰ ¢ñAL¡K±öÌdäŠ \(ŠÌj`=`¯1ÓI)|)ap¤õâmv=£òâxœz$TÍrFhEqc–8Û] .žá좆 ”Õ,Ó¢$²B%C˜”ï1Iº¼mt8}Ö³t±­7¯…ÉV«‰ÕÓ°ï´ÅØô Óæ°²4¬ò…F £"Røba\Ȧ’dz¦œÑwù üù.\²#<44Å稸MaFh7+li %É•‡¼N¯«qÞŒE5–rø Ê#ßpz™ATË£',åI$º‹Œ»5è7¨ÌO=—gÖM|ÙU®ÑYºPäÄxÑ,_A2ëStÀ&g»‚'[S m©6„š¼™¶À®4ÚóXãÍ‘Ôо[H~9„4ùͽqŸ‹÷.ßS ÊÕê^ïªò•Ey,!Íǯ(£êá½z€]7œüz¹‰{¤Ã9º•$¶3`)-ð®²Á*a‘í’IMGÕÅ`á…>·’ꑈõUÍÜÁòÄÀ–d¶S|ö€ðRgsºDž¾¡÷š˜ŽÚÞT ÆYÇ¥¤‡ÒÞÈ) 50ØaÀÜ^ŽÝk°Ñ¸{ZÎ)¥e-bk1Ã'Р‚xq¢í¡õ¤­ôU>i½sª<Tñ5»OM~»Å xï<7» 3®õhDäyØ€¸òòñ4±'¬þ9ß“aúÓÛ0–gLbáØÔ—jäÁíé®'v >£tÉáÄIÈ¥¢-ƒÁyXv(d$%BÓ¹9ÚÊD+hÀÅNŒ ),†‡jA/ȲI÷½M§×Fƒ Iõ\‚´fÇW"9ºÆZAµN.ŸrÛŠ+d` Ú:3¸Ž²W×”²wÎn-uÒP?Þ¨Y™î苘"2—ñ“G–ÇX/g$’äHåF·tÄî”Mnjg¶kP{!´§5WRË.êæt½¯Ã¸À)ßAëxK‘PH:Ö 0ë³…àÝÐ1Úñ‰¼#{o(ø. •b÷âò ^LG7oj ?·- U.ól&i[×À¢ j=Þjc+5ñ*…¶wNá4:½².“GHûv›_è#J~ÇÐìÙ“œŠáËP¦§½æO¸ººß´«ýÞXä‰êqÍ«¦®_¨j»1Æq1”Oh¢È¹Ÿø!D 5õnëºT£–¿´QÕ§~ûæEj5†&b¾0‚wÑ¢ø–¶Û‹*°‰âÖ\€!ÑØ¥ÞTŠ4dQ BO:lÄbZÔ¶‘RÚÌj ¨›¼‹eÎ÷3¡Ê2åÝ KÜyL3özfCü•?öñG¦E"O‰Z‚lˆ. ÞãLny8ñ”PP'ËqáÆC›ž ·ŽÙa–ŒµT}‚úþ+ß°–»¦Ñd¸´Y»Þë€{…ÔÁ°–Å(p)v5h.Û" :bz¦ üz%Ѽ¥ŸìR¹¢!¿æf(ž‡O#k&^oZ ¢ ºƒpè­f57%ži1¼ ë1y.Ś㼨ÄÚj£þÔÄjö=m \m|®Y,,O«Hp£hüÖ„›Êh¡^ðf™*’Þ¨oÚ¨lʼn“â–l†³~õlíž7qž·ìIôÄÔá/,ÂYDê™wKÅÔ›]N‰¬@'Cß¡(Úa›“ xJzZ3ƒ\eŒ–a”ë@0 ™s‹3ü ƒTT›#Zž HnUXGs˜Ãʀ튄ÚZ-Ó0L=¢š•²"+”p+‰hÃÃ#ØòZ#š©{mz±)^°…øBj/š$äày1ìC*ÉCÁ¨ÒÉØˆBn"ŽÄõ–ÇcêiS±Ç©ÜºrÆZÖjÐík¦Ò\"Ez/å-÷Có ‰à'™š¯8Ü'd±¤)Nm*—UQÙ™éѬÚt¤ã]bº€–ßÄTÕ<á}=Ïýw¶#yëa´©nå[\•‚î½§á´àÈFœ·Ïo¼ÐVSòv„v™#@Â{ÑbvTB%ŸÃ>ê^wD‡ë=ÄiÚÆ§©!ý´øy@ÛÒ /›ÔISwyúÞ«5&ʲ¦’ (êöFU‹÷E$µ ‹ê¾ÊÀÈÁPNdŸ¤y¦…få´)œ¥P™>`Á±m„Ê&²^cù ¢1£@³ÂÓ}¾’„k cB@r%´ñØ¢øŽ‘ÒÛqObÄò¥Y +‘¼vc“{ˆ9Tàöhj¦[G‹Ÿ{è#›/ò ø“|~¼ý°.oêvf´&xÎ*c:1öÀäl Ð)Ou4¹úlP+Á1=(õ]Ô“ê¶NG‘]Œu&¯&BvѹŒgܯ!j5¨›0ÔâTEõÚêq÷+}˜èWÌ—š—¨ù¦¨š iïäE«õ¡³:8©<6D{u×Ë‹›ƒÖôM…(dæó-šFNB£wœx«¢w<ƒ,‚½¼ÖJX”) œXäæéaIžàÒd’tè Ó¤n”›D•H2½ªlÔÄV·yŸGWuÑ-:l/þB3xÒn縈BÞ–ØÁ#«³éê<~ç\B€’ç¾êôa,ÏÃqˆŒÂ—oW7¢éÁâ³1³›Öâê}çxGk‰R19®ÇŽ:˜spÒWwé¶IŸb ©~õÈÞàæ‰î½:T»zou Ž1‘pV¢â6, ýªš Ë,g¢꘤OM MÒÎÄÐmÍ4Kìí’÷ «ŸS{{]ùC™¡äœ¹÷dÐG:LØ”ñ´$«¹åP•TFãq›¹EJqç YzÚÅ9ZváK÷0Š™ )xi8R®/#¬°Ä§R^tŸj¼Rv$#+"v¨hY°C¥)‰mDZœ¾s|Õ¤züÄ(Œ^={5ÇQ¸û†—x‚ihýB–ñŽC+ŽOž(`8<ÕK‹R%ë<÷Ì^´åðÕ™Ri‹ØÔð¶òä¨c¾¡DÒüر¬ñ}¤/ô­-äcûø v˜:ûqÌ<U`“rƒ=v¶~˜^ûP¢k(³K¾r}|›ù$$31éXBÒFKQžè›Ý‡UÙ̯=ßÛ™ÍpHõ§Ú$d%»!@s¥›]##š‹\a êµhÜst›ür…2é‹vç¥|ꯡŸq>ôê"[Âc{vYJm¶ù¼úW’c<›,åÆw[k(T'U–%i~òX‡_·1vé••‡Ã‘z©×)eÍŠY ñó[ä’@ï90$rVhké-N«Yq_;Âþ‹}{«FËZd<Â#î¨]ó8ã˜ÜŸ<ˆvQÂÇÖ";çóJÒ¦ ˆIѳtL`ϤÏQ›^ÂÌ%aNG˜ö±¥†ØreÐrÓ´C4 Ú­IlИ‰ô†Ê&Ë(-&´qs¸…\?“Lõ`DO¬%'Lsó!9 Ó÷zWÄ´Þ ,½NU6ˆœ$Ø×N󸨦OD5OˆZ8n»Ïa8µ Ǻs°ˆgff& šîDÒPòá̵¸áäN¯4Šwv£ïaTIqÖ< 1®”yÊ,kW“±YÀqš^dÖ ñ‚cÒÙAài™éSÕS¢¹g7o˜öt G›œÍÐNpèéðCãpAžÅcqS^ǘ%Ž­ö‘¥~2Uw¯­-}D ·ÏèÈ=Øl)›ºVÅ£ž ?[tIwß”\#Œ $\~¾ýº^¾W&ïA!£çËZ1]q¿‚cÌjÿ]ÚŽ',õ6=|sÑU®ÊÂG¦Ê^8 uÓZ-õ±ÛS>ŒÃA»™aáZ,XŸ{ìÅkQÀœÃ‘È»aHþŽ’ OŸY+ûƸHÄõ²“†•ß¡3zá„EÁ'û©ÉÇ7-‘8Dï9æJ‡q mŸÄ>åÀm›»JºV¶whÇݳªÌÀJ=;7Ohå­&·%8Ò`·=+Aó&=0D$€-%›jŠèL šKñ{O(âò匂‡ªs—(ðîòɺ˜5¤kk±Þâ›ò¥ž‰é«t©™é^HK_9Ç3¤ñ[eEy󆨱æÅù~¯ˆðͰ>À`, ŠwùÞRéË© ¡Õ€¥YoJÍݤ^;.ÈK†ǾÚ&NdàB5L,÷ÔE¢ô+|iÜ Ù’ûü5'OÇ‹|  a¶!<¬xCÝ)÷@ß³[ò6› [Xè ±6cÇìC7(§Ä*Ú¢Âê>K^«Þ|ÓyϞ͵Ñ0[Ÿ·0Ÿ06–¼5Ó(èÑ£mõÀ¹vôG¯sD圄{Xø2ú­Üš®ÙÉBköLµDû€sÆ$íJÙ³•g Q—zŽsè¬奄×ÞÁãu|8Ï6ÅÁÜqhÖ8Þ¾÷ò¨ŸÂùnÜD$ªÞ»òƒ¨= 9]Eiðu§ˆÄ{=s¯:–ŸØ½‰7¦Û2ÇJh²Ó2Ë„©•,ºiÍ´½I¼ÛÆ€ˆšìZßá†F±1?'¢¶Ù÷Léä™5†ÍläeRÜ‘<{{ýò Ð[|CÕu§¼÷diq±!÷SÃxÔÝ9Önx{Ü¡Qût½À›Î ¸Xä}_ͳ4®õxÂãís}Êq ÏsÑÊ@ÒUÚzcÇqùêo)? ~¢»Ã^O,Ju=êÕ¶{@;R=êGèöìN!÷²µ®œ„ªUŽtúÙÖò„ùë4–xÁåéïÆŸùÄBX^¤¡¾C]‹õaõðæBRîL­wÝs¬w9AbB{l“î ꙾ÌeM¨«çrW‹ò”Q4V–ˆîŸ/áîÛóaR}ÉÍÄo-T7^‚vP½xí—jˆã!ÈMPŠÓÉì7dßðûü—‰Ü[e³"XÚ`* ‘ïÅsQ|%ë ‹ ©Œ>g/b 5Íðʱ_gÔ¼*_ Á‚j ’¤à­Að§îz+k‡‹vÃû’qÚcýú8Ÿ¾ÎÂìñ}#J‡¨Þø«rײ2…÷,NH1¡=ÇÍL«DÙv‚*i|%¨3ʰ¹-I6 7× ÷¤^ÊCBV-n “êÌ|E€v5L¦Dõ¢xðÙñ.‚27%MªÎn§<¦¥§Ò¯•„¼nm@÷DU€ßc@*¡âjÑaïöÔ’¨,@÷ͤńĦEƒµ?é—Úî|>ïhÜú*#Zp8ÁÞSã6ßs©¢§ë—Ê5;Q3€S ËzLU*uC*™/g¦=¸å•(x€¿6:SŽ ·cŽ UïUÝ!äY;ˆç›}°¡OÞ°Ï3ʔঠ¤¡Ót°x³!’‘¼ì¡ëF/{Ø/¥úŽç•&c³€“¾°‰zž-íûÛ’Ál§§4Yë…’A!8œ™úNã©àà Ñ…)AoÜ GÕ{x@º)>Fðîšcð¦‚Þ#‘{‰‘¹“±‰Ë÷še3Zø{QIö€¦žA@GÕ\å&Çí¾}]e¼è`'ò’ _›¼j¡(^^j×3eyÀGƒ¾«TJí§&G»£«”ùÁˆæÕÚpøvm¦/¾–z½ðøõƒÜw›oG:ÞKhÓƒkô»áÊ‹WRÔô¦Ý†G·Z{S×Då†V|A”ŽßóHöôj¤öz…± è a%eò°µü:Ë=sS]9¸Â—;Lн Å.\ޤP½âݦ¡'‘ ”GíHÊáÛzÆÏýaSÞx>MÞ$r 1(¢ÖWjU Û¸Œr¬Â§ù6%ûŒço!f_ø¼Ù]Žè Ÿò¨Gâ»J碱“Üꥨ#˜ß€ö;wÊ£¼ô;dLÞñÍ&rƒ1:Y3Ç¡e¢z»uîןô?ý¢ŸÆ™ŒßhÅ£ í[‡>ÜxD*‰O¥_)fænxqZI9B©éÝ®Î@VË AÂì’CÛÀ“̉ðá5C ®1ã`ÉšUfŽàLa=³A•©:¦}¡ çE·BƒéS® ±£²ò°»š‹Ú뾪—ÈâzZÉtrû /=—¡eŽ"T/뤜דCMœ}Y: Çfããªè °îšL`ð^¹¥#Mó¼Xv'@8§Ò^9_¿ÓÛ×ÏA«©ì5•¿¼2àÇ¢øâ\Ÿ¸!m\îë|ÎýÛ– ¼M0+»êO‡ Í å\DiNͺ‰f®¢ewǼ¥D7ÒZZVr3‰Ñ!á.¸C”—æU\/Ûô @Ï\Ümhà“ïèöÙl×ÔAæ#¬PE½<Þî€jºì^™ôXäÁãCÈJ©) ½W%Õx™â‘A™!S(·ý˜`49e-f ‹±ÛÒ,+Ô Kjp(AWÃpmyWÖº/ ^5”c¤*,fóíBá@³=aÔF #‚œªNQòhb“EËÖK ÍÌô‘Cãщ|;Å©µË¥ eL‰ç#•iâyz:Wµêz§é£$(öãö ðª‚ÒÈéC¹’xÎ ç^Z™x“)5b'·E·P¡Ž™@ ˆCˆMcÖÍ*Uºè/ȰOäT<ñŽåymܘór#冤$…Ú³mÖ¢ÀÑ"¾qaªHëª7®9Lú¨åž1ì.Kf§PŒ¿ƒº×£¢ÏÙÙsĬWáÍÃ2h†™CWo<)ËÊ×çòº`Gj6”ûàÚ:³p€Îb¨ràbç؃'¤þ«±çI€Š>ÂñQw”†:g¨bh¸äA27_&šë´~UëÌl#D~þ–åu05¿“qÛðP²óè“R›ÕqJ§p‚'‚qlÖ«­8Ó¨p3õê|'Tü¡-oÉ'þÌ_øËbL˜»]g6<·%j=‡×óMö£¿w–ž–BÚÉI‰d¸}-#cµ’ ã2A!O`®U"l˜_¶CðB¾Û Åê Îx˜ûº'MƳ—«m<Öæ­ ª@Mʨzy Ôµ¯‚/:ÏËHªœæ;9°…†jÏ8Z(JÒoðËÌ2¹1Ì£dâÚŽ´ž_âr¸}ãa ŠŠ¦Ú¼z©~çLâ°ó”8+:påÛ—¶AãGw¹Òt•"•’¯É’ΰÆ‡nÑ"šrêaQÅ{ܳ¼.•{—',Þs rø*ÈÂGtRÚKÝóue3ÌDãîÃÚÎjFÛ[j– XÌ[q_„hŸTcyotѶ³ªIfœ»-’;aQßÄòd·œ†¦Õv6º¤½÷»èJuÂz;mØöŽv¡3½ãBáQîêÄU£ÔʺÅÀqX•ϲz1ÜÌ tX3¾æ>—ØFx‰Ï€»£ LŸÄ’'V@p êI!‚H1ʶW¤e/ ÃË“­l0¥Áµ\x4õ`îÚñQ0‹’¶­@Õ9Ì\–Â[¦W-&̵@J\;¨Íƒ7=ˆ­|yZ¥·E¸p òdüJ£ÏÛÜA¾À§U2<Øõv <ñýb9w·WÝÚ ±˜üž1 R$–ˆvõ”§­é4¿’üä_è‹ÿö Ó,ÖçñÜz_ùð B?z°¢ Ô,¯p(,²šWt7á(ôŸÅ\8äi¬½¢1ØÈ¯vrñ‘£R/VÚiú3V‹"Èìy[¼ŠÏ©#"Ü€GÉó2/’ ¤§@Å]N`Àµß–˜<èç†èUÈtou7Üçêa¶ÉØS‡Ë2ø“Œ‹èüõ]Tg5¡ªKÝ˜Ç Ð C .tó$f¢‹M·°dÊ7ÇhðLod­] YÑ3Ÿ¨ðZç‹{ýLÊ÷¼kMOµr5Aí£õ)l¾‰]{ñçÇ*©g“¬” ¬ÃlÏd“g;Äöƒ+m»T?µÜ²ÒÅ Lã»';Ea5„#ŽRòzßÀbëaij‚É é'6;“ÞQ1Ï×ܺ…K©kÂz˜Øvâ½Y¬Q¿T7À÷Ö5—õ™uƒZ³CSÍÞt@ú€#((1Þ‹åÑ÷w%™÷ém‚ÒÉSãyXØ‚—§Á ú\¢H±×ò­4Þ¶çÓÊoŒ°D•NÃkF€v0&ˆ«aÌ!ãlB¥J\NôÞA¡çŠ–å¦|kº¯Ñ,zÂ&D6Ë×@DtËä¹¼¸Ö»F}¾ÔI©p  o„óÉYžÞ‚ÙK5Ss•z‡/L÷î©ÔsŽ!Å¥(TèéÀ§î®¦+é"F¬|ã!]IuÅYÉ¡÷BÖB`A¹S ²|œ«0ž*. Ü“‘¥<¤Å Ç0xÇ¢!/ýnΨ.ÂnìÅë÷®+{A_Ãè»À5Æ ¹¦ÖxêÄEæ|/xÉN«×½ð¾?þè÷ÂY.‘¸Œ)¯‰Ò³ ŽJ#ÀêF'šGF³RêôÂ1´IÎVºéÈãê˜å4¢ËnÕÄ,°ù1=ÎÅSzOb©x5F; ü"Ø™²…š8ýÌïvʾæ•{¢F^3Ãa2eí“^ÕÎÝöîˆù {‡¹©,'@I¼38ê'µ—¤¸ã>Õ{ˆdF>ÞãQM-aÔ; §ri’È[Ëj—b½¯†ƒ½ÔÕÆ8cN¶õäA×Ñ®b¯hµ¹ò܉ø3Óz8çmw]ŠLž¢uVó Ý‹S^Õ½ç/^ëNº¬þùðTƒ…!›8 f˰dràsÓ5ÀäXmNØEŽxϲíQìfáᣙ& .b4e@PØ<ÀÈá‰ÉWm@5µråz ÌÙÌ( ën¹„ûúí½ÙçmçæóRµõÚ+|ßÛô à÷”´7—X}<îb~¤í1–†î)dÔˆ:Ïü]¢æ…W>0Èm°e‰ßm?`ö—ô‚ýÙ.&¤Å¹`Xˆ‡›ëI¢àãæëš¨Á½­Ýè‰@¼îÒ Z°x¥‡Êö»‹^ h\ßW,¯§1ÃÇ[ʇð€^€û‚JS ’˜©Æ¢Õ {J³,ïyË"×9À MÈ—˜!V]Ø~ 5û¢"dX D—Ú{èx½²Mô Ì>§xƒ·ÌOÙc¢è¹ÂbΓ%F „™Á~ã¬OŽBS9S.¨Üï­ß6)»L<ö—zÍ-×qIxy¦²žâ´È `TÆïX!ðB Q:Ô¾Š|ËÍMš6Tàçn©Ikîn)EåÆìåxîá–tÕñ=—2ÅÛ°}F‘\}à'O…àÅ7ù›yZ!ÌÍ£]¶¤¥¸ð˜$:3szüñ›¼žêê% 1-¢Å7UUèÚèÓ5Rž‰Þ®ãª áy¤f¤W–GÚ/lÎÜÀsdTˆP‹IÒ!¤ìÙç lCçâünþÙn.§;†¢rèåÂóÖVéIÌ=#Âr7Úycrçs6 J6¤ºD¼ŽÔï'Í[ñºÄ£Ú{·%Z {¦h ñ\-Ø…-wÃ`Æ­ÔÍÓ‡¨•Ÿy>>;“hxáZ`VPçe éÄl¥X·+Ï´eKÕa;öûAÍ@‹º?Æ7 Ol^;b¬xÀš ¼ÔÇXmüZÓ…ÊŠ¯úUÞ«F)Nü,ÕYØ,ú^]\@wûù@¨<)\Fð-Q²*–1Œ.`õ¹û;1kÚÆ‚À¨…QדÔB,’©cÿó€¶O1UÂEôRW€9‚dMu öøf'2ªRA£óFÑè\OÎŽu ‹Ô;É8 ªìÅ%‚èH·V"žó ßdÍ']í£šì¯«f7uL­û¡\ Ÿ$ 0³Ÿµè$¢Úƒ4 á&÷b,ÑÛa,Ú›Õ&›áz³QÝ$I€Ãí&ëôŒòÐ^8)`)È8ËìZeo1B=ªš€añ‹ó|ñÞ¼êœêvÙÉÞëHK³%]òušB±m좎h2º÷ ‹ÔEÞë ÷©)]¨ym¸ ‰*×ô4U §L ßMã JÓ5Cfb[‚ñ`ͳQß‹BE4?Uz£0Îo¯[ W´OÇ/½”c¦ÉW<üee[Q/`d‚Õs¯díy—ÇVB4¦†• ¯Õ¹ ‚÷ù8mu!x/Q -%ï׫ñ ãhMüÓ¡ìâòd®Jó!¼µN•lâ}Ü0Í•¿ÊBTm¼zârOxLøu Sb¦°Ï3³£y éÇÃto ö+˲Jj•¦®œí¬ö”pðdbÞMHma½)ìÒ†« œ§(å5Nú:+K49ïr‡9”æ t|¤pËYö¢{½E8ÌsÄÄw(Z[–äž¹ok K‰31­5ç— Þ{¾ÜyÐþ ã^?Ó=(q˜ö‡›cüá¯6p`(³O4èÆéM«?õÛmЄ6îóœ™ia·ÂôáA·±YyŒ‡¨h*cÁeç\û(=.yÊ #B î)i‘hÉ•n×¥Xg“é%luÒØû´DÓ‰MÕae•òGMoýn·Ýýdè›-MÊYê½AîGB]ÏÄ…à UŽ…Ẍ#X_.æctô—©°— ˆžähÌg•P/Èg¬ôÝrY--D=¢ºÞôÝ& ©µ†XÄçdÏ`@pHC€d#¹ß¦öDnß³^8Ï^¯{[‹c J"!ܦç5ÓŽÒÙa/V°ôl7¤ñ#;åQ¾#Tgäx`ä^̾,ü›nâC.€ÃkŒÁ3ChS¡íSá{Ånäox<É÷J@µ™Fr4|Q¦Ò}ƒdy6¢4ªŸ¿l–²C Ê™Ãü„5‚øð{(„ÎÍ=ë4"°pkN3´¬5â²K„ˆ{A£¸–3!„†Ù»SQ1½ó(c‘ž(ނӰæ^.Ø.Öà#SÙ·‚¯U°ž[íB$p®¾%qpAËÛ| ‚¨Ñ7twÞââKJÏÃ:ÖM²%]_p䣄TJ?íî:Ž7™üÎü)Uu2䜽wn¸Ð>Q7ê*ªª=VË·áA­8=ÒC/e™Ìv׋ó†~•¯Q…$4DºÓ},ZøÙü{œYJ&:,Uc5+Ã}Œ[%êͺ `:F!Z'Þ©„¢è:Ü yG?4õ'¨<Ï&mq‚"gÌ ÔS{ˆ:¡¸n­‡üÕñKqŸ <(²Tqn6NNº· ‡'ÊlÏ‚R²ðÊ즓£ÈUºÖïXW±W|M$íê,¤›Â¦˜PM=ƒO‰Z%jIbÂWœqŽ›Ná=ïÙµ:LHbâÝnõ;Ê=©ÐèX·Dl]Á˜ÅdPJ„öçÏžûÙž¸„çsÖãŽP§RÍ JÅ„|yÕøüuð«ôW³'({}óç^`ÉqhñQ‹'Èë¾Ì$ÇWJ ÂÍÑû<”û=ß–ñðV=Ûg/¼7°ó½–Ó †8RÊkÙ:ƒZPôm[ÑFi|Ed%òôr¶œ·hâq…ǶëÁ©+†›Pv¹Ÿ³ÖUJW=Àe&k*Y‰6%bñH­}BjCÀ[&’Æg!й2O±Ôîegg´é{Ý=¤€;d^Ò6šÏ| _µp,YXçãë‚XåÈ~É%€+ã‹KæÂïí¨´éñmsX€Ä OrT­š“ÅÉãrNr8¹š„Xˆ{›ˆy7¢.iÈÛ×ϵ8†:l5)U‹2M'æhÈú²›˜^&:-ïiÆy*™¿x&ìXÒ‹ß»Ã:Ø™Cõ¤Z ƒF뮀£—pÕrò´!è ¯cªˆÅ“%1B•´}qÊ'¶TÞ;>Ôƒ@²32›:5Ùí®P£ -ệ¬ÃÕˆ¥¹¹%ƒPwïb¤Ê޲œ„§ ÑT!‘dÃÇ”\ð@HqrA‹ˆ—À‘R©¸ß½ãìz3¤Ü…Ç%¾w”Ø‘ÝlÊ©®Ép݆A®ê| iL‡¯¤&Û3ë²ÕѸmQž…61EAvŠÞò™o¿aÛôòy‰õR) nøEC@èzÁ£Á©¹=×IgÇktæO½Fé”=É»M}ïè|+†´½¯a[?Ö³ÏFŸ‹a¶rBÍ„«’Q Õ£uj´ˤÑG¶¡×ão߬½÷ÔãÞ®E'Ö±€SóÉŽ#tIõœôc<³Ë.œdM©(êjŽÍ9s­w¼g˜!—hsöNA#7áÎb$™¬Âwíð¥4€>[ra|¬ á/ð6#k©««êÈÚ¸óžš/H]a‡‡mžè]òäÕº2+¢º´¢å#ж4xºœí¨qoòÖã¼^ÞJˆ!\xŠ@€u­*eÄ)l‰ pe9>Îç\sÑeg±ÝkpñÂ&©à£mú]zÔädOÒ—ù_­À49ü‘ê)/LtñZn&v(ä[ÜÂ$Þq‚לâ¯W:Šm¤Ÿ’†ä¬Ü˜€ø¨;?qxàêìúÐWTkK'\Ò´žNøx¼î6”Òf¤*),|Ý`xuíï¹æ•pWߊ?ô Á´¯ÎD†(âw¤B}ÒÍϵEp(DîJ`CwÝ$ÙÓä5{%»ÞÒ7N&L]©B,g«.õNa«—zÆ;„rF0UÙÜëaX­ LÜtç“]D¯dVw%œ«g¯©g­ÓªMpä™&blçz.…ÛúÆA룣6ÀÔH† »òÀŸ¹jl" l¤UˆÔbcU¬Ý©‹õ‹--0nP<òÁ°¨÷²|èÁü‘tœ…ªƒu)¼«FÓ*¬ÁõPa~T>µ˜ø¤™¥^p±‹&¥¿i—Ñß•s13½µîm.töÍ}wštUÒ>J8R»‡Ý¤†±åB,Ã(W–M“üÞn`F0qÇØ¡©&3ª öók ÎîVï-Q•yJè,<¯5rA<ýá{ÞhÆOáã.Ú«k2V¾¨1òÙ nÍͲÌÕÝ—J¶þw3€Óh|ň¼ãæ+×2Bï¬)w‹Ñ;ùºÐµlÓ…6á{Í™Öêôn Òœ8à‚ió=~ÔÈeŽÉä!ºÉbùú*8õU1ƒ ñtO)>m!òkìaÒ3Y4Àƒ,ËI‹eS¼nžn#).²g¶¥)û"$"ÇÇKžh‚sš"ƒyÁðkKz1àJ£ éÉ.·£¾UÕúI¯²æž¢àH¾¨CÓGõ&ÔÂßÒbt03ÀYª¿x øõrD°ÝÛéµ{@ ÕuçOQ¦²L™ZÆiF­ã•?-Ž ¶²Ay¼`".‘SV)Ùq‚Qèý2U@öE’:‡ª8 °P¼Ç¨AˆJÜšúž@½ Ói5y#‘ð" ÂaÖ˜ž{RÍu*†Ï ’€ú†tV oÕ=:T·Z(V&]$5·}Áxfr¸‹-#–…wù«ªpYÌúnd<Ë<épËL#í̘êÕK°óð"gÞÞ7^è1€Z›³3Ö[n*æÓêß5­B¼zp}9I]HœuB¬ǧ*Gë<I¿{éd¤Ò!‡&uØ`Mí ’)½°t½|Œ’Î#t÷eÚzÃìyAÑ4òƒÑ*Ã,]/©)m Œ‘mµf·‰ö¹Ô¡÷^K;ß{ÇJ)(š/U5Ø÷¥Nâ˜ïfð¹,Þì þ‹ŠxðÎÇ»J†§°„=]xá™ §øSà5·{Au„ˆ–-ëÏé=²‡Pˆ²d]ü‰")” ¾­Ý3—¢—Œ7.¦©“¦œ¾£ãDÃ!–Â2BÌ&Ú虋™ÃƒM0$1»hˆKÝ~øPãʺ¹÷y=¥ó…xš^¶þ|z“ÏR*˜¢êVõÑt¨ìSÓÆ–Õ­7C çšIogÞ€†1›Yp½¹$ EÌ ;£²*¾) ¿wó¶‹Q@™D÷±¬·`‹È´'agæÀÞe™¹f6M¾ÂPÛ¸÷:Ÿ(“ýݪ²eê2JBhøÒ¾¦ö9,S*p‘MrFKàžÃêH#xÈǃyÏFßó%´É,x}MD‚®Áð¦YKÆÂ•µÊ4ë@ïaí{<ç­“`YÞº*ô¦³â©­–±)ÀšË&Ô¾ä*X¼™T'4HŠ‹¥hª¾`í!Wq•4˜l¢t¬~n¥ ê ôàÎ- ´CÞ”;MviD#aq*?-LyHõVÇ̃î.Ôñùl{Å{û€¨“‹Dˆ;„Õ{<2EëÄlQó©ÈC~|~ã/bfJ¼a¥Wµ==~éßñÍRWl'Iýlø¹6¦—ÍÉÔºÇÒï=íÕ¹¦;›uwî¡7H·g&Úóž4zÜËyIOò&]0Ý1¡½;¯Ã!‹Ú€D¹©å–›+a®ˆØºhÉÝnX‡³'=,˜“îZî‚ £Cú(“iZœÕ¸K2ªÅT*FgNÌÃå|&H2‘ê.¯zœ¬8 ÊæÞLêQ"¿öºÐ¬xão$Ò—Fɑӣ’D½8rÑâÖyá.๣y—¦¢Í³½î ƒädLŸ7Ó˺S•œe#*/|žéñCôèõÆ~oñÑm®¦÷ ¥bë@ú«!àZÏêƒ ªAF€\°×½ð3UTç¶Ù2æjƒ°îI!Bu4”åh_ ˜KësÇZ  W­ÞÈ}ðêF!'Ûlú%Fç<@™GÐjÞ5TÆîkˆjUÙש®{Èe»CƧæÝüœd-Ú‘4.b°œxßyv%OÖ 3&EÓšF1Wm„p3×%?ßÃJ*Í7…¸ˆ(˜hO«¼“ˆƒ‡ó ’$ãp¬"rjs94í{à %‚¥AÕR¯2ôñÆÂ®¯ù†Ž· ]ŒaŠN°,¼k&]|Š´Ç(ÞhD=š>«f/\Òµ5 •nuåàè!·0]‰ú!uºžtê¤ÕSaÁ§Ðù„dšâ¥çF‹À½ •J=©r–ÚXo ,*Σ\h…²J¦+™‡lŠò^Ü>~ªGk—Ã= ;ý®]]5}‡Ñ_wǽ(¶žµ=ÛM}ׄޡ;{†IB¤ú^Ú½ÝeB6ÕÞ§vs“š‘ ÙùŠÜ[Y©æŽ`êÌóÍP¬½Á|ë÷nœ8Ÿ¢Ñ.”[ƾx(±é¨1~¾t[O:žÑö«@¤•Ç;gï½°2qAKQ.gn°)™>Q†·›¥'j#Ðlf1ÎÑÁÓ“Ù˜'ì^’P±“ôæ@òMkBIô.íMÅTêQZt‡pø>P’Ÿ >È€Fsöˆœ:†ÝU£Ÿø>"…® ü\ûnS› ¶‘¢XŽ˜²âPèZéñbízfyèz±ëâte4ƒ5]Ȥ6ä™ïÒŽS¾´Ø†.0ˆº«”9å|ž¼ëiݯq×yPBl:çm0„­ÚÀùzÆ "iCJx>ÇeT/Èõ4 Áb’X^á•'ejQ“³¢z+b.®è«¤Å —ç!Õ½ˆœ r#Šd›ûÏ-¯„};'ko;r3>ϧPàÊ IÔE¯íaö?J'²„!õn@Uó¹ ¿ZBˆ©>->|)¦E3|U‚u/pÏ$Ÿ¿DH/™'%»ðXøAøD‚¾ËŽÒNVÖÒ¥z&¡Ã¶©7ãy^몈‡‚<2 eÉ„ÚíòTA¢vÞ¦ôÎóD] –¶y± 4+xI³‹­ªS¨OãR«a,Éw°v³_XyÆåñgO´¥ ¾öŒ7A|Å»@æ„Y: Œ’•-}o¤ËÀ¤VR‡)£ªCëÞ ;R³3½{þ–Çø®dg,çqëÂ(W­ ¹'ÇÉld#ßC«aWZ<’}Ï„½hŸ2Qžõ ¸âªW¥7³Xa² BƒˆHà:sÀ¨™eبŽ›±md¨l;†œÁI*Õ\Ä”®oÃM0<\š¹*wè23Êx Åýè™õkï k{ŒtÒo±Û(·ì‡´Ác‰ zØ lÖ)s¨J'×î/‹iÇr²V»pW…ocµzžô¼ L.qeIˆ-O“ö^Iû“gývéyK»O™4È”ÝÖþ¸xÖi9|y’]¯_ÅšpŠA]ʽò†n;ع3íKê{ÙÛ\żˆ­ïÕÔy¬à(è°X(eÒ‰u4Ý»žÁ2Í^ 2ò#LÍ™Á0(”G5oY'RP¡0Eú¸ý%ç` DªŠ0k"¥àªÙ¸w¨ÜÜìÑuUÑC69Šûl ïs•üܤ‚úÞþˆVqa8Ò4À>tçÐ¥&46÷BÒ M–W ú„œÜŸ&e¨¿é ¼ŠçÏ00¢Á³¨ÔãœvÔÛ®‚‹fÖ2—:!°Pg\q7/{->o« ¬—Mñf³e–îaÌUSÏÖó‰6w|˜jñ㹨*>Óvì QŸÄÈÔ )¶»1K~m kâýl4H8 îàjeÏ·âYõp\ «G7Ø´cdÚ ™‚qã;3“å!9k` ‹æbÅÇt\r´žRˆ“Ö?Q Qåâ*'®÷šó¶d­ ã⯦ ®èÇE®®Çïæ±¿KÎŒ&€âwë6VÙÊ®*ŠÏAˆ©°«xŠLq¸kSÞ³•’âõv€ç€1³múB*Ãqž:=!Òð/‡yøÒJ!¡fmG6HýREʧ›Ú”កNc§›F=£ØGb®WØâ*æ«/Ó™Õ0iŽÄW B"T‹1*e¸ôu„9Ñ‚=C•Ö‹b3[tM¨Ñ1:•ª×¶N x$ªv èJàgᮈiZ̓¨Y/˜G-ÌɯåúÐr.#&$Nß jÒ¼ißhò,¹X0ƒ)ººèyíYG"Å*eÄÐ$‹»çXþ"Ãpƹyav\¼Í‹®Ùº´Ts.[n{2Rϼæ>©Õ§ÑoVÂÊnêIÕHÔ-*²ö½”4¡°»‘R—~±/8çæµµ#çºn©Ð PYn8Ô#¿·¨çþÚZçT6qS¼dU\(±q¶Ëuü¹‚Å¢­Ñž_>/m j¨%B”æ'ÎýP¢O=ð9x¨¼\eyC|¬<¡5Ð7{ÖØ1Aú.<ÊN5u°Rký|çX#ç5lå Ç#ª#C Øç¹¨‰—5É‘£u^Hè7FMdYÍ­âž Š"¾tJŸ!«!êKè—óÂf#/“ùØ<îiDcÓ2o JbáØ.ôúl ü¹T6¶nL‰Û« Îh“JWíÓÒØ çOqÂÙ9Dgd0NÑ9¯öMvœ)vn÷Õi`Dk/7å;JÑ[É÷ÀÄŽÇfWæ „ø!fX.¨z²…a…˜êÒé {¿sÆ <àÈ‘Mƒ£a‹$%˜–óͬ—¯Ñ0ÊÖ|0fÎ`‚éYxž™ mµÈ ºÀkV­XKK—º÷.º…16jÜxæF!Q`&ÏÇn+“Ÿñ¥(ù‹ƒ3™.Z[’N¢-TŠmì <<¤fqX~“¦E%þXJ\D^:Y%Ì á‚Úëô\1@4ïÍi˜#;=îAmã@04p$Å<¿ejÕ4qÀG›ïå½gÄã{ Ø’+ô"Ê™Iuð9p¹›<ƒ¡äÍ}­²§un†ø"¨™†X´·‰î¼ Ú†-9†œ¨‹Š²´öŒÏ­Ÿ92¢Ø‡©u0Ò[TÐá^Ìõ1gë‹+z㉀Ô÷ô*Lnîq&ô"” .¢îRè¼=„nÌJ=SÜ¥Ãåâ°IÄë|ëÌé3˜ŠSRï\ß3ŸÇî½¶NŒÁZÙ´œyHݬ+©,è’’š.èÔpl̳HÕÇSˆ2kéy̲ƒpG±0jÔ]'w­¬9!OÃÞSOcKK:z™³ŽÉo9†6ºwÞ)w7 õ½| Í°}OßC«õ¡px?™Ïpmƒ(P¸ ù»-|®—ÅòÂðºs;ŒŸLÓvìSTï´–²Å&ª»xêrd#®ç¯tÈëmÆ:*‚¨êÔÚ^®Ûxof‡Q­Þh×ekî>#Áz+wÅ;^å“Á^û{&R¯óåΔpµê#|^2$•oÐê±xƘ‚èI•Íš”4Tºp1½ñ*\܈i¾Í‰jlC$–WÀóÞæÓ'úâÊÚ^SŽxŠVúíãÚ7?wÈFßMáðÕ#à¢zK Žéwà=:Tàçke”…;–Œ…H.DMçu'šv«LÔë/2†üàýÕh¶±“Â,…ïðõ^ƒ_lë!Ö:¬”Ys÷‘±@¯kLjmŠw=΢IÅxñdfëF‰ü¥;öNºt’¦§‘‘Ñëѵ*Ï×f‚åF¸ƒ:HŠèðÌ|ά5d1A2+ì”@[ë½8¬éÜš:®{[h¥çíû &§òÍL¹Â±zÛk‘RÉ=§ _;ÑÒ÷UÌ…¼œIøRóžsì>­äÐçÏ•ƒ÷±m(ŽŽJ÷ f Ÿ&6o–RY‰,)%-Ñ«y"žÚOYŸÈ=uÁy†Ä jvèoƒûœh /ƒQ¥‘+ËNZŠ—ùž2³.8+?ƒUH~ªòŠf(VA” ŸÃçb(š›é9Ÿ­g+@õù“X ƒv¸g47sÑïmÏcg57pk›åE…z”ðŒzÞ¡ªŸ$¼†~Îô"‚OXo7xß\y6IÐ@ôC½+Qþ!Ú¦GÞ~N>¹ý"Å^¼ähè8³®hïÚN¥óÒòˆõáÙrElÓ.ö$dã]YdßÔ1Õ‚3\ÜÛóÕ®}ÞÄãZþžû輦‹Í .OÑÒ’yy þì¶[Øñ"o Õ…šÔ<0ÀKü9K‰'w1j$eõÓt.”~˾Ï ¡tŠDË£¹Ÿ½õG>øÖFEAš9Ð Ü´K²³y¢9_}6ÑϽ/êì4YUæ½Gó<è)`Í(ŸØ»L¬2 ô¾E-\œ\7™„†Ñ×ýf@ ¹5Ý Й0¯YéeÁsô‡E“”^ÉÔ¡ËgàÊÙÌ‹ üApÛ¬‘ëd*äÅjˆZ&bŸÆ£ªÊyïà-Ð &:²tƒi9öêÍ+9È>%*tó–À÷–ÓÙåIЦcëÕýÕ¦ ž·âK9Zóƒݱ¤^Ý= 7i4$o±„ :GPiÑQ]TiH¨vÃiër¦ÁÌA†´ ÂÃÙ0GR-\£ë0³á4FåIõ”aq9K_ãç·äãybö@Ë—ºN]_ûã‡ÝÜ>“¼7$üè:Ÿ¦>` ¸:¾½Ü]²hÀòÒôÁ&“}]¼^‡6îð®òÈêR%iß”/¹¸y‡Èé5ò$\’ˆFp¹"UYrpñŒ×ëÃêX®ó÷†ëêܼy^MûµÁŽ•íäAÞÒ…¾iuçvÃF69® g^áÄa° “æ°ÎÙ‚Ï3q/YK _K­Bì1`6Ĉë{0Œç¾V3 /Ø9§0Ôç{Ï`ŸËç¥Añ©™x6±oYT|WO"(éÚŽOÁ'zŠ9!p¤‚Ë}/›oNšƒ™_b‹¸+k(…¢Çæ»&[”M!&ŠÂbøLw÷  Äc’;;ìòÁAbsS·ÑÊ&1 -ØËõÞ–#*=–È^̶çzRîÏ:5‘J¯Näñ ˆÂH§9Ï«à7SDp›Û™²”çDIY‘t«ðÆd­õŽ„tZù¹‘ à1ºgí@êFêÉ öÚˆ‰tÜ¥jAAƒø‚¢¨Œc¶#šyç›ljâ¨P´ë·¶¯B^öE„r9Û_íA8_¿c¼KL¤ÑÝ8Z(‹¤]øžaRÈ»÷F‰SÊŸHÚµ;óòJ5„U´ŒïsŸ)I‘ã ‹ØÏ¡|§U±Ì$ÞÔå•%'9¼È:1ÝAŒ·®ÐÛx2ÑBä/,îå€ôÌ-{ó)L¾Ìˆ{žš9/ØÆÏu)5É—Ä3bŒ6—‘}Ú͂ř!I¦¨´ÂÜ€÷`uNaP`žóÓiîñ˜0P˜‹³^°ç;ÒÈ¢}{è®4YëœàIT÷nɇ2 bŠîlxƒF¡á¸Wîl¤0_z§RTXÌUß4Ëö¬ÀApä#’Ö:ˆP:à@í ›ÆM|“:sºn€o[º¨Ü_ ¤À|¶ÿ\Cÿ=1]•í¹rЗ=þîiF ⎘ú ¢!á>zb•|Â;d‡Gaó2ìrx#á¤ÇÇcÆn PÔ"šÊJë¢C¬FMßI¿jA c«*y*TÐwØnK=GÍ2ž¹ QíW—êþViè™»8Ö5Ž·>Ý7°³þ<¤ ,ß_Ž) …ÅVÄQäåöÎ`ë+Ÿ§}Ïœ…«ÔÒÛ,[Kë]Èñ•òd5 ?W|›&0Ç´€€‡(™‘Uq§üˆg6&« „k´¸zÚâA27=€që4oÐ xôrÌÝ–µÖ›²'v‡pÿÜ;(§a¥¯šÙË–,è}Šzˆlqg·ÍÖ…¢`ö úeÄŘõ»8Ï5žE£{â=CÕ¼×^duä°¨TðœŒPe ¢|ÈØóâºI„†xl9£ÊRËY£×|NÂÒ<à9^íVïZÜlð.1$Õ›…¢wŒ¤)×/¬¸xe =^çUÖ¶r¼SxüøPýºTÍÉ×☠…tÃM.¶#œ”½¢õsTÈÆn(s@™È&Òe/ì½¢bgZ€ó Xt¨K­ ~™^ ›C2´@mëMÊ¥¶ –Å–6!rªÐ­F”ä„’»ÂïÊBà€€Í9ïÌžqùÏãT‹#J8Q‰|úv‘(Ó´¦Ýq‹|d›3u;Þ³•zx¬1/º9øXb>*Õ @ET=bMi+Bòçå×p ô“a<#÷˜ŠUÔ£¬7Ô¦iåkˆóbÌ´R€zcöØj…k¿ÁÃ%.Ì;Ûá•ò·e)­É¾0MXKU" UTaFXb³ÃóbÄËlnµ]ãäêÆX$À©d¯Ÿ­QF…biªÆŽt3ÞmÞ38÷go¤&}Jg¨_uŽ¿w\Ñ5¯ P[D|®¦ÑwzY/%mñ~·ºà<Ûâpa©æ.së+æ²1L©7–Ô©SðtN’Eò åF³.8{áå{ý„Ù%ÍY¯œïe[S—]‘P¯ á{U¶Ø¼ V7¸ÌSïµõThdÄ’s¡ó $rzâµÄDQøÔÑ 1JS²ÌÊZ¿·¯Ø£ÝÓá!Ô21;ÒŽ N2Hš[ÐI?½ Q·HH‘¾XcÚ‘M6«|ÅÜ=ÞÏ„é)b^Њ<–iB1‹¢ÄØJŽ6ŽŠÛw(—Ä+oߣ&&J/GñyÛªéHazïæÈAGËŸMBñÜìK"@¶Âvi‰ÃѲ‰s›zéàι34Å{*5f‡ãÏ€ ß#º—­èH:lÓ¼ Ì@w·ø¢õõ¹±Âƒ¢«¢4”8fç}É͸vÎQ·n4õŠm+p¹cÕ¦!²àÊýf=ÃQ*s:éy…Í'œ¬ˆÁL» úê¾÷^̰ãt+›£R²rPL/^h©°Œ³Žö>ñŠM 8rÜž±.ÓØöÆËÌAø´LÁˆEjöå#ÓN_¿kÞg–Âþ^?ÜuÕÙ¶ÍÍ3Î{/Æ ç1™˜v cïñ ©_Q4ÚÁ2 ²r;Vb亮¸J&«ÝƒŠsm©UO”`Ïùu¸êÓÕƒ}ÐÌd+jxôN/Ž©ÌHW„?‘+K\Õ+oàhS/!}Êä@C¨¦O`§©ã‰%çë$hgÖžGÔ%ã;ç4݉Åä€h¼,µ¬2ùô‘öšXŽÐ+¯Áâ4k™ÐµÝ‹¥ÐW@…`ggÜñ'”Ç`2­cq»ºŸp<Ùà#j”Ñx+‹¿zñ¥—qu»U¨"=«—%óNÞîFU,w¢–Í-ëf2NOÆ‹¢±e1NXÄ}b  ·ïÕ’RÚªxŒÕ0‘i÷CÖƒ4r|¸1µ'q·´Þ>Þ”\tx¡K%w¥ç†ì;>\Ù„k ®XGüùŽø\RƒÜ;Ôå=ßT£eÐHÁo ݺïÀƒ±¯ñ­°Ü«hˑݪ¥T¦b×Îs‘¦¶wâËû^à¤/¾ ]”ç—+M±rz,ó&³£àT_®f‹` œ¼ÀF¶€Çk/5ÇArŸ„Ch˜¾xãê›1<®ÑIV)àe¸Ž‹ä†:ý²o8à÷9€*Ún–2°qʰôÍÆñ¼½ Ñ‘ ÂàñtBŸÒq‚—Τ80†loŒÝï1£–zhã³a‘£‡`ØÙÕ® Œ’åžÛþKxYyã‚T±b2(Kš*àýÂ0+÷W›x±ýd=q¾{i(€Ò{ ,)yCƒk´O´¦Î^Ï©j¦àšÕ¼jh†ˆÀC¤ÅÓš1£œµÍ°<(÷t7Á€byª|WÊ×|Ù¯Áó5½B*S|ÁXøŒ9ذ’m39QkK îNæªhM4ž×óŒ'Õ+)±Wð@cYá.×}ŒÓÈÚéÚðy¹OíÕ Q!:X:CÉ‹yýÀcc+îô=±ÙHc>‚Åɧvd­YzCSAÓ"•ðÌÞàܹºìJ5ùëŽ±Öæùá#|Â>)Z ¸R¿âbষ®êŠZ´ûð¸tav§¾&Ä5B¿Õ-ʺ¡Ê©zˆlhvHï+›Ýáˆwï‘ÄòVàl™(uE?€¨§¦ž—å#C\·6dµv/Å2µ‡”BÆ¥±³‘ƒ³Å½G7(å;Ј ¼,Ö¿ð 4F*ü,Xf¿¯BA[ͱ™÷ Yåø%°ùb׺ ›߃Duhµy SXÙÝ Ã€™éתè[6SY r™>ãïR˜oV=-^>6¡#ºÄ÷ÞkE¡³Cß1gO| ÇedŸ6_S`ŸW¼Àó%Á7\ªPH%0Heï: 3Þy„hó~n£J×µOˆ|\Vj, íÕ€®t•-#èËeçW÷NÒ¬™óé -öÃÏ6ô¹0§¬2J©}/ÈÄjæ-K­.AÄèÀS{ ¿ØÑ­‘´Ã÷ f|£ú±ËÓÎ\Z¤môu6g‰õÚm›ušg× nÄÃDh~Ø8fI°|~hêùb©èdfvÎgO‘†–Ç&ó%t° ^$¿!ÈÔ£+¯TÙA²§×†û49Òž"Û‹Í|Ûþ4 ‹áð 4ÕËr—je¨8S×¹![ƾ ½å&Ñ´‡®M¤¨qGb!¼5騰r5Ѝ®<#p9Þ•¢¢g'aÖÖ·n5JY‰¯Qq`m žf‘m8ƒÕ`;59DØæFs‰áŽî‹Ä7Æc‰K$ÞuOüùÚó+ä,*…ÕÃE÷7¡OqÈ©\fšøÝj[·2W¼zäWÍ à¾ ä¯4•T1Qy7AŽ ‹wŽy;œôéÉËåÕÍG°“ôçf\w\!5b (A0 ú!+UG×›íQU6§·‹/¦nß.’¤žqîœ3= Ï]Ão|lÜi¡1ø˜ÍG'ýC„"Ù$-_¡yßCÏñ#f²ª h(ðœ,²ZIöΞXÑÅ.ªÛ¢§Ï=ÐXœÁ›Y[KçÕˆdÃéahc°Â I‰ò´ZµVQ߀÷”  â&En‡´Ú£GMÈÝ/pÙ߆ӮŠiÚ!¨¸?ö@Mi¶ÁgNOgŽMì½{Á‹L¨CÙˆÄb‚[Ïqõ‘›®Ì {Á¼ã˜ýâhbŽ÷=o pò9W[…콫”`‡ÕW¹‰ *TÙ:³gJ¥UñöM0qšÍÃy@pU¯öÙZ€¤>…ÆRâGv£¾¤/’Jø*o&øúF!·©€¹ƒ0ÍŠ¤ õ© ›œÀ€‰ô){¯K¥±r°­±ªæ1­ŒÎY"F>A‹œ×vê=ÄZ~ï—ôÉd³Â”¿ë–†àH*ûlô¹¸–ëu„È'.ËþÑy…Ñß« \r8ï+d~n2°ü° £2ÕÈ^%´xÖ>ðEgž¨§æ•ÉtïÉÑ%©%C½6ô”`ªWo_]†§H“$²êúX*<#ꢪƒ——Â=¦‘÷ìÉ®$ÈäRÍ « Ñ''Þì©v‹e/ózÞ9!Úªª˜?×@)ôI½Ç8ºרSO¨\.ËÛÆÐ*šy­Ú8ïÁãlöj»ÍC¹0 ±A\6¤l·x¼Êäo€K´fêê•h¿žÕ({СӢôòá£Ú÷òò¹æàÝ f·Rda«”ØÉ*(¥/RBä‚䞤DC¨= |H©©oàØ ‡™¹›ôÙV_²Š‹êë -@P>…ËäÊp/ˆ†ð÷€•‘ˆ0%–Þ©^Ž7¨wÇ ‘+m?ØšÙ$\ì›Ñ’[ÎÕÄÆëxä›2^a]8¯š!üF¿‘bN axÑ û^u\«U3Zz&'#T/'áC¡gbCñùyF<~ŒwLõ^JŸóc‘Wh}ë ªÑ‡^H^ù„]äÀSƒ®uèÕÁ%ÒÄñ¤.ó0®z39‰Äêmug[ZùÛÇÙi#ÂýÞtåns j!Ì‚VÏNC 4g8B…•RߥÉ5Ì« }dUx)Ó%¬ú`£ Xl€xÃit,¼@Pmqr­ÍV²Ñí„(>ënÃ^ñ(œÄõ€\hI蓇CïAµ¿°ƒ8b¿Œy¤WAÈýV[4vTé4Ô7ö˜J›®Bx,&‰íÙ[²ïVñ¹ÂV4: ÃÔÅåU4È«œ‘ÛŽ¨Ó(âRãj´s@T” Y=Ñr-LÃyÇÜ=ÛÊâE¼Z2ZN õÜCO$¥QEƒÝÀnŸ|ºxΘi©N-ëOƒq' òå5Tè[ì”,Œ·Hœ˜òæ°Å VÜñJxr±`œá ýb°€[Y*ÛÆ§Ž¤ÒËDÑçõ&"©àÎô EžûP=»'»ªù«K’Ï›çžÍ6rpËÂh"O´^aІлY–%G>ÇO«Ã^¼ŠW(](±‰5–ŒÜÅe‰Ù/OýÆâ £í!¯ œ ÐeŠ×å_ÍÂðšòÔBRö¡‘ÆšÀ…Jym?ÄôIâ'CnÔ¢ŠvpÝí B€pºRÁ¹ îá=qvMoyCcwM-~¤ÙŒ• ²Å®;œèk|ƒý°7•a}ØÆ½e´Å0òm&j_h ¸ä «°“òpÍá“,H'ÃQ¡¨X:ÔÇ%mž•¥UÙǘ¼ï=³‹Å+¤k~2 y£tKöj„È¥Nº¢øåCªZö~¥ž<©ëLeãV¯*:ÊB^—¾²µu¥Ðr±Ú¥íÓdõÑ2;7ª3òÛ‚Ëñ(Übܸ—A{a”Ä5¼£{T÷ø˜Œ5uCšpÓÜ’u¤rÙùX!Oùü”ªe-rNm/#gKꉧø{ÝË4 GÏR@GŒ2?QÅ)‹³¼IìkPya/^½t¢ÚÊ=¬÷†6ÓXSrírHíP}{qŠkŽå%\>ã71¯`Æà½\Ü{U­}òªžãƒ<²hH8ÇðdI™ËGõˆ uO¥~Ú÷ ïž½Uon*èG˜ðJÛj°6|®K Áç@&çIóžõÕ–‡O½äž­¼¹7Ï´3Ï…)\ÅÄ^­ÁsjBê{Œ½$Ï%÷È'¯»GçUËj޳•ΩR¿‘Eñèà ëh} É3«l|÷¢B»é¸5üLQލz5Ʊ|6‹§Ÿï Ußžˆ¹ZBiFôž›‡‰üÞeq÷Ì uP6¡R’Í`¶‡g2ìI6À6jÂvÈ3p—)r)K¿üÀ â¸l^óP”¡u oVÌ~PSi(^ê@ÐPÉ Õ!%Õp ÌA\Ü=¯Fu`³J¦*+€GiL¨y_ŽÙ«>näâg6ùö°‹.ëÑà²v@¬’îÐäÁqÛÔ–>©6áË®ñᨭ|G¯±»ëz`‘WÞHXCŽK´©-:åú¾hRR¼›¥ ˜7Py°ŠÏ5´o¥l•ËÜËÌñè^Ú\H)\º!%‘áuÞ Ä^+A,ü«]´l" V- âœ?yšš#h:Ùo߃­„©O‘xçˆIrÜ+Eh´ç¾”«i{²üA9HêF»dßš¼!kK³ãºyóž ±â CtR4(dGà½Î€¤¨85J!¶ÃÊn-ùAñÃ.û‰X‹Ûop”vS™CïA¾dF£¢5˜¤ãÙd:ów‚Ï;TS™ØN§@42—ÄÂq246ÔÒ~ä[€'ÔB|icjúvVn[xìí­° ›…O´y™Êjì•7hÏüv (—ƒÀm¬§'üŒÕEˆ,Ôº0‹ ™w_mÎ;žBôG1ok«ÙÓM£Òô…ê$lm:À@lÌpg§N×CtÞ3ܤ8¦Ð!`Sœ„t÷«^L›P/º«•ç@³Ï9«î=\˵ƒ-ˆX%Ú*×.z&Š­šóøðxÉ£ë‘SîÛÌVÚ!ê Ê•4'¡”×e4·Â7EÆ¥}![õφq£Ym>r§j¹K@q¨þ·ÅÖi5Vï…¾}ή ‰¾õRKG¶gô|Etè¼vž‘N +™½¥ÊS%¹NH„^쬇žëà A±-{÷HéXaJçÅèÚíS¶ lꓵ#…§z“ôxÂ]<_ËÎ¥·WÙ†zyu%™Bè‚¢ò ˜S¯IV×£Áqë–J,tÏ5³’K1˜¼~ñÚ.¡ÓTé ¿J“;BN8ÀÜÇ"ÍÂUjöŒpî=Óº âÖ©¸áÚ=£áé*MH‚¶0R8 ýk  Û”çå¶g&PáUS¾Š ’±&Á÷TìJ-<+ 1îªÊŸ¹)Sø68Ý<í›GéØÂQVש½=ì¡ïî@?#È¥R‚dÈj·&W|™ôˆvÆ#—§<öK1åõd]”©‹ mU6*du’EÏY7Ÿß#ܵ/qòò;l$ á!Ľ‘¹{Ïhç Žlˆ X^ý\ã£Ky䢛ûì XÓFí ¡­îY”ˆ|õÞšÂPAÞ>.=é÷z.6ÊîPß`˜?¨‰·æÂNU)ÓÛµfü^Ž+ 9L¶´&‡¾£çÌm»–­í>^ŽEÆÃÁF†è£kÏÃŹÒo³1Ø ²ËqÚJô„RŒßùÚ:¨ž¶i à›Ô`0âÇÞä@ Ÿ C>Ü´ÓätW†è3ð2^!Ë=}²¯kh¶GƒêY K«à¼ #m ˜gö¶qÙa™ ͘ žÙÚ¬–ŸÈ¤'O±1ô®N?Š EÀiÜx™¯úm!Mëe4‡sãÛ÷bÕA«ž¬úËs!ƒxjà÷Æ®m8^u¥V!•œÊ®tÊhû¨î¼±E:õBê1›=kÒËLÈ} ]äu}zyÏX¶F‡zw ¿êèàB5~$¼O¼ñ¡5X‚ÕQÁvòó4ˆ§vyí‘bôȯå¶oä•ï…øÂ.(xÙIW½œ0ß5è6ÖF²TÜ}µŒÜI[ábnÞÆiò| Yz:® k‚Þ1N*ˆxv{¿«Ç㲇òf{¸Â>(¸5ÌEP­„:¨›D˜3Ps©A½«‘íòn ZÌ\¡…ï̲EB©ÔÝ{!CfÛzMa}á)çÆ“nï ¥Ê+E›Z–dÕ88iM3µ+è¨i—×Î={rF4)ýpPÐÑHPü‚µ}!Ï(t;ðÞ¶9Íó}ËÂÙAå“Ô×—uý¶w%òÚêqœ”(®D Ë15ÈèÕM† ?r¸‡CâSyn(Ûq»r·(X•Œ+Á$\¶yŠ-ÅÌ\L-bhß܆ò›iR¡²2»$›b,3w"®åâ³ÙáW¢ùjlKH Ô£xˆ\bç-˜!?DõAbà’}l—w‹ï]‹=Ø5ÍÏ–¡Ÿ«î€"OÍÄ[y/PªË×qG;{!”ÊîœØøœe·\ÃLú ¬Ò÷Y(2î>†}×ëLù<òj`¾šn ëõàä¾aŽyÈk ¸„€¶yï„äè‹öWgðlÉÇ%¬¸:î=á÷ðÙƒã>Çò‡‡–QmÀuØâx¼“D$€=–°r‰ ÆuEMíHÇýŒdt-L+õ=ŽAß+'žj%µµfÉ+9žä"­36—lܰyk>†ö‚“M]…%­/F«½ûxíèÇøx§+ÚÍ Æ«x½s¼):Ç ºqZ¨ê”Mà礜B9‹ý*/ÉMð=¯É&ÕqbYVE캠èö^|¢j©šå¶MÔ÷Jx|Çz¶¥M¶_ÉÛ†¹_#efŠZÛÃlïèD²hK¿ìNNUE}pTZaAS'í7ÂÒäo®U6ÆÄ‹Ë,N4òŸ?àU´1Çqè¾´¦Ó»cDÁr9ç¢ôëñ¦2 (e¡nxì¥&p±6¿›†¾3BƒÙM8à(3ª@§öhÕ…;ä|B n½¡ÖgI¸I‹æaÅòl´zGÎq,ïFa“ „ÚQœ ¸=gÅhU¡E)zОú¨D$Z"³ß)žK‡j™NÄÃ;^ eÐgÞ»™i¤ùҹ߻g=µJZb,  Êéé#ºò2†ÞLÌA¾›³Ôç‘jŠùÞ%Ó¥ÏÔø¢¢DÇ/ÕòL0úlB!s/e‹ŒQØEGp,ß©—Á¼ç&€½.eF÷¨uÒs¨— =d¼À/q7Çú™ƒ„ÁkA(s[{Ëï|í±Ÿ[?”¶GU+‘µÓ'‹÷Œ6‚Þ;ý«m¬Rß2j$(^îÜj¯ªh5Èà¥è¼9¹«B~ï*ûM5T„'–ƒYMã&›)…ƒ¸v‚û(WVCv »·xyÁ$ʶZ0»<ªŠ §Ð^¨Zã{%qT²x ]8çcq¥ÑœÛÛ7ÊðF/œ3Ü®×Ww¸a£sg±…hù 9ä\"Ž\¹™¢ã¡æ£ëT*èÞZ»K^ÍK²õq¾Æž'ÈìÇE€;+^”4;¡b “w×q`Ã4» h1tœ9'Z•!ø²ÊD.žPqp+bâÄ<‹M÷' ž­îÐïÅ” ?M°ÑFôôÈdLXf}ìTRðlCíéJçö±)¯f±mùS}ÏaJŒêål)»ÕªòϡΫÜÁfCß4Üç Λî­'w Λ»ºÛ>$ ©€â6ÓâÀãHËåÌãvÔuú¸ûÑqPÕõ£â5ÖÝwoÒf™1å5ì+eªÉaI>G‰ ä ÚòM0ðèA†-;‘nŸR¼yáÓÀñz·Ùß3V÷‡)»ð<ïìQCX_hUœäbÐûÉyx5& j1”‡+*š-vtgì}P3n “˜1k“u9kW6ZžÏ_¿gHà(3™í½;lÏû%9ÌZkYdf?µŒÓýÙ6ìsým„Ê¢ï%sR›onŸ¸˜dÑk2 ð÷šÔM¦á`Š57£¿qÚ´‘z+°mÂÒŠ2¹¹©l¤ ¢`b:=/t©à]©¶2‚›‹Âjòˆ˜•S†ç•GïºwLc¬Åí<§ë$;,‡—\¬ÇÙ‘üÌW ŸGÊÛÇ=&†‚± +kJ`Ò7Ið! *÷ËÒêlf.pËK‰&rQ>ÔIÞ‘U°° d½+Ø{÷¦øÕcš“- âd'ÑkÓ‡ŒIæŽÜN££]̄Šr_úk£Ù@‰Âp‹~¶±ïIºJR.G.Ÿ±_y ³ ,áK¿ú³qˆˆ({ôHnÌaû¹Â:öÛ ™°ŠÚ‰6¶dµ!ÀëÆzc´GdíÔñVkPJ›çõAE—æ‰à†²41oª-ТÕa0Þ „ž¹³âŠÖ¨ {{)¨ÅyçÁ6 LKXçÏ3¸Ú'|5\úƒ«0ãAî§€$“ÁrÌB^s!-èj¦Ã“³ˆ€Ò{„ùÝ‘>=ED"¯Ã“–š«>%s ·÷Ì´J<èÁ?dðWᯫšM—;"4g¢ý1NrÓs zW÷(1Ë÷ÙF¢O>?anæËrÏqÛ–;§®ÅŽ!ÍTÓ0¿µC?lxyŽ"h0@Çš)YÏE·*}«•¹í½]òÝ¢ÜÒ‘CõfëÚäÛíaüêæÒýB_j‰9ŠHk‰5½Ð|bé˼ÊZðR¦ÑNÏá’Ú‡t^?ê1}§Ý‡z2F§(Æ¥!O†ˆ¢=…ßFP¬k•àä3ßzæ G¾Ã‘~bGÄ ¯£‘Øð½1Ècɶƒ!kqàîˆ §¤¹¢JJ÷új*° šŽDQÓ‘º–èð9Źdð¥æ­Vâ.?8ê[PÍŒ,BxºŽ¡”7‰@Z¯8Cn*ƒäàîu¶Xbs+Œê¬É;ÆDónÑŒçi”`n¼Y:9y¤Òךðõ 19`{{€¥âL 1ÞÅgãðÏE¸–+Ì #Iäâð*CãâyÖin lê§ÜÊ^h‚õäeU6õKòÍ€¸9`zï)&ÐêÛ&~$`œ^©+WàÅX[âùv ä>qÎÔ¥MŒ°X\YÉ“ñhxoÒXZqxÀ¢hî*â3ÔÉ 1e"Ê@t›¢½ÛäPŨ!ME­ºIOäª`Š“Þ“ ”狪~q¡LP¼"·T3Ow•1²²„ÅÜa`êŽ`ÇMü¸ nMb¯ÞCÆ>X·[G·•«3ײõEêx:×ð†l¯j­]í*hàÈÝs=NËRß9‰{.[H‡hukh/â¯Ö!ýz,÷f|!îñK'R©~•!á‘;ÜËëÒjâþžº¤øJ—Ð%›ûv©½u„¯9ÃD?Kš¹~‚ : /ªà’©^áCéæeHÅaÇj»³Ž½ÙÔëñ"^o»³ãu%,·`ôU‰«Üà¾yOÄÆ'ÍaáŠóªÙ½TçË1‘!,£åœ—Ï„í°·ˆšvb|Â4^jl& Ê=ÓÕY³‚]m›&¿ÂÆêbªsd€Mbƒr; ºùÞ$Ò´{PkÓ 1=ç­LüRRi»ªÃñª¢€%VDZo; ið¿Ç‚²Å6ìom°N—YáÉÍ”—t›—7Cn£iYt«átæÊà6È Ž¬íÅxñÝ«Wc⥿|CxD[<óÊý²ð±E–Fg­ßöÚ’Cê«w þ0†ß³Bº+vR À‰Y´õ#6×¶¦·}‰8’Ãa.TÊ4ì7Æ >ýhMû…â‚2ª—‡ß¤ß6‚ß#&qô²%°{—ó„DÌJ®ã°o^Ü*Ë+2~JÍ¢å7õ2Iè>Ð=¬;7͸î¨Ú§Û.ÖéE½~¯Ð@F'UŸ®ÏÃ`….­ÚàŽnHÉ’Ž>yn&ÃêªB//vý:m“¢½–ãeÓ,s= ŸÂ#»Xfƒy»šÅ^ŒÚûô³u}¶ŽôyÏ=’ýól—€×’¼‘ð,˜‡ÄyuLJZ´¼Q¢Tä>Ä¿íCN˜É•6Ô•pê÷Âñž ½‘–]Ü#òwå¥Ï<¹e‚•,¨É鎅–$mSáÅ]~ñŒdÐBßÀcRç#Oô¦PD–‡‚„ã!^ƒ<¤+óU0{Ïm3Ý^ízfˆ†Gèá3Ù¢â=yÌ€6[,ê/|e&ÒúÂÖ;TßÒ{‹5ÎscìõyS¥ð#9L²¥RJñS½Ö)jM r.@“q£A- ð­FSD·nsÒ¦|nï6û¥2U½8y‚"fÐ<Ïþ|wøî°·tØ›¾{ÜEá¨Î¼Ë½ëe²øZJI;#õ.ÃëB_P©»µì×I+ûl1ž'šÖµ>Í*u[WËÓŠ-¹J±{†j}„¢-.rdWëžä°êhp˜§-1@»„GBÏ4‹½­ë8#2x¸ ›;/!ý© žh±¹;ž’{Ø’š_ö‹3Mca…I |ϸ#Ï‘Q$ÈáÉÅ#׺š¶g[à6å·¶f‰îM ÛÎþ(‘@Ø&Ô,9ò˜†‰ví)OI©¡KƒMÛUÓ@VSõë^ƒ¦w4yí׊¢¯ËzaãA™´f9:To/5›KZ1ÆÞc4•;k‰¦&”¯ÓÞÿ쥘<ásÂŽ÷Š’^²…ª¹v_0섎:Ú(±“³§†3¯Do¨½žÈ|'¹ b ><§ Lcžð‚à’Þ¬U«¸#«ÔÃf>õÑ虾܊”ÔãÜl£9u †7¨±%E¥Ñ·ïæz£0ü¹(H»rÉÕtV²¶‹Gœ?èדÁü:tN§‘ÑÔ¬ÆAM”ÐD†mÀtNtr'‘8ßha[é‚Àé< nQ²Tj±æçéù¹åĈ<^å—-¯sG´vBl=¥·Ã6ÁwÄlB²KO‰ b}¼d¨Ó½[Ìä¶äß 2vw¼m4Bu}žö´·@ ýé×»ƒ>—ãõZÖ¸4â½&yA[ôwÐó£ÒU“uuÜÇù<<Ø\jrVB…†ÓÞ8¤´K ßàÆÝä`?G9ç{ü(³¥_ó­3t?ƒ>WqHD3¯ÚÉÄ,ÑÁ¤-õœIK:9©I÷¢âòή’ÅÔ£¢1Ŭ(qäæLÚR¹pα^>Q¬ƒ9^ Äk‰SÁŽ—m%â*²h­­¤P]w§Q¦àXáÆêk¹ƒ{[¹Nb!=X|ísM˜ìã)¯§Š´yJØ®A÷–.\`gH]’U±‹ñPe¸ôí‘”Û@†Î›;͈Ì!ä«áÃ÷RíñÍ2Ë-bidøÙÒŸí£u…î¦ ]_ âk&‹¼iÁãQ±€²YU¤”§ƒ:b;'yòʦïÂá¼ó$LƒZ*$ lk ~&WFÐë§¼ÀD®gÂȯèpšmxw4Á¯_)úpÛµ§ämÎYùK ìºÉyðhŒZaåî1åÆ3m…Ά`s˜8H½¾ÕÇ¡‰×ªï-"â3Ö”Ô³|DóɺvK¯ÏP®·uh»(Ø0Ð ¿:pÁ@pÞ}±~ÅF¡r‚­+¢}¼¹"- 9½³k¦Šé>ñHpêÞZ’nê]¼¢•V\içÝ£1ë !U%(©X1™ùŠðú‘äÚâHÐ[ê)>ÃÆÙzõ Š(wÜ0ÂººWU8³>½Û{cò¢ wçé¾U}%¨–¢7ø˜åUP8K5²ž/ŠÔ2ôÑ®½¥· |hòü½¬-D|dëJÜÖ'NPŒ­ìœ×«Ï¸” ±`Ψ_cíi½·…–ÊWË>ê«p}©„|¡afIæ¥r¢å…8­v¿™ã7÷´^,zØ£×›ðÊ}èʯââ06{T(“¼±^>qiÛÞå~€Úîòìeg5Á2Ì&W_ZqD0Ž×€Úó4¼W ;wëÒÖÎÛ'§Ì}x/ùñP!m¾÷âÁ{ò< ^s‹<þnŸkryÉ¢»„ÜÖ6X:†À<8.Õcg'ÍÛ5=Ã\¬j1(é¶m½xV'µ7c­•º¡ÞGèIõ¸Fú‚,ËY÷y2T£Ilì{ÏPÓDN#枌*XÉæÝî•=!°­3(©AóÇgu ‹ÚE9œ'ÄY¸ùì=ÎTå'+ó®!A¥q«z51T›Îëu m§Ææ¨ÆÚfoP“mJm½·óVÊ?ƒkQY„ñ$(oV¿ A¾¾‡ÅÄÑã4½+Þ”'Ï‹Ómß {† ÆÎ)óî]yû¡ô‚èÊÊùm­,^IŒC8d‚vzBœRqÏÊÀ£ Êò8ÈÅ?÷Vô;Aó )šå PÍÇR(A) Ê1lÛþ‚5U^‰¡Ýí“àÛ~mV¾Æ]z/»…Ã_ kP)?ˆ›£8Ì ¤í·> Æó‡ ≉”îæ¼õHM÷Û÷ .{I­îêú타¶›HÅ{úrL6Ýq˜ÏáNÄFö,1y­<®/uNx°@tWŸ­†rÅÂÝà­›"ƒ-6d—Ǿޝx+v(ëm²äÈbÅœâHý5[¼é'ZúÜ_*ltU\¿hºGSÃ*áþNZÍhß“S´ê÷ƒeô4œIhi•J [èáBGµJ-ÑŸ›àNÌ‹m¸¿?aÍà¹4´HId$¤¹8–ãöj2¨ÑD½sȘwúX îM?ˆ*DØwq¬²àÏpâ)*‰_KŸÜ#åÒ#è±ËÞÎÊW÷ñÓAø­¡,òÀX à²ÑóõuãuÔƒóÎJid¯Òç9-ƒï9ψ«©E‰æ³2+iÏ5{NvðlFASº—ê¸2픵`Þ3…eRÑÎÞmUyz¤Ökß¡jôàß%—år¶Q~Á!Äi+$Õ){Ëš@Žóu‡Æ[æ7ÖU¸8{L¢DÙ°H¯͵ñeà–Ö×cº Î õx†Àz¨¬’=Æã‰“i¾‘°ÅH¨°w"^\»®fH¯±¦CæÑ0€9õ¿ª®^[º¸h܆€Wo|Û˜ÞËWgÂÐc3Kz£½h? ¡4Ûðö4.Õx‘\m¦©wkùQP8†V«¸¢š·é£²@ž§2ËUÔSÍ \"£ñ>ѽ±ÞIŠ÷¶¢\s¤’CçX#^úÚmßêŠÓJ¾dC3y+÷j•fÜ êž‹¹ãçáÀQö’eax¿p›"ÀCTî~”³Ž½Ï{aŒ1žr‹‰ƒÝâE¤’¾~Çi¾ðÀ3šg‘œ‘"p—»“dõ ?I/Ú×H&êÅ^˜&¬tb:y3§Ÿ-„ø³…èíƒéëIÌG±NYû¨ä¶HÚíµ =WH’Û»JÊ™O“)‚¨¹¼^ÞL¢Â°Sæ›× à¨é]C¡Üôƒq¹2èÍ[Ÿ/&I vŽ­”G]=8‰ƒ#¸í»7ú"«™Dê¹ú5ËŒã²m!e1e¶=™“Áỉ°ÞkZ.Ü»‘ ðôž«ÝÂ8çÝ=«Ù÷À›´•šß3`w³¶WnEÂz ²‰Ïjç4ÉBÉ"F„'ýlŒè%{×=,›íLÜj/d1}ûÔª7–¡4öDlÏ›)z^ Àá.Û9ñØšøéÜ=j3¼Çù\Ü’9Zæ >KxI¶ªíwúWA}Dó¤ö4µÌßáK˜JÄÎVBó¥Î·U`ϵ!»é ¡ØCz‹5ü²»ñ¦º»qI£—<«÷bC<Œ¨ò¡q†?ÜÌz¯°´÷¤k°K!;`ƒO¥mrðesyÞe=d|¤¹ æB“E~…¢œöLØAŒ-Y6tiUï k¦tuOjL–G… °zìÞdJÑk¤·lÇ çt„á[Iv„²}fü-–OAf«è{7H)[zñ2Õ€w$@š_êÁ „®šEÕæ~ýÊqÏÊ9Yäö¡—Ü û;ŽJ:bòh¶Hj“‡ Zµ¹÷ÒâTÈ•i£à½³ÙŠíí—–q85Ä‚×ÅÖŽK¸CPAÜZÜxPdC+=Ä•#%³¼™¥9#V<´‚ð ÚòÒ‘ÇÓ–ÌWÞX÷q$¤«v¾´’*ýÇ$Ë ·[Èq„ªŠOCÎE@‚µO=,8ìå9‡i´Ô4Òz?eñ7W¯ÏìÊ6÷¥ïx¯…á‚_ži{0,Éj˹Š8÷ã¤÷ùä‘Ú»©}îݶá)åj…-,P©DíN‹ï¡#2"^‡¬ÔXG+”q㹑|¶þ\§¿|é;7K9|u‹ž¥Õ|È‚/‹l Ñ<ѽùáÚ‰ÒëR-zÕLæ¹–À†Ss¼œªkáŠ|=ÏßszOŠP Qžø½§/ýTµMìHó :6Åj÷ÍêÛ|rsâ.} ùÆ9©hy†˜C§ÌcUôž±…gbU‹ñ&T%{Œ)¿ÌiÕBö℞bm$qÃæCdt H™9@bMh‡ä×ð«‡?}1}“Œ$5ˆ/ý8véç¬^f‹i¿+h\UÃq´k’Ç)tRü⌖‰gŸéq‹Jw:=°™Ø3”²æ-[pA£}äÖ@ˆwuï™Ë3‹iR=M©Õ*XΠíÝÊ­ÿÛ‹üóïÿo8þã_ÿ™ÿµ$úO2þýÿ5ÖŠ*¨t|ô^½Û2~»Eü®GhS©Ë©šLYwÄ”nL¦yf¼á  0F­$èôÚ ›ƒ-²Ø•‚6»^Ys-2n¨¢^á 1 ê¶bÉ}Ó`D¯}ƒâYí9WÃf¹’Ë{Û&ÂzâWÖd&ýœ•ZaœµÑ¥Qq%DˆR«µÏõÞ Bì+¼™àWšÛ¬ž4J˜Ö ­b­T“ׯÖMÔFÍèá 9E6ŠWê½Y–±ÐâãÊë{³¼X‘¬]ë†ON:3÷!ïø›,.ˆ8ßp€å*px\8~}ï^—¼+ߨ¢M‚WÓap¹"Lžg'/›T‹œ1ú™y¢Üû¼;k.Wv’˜™¡óðmv{@õ"ð%; À_cêLÈÔ©„Ù¾¥|j<ï-[œ9ê RÕj1½-YnÞ”•GÑ/µÖÄÕmSdéM,{Ú¼{½:~P O`;£ã:àëÊS#BPSñâ1¶·#샡W‹àáˆ3QlG¸Oà ŞÊËÉ¡‡ýâ¥Äu´ß{挊ϗ™ÞYžMöÝ†Šæk  ’W â†ûT5¸PŸ>(yµŒ—,Ãm3 ™„áy>Ëh£´›ºš—Zu+yqÏCF2–¬.¬±âM¼í{:§“„´HEÌŽÂ(ºÁêöž–NîS¤Š{ÜŠŠªÂôî)º2L<¸ Ê73CçÏ\™õˆèÄ‹‡5X ´`½•ðH+$12–ãqZ£Ï=c–:6I@Ü07wÂ¹í²¤* ^ѹ4ïf#yLuHp‹ž"8î£YM<þÌêŠdkVŽ žšší*ëô>Áç¿,˜S§$@æÝëâ*·· GfŒ ÞÛ–#á}@V4e£ó. ä§Ô諈~uÒó¼XÞXÒ@.Õaß¼]÷<Ã*UЂ²ÀÙkSjWÆ*·hp+l˘5b‚êIÖXœT¤ ƒw¼Q¤÷n{õ9Ðs“L ŠÊng€—äÝI#’`L£OnÒÝ$\;W™`8¶Iˆxœ7Pæõyr9Þ€<3@õ×’ø—$ÝIRÊÛÙ#g‘ÝàÒ>O¦¯:ê‘ÏS ER‹ J9gn®ÓL !#°°õŽ ãצiï&䢚{ÈÅœ)'IÐ1à:Ó4Á@‹õÌÖ›9³0ÛÙÑÇ,ËPë4çC:¥IóÀvã–|èVÄö…¡‹·ŽZ3ÕRóŒ‰ö‚²1«1IYfî‹©€`©œç;b(­ÎU¼Ž»ùˆ·OUœsÀ'ެ5yúE]¬ÚžòzZãSUÌ•»uò¶Ç3²) †dºÎfåB²@eÅ,Ø­ûlÄaš 4ju‚ÖæB³„ÊôÌs?òPÚlCÑe…z |·ÛnD)ºöì‘Ë2 w¶pøùØŒlOÆEØËGçÃ$h¸øêÚ‘:vy8Ë/#aâe$7‰_+YUG˜­[?Gh‡fqAõ͇Ǭ/01^¹{Ï#\¢§~|ˆr‹ÄÈØÀ€"ËX$¾ä™°±gõMÓ}åå gÓz26C3)V¥Áb¹!2<¸Së"ÊÞÈ&÷Ñ’’€ç¬^l$|Ù¼‡âÛÔ#Ô„¶;¸)kÅÍõR¹Ð‰—Š,SÞ 7•‘'Tƒ;°ÑVQ%ÎÆo`w;.P_3åM ÃÈQ»ù{îÐÁ”ËÝ›vwtÜ^žyÄý^­ƒpB°D¾<#€‘÷˜ "ѷϽ7^GÐãÑ, —@Íýõ‹Æ¿7ù§u𦮊`9÷ÁA²Ý†iBÔË„(Øw' Ë;f´ànn‰-™UÝb÷>mŽàÇãÏ»¸½Ç (Ý,à8ÕЊhX/ˆà6$&ÖeÆŽ” ¢VâĢݡžV¯p;$ÇMd3©ÇDhkÍ#U ³ÖY$~édýÞÝši+|+•³/îîçi53à9¢ Wèch¥AЂTf9Àp»hnH&X̨ܒàꚺ•(•­À®-b{m.¾l²ØŽëLÒ¶Ôh ÍÍYõrs_¼Gl±={s¯¶ÀR°eâ•‘2ŠÐ¿!ÃÔÓ±ºiCü‹kóÓ‡5 KÅRÔ0cP“ˆøôQxV˜ð‘N仉7Fá8ÃúfoÈõ$Ÿ0ÑLëZ›‰:/ÒN=žv¼µ{"žI‡.®ã‘¾ \½M‹;ÙÈNÁhz²ÞÛe•ÞýÀä{çfÎ&½vÕ(/\÷•³<çDÝS~R7Åö op]S¦{àß Ó ‘up½w‘ÃÒ÷‰^œãUSW¶9Ä.6ƒ½rÂFò×ÒLvŒ7¬,²gÅ›0:²Ä‘rÙéjÞ˜òЙßêC¢™Û! ¼Ö!»°„‚`, ~‘÷*ŸÚ¸/º]WãBdqÆöµétG;í‚n«I,™xºK”_ÆÌ±Ž6p(áxÜ»í`ŒÑcOõR¿½õ¬mb'»F2kâuæƒ2S™Ô…¶BN«;ÆìŒÇÉUeæ}›lØëEIìS/HÏÞÛ³z™‘å›Îd>Jx2ƒoQÒ—®¤Ç+ó 50¯ÆšÀQ”ÒïzªE—ò½á#Œ—v­±ó8%TŒ ¸9Áy«Ä1«;F`Ÿ§ÍV‘˵J*è¾ ´CŨǖ<`C&Áñf)·–% мÏ[1ÎöHkw»ý%˜®½ëÓËZi’ä2Qΰ¾×î‡.:Ñ^L|ÆÚË 2”¹%:8)B&á‹¶¢ó Ì}!¡¶Œçl^¿ÞVðwâ,lj+ XsV«ÌO6ÙѪ!‡^v§v¹ù><  BYi¤¾W<ÄE¡í)œíµºo¶Á_˜»Í¦k9¦°D…úU.zqÁ#žµµÆÜ½6 Wæ^¼ó‹N¾7ºÛ7÷÷c§<Ù­2:íòñvD:ðy9±‘3n½yiJ$Skv¶ ªf:Ú8 èâ8“ß µ’r^Jè‹f^Ä“E>\ÑŸ2¿g}/XcV­y0¹B=EÏE*ïI’Iù¶YE§’X&í»êëÓ2ê{CUÌ…Â…º![^Š5Î(éjOíÖ =C±Æ0¶÷ n2¯Y³âz˜„Ù¬@(ëV‰Évª¹¾’ãw@ÚTûÈc]l˜ñ=Ø:ÍâÖGQèóò q'¦ î1 nBçìWêŠêœvo$‹-ÀU¾÷<Ípúê…8*`Œ.ß —Í©GDÛ(^¡ Üp¤å ¦+^rPùÐí1¥t¤ˆÆê€'e“‘x0éDˆ‹E½„K'bz¤ >îöEƒßáÜéÂÝɲ†"?í ³GLüT•´×J-_Õ²Ã2I ºQæZ¯ÄDHcðÜ®b$?‚ä Dñ)•ò‡!eó6ïuK¼AœVÛõ†ëäËÕ˜8Ö´5@×|o.sa|öœ2Å ²Ê`®_èöÍ{'zª!VNIƒÛ ªgôÄÓ„-C±”4ßXæ­bCÖeÆUyµ³ §"¯º²Ãˆ“`}zµèLyù`–…ÐÜSºÝûÍÓÃ’l:éÓ-[u÷ݨå¨öºñt¨Xi|µ•V+4/ê¢†Š¦ÞMûùÚ¤¿É¢—`¨„ÆŒéç)0e‘¤þT‘V[—ëÊzÈw_¦t?3»F¼TÎÈ&êIµ¥èBOÛˆ¥N°­_¤|ŠÕ¨2^Š?>@¢ØHÝ3¨Ö&Úm¬g·ã•²o§ù½yÍ2A¹·±¾$£@ýKòvîÍÍíÐìÏ7hžk ¬½»SµäÇñG(2^©"@çsHX¡¼ðÄÔ×LÊñ\Šû2¼=àÙÂ…ÕN: ¤º ?÷È &qeQå-±®ìWˆú"&:ûÒÀPWnD–‡¨a »¾à[ö)ŽmxÀÜy5 ÏpOÅ3]—Cƒ%ªjgSô¥ ;%²í¹°[J÷TË£jÊ­~¤²†5>¢ÇBØï §½A“ë>ɬ=2õY_¾&¼ƒGNÁˆS¤êÀåUÊyÞMﻓÀ°ô÷†²®¼ÕÓ" ³}Ú¯ôÞee°pÎlO^¾ylÉ\0O9Â2VÁ«ïÞã‹©¨ñÛ†X ÓÍ ³’YßÏ^#LìÒÐ6†Ö{êaþö^V¿©ÞΨ{o}v#1o6Ó0é–)_A+˜cGÒˆ!“y·u=Ž|¥k$X¡ËK—­ ÅMžëX"ˆêCž=€Ã Ψ¥†<~Nì’Ø:òØÏ¦93Ÿ¯Ý‹¬G jîyåùo’Š«SÒ Tå¯~|¡Ïd@ïB†À‡³Û,Pß+"ʾy›¤ç%Í.a‰wf päme+$kcE®É6}'æ´Œ;ØçêÙ32•Nð~ô6v˜ðÑ/TÃðuûÛÝû‹O¾~É·«½§Þ&šhÕsZôÄÁ9ÞµùZàJdl¤Ú(‰fjL‰' ÂE<Í]ª®S =~qÏê"¯Ð`˜S|ªÏpï{W‰çÎÌÌÛ÷˜°pH[pS»_ç\Œµà -?¡ºèhÉd±æX§«§K©<˜©a†{oÔä àA†¨<–Eôl2ízû© >‘"ûS“ÐuC`ÖiZ#H™1ÞùÑÃV°J»W3„\¼ (2íÔñ¦)=æ!?`¨……Òi[A—6z¬ÜI·0ï£1ù{"·o°w}JAßÌ(X¡jåss &æMß6{)ä/¹L7jß{6ÚIÐâ\T¥š×ƒÌŒ¶oâ¿C—!Ê€Í$ÑvôÊS™,ÓÓ”èÈLAŽ“õyB£Gû,µÈË%0{c]|¶¤‰ï˜€ë™ÐDïÌQ8‡…³Er Œõòu ž;’ñ“T< -tÄ4zk®S8 xAx ¦ýäÑehìáyÄ[H¾ÒF“°ñ©ç3–GûˆL°»“v9Ž7E{-‚±5”D{€³\©ÒÚªÅ3ᥦ#öGaÜbƒfèfxRöÆ‘‚Ø ÞA.<¤GBwwaV³ny>?¢'Õ÷Ê-kwÒÒh‹“¶T6¹·Úº³î™[Emø"/'ÙÓ'§±o¹RÄ“i°NckžDyÈ#ÈV”¿Xáä# v$!ý +¥¬t]}¯;³H@óâå×ò,°¬jZ‘YóôkêX Ï‘Óq'¥ùüzÝiÆ_‘ˆ\Z!Ú3NÛl©2'n ›}\Û¼Y}&X72 ‰“¶1ü^eGdN˜“X 9ÑKTRÞ«ÙÂg`ìk“Í%J"¬þKg¼þÏÜâWïzê à-Á³-¡öx8­p×8x½kªoвtº±‚Ø(Ýó¨çIÞŃܜÊ5A“×utáöžÏf:Ñ-¹¹»*Ø{ªÄÏK;Ok|,f‘oJçÁYø;1D43•±‘ŽR„Ë똵÷:¦Þ ö&Š®ÐsK˜Áõ—ƒ‘=mMu–zÀÁº:µý83=³¬%Ô³H…CÊk 3ƒn…ð°ñ•̨.ÌSWˆy€žÝW@—öjÒÀzBÇ.O¢øÕ¾=Ù²&2yÐá6Í"Ztâþ$©bMT;Í¥[ 4û½7HK“Ï2,ñ•†0€ó`J€ï¼Ê³—°Ø"©5ðôð1o«¡Ä«(™½Êª÷”yù…Ž.å\†`j’¾ÌI·(¾{ÎÙ‡$¼‹ÑWTë«B\KbkIj‘¦|<ôŒ0DDm™…æâd ÁoÓ¯N˜¨ê•K[‹*W Ï»§ÌïÅSë½Z…È(€&DtÀ~÷T*MÈ Êt?`1úÞû¨f1ºìDé3ùó)ts›A¶»k•šŸ¶æ» £À~?Ïšzfû€øU³@$õeãÕnAuµ5…q¡zÞ£ÀÙÅ<pÒx2iÑRg}/ ñ[S2ëƒé&ØPÞWKœ¦š´-ðŽ # _¸Ýø ó¼ÔƒÀÖóí²"дÄêõäÈ0‹ |T¹Bxͬg®XÖöÄQ˜=œG¢ Ÿï('Kó#Xˆ:–ÈpIÆâiî… QÇéx×<»¯˜Ÿ®epˆG?>-1&\6Å…9ãÃà§È-ê®óðt‹J%ä:)ŠÝÌŒ%JõùJOWHƒœ =X_²Yç Éyk¾ÊæãF˜î­h²ý.h$³‘«÷NÇG–c–ÕZܬkæé¥ä oŽ+y×ÚY ©Fîn µ‚ÞªòXúºØ–r°ê›Fܘ}/aºÞ–âÍ醕jEÅq¾h.1OŸÇ ƒœiø†ŠT§¤\r]»‹¢žWÕ븈&W´x×F%x„j¼öxXoa}KMÌ,;–KÌÓfyúJ²l¨Ñ³ Uw9—ÞǬVÒùŒ3Ž Æ{e’“ãñ­9¨cË0l÷ƒ;|´›³W“-N‚-añ §…Šn1_H›WM^¦DÙ>Oñ¼7¹!O÷Jôa(¿;&ê+yƒB›(•ÅO¼d+ŽÚ±6ÐâðEËî™â+=yárf4Û{ƒµä°vñæDÅlÍ»p)o˜¨€°•@'8Ot+øœ‚Ú[NG‰bZÝlâPÚKÝEpWd|Ù€v Ro8µÇ×ûH|eX»oAÇtºÑ;Ü¸ç• ¿°·µï©å<_Áƒd­ aKu@OÇ8š#ÞŒ“kÁcf€gbäWzÂø(43ª\™½-ï²¾vxb~yBà4\åy ú/ƒ,ƒ¯”ÒÞÒÆíS[sz‚è"¨Ž™j¼0Ÿ>“EOtœº { D`•ýJ¥¡5€×1$_« ¾¾amt—p#}ëÔ+Ê.&QwEÊvL $GÅþšLà Š , ïÄ “é™Ô³bæGìîŠ7Ò,"8²Ø>GPÝü¬lùŠÎDO€¼xyÙøØ²(,±k³­Y¸¹ UË¥n…î´9@Zdü5J¿Œ4S¨É¸æ ØæÌºèzªî¯Ö𙽗Èfa8l¤ž3Æ í„P˜qYé| §Tˆñº3ûÝ/ÞЋ<ã âÍZýÄY,&7^¿~ôººý…Û^QÖ c[ƒ+q¦ú\ôZ´¸âQxÇÔ›O£M9/mÖŒ6 3®¹X­“.€ÜÎ̵ްuLÞ»Ýu(êå Ê-¸óõ†`öÉ1=¹°­Âc—2ç uHU yTºO¸<îQy ëûÄÅ?qÉÝ‘ž»ñ˜íe‘ÿx¸'$äQï]½F‹¾mz´ˉSejѤÞå¹-ØÅEÒÍÐ<Ê& Äè„,ëh5b7»k7Y1ÕäZ~&VM‘iÅþŒcáÜÅ©/ºß°•'død[¼Gz-[*ïÀn?®Ëz‚~Ç^⤄MÕVeÙž—é£0÷Œ®3O/í&ö– ¯çu…¦AºñÓ 犷g\„QwoyoP€=ÕÆÆ•³àh{=‹šÄÍèYîç!H`Èqnï̇,Þ2Ý«·ñ€±ÜEÊ»O)é4©|{yÚ€û4hT›Ç°Á5Çóz#%3ƒo>–"Ô8XæÀ·o.ñp…óFú{¯TÙU"5iã¹Ó5Ÿç=¾A¤7þð𘯇â Xï\p€eåœí³¬Ö‘¸ï+YbG™ q–½¡k=4õSÁÆ-„ y|é3ó¬AΖ÷b“ž–¢œSÝ€­Þ¶Ò\ÏðIxÍÕë*¸~$±:B¹(Z§[HÖ~ÀRÓ…4åÜ´Ëæ½O³.œè᭱Σk XRÎLåGkÕZÇÇyŒë´$ÚoFgvЏž‚JÏœy5f‹ž?xãV³+vn{WªýfŸÑ‘Ë­= u®!0*¨2ï·k˜, ]ÖD[ ޽õzÊ£+ï ç¸f¤?`±%{íY^ï}ðúÅ‹Ôòë€#  å[ß¡yƒ}¨á¤òž:ëËØ=Z÷YC<®DÝgácmö {zµU6ŸsôtÆ€ó³Ú…8óza4pÙ#,@øî=«H [¿ª™Nµî*;/ê,$ˆ–¼“XYXÌOuù,ahŠm„ˆ ƒ‡]Gß]ßöf{_MÙ¹9w!×óx×¶[–ïUÌl‡‚°s‡V™u.!*Q̘%`»"ð{ úì-.L(Ç„SF@A1[ÎÕ<°ÉÁÜi!GNÛ³Û(¸{®“P©µìŠ ?ÔEȰĠmz•y\†Hfùou·¸„Þ`•=6÷S™ÚÛ.6Euiõ7%Ú Gzh]^ÓµW$ó 'Õ‘·$˜E>[-™63•°D» ×Ì@Lœ²óS4„îô–{.À)p€¸D‚1´ä€ß܆sñlÒ”B@cúÓ#m0r`o4¢ 1³C4€ª–Ԫæ×êVÅæˆ4 3)Ô¸£DDöœÎt'WpŠîÂ+ׇ$)åM¸€O†wDnÏ”mÎï/¹Œu„)Qï–ëͨ\¡ÓÞÑ«3c¥á;µ…z̵@Ýï*ütFNç&7±à¶gR¼‡FêQƒ˜¶/‹žÈèx/6qôî!oP§-æK8t„9ôë¨: 1Ø3]3âr¡ ^4„V`w»¢ýÜy$ Ôâ¬Ãú$Γ±@ÓYºgo¤k’ÔÝ%Éo—ý–·DÂÕìžg’ ¦t­ô{·°¾¾l¥Bð†£síÐ8&9ºš5ÊÝ ±Ç(N_xŸeÂÑ3wˆ— î9™ aêd¹5šÅmI(<Ùj®ÝôröÞ{I-ÏQHœ%Ý6˜Êá½­y9í’¬"§Ë'RrqáDùž÷U¦ÀˆÃ’…¼Ê|5õnŠˆtg(ýüDÛP 97õµ½»ËÖ7ý®õÊG ªÊ­â=º|6™ÉŒΕ¢æ˜K2x¼Àj)Å®ÔÐì{óªVo¦4bŸô#¾)!ìÙë}0€bëäð J8­1‹ Y1ÍñäI€¾7CYy‘<ÓX+‚XbÜ©+$›m©=Ö¤»óVT™²¼ˆ',M/+xg<°ÓÐ ÃU!‰C ’Uki±xú¦ù4 :äˤ/c^‹ö(Fk¤¾†-I%ùKºÍ{ÃRT®6tŸ «©M÷f<`Jq9ëa­ƒ•ž£~˜üZ3g šÕ_½[á¦d¦ôl¡hŒ‡7Ø»»§-‰C~vƒk.ÏÆ¼bzsäAA‰-ÙãGóÆdY°÷Z”g¦µ^Á$ͽ~/ÔÅ×£<™` ‹z®jù-F U«ÁÒɤ`b92ž]Â¥…<¿ˆyèlͪòÚÑ‘¤›£y=WZ÷Ì `À%ê9Áíh½Á|,ÒT£‹iC‚%^e˜NæñŽl#¸¸-† vÂöI PEà2P ò–âpãN<,ÒÑ·±!h—)Õþ’ž*Á•TldcϱÈÓ<ᵓ‰ê‡:ôZ¼¡ â‡å[ÄKaÎgXÒ åc'6ÄÖ_¿ÍCß8ÑXI‹y Æq‰9+¢‡† {醞ë#÷Fì½›ƒç~㢼ڤÖÊÏÎ|,‰x*çlu•e[C¨B3F¯˜±g”¡Ä´¨ƒª­å ±×Ô dÖl`†ÏdÚ¥4ÁŸÜC2ßn$L”yüL•Fw×ßÔV’B£±6(Ók.ç[“4¡µƒÇEâ侫aAZQív®Aý&â±›f˜3ð²—Oü¥µÌT“Ì4´Õ^Mâ=ÐŽ=K:ÂE~[#{ný‘;p± , àK‚/e.‰Ü¸ºAÝ-Ö÷SãÀˆþrF 1šìÂ$66ùUW.JêH 3· µT^‹EAÅ6»tÛÓ„töªv×®L‹»PëU®WŒ`ŒY€ØÂL$êàÁ u¸>3±¯zo1 ßL¢wSÙ»YØzô.MÐgÉÁÛMR[kßBê+ ö“;f}¾ç†W ÇM;Œ:O ÔâÉÆ&fí-Jb¾‘ö\-j ì6£zö€Îh`r…E^A¿ÕIk¯­—ɺÆf‘X°x…!¢i¨OŠªêÞ=–§Gfz‰D ‚ïªð({Cý±Â™¹«e¥½'„0ŽVFPo<½Ù‰ß ù&%Wz„*ª¬¼}Bnöz†]±,‹äâ;*’ OÓn{1MÇyd÷JúˆøáNœ½‘×yŒƒOºÕ¶Ï/B8;UÃî¼Ns£´Ö¸ÚìH§†äØW-ƒg Dh^×Èè§3þåŒP*xa÷Œ'³XŠí¬9¡é_Ò¸¥@l SÁIˆ*uǃà#=Ðt‹ áeç¶KUrEòœ/nßYeÉ,a×+ó§gOÑ1¼xÖjÝrOÓDèm )ù)ÛÓWǼÕóîq«ÁB¨Î[· ì%z ~’(´]×ÅÄt;K†üüÉAƒ>4^ÛÝ-…Ó’ôéÈܰíä౨7s3µó(8‹ûÕë|Œ›höÞ¾D©|\¬#áØ1Íb‰ôšQÈL¥ž¹Aï4ÔD—½¾”¡{ÑhäÑ4ûÒ0+a.{_™Îö”š†=B3zb⶯éa4ʸZšž´ÕI'Ð#•aD߻Ъã¤ùÙY¾,ÓÞÒ,oÄîI-##$LÄ8µ±‘܇뺓ÅâÕ³ÀÔâûæ=õiv©É†|§eÜð¼|çélwlÛ((ðÅÃÌJGÉ”í¸´ÞÛ£†-øÍ„Ü% å%òÂD‡ä¡ajfÅÓƒbå,°}”y=<ñP”Î:‘1ª“vøïb1SOá IãÓ¥uH»Ê ApeË;»‡ÃÍ [˜Y8˜ §VqŒ Ée:ÒÅÅ>„“nÞÎ³Ž DP^:‡l¼á÷.´0!|f Ë•Ÿœi]›Æë÷¼5OœÞeÔ^ŠÑÒa…ÓäM¯7àÃñDnt¯žŒz½dDæâ0|ÉuŠ +̦Þó%ÍÓ/iœƒ–ßLÒö …ÆÀ9ØîüùzQ ƒ:Àe¯æðI.¿H¸|æf0™oQÕÃÝ8Ñ ³€uá@€®°âÌŽçÖŒ¨lpÞ‚‰ô,@¾f¨’ë«YÉ´eU\ëz6MË' SÉÆÏv·ãœ^öxÜÛÜ3µÜz1ÏÏ`RØî)åkô×ÕLl»®õ¶‰–ŠŽ(ö”SÈ  Id^<}œ»ÊææÎOÛÄ—ðB{ìðÝš®p·ô¸t ¿ÕÅÄ|IèÏ"Âr/&•ß8 ]Õ¹¯äFà6+Ë=D¿=8Õ±ö]c!%ZÜØÃÔØ¶ ,U¢Ã*±CpЫ.ð” ƒwl¤ãýê24i‡\’õ*ž>;3ìX}%–¹ûäåIh³*t½xŽ€ ½ñ0¬[”0ò™yyœæ¼’‹Ú3í>,Z0M5Oã5Y_- v¿#,=-ëN ¯&&±ugÃÀ#ÔX.ÑñWÝä:ÇÝ’ªÖü”ï‹{gÞ|áo¸‚vÉKŠËkÂû¡å^ãŠÎˆ<>‰ImçzC(nC»Æp m—£”ú*<ÏØèY©Ÿy¾èJ–ÐsL¢÷Ôæ±ˆ©{=â’÷¤/SmÍÓ!¤ƒÆÀ’2M‘bv5*pФ¦!Ù%Å;°Ë÷iQûà8=’æ¬å„3åkÀŒƒ4~k‡`½Ïyšèå;f{–U‘=zÖcOöËæ/kLÔßt‰(2´ ¿*Ý€ð"LÂýK›£€°E˜í—œÄƺËk©ƒ¾ ‡]ÞX²âq¥,ÉËùn¨£yØW¬*Y³ ÷ªZŸI“ª ·ö)©ÓAkêh!.-ä&£¼7=í‚#_a؈ç“yåÔoòvJ,<3^ç¸î¬COº×R$@Zíyë*jQ:©Â;Áì{(ZÉÔE¤µoƒ(ÞÆÂUcÔœš¾·h%Áœ@Ò-¯Éà˜… …lji ,R0šÚ¹W¯vß;QKÜ|ƒö,jp¦Ÿ¼¸z¢,¢é‹û S (ù\¦v ü¥’"ð yJ¢; ¿§Jˆä¶ÑSëEŠOÄòùé6 ¾ë™’™‘ˆÖ ±{GëI&WîÁúš 1"ᄺ€^‰´ß{!’ŸÕT-p3•Q¨ªéc€Ž·;³@1Õ²ûC¸)Ò.Ü’ËÉóª•*!60_&ó%§± ¹SÙÝóŽF ªów•™h÷hvuHýŒõ½Ç—s­ ]²l†ˆá[˃±‹…à9½:àñ‹aW­|€¯#Ùî ä]jœØÁ¸®×­a*>áƒb`v+•µfYЫgï¦E‹öVë±FÍá÷œ{8ýAê´eà D²¤Å±½ªGƒ\µ.}%Z•ÙlöRï]\ÓÛ3·%ï]ßO7J7j as‡°v–/m„¾´]Þ[x²Š—yLnÅデÔ¶ò—7u¼»ò*·óÅ’;›CâX h¬eÀaV ÒžY›%ÃóNQ…¡ŠÚE|òtü¶mHù(Áèrêh^BjÀްy CMÀ«§&æÙÌI5­V´G!ZOê™áN¡Ç†_­_qÏ´·2æ´ Û&M-š¢fBvqža˜’ŠYJ–¤až½GvÚÌFõŽð*‰‰Q“Tk\_í“ð› „$•÷dÐÒJð$fëâ8²6ŸuÎ{åGð(ùF®õ˜¯Ž2– o´‘ÝçÜ*˜ú/®íð9q[CdžŽ½8Þç¦õü ë¶:Ífêé{«PYkE»‰Ò*[„}W´å Å!jµp¬OØ=IUa!¦ÓcOE2ô­¾Tì%›¤Güý cGG^h#¯³æÌ=u6§%°@u‚[àV؈x ú`]@:üXm)‘èöáᨙÇy@mèX)…“÷$Ê»èÆ¨óÒC½xxh€<‘Í¥þfwî²úÞÓxg">YpªÑòš0y|Öªe§v³IR‡CîÑKƒ°™°]P®P¤n—nÇ4™wt&èo¢w)^µF‚¶‡êãPz xlá­4bœ0šb)7Y<3ÞoBs/»^Ô[^zÌVí·/¬Ø}˜{õÎOòaúWð­§‹VÍ >Ë!¬”¾ðâ$`äºú…Jª¾{¯ö=ºXѺg.ÂÓq=›´f˜²D;«˜#lŠòBcpû$«¼*óôÑ[1(2¶mà~²6+›” ˜:·ïy(„3+ ÌÌ›ÎêéìöÇÈ+ºKÍ|::}ì&»ÓÍ»cŠ¥´˜ï¹†î"Ù8‹>x|Xo(Bˆ¶<:ØfF®ÌÁ¨$hCF4Ý& Œó‹@{L/fžée ¦ ÂÁµô ®•Í¿!e®Áî ËÇO.Ùðy“ÍÄÀ©3Ä"Ô6  ¼BS·V=J0*%–mP”ðI1¸§·~¿º¾õëz˜>ï6 = =wÖÈV_+¸”4†®SÕ¹Q€¶#3lÿ•"2$EmCÄ6 PÞG²¯õpŽœˆzÇ>(ÇŒ Īåh](ôF mÅ‹·»zŒ3è­ƒŽSÞz!G$¤ š†âR†¢±ný3o½¹ ``ê¢eÜ D[&åí!Š´£:Ê@÷”GÊbªÆŠ]¿G‹ c®Œ’@ sÈN¥þrV©`0ÙA€qËzún:0ëÉ›À°N~‚×DZ#ÆýJµ°•ÈÊúTÌæ…€3Þ—9¦_æˆË-2¡f!ÐøC+èzÏÓ\G®ß_ꜻ% ‡K+g½…¨%$\{gYÃPǦ +OÊh®!qŽ`ú¹RÕ ¶ñ”iÂRUÃ#ò—)—Š’÷å¡l¢á£³¾y¾÷b¶.I)æ~̯qsŒ"9MùÔ töƒÂ'ïÁ ‰2—½['ÓV}$•âÞ†æóbs^û”Ô•¦Üƒ“tlçÖro&LÎY¡Ò¹2<§-½:Wó a¦)§ ôØ|óÞ“öä[÷æ ,¤Èw…àÌŸkd·{eðË}Ù3—®oÇß %¥÷y¯÷Å(ÌÐxáiµ›E4—mUÙ0X‹®h­Ï ¡a>G(ªêß§/Áf”¨õ`{s^Q޲*„O¢u[µøCeͶW5 +¡¹Ó-æÀ¸åh;y1¬ûŒüÞk…¨òC{Š{P’ÓÓ…§OBTtŽ’±Cà©Õ I¥OQiYî¢â x Ð>© t_Ë@F™J4º%å©õ]ܘ”®:Æ6J]QrÞõ¼€ 1èŽùn±ž” ø†<æ…¨1 îlU#êØ§r¯¡¬Øo!‰â-›¯¶¯–u¼cÔgUpƒrÓÄ«ÌOB.³µÓúìYàÜ„®§‡pAn< |&å—:¶“„bž‚¹°¥1a³–×x|ia—:ˆ#Mª/½ T…õ™Ç”$=z¯ÎßÄŒ„€6JM Dݪäʾµc-ÑGÖGbùZô•+Ç{å×OòsÚ útg» È$Îø½Ñë }m Š=þJêÝ¥¾Ö¿ä‘`’[)’Ø[`z$üZeK²š§ôbá5:ùº™ƒT¬m£èxc ì’-_ÆCTŒæ89¯mèÕ¦:¶1 n f˜=Ñy-”d5«ÇR«9Mp«3PÍõF—ßlóî{IÜJL˜åÆP‰‹¯F™mi´{'»4(™ÕÛÃÏQæÜËó-Cõ(‘Ù8‹*SRœ+ÙVÊsÈxñ(Ì€pn”‘Ëá|L¦$ùâ”vhoýáVm*@u Õ[ºIr{'ìÒD¢¦•’cöXÞ[?.i£(¦ëì¾Mm+™Íñ”ÄA:úØtëuÀ#¹w×ìʧQb‹„È Û'='mNuœAŒV¸ÌÍÌãeÈ».(\9ÊJMPú°Ô!sºsÞ½Ò7‚K3H8ËÐX.T£é4èžò1$J[Ï5ë´Çí]Ã{4ƒ¹'Ú*9Þª7O ñ =*®È~3)´Ï o…í5[›Õ9Ïì=Gàq±Ÿy§e¹Zdàjá©ã§ÊíØ+ Ïù¹Y.·è!ßòI·_<0êµØ—¯–!&€Ü±ìMÔÌË„öt?Ä ßŠWdx'GÌ¢…“Þ–~Ïì^´Ã{"‡c0"fÒv•¡Ýá ɶ{¼BŽxy"À¼­±ÌÄnU6„¯Ž¼›‘»Fš¶r]iž#%pÎ͇<ð)OÞt¿yà ¡"žO¡›¬}\é ÖÞ”¬{¦È_ö°+R½äg ÄuÁW­…´Àqt* Ý›cwFìn0ó”ô嬽â¦È4[ijȆ`MŒô‘)öÈ6 `ÑÈ¥C¯lò$7ŠØÓΨÇd Y¹’O’Ví\Ö…çDZêÖ2x#oRA¾†»9ŠñŠÛ4¶rÑ9•ÀzݦóŽ«Í öùõ)¼cé(Œ²ñ¤Ž¡¶…ØVÂúzŸk²xÍp¥ØÀ«vª{Åé=<•–.qýr…Ÿ=m}¯^a…·i䘨õ;ÐZ.Ê!T~µ 0‹ÛqÖiöÞöTïkñbAŒ•“xÓÓÒ!5`àÔ'‰™ˆò`Ðâµ]¿‚KœûŠ6¼˜Üåµ'VjnY9?~u—§Ájc»½lGSm×G{KHøØ©”ñ¹x °˜ñ7ßCa—ågɉG·ÕÁ îäo‚: L:LßÃÁMjÚt·$˜“X¾6Ëx…n¨S[áj„¢.:‰ŠÛy÷ðé”"™.SÁ©ÓQ`[pv†ÖÉäyNZ/Ç-ªµÔÃ(˜à©âî[w¬:&•Ö2ä‡%Ó§È cô*Áµè`”­c®=”fÌ€EéõÄ–4æs*§„ˆQ¼–K-ÚHò XWÒùØàäQå¦w…/<>ËÒ§"«!´›Æûfjp3¦3ä=tþ´Ç¿ì±jgW;½Ø¸é·¬ûR¨ÍvØÅvIaþ©™ÉââBb»ÊR‰•¿µ;š#›…TÊF3=^œš¢ мÕ_!(¼GF°")u9 mÕ¶È*B8LÕ–‡ˆ§_*¤B:ÆÎ‘BnÊ ¿(å€OØV œm/ŽE_<ÄçXÌ9Nhpð"#Þ»ªˆ,Õá‘E°éŒÝ. „%Ý{Šî&H£¬]9Æ1[àt–†K»ÏòÌÊ¡(Mß,ØÅzIÂF4Êt¼ y5ÇÒyœŽFy“2ZlUø1¸DÔå.‡>‘Ñ}&J™ý"’ñÝyÐÅ4Ø*ñLea]ÂÑ`fø63UaÕ™B€ñ*î ÉSs”Þ÷Jhv*²—çVe8R{•ˆLkfgê̲qX¹ËOtVë㿆¦lTêÊ,éz‚Ï»æûä¡o nGsÈ" [ç :Ä3W†€w«YM‘ƒÆèv02Z¹s%ùB\i^hUkŒcªÙÊ8® ]ìÜPJ{ (nwÕ:qyùd»±Ô|`@à, Æû¸tóõ+Õ×cv­Ü$öÈIôH d“qÏ’éu›Ø:ÖX5ƒ‡ûd±¬>*Õ˜Îaq™>}ìí-CÓ*˜œz/E¦V.Wb–*Žä<`ƽ2[¢‘7ÁÂ1¸”Q™ŠIZÍF¼d5àG…[GÎ<6%ý}N>¨_ú\¶Ð“ŒØf'‹´d‰ ¿ À@O6Çl¯Dœß_þ<¸Á—J‰ä#ív®/c×çZeeñšCRMvœäuÎòY ËÄ>n¿ž7’g ùÒ´È05åŰÚÅm’ÎAWøtC(P Œ…n<Ø\e¶ÚYNS!ä+ñ¬ádϪ瓒Ýù8ºê¦Èò¢¼vK‡Ž·ÔTÑa]…€«Õe/ú<½„(ñ®\¼üY+?b˜n?y.¡;•@NζiÄ%CÒ«ÜóæÞà # ´ë…Ý ˜_†5V›± îºcïµ^M¦²Î€]ï ÏPxÕD/“(Ô4ߌ 5hëÑñ<vá3ZæMäØA£:êðy/OÜÍË—Ô{™×‰õ)ä0‚é5oÔıBŸäo‚ï£]ÊãÂ-w|qôf&íjC’¡Eý…û`:_]‡à<Å—¥wÎóŒ29a‹Jýå`Ö¹I [¬ÙŠÜ#¨ñ:¤Eã3”B¿ãõN££¥ÈÀ‹4îá™»Œ¢ÁfoÅ(Tì‘“"œÇmõ´E[^¿Í—ý€ÃÆØž$^QH¾È}>nÇ‚çÚ¬Ô5q°V YÞ½Né¨j9ó±f=¹Z,æ~ª(‘çv5­$\ª¤ú¹+ øKq·W¾3KöŠÑì¸0 öHÄá0Šn|Ž5èRØÐO¤Æl牅[Â{;¾þ,edž²+’ o!ðƒ/ˆ¿üó¢ñë›õ¾k´î+D3ˆ’7¤¬”ï땵E¹ìŸï¯!–7€%õ®®šWφŽ<÷f훉ú½Éè$Ñ~$$ Óq‘œMð²(ŸSä# Õãy.C(åüF¹„êu“â>7%öân >›Ö~zedÁn2þäM°ðóºƒgölß¾w¥"ѧ²†®ÌȘ¸âEd‚`zœ‰|T0~ÇfTÇ'¢¤.éí‹‘ÚŒÒáŒÚ]O-¿Å¾·ù–DÛS3¤¥â=ÍöÊÓyÒfZ"úD_·D€ff_X®áê ¦YWƆBõÒ¼F\KÍ¡gn|úP'œ¬Gz6³^Ëæ’ç[yÊJê"b„çê§ð §¢ÛÇo&‚c"œìUï e8qI0ùüá p%>nš7„~à *t'OÏë½m÷î·1åÉ‚oËÝ¡BŽÂM›-ýü x¸EQ<éÒÎbKßBÎKgçG¡ ß¿õá`êÉG%«s¤CqLÕ~k­ü&–3îE&¢µ5ä­" 晼~þyVG§/ÍW˜n¨cŽãM*xÏæ¨ÆB.g©1÷¥:¸3Á%qò+]j4ÐD˜bõñ´ÒEïUoÞ<슱à¼`1 jŠˆiô÷LætJ-I-:I=d²½D®¥€4~ïuÍy ’ƒËKæâÕ©Gu”¡š¾™ HÇÛ‡÷žÛ½} 1/\–êl†^ø£Ž«/Þ÷WçÐ×o=äNjÙ‰@ÐÇ‘‘ÎM.„pI×e³øïÍë˜ÕªrŸ›„ñPßä’-ÀåÎö{-]þbkA¶ùyBÑ#ì÷r”*•W¡ÂÉøI{PU²‚ƳÄå 0'é³=°†ì 9vE±„V^xðæPôÞSF€µÐx÷Ö‚%´7"§òhßpqNÊð«°'³\ÄB°íÀØÙ›ž­1çôÚj#×i„ª‹‚“_š`ž.T¼¨‹ƒ_’&x)9Úulá‹Ðge{iï1»8˜çŽÞÆK=¢ÅE® uë~]Ò|chÀøšƒce@g†ù6 ›·6—ñ¥Ufá UDå3-ŠlðǘìÍL4T•6nk¶r(²´‰˜ûÜ–©v‰ÎE«xYµ*8ø¹ÉÆ>¯·&ü†:àQ±0*^ô®CAÚÅqÀ #:$dÚ$j6ðV*ñúöäž'.Å-?O{R 4¼Ó€Ð@Ç¥$™çàAp¬#)áËôD­+„yÒ’O£\»êxw}N#ê=”,©(rÛpÒJöŠûÑuâ ëÐ;žð™|yom³8Ôźâ$`­°|SÊZ¦ÊnÌ<ùJ j©Ëža§DäyÀ“Ðu8%h£ gg#H’6üLjÐd¯Oêák/¨v¡²ªÆQÑ›Š> ô3´Ö¥L¸)VyÐdˆLúÐneQÞÍ$Îè;ä&ÙÇ/ädfêe‡ê—A ŸSÐKtu/„nØ99éìà†þü5ƒAkóQ„kD6õ_ Õ›æÇ•Cæû#\ç*µŽí꙲dëjÙòÜX,+Èî£ ÙAW×%z°DÏ€ïP6¯h76 +Ѫeœ«‰’FG`hŽÁéöhU“ÝÊNÖôaób>ãúenL75[¸Zzü uÞS™t€àcE0è»|œ®sRnÝd6Ú®­@t}_f/ÖÚ>m÷ËDLº Ì F‹ØæÙÐCµepo'ªÊnÖ¹|dsFõ0ãìæš<J׋…í‚w³eŒÒ?Lu¯ÓŽçµ™îêÕjº]·vy\±¤ú)ªìSw™aPÃÝgDþ$°: ©8…‰œ _ínUò"YØœÄ-›r$Y¢NÆ1.”V(‘Â\Ò‰F†Õ±1Hò6§²>uØðº­_'Ý‹§z½'=–ÙêÙ½r0›æ ÀËÃ*¿èí×hJ“kþNPŸ‰ã>n¦êG¾x$†)b´&»ï$áD¢0ðÞv5Þ5¼¨ySp`™³£wOÆÇù2†ÉŠÐŒwÓ7#ÓToOË=PHe:Éßf!ˆ–V'Ä…º%÷}@±’ùB:îí |ÃET9IINwþ:ômØá™ðË *9Æ{¿«„—ƒ/¨vÅHå&Ï$Ì:6¼©wfì¬…Š‘(y:„m.â®hÐ΋ ¸Äo…üK!ç+Á«§-Ù]2@t~ä“…@†éÜõ£©í~þ¤(þtè,ùî´­äy¼ºÊ ž»{h AæýR‚Ëçj*oÀwéÙu“Ñva›cùlÛW¸w§J…-Žð¤J¢éÈf`{‹¸³Þò¨1ošÉ\@Ô‚!Õï±N“…¸ Y˜²âhùÅ@Ã-r!<#Ø>ãz]šõ dM9Ï£\Ï]£ðæP°åy3}ß;Zñ´1}Á …m¡L}ÔÌ:Á”ïØÓ{Œ^‡<2M§èƵ²ðÚÎ÷Ö ®¡†™ˆ;Ë£ò=^¡Ñà—¸mÔùª¤Fqš;w1‘äí=DäÇÆ–飳·¢ûäVmdMÑGs|o^Ž´?¸3±àËMy7ÉÛgö`× $3¦"rg©…$PC9wÐÎʃ HsQGMÜ3ø­ ¾:¶C9L?ÐÉ®ŒÁ8Y(Á3@­Ž!PΆ޹«èvôÚã–5Fš(—Âd½_‘òð{\+A”:;wRanjô^¶x´”Ù#M)ò×…s„V37W‡´|[É´ô]M®Hciä%“ëe€º4¯Ú¾T¨…10ê—ãµqœÏãªòû@÷.DAÒ£_«ze–©X½Ò²@&B65{Ú¥huÈŽ½ÏÔWÒó=ç0ßL?ÑÔ£5ŠÑöv0Š ˆÍÕV\XÍ “ÈVHÅ*énæ„€äË!Ñ/‡â躭f!`´ÜzlÃÐ7µ‹ѯid6.leJ³q£þ|—m2tª*¥Å¼ä7EÎ"O üüx,pYö¡Ø.`àÈÄ6°Õa‹ÊYÉÛGùZžokŽ31èD’u‹æV3SqùUɤ´I,ÖB ±V(<â·zù ÞXϱL 4%ÜŒr£"6Z+Em¸P7ƒç-!]?x¡ÇD .i¤ÎÀ KÁW ½q4²”±|¸ï²\áwizòl±}¼šÂ¡"^×@úNÕ–JiŠõö^ë³ZÊ1ÙW¾M5…bä~¦ï 0€ÕµÑ5ƒ‰Ñ†Ð#™CÓ³”‚-8ÐÌ®Ìc.Ù*^p€êu‡ºs3ÎlN”“Ü4àPÓ°†›Õ¤™‡yû°»/Æ¥XÉhïŒCl™Aóc61pг¦-xpžC…ž˜:Kªì" Cäg@!ZdÀº£oS«\ßYXÏ"bFêqÔ´mÁC<¯³‘Ç58…bŽô¤‰#‰·ý‘¤©œ4¬œd·®Î™ØÍZÌZŽ7? ”rRäIg€ã• §¾`Å’-BPF¡i«{"!e‰Ê€t˜{¼£ÛGÔq½€èîKQÞ(Ž)¶±¹u¸ã*3Ï£ŽÂèm¾·¶0l>ûX/<*wdp€Eß)ïË7²Dîc8ùæ\&@;ò:Œ:õ!³S¥R‹X¯õz¸î—DÊ_Íúa½Ëä2`ØaÑׯ|%œä¡ùº-Ì™,ßÑÑìŒ$Ôë_±GÒ$<ל87tï=®¦"B×3.űÏÙðm€W2y{‹.Hö»‘÷¶#»™¦2ßN°ñƒSk*‡H÷TeoªFÍçùfø4¦ Þˆ¿(ßËÁã.€`Äò‹ fʶ°Yt²‚ÒJ.Ü80¿á7!ò^DE ­‰ZO/'™²9Á8û;Ô§€ÀiÙ~O‚{Ìõ3vЈùUgs,×£å ”|]cÙè·¸\Q÷ä®_2àæ3ߪÂ.mÞˆÖ‚‡­­á8!L´y²Æ „~ /Ki„—<QïB{atL™ÀY§ûB:2û²^²+_¼’y®‘69)Uçƈ¡ŠªEÇ'´n¨C›-o4ã”ÏDøöPYÔdvv¤ù!Jðc[³3²ì‘|ØçáÍ÷tª@mdùyéeŒ—ÁV°‘3²JˆY—ôußFÆö#ÇaŠ;÷æ¬j«M*„R\!t•î¦`ƒiT|ÄWü ¨´c¯Cк§¡À‰3DǸ˜EA•‘¶´-¡X£;kž¸°öáܳÙTÛ¬Ùcœæ–}®FáñÜJmWm4Ò;k ü é{Õ)iÚ´:â7I*&ªƒ’jîqþ0Ð_x …î8`BÉÁµçÞŒˆÅË)—ôÑM”¾*M'”·«ÑMÔõ¼zaíí¯@BÁzàÃ_}Y¤t(¼ý‚ªMl€¥-¼½Ü`AEØ1mhâJ|âåN«iIþ9‰yѼB.Œ~Óû s©šn¬×G_Ï#_K1Øœ½w¡Ä¥B‚AøhHVž¾•‡D#$@ç Óo Pã.ö¨¼6ö s÷ØWôtK£p3ñ¦Á+/ݼÒ&c)ðKR®}SOûÉVÎ_ÄJ>ô‹ƒFï½ À®yøˆÇ­W¤² g0e½¥V¾ô0ûÍZÕºDÏKž„( ‘«5ÉçÇÒ\ÎØ¶¸ŽhKc*ì4“‡e¶òÎ\_£Ýb—ÍÝ{6ÉzvR0µçøŠaFí¥üb»[ÔeAâDVà•Ô±i$â-º½MͶ ¦»ÑayÇZð†G6“|ñ¹ï«ÞâQ{Fo@aïÅTÅí±ñ©ÉtË»›¨ ÓÞïQ¾;¥5ÈvÂ…ÀG)1Ý| YÕnþ4಼Æ4^‚®Ÿ·¥Ž‡\Ù|ŽÑníZÌLè2ëÅÝæœ0Æ”üâìåÚ: åiXn`„ÛÀè±”w.'DÏó OT°…¾ê£xµý†äMeùÍ‹dÏÇpž7&&uÇ*µ~ØØÖ¥=v2=EÉóhÒ×51R9¸ú½Éa¤Õ™YÇ·ï=Ôæ~< M«‹Š—Û‡w  c^–û棳%³:ÂL{oŒ^°½—/ñÆ”ës±E}ïà²×«üñ³é~à˧8n)|ç zþ¥‘×FEÓ·q‡±Tôzm’’ lÞʶµ"Rzåv¨Iºë3_䕺ÊáýË£¬gdï^[ÚK•CÍí*XxCæœ—í¯ž«G.G1b—^§Œ>ÝJoQè†çÅ6éÆLQk-A(%~Áˆ°ÇûüÜǧ°Ùß¼M6òãW$¼ÐU­Ú—$©tuòtkßøÚ Ŷ¼÷’œÞ,S #wD_+®·©9¹±j²Š7"·PYÊk¡|çUO€ýñ+Œ–¸D¼>sÓ84¤Õó+©‡ h󖮣³ í€jd=_˜7æiXPDÈÏ×1¸¹Ûº+Ý€,ÀûèöÞ¨èCÆ©Šòð-#yÅ ¶‘¤Iv2Ç^ut»T †¹‚åݱK!99(ö–pÏ4Zû,?ZW`i (zíÌ­UÀ(X›,ÖžèÓ|¡ñTrñHàQ.qSB”ÆÖ¼=Öu7ÌœWâTÍ¥Á52lééÐé“[©â¼2R«ùL b©ñÌ,€Áê<{óvÞd©zº#LšDß!ï«A«§±i8k¯Ö¶^ ʲ°0ך£ùãÅUs­½ÁÍö-pñ˜'ô¬äÞÔQÔ€h™5U¸“æ¾°íœNÏd!–#CŸ8Ö¸Ç9¾gFÙ­u²›ñé‘yÄv¢aÙÞ¢ÁÕì±¥âË'JÀØú^ž««¤˜.?Ù¡&úS¤öžÙˆwç0mÎZ¹}Ü6znjð2™kAà±ÔÙÐÅÝ»x½øhŸomfi`eÇyðëz/sÍÝ6ÌßB"n% ¾HE™óTÚå¬X±êųKŒ~õN3ÝKØj$–èY 2² ½\ŸÝÒSÐÎCaé8fçy •‚lûç©{¾ñ²&ŸqΔ…ÈlÈ{lAcÎM 5:3ž,åÎ#åĆ~õJ¼J.*RW¶WÐõbš´C()¼L›Ÿ…×u9¿í#ÈÄD¬Öy1×ôö,=Ó7žj@»‚+½DˆBng8”Uƒiî÷öÕ8š3¹õ» ¿ëYÍ=™”x¾û½wì9ª·‹­Yßшsë U™W·)á.ZÂ’ŸÑõ>æ—®åhÀѼ+¾¼ƒ¶ï)Ø‹ÕÂz ô¬U=•ÄW­/Jê)bf‰YŒ’SN—qˆ— Kƒ:Æšo·ˆÕ6?4à»}ÇðW9­›E ±¤Ã±µÃ5®ÓLg²–ˆÁ78Ö•ÅT|ÁNñ¤VëZ½Býî˜ë†ÌkÑ!A’áVåH'À†@±ÜaÞ‹ ]C#’,h³…4àq©Õº«Kð*ZMš"«ŒÕnµ(g©^]˜Îs!<ås.Ið0ì 47ÙÞ¼¾¬ËÓnö"sO`0ù‰®¯,Ž>ÇÀGIa–/‘B¿D¤Ô¡ UÛ.ºe׺ R…—&ì|ÇÍGÛIy°Ó3ü^´íò ÿic¿<âWkâQ š)akâC¼,'”´˜Õò¤ l¯«c¼TRÔ:A&Y€Å›îF¼Ó;_*Z–Îa$÷s¦àL4#ïŠ7:NÕød;èð¹Áôˆè3ac«èsx»+[S}Èõr,vŠ” òê­ŽÌrv¥.X=)èKî™Åî—Ð۶΀Éó|‘0ÞZר¾²¶‚r`%‚»¼uõ}ØïÖ«ls\qB»%ßΰTS+Íxò0ÇmTU:5z º˜°‹í#Øó¢òYpg¹fúÀk|}ÍxàÏÞ ™ŒÉµxÆCÆ÷V©‘„Õ¶Å)BÍEm-ÏeÒ_Þ[7#„5{$ÆDK‚Á‚´Â…®aýÊ B;}Äȇͻ2`^9ǃ:CμÞÀÞî)Rz­ïPNÀ9NìžÕn#ˆ£¾1ò–¨Y=!½÷p­$£ÙX <{Š=d·ß£[ t)ü2é™öú¨xú .ݨ1¸ ¤ŠÕaüñ{€$¦¶±”ÈñƯþœ” „bæ 6œµ¼¨Ë–|èdÝ4)VU&ï2[¿éµêÙt }Ê¥Rž¼–š$FZpîêáLâN]ž4h6Çék󧺲¬ ƒ:´X;0 WOËùÄió …0°Ï Nã£hÙ{Sm±øD*Št_¼&j§:ÜuyF}À)Á€ÞúhçªÈƒˆÐMŽ`ÚÞ{°Ó»°J]bC•ü.q=ÏrÅÒ¯Øw8: [Çc(‰bk.+•ºÌšÃÓÇð”ì3 Çðkd/.Åö‹UX}óî*;ÅGU¡­Q$Üâ¸Ï•s}°}Ä‹±‹rŽ_¤iCÍ(]U“‚Ë1…d‚›(àuc¿ZyXBºŽè>ù¼`Îîx,›»¦Î§Þ±6ÀÐdŒ_>–8…6ÆÈÖÓ@¶‡O·w¬Ó¼-ɧˆ»S3õ¶rÔk5ÔB*ÓøœÜ”¿Z«ÃRÆ"j"5K®g{ Ý oŒžiÄu>–|HÏAíü [ 3ëeñ"EÍ Cœ' i¯[>ƪ~òú<ß–ÑJ[¦†R¡.Rã» W6ÃægfëüžGür3„ˆæ/†* ×åŽâvìuä‘¢½Š~åÙRxÍuÖnZ’gJÚ‰²{#,œ=ôÒ”ß:âSAÖ+ô˜é7¬mÔ6¸aËŒL$iZ"‰QD:’fWX2ü¥Ò—Jµ[=´ï<ƒ‡9";ìa®ªõ4ñ&ô¾ŠL®jH;‹}ñ˜Õ&¹þþƽNI&|Ë:ã]çZ<<ÈÅ„íY/—Ù”˜mã̃ OѤ3J[oX3Ò1ã.žpMÖfé%ž&óÀ2…™‡<¦Ï©n\EJŽbÝUe‚}|Dï­ç¸Ø“Ø Úwµïœ1Éü½Ñš;wÀ¨”Òp:f}¤nVož*™Zë¤^ ¹{mÒ‹"9,MbOíÉF3 Ó¿ %Þ¹´Ù]öhˆŸékµÔ^Ç-o¢­8C²„I8‚¹Œ“¶œº^>/±+Ó¬Gm5ìFÖǽ\óøú4mÆÔÌÀœœÁÍãÖö€p sÅ7„®ûž #01ÊÍ,ç=õ$°‘ ÁXä±”‡PUóÌÍqN‹I8äZ#)U™¯µ(²û2}kAøén,k^t VÉëÞðæÞ†j^pçÇ–Éšt„º£b¶¢HQ̸·ö°OvóžùIRˆëI* Be‘™‚^k¿½:b¡6–ó~ND‹LlSL— —:±Û;wÐÍX2ŒÄ—ñ.ãžÀÝkpA”ÇïÙl¯s½‘9p‰x5o¤M¤BVw¸ž^ï”z“õk‡çþ‚à¹yc¶Œ9å¹´G{uì‘q¡ÑÔ¡æF%öŒeØhQ5 èÔ?TtD0%Ì§ÍØaîÓê"›²†f£Zàamu“;Îni±ÈÓ“_.|¹dY™HÛ”öØÔx™ráJ%|±Ug{|tsƒä’Gå^Ã_ f-ßyÉdÞ60pSrW}+’ z°ºâí WgzMƒ/KKŸ»ƒ{׎œ-áYU#¾YpyÁ©³ 1ƒ“K» 3ÁM¯ 8Ú hs—îŤÒDnH“6\‚KÃ!ù•¼…òZhl§ƒRã±8}é²hÎîBB#ÏäœeáH I!üÖŽH¥cÇnÅ­¶G ¼Œb›YÚzŸtH ·v¨ëñKÑ>J!“NM÷§‚g¾~]Žêë3~cöäÀàíb>(I|#§e½ù¸»óÕ¼§Eà“-n¾.uÈVP¼ãvöfݪóJw¢-͉¡”y$VÇñ{¨Xi×ÁŽO-vCdž>&0õ޶}­ºÁÛ]Æ~‡Ç@[Û æ®t¸4×Þ£×ônWpnߨÔ3‹žu'®«ô,}·Çƣ췜~ÑàoVûüNM}ð„ïá3ã|c¢ŽA¸qÀàë[…€]–w¦‰÷ØîPèX&Š ·lÖº Ø–MŸÀ£w-ÝÒË2ªÙC‹Øf—“>}(wHï©LÇ=™ òçho«k2&Q.Ÿ B)¯UÊ wPdIô «a4-Úˆ‡‚\Ûh7)=ãÔ¾§[¼/e¤pƒaÝB/ýÆÉ.åE€¾8|`¶Øû” c¦¯o48 ½AúÚòm’1€ž 6=QBÇ+Ôз¶ß2ù—Lí>»djQ?)«+ûÈ_ðÝÃÅÎos ‡8•V£W§V©MeÙäj/·3àöÅL9J;:™¼­ÝG›êþ@§vÏUeô®µ%I·5¶½nÓ…=^C³»$M'çš¿³'À~÷°“Ûù@d¶°Ï´ŽerBP=BD2oÓ5‘¢ywp¸¯Meˆ }AOÍâ)³¼G@©Qê¯h»0rçM¡ø ë š~PÊéN"Œ•2ycç4Õ ïP´â#ýµá£„ñCi™œB¥DOÀ8ÞÂÅe…<0¥Ä€Žk uèP,ð¾§³¥–‘ltOÃoÊyú^ß9·n »gmi&[ŽÒt°¾Æ‡u7…d§ïüÎ}bs¶[  U¬Wx­Î*ò Ú›kU*á‰]¥ÊÛ¨×8#˜„Ü»ð.Ÿ]¦Œ¨ §–Š5ÖK´=¡S¦¶¢Þrº5¦•‹ŽJxu¨¦Y`ü¢»ïÎÆÊtÎyßD\&i°I—lÚɼúeN+T—¸„f›{Ë/9“•OqØÀ·ð̼óyNq£¤?7LTD˜¹fЩ>’bQć¡ð-’¸‹ú9X¬¨s±½©¹ w³»¥ð~ï={¤Ý”ƒ•»§æ5u7U¸Oœ¬—B— œw3! ¯•m¯èá\T”äìèd=n“Õ®%ÐÙ}kÁ™Lp5þ¬ô4Pª¸ƒÞùá™F‡»Ç{f¯‡¸Ô½àÌ-©ŒsPÈ$G›û=í¹Âš È^ñÞ/›ž~Ù¸ünŸÀõ6 lG!È[-Ñ…ðÐ…™ 0¾Åç«ðœÈ ýq¯nNS•kþ¥ty®"Ç1N3Ük°Û›èDk~?ïcád§ÎcÓºaS;–=mÍl£ª÷S0¯ëÑE– ‚à1/¥£ñC×§f`±¨nõôL:BFÓ¼Ü268R4©¯ºQz¯3µ©Kð@Œ¤‘®ÒµæÁ«··Ùèç‚R×3…h4¢åÔ˜7œ#³Ä¦}`¯ìŠËfʯ¨¹Ò³ å±±‹Þ±õ¼BPP¤³åprGô ö|#›íp)‚‚Uð1mM%ª˜+=Pg^2+šŽi {!ytRXø®­-ïôÁºð”¾mA»y$8HPrÚhÓåpõ¢s^©`±–ãÑQÅ `™qäÌå÷8}÷¬/Y¤#¸ß>¬°kXšHLÈã©îê©{ñ^`KnǾâyí+çãkrúÀ|Õ5±fdõ‰·8XªÆy\ÀðV=,{¡ (42uª2äÕ¬ê¶XõpM XiÇÃóá>×Y‘çSr5XÎÉQý"ÔSc¤ÞREF)ŽšéÈã~ûSÃCKÊÇôx½K¹<†b_zéºE8щõkm{Q¯I_ùÛƒs‰Ò΃˜1³û´ÛÃtu«˜ ööñÓÇsÛæê9B[-‚#} dV(åŠ|9Âþž« šì½©Â'×ÏžZjç“5äŠð~"oä88à¥W$—}êÄü¥Ó{ôžA²—Ò.?a=´æ=ªó±íÁḀÊRàòM«+5„Â0•dY¾"ùïé).9'äµy` ˆËk7pvÛø²î:°­@ qšâ]Ãb7RfôŽ>®NÎ÷Ü`ÊNò¢…¼êë—o–ÝÃ¥í¡7=ŒŠ¥lªWPI‚×Þ‹hÚ)"6/õn]>ì¾È+£0|Ï-­÷®ôï• {‚ß o×SZÝn]R3ÖB& à|Óïá[†‡ô¼t ÑPµžñ¥ç:3äoÜ´B,÷›©Y±gàO•¹ŒÃØn-^â˜Óª†Tㄨõab¿~o÷AtqˆÖ5“è-Á]ox]OÎÃm™Ødn\1«.‹Pë’GÖÝhà[”ëë:B^?Þ!¯ ÷õˆ ŽƒökñY{¬StÄU%¦ ¨@Æ2WøÍ)0jp=8;b‡"ªxÙl×2KݳE–lM,’÷VøŠ „ºÄ‘1ÐdA QôŽ+GóÉœTgÂUú¨%:>8DKˆ»€rSH2E®+5•¨ƒéÁ{eƒˆò=¿X±§#“£ð=9†hD]±ŒR3&ÅdŒàDû©´´×‹4zYÙ›KV¡Æƒ|ÏS ‡’ ù¹)¾A¬L1THÁw\Êh/íUÑôå­V*>½zŽ.†$ЧAâ¢òÆ™÷öbÚç½&c ÝÇþˆÛ<È|t¥HÍ›oܾ|úòI=H.”ÛÛ¸†¦€rÜYºžç óó¼‡×d¢÷ö¶µ•øV?¿¦Ô |šþ÷·'ôm_L|¡¯F a/²Ä£'¢ó;A6ÁñÆ@U¤±s0ƒ 8dE`æqŽŽ‰pS÷†™Öƒ:èBÁH·{Ò[UðÝ·{:×8<‰é}év(ûx8ŸƒwßRGFBb… ¡j„î¬,r‰LŽP´gDUÜ’º÷Q‹¡4Çæ7lBÝÙ³ð“}Jz{dÝ­9 #©,s˜¶RЏ€vôBW]iú> í>(OñbFžuç$¼ @©@ò;k¶¹3£Õ—cÛÎVÁšª¥Ëó¦=}û•€±Ü™3>ôD©TŽR¥Ž¨°w¼Ö¤]¨ÀÃ`¹!½¡Æ kðBE¼“,k/ R޳= Ž¥\¼\¿„Røê$ç† ïî&ù®î(4ªÔídy/Ô ‰³Ì–O+pÙÔsV#“é«ÇIÙ·¡ý÷æîT^$"éÞ[˜»d÷áeßá$$“‡äÍÌÝ*ðVnÅߨ]Ýpѳm¸ÌÀëâÉèß>ÐXçbcLn1ÑQŠp& á¡ùLæú¡èȉ.ùß«a‹§€ ¯:"êâ©Äè»W!9‡'‹Æ1'Ö!¹ÒêoúžmÜSšÂe1_߉Æîƒ|9ñV£œ.€³ŠØ£À7w¶f<ÔîÇœÍȹªá®Ïg`ªÞø¥¦¼Á3’D“>GÈ À¡˜~µ ˇ‘òÀ»ËBŽùhû)ëDœÄÐ4N¶Ì RY{T­wú)hž+Æf¼"óéiÚàÇ"‡æ;J—ƆñeLÛÏÌ."ã!ž³ûk§tªÅŒK´]ÁY‰Ì2AgG‰{õÞT;‚§ QÎóx<!ùRF|zÊ—Ÿ :DLÔK¹è,ô †‹Å¢©¨S/Š&'{µoËlÀ¦uÙ]½wÇ…“u‚ó9Xï5ÝhDö•Nƒͺ½žË\ƒuÁJdêò €^d7ñ> x«-¯MJ„ÜQJ)¨Í 6tbë ƒnÔÊËpHï7>)wDOÇ'+“.o)®H,'‚!ŽÑ—A\üj0c³4„YÃãzéÚ$âz.Ä£b&bcÔ‡Hº|Ÿ{мµ9õ o,{"%ûŽF »Ýò}õý}=ÚYÁ¾ÂnØÑ°-£¥¼zG³Å aÏGaôâ´[`Œ#ÓöHy©jtZœ^³dú¼|$âôöj¹³•æyòs/¼‡{ÓRóF‰ Aoá'ÃÞ;`DIN‡ º× ,m¡Öeytï¹ÅôŤ¬åœãƒÀ­'¶ 3V®~Kc(Ä9ÌK¥“sROáò4ŒÙGÆÊ4‹ÚP…_B,ɈÂKß\ñ àìK˜^½;À#!Õ³ªºzŒÌ¢Žö@e4qÃÇgÝc ŒŒ±à‰UØpŸ?z‡ðFŠŒ2ü…¤B†Ð3v:€™"à÷(؆ |¢\Ã.z…"çžD43,?9>xQOðª0¼î)ÌKtVÔr{kûñ¦,n %JmÕkËQrÚ%t‰‹>·ñƒ¬§”üb[ž0oq”ìP(é ¾÷N, =4õ‰] ”` ù3ô¡´¬ñ{æš6G%H`Ô‘XòXìÈZË%’ZC´î2-@GX[Í\K}çÞÆëVh õ/¥L¿”Bã—f$8ÄdÍ÷K飞×ï]”tÏ™ ¯‹ópÊÅÕØƒês6Ò§\Q’E‚U9uñÞÅÆ5?¦²êòâ­´Ê“¡F'."«JQr#5–Çü65J #`s^ŽLhg4Ô…Ý&Þss'6§%æ1c°}ëoä„,ñ¤n¼í¼ –O»9£ûñ†f“‰›ÓcfÁºé‚Úʸv7 éAÀH_)xË¡ÉdJ7Ý•º-öFŒájØ„Äã ôp'”)¡5é‚0¼8Ô ÓδÑP²¯‚VXŸKhVŒÏ´ ¼˜M<žå!ZÝ¡0 ȱ7±ÕTX-òPª6`Û’.#-ˆ.%y¸Ö˜vŽQㄈaç{»yÇ{sâW …]ŠE«â÷ðVrAyJ©÷½h<~‘"7 'ÁúDìµ 0tIÕžÝóq»‡y´á%±q°jÕb#q‚¬úÑUên±¯™ FƒÝ2«[ÙkÆ ð)%¿\Œ 1˜=“ê»Ô€PÚx˜óhŸf ú·™]¤ŽËãÐ }þõ[+H9xPTŒáõ0z‘™yÍy¢`ªËó=‚;¢æãcGq—¶¹7p{ŠÈˆy+€?Æ÷š1W¥:—@㦱]_Ïà” L.÷ܳ¤‡¼/¦Rwl8ÜÊAl—¬Þir6¤19émNzKɉXMÒݲ¬õ#_à~=Š)ã'‹X/»TÕœÃsAœnaA»·[ßÝëY¯A‹O§œ¿œ¿¬Ä nž’CÓ˺; â=%Ëg=à}" ^•~¸x¬íPŒÂ7«yzm?½-™D9±çæ²Ú!ðØ¤‚|:i z(eÅØgª=xÏ.}û1k›‡UѨ§¢éKÒGùZZó™r&œ˜ZNJ÷äƒÊîÉ34†‡ÝàëdTjBHA·h@z9³iüž8n ‚Û øåúÈ(Ø.ŒG˜VE"ïxaËz,íHA½Ðv)2ÓWS'4¢´€Òs|´íðÂçjì=Á¸(ó@u˜d/n1ó嵋sûñHpVºæ­á¥™Ç#ÕæVÐÔç͘jÊ)ûr›ÌFçÉ0Âv*Šž÷íà›œs Ê”¸À×ìÏs1ÏÞ6©_Ì«}1GÝ‚ýbS‚ƒýzèù@¼´ˆ#Õ« (°cÅØÇ´ÏóÍ]Ù²¢‹ƒcý”SNú­n feÑà£AXȬÉ3?è+ãÙ=ó®.&ªšð·b¨Ç-j±1ÃXïVQXÜ5Uò’ÃP÷¼KR¶*9鹦J`õN=ÑW“v°ÔG>$Vó» Þ—›ël¿ƒ_;]“¶ÙØ›y(0ò&€>$ Ô›T­lÁÖèÍ•÷ÎE#_…<íyj[0äH[Ôó§ÂæVRýÅI—îtª=ògCïÂe±;˜9xŠª¦Šy‰çųÑ]”m´z²>Š}Гl`Ìô5U1À—U¶(C›Æ §Ú>—õÌ&0¼¬PgK+aóµí0Ç£ÅåœÖnŸy G¥R›-—«±Næ–¾w{]ËÐ^ýÞ3¦ ¿{0Êc4à‘»KÎx ½Oø¹Lù#QH¼(í6fV•ªEÎÕÕÄÞ…æ ÷z[/Ú¸Þ i¢<‘‡rÐd}Úk©Søµµ<9VëÅÓuI„ÌvÍ—òzžà¸Ê9úmH¬®ñÑ,Sã.aÌ–‚j»~jå_ZEF-?ÃW#怲ñ#ºáhüu¶è+3ÍŠ{~oùl(º˜ß¾JÜ+ª©±íDá*Ø®NWIÓƒà*sjï`ªbŒöÌ]=Ô¢ö4k¤wE{¬Ž NÝ^>_ ëHqs„àÐàÞ3I‰–W‡ÊƒoŸÂ6ð%snx×U¥úI…a~§¨ÔG£ù–ÒŽR«r²·å¸ø gŽC<# §kËsÂ\F~ƒôrSËÆE@'c x'É ¶á­3?WÝL‡”Ç)áO'¯í8P†é"‰ÝÀšèQÉ^ŒÏÎË—ÓÅÃñ.éfïÅ‘w¾b5í^[P€¹\bK¥ ­õÔ—Ua–|OΟb¶‹yÍè»'ƒÖ›ÈúrÁ ž¼cU{j—PZZº[—ÀQ«øÞ8Ãn,ÛAÄäÁÇ+òPE8€É"+¡ysäS7¼˜\ìèËûò õË«ö£Òx50&{[ÓD9Çàž!ù„éôÁ[òWÕÔÍaÍmÔ‡¼ûy &Q¦‹½î­#–0Ê¿Äj DSo‹}nZšuœ”uœ ¯ëÞ´:5{#,cº¹B<ÀC{÷6Ýê&»0² RÌV_k”.E“!(u{½syj7ÛÏižÊð(¬­¾ V¾`/‘µ}˜ÐY2$µi=ÝNã¥KMÞV¬ÅŠ5 ¶ŠQ®Ñ'ªšÏ1xm_Ñ2œ…–^ _ÚácU.ß½¸ëTç¢Ð!­J¬c¹·SêÙ-mÑàF\m›}¤ïuD³M/x¿dOÁ$Q‚ÆC­ºå^L¡T(žQxB<û<»©V…NpŸ¶Ê{ã’Vpz“ËiëܬÌüVº9›]@ú€i{ýª8+ PËò^ξ%>7œ¤qu|‰í´JýÄà Ñ,Ë0U¡ŠÉ9¹ðÔÑ”p÷–X»5:­!nU3 ¢JÖZ"Ÿ,B,¾7ôzï.–Ÿ×*¡˜eøDqÜcXÛÏÛ«lݳËÔ.’_)L>·R´Ñ»óôqs|£{/‘)+ªÇQâøJeŠXQ‰äНõéhãO™Ø*[<®4ë`­²„\ióA1V•€®É€§B9jφ 2P´h@¦<²2ðxð(d(tÌü­ºÑewtu1×)ÁG<'&lïzN±&ºZŒ’÷šôBH^ rU­hÃãG✰—Fª¦eGækÈh€£¡ŽŒTsàö°¹ y³®¾Ä"þk.µ5)Ár•É´WAâ†4˜©2“¼µžÑn6ÇÈxpC*a5øÆÀzá¬Ðßfåµ¼n™ZV ;å‘ÒzV‡S63 #¼“æöÚlgÙžÙTËI¥7òÈ'Õ Û›•w…Õ• 9¯XHÒl0„’°RVL²"Ó=c\(1—‡ _Õ–ÕP<Âg‡¡ ¢Úä܃èD{ñ¼1ÐôÕÖ ÚÜw£—c¶i$´kdá+Å=÷ÔVBêjái³y»—C ô;«6P=îZx˜®¦ÌB‘Wµ Özi¦@Ù{‘údö^v¨•â{À0˜ª‡w"á½°¦yž½ z täè{Þ—wx¬)‚%«—úÁêuê)ͽš™½V=ö†A®­z®'•ÓI ãì{¥šMó^¤p&fwI›¼ǃÒ3§ç¾VNmö€ïÁÂ+™W× ‡%(ž;ÛYlö@¦&ð&ñÓcz'éèÍŠ0*;©1Ó2aVGºÜ1åÆG ”ï¤V²¼¥ zªÅVêL ž™úb( dk˜²”„7ëè‹¶„™‡eÝWîËÆRGf* ¼Éo¦ÀùÔ½œX0‹2Yø±qV&˜C<Ù5¶­âkeÕyç믱Èö®”oÝa(mÄ0CdzøDFÎU½.Ø'Œ$Ü0 ŒlqUïá¶žç­”2ŸÎÅñx&R;Hºêñª³ìZ²¥;çIèx"‰ßÛ!Ô‚Ôf{:¬V»12Œ\l2ñ„Ѹžn˜¨Hû—Y¾Ì‚it|Ï:¥Ñ­å«cºŽó0f’è;•'À£ xë\˜v7]lÃÚKH©®UQéYØV:šïýù6Œ59.ã»bî QsE!-™ qžG•’ê¼Ù1ÌØ0½-N6ÉÛpi§0ä:ýÄôxé^¶Ôú‘m\R ôÇÉŠEhX+0¼&忢 ×™º[£ïT~q 8x†Ï3(Øžòˆë¨õ8²mÚ·&àžRæÆ¼µÐLÀ€IY©Ï¸ëí{Uc϶¯Îa—x8\Nñ–øvj¯žÛðNçâ1Ī‚aÛ õeÐ,˜¬âx{ð.ΪÙ0¡Ès äËÙg€¶ssë-XÜOrKÏÓW‡GãJžoOJ_Ð#I;rX¾¸¾žU„ îJ7'Û Î#b'Æ×|q˜³*¥v¾8–KFðàyÓeŒÇMQ5:û¾µnîáÂãöÊ;E7ñˆ²ØãDV/`~Ž—Õ!¦`P5â{¹‹Á©ì¼âü”+¯ëY¹ø/&à¦ïÖpL¤Hbœ„ZyxKŽõÆ;^¡^.€±fZñ1l4Þx¤-¹¸ u5^ólª7ž(!qÛ¨¿)bI>ò8:Gb†ZÚ!/àȘj“zWðj=±"´–™ Òß4A>¥–0ˆ½›~çñ,2"èÕÒ•ª ƒí>;®v°·/ÔÝP5‡’EÛˆõ¥ÿ§tJ™E‚û%ºÞX$u½ôëj 5BeR'eM» L2cvö¾ÔbøRk–\+™@× @ ù®°çrk6p(ÎYá-çÛj`u½ˆdíXw¨Ðc'§uGJÒ•t±»V±8}Æt¹µE¼]ÚÑÝ“¸?÷’Tý•¾ä×éÊK/ÓÔ19Èò®Æsv ¸ˆëŽv@$v]ËËg»uÎ"Y`v—Á„­*›pÂÆGôàŽ¬ùÈBM2ÊŒDŸ!»ht%PÞ£ôã2ã‘eUË•à¦n6ÓÜJê´‘Só¢„WLšEÉV4ÄüYß.)ͦ\àëQ®ˆµK£‡ìىÄ9/òé¯+£œ5(·‰ 𲻇ìjª…” Qd[„ªgäì6FHP™Ù(ˆ‹•ɮҾ!; fÊØhÊ@·³{3…Z–ÓäýÞ‰{œÛǤâÊ-?Ì׈8©ƒduí= æ¶Ezï‰ÃÄéƒw4TÂ̼¢é4ÚŽ£'bd¦è€iƒ˜ˆ™EF&N¢7&ç Ö8ø¦³Ú(w_Øáëb-%†Ä&¬]@ÒÎMìxšŒ}Ê^ ;– ¸ð¦Kp©Ùsµ;ºëc L.åœæ¢ÎHAôáR _·Æ}ÃMª¡ç&LL„|¯À´}³½K_^/$¼R}Ú#ïà±L¿Œ[~+çM•UÔ@2ÎïlD}vµÚ”æO9”çCŒéÂH´>¹E}Ñùð]oöfÉEeÓ k?±¦  ‰¤ŽÎðä×âDÕÁh1{ï ²&*ª{/ÕÁKÛ÷¸Þ›RÍ7œ~‹6tÒõé–¾·ºÑAŒ„ºî]4¦=Â÷DG†«1²)qÛ{v×R —–`óo ßK¸Û¢°™2˰ƒd”Ç6¥ZÊe‚@¢Âã.*R°jæçiT¤¯À…™²øxÐËëj©ß•£õ‘·‹[v–.i¢t*Oò´Í8p ±¸–º »s€™¦’‰Êù uG(ȼÅRøå+„A£GEe×\޵)šº§œ3ö²‡ttgÒÜ…}*É2UëtÛ;¡[áw ʽê`ÏÛ¥µíwÞ[-š€ê´ª Nκ¾3Ð;.©#9i–!jLÜö8¦ŠzVg\rì×-B%ô>…0Ã(A®Q ’xûÞt Ë7 >ÏZ–Lº=¹µ%ÇžJ½d²#¬»8T…ɱ~Ñ29ê"kâ bVšéD§ÈÅÔ'&Ši°ë„zÑ=ã…pOY$IÍúâ™h¾}°´hÍ ù\¡P1„#³ì•ÐÚÊc(¦­ÜglÞãexq•g3û´ÅX K,Þ>Ãx;ëÈï¢óµo=¬“{˜ê¸ëÇòŒÇ1Íxã¼uWX¥D­ºÛl<ÚˆÛO(@õ˜:oÝK8e½íªå!¦5¿D¶x’dEã±Á›ä¢Aˆ‡«±q=˜›0• /àg²TaR`^“¸x_Á¨íèƒ3½c]±»2z:"/EäáyLÐn6Zk‚À‰k °jBúv-[F`qáÄ•"Š$îo\•J?×—$÷jpb{}Ÿð—\¢_r1jIOÇmÖ<Å˺F‚6ñ­t¿õç}1¯ ²I8lž¿®µrIÍ×[“>Å+ÂÑoW°J¯K³qÿ²Káõ•¬¼ñ×=ÛEÔÒ&«v2—0eãÆ«C³€,"…ƒ&Ê4ØÉÍC {Š×­Iï©MÇÝzYDß>œYÑÅ¥sH™D)•„ŽçÔf[»¾júì1H5V_m[XWf„'<”žÁ:ÕXEt‡Ü÷i À ña#-6·pÅtyM€6áA4ëseûmñj x¹Ðµ­Ž9þ~Éuò®Øvœ€mƒ\ù ¿)ÚÓòWn.äÑtY)¸¡Tf&ÜŽÝHòf¹Ïûé é»\ŒÛlÂ¥`d»êRàd¦›^›ŽÖ1<óÁŠxïå=†1PAw.S5%Ù\DK…c®“ÞhØÈh˜4(·[.irØ—)êÕº/ÜKØ@)¼ú‚^ˆ¿{ѲÇ/VKQuò†ÁÌY•–-¨O®@£Œ%Ö¾'nX³™ÓªJMsCÏkñ"fØÊm*½$¼ä!àcõM9”‚¥ã7|¼—joÝ3çXŒR Iê•…¼æ;èô{4Ïø¦_ãƒîSÛ¬™‡rk/`NëÝKkÓÓè>t\‰:ÀœÃ©{©æÙwÌ-àB “™ïÒSª½ÛhÎòó`1ÕNáá´9̹ø; ‰“¬m ´³=á÷Bž31=fa®åÞÚƒk8ðŒŽˆBÏ” ™_K‡9è½Ï×¢ò—]Òryª÷háü!ö£õI'çäLI[+ Ñz]™תϔ…¯©\Ð[Y€Ý6‘ë:žIÈŸ“ñ’æ<õ}N²xÖ·ã9\¡kºÇ$5„ë0ª\i†9Ði£| Ú»„öq—½ÀxRz2÷F†ó>|Ç;†`ÍoìÙj ÁرpªFˆjg…7ÈÁ<,rÄdßJžŒxZкᯟˆMß =w—´®ÄgÚ“ƒRM·‡køz^vºÞ,—¢ÕíCÀ‡™²ë¤',8<×p°5›]OÓK³BÇÆ±( Ï¢eü:ûÒôÍ?Å¥‰mW‘˜3L'S¥= ×FáÖ'7™Íô°Žl½•sö]”àͱ™T¨¦6]ê¾ ¼(‹™¹³§oq•ábœÚ)¡3nX*H­Ð"¼éÊÖ‘0¤ó Üv²¹Øì£#xV/C§ÃnJèY¬¡Ã¬³«“YŒÇ‰^pú¸6(ÀJ9¾—U~iõ˜¶zÝ­k6ÈøåÓF>ÅçZ—¢JgIûb¡UNŸ°ù9¡5nØ®Í…Ž®"¿@oë[ zºˆƒÐ&ê†kKF8͇“Wh(xÏÀÃ!RØÄ=ÏzóÝÐÀ€6<í\>Ór—¨w‹˜/îwPñŒ$èÆ­æÐËíð}\\À¯ ¨sõ»dz  ì kïž(dï«q›0n¿ ™„V_Øæ"–vŽª­à|!ÈV'̆øv_!çu‚¦Ö=ð©…—þ¥—Ñ—^†j‹ T‹icîªzN/—wïÞkÒ”>ë]êô‡Š :MKhõÌ9!³ˆ9cGا/§9+âžkþå×Àõ yMz.Ù+Ÿn™˜Îã–ʾä‰ÓÙô³‚Ò2ÖÓ³@ÞõŠ&Ùê \s,ŠŽ˜ JlWƒ@²d)ÊCݨèt³}Ška‚X‘ˆšeDcëSKXho¹U-ƒ/Ž»nõš«^¿-AC~BÛ0µbû zã‘ ÂÜôTÏ£FŠ©náæê0:5Q²PV½¨n{SÎÌM»º=é¾p±cáA5¶ó¶7 ”Ù!a¸ Mï³wÔ ¢ À[ò}´ô¡û_RàÖ)—têχg4b¦—p,ÃÝL(¡2ù¼SS—$ua%ׯ 'Ä{B-O‡2¯˜øåÓ@Á} Ö#tèîQ?z…çI¨y¼ŠÈ®t[ ‚Ü4t„.Ñ}§dQ>èÞ(oä–]x0®!¢Vo¨UíâÁ „;B¬š÷jY?á‡Æm˜AJÓââ |Ùc Ý®Vmž;Û*a@XüÒìÐé½}Ä".¥ŒoçyÙÖ“×§¡lo›÷˜ç‡THÒÕO!GG÷¶<”YÄìš pÒH,Õ+ Î3MÓ59"” .;x„¨,<ÑâíÑ¢/öñNôu­¦ãªLÖ£¥£cˆÚ¾§²4c¯lPZÎ63¬Qùá½OAŒ{“ÚâÜÍk¸¯Þü'Ø1Îzç¼—ÌÒ,¼\ .2‡Û,’>"=Cï@Ä‘ qlÁ¤–šÝ4;,ê{gog¨qÖÞñ¾”‰×jÇUp]2¼2à÷ŽG›ájh¤GôØœì ÅÌ1XU’¹ðA6¯I#¬,ëƒÝs™c!’&lé(Ó­l¢æ-[ƒ5P3ÏXE´.';LܰJ%ý;¿—EANYb… ÆÍhiÃüòõ6]I©QyÄ™ WnÉÅFÍ+ é·O³”hL¨WBM`¥ — %ÞÓ2½šÓoÞrC ”ø zR  ööêžÚbXê•Ä ƒÄôK-ð-b"ç=fº—ã75?Ä Ñ­–1mïÞéI½FªÚ‚‡š°¶x¶¬OùöGX?ÍeZßg+|[3 :»fʶzÄL“'»bT¯”ä¸v‚«EçB¯‡Ë$°mñyUÁ10Ç:?Ñ'rojƒWߎéf# ­ <ÔRÉuNÔ˶}úæ½fG”À〆’M¨^ âG鯼dЈˀ«/œ"€§êdÀ…%ü•Ï™iM]‡¾Þ|¹²{ –…÷òÕ·Ä÷Ý]‡5™­õp?}–Ö}CE]g1Ia×èiž¶¶z×kàŽkÊìØ©ÛJ$x¹z‘AÃ4½¦ä‰üHwjŸ¾c‘H &7voˆ‹º:‰Õ+§oÁüK°ÐAy’šY:$DÙi+Žèϙө†.PÓÞÌs›ëÀ¹Åb=y‹³åéYRÑe¯à‹n²SåÜWj½¨Xþ¯aÉÛÛ œhé*–ó´_±"ÐhV^éQá)—Éœ5FœÉT“.¿“dC6ï38®É8ÄêÓ;Ú”†+]'M]A|§÷èèt_QåÂ#žÀ†¢âÆðw3$w0pس$ÎItÍï(¬-Â)B ¸/KJ†™¹HwÄs ·ƒ,Ezt ¥ ©û¡n>¥dLOÎTdÝê¸ÞGļ§Dy5÷Z L Ãzà¦2g9†¦èaÍ™ œã»ÀmPíNyR†‹yVkwÆaY Í!„¹Úóž²H¬66yÂðƒ}=и¥¯øE=}ë5„™†MKGSCó8»hÜ_— À‹ê'gmaNˆ^T<7|2œÏ¶¼Æ¼/C€eJAìiÅ骷-ìÒD,=eMˆKvà2j³y¹çË‘z z\<ôv MÅ.^Z±&Ü&š*³¤’·NŠ…+$> k'HV'Û,±Hö‡èT.¬†ºÞ…íí8,ç2÷ÎqÄïf# , |­@³‘áA Ïe¬O QV›Û:”ø{ ®4Öº–Ö‹tÊþäDcÍÁ¨Õ¶;XvgqÕ,‚ô1wè-½@ð2(çS¡DG½E^ïÍž¯¬F«RyC4Ì“õÜ..k…Zh$^Úâ^õÈ}E±Ïî¡ O?=mÙ —\†bÖëÐDú潩Š(‹›¶žÎ¨>zQ¼2«/Ìg`Ϲ1Z^a”ëµÁj°ȃæÆç•àŠ)È—b§¯ígMl>CZíˆ9,pçÉ;JF®1=éÍÍ´ <ár˜%I $”eõ|Ø|Z3׆%|”ùáº4ŽTþçØ{õ$l¼9˜kž†sCƒ„ÔŒ“‘§”êLw› ½µ·Ùp¶Æð²µ™Ãø‰,Y§µ‚ ï:š®ŒÄ—­Ió6-Š}"惸b^ª]êÄ<ƒ,·Ñ‡¾,&NX/¶Ä-Pð êÊúÙHñjñY¯ámM-D³ à<[5e\¿_þBÁËV:Ûjçº6ת‰\žU{l®ð´Sל•4?›×ˆ&¾EŽZ¦`Y#ÌQ¤£>¢= ËšîKŠ7Í2âcƒ/Nck€¾Æ4éEêQµ³Evwí¢š­J0¶§úz]bË-Ž;›ÝF±‰ÊÌré®:¼0™K “@¨ÓsË,åP$f6Ù$èIÖ¼ÊÑÚwæf®vNÊ!µ¯¤l¨}Oì*r×óUÒ<°ï‚j¡(0!£Æ„-V’;c:E}Ú¨g'É"¶Á]²neŒ•d.½ %zC ‘ôй¸Ò²×WœÜl´ßhOùÔTÄhlÙîÝÄ"‰²ªTøEŽË-f>ãVdÁí&æ`}Ó[ÏÃòÜcM:mÜâ7 !\­€R}U2ß=d4.ÕĬЫÊhœ¢¶áØM¹üáÝ%éÓ‚yYèhè«Òò²µÆÂáæ…eÌ”P?Jñ÷Öky–âË1¤/Ç6Èr½ ÏVŸMÝuSZ¹·Õ<Ó ŽáÁç5{œ‰Œm¸Œ+ÔsyR2ýó7ù-*ìÕžªjIc—€pŒ³æ#YºÜ÷ŸdNum¬ù,ÆÍÔ8¬Þ#¾«Êpó‡tôšß ÒN+V/çÀ…o†É‡×~ðЪB³ &Úð8_µÏ!£>Ô Òí«+G]¼~Ѐ’ëž"Ä8“2—¾¬Ëg°©óR×$ýf)äd‡–7œB&ËÙ‹ÚŠ/¯‹"4_ž=³H’«‡ŒNÌé4í,í\<÷\R«Xz£‹oöE^×¥YÃ$ •u‰Éih­|Q—O£±íî¦ÊYÈ_»’¥i.Ó2¿¦:´æÒ%Ñ÷N ô°üº2`…l«¡;Ê‹’Ê E•Ò—˜Wi„ræ7`o"ƒ2 é%¤Õóuup2W{]ƒI¦L€Ä\²µ¼ŠOrò %] †ívsF&y&%Å=t&S´tÏ%bƒß€Õ­Í¹{¼tòiŒ‰œà6¢2Þ'çè„-àjÛ1lÝi5×Ýû¨—çK2‚/ÉÐÖ‹Ç/Ü7ª@f£ÃŽŒž#v<î•T +y:y÷¶Ò”jŽðæ^ÓñÅ=.} ï^ÒѾè›ä¸äà9ÌøÏ23$[z“Þhe>°cºqòZÐô2…§e +ângšy —  Úå \ÜRÜ$^éÞ‘cLxƒ¼ž>Os“UIÓW ¬ÚOû½Õæ‰Þ‡×ô\ÓyH¥B™Þ+2Ú…Ôª7Ð$;ú.wä¦ÂFož¬íí–fl̉·a´ø£>.R´©"‡ÇôxÉ‚UdéáØÁ™Ôú4±m6pܰQºð4›c¡YW“À“ÐEà vx·F|lâ÷"ýj îî=Ð'&ë€ ¹#G&T‘ÔúëT•Fá$FBðÓÆFƧeèXîN ût×8ƒ0¶«/C8†&R¡½¡t„ €ÏÞŒRN]œiT]ÚØó* ÷G±ÛSÅÓìXŠ7 HyÜÆiE<)hb~“œ;ˆJ¦µœ"3wïÜ'žªï{ÂPÁ2¹JQiÅð ‹‚²4зH EÃU¥¤ÛÈB0úJH½®Ôâ±8ëéQt¼^x⾸©-ÛF-ÏßkWÜ€¶G²oE'OÅq¡r÷NFF–v·ŠYïQ8„o<[q{ðÔÏ9i¨'1åYâF@/H‹Ú»«ˆÌò š/Ò<ófãáL9óèyÏïÅ>á…*½`]Ñ‹çÓE¹ƒ4×Ó)ª¦j‹q¤#þ\¯äáH ÚÓáryBÏl´Rꎒ/>-óÏ×e ÉnÑkôDlÀãhU¯çé å>•8M)´£K Ûßy‘¨Ã–ë">”K>߬«n|aÒ%§û¬(ŸéðÖò»þO³½ÜŽAº^?Õ³}ï‘{l£È:LãêsÖ°'(!L˜ÎTòö4*|I„&Â`&m}iU5Ó÷…™¦Ÿ>”Åwë·“ª˜Ýh‡§°¡Îqw$ô¦q½€,œTÞȈ5âŠ×ò¹+"Žò1æ“xÔjú¢Í± jtä¥4e(qõ¢ ˜ß;ò鈦ˆ=õ&$CYN[‡­¾=Ç–…£ºÈÕµB˜&Ù„¨©–çŸyôõQVÈ{"®AÒ¥oX敯(oˆµ>¤ ×RñëvÆâeľ»d4 AóXî1‰æ“7aÀÏAÚR.½! 1ßh²žµdy”I?VT¢äUŠÅ¨Èy÷ºYì$Ó»w¸6ž*òK²€×7ï^naê㌇-©Ï S9¢kMèÁ$^&›Ìôd?m•W3e€xd¥&Ý' ªÓàÕäÀ«   DbËïM«Á g¨;˜ËãB¹}ËqѤ¾I/&|Ž0€Ö`F¶€ÉlýñpA“Ì0ƒY²[ #®:Æ;’<‡KTsç„MLo€TaŸ“"d›Žá³Bˆ&¬&lû ÓX£•'a7‰´È°!ZÑ­Y¾è*:ÓÅÁ甋Ðý°VqFä¡/ÝÆE?Ð ©¨´¢—¤«:IþTÝÛwÊÝì²c¯ÞEzì¼GÝæŸ›Û—fYËò¨TöÑc©©|¨þØÄ„[ް˜¯ªƒæ]v$kË2ݱCW¦ìù¼!LBòz§eDzÈÇÑï®i­žjχ*½®À|ö®MíBoä•ÁJ˜£‡n-8ÉœÂù&ˆC)l1™pº×ÅéÉUR¹¥Îu8¨äÉ ’xON`ðìóÞ‡[Ï–){fBΊ^)ªO¬ñ©3Æ3•ö Å {~‚{v¦Ò™]p”¥3†RUL³`׌óHƒ!ŠxÎKÝ„‰¶hü8Þjò1I™ø3Cª•Ä–W`÷Z«-&¤ž÷åÖ#‰KŠVª)U…~EA¶;öN‡i({Ìw8mÖ¯ó‚_ìÀ„vHu8êÝ›ÒM¬&5Ñ=.ËGžwÒIÐvNîwp'õ¦ÎÙ“·UŒ³Ü»Þ翪 yñ2|¢²!ö1¡Öyí oT&C„&‡q-Ñç:®2É‘gâñ½Ñ¢æ-^+ GDƒKEYØÚ‘3¯Æ5Ób‹‘y25›w@Qš_ÊC’^ zôdBÁ^;ÛN¦$BîÃu~ 1µ2Íêsbþ8h"в×ks2LÍÞSôBƒ×¾ÈõNêz/qdÙ+ª(¶ˆ_E·Ù=0Ö´VÆÚèò€\gîy½¬ÞçØúL‚¹rü)S=Äãs÷Ç;âé\VÔ ¼–Ìç$·%Ýý€Ö©÷®&Øï¢ölù%¶X˜-qøö€> ê.M/˜7ÂL¯”Uået¿ÓKr»Øl²µÄ¾r›buÆ{š@Éûü¬.J¹³µcqʦM÷±ÖS‰tÞJ8½{%\lDê_ãm k¨¿¼²°ÈÀÝ ãÉ),S¹O(¨ŠâÑš±Bõà{¯@¥Wu¶Ž™\q!ŸlÕñ–=éÂ{«xá xÛ´_¢)}ohíïw.v†×xk9uVªd;“ÛùÛ0$Ï•YóìÐ9]¦h6xøjXâÈÊ)¹u¾ij\ÜS«'Seڔ͊áxSŒÖï¥ügZ€rú=ö4oô.W™ÎjPè Jë¬øU=YÃ@§j$¼·$©ÓЫñêpÞðš ¢Kˆ(§›<â|ÜKB÷П#¶;dŸ2¨³Ö Âu½)C6"xÂw*É«w¤éQ äcæÐï¦8‹RÕíN…¹÷"ˆÙ—‚TM-–È^$§º.S¹7=Qª}Z³ŸG‰ñZèÕðiE…ä:—Vpo=»*¬'0[ï–½:A“«JÑ6òv ϯ7D»\ÆëFq/ð¡KšµZ1&ä•Ûõ$Ýû Ùôxß YgÖ»êÊ1šÚÁ[jæ#1¼ôˆÙ#'ͦ†Û Ÿ#âBF| †‡ývû·v]:£,ú¦u7PÅØ%½ (¡Ãy®Ž|{‹$q¦õHGf5ráaÊY d&Y°žÌÞ\ò3èð®uÐT˜­b@\Ô«uè+,+B#@{:'$Ÿ[šÁ—i!÷:}1Uˆ¥m”»K£B{¥·ž;l–éí ¿àŒ¸µL ävã+DŒÑá“2÷öA®È«,ï» b§ñ|ï$i\ËÕ<úO5zu„ž€Hª(UXÏW2í=~\Eï.,5¤Þ!tã@rðåS>á× ¨BC¯‘ø”ïÞØ“b?2xe¯O0€`Xý´†k„d8NÞ z»¤rëâcÓs¹¨eBµFÕ¢7\JµOõU&¥³Û°úøµ‹KV%ÔZ·ð„ÚáKÁ>ÇéÕ}ÎdÆÜÁd RøèƒGjð\UcB$Ú¼“‹MÊ»}L¾ñ`2¡‰ÜX6Qµ ÏvÂÄG êÔ¯£gJThBîxr†ÍÝ»>Ó^ðt2Yñ4GÀhMß³}7zá Žì%‹ènJž;L†ƒ Ι3œ'g²™ÜÙ¼ö6¦ÍáÔ 1®»‹›Aûž$Åcßã»>.ñrÇó‰£k¾WÄ^j ¡ãˆ šñߺåš&u:½rÁ-Mbé’Ž2~WÒ:@¤SÒF“Bp<è¡W´ºœ<öìÝã›j¯OU핞U­S&­ç´Ð$tÅ=ô&Œ3öe¦R üÈè]gíœ>H‰å÷ «OtwŸkӔƀÎùHú*ŠQxÙÖâ,i%‚ÇôÛÛ³ê%*᫈ݬ™Ìgj&J§"›éÚ+ªQiΉD½Ï‚ ±Õ$ŠCVät¢xÇ…[ò[Uªi©Ü£—0¢Çs¤¹®äŸªù—jÈ5äˆg;Tv wì¡Ù»ójϧGt _`5†$œƒXÝ5WcS1xa>Š^GŒ³ ~ž=Ý žNKðØ ¬gjõ6,$Çæ_×®—PÙ(•x^=»r¶-Q7{ÑêÕŠóvíl¶ÂCÊ’ù鳂ɋt0qobFõ’öRfŽ…)¾ÝA¡LÖ„'ïÀW—#IÜæéI¼®±;­£Ìì@´¬¶}þ &Zɹ]`½- 8¸Ï€ù±)ÎkÍ‚O]Êô4ΰ\GÞULÍkqv™;F@ªÑÓŒž›zÈÑܬ§<&~€"P˜/…gI@W7hŒùÒx—¶ZÀÑDEçˆøŽ8f×l3 žÃ ð„€;¬×™WŒ£îõ¡ÆÂ¸zó­ ùK*_ö­#[´e•â=ã÷d0Q,°PbÒTÁ7Ì:k¯ËVHùN¸NçåóL÷fÛª}¬eET/û@G ÕyrÊø•5{&[1S\@Ø3t¾*%À°Ùi‡i«„)™GÙ¦"ªØÍ^Äy xéjCH !*¼|§ó‹^ Ásƒ„ ÂÙªÜg±ª9q ñ¬ŸÖÀ—kÏ>]ÛèJ|‘±MÛªàïñ ƒÊ{ˆomÔbÍJϤ­ÚÄ{IÓ…¤W’lôiyÚÂæð FÐÎÌnÓÖ>T˜?ãœfâ·§¯9^¦çûO¶ZgܨӛÉLJÏ":!;÷L× iµ%%T-L¥tJ‰«@„±^ $ ߑʉ0‰kIZº?À¼tBlÑV.IlIôG׿:&2[:K, ˆG1`tÖÇáÀÕÌ "=ëŒÀ¨š÷Þ‡X¾wAƒ}øPˆâíÈYA “Š›`K“È”¿[qKÞz>Ã¥¯{ÁQwÕ)ow»Q:©i°ßÊc¸'í÷øÕ,¿QöI'Ê ,‡ðôÒ7O®7=±©o)â ,žõŠzÌÖ}I×èOžtdf\ÚÓñ.E…ðón Ñ &5x £\öƪ0÷øÅ³b?ÈM{mió?X~5ÏÅD3ÊÔ±Ù4Ö±Ëlìc1»ÓôŽJ¥2šŽº¤S~»ÃW¨.±cØ\t¶ éJ<çZ—Ë\Å`,LH‡M!BO£]›×œ"ñEŸ[ŠÐTÖI„Å›å£èŒ³]ÒÝ“¨èWü¦E"2m¸˜&)‹³q­ÒŽÃž2]¢¯Bá* o‘ÈÛ%èx0—y’`ƒù VBò)ª$E¡>æ«&|%¯Ø\ “q(¦ÐnÞRp+¶êª,ªè»€Ð€=ïW¯D¹—˜RÑEƒxÍ;Ú$ æíV¯1ªå„@o|2­Áq»ÑâÔ×DpG~úÞ{3#œ™]Cœ†éòx¤ûÙcÃÉß#§u 9`sÞ*ëŽ ÇD\0§°&f*A»«n]³£/Ÿ¾g”ÀrŽ78ᘷóÆrSãöÁLïcOÁS>C¬ ·Í3œõÖ#¡ 8„7“òÉ%5„Ëô–¾wV¼/7¼«{â9¬ÒˆÔì]ž˜Ýd¿¡¨ö P)¸ªhO¢Ô# ueS¡&‘®chèÆ®‚–EOŠî ‹W°êY˜û^.BáðvЖÅc“N zѲ»Ç1ôl'ûϽԌ'ç/Oûe2–VéáÉ­qñHÇ™K ¸ô{9Oʾl ú² ö’,[í1Ú›ÎÎrƒ`Ú1¤3½“(‡ËÈ5ÓUê2‚§sØš«r•2åðjI ó^qÍháp‡´-D•Œ§uÜÉî®]Р=<“JÂØú.™ø©gCÊÊØãV$Ä” F2F*›F f›W[uLÚÔ2$ÞR@€º × ˜¶úÉÆòñÁŽ{ysPׂ9 1!ŒŠ)ìù¬ Ö;Ûª>š ½w›=ð$)m…öjù5qldæÚÂâb– ×ÂÁ¼Qcyú"Ÿf§Žb—RDø{,»~0®ŠÔ.–;6EI'Ê…·$O]©ƒî°Š…cbìxëYI,qÜ#w°WƒuW…eæcï]„@Å€Pƒí\©•åeò»@φXYùM†ŸLiò«ž40§»ÁìÁ­‹ ˆ‡·hølî&Õí¡Â•óÑÃÚQjœ{~T§ô¡›|nnũ7¯NC²ß +½7o|4µ|e'lèLö=̪QLMÏÍ'XÛ]3…ïUo‚’ðÖpßl®¿×2b eÏc¼€ùÞvéÔàÆúÏ7 <°~È~f¬DÕ#"«ñšêùI;[´û“—¨ ºiÞ–[Îû5¸÷$•ø1Â(?âwAJ<ó¼ ÇÕ¯õO…DÞ"’£;N4‘98Àd? Qåe2.Zpu¢˜ªŒ{&ŠrllqO˜dýB¡®ƒ’!D•Ht÷E×%c€ñÊl#ó"l[Ð¥áV“{¹€Ì:N¤"_¾[›¢6¬–œ´¹™’’(íÜÅyݧ•vÉ‘´IFD®0rrðâ^°©ƒ‰@y˜q?Ð$yFѾäûÞ ¾áÈ.~5I³÷\^#Í;tH{ÕÏý…Žåú[ËC“%§Æ}ÆDéÇîjm*ñÞ­Ÿå38 D±·oa35çm´^$¾£n/Ñcð®´÷°³„å^§u'?LëÇÈ ª‰<Ú/0tjB"å:Ÿ5ÙÚèö±paÄÊó$IÕÛ–A[zàyXåÙüïs’ªll0µP—B„8¼Ð)Èœ….åÚ÷Ö½Ó9ÝÔxqýâ>ô+6´J^•¤º˜»g˜B»¸1ƒ)ŒýÒ™DH 'öåèõ¨£Ó«+j¿)H;ˆax¯Åq®*(-oàqe˜#fÏîNæäõ¾~°ÒûTÛu£1¯èÁ Á¢[~úæ_¾Àóˆ¸áf-Ï«0ëšeVdÓƒë§äÖ3î—Š—rQ>{¯#[R§zB_^½Á?ã²M•)s,ïÄGÒÆ€¹‰7 q4t+›_ÿ'ÜT+tgî¾³E×g+¬×¯Ût«‹Þ$zº{Î.† ×ÙÉ`1¸¯:IyZ«œd(ç>î鵂ÐtÖÑ}Jóh-"û€Q)æ1‹úféŒ]øØÓev‡³}1pÅù|]øÈÐO…ýQ2²œIÚSä)ÎB¾"6ÃaÞ %Ø´_nžŠJé1XƒÈ€J‘X,tjžCÇ//ÓÁÌ7‡Q+Él€Qiа\Á)-ùKbÝÓi!¥ÌjDeA`ÑágÑ&uÍX¸È8 $8r.!ˆˆüvÉyošõ6U¤™â­%¦ûŠ€K¨bFƒ£i& L˜ºÎH;™ªô: 7‹ Àûc"S8×Ç ŽÔÖ²f0´¼«³ýx襉ê>P‹_ÁÆÈ©†ÕvƒUvXmé Çäò@a³Y• &Ëy¼÷ÃC¦ÐgiÕ`‰•g£iÊêFÈ™^f¥‰4¡_Öñ<í*~§‘ø©{ãaá<;r=<í¼UFÚ×tðòhí–M1÷2°6é ä 6e¿·\սə‘o3y\èÓE1|™ûhæ¹±ÓLäÇ ´f˜ÞŒÎQ-ó.ErLÝ®Jù*GôB„Ç:ç·› ¼¸¢g!¯eˆ«Ù+ÁÆgR$Ѿ¯X^€Í¡„/cw쑪_ؽ{¹L<–ƼXGÌHK(fÏC¨˜ø£W†©S ï04Ha$RéÂAÌ<‹Sm»¬%6Ÿc ¯kB"³vœ ˆÙ½æ7gÚ«t¯8¬$†#93n™”7"+Öm?O\ÐS •y V„¡DééRŸ¾lä{·ÌTÏ`¼æ÷ʹ24¯¨cj„ž›ÎQ›wÑ5`©zÄK•,Os9­±çªñ¨‹kT2Œàö wÜ‘A9t¡ô­\ƪs_V!Õ µ´I»Ùp‰f€éźöw®}VÁÏ¿sfäÙÚÎl>D±…óbƒ4”²~´˜¼"…aùô©’ÄÙôn妃ÄÓ1¸"_44±r‡£4¬½Î1I^`)#c¹vçw47n/<‹YG¯’‡¯qÏÚ!  BlP[JQxq 3lRù…ÎÎÙ+óQ†¸Äì˜r55[G3K‰ÌY™}‹)¥¹½P#!˜l´P/ºÞÞ^ÎÉN[²HK $¾ƒ}÷`ö½™H'Ñ7=ê¦Îh%ü¼Ô 4—c Ÿ‚UP Zé Àì9v·aQ’uoÖ‡²Œ¡1y]¥y¦wœâq‚ˆÙÓ˜7Xaö<®+]w‘ ÍÒ›Áו™V’½ g2¥èZñJâ4Ú¥øK9¦/å&8ÄÝ4;lMê`±Ð›¢ncʌƙâ)•{1€·º «ŠƒÙ&]K# ¢wà1©‘¤ ÌÚÞLuRØ^°àiÞö5ŠÕ)×ä¨Zýçñ=Ý©=¦8ÀU 2‹Ð¾ŠÔƒ'¾±X],RÆá«òÅwc'±¾ñ¹:n¦JkhZ¶«0gñAvo‚ŠÓGuÑ{ÁØ&<ö¨ÝTkìm7l‡(µ &<îÇRA†î+‰Åc.‡Ò:±z(ZûÒk§¡R³­’ÔŽ*DÕ-Ï!hÁéQÈ•‹…Û°»{µ]ˆVl•ŠAÈR\ölÖ4λŶv^5ˆgŒ¥êÄã­‘tªØ®ñµb°qÃ¥…²+§:;²/Ÿº®p ó:Ì¥¿ÐÄ{z°7)×ûóëÐXT'=¾S¡œ*Ûmd$?œ'ío¬­DÙmêÛ‘`ÂZ»T´ÂLb‰âvM½xز¨µr6oh= ß º#EŸDªÜ¸:ðV±á<>È7ªo`ñµsÓ›é•ÇžØÛçàºïÝ$O{´“A¤É[Ò»ô¡k7 )Êܯ˜JÚƒu³"¸‚¼ "M bkC÷|9̰_X2©ïHH°2×^¤FÒ›®>CÉÍ<‚ÚCµ2¬Kâ«]—y–ûGÐÜC èrX­#0×á\ÃÙN§a!0Vô™U½Ä=Éjoón/£ “F©2'hÀ"™©„à†eíÊ.uäqû{Yùj²Þ¾(ì|@C+½›˜œtË%@¯fÚ–náË9/çüa¼ÔckžÄ¹^}ÙãY.þšž\³U#¿­±;1õRyÓ—ezÀ/SýX÷ÐòN²ö½JÃ3u²{µæXZ6š¸ùËåFöAúódÄR‰´±•“ñ€úu20Yì JÑqŸ—‡l¶«ÊÚaM‹pùáZÊk}?¼¶c-@¼–(ìõ43>L‹}Ë£ n:«dïi«3dXÝúÌ! 4ßó‡@¬FøÞ:½[(õöÖ”®×ã€DìühZgò¦¿‡—Tïá=Pñ^áì‚£Õ”`äëg[yëõt‘ð€BVð1ñvTg\Þ¥ãíPæ{šICm‚ójdÓ k´Iºo²ñn.[Œ^s¸¦à®né[¢XL¬`¤¶› 4Ð!«ÜC°¹ÒÚË7[ôàÂð­÷] GnèÄî>¶­Ì‹pyéÆwV·›„´›H/L”§9'X÷é!µæ;Xk$B®yµ0¶â¹‘¸pç{¥¾™ü^¾A±Œ·*–‘ u¯Ý±C"*6à¥Ùë,n“±'Ë©/l›ùll%)÷ ¢Ì©Ý÷(Þã4z ÆÈœ»Ûòô]Dl¾¤ð|ÎÍ,Cq»¢K ÎD™|•Gp1ÇÐ9aywÑv°LÉt `‡D‹5†Ê„&¾zÃFåïZ±6nïžF½Ûœg2<—ï°óš”ŽV;…“8äíÎH¹ošÀê킌E$¤m¼*’ê.ŽËˆÇU3ôBŸ›ÙÊ 0akÆ+K}×}ã}éY ªçx .p\{î±¾}ço`[y*âì9½‡0},vÔ£<õ¥É—vÆâGû ç¸Þƒ~OEVÑlÁÑ.±­ÝÑbêI?[¡­p¾ì¢g9–0xùJax¹ìz^Ävª‹äBñ:×H"´°øÙÃòh}ëÏ®ØpdzE-xœj¶ ›ß¬>â ÐÜS³FÃ8;éÂŽ÷^5¼³àe]!ìšÀÖ8°× $bG؉4]8Ï}º@¸¥dÁâ>¯,é0b¡;6±Þv$HíAYŒ‡zfÛv†1 ;uØ1Q9épPE!ÏÀµçØ™À®g+üqÅhà1àøT oò”Øk^”÷ЧA‰@§Õ¾Ä>á§£0¢STyÌ!‚‡!b÷äÞŠŽF…Š/àæÙÊØ(iñKÓg1ä0eSxô2Æeeâõë…¼N®î|ÏØîø©µu¥«Îh©>¡÷¶Ó’0è=P§×°r¢™ú–t¯Êôɇ‘P´5}RFl´ù,û®P±@\öñ=¨ÁÚ3 "BϺ½LÖ¥ü½dÇ·¡a|l„yk׫oBFá=¼ÀÈÂjÙxÕ¼ÕÕÔ´mþê&U·ÌAךh˜È s›©}y÷èË;)¤w³:û˜Í¡é°±Ñ[ãlO>,yð&œ:7IÝT'êÐÏ#oUž8U.¸‹jHÙCK íHm-»à‚äP¢iOøÕj“°uô¾,{ò‚åúš!7óì?ñesÚœé¤ÞX3Ïk<ŠŠK±‡½ßÄIÛÎ`»h ñxºJ…ôCµB$£G;õ8mQ¶_r„Ã$£±Øà1CóUø›WÒbebQ/5¶¬Ð$ªêUÓHTR|FrD)©î"oŸ‚Žê™¿¿ ŽÁL›ó}\ÙÖë.öŠ!ž¡‚±¡˜’ceÇ™ÙË|¨h­÷`hÞ »ùÙ kŒ%äqg)ó¦fèÌë"S¥Öº¸EÍ%65q$އ%ä}3Hþ(b_?¤(~o9Tra7ìBµÞ«B¹˜ÒMÐÑæž,5©má›Ò ¯âÂJÁñåX“h(ÓÎÚ'Ú8Y¬4 ‡¦U;h0M­ôBZÞ࢟¼®£‹‡!R ÞR¹ÊOµŒŠÇâéÓµé§;}¯‰#ï()À®v¾ÞÉ ÷“—„„¶/û…QPo 3vÝeš¢JDÌu"#ô©ÉøáTPM\6dvD†âæ2>Í!Põõ –½SgEP³4ÜÖ>9Ä\¾…Û$‡¥çìQ÷®Æ{„Á!|i÷aÊÆ6©0¢T‹a´Ù*ëaæ?§šôœz Œü@GŒûèf+1GH¯ŸMAOs™Ëö,óE¾±HãR?É~§…KǧïÝéÍ#ª^_¡b´0`‰ïk¬Ã—xàbxÖwÒmRO©Cù[M¸ÌjÐŽºóâ›&é\â×åç'x¼2Sâ¬ÁCzÀn~š³ï2gÃPoZa˜žë¦âHxÈŠV&O?xK$æÞ&àe^ˆÿ™}‘ ò\„çjçšD@¯zíÑà‘Ó¤$1')Œº½¥½>iö2ª›lY£U -#87&<ÄïˆÍÆ2ÁuWÒ ¿ñV¶©HÒšs¿ˆ As^*UÁ\q,¬´tzÙµ‘¦Á­ÌõÆ®ýÚÌè%]ÞsĆƒ”˜!± Ý(3_¯"%<P¬W”mR´¬q%~G1/¥phß !„›™4IL?D‰ë÷*weN…EºÑÓÑr¢Ã¡&°%Gö PßøsP„uìá³>äAß§º*–8»ÓJ:5îJ‰3æÝ½Ôq½Ê-^ÍhÄ yÙz“ RPï­ä¾> s‰9¸ Æ%肈ƒÙsgMÏ“R¾¶æa¯dFõÄ µ€õV5h0(Xñ眇KXÒ%ÑCj&ìäË}*å‰|.V|þ¦w+KƒýZXííeRºG‹÷ùµŸê†=X\2†Ô´cÀæoÖMÄ ô6ÌV®ÇïžNúUG7¿A'o|\-ÙfžÙC…Ë'ùªådÒ²|´ tÓ<°²6'|gs^Å3PÐÜ[ŽW³ËÁ£¯À3‡'»üpWxè¦öÑY\(Üá;£®Õ~€w‡@ª¨NÑ[•;â~MöÂk7r¬×ý˜ SÝ߫Ʈ"Ùâ`q<.CCû4Ï?_µÞ~î…k a‘êfy˜NQAÇÜ)ÉúÅ[Ù—NûFÚèÎÖFhö8n{Uô«èë´çŽ›±¤ùt8¦@}äiô:y…ì#<’©G*V¬”°òŸzT~*Ä)ø&ÊéMx6áÖkì9añ#¿/;0öXé&Fl}„ ‘êîsÀ÷N*d„ºÌŽË]7½!X”žÅ`³Ò=~~œÆ½‰ûŒ²7õ‰Ysº¿Gþ¨ÑÆ=¬2™\c¦ • ×]\2]ã‚Á¹yòaéˆ[u[Ÿ“¶9´HǺ¯*œÇ̉tn5H0Pjïy—n‡¾z/Æ:±ãÌÕ³·dƒÞ"Hâ´FëãIÚÒ3â‘Gc#e›Öë•òSó™Î"HËŽƒ—lÍã1H56~ôz?„5¾ò¤QÓ–pb'¾W¸"íú°Ü5³eQÎM±;´wŠ5¢Æ5<:ÏÍêµñ9ì²NÑ-¾Ñ¹Cy¡a`—pK´Z×î#|ú¦· Z%°Ìж£6—PO ˆNpGvL - è‘á;¦1:rW Üšnú g$§ÎWY‚"<ˆR^Íóx tnþZLÛó*x€‚Ï4±÷qñŒ_ÊÿX~ÅÎê•o˜À 2>Æ>‘gFy[UÄÐTäã"Úz¼ Œ¹/ä´ˆ†s_¯z[—l ªO§’Y´ÂD!µž(½s¶syïÕX;œÎ›(8Æ×¥iÆÃõމ” 7µGóÔêHŒb1¶-2/T=OüXª…„æƒ~Ö·Îbô˜ëÔ‹òõó|›xjˆ3÷¥^Ø—zå£&Be¯T–ü:Ÿð¹ŒO³x`—š´Iß«‡Æ6[cÒ‰;5•ïZ›W$zé*½ß–eFv±ÐÙg¥rtÕ¢¬Ûµ[Í\Mï(ýìè­qÁUÙ©qÿç^+à.ã‘åü$Ïy±ËšÏçá•ï‘]Æ{·M„gŽQZviÛ„ËÞ¢U7Y¾i¬ÂI.£[ íÓšcX¬ì ²}Y@)0™ ýenç?œdu{»>î¢ q%,vB¤ä%—µÔ Æ!çÐ™Ž±“8è™ä]gìÛŽ÷¤eÙ,ÔÁÜh»'œÞcÓ8éÚÔ-¨v¹pl´K룱ä íPë7ðPÚ 5°×R[—µ@bYx”cråëlˆn,ðäÆÙH@§¶e<ic]À|—‹¢Þéã^,%“è„i¼§Þ8rºTÒ Ç˜ìÁ¥¬$Vž_Iï=…÷Èç wÔ³ÍôÒ……Ö ÷v S6{ ‚‰æÚœ!à½ÜÁãUòÓç®±+½W’|CŒI‚^ÙÓ9Év9“)žì[WhœA"ý¤·{âV¦ \üd³lüD©T„RÞü'»5¦’ms4ócÏp8ÞŒ¾ÃeËVqòV9¡½gìjõˆ€^ÄHÏIn<.¯ØlŽƒ³PQÑ:ƒÕ^º,QõÙž·˜šå/)xX9dÒ$å ,Ô™ÉîdÜ%’ã9æeL5äÀBí¨"šÐÓ‘kDcÏãì m·izYVwÙ¬Ó÷8̰fŽX3ÙüX^‰’É ëEùiÀMЬ€þD,1xr ZŠ]&‚ÌQ*3ݘ B¬âiô«Ãj8w'›ÔX ?ì›{DÕ¥¡ÕÁÆTµRާ|'h¦8"¾þhú §/©d™LähàÞì¾,Ú ÿUWÅ‚ÈÄe6E[‘]äŽY¤€˜´l6M øXâdt¼žÓ ‹E÷¿öYz‹Ö>TpÜuT0ÜyN'Uš}ÊÁÕQå¤×/:HÛ&Œ¡ž+ºZX/‘…Åè‚-šðyeð©áË+Ë:±YÚ}ÃT•ɬFÞ‚‡w .èªÖŠk“ ÆQ©“l‰Ïæ¦YϘùg†ª–bhˆèK+r/@t z).H€±êFè`—ædlVîÒBnð†Ænc=HÖÆçYäš ÀÐ,›]ñ°¬lFŒÔ]CR¼ÎÂaWWzKk‹åÛ un›,ºŠÑ9;ó^¬À‚WÛfÛ•2΢ö½cyžBîsª6RÖ1ÓzXoç¸å"àÐÏLJÎÙŽÈPÚ6®¨Hª¢¼Þ{UÉ€Wk˜‹^w tfˆXÞ‰ sö°1í-ÞŒ7‰¶Tˆ•O5¼=”í»fòµF ñä7æÀb±Ö8.ÍSå}½DøPuÚ/WÕ»Ô-~Uè;=G}~`Pĉù4k®•]I¦±T…ÇåôÈ{V2¢g† mîŒùæ‰×+vbGpÓžǺ¤èf—èo}Iê½ú²à󵋳˜†ˆˆ»O]*©¥€@Ã{ôIö{+ ëʃšØvš´Ú8o\§CÉ-ÑAÚTÅÜÈtg:“ÓSTwŒéœGÊÇËCür3_¼ óÔ)lëÏØ~Múâ9·ç5^`¾ÿôS<žePFf- †ôžTr½Ú‹V箹‘®ÆÆ…û& €Ö–vA/bÞ[’URÖ•· ðê»0GV‘Äbr±W&Ï(‰û^JÜ*%¤4`Cßú£WŽWéq÷º§Sñ1è[|å·/c¯Ò&´UõþóO…{1´ðÁ5ñŽò¼\ï4<Ž×SõèÈð)ä«!ë;5BÊ~UXè@|‚Ž®Ùý€çDðHŸä3—á1??ÊÇÍ.XVz ðGܱ9ª·3U<ˆßòùÁ…›*Å󜌖-Z}`4å¨&•²¦ÀL¥WËã¾—u¢”À»½Z¼Ï%hZU·;ô¡$¶6v -‚+u¤Þ"àö(_[ö¼Å±½ís¬|¦Nk}û`•Øe4ž'#±Ì 6Î6Ôá‘=°Ã¶b¨kê*÷F¼°ú–Ä[x<·”5J$/h;­!Æ›[Eª˜©¨cPdHBá8鹾Ћœ’¹ŠÜ3­^j"ÙÛx®ÜÝOžUé´>-Ù4½ÔH›ë5–=gxÔUY­™©œ{Ú%C‘†<*;É¡RûÖ$šš½/ãÞ Á¥zo¶Œ×(ãn[cP™¢ç Ðõ>°cÄèÓ‹g‰'×Oú£‡ ”Vwäc°§’%<ç ýÊèÜUŸäF‹TÀh_G@g ^óFõÀ9ÈëÄÜBޏÌk»î3+: ¾ eòˆîÅL_'Ú O{ÍñHàÍmxX\ÌE/“§T$N.šbåS.E™}ùÇöå<ºb½D­œGÔ€+ ÁqÖ×¢]ì°kn]ºë`YQ£ºÆ’…i”¡Ý`zxgJ=úÍQÙ»fŠ3,LÁíô—Ìí§:)W•£}T¤ôÊ7œ«“.gû)ñbÁ°È¬¦ „ÁÚ›ŸU€8¾Mº5÷$d*ïvDVÇÜ Þ‰2wÎ@\{ß4kPhl@¨!×8ø‹W·§ÈpuÝxý¨Ô'¸Z’ÉQG·äâUCJ¦úÓL*ÛÅÅê¢0…‡Î™Ê¹ŽAÛ–«/&rðÑ=:M }•—²af·†X þèiÂÉØˆ_ø¸Ap[G æé<ŠBì`pe±ñgÑ(XŽ·‡ïƵ㱃8‰së‰×&5mÀîÑ–x”…[z`5Åî[ aV]!â&A¡×óÒãu¨1ñBÁd‰+ã‡u7Y>ˆLN€–‡÷Ö—Ìá%”8D5°V®Ûɳ{w @Uû–¡¤Á `Òá¨l¨ŒF8O"1°ìã W)ÑjÚ«ªGNOxZC¨ŽMˆ0ñ‹­MIS‹xà ©M¹7–Òk·!M Öž b:G$d±Œp8.3ü¶WvÅ€-ïrøùcÆ,«Â®Ìz r•!ïÚĵøašË¾Åî““¡G¨žl¥¢¸âZÜL>UJýL£ß¢±‚¨¿0©kPÅ-nÞ[M Ä~ ^ñòÎFÖ¾ˆ Q]ìÕfsÝÛÌí®£ÂgpKZÙ+Ò—¶XÚäÓ ð&l¨ìrù½^©ì×k’ñòÌw¹™ÞJít?¥É)b¯T^h çËs ^p‡Öý% È—€ÏvûB-•Lâü=%G±Yæ9’èq€%t†3Ý€ƒ#íŒ1¸Y&†í´gpˆýŽÌg+ Œq7ƒ ïô‚oT]-…¾ØñjNkÚ’´"[ö±Ö«£‘ÜMy~tdÿhA—Áøõ*GF:¨ÓùÆ.$F6iÊ2ZJv]‹²Ì+›R­šM~GJ¶Ú o 9l)¯LÙI‹9 Ý`™Ÿ‹€`ÜKu ívä8¬êšŽ0ÊcuöŽÊ­,oÌ(šVGT™©2ANHûpÕ’(ºúbÁ_`[˜lE<4Q mŠà¡´l!¡ÁoÊ•©¿à+?Vníä†h‰`£Á™’'A^·KoÎò¼6·Èdg ¦$²u‘Ôð)ÖpV v¤ãYk3GfÜ#³.Iò]²£Ð‡ùN:ŠâImAfŽ MËÆÞ½·ƒluNš. ‚ x Uþnì:™h%¥dW¡_¾na&á@ó¨ÁÈI•pZà¤$CHˆxÖÐ|6¶ÐÉâˆ0>­“©íBž­ÛAù"r6ñ&aŠuÝòãb¤1TœêXl½xÃ/¢I¦%ÁCŸ>°¹7 [4PYúß‚”9^‘„èq%ϼÃ@‡ª&& 0rU.ž/6[a¼Nó*}ápõœ•T9üŒ< C ô¡#Âu—:9zÚà“—ŒN4¥ÚRV‡šð¬ÞKøãv_·¾êIHϡݵS5V·yúÖeE«›áAˆËø\Ñ„—é¹ _ñ!PSë@yêªéF,¼{(¸¬TS æ€Phðe Ò§9 e¼†MGÏ×B$5iœÂq€èœ#ÛDØ_]v€›)€kSO«ëmÊ«Z¥1M*Š|Óü@÷t f`/–*àrƒ1 ¥¼UM „¸÷Êé0e  KxÊ?ùOAz öôôdêÙ°Ðæº÷¹Zñƒp¢÷–$ñBnA“™ê„âëJ{3ËTi)ÉDÃ/GRv/ –n9Õ\ðÕ>¦Ó&U8óRM›äØOÀµ[T±Yk`ÉŒ1|d×Íçé®nW¡Ì«44 ¦‚»v>zëhó–…­‰]óeù[é}ê©éœrcìŒcç¾²ƒ=¤oGJÐo±JÂd°×{²wV(RùÀ¶ÞHË’W»¹‹t[[ðFX–,†¾U=9&—J8G}³|ؾ°âO¦dMWI8œêF_Æ>ôZp–Œæ¸–e,ø82Œ3Ä'S&ŠQe#n& ¯4U˜†½Üp!›p† ’ˆ¿±Í ôDP¹à„siÄ:Á7 ˜¯ R=UgVñP7±+;Q¬™©zQ‰…{•>{úÓEøí+£) \(¡²sD„cmën*»Iùç¸jlÒ[ŒçÅ#¢}4ë+ÒÞvt["ËCŒðËGæñ-µUÇ<j Àº¸Ž÷Ÿ§¸>š~„þÌVù0-Céô¡±âš?UÊ£ËJ‹HY^he×q˜f{70ðH}F#­R‡îr RZœ„_H wö\£ öDB¼Œn}ÃȶP¢9/БÊxÓ»b=b®ûÕ\œú±›5sî{Sñ=‚f™Ü½Tz&ø¥ Á—‚‹w—ádÝëåVýè…¬x‹õ?ä{NÛ;¸üœ,êÕR½:E~Ad˜‹ëDµæz´/ͤújÙoݘdùn1Ü«5û4RýÁ‹Ô—P“`°®¥§e÷ž(…qLt¯ÔüçàœÝøÉ>s`,è%mŒ8 m PÞt¨·Å`ë@ísÄ]„Ü—`ÍÏ’ E„yˆ·’EÚ{`DJ¯ý0AøAWw=æÔ!/`íœT£¸n`:Ñ)ê¿bÁl*hm‹h£ÊREU†ˆõ$Tô¼s€ö¡™}ÍpkÂÚû¨Ë0¼ÁÂfÇ _—sx6)½C)ÎYº³}ö|¾ñ[ZÞÁY͹„zÍ$L°dDL‰2œ$úêÀ_m“,«ÍçÊlAÝ ÞȪ¸e#Ž žM(€ž·Ò¤=§¨×CàÕQž\ôVŸÖÕ½¥8ìgšÀÁUEÊ^Á¨ {x }z/–ÐFc÷N ;Äé©‹#ú&Û›g^Mô:è#"nïÈ—bèȬȅ¹§GQ=ô!^ƒãyá 0—9¬×‹-¸±‡ÂMAíãDÝhˆ¸‘E ›#PäöØÜJf[ÚK•–_XO çy‹ y¼g±9››Éf8¦t`=¦*‰ga§gÔ7ª1X 0´vhæÊâké-(—Ãðjy¡êä˜{’…i;¼ ÎfÕi²^¡ÞŒíÓlÎ~7ð¢0˜Çe±b.¦ÚAJwú¡vâ^´è.><©~4èû|Ç&ÆW ó=%:[Žj&x×p ƒÅ±ëlü0Ù>ô/-.²*M5hpJ¦Wi*+ À¯A0Ø€^ЮL&óh€£ú+ˆª•(‰'"(ºÓ‰VT½xz~Ô´/úéÐJ:ÜrœqU^ ðÄ’ws¹-ÈrHFÇ:˜Öp»^ÆA?4€ÿ$äö@؉3:QS/m^™÷âéŠöB‹*rÐÛŒ Äâ”iØMöö47ÏXÈ#¸°ÊvæÆÉ{8P·Y'XÞd ˆz>Û!ó(»´µ#«°ùÑy½µO°Ý`Q¹vfó¶ul­a›xÜ©:朚B™ -¬{ºG§A· ‚ÒàH è«=¶’i.­g•³²ÄS`¢ÖF5ßz“™±“¸„N1_Hv¿}+‘/ •m¼¥a‰M=צⲘ;DÛV|Ç ZÌäùs "˜ŒT5Ò44ÊÎ}½u¹Â1ézÔådÝî(!pÔGº,Oe|xVÄop0‹½ª©Pß«ÂjŽÉWõÖøž·žpúÓzUˆ°0zo$;Ɔ™ é=O0¶ŸÃæ’í–[o^ECˆP³®YVÁJƒ´"Ù;8v¤ÔÚõE7å /+u}¬#ô\Ϧ´V!²˜À`Ceâ]{Y ¹Bl†¯œ M1Q,¼ÅÝIs)y¨jéÍrÓ žÏñªSŸ\z`“+)v Œ Å3ó®B)ÜÉâËuZ}ýÄ‘HÛPkj¤'Õ²Ž1Æ6ï{M>s®”žyþø…àt¶\‹.¿¨1EÚ,”–ãÑ'žÜ'ú_Ð0Ê9žfïØKÈÈ2a>&PcZ½GHTÆÙxTÝ“Q#×úbm¦‘ÎuÝcyõ%á³/ Ù!Y©SsçÒ£ ßhΧSÇåö¤.‹¢tê5árÍz0mmH”Fõ…½Í”‰ç¯ M:µ¾ >’-(ë­]Õåó¨(EðDæˆ,”&udGZB'ãIüû:TÃÂ1?Ì«`ïÕ›ÐU«€!' úŠKáÀ7=„mU*;R7Dk°«³¯ Æp•c°x=,±…¬ñRÀKm˜èkÖå±Çïe‘ãCzéJ“b| 6´7C hJx士(©²Pˆ¡;ðe8ߊP”¼³ƒë–LMY\&ê{’1yÃ0Œ<Ôp±5˜.æÉ‡´ÖÓ°ñ°êÕ>Òà~SävbÏ#*’x‡—ˆj Iº¢å–ò²Q_Ÿã„Vè!XÌ3ˆ06Âfó¼áÝ<—Äw(¹;“Û4¥uwÕÍ‘3)ôù{Š”ód¦—¦‹^>´} 'Í˶’«Z Ò¿™ÒÃgÕ2Çå.7ÒM›cà h;IKÄ4çîÉ9ƒÔ³0.m #\ÔžH½wé`UUa)o‡”1hÄJÞ8ùîTLCûè³ÇºþÀÉÎ)æÙ©w¾ãt¸ÎMìl¬fOcŽfxGí#~ÌÐ<$D={Ú…óŸà$ÃqL°Î»×cÉ(1@3`x®L<¶*SC³üZ½Þ{Àªå*7l×8û¨÷˜!ž5]Úõc±¨‡åp:QÚ9ÞìO,Uôyó`è—….Ÿ[áxÛŠD5²±¢>‰&ñÆ×ƒâõõ%5¿:‹Mç’±JoØ¥‡Øä»ˆz ¡aJÐ+lR@VÖx‚*ZØ T»êÑ(øÁ =KT TXn>• 6ã•!ØÙfrYR59# ÕRúOC¡Ô@íÆ©lµ»'N:%NyåO)wFËOnE‹ û)>µó´Û(Ä|¸»$˜¦†·&0SJú€E®†xSu"©…®/»ô'ÉA•ƒ -Œ|ÕDvDaýüáK ÀÑ$¼‰s6•KŠNÆÙZsµëŽs£*Í/ ñžâµÏë)¸Œ6´9 |!mCÖ‰ž¢.ï6Ÿ¾Ñ7Qcuƒ«½)d Ùí¤4§ìn->€þ@¥æƒ#im´õA:5¤©ríê"¼]ÆÖƒô R¥(¹»‘GÝâ4÷¬l2W…ið5ÉS©zÖó‚‘{PŒ q¨XüM`“¦¼œ±ÅÙË×6Ô´ŒÆv;©ïŦ5áù¼çýë¥Þê‰Z=™ï·=ëwQd*`$•EÆ(¢Lò2D IÎÖ¼+°œä-¬&X›­¨ãCš®t, ¸J–ö5Œöã½á*‹î¶æA—PϨSï55‡c|¨üXÉZ!öÎgŽŸ' ½EqrˆNät–+N,b<+‹t%¾G{ê€ )Ž…ùÄ=ÛªÐTE¼r=µX97i†5Û§K`Z×›IS"@ jÞ—­sîÃk4T2!iuÏî^„l陀3¶KÜsÅä}“;ìf~ƒ*^Ìœ€jŽ…Ó™‹B±mu{FP`>“ó¥aЧ†{]'ŠS PÑ{Ðü$†wcûÕ(@Î ô´éìTUN¹kj¡SBÀ?'%Àe`rÏÇìB—o5¢¡eáù¶öK‘ðl`Ú8ôG‰¤—øzIy=XWšû!9‘P×C+îÆÿ<¬ÉàÍ›Y¢ŠC/BÖ{y©Îí•×\FÝf¯åtõŒd›°a‚dùº>fmThš—MMGc0&rŸAƒÓ{:*í»- B8ÊV˜!©“:<¡ø òÖÝ‹ ƒÍ+¢èN© aëèÀL“q›uó’Û\[.w J×¥švêÑV óv=¡(ð¤5\¼Ì†5°m1Ú|Ey®a›¹ ¤+\"÷ éI]>2ŒŠÍY:kQ7.à½g葎µ)¯º•pÚØØ$`xš rkù‚ݱÇqBß«“лgQ¦½`T¥÷Áí8Þpî¨)) ‰§"g¡5¾—³Œ ©/œ¹ùN/¦aÌ›;ˆX*fKrü TÙ="„ÅÖD{æ¤yñŸ¾.˜Å·’ô°=rw·V) B)Êb#•1Ë#/yà¦Õiƒxõˆ‚¸ž¦4"¾ªí£E”ZõÎ6ðÆÙl»dnSŸG¢r­ÍÏ%<8cÔt\ØöWû\D ‹i—4®»Û«,2¥Q\‡I!<”°xŽ„ß<È÷¦ß½ç KsÅ9•YílúÆå1úCq{‰•\Óå¬R'‡éQ§â •€Õ ¼záþA]¹Ê„5Ë€s:y½yôP7Þ6½›T\Yëz,@y9àöœð­XÁ9xè_ s+#£‘4á¸y28©<]¨aPJ B?é!®pB)«ÍlÂv‡—ÔÌç\#TÔÖ;ÇD2ºƒÛÏEDŽhÁS5S]…JI ¨‡GGÏ^Þ>l'FD’|1±Êû\lºJzÿqe’ƒ*ëù ·?y­nÀÊꊻϨy"KŠëm)”Hx¦¼çݨ˜e%6êoî<²}§ÙEkHÃØ_ª9i°-ÞÞ>XJ唯(]Ñ<ËÁcÚ]ä(É÷'³G:_k'<*㸲ÜeÕ™‘Ûf=ä~²N´zÔÄ©´EMKe„`ZS‡±‡ÆÖéÈK7&¤¿hÂŽ•˜§®Ÿ® ºÍk¿eV1-vO8—;kIqF¯d7èÕ£ Æ|Ì•õ˜®ÏU±d‡<ù†gP†jôˆ_Öu¸lWû§ˆþ%búã…¶×i@VfÎ~/Ó˜d$^¨ÂFõ‚I'.^ÅK†ByIr|fÖæ!‹ïìì£Á·DÊÍ2¸Íeò¦zÎ_œl¹c‹3Ô äç€[tS1ZÛØBÞ›“¹wÏVzŠ*çDÍõþ31‹ÒÌ^3 ¯ú”Ž.:…ˆ¨ ^Òe^ošZIGǤBľŠÈ‚jìwÏ©Ûk†šZ""â\H„Ò„yBQ+§+6 6z¬)àÃ=R «5ƒ¨†ÓÔÍwØ™®Q «±cobòåЈl²UŸŸxf=mÜE¢ÑHïâAñ‹õ—d¯9!uÑ•&Z¯/qt4¯b†m¿÷Øp@a$á=Âiñ2®dTçí/ѾL°ÀW&Ós84þÚÓðq™œ©?4_‡Ët8§q9\5\Fš¸ê5:Ž´+y¶€¤GVݳF(µ¦ ­ ιaí×ÏBLÙtd7ànG™ƒÛѦŸg½rÄMÏ –ÑŽ2jƒ”÷þ};Á“}#*À#®†ÌÙÜ.í¥!Ú73ènQ}sQÒ—Ñs§37«\ cZºC Xε^±ê¦j®éÃÜœ,q«ñH$…9CŠdúÚ'òù1ñ‹¯š“óŸi“¯ûž\ËzsÃc‰Y'‡‰m'Šä®M½-¨ò#5¤·ƒ—ø/ tn3ꈸ7+ñÄh-’0î¯_¼§§]¨|†$ß–væ“æ'÷º§g¶dGÅ#"B¸”`p÷ŽÌ=°eëç-\æâ]ð'ûat]Yž§ÊNÆ\Nh‘ïÙQ,5EŸèc| XÅ’=¾,mïļOðQÔ.+“3Êë•UCwÕ#¶á”-[`'0”ÔY(Ðb|$¶Ø{ždý™h0ÒŒ˜y¯€¯G_.Ùó6Ž"£4“׆½:;€Š¡Øo /q¹jÐÁ !yˆ²2ÜYÓÜæØrMÙ†Ða–¦Wj±hž¤‹“(ÔaÅÉe *èéã8“yí]Þšœtn‚†%¡"šxf¾é¶Ð¤ƒ5Ð —&Œ-#µ;qÊeè^<½^₆é“Ô&4ôÜ»ÇážG½ºÎ:³§c·*àæôîÒ÷Õp2s¼NòpB™Õdôlæ]ì†]¸AK7GíWá›àm<Ľ›ïÍ—Š$_*rÇ£VêânI™#ïxGsˆ½àQŽ*fµînLÂ[ŒÞ”S˜‚¯ AÁ5\Æ«(ìÒJbôÕ'ƒs„OòPÜ%*£èDl bŽz™U#B_ù¶ƒ?›HpÍ—€W­aXuzÖ©>:Yì9õŸ‹ž ÐLšƒ/»*ìFpýÉæ$ viÌ ³éA# ź/T‚z\±v²xñu‘Z^^¿ÂÁ|"ÚÄŽöŽI“ ñ^ëR½ öÔ^ë{ÞQ¡ãçBÛÉÙH;¡² í{l4 Þ‡x}òš%yÔŽŠrÑ=ÑçVØêµ6þ˜qÉáA“H”Í, q‘*ª]5ˆ>ÕÅÒ@b ƒÅ¹Téìš㻙Ã~™Ù²åb‰^B©d€¾Ù ‚3H-h$}ÁGG6¥ƒ ü ÊšÛù´¡Y¢U}V]±cÖP{Ë\’;ÚŒC~xOJ"m°[‡/jqßnѹ1m*;>2O½ Ô“‰Å³=sr!è`{…ÒToÝí„Z8pácÜŽ2¢thŸ[ý©@CôäK»X.”NF¯ñf—çønȓξ´íHª+Ñ=s`W5ÏìVô§Z/©eGàèÙ’Ö¢È;DÆ“ÔV9®)‡‘µEfGpR,§®•áC§ã£âpΪw¤%Ùž¼tÜÅ·ºQeöM¥¦8AÛ{—3] T–öò` ¨gµ2œûÕ±¶×Îa ¢0CŽ¿GmkŽ—`EOëî‘0N"Hæªh±É1ÛS!qË£îkó°iêÞb‡q²3ÓXÖ‰( #‚׋L_..ësØŠ‘#ýž²ŽÌ”9÷1ï±½‡Êôú¤%Õw¢kzFÜÎ,Î=F%2ØäÒ)SÉT¶agVèô–¤[Z^;ÙT+¾ òc^¾JWQ3Øs®ðgÙ—”þ’T ùµ- $¡.‚… »ø2–‰ð-%pH½ O%ëµÆGšÀ'?í*èåÈ59ã‰A§mAhÔ´N@¿Åå™¶®©ò3œ ¬×-aÀ„f•%)lUkÄ0˜¶óÝ£ì=z̾il§’w«1JƒC–•žäOJÇè[\‹>‹d&îxîù²ÈÍÃPŒ¨vx. ^;™a I‘«ìI²Ìòd·Ó¥;:L)à } ·óöˆ3dby¯.yͪqG¤…lèíÈMBIUe(L?0™%¶Xtß„BȲl´p–*lOÂ~9ïÀbØc…±Ñ‹â³¶® oEÅÕ+8ÞÞ~/w1Æ9;GÄ%~Í~“$±ËîO%œàõÍää.¯Îõ~PâN¯‰è¹Ù²ì^Óô3ášdHN»­Ò­WáÆ}ðÎnŽ wüY´o³ i ›ín’e‘× ï»i/¹g”ÔÙ`ƒ°˜Þ¶ËZ“&m÷°ÈžnJA!RÙ"èœ ¿q>^ÕÉ©8•ö4_êgÙª™W˜LŒMïåÒ«£'4àw;>Çá­mPCé1”‡ Å×—#öBJhrâ={'¯Þ‰ÐÈœ¤Ì£ÕÜÎW”ü<â.¹g'PžL"Øu‡ù¸ o²@u8³H•ú‘ÈŽ=ÕlªX+€.Œ‹¼Ýbd]à'½Ü“"Ëh› e‹ü%£À—Œ&Û@Ø¡® x·6ŒU #Ò/Ê"xÙs4ž’'!/AٞƠ: å Ÿ¶BfÐ)d±­¾¸£ÉªçTJÁ&“"~¬žáŒ$°Áh9¼e^)ÜÜfÔù…÷1ñ † ?­ ÙÒ76дӲÏÇþµupº%Š´h{Ô~¾Øcê¾P½¾ªÁ<)–:Q}9x¤ê5–éæU˜¼iÖqe‘ŠÙÖæç3 BôîIßÚe;ä"ŠM5 éíâ¼ÜÇ KC-K8îÕî/¢CÖ±ÉKaS5Êž$èê~sÓÚ6›>3E ¤,f+K¨lpfèì7C N¶’ÌêƒW,‚0¢çûœ÷]×ÅËè4_ß5j/£7«Õ2wã¹ÔîðÎagô)pF¤°âã$˜F˜ãµš4*E_õ Y5Óð€C|R\o^8Yàð]Z„8;¡¡¡Ë¢Á¿F<Ä÷¢gKnÆÕëññœèžpµãÂæ¨KDL‚ÜÃM ”óñ\|³àÖsÍxÝ%^Jþ¯Î§¯B¶ùo†NIÚ°7޼v€ëâs´ek·±âÕ±*ÆfÒ~ Ó)ánï„íྲྀ‡X6]i³mŒ~•å¹uZÅÊßÄåD:Gï‰IÔ´D9Ùr›É˜i(1§í†CYÔ¦?áÇD“8cÄšOÐ8Ì"$šÕäÙ8•[¼ÄR„:Á6uM}koG{x?e<,™}º®`SàtÅEbƒ„îNŽ¡6^çøöйWéI¼ôC1 ±¨W‰':Ï:R€È3xì9[×ë[:ÒÔSkB%—|D’/ãÓ·þe£†Je)RÓ³Ò‰£0t2’œgä Vªº›ÎNjÄ$}¢t•’„ ³¼h:ˆÎ˜ô`¢+^¯7 S†Â<4€*é$ó¾ð “°‚4ÃHMoã)O0–¹¶~Û¾ `e-j‡EЃ±Ï1@T²Ýá?_ö°> †ó‡ÝÌîö<± i,5 çZ¨0@È’E¢>W Òi—LHý®Ð [ûI#Šûðˆ ¬cÁPÔcQH°içD<Z*¤Åg ÖW¦Á‡©J &%‹ú,çåë# …ò ؼ”7"{hÀ8“:Oš5É¢$ç$ÍX](àM¾÷ ¤Qøž±ÖžZc§ÃìâôÉuBwÂé·FO»ÎdœDùžI‰zö–;:±HÈ=|§$З3ŇؘTdqpÏ*¦ÚwLøŠëuœ§ ¤(7n»f]¬ ¾Â•Ù˜6EÇ]&ÊÃ©Ž™4ˆîO©€‰¡ Dëð-lW'ù™V€&Í ­a¸_€ÛpKÐ>nØ;ΫæGøE™‹Øl^¼`^•á&̵Âr<Ѹ›W^ƒ[þèÆ¨*ô”]Ì<±.0åI]ÅcÖ©ñ–gx\lKÀĦ¤VÊrá'Å­P,ò|/É|c'¶ÂM@d¦wN’¶+Ö _ËJÖ¾.‰En†ºÇÃñœm…(©{ˆ()€“W67£†šÇ$a»¸û5Tó¸½~AŒUÕÞ´#„´Ó^¤ Òú6’w½8w%Çò€Ðß#÷“ÄwK´„P?¾²Œ‡¯dÍßWR5¾°7ð@òÂR°ç´6ÚÊCæõ!9¯“ ¢òëF†gcÐó¥£~_`x₊ZMDªù#IÈ»€ócy'\@Ì~! ¼Ã´vÌfv§4)íXÓ ëÖ y#;M×^‚‚Mñ´ìàGa„t<žÈÈëå‰aS7` WäºD³!£XF™x"hö à Ê>Žy·upËÍÔø2Ñ=ÝœÿóñåÌ–wωÀO!/ÞÛÚ÷-†q½äbÁG‡(Ù¡V'²Fír[¹k8 /‹6í¡‹¬ªè«!=5¹ |—âk€Ö%Þx׸¸¢ô¤¸äñ‹HaîsLUEAÜFRàÕÌ·g‰Eoû%8ÀÔí‚Pп#ì_ Ÿ ÊcüOÈ{VÂÖ¤ u4Oæ•ñíø4äªrRŸs¬`´ÁAÝò½PG UÌ ¬Y%XÅL1€º±jë&è5öp€Ÿ.ç9¨m¹S®`à9-1Ǩ‚*Y–Põ¨ )æó=zÒÕ/^yØ£N"éŠ Y6/6bö‘pt‚b÷ïGÊ¥ëýžmç&ó\³£–E²T9«ð-36™ºj7Õ8 °™Ï­ô˜¡Úƒy)Š´̓ A³JhÉÀç•d,€/(Ľv§,ðLçSq šŒ‘êáÏAV…FP+a±IàUd¾rÑ>1XƒÈvך7ÆÑQÝa8ÖLv ¨äeòä•f…ꋇ›“¸µÙòîyqíÕ‘ƒr(‰G°ì;Úð7.òø‘ç;­d²zÏY-d™ìéŠqH£OÉÊébÖ€šy˜•á£%¦’Íâ~¼/¬ÙfÚÅ‚Fƒ™mcµ½’›ÄP¥†;ۥǠcó‘ÜFc½çܶh-X @8ÁO"=Ãb€rÀK³Ø5 út}O@ç¢3«%UàHnÕM–½}Äî@4£•r6ú,Ýü1={Di ÈXs«:Üë=ô³Ýˆ‹Mò…'Õëv,Y)]N‹J‘Ý´ «|bVQì7|ýÐ'’KýP8³Œâ} ùèKȧ¾É·ùØãñ”×¾Õˆª=Q ~<¶6=C7Ýõ:ÇÞQ=¦„ @º_èÒzvh”[Þç¯ðQç`)ÏÒ½WxÐÊ´\zÑ4Œçg ˆšà/Ywewu™¥Ùb|W‡â,ÔQÇÍ&#æø^ü»E¶?è¾'/œÞâÀ/NvpÒÂ!$T¾”Ytå@zãÖ¦€0%(„¤Ãbz‡doSçÚ7 §d‚ùRý4u¡M,Ÿ¬Ö9< x=4òŒ 5€Êçh@2†T¹:C,lŠ’™¶ÕJ i¡kh_‘=‹„ÓEZvX–ÞeT+éÑKºU]‚)°q™*¸pæd69qT{ý$ß”ÏÓ3ƒ'ööv`<žåôëwdÊS•ž½:›9ç>ƒ5LÖbݯ#=tpÜGD)qíË©;k VDÙÑѲOC„Bêmú9R°` yL²-¤ñÑ[wÏ}"¶V#˜å{cÏJÁ\’‘ª’¡qª¹Å0o¼´a(ë³—•-îù¨2’Û™_ÈÈžB¥¥5mQ=S¬‡¥O(ÜŸCÏVç¡gy§¯æ9CìMéhǼv®=«™%#À÷2†hg°«G Ê‰Ž™H4—°©jc_B!Z)Ðdð˜Ê[Æg|rµ¨ð¦±+o üD‚8ld˜n΃m œFt÷œ—Ûx’êð]«¤$°TÏ;Io  Jœ|ûð÷ªwD—%^X¿„SßSf3CBtaç'v­W¶ôÂv×yýMÂÃw+ýîmü±½3b[6%éSR S»÷SIxŒ¿«œn{x/ ¯óës‹tø2R^ÛBS= q1 B7wƒ{5 3L¬ÎÓÏå"<ƒ{°SÚö\FpÚ±©Ž¥´v-ƒÝ^qM%€Rëi¬›¾@ovÚ÷p˜‰º½ W¹eyK¸W$œ.4¼Êyó’U¢çé3hÂ*Ôyê±nëó¬p£wèÿo‘ÉsDñ^¤¾ê^Ú–}m¤¸¡¾"ç£{l°Ej½º£àTÁ¡s´Í0›M»©dbÝ$ } åjJ¬ù^íH©«Á!â¥C„å(‚iZ†¾xÁ"MÖpÕá¤X&íY‰S«H’„i ûÀRAžOùqô ŽrÑ¡y†ØÆ‹Ü Kîͦ‡Ü$XŽÏ)ß!Óööòµ>†8;˜VÁôZ¸…òÉ6¡-L-Í ½Ý[/¦‹J`ÞáµÚóé™.rïÕóÁ’©L­S¼y¤FÎý€|LKÂKêÐBɇÃ5/éu‹wÖZÍJj¦Xø©‘úâÓJl»Wkóv º´Z‚¬·aBRˆT嶇晙-’^rӕˆAh!F¶íù›YrÕ*¦­ôrß ?MÂA}Pë‰=D±N†Å=v´®"œ–ù¬“%òµDŸž¼w ørÐ…£Õa*¯C6ìq<¦™œ§¸˜Ôë+sż ó%ðȉ8à ӷê~38£{„*<Ä> -m K6„ÓÝÞþœE6Ýý?"ôE,^^Ûî™"}²Æ¶%ÐIBWŒN[Ñ€o˜,YÇ]Ò½ÃË£™×M­¾™ÇBÄ»ÏJ·P^ÞSÂ:<§çôŠ_š¯æMó Ÿ”Ap¹£É ‹t€S"~ºÔO¥ŽA9CïhrRíÉ}*éŸom HdÊ+òK“ä<&"ËÛDÁó&šujˆu¡¬ìNZ6Õ÷©J ‰0¡I§âºù½÷æ­dÔꉂ+w Œ«¸•»¾MÆÒýå®/é8ß³˜Í7Ù†ž9UqÑÜ'=Á÷øò6=ª‰§ÂQÓ´ef-ä”s»—«š{+gKJ\VÏÍ[îÚÇÛ &³ +µ€…Èzg ¼¢ë`º'¨µ·—!žsBÓ{¢MïQûº°—"F<í„é¡^d#¥1 WáÊœ³ãD…ÚÝn¢o]áeæô[Þ%B–Gé¯ÃÉjÓ—“a_NªeDµ‰º“©Ú{.ø@àv÷Ô‹Í/Óäg¯W+ß>A×lµòîÈ­A»­‘žÔœB†‚;bŠnCÜB™l2OºXcîˆYæˆw›‚­”¯u‘ñ–Nî°nåMƒ¼|›YÍzÚTpÄ/ˆ1”™¨eÿ“rɇ­&È*ÖAo"úCßÎËî CzBx[3ÃHq²öùYq½Ý‡ {ìØ…TÎØý +ø™Þ³`{Ìù4Ö¯t¸ÚN¦kK³F áÐIViOá“Užà \d› gÜAýV“”Ë[\è@¹w˜ôrõЖ¦€$­ÐŒÓÍ)²îÍÚQ6ö­†j_©Ëy›V0‹t´˜g\6¾ŸH‰J÷fg3å’~ê§2&¢ð½å~K]šyžÓ]–ýˆ<è^ÔibƽÕ`é‡Ô;씌ÖâooaíP¬=Õh­œå– Ùh%ô6V»ýáÎв¡íôÙ{É$ˆCÉ\šîÃ9Ô4vÁjt€ÖžÌ‹JF‘@Fäè±VáÄqÐ ,·Ù^?hÜõ3.÷A§–x„[õDÞ™ÁšU5¤ös¥Açr°WÍÅq€Çäp<ðš¦õáhÛÀ=Íõí+Bܤ÷˜×¤­[®"øxc³’T„‰«`ëc„kÛˆ`Ýב:(²ðXº™Ê¦…ŠÅ^€ç{/·lB CÌ"ÎYB †åü:û5ÑRôv s‹¤¦1f˜¸y÷bªÊ8mÓuµ6wÓ·@’<Ô@cɘÑ ç Ö´^¶'j°ûh3½·DÜÎôNWKsÿµ’ׂ‹Ôµ™‚Ì:^m¢Áˆe¯f\ÊË—ë›"šå6=á‡Õ›šzÍalI„GžËód‡XË­/ôx òÕpç‚­‹oiÄ4i÷â ºd®½UÛ8ÊʈU6žê·ÑÔÏÚßͼ…ew©x˜ÅkWxµY°—Jy-´ÁÍãÞ³yreSSoR,#i®^5?És —ÅEȉ¯'’zžPhøØÅ|Áve­ê¡×^²cg-úF<¾ƒ7½…1óâKÏ´ÒÔH”¤Ý`"e›8HR@mCð³N‘ÕAÁAc;ƒÇjqÔûùLàíò3sX{B„˜±WOm/¦S@ŸdËåB¾yôæ…b#Ú‘©Å„ÍjNú.VßP 7³Ÿ‡¾Ù&–%>ML83ÞÚ®ðfE Yl¬ˆõªñÝ×J^hŠ¡¢÷ª£šQÛÝðæmYÅKÅÆ4^(°|\(=Ħì\"Iïó ÂõÉÄ¥;ú´â˜ L 4‚¬5;†ƒ“?5yÆÃu»DX—ÏàÃ7B(ÝKפϸ±H÷ì‘[Õ[‰§Á… ïÒrÞ³NY‚‘õœy¹'÷PWÛkÌ×ybô‰¼£Çׂ÷ R·nzÅ€ÉzO¤P×MçéÓèW„øÚÖ·¬ôqxEPÁÂãÆËæ'íõrÑZL²0Rt_Z޾zÊwBÃÊG,l £.ñî%ÒJó‹£µdV$ ›*¼h¤ÝdûÒ’às³Tm„Í…msi´A㣠À:²vZº!ʈ~8%y(3Ñï˜wRéæñ¾n8šÚÇ2Îx0N0`£ç1Ù-®EÎûF^æ]c"h—%PT>\[u{㚪Í>Ç{Þ¸¸‘Ïj ;³:-È¡9¢ñê%Ò å^ÿç%bëË—'ên¼@â¬GéV]ŽÏX¦zKùQù1ÜÜ4SzN-§×ØÈ{¾Éœ×`ü‹pu,çí&÷ó»<½d †à~áLj‰NŠFèÕÏ^?Ý"¤‚tQ2\'>!—jš¾kkʲ§IÒ}s0«gƒ›áá(l¿¡†n)[!UˆΖ2 ö{û@H¼ë޵ÉÛP¾Š‡qé™ÑŒqÝ¢+—OiŸ ]Ì¦× /£)sƒXËÑ>RI ÛÍ­é‘9Œlôò¹m ¼±•6ÂR‚[æÉ¦ñœ^ÖØ\ÝyE¡óâõu™JZ¿T­ÀC5u¥¸”3|~)§½Çü -òP¸_E9=~a=d}ãü(›ÑŶºhzÁ2ß5¨æ+#zø¦|QõavNÈø$)\ù«„’w)ƒ)AÞ¾ëÓš=Ø~‘É~xÊ→ú ´CªGaÎa-hñ5r%«q^‰lüþg+û.Y9Þ\«ß¾£Éœžë§¶“§5É>¶¸å‰àÐÇ*GYïÅ/U÷3nÏ~Ü6Ž˜K¥¤´v³ýbiãÇÃÁ=Ž¥D‘uÙuð×ö8sŽ[¬e­q™ּ:ï¼qeSEe8í=_YT;ÂXtoøX­ „1ßiaY_>ˆÇ–¾g½‡%ª›O0ð n÷ˆ!1ÂÞz³g,o¢)ôPÞ§—þå%ínZð©ëÉŽ»iU®¼´Ïíy-+µ-³8Ð è|I€ ](©õæeÃÚ¼dÞ+Äêã%¹}z×3c­MK)=¢gÜa4€`¢ >lúP@Ò†JNä© Ë<‹ðuˆfÍDC}SHŒC]BF¢ONEÿÓ¸­ÄK6°NÙ¤/‰)—í¨Wè ¼{RÆ1Oànƒ" üjßV>P‘ fl®d–WP" ·lõ"˜%‹Ö#ó¦Nô1:Þe¿{!Oã![ÜK@÷Ãdó÷‚HÝðõSÂ>ÚŽ$8¾Á¢J‰=iA‚~†¥¯Ÿöz¾¢ wjµ6œ†åÎNè1¦uǘλ`6 _}Ühd14j QÛ;ú¢šbMÁqóB•ò?¾t “ð< Ø:Ÿ§¦œïa^··àÛƒµw’›Þ·{µðmõÙîyÚ2»HDq„)!©»“ ž‡ªH¼:¹XêniFÝ—ÙM’ïe"'åÞšœ‘æÛSyqÓü„»Qù±„T#!”Ïhi/Ha@:‰šeäJÍõƒ;Ÿc Tò Üx“ôe^ëË}§woÅÄž"ÉÀsD–Mñ+ŽW¹âåJàõboM¨ž²!®ÏsJò~§8ŒO\aåÆ0…ÉĬãƒÁªWšŽXÍ 7`GpÀ½¨öº§Õíq¯iÈ#@ݵT}ãQ²Dû€QKà–D?« ;ó RÝ=2âUÆy<¨˜ï˜P jÆÑ¹3ï½mƸq+å¼Òâ&æÇû#tÈÆcnü´’ÂËã>ã©€wqfº”4Žœ~Á?Á2Poþ“íKÌÉBœ†yS ©®§ÖBŒOÕÈ•„\"Î,aÊäeѽž»TáÕ«GˆP&æVýÊÜ_*{ŽHƒÂá cµl{ÆQ‚<4'JöðØ•Ì,i<4,0\Ø—ì~ÀŠrFD‚ú*jOˆû=çz™íÃ0¦=X•>æÑ4ÿš)º0ó®7u1V§Úz€G½©²¥{¢ò ôÓ.·7iÛÓÑ[ø^V4ÓãöÍyå§Çe:Ïî2Wëm­)‹ðFD̨ôráBˆTáy±tyFìDßuÈÒuÙUÂ@»4u¾ÆšØm3‚]¡ìÑÖC'â Ê&‹b‚j `UhÕz¹ê ›[vöZŸòCÃ=ƒ]–Ërâlؽ$&éð¦ÜW çIÞ›Ô¤e?§ K·T°9܇o-/]«“I£Ÿß¾žõ;µÈwçÃÅX®õxe ¦Žm8‚¸+#œüÁÌ–Rve¼Îus_b`“Q㇚Éñ)Ÿ‘.y$f¨ù ÙMM¾*"qð¢#\Y‡¥C?Ù`* c+n, &e—âz)¶¡iÉÏE½ÜØT­À¼¸µx ‘.CÛ‚Õ7jp(o{M rº)Úv›‡-Zp÷":ľÉ)­YAgñ \†iÓýM)Ê¢¢·UÅGj5­G‚_KPÑÁó gïÉžY&½G††)èN€a}kB-JbÕ)òrW.¼U=4Ale´dß …Œ¼jÓ·÷^(ÂCñBÓq9ëh‰ôÙEËGž6ú®¹Þ¤?R˜ª‡w‹yúF“ÑL:`”ªP‘‡é:(‘˜â…9Ê[`€¦ vãØ/3E¾ÌÚˆ¤sÈ]X¤IÂrq‡%E Óð‘aƒ4Ã1l9ƒÆ1ézHjvhLçÃ^"”hB²®1ôæy¿Š¡GuÞ¬9•×ÛÍD%žI EÁa4®nJYÙ5ê^}ÖÕì>Á5Fta;*†Ò¤e™JO=6ó®ß̽ÿÔÜÃ(tŒl‚–ØÅc\¶reÃhß0˜ÄÔj7{ÒúŽT×!¢GôÑ@\jùkÖ®^'>Ò ÷PQä¥}7A©šOŠ,&çë‘…AÞ~íUÌDX$¹³) ~€EÈ0ê‹¡葨Y¼9w΢89·™ºÁ‰wèô޹ܕ¡Š"<£Šz¤jöž®m%ߊž? x´Äb@KDýÞÜx7„ÖãÁ"Æãƒ(¦íéz‚·£®=Ïx©ÍˆëˆƒŒ1\ÊV†nU½Þá‹Çé§^k6óruV[K,@õ<ßiñv¯i¸îÔ­´Û°3¬ uÄŠì±fª–³XØ´b+ Œ¥gCtñ¨=‘0“­WVÍöZœºÈœ “%#AQìòä9ˆÌ^.ì!¨£3$6á=ÑAŠ×±'åO6d¤Îíæ=('ÈÈÄÛBN¨™0“­ï¢¸¢ÒÞµãÒSÓÃc~žFБ¥Ç€¬±áø9À2]À,u¢Ã½ ºrp0¿¾ÌƒmlÙÄyF£…œeÞ«Wìt÷–4 £ß­÷à1|¶u Òò\Ä^?y0ÐPí îí¨ŽöŸ›‰HbcŒù:Ž9 õØÈ2%4VÖ̀rÌ–ØN6§cý¥]•.ƒªÞ;q}8õ'Šœ=”tëNŸYÝÛ~Ifî} ›‰–ÄP#à‹øÔê`cšÉ4kGËÙ„É`î•z`Àóî8£¢A Ó'd¯oµeñ Â1+¶î¢ñ ÇSR{ìÛ]Ïmë"kQ¯µP‹˜]ѪüZaÚbëF—ûúÕ }Øo:_Œ¾x ¢òì½bè™7 ñ8×tlŽ/´ÆÁúx¦4»®4g3ý™­a ͽŠå¥ˆ':†LÀú0t:å¥=^b•i`¼É„åI)³É˜{T àñ“ig,‡uxž“o=‰Ú‘E3}Ãìöcm¤r­Å츰\jšÔ¥ºæ!yƳ¶ö:Uö,ò '\#ky¥»àÊpG”áJÙˆÜj0³gÁx¶†¢Í«¤§kd±o®G_£¹K›caÍó‘TàŽj ymÚÍZ£´oiàÚ½¨ƒ:€¦žŽV6¥&wázU#"çÏ(`‚ž× ,VÔ±{kØ’òzê*ã£Ñcª!{%ó^>ë+P?µUì{¼ožvHŠ¥là«Ó§Noø½ÇG[šª$¹9ásN”owIÙ—ŠÞœîº«á{ZãFt<ƒ‘Ñöå¦Áç ×Tê½.T=í÷âašÌÅê°4YrçX¿³b€á˜- ±ÀœL­•J7 Èx&äÆ:ªdÇb÷¦¹F¦úyD¬)‹ úKÇ‹œMn=R©vR+@õS±ÇÓÄt¶¾um­Økos „&NßnKÝ¢EÞóâYñA~sräÿnœùÔây/V¿wÑ.‰ŠrüzÇU €Éç$ÅmÃÈúM„¦±ÃÞ¸°\jðËBo÷NqöŒµ6(~,žIݼh…ïv|$¡‚ë&ðç@>0÷Gñ20i±ØÕ”-Ýór&F åZ»£%­»«ä]<øÙPºig§ÎƒŒ«œùÀ1ìž„‰Ì r2¾wB„¤’ï:¨S;IpTÚWM)|¨ò® `*ë°°ú ”Š ô],ˆÔqMêô{@·Uïùà@Iq‡w¾¼!EÒ°­9 óÅ]í'•dɺ(NÏåŒ\F/ñuµ…*8õHÃ8ݪcðóYdTpPU°ò­²ªòÙ:Õ$/=d…=ÍCŸì‡ ´Ï@eóÈ—Ic×HÐ>],®• ±åj…°J ¥}…oêtÑ }÷Æ[»æ‚d,:xÈÏÎZµ7Á«æ’_Ÿ=K’Y§#öçjVâd‚¯ƒŒ‘R(¡:£×Ïy¸‹ÛØf–E8ç&Çét‚ÈF"ï ž;…¦¼‚y–'ï]çmÊNÄ£o¢-S‹Jf– 7Wì‚‚¾¤Ê}ô)§ÉidgÞèi‘¦¨‘ÑbµÀ£ajáG“ͳïEùÏ£h!\8 ÕDë‡Ú¸KÔË[&Z^rd|f°É@Ž»5ÖÞœl\ËÛwÕB$_¾ˆ·8Ñ„FPÊVS£³¤wgÛ®ÌH²¬—)y6`põÑ\y$:4Ÿ±êþg§AÌ[:c}ˈñ8MtÍ8¨§e4½ã¼ˆ =ûq­c>ÑŠ¥rv”Tz÷|Ô1î‰I_ëªM,Ý I­Q7íå]Gðj0¹rÀ~¨µ«€¡ gEÈ&ØtWB“ \¢âãt~pêÀj!D6SP³òF’ôÙkÓÁN •Ác>x;ànªÔÄäfa`ï²çø•Ž˜¦’%9hu¥ù;à ‚V.g1}± ÃH87«\œ°5‰½„ÜÏg¥'“['ÚFSÚ,µ”‰_¾ÕqXoœ’0µ%/šSh juH£]]»Gæ(¬•ù ¡ó†º!FÔXàQ€„É•ÈÂKóÅŒƒ5.—·ýte0p9püô¬¬CbÒ&Ú—ÚMļt)ê*: (z޳§*Ã#>#Czoû R ‚€„cxYs…ìõ>·Ñp:@‚‰,l˜‰MA`Êgk’úJå:1bmŠ>c¢š$oÊwîì½wþba>_ëÏ>íTL»â–rè׿m€hO× dK-ëôšA“lµÉ{N †Go_†sÖॆç[I}¯ó”¤•¶ñ¹Ëà *o~GüB;1F5FÄ: ­«§7 ^\"õî{u’…¥À­ÒDj9O‹7ÛntºÂ²S 8¥®d#/Ü{»Žr5^W@¼øó<0†±Âç/—ÈŸ*äìPSåtI—áf÷9 êhËÐ5áñMbç âYMtŒ­§½?Ïzôô=Ë÷D¸ û+ö*ÓõÅ­-Ý>-‡›~œCÐ^p9¦×^½{]¤¢'¤nYþ¢ãN‰Ç²ïÁ‘D måÔ$½a4ϧÚ4×ÜlpËïµ'Æ¡˜ž¡¾¾{–8¯=í*A}Ôiôh1vÔÙ˜ eR-&¶R,h¡ c  € ê :ô^ú¥¨Aa=ÔG¯ $}ø Âd-å´v‰˜V] æ6nˆÕb+l§=;y›CøÆü¬üXÙÖ_Ü,Z²ê>t}(|oàu$Á;Ãò('V9H Ç¹È†Í{M)ZÛÌëiûÒmöVñ, v»Sá-sŸ¼Û$›·ö.ýW‰&Éøi«ËäS-î’n·î#"&îÖ™n à’W¹Vðj™lܬå=ÒNÝtQ)}˜Ïe/4€o‰-”,hP¡OpS:„¿Wà¦¸Æb*ÚF ²^ *°F§MZÙrlÀìuΠ깦da/ªœwµËÞ\>¾Ü IzÓ‘¢°¬m0Ñ'¬!èT·1§'á­4e¦GÛÓJ»oˆ›^¾xÀOÏ6yï8––¨ãE–úœÃÝÔÓR?‰üÒÓåKOÏGm؈ç8Ë9U*½ØoUѽ73Ã}4‹‰‚ýĪWQ…Kßö”4™Ñ#Ò|á³Èµ‹°·MO\&Š0Ù,eÆ‚5a& tô 8¤CÎ.Úýë'×c`ºjQ(©×Ödœ•Ž‘ÝEñê‘ô„¶*9\½“µT@Ç›±„0i£kņ+x!=\Ùc¡ NEh‹µx~ã±ïeN“——cÙEÆUòì°µ ¤Wóº‚ÕmùÓ:qF!sRE±Ëzõœ Éænãõã—o´ví=%i)åè}]’e|•¨: È £›Žþ¸=E¯œ›¶1)±fF4³ª[Ml°!¶$ E9Ðæ‰ìb¤à#ዎpÒÐ€àŒ…ÕºC·~úòуe r|æ(‡oï2¹h‚n¬*µ§ïQ±êkº`¨×/6ÎôqÝ«+„Ê™âòXƒx<Pç~M­E¥™X°#æï]™˜<²GH˜B‚!Ž# ©»¸¸`ï,ß.nJ¹ÃÜsÔË0õœ˜1aäH~Å·Ubêš”Oja›Ê«·nüŒíÑQã²"®!¶½×T4Ö²Â/¨—D.vv2ß² êæyk&êŽXi@Sk¤è]˜>>/÷ó9zÌåÜBÐE€:µÝ¶€b¦¯'—û% Íêæyul ä»,¸äW$V†èÝjà¯àôñÕnÔ@K=P¤My.ã:žûtÁÏm$%Gšäu]ä½&¸Q¦4hF$±.}Ôï%kWG›Ö ܼMÁäӔ܃ZÀ–9Ë=À|L¼ø(ÙðËÏ /?•/Ðo `‚œ÷l:pv'a6z«IV@Sâ›Ô ~caîgê O9T×{˜n¼ÓvDÝGŠW¤‰Uç°•QMæ8ëSfM{Ž‹Ø£ ¡õxNÏ©=—sü½`ó0{¸!¯[i©(¦GŒ' ¡#(|’ˆJ“E¡ªaD|é_A«’墼Ü;\q±,ÝM0ÉV×B之ľ{ÞfÇ”YàN±ö ÄA=©Êr»s¾Wj,ðêœií*=¬x¡9Ûé¼mÔ‡„’䩌ÉxÂú”€n*…ï­ñ;¡x=R´âí/O²Ší™QÓ¾ñh骓=ˆlJ$z®£Ú‚ÒrVLžvÃòÃìe‘âÚÅGóxãRúnÐÁàÁ¾>ñzDÓÛðÔ¶p4ÖÅqöˆk.$zÉÅóK¢4˜`ôdçê¨1M™ÁjeÕ¢Z‹ êysô;…ë­ nù õs ÁÜ oÈÜg¤×þ:½ëàõLTØâ‘¬ói¼—ÔjèÆnä)½°èÌ”£"µp`0Íh»|Þ ¥”‚h7Ë»±ÖïÚÞ]—"ñõrÑK›‡[þtÝÒ »ŠF,ŒùzáJ°òàèv.}ãáÓgvÏýÎÏK37÷„†nÓ=¨ ‚LJ¹Q;gBÁÆFgq‚ÆLÅI?írÑ·ÖÎÚrðôb¾žâä«(¡™XH*7“Ú']ÂÙ9öºÌÝ6µ«}`»_^i5Ë¢Â6ÙÊØøèAk²Q’wøŽjB°ÎKâWE’‰>‚SJkQåä§Ióœ8ãyùžX. Ƀœ–ð"ƒ ¿ÇNUàÍ'ô@ólw>Eø"4M4¢< K»·cíåÎÑhŸäÁmëׯò yE©Ë¥½ 8󥸪1d3[EóII´ãÐ{ÉÍÎT\ÈR×Ñ•:”pKJ'’mæ¸e#Ø8@N·c°õ‰ñpëQ•·åcÀ+Ñg™\z¨Š0å¡v÷žÑœ+ŽÒˆ˜=Ü5…gDEE ífòRT0’„sNö]õ-Ñ»KŠÐJŽ›j­\t®çö@ÆqïðÜ»ËÕøI¦ÅÇ_Å«óõ/éݱn×gôrp/A´WAo÷?èKy^]’‚O™'ò¾´‰ˆâ”{‡ßþUß'm!×’y™ýºÒY/!ÄœO7¨, %YVNpvÖùÚ)VŽ[ï9?~i>×±™Ü½æ´´»qn0G.cìٳʦÒ‡.+•©…»å¸{p§þh¼ž/0³ÚÓ ]J»z7ü|˜€ŽÃt®’0ø.y2T¶DÄ­AeÞx5†È;:o½Q!V±;¸YCt‡~Rí2o´¹ÌðM÷‹=ݼ`¢{3nœ©B.ã«;LDG,¶ ú4JÌÉ8îÒ“ ú¡¼¦L0 #»zQ`;¨;Ñ©ò3‰72”tŠØSÑø>£½ lja%¥„á;šêþžîvÍòö#$”©—áØŽ#ȇSÄðÄ*uëzù¹?›óçšÓ ²±èÛOßs¶¸§h§„š4öZZž"Xúq>Œ:çåb„1¼œ©@,2*ác¼ŽåÔ‰'o·®ÝÑÎx9¼ã¬œpàâ±Äm7Mƒ^ Á­=>åð»uò®ˆâÝ­u|›eîÀÌ1>Ú.z,âïïzJÖy|™ßdWOë;··õ½‹¢}ï¢t­¡%¶Æl«|=×>ØOçádÇ<…4dbŒØÌ&w‚"½i…6ôŒ1PK ãžð$-CBTMaU±f¹ÒW䶤O·m,ferŽQ6¤µÎ>ÓYj~ˆõ,–oV$ŸÚÝ9e‹]úá‹7\”¬,ly6U„#{—S´)«™f@Õê?H—ý¹î›Ûå¼*[­5 æ0nnt/e½}T`›Ï‰\ ÔH‡)Iª×K€L¶ Mf܎ѳoÂí×G8=¡Ì#®IÀ3 #ñÐWŽ«(Oµ§3(Þ.œ9®l&:#B?ò*ˆDšYµÓY*9o|ŽË­Œk#!â)iµä®œ—t•„v¯}©WVfÏ )ºtÑKRC-R8!tK¡{œ´0‘Šï[ÈÛ|ìùœÁÏo&Û‹Æß‰ ¤ïël¦Îgxnj˜3ãÌl芽O#wwdv0Ú„ªm w€…ž•Ù8úú Ì×xBç²^@6b¬Ë5E¯®È÷)¾:3ªŠÈåä¶ðȤð}–zÁY×Á\hé±Ë[ä®›Æ jãPë!TL¶‡¬FÜ&!=.ZàYýÒ»FŽËìÄùéÜCÕjÍç¸ôh‹se¹/q|8ê ¤ð“R¦/J¦¢¨§³ÒŒr™kÅ-)¶Ð—«rR;!é¡çU±0Š‚iˆƒp÷;2Rr¬{³dªîfIü@ZQµé´;㨠…6l iŸq=0·!,r¤ÉÞ¶1Ö›Uõ 9²âµ™Õäpèv  zÄ€\Ìä¢.uGÏôùÂ>xé'ùÿ±‰B®Ž[KÆŠDرvŽà¼š'PûRêâZhê,˜Nd:ŸÈ8RWœqd4?k‰^î70do^ˆƒ¦á @¿8¡æW èmÏõ•%Њ•%ÊS0B0Åe,raCP—DHx5í*-¶ÆïÞ„¼”¦9½\/ÀØnñ…l€†w „Ó¶úq‘äb?à« ¤ÃÜ×ÄÉ÷¼¥ªŽ©šMÙŽ8 µ&Ɔ˜k¾î]~†.‰P»c“oÉSÈ`ïêmÜKHè‡óMºÃ^?%K8Ü9¼SÉ-DAˆ{ņSš¹›Ã˜2âa]nª6d³½ð™ À£Fª½Oη!zh'°d•Èp;”_qµ´=@ v¶%ÊR%éxqؘ§x•IYÇ{kŽ^“ǯ·e¬g:<#¤î0[Ôß(y¥Þœ…:YÙX D‰´±÷ª&œPg.M [0JUF–s½Ìäª]\ºd?`2ÖLÕè4 0Ÿãè>}è–\ùfÖýNÅÁr=*9žTLC¶`íÒóå­Äâ9l K_==òfm--}0t`Cz¢µu2KÏužTÇáÚEn-å*Â:ôòYA{Bç=3ˆDõ+;.|ûÈiÑ|ºcŸM=\v)•ã,ŠyÞnn¨=,=eü„‚™”çU9•(÷9Å1WDùªU€µ2Ö˜œ}ï¥_˜³ÌtÄ«I7Lc”3YõÓ»…Vˆ9[o•ÎmŠñü>ͬ„VŽuÐÆjqˆ§]Å€èH†…[Ùr>‘ü—¦¬ÐAh·/_š$¬>‘·ý®k-ß9©ë=Þ%"¥áWR'dBnÈc%¤/âQBv–‚ç3‚Æ.ò-Ù†kA6ÜþÓXö¾kâTš§ÎnûàÉP?äBt秃ùÞùµ7IJytj¼8u š€)”¹ºÎÔ=Ȇ¦A;^—µ{sšì2Àñ¸(y“g¦tß=#¯ä%XUãÊ1«fªºÂÞʧá™"í–вƒÀÞ½…À™ÈètâWlÈPiªÑ®jJ%ÛVâjQfýÞ©çÓWO›ktîœér`;£ñ%Â;PŠM³ƒ—1Íf:îdÖĨp¡¹ï™¯&ÙKOáÎg¹ÑºsŒóZé¨ :¶PûäkÔ¨vÊ»m/ŸóˆŸZÚhºGus\åÀy¥‰U=¯d1P"šˆá¡ µ½ä¸|ḭ̈rKÜ‘ƒÐ2É‹G½#Š¢\<«¯ðr¼„²w –0üqÕ•‚‰±p‹õp ­ËF¿=ÌÔ¼Qç3×$¸«×`Îd=ä#*÷YšØß\ ÓsXDûµ.'ŸIH'TeØB½c{3ŒF<Ó(ï⮩M'ÍlÀÂßÎyN/ö“š|ÕÖ6JÆË=ï½|^Sü†­Ùç Æ¶ÛMhy?õrv)ʾ°ëבe#ܶ»uFõjõBϳ¬(Sô—x™ó¤K̉æž`£tn„öî%´[ñ̢–³»äèŒóy…’­UãýðTß³³†MWçì µüæÔ¿8]÷,pó@ ÎTÖÞ"X“~YñúͰŠ?7æðx©ÍŒ*ÑéÐlå½'Ü}µ€V"äãñØWÈNïÖÑÈßáËí;Ãz4µKÓaè}KŽsYºË^„î( ‹L³º2ª9>rñ ,¨²_Ôj‚-¾wëíÐÐΊqÅ,o6NxT »áU”îü *< yhå:òœ“ß9­ÙÈiAåºÇ;ܳ¬ãÔ e2d~˜rC`€ |6è¯wìåv!–¤”&ãMÍIRae4ì4վǀÏo…5@Ë!o¢‡^ucëK„ã:>r­r˜h9ì; ‚ƒ;DÊnõNÞ{ž€{¥‡àVKÄ{3à´€OuGñåXò ñ Ê{†ZOÎj˜ýpVù¡f2V¶Ë½ÕÚ™ÎSÓ'FVÄÓ$o w}ç½gpÊûîVì©I&£F&ä jÆ4“Ò„†¡¶ãŽ^ÞB˜>õ{Äf«0÷ní¨— ¸·.qJ't°4ì¶*Áb²aJ"%ˆ&)cLxx[”QÎâëXvþÒüì9êJž¥©Ó&ÛD­NWἨIu<«¦Üy©,Íœ>è<ºsBÇàP¯7æ¹É›ð|³£@8¯,ÂÆJgŸÎàÓu‚GüJ•Ð;žððùäQ‹m±›*©í†ÁB8N½2M¶ R8#`¾y‘'ÉÖôªö%׫Áuäã¤ÄÞ*Šx1 {t …ç{P5ûÀP4öˆ¦„½³fnNç| #Ò89(jqWt¬—WÂÞmˆ…¥šñIg¾°¤ÞzªBótÌÿ#U]^ž½Û%{ö ´WÀèU Ä¤ÑØ\r“‘}é»É>9 ãÖX…YjÔpÓ·v8+ç ¸ùøn*ËIDö=ñGȃ¯’q©šã¶F¼‡TÀöE ¦u€ÐHt‘Wáµ'¥ŸdH¤ß¡?%XË@“wò¦D¨®è=Z__¢›§qî(Çd¼PªjÖ†š' –ÛS©3ÏÛ\ïã±îØ4Ï‹• ºxèWºYô ©ždq)aIëèìEd4?µŒ4ÅwlËh uvh”naåê í) ÃÔ«ƒ'B¯©'áÁé>_ž'ýÉL…H]ˆ?£Èðë–—\o½g¡$>€½‹8O3úŠö¹U>ÑòU“c.H¯Gû}IŠû(YièP`7fŽ@N(Ô^¸#>Øìa‚— ­—ØËT*âMo±¼ ¹‹>á:ÔÜ=Ô•FÖÂ+<±\vÞ³qT™Ø ÍËuîëÈØk(ÚW' ×…©èRóx!ÆH/sœ´c2JÛš`€²&éºÕKkøVáÕ ƒ ;†"4R5ñÒLÉ=Äé¶SX¬ÊÈlœ4aå@º(ØÀŸvw>G­ã–øÕÕ7óæž(È) @9¼0ÆS¡T&C˜÷fJêε檣üHY)“'’ “¥ß»3ÃâL‘e¨)DHï-ÓE…¹ „Ø ñ»Cì<ËðbâSZ&^¦ÛW•6"ˆ»ËÝ÷‰&µnÛ+h!ÆHa&Ù4t½¸’•ö”|ù¨@‘¢$!£Eßûú0¿‘•2-'f{*€=ÐiÒ§C”DfÏ7e©U\³¦s7çö ±cF¬÷t ï À)A€c!^Söê _u=|VÝž»¤è$†Ù˜"vœ!ϽX‘Ë}fN§ v¯‹{H•-ÙÀN¤´Ñû‘^À»g• ¶­ ^ôÆ‚úf¶žÇ*c% /=,½›Vêy› ådB@•ÔÂÐ̃aÁÙJŠq"€Y—Ѫ¡ lwØÚëõÐQ\f -ò`+. ´½«ž1äÇð²æZ¥a­ízÁØÒ÷¶w‘¶üu qÝ`Û•?"{/¡€„;c”ÑSW!€ùÒîñòSUų}èôÝœt©'§ñ‘'>æHgÍÇu„Û€¼'Eu]\‡l‘þˆ#U,ÍÑÆë×öÂÑÄk/ÝÌt÷ú„cÌÞé…LzÅâ¾Åð{úº`yÛÆ»üF\lù™Ã³a¡›ƒZéBÖ1¿<íàË«G~nƒŸ¨>úBõ½]©8¦Ð,b£^ ‹†)pzË‘ÃÃXÕŽ¥¸˜\ •ñ^Ô‹´px ¨àftÓø¬A=Þ²FZæË{ì¼%ñÐ)ßjî=`_é°Aæ¢çøßr ²–.–âÉßy+#@z>í¯¢Ñˆ ¥îx(Ö|ùÑìÃp`×שöz&sB=»Ì»í?V­ Buº<͸lúN¿åɈ4›3 ÒQ}·xò PàÝ,—¾¥]iËŽWðž‘\6éÙ"Ÿ` …•@ÊÜÓ3ìQ%œpjˆqj|ÉfÛÆbËJ^d}¨µ!B[Ý wt–3°N•Ò@wDö8tˆ¿ÞUéJ~Êe©3v0·¦uýñ+xŒ@\VóÂMšö9Yô.ñõÊ«À’› ¼p1IÂ}ƒïž5V9¼Ù5{EA¥–Â)¢©^:\±J/¯ f_¸û‹T•í´ ›ÃIÄ×á¹Ûس˜—Ñ{F3æ6XE…‡Ä/ª¦ã’)­,Âë½õ-(…çFyù^ÄúÒ#<ÅÎÇœR{ö*íz‹jL Ed5ÙöCšôK–J満Áƒó2íÓGåêú¼e`ï¹^ ?€LÕ¡1†)§Ø—ñè})(Ù‰[IYrô‚U×a9t_ Ú<Å †{ç¥'£Iù”18·®o[Éø^pûíÑ`­l'µ­5eߘ‹÷¦i×iAXñ¸ÀC6$Kæ= «#F8 ®Kéà,'sÂ¥ &“…Ü›ó»d(lÜ·ìÒo…^R%Oħ™±CkcÙó{B­¯ ¹À]âÆ”æ%bÆCöšÑö ¼'`ÂŒ7#ðÄŸàäªr¥ˆ8ö4FÕ‰ÈÛ›€Ë寽‚Þi×?{Òv¾ìÐ ÿÑŠô"C»üö§§¼^ÕƒI~f˺­Þ„ ¯„ Ÿõõº‚'wŒ ’¢.k‡r¼”7”RÈÉú¦Ä΢¢¡Ã5õœÐ_]·XxÏL¾3mÞPqL~´wшVÅ÷\jÄôÉÕH,F‰®. úé«}“íd)ò¶Ó–ÒªD À0æÔܤùùA¢ó쮋¨‰oÓ…îêAô†-C€²š‰ØuZ5›‡jõ"jAîª>~)BøSÔ¤ÙFŒ^”¨o§ƒ ˜OÄxcy]Ùñª;×íqc*6un…@·‡Ï&®f+Œf¾‘·hÇa²¹´µ‰W±¶‘†KÓá>1é¤[zluEžL¦¯Ÿnî¾8·£^Ý;Ìœ2Ÿ„bJ©sO~‡c6Ès²½¦ Q#Y˜¼uá”xº‘6iF<оz­ íð0L‰°¥^ôì‘kR?‚ÎZnv7rÅPz‚×±±þ, ú¼üv¬Ñͬµl’ÆãÛa›¡h•B}ø$I…–ìhG‚2.Ÿ†ë­R aÓÅ»z¼ýÆ .ÄðÊà ¬Ãë=sr–.u.Û«aL;W·´ïÀ­ÔÖÛBJÜ÷Žô\¨PŽåèåLÈÛåNZ•ªô+ï¤w7Ø$DOuÓ{÷ˆ•µ+™—5ߨÙ3qEǬڛjÆv49|.ï“Ö°/ZAaÁ)å©K Ø"‡§eí“•I*;×µ’XO¼wÔ 0W©bÔÔCu³^&W„ó Áù½ÔRi€Ë±³u·)¶kž—¡Ús›ä±ñf†ðÖ–We/Ûd MóLKDEÆÁfVOüòã~/¨)bÃÜê­:á¾ö%QgÔŠ°R{o‚l²õѤ?n´„ù×—4·`Åy©R‚Â/ª¢_:ìUû€1”w⃳"ê3­;4?ª´er°µ}Ãf£œŒQMíå™ýúÕ‘ÜðÅ<ËÕœ‡ *Xnð<æáR­ªîÚÕf€uߪßôCÀ0Ùõæhê7ž€õ¢úŒˆ¹Aü-Ûb“Ê“EŠztxQyc ÷:nÖgDfgÂÌ]€BZ‹£<kCO’Ø|bpÍ!8“ŠÞjH1ížGQ¼åd>åÚHLj|“ aPI¤ŸWÖYa»Yz6Æ5¾&9äN¦1…™|âK 1<ñ’t”Ö4NJÞª­ÁÌó0ðSØ@a|[“‡¤Õ.ÑËïØwo=«¨°º±ÈssðZüê°C‹ŒŸAô¨(TéñC’ž ªÚ;ìÇeíSù°(“Ø3ÉJ^<ß+¾`lÌÇF-­·8IÃýx¥Z)`5ÂÍ`¼‘^‹u¿õ˜¢¥¡ƒ÷V°¨¬ÄvuÕRDŸ—”Oc^27GHïë•(GG …gìuz†ù䢴Mšò©îÛæ )"ÔÇàU#Žªœuã;ªOËÉûHÞÙ0áéU&‰^CqàÞc•Š#U Û3¦ ¾9’8%o·-§÷¢ô6Ï3ô§A_v>/â¢g«†‚Ï ßg~Ò16B\ú´µE£4s,i¾pE/\½7*gÈeB0â= éXä©—ÚCx±q-óÐФ*{úÁ¸“¡Ž {n‚Z³@ÏÅ{Ïýlñ ¢Ïª™«^0=Gƒ7èûÖ‘*á-ÌÍ>0fÀzxÖ·²DÚY\Ä ©¶rà»ä•A4Í“·õô^[<….{ãD†ÏZ¬Æ“âðòã+ˆÄ´å~¨~ÿñz•bÎ’¡Áœ9s®¥q[\ï•æ°W¦Á‹ñ!¢×޼½Ð*î)¼ÑæTÓx"b¥2ÂäžÓ½TWé²%áÓ€•h!¿PLrö™ët-÷%´Fd… ǦÅèÜ0Áž@Ì>»s]@c;}SQ4'l²M.zÐ0SÆà!¸b'ÍÅô^‚©ËëXîž>Džm®=ÍLl­ÀÆXÐÝ2;[ Ççõ è <¦;\É.a_QÉ[l|š„›,§dPÐF:/wÑŠ Äì•È=:dåê‡sÖÂb[* 6ËÍžQ¾Ö-omÐÇåj».ÒéŒ5"4ì5->¬'†z¢6´ˆ¸ïvu€ð•D•=¨½ÕšëEqkä¶ YÆ$h~¯I<ñ5 ÈCè${ëšÔ‹/'Ù^Ùfs>ÈÔ[~Α ÈÐÂô Vc¹4x–˜yHHóz²8ëÉ´ð`l0ù$ ®nd•CÍìaÞ–Îlª)+SšÁ[Z$‡Ù%pÎSi{»­ÔØ9Õ¤ jh¨í2_µ‘Qhháæ\‚{\¬¹2¬6È¢ £ø¤Zô‘ÚT‹\¤ÔõÂŒø±¶žg ®a{D \§âÁ ,ÔÉ$P`Û[xE™·È.Ö®hÒÀ‚ kxv1 æñÄ`.1ü”Îã2ï¼O^‘¾x½´Ý!™43K"G±ÂHejڎʃ8œ=ÜwÜ‘â+˜Ý”ê1AÏ(ŒÅÃH¹ôuÁ P` 9½Ç¦V¶0^›Ø“à’üØ-]@\¯¯Þ½÷.õ6[ÜB›òäY<Rï÷BøJT­Ùh¢+½s+€¥2}Óë*ZÎמP/ŒRKlúÆ“cCZgØØ—Ñ`ú°R¡Žá¯š«b+3òÑ"©ê[ «ÞðP5lËÐà‡[˜‰('‚Q’âÅ#D¥L†Ùd[áJÁLŠ‹*6ÛFùÀxüyúüx¹ IاâÚ~ÄSÄ‚»O8.Ï_b±FoÞ 0ÆÉ-‰®„œ&™’[w€\P3iå]Äè“C}4™¬ºâSj¡5¹ZGÔweЀ,G™¡èÅî;­<í—MèÖ ÷^¶©p6¿(ÌÞ@îyÚé ãahìÜ¡‚, ™*¾‘1ãp&d|+”Q~fØEå%šyæ|Šƒ! á‰0R‰¯Õð±“æÍ‹]Hfé}:r ÖŽ"HsJ–s'GìˆuØ–¤ÂÖWìÀÏ˜Éø…ƒàáÊòkÂå‡Z9Kjp¦x®bt,·.änRq¸F–´ŠB+§ßù!v>Ó ¢³TJù‚Ȳ*DÏâ1%Lr2‘Èø ;ùx¨¯ºâ‰“h@Ãçž*6 1mòŒ×#}É<¶•¦ÉgBž=üÆ,ì•w„…ŸYÝÙ^c d©>&$ƒ-éb¾“ŦàíN'ìžÁŠ4’l~ÙƒéèC÷$+¢Èœß½72©4 A²§ÚOÙÍÞÊ’ËôÃXŸÞx júà_3%Ÿ4Ý:¾Sœ£å&?]·ÎgðÖ≪{Î`V=q©à„o2?%ø6ª$K¢áa/w^­l=îõ´ÓqJ×Ç,l>»²…]ýJ5Þã²[yS l-ªN;ö–ø¤Ÿ¨ëd)Ä–³!¨‰ŠšPQá¶/:ˆ_Ë{mE™Àª!ÛÃüó,OºšÑ,+}Œ¼õíƒwP°þàu^`HMê…-`À¨ óøÌ"”–¿çìñ¸qB¸‰v˜uÿ#V»ªƒo‡ÀäI""Àb<—Ñj°œ »ö o\«›¾]&3=y›ë7ää1Cd È–U£;• hOÙq¤¹;L/¥'›˜­8X¨ÖáA•ÆTÖô{åOh¥¸ÝwcšJásjÉÏé!âòkt¨ˆ[T(ŸeÎ%º¢øÙÎè{’³c˜RMP Ï×AùUcŠHïYdzEé¹5²÷e²uY,tu+¨ñЫÐxl¾©“ÛBÏ÷éç«q˜9ßã(’ƒŽèI¨ÎžpÖ*o˜ä2ëÞkï=1ªE…‰$›“å‹xÍx=ôÈa]¬PÏî¼9jéÁ\¬H¯¾N§³³gôÞz–¼öÆ7 VšCì ¼øfør…½›6¶½Ÿ =½>ƒeòŠßP¾¸’sPƒ#X)ë~ucMÏï³Rð„Ub2Aà­¶³˜ 6Éà‚ÊS¦—âNØØê®ÐèðžmŽY„Íh¹éZXy ëKûF†ô@]ɳÃaËÇêÁ¾n°d”qXæ¢4Þm­]Ê.ôÎ&ö¬9R™©ÚG&ÐÞq¤ßª ¸çí+âÀšA`.ت}J¹z¯³ç…g[E¨bêˆî r‡ô¸ÆÛEôΑWÞàur‰mô gm”} |‘¬á®¶úÈz•¿U}« =“M-ï¨ÏX=†av¦*àé¥(áPˬŒ XŸî&cú 06ÛJm5„2ÞÕÒThjï´y[ÞÓ5Ó,¹¾óv…ß«HŒ4öA¨¢¬:.·'êæMîaÜl1ΚaÔ®¾bÌ0èÙº§, Mïí2· c 䲎]à½!4²¶×“ü}"Ëö¹ÇJ½K¨ÆÙ(œgø†±ätíëÔ×v)'2ò ÕÞ²Çv›œ…ù ˜Ì=˜s¶”7ЙÙJ¼Xƒa(¶^¾‹Ô¼ÈÑ>|¢•ÛQ(½{§)X©½àz[áPYÑ÷âÕxï­ñR4û<yŽnj$O›ð’ÞEPS,és b½‚Ư©Ú@<õŲ‹£S§Kxî“àápyöè%å0ás¢Ç§âgÙépù³Qds_C®zsKuìN7?¡P9Z crWÎÓöcHLaf~R’fè>ûøÞã;K}–0ÇmÝJÈÏ;§¸Æ'ÈåÙTŒ)Aú;rsžx§cK|GÙK9zý° € 8v“š—_ñb£d¯HjÚ .&\µç´#v ¹r»€‘òP°Ñ€+±³Ðã0\~-U°9r/–yÞÛ~…„ç¥MÂa*1„þæ”:Âv3´%¹åÞ£ày5ï.oŒ]Þ‹±24ÎymL)àA¤ðÐ}“hÌuAÛ]q3ÚÖH'Äp,ÏM6ø¢DE€DÈdZßIÁm°¾Raíñ4¿þÙQ[×Öºá»+r=qèº ¡d Ç|®ïiwÐr¦1õÉhJn.=5òäÎW5Aɱ£_/”4ÓŽ´ŒËÄ¢¦Ø'³"_Ìn ¬szq’Pãv[÷@=WNá˜,jµèk›fOŒÓÈ®{–{±ÉOèŽKeï ÛÖë•;ìÈâjÄè;« nà%ðç̬ YŽüjµzÚìŽÏ#±fÚwçÉ)H×> °€* MT±|K½km¯§|oÞ¸q¹À­¡ï ¶IžNí´¹`>’³P©L¤Ÿ·fsyÛÿA;Š´çV —%àsé½wðÖI£§» úöƯ‡C±vBª›@'Ljèe‹’¤¯Ñƒ0$3;7ƒ'Gôh­;‰Ó}4Ag´D¦Oùˆ‰¢¿:àñNŒ)g'½Œ²ãLJ],ðºÅM! ÓYé’¥¥^ù´°KSÐúÃÔiÕ÷´ò ”/‚k£T¿ d@î%ÞYRÔ{g¢×òžâØÜ0pXê¾óÂ1»\Xª‡ø¨IF#zÔÙ.¡Ô^W9‹ƒ4Ú b©‡á¶½^›éð(Ȇ+ާê8\ó„)3šk…Æå™BŒtt•,B‡?›9ƒ1Ê‚ÈxIÀJ÷€4‚[7s§c"‹rCüÔ.Ôº/qÚ´¼^ ±­êwxʯkf8ØÍmMWýP;خД-Ñâ(Eͽïùve+Ò›å#\çó‡Ò0fÏX C‘x£—ñTêñÖȇ >{/cÖKòA p°ãN[ãK˜5Êü„Vé ZÔ7ZoEáÙD’=y6Ìθ¯ê™ H7 û$Ò ñ¦^çÕ,é‹):+õ ÄÑàÑ{qz˶|épG÷  V8€j#z+¯rOƒ*Îë(*Žš€ìfR‚®šš¤–wµ©ÞÅÇÈ”d/0|òœ^Fi+*b®Ä3ë”JÀî"²µ·ä¤vÅw«s 9àÅsyÙ7¯nÄ%ü¬£J–éèቋÕU@-@9è£F}9¬*Øï®óP-ËLÅóM€¨?äóEØGÚú4Àm˜Íu„wÌ©ð”EùÁ»Åw0ì1.ñ–ÔÕlƒÁ¨—•}'Ô{Cá„ $5Í‚L[¸ $˜S¬¹:½Ù\©A<*Ìv|)"D-ÄKS0Nhîñ”É¡ÀXð0šúáÖ’=âç@‹[×éF@/)r+ç|'Ò€Ãy¡¦j]Š'RϲêtÑWU©axŸ¾Wa†Ä% ’y„ð΄Á^¹ç,ŸßðY¨vOä¼E–ŽÓ]ƒ³ÉçÀ”ƒí:¡š08 å-ÔἸwÊ@æö(FdEò¥)a9=èÖ×íi‡öTší¬_:ñ%¸W½É·»áÐÖ!oÞ)Âl×Aé ;p€€;q¦o…C/È'µ_Ô:[±”¢Ê³3ä[‘—²Ð|\~í‘ïj‡ÁÐèP=ªñì~¨ÀÊ„åö€SgÄlÔSãYØ£LƒõW.޳R•ª”h¢ïÅóPÀmåQ '<¦‚_€µ@V\üâ¼ock<kCŸc>y9ñHò!ÐÔê³÷¬^S5GEéb€¾%2UJÆ©âÒ~þ0O• ‚Hë¿Øš©oÑmE>Ž;|$·¨dðƒi^ˆ>Á¦¶.cX?­h÷cQ|5Ž©;~"˜7 ‚²MöVé=7lY>Ÿì>œ2HÈÙ‡gí ÒíbŒ~PÞ,…DUáìvâkÁø‚}îYGÛ(P].Þ$¿™JÏ‹¥×·¥PõbœüFÓ^Gó{x— ¯_Ê»4ÇDV7ÄÊg/NnQ&+†SV‡²Où cÜE9N…3wìjæáo$Ÿ@?JÕGRÓŠFeJÝÀ£§vR%úp±ˆNAÒªl|<^>vз8´…: ÃêZÒ3—×Ë9:–n8¯Ï©ô0ﹿŒ¨¨ä-ñìKr"UBJµK<í]F{#ûˆ‚6(Ô(xL()0¬‚e¶±æ<@'Ø3D0ùú%eæ]¹Ò ^'* ÔÇrÛ^Á,RUmÖŠAõ³¬ºr!v Š`ƒù¢ˆTѽÍp4àAàs[3b@¹‹×Ã4Ém‹ÝM´éUÇe®üLò1¯!Çc  –¬£½olý Ûî÷\R)_–æ°dE¥?x¯‡»œ-§ãx:äwN ‹Ðpï— LH W}áØ°Ê½Ö;¢5÷œ÷`(*ËqÆÄ@ÝÂd'ëõÖTm?½yA ÷&©\¹¨ÀCÝ/á¼Ñ¶M ¥U§w™µ‹3p,|e88Ë×7œô7îFg17S"¥Pà5Ô•¾½8 uÞY«-ãBñ(K£ªœ`†ÑæÙ²Ç#„Š;áɮҸ n¾ôÆ»z*`êXA á(¿ÀØ~úÅlÞxÔòi»·0,û Û8Á”fšÃ‚—ºÆ&Ók§=…œÂñµUt1%0é\jÃÇüvغw„zŽw ±k1cƒN¶‡û\º¬áAð(öÈè¾~*<ìZqB@âOžvÖÆUù;µvS&-'k¦%/\©C÷8€J{€`ï^5»“w>zmjËO}f°÷1,ef«l>Ü£Ü0¬d;~ $UÞcO³(àvÇz'“"ž6’Ëãí]¤Hv\±½½ôZÎ{wàê3*`Z‚7Ëz†N¬£D˜YK%µFûnÖksBîÕLå•§<ĈâjˆØ÷Æ1(ºŸ‚>›b<6*ˆÕFd,ÐGã6’o¤”ùñÛ’y« 3àJ /Ž‹ŠSÉðiˆ½MRÄív=C+®·V9 ±|N»FúÂA‚ë]øBWúéyÙ™ÝÎòU¯ÅR×nmÕÉaÃ9r©áè×åð‹`‘½‚×,fd"1Э3ÔG„÷VšE"¥6"\‡F×^ÝQ³¾™ÍÒ¬.1ŒãäÔWÔä D[ôìY[Ÿƒš€\§Œà¦5 ¤<~z¯ÊÙgܹ8‡×€Þ¾§ÕGFî(äÑïîB ¥!t*‚=u‰®•Lá4ð?vÑ8:áBT‘=‚߯ª¿ åy\Ñ 9µfð s”Çá(1âô½¥çÈX‘-‡òö_ÞõÁåÃ…š¨`/òëÊ ¤#‰«ÈÅ÷âüUaæC¼n}#uåIÌ¡nçx⮳fÁÓû|¢ÌCß¡y¬ 7Š1ˆö¤UâcPY”Ú˜0÷€9÷`:óí½¬_Û·³±¤9œ‚D¬ð­“eú²ž½ð¼^±› xdöÞRƒzœ’æa¥:GmÞÀYúñµfÐVŸ<,ãKZ³Ù¥ÛCÂ71$«DUJ7 Hò óUL5˜=o=мכ<þˆø‰ˆEPJÝ,¯¯;îå»Ð7…!&aM›¹áA±ÇsƼöÀ‰ó{€ñ*fðõëpöLàÖš’j•}ì1¢¼Ïâ™ú qÍ*5}í=º “Ñ¢øŽ1«’ýp^Âå£uB%ÎݪŜêª=›…ëSͧ—zo=â@4¥ g‚Ui²Õ®ÕZÂ=¥Áéʵž¤´§ÀëÅk)Zg&ÇN“¦#¾ñŒ‹°Vã<BÈÏð5¬X+š/”°¿'b Og‹ç™ÊÄ&·çòl«·>åc¹Ù1Д 6f;(VÝÐÙãÚ|ÉöÞaœ,¤Íï04¹Þ3lñäáÖÚG勵ë4w Ý»9„«…çÍG@ã "—\-س-™§QõÍ®±;¼¦]A}ùÂŒÎò$x,,áuSfN÷Þíãõ‰³ ‚X³‡:¶ñü¹·Ä^ø+|°}œé642˜`š {íArl:ö¬¸+–j;ÐoÂJxv½Ž ®S뤢ÕÈ©tµ0KG{×/Ÿ‡QŒ„ø ¾}ãdƒu¾ŽÄ¯²2ÒM¦Œ>‘ ÷)»9•¸éäà1Ž~ym£½*Åÿ…¤Hñü0ãÖ߯yA§ ª>é!Ô—s•¤š2S/p{¢äE=¯ÙWüÍŽ3 àd…¹ {‹#ÕžOoßêÛ·ežæ+·7¼Æàm¿‡@Ê>ª¬MÁÌ¡L¡ŒìÚ%Gœ÷ N׌öí´È‹Ð[­~hýªÅ©z_–ø0·×eÚ˲q*›òJ-¤S«u\,~Á#¯q`÷U‡r;Ò¢?eM0¢ÎµZyä"O¤-Ó¬b•ïYÅŒäžÏudx;] KCˆ­VøQsi#yï½·Wq&H[ˆÇ¶âryÂ)Ð'ÒÖ<äÏð¢ë¡Dó”Á@<‚g/W° âµ›>tmŒ”'+ÍóÀÒØV’ø™5Ýq¶l̼<£“·öðäñR‰¿4ͪë|Ò;`¼Ì÷4T7Bª9àUlÛI»Ìé[.Êu1øyvã½°IsXÙ›¦¡ª'DýJb%-»kXÉ^¥yÎEÝ¢=~27wKÃtHΛŽVÎMƒ0²L#õªyÜÅ¥²Ød Þ²Þ©Éå.tXà—f,‘¤’K™~ŽÝïJeŸM$à…qÈrˆG‹ÒöÁÍiyêKJ5€,Ƽ\Ô:L~³°m°÷”_¼3¯7qT 4Kâý0qÕÂÑÜgfîáÑa„0cW_UÜ »“0?–¦wqûè™ÕD¿+ ü„í ^êVgQ#šw÷-£'•»¶ZB¥Ñ”4%Ý í 3˜~ÚI‘0 éoJ¦vå¥à[ÅL1WdKeî›Ó¶}¸øîáËR[¤Î‘gµžC£ÀûF|h|V.Õ³¹oóvW¼!c·Ý%|y¯Oe`œ|fº+ l“¢O»´HÁµ¶<#¼¼Ümá¢^:l¼ Ì7€ôà"ßÃ÷½þÈ3´T'=¬XXGMá/‹At8n!žwˆ½‘0qëãNÄò†!jÃH_1¥ÜZ{·qó†•õsû"–›ÖH«êÃy&k´¥l`ôX‰2ÔwºˆQ×#±´E÷Š¢YÊÃ÷\6‚Wò¥E\¶±kèË ”ºvµõî6šá@ƒK:é')‹Ç‰u çó¸R“‘™„ã±å­?if·}4ûY¯‹S½ zÞiØ÷¤4wÈ!m_h€µ4Ÿ’¶v±ÓªæA¶vlÞ´d?9”>$ˆ[3ÁÁ‰‡ýŒÈ5JõX:/C§c½‰ 9Öiec1±$lòõÇ•÷èŠeYˆšr2’ž²äÓ²£Áˆñs¡©¹‹Û„€3{/øM«œ!ÃÎ{Íô3¡_ˆO< ˆ×·c¯j´{ç’EBdWøñ˜]Óq‘ÖóKÌØ¸Œ|(›$$€†í=îGrû¨›Ñ`ôÌØË+uØ=,( MÂw» #Ó-HCOAÄ£¸›`¹Ý¹aÜL³\àE”n)ß™Z§åbâÖêaEO-k ÔäÑ3èWu ¸]FL4ƒÏŸrqåIïAÞI¨6Ó1e“§H½Ãõ¾à[SyëÍ3¬¨±AÇm+}”O;^g7ÌcªpI¯—–åèáa·MSµiÐ\!r¨RÓ~M ôv€w·oì…Å'½$_ôZKAÂÃÐÇ«ÄÍpÃok™L^$v:ò°±+c.y‰qsrz66)KšÁÒ<\´áì–ºè%Ô¶C-l¸~ûÞðÐC}k6½ÛAêçGu±@%ÙÁ/xÆ–bÞβ…&ÌwMõÙÕ{àÈ[(ÑIhX»@-¯Ÿ­Å è-7Ho©½ T¾tŠ{ðè‘á½÷|Þ0™jXÇïß½·`—õ04X†‚ß(ñ°æ¡ò5 5Èꘋ³hØq {ªÄJ æB—ð•X3JcBB¡êSÈkF7¡[m-¹±•&̘Ö)ex%¸wƒ‚‚¢²«:9jöºŸh s§™RBОW³v€ç ¼Ü1Ëk{•ÛïzLÊÙÙ<ý¦oI Fìv¡\èbã4v}7©D÷D³{iúVJ±Ú³2˜Ý·7b$£ùÎÑÐc.ß‹ h=+¬¥'A9pX®»ðB”¢ž.B%€5–Ùñ™Q3Ìy!….Þ5N?07êL”y—Žï`7È·ÇãÆ÷ÙZïI¸%êÜõNG6Éê’?g³÷^„Ÿ'Û¤"Ui%ô*˜@b*“ß¿S”®äŽê=Úfe |¤DêÙRºö4{?´Ülö¸hb- [6Îð.„‰„¹Ý Ö,°×´[Ñé|;öNŸ™c"wD\¿Æ†›¥§2WùEYEÛrÑÉe§ž™<~^ >MokPÙä~izÇÀ¹ŽÞ­dò²Q—ò¢¶Mž%15æ:VJ±jÇT?&$%òT·…¼éð=µEJqÆû€O°”&…²cȵ=‘s‚Èa4C±wì¹( `'Ünµ—:Vµ­5õs÷8œšl<ŠãXÚ¥àzž£¤ùpõxö_¦/|ëMÕ륻-¡—Ý·Jè7 õ–ä©´¼UðúõM‚9ÀnâönF܈Q•…òøÊz”íQÖ»ÒâäêZyµxÃIô¼s=õưQ˜ï +ØÓB~bÓ©Oá HÚX º©ïɱ˜Å±lÄm…8ñ£À;©;LÜmA\—yïÑ+}båik/Ø´Ö žÆåüb,Ç=IIXl6F!N#lPXx‹¸§µèlõк`ÕÔ\šUwãhmMùKà8PßLyûõc3 Îj5 lõ³3 GaUèe„Gu1°è›X€žo'Òt§Ê‘¶‘³žè#ßádòMÔWÑRŒ¡ç]^9!ïj…Ü:(¿„j”Ußíg*ÅlËP™C¯E°Ï󂑉Xzåõò?¢8k 41/…DnC, OT¬ÈŽ—Ê1¸7tÑvN-}ˆRõñö›`J[Áâ£Æ÷:ãh»)qs g®A²ç`ÉZ €—µÐ½`¦Àíóh˜4gyŒ=K퓜;hŽ<”‚÷R²¨ƒï1¼ÛFå—•*æ¦ÉÈ0ìÛ-a«âé[C®¾ úu^c²²jyÅÛ˜íÕ4Îy]¯Ž:f-VâéTv3.È¡¦7Ðêï*Xîí¤HÌ´¦Â!C¼šÙ9êb¶É^©$!‚³¼ÞÀmO8Ub¼0%a^íeñ¨Gï¡õIn回$è¡ÈŒt $å ñ™ÍÊXv¥ƒ™|¹: ¢EΓ¶Ø•ãÜLAɨSªÊ ÚF>(¦ñþØóèÝbI®§ôè º¸"˜N‰lµ‘Ç®Kÿœëú²uÓ¢K·²9´`ïÈ\¡9$Ïñy©æ8¸¿È1µ¨h=–‹ä"sÂ3§Ö¡f¢cy—Ï2ݳ/cÇ9x‘ìÞÉ›+%nPƒIe}Á/Ÿˆ{)^ÚSç~ù‰¡õJ˜—´žÈÑ•9=/$¾÷\ZÎàAûè…‰[Ñè-ò«õч '¯ûM7âMıÎÉÄ¢\ð{F핳ñ™èŽ=u,ö¥bñˆ|óÈ2¶ûhÃw4ïT$31Á¢×“¡Ël±Â€†àžEÃ…tèE\  “=ÁÑ–1ÆŠ±UÃaÌ©Áà ªò8ñ¶j9÷2‹[©¡ êµdt1PPf¢PZDîðbvk)Sz ¬ÆÓsQMt:s\ á±íÕ[@ÑkO²“llú²€¦g Ck÷æ=<'/¾wêˆoKž¥ ñ™o7 ½‰ i Ú{-c¯˜øõ,ÃîÑ«xŸ«}Üùl8‘44Ÿ9>sq{ªò†×O¡‰.ò¬a_¯B‰ ÛíÑ—±þb_ÜÈ`š{?H–džíò*aÆ2•‚mó|Õk鴱ȠذYn±+×NÌFím¨E¶gnò˸zÈ‘˜˜o´Ÿ¸¦Ï^Q<·ØÚ™‡c¨©“Ä6ˆ‹˜U…dE`—ïÅÛ}³ˆ/Üi€¦÷ÞÓ¦[ÍI«Iì.&«3‘ÿæ(¤[£z:^û¢ßb{ñpã¢Ö;±».’~8nrkUÍFNÊbÉü¤ ˆAÏ ·æ½YDR~|J Êš+•€Ø†*gJh½êiêjýö Éß[‘RzÍÀÞI@¥"ºñê_• Æ#ÍZÁMTв™6 ‚ç°|·\d ÒËbZgšùJ­Ðß›˜I0ÐWñÄJ'¾€1Ë÷¸Žå°b™hÁ«~.| ô¼izÝ, Í‘x™@QM`fb,_kÁÜùM‰héX•¨ìœóX³¿îðeÇ6ÍaGlŸæ²j¾¡«“ç\ð¸1cø5Ź‚áF Ù †føoA“º†‘ëÛó>¯BŸ¢wÌQ‰Ï×E@ jo· Ü©y[BÁgËj»òŠÏ¼çN “¥ž`µ»ÀMk~çóÖO5·Ô»`LO÷É•.V.‘:£Œ–Órü~Ï)‹ej¶H}¡†‰Dẩ2å÷tpfŽo)cI’Ñ×R¦ ½,k0 Ð;Á·ª‰$7ò5v·Çó§qŠ4/ã­ (>.æ³uÜKÉï)ÝP„nsx >zº5„ê„)’C8ãÄ,X¨).TÅãu‹N·ïÉÐ^?²-~ÆÞU¥„w(‹0ûÝU׋-7y0‰Bl þ¶¹f˜mDö9ˆÊ$¦ï%IŒÉO„M¾¾gå:mOtL6Âç!Õ«¼w€퀆¹ šú„=äÔg…Mðç÷|χNLBdNð=éŠ}ójïuhÀzÙkF"vdoQgîðnIy˜ÏñžôIWîsHhRóÙQOê0;!é]e#_­¹WÆÅìŒËXþš¤P¬m@À@Õ^Á\,u‰ÅH?']É­"‰Ùzÿ1#ÂÇ™÷‚…ж c0å-´`hÇâ„ö]hWxf<8¹Š|Û1+›…FœaæZ³.ÃÏëFzî)-@Ý¡â¼N‘Ѫ}ÙèÛ¨UŠ@5 ¼0÷ƒñ yxÄéÔ´Øöq”^¸x«„ »£6÷ÑKK»ìŽ¥ÄåQ/¦¥0A]uU_œvÓWÀ$5¸Ùw>ålOê©9³øXÄó±x‰ƒÃkC1@Òô^°Œð´ÌóÍz Öâˆ~´`õXë›2™Á.¡#SÞ¢AÙfy,¿U® ÄD5ØH†M>8P¼#Hš…œU®®½V|&¯³Ü\ŠžÊÑêNÂVZDP YnSÔ [Ñ’Ê$¼ÅÖàs ÉbEˆðäjÄßcnC°ìzCïÍëúÖš²‡o|ÆÌë7Bí¤‹XU4®¬Îw1Êgìñ@üIñêÔÚ>™ÀC„>OÝì~©g&F…˜â D}¦#S²² ŠŠ<ÎfÑÏíæ\òEîMÎSAIëvÚtÙâÄÇëþ†ƒŒ±¬›rÈZµƒ½­Ðñô9Á­ûl†å&Á2CS4Dš(²È£ÂB.<±ILã†æ1Eí²b×*NnÝS’®t“^«§ð“{ä­ý=—੊¹y‚îNó¸½ lmßU×CI\N—¥ÛḦ„O†}1LZÞÑÀ´iÕó˜ïÚúUQ*pʦßÃÙD|†g! rpg¾n”ŽñÊ9BŸJì‘p*½¸&«‘ˆ²Á­#yì/«¤#è¬p:*=ðô¿ÈîÑ´B·À î7>ìZÆÑ8¹%ÞÒt¨Ý§£àçÌÜL³ÏŸc ºÂ‘a¹jKmu#i²C«Œ¶×À[+%B4p_åy¦Îh¸”êïùA eÖhâßÂ:,Ûš-‚::ëXäã?œPLÇÙàªÖCxl³çéþvog½Êà‰í¦TÁ!ãŠ5ß´——WpîIƒÕÅ#”“s4“wF;~LűïÂ\kù½ ¸y,òöå‹Û}5§O_³Û¬ °Þ8=Ö^ºõðC¯9€ã9­AƒyAÉjê²»AE/Ri‡1„¶àP|®jª ÃL6ûV¼_л9<5rŒ~4ºw¢ý9Ëuð 0ü|´ä=¡ Ù©a6aŽg†˜NÎôDö":‹‚¬}£àb¬£jwRJÖvxöqèí Ͻ¦Mraç ì+:lübnÐÉß;§7nàhò¦T‹ìò¬…œË®kužAÝó×KOàJ‹è–¢FÕ™ðžaèqAµàކšéÈ«@"~bªÒmYÏP=^õ¬žÆ»yi½7¤ÒåÚ¢'èžðÜ‚[- IàÁ{˜² lsØQ$Kèà)¼rç˜ÓoFõy¤MÅ•ZoÚ(j@aOFõ®[×8«¾Ì¼zç(èW1½3övm÷U?à Ø{.Ÿ;|BŒ}Ó”¯»Þ1cñÐîÝñ[ñœ¸Œ~îÍÇM øx"Âx±«3؈‹L68$W¼JšS«Âîªý`•a‰B-'«é™ž¾«g¸(o»ÎÕž2OÙ*´'ž‡0B†ìœƒÍx§%, 6\¾ŽËµ¶\ÓCïàt¥X[-U®S=ÒZZ‡ wªáw(zÛµÅ#ò’[V¬ •¤[µgŒN ³‚Ò+•Ç‹°–¨¢Ç^¯°cÿ£œ·vQ$(žÑ‚=>*ÁF|ÑnhþàR3-Z€ØÒúã˜(åÊskÆ4ZïJ3”×ôÚ½…iù]Ý¡ °cŽÃ½%}W´Þ±:™šœ°)x¹ûÌÅÄÒÉZð _zQŸ&½á·¾*s“léÖ«Ñž>Ç“¦“útT0ÈBئá¯XÀdÅ«eo·ƒ«ÒAK§ãÝË»Xðå‘zK™§þä‘êA¤”²©ÏË5œx{B††]Mà0ýªÕ‹çÞ;) Òž‹3ÁãºK>h@¡5ìZœ+@ÓùÄK­=F+ÝÅlêÅz`_¾z L)c&тϮ •ñŒîUžNìQ<#z;¶e(Ó"êÐN‚~çn‹ v^µ£æ—›¯—T‘ÅöúÜh3•%ƒ>ªzÔþÚ¨<‚vЧ ¤yÏ;ŬEL½ZP< j|b1K{9Ñõ‚CŒðõÆxÃŽ²7íÓÆWï6i#œ pö¶àî]9‘u޹ö<ó,ïYjíöj‘²Ç½Ú"g챪ï¸D;¶ƒÂ±oŠ—`ò3hNp=ÁßP³;˜ê¤SNYJ/y„Þ—–Ët„  ·)ôªIÃ5äåA˜ò[§WÜ/ªß.û‘ÇëÚÈÊöî‰GÛd4¬ÞÌKkGç(K^ò šv£4¤6ü4¤{¨Þ¨ð7ÅþE±¬(U !½éµ=9?Öó."½z\Zý·5=¼*)ÕxŸ\ÞqÙc”#Ám‰“|`¸\„œëd•҇r™å{3£7X%Á]9ÁA•GSµ»ª•gåE'Õ솘/茢êën‡† Àªn™÷¶ïÛ¬æÄM4Fè]¸ ¹s:¤V7SÈóªÈx‰d×z¡¢¸GA)† *íŠÙÝ÷Æyp'´«P pdâWKÓàB"B¡æ¬¢îù«0eLÑ~†+ÊlÁŽ]¯ •_Å6h&‘½Ø°~5¯SõÏôã²æËä„¡ž§†Ã„×Åï%VúkŸ¸làyõªÒÈÈüÍÃÂ2ð:·{i1µþ*ô` p¾´‚V˜bðY2ÁRlu¥ \#Dæ-5lSí&*ËMy°2ÄÊ bWîºoæœ96b<ŸB™à:nf‰%zçò^¦¿€Œ ¡Ý²Ø‚E©-»žÉL¨i{µë7sŒxè›Bô×£zך‚w³ †ó‘\ÚÍ$ç¶´À¢,Àñã>LŸ¥×ËáÖYm©Õc¯á–tªfKA9ñ{ÏQ·é½Ò”ƒ×áá$}P;0R¼½|eššûÈiíWÝ1Èkc² J¨ÁÊg Î0-#áx‡TÀ&ª"#Φ c÷¼zH,™¬ó©að%dÈÖ†§1õj¸/¢¦t0l¾BS<á#JeXrÂ#vp}hApYñ$·,næ5ç1r‰M ÊhIm* . n§¥1ט¼7û¼WƒŠÇ_>ðrÆäW²<†6°|í¿^5b=zKêGµ¦nÃÔ÷Žq òqti5pã”æå+l€à™h­K s†ͨ ÅTÜK}hî6š'y2“Bs—ìã°/Œ/]íáÜ›œ‹H»Û—œhOCAÂ$žøs{i-beþ.;Ž®Û—‹dã­‹Vpé½a tŠáóî‘*6A,×kbò-hÅ.FÅ{à9Lb½`ÄéÓ^Üêçp¾ìûp‹ åEjoBñyí¿ìüÞ’jÍLà ’h~Y¼ 1ÁúDÞF\´o\zs?]FÑb(Û/jJrïµ ì(•$wq ÆtÁŽlßäu4HìKßÉëÀäF§þZÝ,²ËxŠò:!×ñ9uª×&‘Ø«¸}}zZü¬rnb«¡&wªœir{Æ#‹†ÑÄ&„¬[lW9|FžnÈÍU†#E{ÄË’µ$Æ×yQhhp)l…µŽBAé§š|=d·p=›c fº²=DSOÙi<žÖК ,r5 ´­¤Fnˆ¤‘±DòÒ»h§“ÙÕÒà®ÚJHªKm¸­V °§EWƶëæy[Ëz¯üùeRÛ8?ëö}üœÞaüÊ.ÏÌàÇÝ ÅmbÁ8|ÛÚúNF9Ù—ÌP¨‰—áÈs!Ì¢%ï]vÜAÑ"˜³°±É¾ˆ6ž'ýêªõ^ßí‹&IõjêEÑ+@SF}!ZFVÜèCÚe!ð$×bøØk?«ƒéíZy«J¾°˧ŒWUnR iY=<žÎ7¥œ‡’Šm«ë ÒõØ4k„ÏðúïÕ÷N…²yA¬´érZi*‰Êfå‹EîãrŠÏIÀéÅÓ|ÆÕ¢ý „a=UcNÄ]Aà7׌C>êÜ[eËo<:$u³Ï€#™ÞYËTõKJ†7ñ,“cóLù‘ð5¡Ï¥eÉŒã+KŽ7§/Ã_ĉ›`—P—4EÝÌ‹§Ùa;×ô$[äI°¼„ç½Ò¤ëÿ‚ÜÔš„ªYr5œñjvhÓ$4mÁÌ'!&³%Ä¥Íמ½œçnÎòèÑÚxÇÛ=°œ¥qhÏgû±+’d6‹ãK›Ö„tŸòÅH¹~º~±ÅÂÏÖ»_(1>œ"šÂn‹á1x«WøV5 ò‰7 ¤ ‘ÇBá¶s¯Ó¼6S‰$Oc=´ëU U‹- –l…½qƒ¨ß<‡Á»¹èN +eƒlo:‚fP'C,_×ò ·!of¨¾u˜>DV‘“Üצºb¦2­¨HB}ùÊZ(ž¾ÂQzððv= oÖa ôV‰îHkÛÝ;Á“êÆ"ÔªµÔPª›œJV=#7´©øõ4z[Hêº<øBüMr_-Þ ANqÉöj4ÎèšýÅUQ_ȸ¡ƒÁy¬+¸½˜”.ã¹LÛ;¸×”œ*‡ÅW¦ƒiQr”KqœæÝÔÏa^@„7ÜÖej$¦ZïDÜS2—<›ëu¦¬Gµ~¼¯ß«À¾É’µju*ë‘÷®» U¢ýÁ­‘1WÀyÒCÓ™<#/8ôí Ò<¯Ç§>ÂàïDÍ™… I–‘F"Þ‹ž\c¦]w9}ï¹åk× ºmÃ2s– oÒ…t âs™Y7š@zA¼œ«I°è.çfê£|—ù 5«ª³;}á>AFúÜm´©¬ƒCåÚèP´tF¾á¤¢‡Š: VRƒƒÃÓL×ÞZ ÒÕ[é-R^çÁÞz$Ùð BVèhì)Äc]ló@úˆ(ï‰ròÎ4ú x¿—ÎôÔð]VË&'9sæckØ0£gðbØ×—]9òÁbH·*rfо¶v¾Á(ÜG5WÎ:xÄůÒA% ž§Ä&8*¹Ez§¾ÓRÙy¸rÃÙÚ`â?’‹»YZœ6hS“ ºót_5¢Ÿá*Õή±Ü¨õ3´µœÜ ƒGY²‹ãÕ]ìpÇðhzâ¡¡ÝXR ©£±Ÿ³®Š  ã Ý2ðØ*ómÖëëz@+5©íLU¥M²m”bÞé®Yoe¹B±•’¡Ë™|/g¶õ”o©gîÄÖx˜¡p”Ø9#ÚCUóÔÐ74²ÐÔÓN8nù0ÃÚˆ*µ® ðSsÛ‡?iåú4Ÿ¦Méù=Y›àRJJE„†z/q W#v «žgpªXӘώÛïîf5›ÄNÎUœq÷•øœ%Sooà ç êåë¨Ñ,"gŸmCÕv|CŽs èÔ÷üÁ’m¢ç *½`l&L›Ä:3x/uÏPÕ%IbûÞð#oؾ†¨ó᫊!ƒK¹C®™JsV {›uyÔÅÂzdû¶ÉôÞ¼'b‹êpƒOÞúÃy9¸Ô˜±`ÞÉçåô@¹qï-<íW"G}†3#¾¯¢æB7¹áÔ[2šê1`õË®·4ð µáø¹U€ßÖ€»ºdg\mʹ¶{ÛÃ!ÙèòK1lZa|o·`=“‚QOsµØ=ì'Ñä¸@eoü xiVB¨°¸ ’4t]´ST€\<Ÿ M¤µ<0!imHx\7à°zNÐÝ»Ýrà ªZäµŸÊø{ª ©Ñá6áËhç‡á„}¹ŒT!h)FôÜŠ!Êm0,¨=ߎÂ/)%§šêØJä18ÕT < ˜¶‘M¡ó|Õú¦-(*¶hØé›`‹ë9O¾,æ\zFB¦–<Õ5›$ âåˆVn×* %¥zH÷²¡LÙ˘U´LöBdèž.ªF¸N=Viû‘†>íò@ˆ¯“¡3NsK “=çÁÎ\,9x`°wñ|å‰ÕA¿eè1ݦ'Vn¼õ·& ¥…ÓAËRÚ …Ô$AõU?Z¨áâ‡AJ÷„uL†v)óZ]køRp1Ì[áFGÙ^ͽ]N¡>xkjwA³ Øú¼0<¼¡‹Eõ54RÓx¹l :扽꧃ÿ²¼ö6® ÔÜ ¶R|°à<5å‰7‘!û4«.ŸÍD½æž~o¶ýÕÞJfV¾6Ë>E î¢ç÷ÒSƱ¢÷…wÓU* ènÁ,¼8@c£›•@#è‚ä&ëÒÑ+ˆpØçüž´ßPÇxlÏãƒÊH_rzCòpŠâxlW'ÆFyÙ¡g<¦šÛ6èÜé/àÉ¿ª–Ñð;ªñ“70G+Èñ@¨„ÃGnE¢O•Ï ¬’´1 ]¹zUEo`öVÍk˵S ˆ˜[¸lÝXäéó-;x²K»WµÖJë… v 2Kgâ’MòœgÞ{O.o+û1®PLeLh­íD?¼kXÓÐN0î'¾}A`"x¾aÆ{†óKƈÊö,mT^=ö,z¥p9´­-/6,*Æž©4Ò81eyÆkç< (?ˆ¥ò3ª7™Ì2íG–¼i”!ÌWù éUô½ë2Lúd™í‹eˆÜÁ8ä°èÕ}[A眑û¬–±ŸŠ‹l¢õGm•0à«ê#SÕK3tES~ÐÅjR^Ø`uæ:òŽÉm' Ê™ÕO#†@¤ê@/Ëçù¹Ê-¤†¡31´îùªÙSØ<ê–¥®à·eܸ©&žGI“0„!û={ÔÄÄ({7צÈBoiòY •’x0×2Җάô=p+RÏÖ+§Qp|/ÛNžà»;ýæG ç¦tüIë,HEÊ+¡Ý5jsÍV $'Õ\ÛJšË“´(Ǫ‹NE¸¤ÉsN»_߉c§QKg?b••d¡zìÝ#‹!h„J²ŠîCÙ{m1ûTÇ“† gXÒ¹0ˆWü\“ÎÊí8VCŸ,N4Uàî1Ž æ^Nïòêe É£ŒI‡º6z¶‚3c3÷|8xw5#ÚŸ>‡‡cöÊÝ6«Öž¾TÊ ';Ó}Já¤Ägˆ.¥$¦ÅçT¹æ·tÛ¨ïm+C쬃 ñìŠíÕiï˘æÊ=‘nf•x ù;%›4§ó:¨¡]¦ÁS{4c—˘öÆM¬žÌxf -<¯|-£îñ\@A<¦Zö[ÞŽóë€—êæø Í"+/BÊ{X'Öæ§oÚµB¦¡ ø< ff{uàüÄWnrsð A'#EmÒ¡œNd/•§Â#N¨’±·'æõZê,s=˜1¡7œQŒíœ³‹»ðxÁ¶…ØoW6(üÙ­m§Î>[¦2U“½Îd²ëæˆÍ~,óø&ªüQ ù².%KÀ¼ºLŽU^}¹-­í' ·ÌÊ&¶2Oö0QÀ¶’À¨|Íf¡¯G"ÅdâNE ¤É:Sn] ÐÛ¢‘J›ç1©8Âó~HñbÚÝ…–\hã8€tÈoN4uÆÖoh~…½}AgdVn=ýªí§ôåéË$¥ÖªÐ$Ö'VÑnQùÎ;`!‡OgG B>x8Kh;XÈÏÅž’)w[_r+%SŽuBõR¤’mÁëŒC.¤”wÈ-ÍÊ€‡OÞ蓟-zÐM7/&õ¡Œf×ó|Çðœ _&-pʼn=6#XEJË”U]ªå—OXßjã¡Õä#±÷êZº³yyú$—pÞªêí­])$ц#Ç\?Žë§Q«/ŒÇ…Þ@é÷é ±¼´ gZ¼­}¬—è|(@ˆ„Ur~úl÷:²¸.r¨G¶À…§]Lx•ôÁX%ãùt“s‘ž“µäTž0nÑá,®\”4 rÇP;„ùÓ Ô{ȸgLFY5^'©ƒ1,¬ýgÅŸZûwÈ ޏÌLµ6«3º˜ßÞ8½ç}ïNiL©zμ XâL¬M`_ªÈlã->P»›Ø|#¨çr¦œ#÷äÉø3­Ë½«ÔÙˆQâTKëð¨DÌË…x'£—Æ’ V6Oü›gÿâye°Ñã%¤›õª‰±Ö"º°°:êw&0ó|ÞRvš-–a›PðæS¶ÌÕxޏQ'ùJ”w–ñâ•XêÁžbÂäâ@ŸC+TRŒ\~Ï.w²¤)ù½f Ú0gaCv‘Ñ-rÍaLF/¤”'å†tT¥peé Ä©2ofÉ[xlÜUÚ'Q5X#qêÚ߯<Ú€-wsì~JñPί<©cÜÕ^ÎU<Ù%ÐŒºW.þÿþ옉ˬ Üx Ƥðõ4Ä9Ó¤k1àc&ó|ôçIèöGÖ¹«¢˜å>ç®Ü- ,`ÚÊÄb)£âcúD³Lœû]Û$z7‘æÅB€,5h¨ÄyètáÒ`ÏŒ2Œ˜r©íÅõùpu?¸ äxåïXîœc¸a¶@yÄn@Â0/øm?=Ö´Å“L¿[HRÎ$ÄijmX(Ì~`«CÛkeÝ"/3Oyƒìj—ë:½VÝ·ß;Š!ÄZYôB=ûw‡&Msçµ@}Ù-óÖÜxHtG#ô…¾¥†íÉ×Ý07žé½Ðóº1ð嫊äê—¼µÕi µ(¾”‰ŠIàò•"â{}Àܘ^5@Å)úfY“ˆ’!aÝŽ÷¢ãHuD¢Wö4¯õ=Ô'çôpám†;Áƒïªîf`±‚:0dYÞ,«u;’ÕäÒªæÈÊ8 Ý É«~Ú,6Yoân0ãöža.àùìâˆ=ÅG¨lØ•²FVõìµRÒÓtâ……ð<Ì_pÆÐ4›Ò ²·èDêz]˜ñXFJO»à©ä›8y¬Ñ¸`b-IûT’B]ØxGÚÛÁ^¼#‚Yt”5S@øef_²Øp!Ùõ(žêª‘¦UgÖ“ƒµ¨Ä{š2Úb¤K§¹HÒÛ²iù€\=¹€»º ex\°ç¥¿j#º°ÌãÌ K£à0 ¤L¼÷iUv5 |•Y¦o×Û[P]4$eº(gžÒp~‹÷tœÊQ¢‚´¹Nq ½·Gçü½„‡6|n0ëá)þÚã¡Ä¾ö<)A!|åú¢å,üÆ’ËŠfìÝÙ²n¦ËµêŠ(¥J ÐX,ƒÔ;&CËœ P~ÁÁreÉgc<³€£š—nÇUc)L”W¦2„$ÊT Ž,í,3á^+yŽÇŠM;ÇfÌú¦sHZÝ1ø¾GV¹ÐÕ#µJ“FêK{²a™„$"'±§]â6³±²ëmèC ‘ê.ÊŸe0Bƒ[쥣lòXJ4×™..`t;Ä¥yÓe®xîž³æ $ñjÐZ'|ZÌÇ™Wòf(cyrúÝ; —µ2®B%ν½_?a¥|%€1´¯ç€ pÕ ŒusºõÝR¤æ„Ý›@¥vÕŽ¿'ï5Lã ‹Š¨5ìmz °“ãÆk ÷$ß΃H Á$Ç8æG‹^i[$=hiÄ]èh}„Cצ³ÙÇ {$¯SÑí…ŠJžx© yFÖ ì@û@äê‹zˆÆ•i»ìnHÇă‹FoÐ쬒´Dp:¼Ê„u ‰”†jß}€] š-,0Þ öÌå¹½‘›o5³G“Þb>KÜï. Dña&¾ŒÖ7š! ¨œîo“ÍHyrØ6¶«fí­ĉ¢M^ð3|U²Rî;j}Áz1°**Ch~«§½`NÎÎn9ª%m&JVâȾMjuÇ%oAú*bª×êA×"\¨H ˆÄƒáÌ+£R$>*áãrzÚCƒÀæn’!‰e¬LÇ8´¦ñ#ÎÍØ|ðMÇòJ¶-<ïYƒÄ½˜Š Yµ¦8vôÌÒÓÑn&9(\ª¸èÒˆ‡×ú’jÐÍ D$9Ÿ4XùÎÒÒJ,`oI‰¢­…²{.3ö6º}1-_Lkvª%p"?—šfò˜`“{±”®DÏJ¢‚¦ 'SŽÀFüùìy³","^LKcãyYváKäL¢gðZQÛ(³ã«Ô}FÝöÄ÷-Œù£—yÄU\ˆoËÃ] êÒ´g%t¤X‹¸º^wí€[S‰ö^3…Lm<°BÎ#:¬×Ò£ €}Û¤x•èûˆÚ[ Ñ,ÐKÎN<Ãˤ¸á]»¥ý ‡¬#k‚ZJpØâ2ö´ð?¨ãÖxl±†:ÊRøø•ìöq šÑˆé8 ®H«®0RÒ‰9dP¸ÈÃr×›ÇÜœ™ÆÝ ¶a.¬ Âòt¼oéÐáÅäeWd"›gÞië ì1¾:í$Dº×n#­¡ íkã{:JýÞÓèÀ\DÂÍêFõ#™Sô€ØŽ÷æéÐÒ¡Àí–É[È+agÍèÞ PNo9ÏÎÁÑ'åÙÀ3³\Á ÉzñVYD‰£7ÅõYKdÏÛ±7$“™ó^D fŽ»ó>`·0òóCE6Š;pwS{NM<Â#¬a”@TƒqóVò¼V %k ¦²-^0RÏà ÙZ0Ïê“@I#yÔZ*O 5ÉßFÚcŠ>yúÇ+O× –­ÊßÞ\wʆӉtŽr‘§óÜ’bözK‘6oPáÈÕŠRWíÒÙjÜsóógK§z^8]’£Ýåa6ŠH>àžãWdoM€8\OOW<‰ßI»ð[xr)}ÎÀ0©.¶& œÄ;´‹´+dbƒð´üË Ç&Ó«¦à]Zö£[·§ÀØØF”wsDïdºÊ„Pìü C¹:öiÎËëöW 9ì/ÛËóM>è5²®åE^DÕGÏaاWŽ3-CMÐ…¢â)äð•ÞC\”¨VPe(KAcâr.—ÚíØC8NõVŸ:=‡ªõNG&ô"M)´g‹Óåè½ؤÞÙÕ7ka38’È+‹}Rýº7—ú¥¨¼§F>7=­ÚVì§¢jfNÃ*–v–é¥oDvš­ ¥¢±‚ºIL˪n=ï`˜zó–ÑA³D$d‘€á%Í:£6÷:nÜñ9_]ÄÄ©Åðò1tÍ}weè<ô$0*FJº¶´€ÒÑÒ9³J‘ 'òò‡cÁ[1§Ëìg¯nÛ¸›§(UÜ vdtC@° Ÿ•ŒÂ{ Ö5«WÊ«Ïz-¯˜øÿ ¢KµGÀåû ¯)ÖüñYy- +ݪjÇA=¸+öÌ›ÉÅ¢Kæjš¬<©ãÊž{¦žF,b7æʦö.8ø4ˬÁ!͇X0%“¹lKßø´ufwVnjp<(™ÀärÃÜ…²U>&ãIó™{Ú³ÏVkBòJ²Ÿgíx<÷J;ŒxæÒw;ÅÏ0ŸÓò6&Þ!£âf°&¸e#¶ðÍcì=Fî÷ô9îé#Qð „x6ã±]·/ ß¡#`9•M÷fΘ¡ö•í&½íÇïbrl$êÑqž;3;bOº¼Õ·kJ/^]à{íá=ŠåÄåè^S´Ã$Á'Ò,wœüBsÈÁ68•³Ÿ¿ç/™iFúém7ÖËÆµI†µH±éöÇæM¨°[üð©Óèª+V©…v— ­Œ‹Ñˆ/ÌC,¡Ã²K˜Êذ¶²X{UðJ ¦£ü5ÐíõcS=OòÓMõEã=5*6uȬöë^Ãèq®–Ùv²ö{Só ÈÕ½:@ß{YVš:µŽf‹¸C¦r½9oÞ”µ³XdÑO§0Ö¨n;&çT¥'ŽTûÌ8íÄKžxmuÊôŠ îE=ª“EÂzO‡ ¶œfžôݹu“¯˜¤…†¶ÙT„6½¨S襬í éjWHfF]Ù>S¸kz8ù½W“|a}ØJÞ÷‡?yðFÆs´Âïõ{h1 ¥Ý爹hÚS‹q'uJ(p&Î|­rø•Ï;ëh‘âº'UÍó_ø"ûƒ(˜§ûZƒ‡»{‹ >)Y Ê'È^2ÑîË%xoýù cyh‰FÛÞìéÎ 5ÆUÊ,÷n$gFCcI•ùM&Xµ«_V×Þ\iµ{<çqáÏœ¶–³f;ÓCµuÅŽ„ |+ÉöJs‚Ç‘Hœµ|Ü£œ˜þãúÝPL<òƒÉQrëñÞwº/¸öüŒìž&b\qvqÌ#멵“@9O †aHÈÆe[rÍ èa¸5NzÈY0#óå3IŒ|P5‘£ÕEE 9Æér9b6ØqŠ<ÂlËcý.ØD›/²5UJŒ@™ˆL‡wj¥½ÕKÇs]mèÒ±éèmÎZ¨ ìð%·‹¤)nž¸$íSáa#£wÔՒ΂zɆVÑó6½É Yæ ö:>=Ðð[ÉÜÀäCk7ã;m“ÛQñ&0¦8h”Ü«œ2h‰e/ÙÇá­É'gL®”˜ôs1**˜\¶-1Ë~]“Är4kdƒòLÎN"=o Œ¨;¦2œÉœ™‰4ÍžÝÄ*Øöš!ëZÞ¾ŒiN4 ½‡"°²¾¸ÓȲq0Œçx† '®jÖÈœ4EèSëcrR´$$Fiï–3<Ÿk=[EÈI'Y÷Öœšp=r}£,OEV x¾í—oðux¾f²†”tÕ~»Œü¢H°é(k½ˆõ gLŒ?=J5–.y¤:t‡˜õ&[Æž.2²4ÉÝ+PoºˆW ] eÝ~,íŒ ÝT¶Œr 2îóÞ³EÜm¨ŸŸìÀõË«ÒcÏmmœ2̃Óü“k¦/®câ8ßö(–à™>ºw\˜«ç“û¦¸ä²<ôµ ް*ds™¯´ŸÕc…6a¯Ã¾­9‹ HÖƒéšC†‚¹~þô$ezÊWI3g^¯ )AŠS6úAˆÐ×*4—X«4‡'z@!éj€£ Þ$UaÔãeoÌ^.¢/­¢ZLÂÕw<Ù.ºky̨èúˆKŸ>~=W½3åxîãØ[([§PøØä1VƒÃ“$œ ?óˆ3rX‘h,ÕÞâQ¢v†—Y&õ²˜1ñQ*wïá“t:;!'Ä7XŒ¶sÐn›µD¾àÇa ûŽG±"Ü{è®ZÂ-na8™=1}!͘Ēßl"⬒†!J„!‘g=¸z§\.TÇOg콘²ÜÊ]•gFea´líÜÓ{6^mŒØÏ`ŸK÷ ’¾­E¹ UØvFûýtˆê!Þ‹{ÞÓ%®+-Àöpõömž,4‹ŒÊ¢¾x¥Ž™ -{!/»Ë„öy_}‚-ßF|áîÄ1®r8/ƒÞ°¾÷ÂÌ`-[iÂ7˜ GSÒ™˜Îî©Ë(d:ߍÙÜVfK(ÅØV·æ*ˆï¨È¶<Üy¸sblÌÎNrú,Š×Ü!¤Í©€Pqup¡„±ÝMóÎËÊŽN£Ë)&_l¼¶¡òKk›ä3`Œ¬ÎRy攎=Ögz¦ŠHÈ󼺉Kk`ƒhÛÆëâu(­Ë yîDV2îTùÕ5s½Üa„šˆÄþÙñ‚h—»ÅD>SÉeÚ$»ðP#E%@:”W‹ëèsdVbÑ^°B<e»Cí¬ Ø)Ínm I4îZŠxH/b³7Ãõ¥S2Áñ6vUYùÞÎòMDá¾` Î{ÙEoÞt¼>wqµv€¤÷ìTâBt —W,)*b:€rò„uÛäôêvŒ((¤R7=qY™^Oe¿^W5Ýò#nA•¼m˜]tßWÙQ«N|²(·×;ÀQ>“ÍÉ$Ô[&MœÎë)$’)(ÇÛ!Ãy=·îçK'+é`äc–Ïž-ùÈš7o¼”×ì"W`´zb&å©Î‰Î–“‘Û:ðk{qŽ™{pÖ“´Ãy¯ƒi¦1DJOF-` iE‡,À+!Zi¬“Âë%8€ÚA— â@`oÒ†¤ 0Ë<õNe},2¹ ãL¾ºË¨Œ4‚LEÛR®Ò„Õ4}H!µF´Lõ³½×èN#~æo6Ý ´›O—f¤ºñ­–uËQ›¼Ç;Ç z)ÞÊàÛǸ. ê6œWŒÀx÷4k¼'çõ®»åˇž¾Ü$ÑÞ¥xÕK¾ç9Ý„  ·EOP ËZ£_­ÞSˆU5l&%¾öÆF2ò]šH‹{Ã%‘¿Ò±ÄŸ©áM[À¹)†%ë!{•¯…>$‡Û“°o²ý“ìg{¬ÃP/Å#ÊF—5V´=rV¸V(èŠgõNÎo`_L˜qv磊Q§Â  T}­…ŒJñͯJeci{¢©ôz#|§M¨è¢DLí»z2òzÞ±:qRÖñi¾èL"¹{0Ìz]v:AÍ!v"Ãy]¹´‚Ùª2¾ö4Ž™êY­G“d"µŠÓà&ïzÌŽÛñrƒƒ°r\"¿}Ò6Ì5§) OZ^õ+‚‚xi6®ºtÿ¡M­Ô R½ÚëÃKÙÂ3çS%©k>ʶ "$=Ó¤x¯ÐñÔs$ÄÙ 9k_’éF™úÙ½‘z5Ac¾O&]N^‡E¿CêS|€øêíîx½·œ{`«”Sç»–8ËÛº¬r1ÍÏîØ¤2ñ©L³›„ÂÁ®,vCÚ–» ø«{•šúѼFÂŒ  <º‹ÒÓ·_h¼6ÅsÔµÊGSªZÑ Ü™-U>•£ÛÖºâcvÒZ4hˆºpPí€`{`#^I±ä {2Úz²]í§ÏÓIzÄ(Ð×=ÊÞ$cT«ãó ¦°•á“xï âVñøÇ‹Ž7ÙÔ>°p-šäF·”vô&Q^žêÞU¶8Jljˆ‘2˜x¼K\|ònMWZÀ’ýÅùÒÖjß,?Ó£yI`š¶0ìee©×¼Í]X¬ÃÌn›OwzIa4ð%¾´®T|æ"®çèa ðI•pskÛ>.{ƒièùt¯#—©JáÍ`u! â-Ce»Ì¶À€0I;«4·í¼˜GúÊ=ZMSð岺fÔvÜ£‹£Ô˜Üc`ƒ×Tfȵ­¹8ÓÛÌ/ð8<ý4Óê|O&@Ýø]&<„ƒ¦K8›^ß{º—c ø6éeÍ´;î ]ïId“¨8OzE)LN7#ô ¶á¾„ÜL»O´õûè8G¨t)'¬¯ý *ÅÌ{ûœƒtxžmhå%• %5óñà ¾A>y|NŒÀj·+± ºÎÄ5LÍ+!Øñ’D·¬yžñ1´GÅ£5+åѰ‰ÌMxçÅe¨-»2 §Bû&Ktìuw§u×ã&^>­„‡ÏÖ`²Þ› ^ö{ÍñR€+'QŇ@›…³!f;ݘ”7׳‰còÛô-&Eýmà• ¥•få|B¢O4s¡ a{ê5?#Zx‚˜Yª“¹¹Ï·ùYÁ‘ù­ù³¤(AãæÃÇt¥~µdüâÜ[Ø]‘;Öt®^J=›Jä(r{¼iaÛJ6 àrÕŠÆ/§]9-€L¶½mßÀ<, ¾ÌµGÜàõ:›ŒçÝ›V~VŠIýÚXã^g(äK„M-¨÷¢ÌÞvmœ:½È9»´ Ÿ½iH>^—Ñ\ò±g½xñÀ`¥r¥a‚ñ\òYÓ{oÐÁÜð €´m“ elm ‹^=Ï5@Ñe*Ë¡d£º3ˆ.Úëi³çXšKñì€$n2Þtƒ¥ßë­)¦$—(CÊ·ª=¨wŠé„CÌÅÍ:q#/«l¨TÑ"7 1íÉÓñá(sã=[ÉÉõP†‚t9ËŒyJ .¹´ÏŸ+y,p›Lí²RÅp b<†•!’[·°ò£w–A†ÍÐú^‰ `Ñì¨3Ô°7²  ÆEÙvØë½}†‡ÞpœñÞØ8íŽ^£³Ð‹Œ{ñ’9éŠä¥Qµ±ŠÄÊÝ …×*í{Èàb?Ù6ùb›•ÆßØVi{NÄ)jßâ ‡`î—~V^UiüÈ{/s”Œ¸¡FƒÑ9)ÅùŠ›dáI´¿,²ôQå¼L)²£Œ¨ÛQ~òÔN5Ñ6‚³#D1÷Šòâ†ilÞéU¿{©£¯!l«¹8¡ ÎÂãÄn {Wp…Lï ½S¢Cüe)‡Q"çªXÇËš=+5v˜ÉHéìe¦6E†{ó9ß=ÓžAÎÂÇ^!0hûÜÖÁo ´žQY¤¢Í,>R,»~†ø†ðñÂðºñ$Ô}G:à²Bê8¶yÌ»ýé£~×^ÜAР!YîÄü!ÓS^_sä‰ñ¬fÈæÔM>Sˆ$ZÀdޏ„%1e´Ú Xz« K{õÝÄ/ñdz…€Ä´¡ä±B,%œ U¢uåI!ûšá$M€¼óÕlÅ+¦‡ÁÉpÝ*‡κZ'ñªfÉbù+GâeóBi½•ÑÑdÑŠž&5snžÇ¨¬˜OIçæLŸìpb±G@C¢çf*aÛð¨g.ŽÇé[Z³ó|HT'-sìwQ(¯jdÀeƒÂ;Zò°Ú8 ³ jpJ×|3` F*î‘-1ùY’?Y;’b1È7Ê8Õ:R0FÍÚvj#ëáRµ`Iâ«ñTx)šQÆÞ"-ª3áZuHÈ¢t,ó]{žiÓ"UjÅÖ8Wúžõ3O­«88¤®oûE•R©¸OõabqÇ{ï•›÷áêEŠ .žòº aÈ àŽ©Rï¹§Cñžj=µÀ8Ò­V‚Þ³yx#˜9ô^fQU»UÄ+KÖ–ÆôòYë÷×½ÃÓ\0â‘¿Uî#Iº ŽÃÜ{‘0ýü=\()S¯“à³IÛÓ@¤½g7é }//]¿lQí–›ð`è×ÏðùàÎ`Ò²Ãýè îf+¨§¯K•jB`{ ö¸ 4^£(šÛa=  r€Q¯Þ—ÆÖøèíª¼,By/ÖïaÕà<÷aíÉ<ÝL « ¼±z¬ƒ•ucgÈ^cPE¸Cû‹x€BÇó¥ð[RGL]Ý{¸jÈ3CŽ¡­OÖ*ùV"úÑV“.=m¤rºdit`–ñ¦Å<°EŸcBf¿x¥6ÆxÚëE=kƒ8øÞÛ‰KVÁÙ2ÓúÔ¯G/çyÃtã³vË#ñÃÞ»>¨N@­`ºéìGÈ;bmžü^6# x.«4w ¥Xc˜ c PÉ£2Ö­y%žóÄÂnºš3“gH´àFÞ ìsØF8JÛí%©÷Ö:Ì®%›—±Œï"âÓVÞÓ|×ý$å Þ»‘Áóö|O wŸj`[_Ä.=•ÝÝ|ÓqÅNGzª <Ê;t11“Û%ˆØßÆc4Žâ·œdyêÌë îp×)[Ù¢÷FDÄnxëäLSlh¾Î˜äöƒêà§æ ,n[ô²NdP!Û¦¡8¤ » >[+ÇÈ÷NUò7H€^:嵐)-¯2ýF5 @JZ´o3ÄSÛ™÷æ=÷âžœyî’›=Ê¥ÀŒ¬Í#9yw×I›¹;ý·îÝbR59ô´¦'œË4£âÎ5q¶Ã;&*ê œf¼êñÖkQ7Ï=ײŽr®JJM'"ÀsuÛÖmzWäúR“b õˆ¦›ãÖðt±îl½$»¤mò‰×¾ãçxr÷.}9îÝ[—dnv3Ú€Õ…dÜ! à ¥°O4.«ŒÇÛªêñø²87D”j5ÃÝ™—åìÜÈ{c¬:NÕåÛ’TB=PÕ‡ ½­o+Š1ùùzÈ.Ùr‚üÇwzó uQCy`“*$6ƒ§Cæ9ˆSÒÁäaî­‰%L­ "C‹gé ïúñô¬Úî-”¾ì|ÞM/ í¢<ÜÕ³£_šÞ‘¬™½§ŒËqú¨VÇq‹ÉDIÐQé9¾ºŠÜmËCÊ#_õ×Ù`ž˜Ê¥‘c'M¢EËÛl§ÃoqxŠ}‘wŠ¢´áäìÎß9\{íK"½#ºªh/+œÇ ­Ï†¤úi•Ã0LŽ9˜ŠŒ"äYËs]'Îæ…òÿ³#gÄÛÂÃÝS³Ùm<÷õ‰˜Œ³\æU`«{-êS¸Ð®MæºÖêÌl§Fp"w¬–tøæ;”(†Ýµ£Ûõ{wXŠ£YÕ›¹÷ݯö¶œæÜšAêô è´ðÅË·Å*±û¤Î\ õÖP«ße©EÒúf+²]¼åàx o^#ޝ•q@6$&øP>€.{ÑþÀ_4IJ\Éî¡¿5 xfn,VïhÂ˵§wÛ…¦˜°ûÕsâñc¦;Íz-2qnT†ÃBœf»I%¯£ŸŸŒBÊ ¼¹÷2Н:=]i´k¡ æÞô>o~p½Ïò¶û†KŠÅú…1 Çø „`}—%9ËÏ™FhüºÏnÜ„¯MËB§žû)k=ƒ÷–Ï¢°¨ŠjȪé1BÜCŒHuPNϲaîȧåýF„8™a€[ë,©¨Wøè)[f«OÌëtŽ÷3Ì:l½hŒìµ{âOúñƒº¼Þx,´(úBçõ!ë½Ó%¿dE,ÞëLòœD*?¢¨Òu CMB¾I¬Ç6™PèûÞFN¸q5Øl§QUà™0°Òº¾L÷rr‚c#©eØ—5ô\×7Æ’»2Èr…””_΃shì[‰~ ‹EþöäÝš’jæ x›õ`™¸Ü6ÚÓÃ|’×Í{òÄJÄ|²Nßû\A¾·ô‡ bÇæû„ð°ºO&]ØÅª}Â;êÞÄØu‰×5×9Ûˆ´\ CÞÓ ¨Y¶|tnïÔÓ`ÎØe\Ç ™‰,›r+Õ(ß­åÕ˜nçk‘xo†§ŸœxپĺÑn™>’•QÚ U_ ò‚Íözòì–»×2eîDLÝŽÍŠ¯ )„‰¿ík¦¤GïŸqÑ#ÍY1,dU÷P•tgëèS®yöN¿QE—ÝÄ,>åxÖâúáÓ”¬Í&Ò²c$ÐEOë¡ñi»¹s\>¹NIP-2]_ŸE·mVˆ§ˆƒtHZ±“-fº·´‚³w7rÛiÊn©6³V˜ƒ÷à=ÚnØ"J1‚Üy‘#}§!Þ’mŒ\7ßsö¨Ócne}½8ˆƒ8K¯fàÙ#° ÇoÕý\[ù¥Ø‘=5xäâK6!£a„ä`ì‘Ñh„À/7&pÄ &ý¶&ŸÑkt<ߪ÷NxÖìbLöp^—™-òeïV¿,k臉— sd¹’} Œ_”ãÔùÙÛê¡ôylÏlèÚdS„R*a™qßð6d¡¡×dT¼”,Sµ-ˆInUÌæ£‡R+]’-*³5&Û‡Šègï‰I xú[÷P#‹)B4_Öm™;Dñ·Á%‘~¹ë»Ö|Ê!ƒÀ€Ä]W¡Ï:µ.&A˜±#OÔcèõšÉÐX·ïÚŽ©–¹’D½‚â‘ÆHÐm`ªä#N—‹„ÏŒžfÒc,¤×¢2øª†éÞ‹š!"ìâg’@<â‰GM-„¼¬‚˜oå€ýù곋<)— ç3ÙARÝ}‘baÏè†BÇ;~r/ûˆVÈÛš¶’ò½ÇyΜ‘¯°ƒ jûÝ<÷)ã<粈ÅÊ”tËg‡ê+sí[N¤³ú:^w˜óÔ–½zJi5º‡äÕ–ÃÂ’›ëýl^’,éÛöÄ S&Æ`¡ åé'â_ˆÃ °öGñÊíeè³ãîwNGT¨’×u\Á‡ê2i)ÐôŠi¡°Þ RËa9‰Ã>È ÖBÚ¦©ÉŒO“ªÈÇsZžöÞ2ßsàó^zað±ã­½ä’sɇ‡­D¾Ð”ùñÙÙ##¹ÞôÁŒsÅ—Ãp UC ¬Í%˜†OGìEx êÙ±›²Ë»è3ß㥫R©ŽYb rŠÖÝ4ßÁëÊ›7h¹rw^°ZM9*3wq“2ó^Y?• ÕÁ«Ìÿ/– óšA[ó~¸cA@ÉÞªrÎF—ìt8Û}ÊV0t—¯Ïioãм<}f*aeÂë¦fçý#§…¦LÅñ)0FÕñ›˜=ä…¢ÉV^4ÎfÓuÌ\àš({Ïmg¯©˜ãv>›è BËG¶†É+YZOÐ-RÖïHe˜µ@y7®K+‡! ±mg£R5¤ «úçKb,Aà7Í$Ì1Íš¬î@áUQƒ ×NJ€¯¶ 'w³hué:„Ghú½½®B¸¡a"fÒË|T륷§WÝíl8[†Å†W›<Ú‡|ò×säÔ^Õ™j¾ d FF @âÕËizNëDBà[áýØ.#t“ ó&A¶ü@EJ½(&u„=Ã¥GÞQ> $?ƒU;5–|ŒÌ šWïÎÎA+^I™¼˜®rH=̇¡² Q!²‚»³RÏóùs3ƒDEK®3y/æIˆ’¨ ÷8y ÅÀó ÁrµRr;I[ÒóB[É×¹1ƒ:äÙ2=žÑU~áâQ~·ÏdUn{AWjã=%µ£ç¿‰¨™=Ñk¹±ˆ)M–“É•+^b›²gO uó=+{$ÐAm¡Ûλñüz²^êk rÃC]]Ë…åijuñÑÙs7X½Î|QБ¢”#å”É`µ.ʶõz§kA}^¹¤åž“—'ÐòÈfÍ0ÖÍ8Ý„Ìp¼õœµZÅ+ˆÂ„:”÷öIಽ×Ô[ N´¡Öƒ&ÌÔæ-ILJÍ‹Š)h%aLúê9/°Ÿ•Œv"œ?4¥~iùªwººÛŽiUwcXå³~–‡P8ˆæ\™q×a‰¦Jhﱨ×ö£‚åè8j$äç·Y²Ïò?ÈiÄ;˜èqï>$LÖAá~HhÈaNù^ç{zà•ïÁ Ц»š=V}l<¡“Ü{Ãçú4 ¹qßQZK=Bš1|)8âö¤,1Ú¸1‹zßaÂ¥…tº& !¼w䨣c©B’ɘïÜŸó#Zó¬6—€wÆ» :ïxTô˜Ë¥`– YKj˜ËUÀe5_¡e£ лº¾Ã\ëp>8¹Þ7V&8Ds0ž`6Þ§¼”šhÓ ÞÉOŸp Zó‹›ÖÜáYb™%Μf®›0ˆ4)ï™;&žºïâM¸]9cû¸¾®Ç“ ‘],Ó/Žé²–ôöJej$P’d[µdd{/FêexzÍ‚-“¬ÕÔ¾Ú]KÑ•[ñaF5„€züzQ†:ºpÞ.ïóz=i7H}À~^AËz¯ÆÍ$õäžîªÅÙkÁf˜k°ó¶~¨Fà‰Xc¼ˆŽuud"NE'ìU½`½~Y´KØ<\˜<230–ë'œ¬çúB–k²Æid»ƒ¸ :pÓµ9I#N‚$t=sãÁ¢^™PY/‡¼ç;–j|ƒÐs,m8ÏK,·žJßm@î€9›¦Ô›èVWJ¹§z€¸}9 ;è˜ …·‰Ç)¨åD˜mŸ IÊšÂ<©–· ºécAj@`ÓÄíÁÎVçt‚³Ë>!gûÜÇ=4ò­Tæú“ wd6‡²ïÑL½fÔÏÃ_«¾¦´Ñ¬5%Ø=ž–@ Z\Âêq‡œ­3®B.w  ¤¶#Xj÷ü”\µ}ÍSÊÌ®—&©Dm^¾}/K®p7 ^¬…?¤ ã‡Î7ðL0WJ6¦ðec.â%ž÷ ÁëvÚ,’—3¥¶dì"oc b ¡ zÁÍÔ2·'¹=‰qÞ„,Ý@ÞŠÞ¡ä£Í->‘™su³ÙyŽ Åú¼:ÂÚ_<(dúr»§£¾ï ‘„[1¶,‡zåÒ[n¤¶ xN;5Ã,™°ÍXÙ o&/Õ±ížZ5ßWµp#ˆ×‹ˆº·ÇZ3Fl³OÇIBõ¶¦±e‘#òÊ R̺¢w¡¤^U>ÂJ1…¾KV3v_€¤ô†ò“&˜ª%h[)¥Ä×MsoÓèáeÞnnOƒÉQ ¦˜U#æ-ÂñÌsáš-7'æÈÐ{ k¨Ihí‘ûÖÓ܃Ì]ΩšRüu‘…¶©OÙƒmr[ã¼Ò"‘PxµÌàØpƒ’ê¹²R&´œQ·!Ž·;½ËRÖÈÇ€}yî„ rö¢tß 7Ç;£‚ ¨Yµ®Âaªà 9ƒ4é¬y”ÑàÊo‡e8‚¹äᄪQ%RG…§Að¾’W·²«Ñsq¦Ì“MYe&ü*`\´ÐZ}`¶µ—!Ó¸<ŸJgð$/rb¼d™ñ<1Η¹â£Øow§EKkäbµläõ‹ÀPÛWãä³K˜Ò’ÍÕµ(WÁÎTën ï]sF*Sï”F7pÂ^­Þ¹ òÁÀ::Ç|TŠiv ,NŒ‚^5o²P†ÍEAŸ†’8Hós”Êát‰y˜ÙûAÐ9EÞF6•~Œ]‘ÇÑÙž¾RæÎy¯åBAj`4ñÃÆ\yôHîÑÊ{*`ÏJ{î»_˜™tô3nQ†+£i¢ÜWÜV2¥Á!t†"“/2›{”/ ^KgÙ‹z,ØÎɳþŒœ[6e‹Ë=ÂÞZ<Àç½dÉG#<˜F+C6†ÆFú¦P4=v÷Ê›=3ÆâÀ*¢ä./84-w¢÷y¾óÞˆ(œÞÉÔ¶ äPÞ{ëÛ„¼ÄOUyˆPæs¥/Ì­6瀲pdÚν¼EUZqÝlÎÊ£Áö¹¥ž?}ëÁyŠí{ëCP¬Ìxªãp)4ž˜òÌAϬ<†+kš.*Ñ ¹šR{ ÉëVƒéùBóÈ®ŽâÚÚ4{¦ àîõC¶’y–ØuWÆÎ$• ìB³¹c6°-É¢b­ÇnYOäË×}G,óº+bëÔ{ Õãj²åâ`Éïéò‚¬ÏV¯ÁK {—¯$©–?¿QÕ·à”èÛ‰W“!#õç2°ªòèr'߯A椮³.k¥® ¢nŒ´á#Ý猭õŽ%¤ãn£N•Ô‰Zâ¹óÁ*†„ÇÔd;K×õÍ0RÈäêSÊ)µ&Q3?~Æ„1œQ« ãüIhê vѹ˜¿å]~•$öÀ$ù!ÝZéDTY»5—+¯8vF3¯cŒ•žp’@ÁC¼¹¾†Ì¶´ÕsÇ¢\Dâ{jnÆã‚:¥ÛÅYdNjî>#¯áª´C33D!ä‘È®tõeÍ3&xÑqX-Ç#œ‹ä×ø@ïIÚoî1œÂÊ1”.4GeAÂ=ü$°'K_ö[YV8oðǯ¬»<_‹Ï(°iº6¼TÒFÍ3Ýæ¢lìÇ™V,Ìâ<ºýÞŽ3Õãdh{´1uðžO5A¥&+òvp š¦Áš?|™Y; ‚»"jˆ[3íï&¹”D‰|^«½ZìաʧIjl¸N'|,@ Qa‰(ìQÞ‹!†iŠ”2óÎÍöñYa‹ÊÊà #î#”Þ—F-ÏfÈWPiw×ã ÛOBj×ë‘…„Õ¯¼Hvs~%`N³:pøò.£éuX©&h+Ûsè{ÎUÁíÇ „É0ŠÎ1-žé¢H8q̈A'ÎD@nõñuÆc@Ú0…€W×"bŽœ^®€êu'‰íð<沘)6³OÎ ¾8÷3=«ÖH× hK•ûnõ…Ã,#½Õ,zzúx˜åŸ0‚m³*šïÑŒ­E‘ÔB=D®³|•¶Ñ‹-~±èH}a‰#.1Oç´Ê•ýÝ<ßXTÞgç•oÛÚ]ÂNãJª¢„Ñ ¡øR„’¹Ù‰€Æ¾%Ú°®t‹@iÛì8öB w™ÚfŒ¨Íé ÕDe&ŒFD½X=B"/xx3úZH`‡_=^Aº…KyÀH0¯¡íÅ£b^-H"ýñÌÉ•nÿÞo3s¡!»€Hƒ ýˆÜwVÝ#k Â2œžÓzžtyC ²ËøB x(ìfè¬wÚ–¿Óu{WÜ:(ùÂ''ê½MO-…Å×{ü²[Ñ,Ÿ$¿‡D}}á¹ÆS#.4žµmu{8h44ÐIÂx¸ÈAµFlð-ÙhKøÍCÄ:zN÷Ô( r-Ñ"Ó´ ÆL€Ã6œ–Éšß™/Fçê]äò^ö  a°ñÛvš ¾00Òõ#i¶èmèòa—×ä ´[Ê­yàó`(^ÆXtª‡ôÌpÎ-^£Cl?km†ô8,)&!®jÜŽÂ}y$L—×+{÷¦íTS Á[5¢j4á0oÉÇo¾x—™:#ué”|ÑðØËCÎHv…À™ÎÛ53nS… —JÕäMÜé1fÒ¾fï3~”r*œ¤öÆ7_ò£7ٌ΢ ÍBVGvç5š„$ÅkÖIí¬νlÑa}¦ÌEý¨SÐZß=H^Ój¾‚—«èeúÐLn£i%–2G_N0»Eƒ$v–A_da£¬\q™û+ ΕtM|tkŽÜB@6«‹ÇUO•=¸x$_´K7¿uhÌš¾,õ0„¦ò …¤§gîJ`EÅž ¦™«•O*XÒê!ó ãBÄCéåÐ 8$ÛoÐýtñÀUZQtdBh¾1ÖâHà´zù_a¾¬¦sb-d™]Us¸¨.Ç KÞÂåm¢ Rñ+8*ö’­‹~­î`äˆÀÉ›U¹³ºq•c-½¨âõ±bÃó’K¿w¬}†µuî(u$ž€#¸n­uS ïñS~‘o çùÑ3¢+1Ïz.™Y)«,isƒsv‰ªˆ,¸t‡Öß…?~ÝõÊÒærMÞ“GbuèˆèoP±.ã^Q]dO'×*¼žCé›S|C]z+Yÿ“~ªêšC}&„oµ“˜1¶ eûI½ŠåÁy"ëe~雉V®Ì"Y »P¬eŽ7ž’Jbµk$-öPqSæµïQEh܈ >eÈ‘Ôg ý¬PÒ BÇWhïJæ*ï{;ІYO#²®U¬]cj䨓—=ŸOѶÇ>n Tê7XJŽ*ÉLŠaoORâT›?0w#j$S| 0@“–Ä![Ö·ýl62à‰¼ôiÁ½J{xØ$ºÇ\í½}ÜWoÓ‰Œ÷üôd©a€ypÎrX·s‹Vàˆvâ¤+®ðNóšw TâÐÙ–IsÌWD$3r³ ìå[Û¼\9|ì'%tŠ®yÌr»KÎ~¹i LÇ­ÍCäÆ ôœÕh‘ úñCxoxµ«Ö¹d41aŽ^Õ*&áR•Yµª’8Ñ O©† Œ2Õ#[Nah²‰Õê}ç܃½œšŒ3Ý„sãùl€Á®ßÛRÝ9ŒâÒyà¬í¦¡Ôb,OŸØ»,ª¤D¼ºwc0ÉR8%ñJ ÇÇ“!µe®¶f°¦#ˆàIvgÈ4É©¼ŒØwšÝÊUÎu!©D«¡Y*-ûvA)ëB¯õN)ìuÒU½ì{H%*ß Y¶4; ¼‚eA7Ë8}®4'½äMáq )p‡ÌÅÖû†$}ù½Lʺr*¨(¤¹(¡¦Œpʤ°xI;J´,â(«1Èt™Ê/•°Jê9vu颳ʭ%)-ƒ‚¿Ù§6‘Ö á+=yL“ho—/8Èh„¯£+ƒ¸^é†å&RΤ‰kÌI¹mìB©/®º—€g‡,RHz ’è.®ÁàÞ©?ã8~ʵí°U²7Kêø„ žñµ© Þ*› R«Ê¸=áãæ2}´À†iðÈQ+%8¯6ò&îåaîÃGìóëj˜¼>>ú–iÞÆ¦gÙ©çn*D÷ú¸UYŸŠÌªBÉyN•Ìý.RÞ ë¤ÊSÒês¨Þ9iˆ%Y”Ãg–/Êá]aΙ CÕéù˃|wdú¼ãe) xY¡>DF¼Ý0J¯hÌÊ3ÁÞB€9N_uŸ[>KV+_Fê|‚ÂÅsøŽTçr4 7¨Ñx¼ÛX©2ºÕ: ‚z‘Uy®ÖËž×O-ß;ªmNàhpq¨lÇ1Áó Õ"*³Õj0~3‰„Þ²Þù¸¦ÌË]bÅûi˃aC{ÙL×îHÞ² æ¤ŠÆ÷ÝÎeUà Ù«ãÔWÕ©¯ Gm™£ y.uÕŽ3à€§æñ T’SÖè#›då ½‡,ÆÛ êåv§ÑˆW]Œ3 FÂ^FJ/Oo:˜i#ŠÖxLëb:XkÃç¹VÔí¦€‚$O´¥à#àxaþòµ[ßj<~“XïüBpçDÎÙ^™nzUP)¹&ïøâ½-¸P¶FЕ³‰£°È {„uûÒRœ$ù¡ÆxÁµA›+úôª¬s æ¬uzÏ›Ü}fDõ Í«5GÎcóª%hYkZÄÖÍ„¹Ÿˆ)˜…¬:½$8^n'˜&Y¶âŠѨ›Î5BóFäÕÍ›D-‡äÆöúÇã’ïK*ò¾OÖƒ>YV[‘8©s¹÷ ådìuYM4žæ²>#-Gy«FeÚfêÚy´XâJ‘€É2D6¨ì¨ì0jËP¬¬¯'Û|ø¨`Ý— `ŒjâtóÄ}Î-El=C§q€pó–&‡ž7&©d~ù0àI€¿â´¬v~îtîôûÉ¢¬AÁ‰TÔÏÑßÒ&¼=/ß=zÓ®ÔœËz˜ µk‰-^ùŸ3š=(zá,2- wÒœ“c—‰ÁÁ6E2î‰ æjo0(ùE–D¿8úvfâ—;Cmv$ÎYÓf¯DA•žãa¿ RóW!Ö¬UO3‹qMŒáqbzïÀ¦s =¶\×ÁŠÚÌ+»Š“}YÙÅQg£á΃snM’ .d.ë)úø0¹·Ä¶Wcî=ÒH( -glê†É% Ul·©7 -,×Õ¬LîÀä@=:Ùi'9] Ûº`É—5G©]“”çØ5(ìN˜Œ!àco5BY¨.ªdÒµ¦O¸5is¢K.ÉTh³Adúë»Ã¾P +“ K±ãDöë"+%]Kˆ{¸ºúrN’/Ë{,ÐnçUJ³#!™ï«õ³çër_­õ ÿ|+ÏrÞÁ`n.’©žpŽu-´Ó*‡f] .xf [:8/‰u¶()rot¬¼Yû…(]&܆»quî,3¼xwÈö¹o²P[a "“x¡Ô‹´š‡»i u1žT!œKr.\Åb³³š‹—¸öÞøM<´>áMÜšªk —+,z#"y\4€é&HÉ)Ê®HÇ!üøÀòÞpƒ«Éåe—{?À°ÄÙ9’—¥¨«×íîqñd‘Ægôfæ|VUzò î¨ì²Göh"¦›]á܈"B¾z=eî &nú0!*2J‡&[!*Ñl õt|³Ù˜Iˆ¥MŸ=Oèy_°|J›_ø*V›‹Ó<æ7œUO§ãnÝà¡dä>] · ë¯2¶­S®%×4‰ £¥êei¯gA=\Xß™xE¶,NÚ)¤qF<9Tw~.·ÌW²&`¾è¡aÕÞšz†I9̶r†î“š¸rÔ¼Aã±H]²vs­M²ã> t…@g~¦›´ª„¹c]q§Ëúf+FFk^!OGÉqÖ6t?—6Õ†ï”=¶ Ô´®3ÑœƒO§õFˆL…NâÞÃÕ  Ö²fœ}EÝlz|/ÕLí‚v•¦mfQÄi©Û3vò!z,·¦0î-¤?ó”Qs]yTG´¬QžÖ.ãâŒR·'‘GÆÁ÷=]Á±b¿ÉpI(Z@¬‹S \íSÇß´ûí—ju¡åœCý)z4BË)èÓ—~ÛÍxñø-7)pøÚc\×yÉÎÁmoVÑÊ•Aœ¤®u™ëˆŠ“¸¹Î²‡êe¹bx9ú+ªQ]fôÎ.¦#ÃfÌ}g­²gù’R:Ž·Ë±—Uuä GÌf¤<8b€`Äk.RÍ0å㎴‡˜…8–1Dh"4I»Æ\wŸ ×Í{L/é^nt‘³$øC›+1ZmSaêŒQûy‹(Â=¸]~0‹/:ºÄ+åì¶Ù ÍŽ”ÎÖ~jYý‹û#fà×k.=[»Ë‡R0Qðtg][,¨×7ù¨Qâ‰(Òè%Á”÷cË×Aˆ7µ0D[›lÆŸ÷*M>ƒÌ€MUÀ½|bï•k>¶"7ðgE,$ƒÝòÌ60fvñì×…  ÄÑÆi‹zP¹é¥ÈDíX„0әܙÕý¬yaUj7ϳgï¡IºòÍ{P”;ã#T¸¯ÓºA"–ÈÄÓNîUÈ3ÐzÖœê£=ƒÂ±ƒU`½³ýbzŽ}ùñ¾žŠå`¦ dÓT•¼›%Ü@rgRü°á q/ -¥!OÜb°ßº9:¨ÅÖ†F¹ù[ˆsì(*Ÿ}öhðñùÖÀ ɆH2ŠÈ|‹RêÆŠ¨©Þ›£µàú´¦B1xωk|²"ÀeqŒ«ÚøíòË£·úu–µSéÊÞ3¨¡ÜA{e›¦ý¨¢”[=Ñ’èõÆ¡TjŽU¤¾§+ ó\$‡fEºbÜ U^'& ‘8'Šõ£È-×µ7oÛîtLêQÍ¥%vd{9æÃ›Ü½­}Y•ò*¨é5%ä…Õvì@†wWš›ä€×ƒ1ŒèD§4®º8÷˜ûÈ*{.¿GV\òž3îTå>(¥Ã#D{Fm®W®ÄOhRèužÃ”/KX„¨Â#x"5´r-0Ègkú `Ñi­h1Å›…3CSˆª)W—¤yëâá./dØ^Üù’Ü;žG ¾Í Û„Nœ¥)/7ò|ö¦–L(ãMΈ>1"·Rãná—O„QÖ); JèÌÎÅ€Ú¯âòñ††**^0ºàaÅìk¾Ð™çæÁ%:sf š¹¦Ì™©%¨·T­®[ÒˆÚö½»“|ñÞ!ØSÑäY/ðhµ}½JÉŒ,Óƒ@k›ó-‘91ò`xá%óõ£Pvdý£žkíÛvÙL¢m+*ƒvI§Ø‚f—¥8G\ýh ø=hðw&"4â/O¢G›#°×Õ7) &ËÒ4Y%Lƒ9g“èe 4¨×³ÓBG±„Ïõ¬‘ìB±÷ô¡b)¿7¡A<.=iàhYæñå, #Š›èÞ´*@¢–“º,£4U@µ¬ òÚŒSGð93œ¶ ÖJõ‹OLH±ÿ€7hs\¥ÇacÓ¸zóÐ…î\øc#̨£Š o…é‡!ü"çeÇK ä\tBÒO–Q^Uš:"årP†.õø.Ó"©÷¼;õÕÌ(=~úP9´œ¹»Õ–_Aš R˜Ì˾KN³‘f[b6>LˆÝß²‡|•½I±cœS!;TEÔ XÊÕî"µ^‡ "¤9ÄGlXð]€ØúJ^B#¦ƒ¾’º”ÎÛÖ ó¦óÃý¥Ò.Ù皇ožùÞc|ÄBûl ýÊk¨x{çOº˜žá<€v_zS;¥¯ëvÓÜÌ]^#ˆu¼¥FÚ†@]'ö@›t³YNzazÁÖ/ò1š˜–xRyºG ˆ:ܽéÀV˜õ-ƒ¼'û¤JÎÃî÷ð`«†xcLCV»à¼jf—\ƒW=’ŸÂ@—§+oÌf†”ù"߈ór˜nØëxÁNgÂ=©¬-¹œÛU“©ØóÒ£½hb«¡ÞE76n²êÅmw±h-G¾AxÜ•¯µÅŽÐxªq# öŒ` ”Ë]Ýöq¡¯£X>:Š·bíÅ@iË×AÉû22ý-Y£˜‘b/V TåðÛ"¿ˆ>z5Åëò¢£õ]–Àû•:òp”Í ÕÊ̕쭉…Æó¡%…»³”À{• QïeI\ÕÏ–FâuXÊ’MÅ<&ÈOà™¾€‰Ø»Ë–êM¥'oopåêñŠ?õÚ@m÷Ä»UŠ((u~)Vt]ܶ&Ë­&I¯á°-ÀÛ¶Ö-¦_[ kºîÀ!J+¬¯ôÛ +°6Çèãu“T#·{®Ë”"©–%s–Õúv´©Ðuf×Åcfw×,“¹im²ø7L2§2'q‹ðfBc4¡ðÅËÆÊª¾+ é@wo# x1濾}ÇC)Æ&ŒnT³–€#¦ö†…H\á [0ölŽ„mÙJ:°zv?7yÂÿ?¾§±â·ñ žIE†T·¾Íñ…=@¸1ÆF/éë†`F%PÉÅç‚ÖlÕü´ /|œ—.šçF¥Ü)÷á¼Ѐ|+å£$HÒ'ÕÛæh׻ձȬv9IŒÑ¼ݱ\¥ ;Ó÷†C+¡)5§·Ä½0I9ÚWŽòˆRü-oÚ²¼ž&u…d(™VÖæËð×Cx—ÂDThokŽªÆ4{-p¼‰ÇdVéÂ,œ“GäEo¶g¾òà…©¥¨Ô«¯}Fñ„Lúվ钛\}TcìƒD€!îëw2 UCE1 4Š>ZkëjuãÓÛ›E›qN§µÊ«o¤²ù¡°í{øÏ`¶–Š‚µuঙLDPmDN K¥ú›”=Ð* ŒÒ"à½ÐêŠf0P:øÄˆi1XÈå\ëe² Á¥m‰>¼ÌZ÷sí5Éw{.9‰•™R<ïEk’yòáyêë¡.Œž‘5ñ5"Uj<4Q=&cLžÀmº—î47°…ÜR®I¼$ï•ò­.>9P'ó³$©ä¾dÈ5pgŽÐçÆyq’D…) 8d³Awœ„¼EÐg6Ztõ%>Œ~C’Ïñ|ýõkfÄ—|§ò¸F Qž]É–Iî¬f,MÝ.€=Ü—Ñ}{ÏHÏÜë½®~ªZ¶Íã3P¦}'‹×D§f¥áuoÇö“x/âw»Êo.eÒÜ€=zgñÆñœÏï Wž#èp×S £ö¨ãõSÛ±pxÉîNùv¯Úõ:2BiãÒ¥’è“„¸XÁ¬¶…tüH˦Ð\Ž Ã+1V‡ÞÝÉ»2ôEzàûÞÚê± Gj "ã Ž1[Ó£ôk~àp ØY°v-Kº$ ÒfÊÒ(â¨PªC«”6¶ø+ ©é¾áTVÖ,:bÔ€:j£ÊQ¿K˜ÿ}ŽØe¥LÈäpÞ`mq‡ƒoŸ½Bãó¼yfO²=±ó&eBÊ¢úÔs=• áų¬MkC×Ü ¯F8 |/Yê6„OyH‘˜xu_ŒÉÅ!cŒ¼±J—~›ü8¨•H&¤ m"÷ÑUóμvôq´õ§Wó„…$Æ# €ªÞ{ËöîaT¿ËNàÅ qgx³~ BêWÝÊ­žâœvÝÏ'&Š|"¦øA,Sãnà-ƒÞ£Á`nï\;ó6¢0õÑÀÞ(D€±xòÀª S”HÞóAš«4îÚHL¾ sH–÷p¢r9J¦£1°!e!è|7(¨CI¨«HÔaAÞ“,Á‚w]v†ÛmÙE+žï­ŠäÄ‘nÃÎ;h²òŽ!í×'’ÔRâ4é@Š÷õÑä2¿GZ‘ñìT=(~ÇÌ£\ÍMJ9‘‰¼™¯cs¥HÎ:pð¥xdÇp°—ÃÞ³û´Ó"Ä •Ûh¬çí©=cÛ¹Ð=;P%Ò–ªJbsM7:ÉbÊÅq!tI==ÄàE∀fFqoL¯ðï٣Aó20Nßf£:˜°BÎU(Ód".©‘b!8M‘Xe+ʃ7¡–¬K&¡;+ޤυ^‰WGTäEÁu­HÂê//ÅÏMf§ªJï"AUˆÇ«F”Ó4KeM{î=î´P¾yö0xLìÝö±îèoäýy“ã•ìÕvAÓÛ¦jJžu`ylËsÂk_ØlžÒX¥£u3ì¹?E÷ž¥âèÉ }žo)}ù4cÌ×ÑÊÍ=®¶‚c@Θs#—j²—{“ÕîŠÁ.î©_A^u+Çy?ˆ·/-·*JÝßÎq<ò֪ъ)&D~˜Ã·H8²Q'B'‹Û§ [)£½õÈŸg5li)g›ÝÓt¼lg‘‡ ­¡Ê‡àòô–Fx-A5—wÅ®ì Ñ9Jš·ÔòzÇÌSÓZÞÝ4¨ܓ¼ÌQåî„™ä\MÝY®-C\iÁYŲ·™Ä`YUˆ*únõzÃàmõò[¹È¤ÃÎY9 ÄA¿×é {1µãàíPÐh»•LÅ[¬—•ú–Ž¦Â»K@0Ñv <{ YÚÆ°‡[¨JÇ'k^i†è­"­Is¡ã›¨V[´{«KÙlêZç/gš,Êan‰hk‘»›R+]ÙÜ_"&äcÞrœàG1âOMõ”±N2×H]!Þ6„â½keíW \XØÝlIuñ4Ìõ±1$¾êJÍzª-ë"¸ó\ùN¬3Å!à‘çËæ°fªÌˆé€‰½•oæÕ¾˜ê¢yÌÀ|±ÊHÎÎÝrÐOÖß¶¹ŒÒ†_Z¸d«Oä@°Ï¬f<ðqô–0x³D.û ý°³¥¹¬¹®óâ´b®ikØêÓ.fgG j*Ów,вcsÝdWO½ôfÎØõYšÔ°<1Š;dF¤n%²7Þñ•} ¨“ÕÖ lÏ¥IÇÅÌ3R[÷¢ÙU¼ëâÍŽaÃENœÍª š´U{:íñ¬G„lç^¾|ñfǃm!yᬶL¨­“¿–$„ªaë…e«w”Œ!zVÙØ™Å-6ÒN¢Ë«S35É1>·ÌÏ™X¬1#à°Ù¹ïa?U?“D” QA0­)Ç,Ç ß‘—8 𣋿¨±m…“ÂÑÖ]Ö2ú’rŠ9aùƳëNûiÔ]RÛº m%–Ÿ(¹îñIØYˆíâ̾ð>?­z«ñ\5Nvlëêi/Œ>.ô|ZË.(pÙâ-[>Óç/ážÑ?[ð‡=ñlö­PKÎãK‰á‹&};ØmÍVEÍTxï‰Ìt*W**ñ;T÷ÓËׯÆeå>yùðé$&ß`qBÐÄzŠ˜ÅÃò·Z èá9>\ï¸u…ì7@/l¬…‹Ž©,:56:'`—qÍÅ( <=àC9¤;Ï™l$÷Ôxð.»–ØQü1‰uÄÔ †ˆµé© iè¼4>¡7ù‚þ(ÂCÕg¥ç´—!#´ê-,¿Ô ¡Û|˜’Mg6äórø½“Ué:i%³Õãc'ä=]QøÔ‡‹ÃŒI莻lg-ÙÒtŠ«Æ ‹]Êf[½ ÂRˆnThŸ.Ö¢>¼RÊ5;·¤3'IïËìÊ–|”¼[¨¢’çÇHÅE©ï=…å½~°žÞÙ¨Nꯒ+¥æÙ>ôÉ>æaN!çÝAIJ/é!–’-{ì¬@Y¢gž©¯Óösc¼!.iÞ¢×|¹íæúõÁq’RºüÊžŠÂs*XW•KrÂmí…w#§ÉÕìhI zÄÊwy¨î¼Ï y6ÁdÕ¹ïtÇ9ã¥Ñ\ >Étõ}&!WâsI8óàøqf l ξÅÌǧx.sl54½Vüæ%"R[[ìÕcé^ÊBR|—Ë~p¬A)LŠ]r‚yoàpí„©+νœ®O_¥ÞÀFjq“«PÖdF›â&h²+(šS1±“‘<ÍÝRörz²Ç¯ˆøÌ’©axNôø0PP®aÝŸ/º+•ôÔ8Ù[>@è”ha}n=káÁÎòM9–¹ËÞ]r¡Íã¡âXå&MÃã‚¢y±Â ‰¯å=OÞpwŠ­{í 1©¹A«Ù~ãF ï ¯,·j%&^O¾Q>m¢d=w¾Øç–ÇNÏŠó9Õnµ úˆ[3%ïK1X’P¬«}ª¶láè %Pίå²yƒßvºH0FßbÃ6F)ÐúGpøñy?1À3̨d Ø|2E²z5lc—ÏÁu@×1†EâÐÞoÔ+<½: 8ú¢>©ô}‚}/Þ’GÔ£dµJÕ:™ãìNë)Á-y¯%ã"»š’BæQ]¼9NC¨…;ÔŠ¶Ñ)A©ð'l€×&§” |@níiöì¥Ë¾ ËÂ>…Ul8{»ñ¡ž;áì‘ îÍ{×®\Ž®¢ª9äòÂVûÙÚ퓎lR™b™~î G·¥ÎÖ-ÅYYY.©ÏyñFÄ1‘ЖÆCÏËÉj´y45ñŒäuxxœû lP>BªEÛ¦Ž™3ç±=ÌœïUËb¸§SÖ½~ÇøöÜÏ›k$$X ˆ1¦Û«*3S¶"R£C"Ñ\¾#_;P'“b§ª1¼H´‘™„â|t.vñöõ*Ÿ¤¾F¦ ‚ÛÇ~޾áB)hÂç{´H÷¤NhÉñ|šv^õnѥݸZ½ÌPeujD,ê«2]²z¢Á±8#Ï1L·5GjòfqS GAö 6ŽeQ•¬Ð)s“ÃEç<¬þa¤yÑ<5ÒöÂk8ØH_ëp›ÙUsîÒ³\³È£EÈ¥1p’w<½þ,}“k×v°yô\ÞuPRFÜÌæˆ6^ ñ#ÐÌó| ¨1õÞIŠÌVEBØ‹÷ s‰ºÏÁXDûEÀÜiÒBX@ÉÔºW„ ‰”Kö4P?›ÊÆÌ—p[ Ø­“ÉÒÓŽ^”Ö)ãàˆ,àjšEÕËjšk ^Ç­ !Ì›ç ­°†ÍñHÏüÀBè½zõv˜¯NèeG¾¸ z+÷,ë ’˜3Öi•µ™æ vc#Ïñ\ì~›½w0ž<®‹Ö ðÔŒÞYb=c Q$ðFÞE6a_ÀÔಽ! ²g$êÃkïOì¾°£FÏÙ(vèç²øàêodè™00ØÛÂêÍà9l©û… ê9†žƒÏ‘\?[²®WË8Ízà"=;¨öª’ÂÕû®ã]Q3àXò£F7V<R ^–„0쬩Øáw$X—UÜÃô„O€¬4Rº›]“ðœ  Ž0»ü`qŽN%ø=ÕˆTšb½%–‚¾zeã¹5j܉—¦ÜÚ@87vk‡^—7µ]YäÈÌ; *ÑØ~ÞÆóŒ¬Å™hãŽÞ=¢¨ÙÀ}|þ÷˜ÓÙ¯–r³5H˜ëufÝàsE(4õ° |‰K¬ù3¬©]+quˆX#SØãtK×iƒ@hxàÂÏ`ïR-ÐOP2ÚŽÃ÷ 4Ɖä` ®Ç’²iï x@øRMCS’s}ÒÜäâ¤)Þ\]Pâ#¸K.¥\éÍöÐú-2>2|á(ø^½˜ ªè‡{ÍMÇ]çLQqƒEßÁ³öêCËë*“÷ªW½Oµd`Ëã¦1p¾Ð&@kõ®ïHÓdóà´9®” …2âaMmÊ{FUW€T‡ÀÃÒÔYÊ£¼F•æ õ^”ÛãJr(¸zÑÍþ–TAg*É]n%¸\wáàÉ6@îÈÞG®²Q;žB×áÓ‡¹z.ZöÞI9Ðæ^(ÅÝ•e_%ÈŠ‘YFÇËÐH®'¹¥Á²|¤ÞÝ®P—;bý±MéjM>ÎF£ FH¼@SÔ¾V2¿Ñê‰\»5%U¿'3®FÌY±·§½»O’ÅãÄÜ^AÕá%Y­uϪÖ%‘ðn—g4§Ä­Ô切ä\¤ù=Nlà^Ö"5Ô—–´fhjqõ·›Wú÷"ª`Óp%÷¶ºMEa"BA…^÷ë z¾ô²Ô[/i´ …) uaO¶t1Jè4ÃÔB—…Èá"à š$žT‚•S³åës7¹áúæÞ¿¸ÏEãKfà\«îõ®šyC¾ºc¨,ÚÒqÂ-@UŒÇÅ€]7’½Ò$=ÚáÝFÛ°”/ð®²áU¢¼K!{–8f®8Œý•VF¬¯Yæ–'¶¦<•w†ü/m6§K•‡˜›DŽúñT)ƽŽKM£½Ñ3Rjx‡s{9Þq?€7wlåâ‘ZV¯Uß¾˜‘Sh0E<8µö°bíÀWÆ•¬mwA•÷M}ß»OKáÝ’<æö÷.è=©õhD”el@\åd™&ñ¤ƒµÿÀ·',l"…á“Øâ\ˆ8:Q5²LxÅÏw§ø±=”Ç$‘O– ÛØ¼Ì°$/(\‹÷]è»è`퇪Œ8­¼‘“MN©ßÜk÷ˆ—|÷Ðßd¦dsc2 V³u=¡s(r Ø±¹.Á .;|˜`RpÈEç\ø˜aöˆ’ýµRï½C\GâN Æz&!óÀ»-$É—‹eë##M¦ÚS‡–0;7vd1‡®°–sÔl{Ž`W$¼Ã©1ìŠu<]¯RŒûaºù=xmm§<î‹îA»Ö·z¯‚Ôbµ‘ˆn×ß füô‰F³C«žˆƒ“9¼€¨Ò®–Óö…j³¨µ~ T]Tª4’'D Cü.[k[mA¥³å¸i8ÏÑ‘&ž7ŸÎŸ¿­gòhjkŠàæ<¤í‘¿=LcUhI ‰w‹'áJAøV”)E´gGžùëËD™ 'ƒÙ`ÂD»uY§¡Â‚¦]ã(ÊJñq]°d‹ž‰NHÛ:çíÑÒçÏjtyŸ³#ø—[™ªŸW‰Êá>»¬E?.³NñÆš,¬qÝÑé£ô0” h£°F]Ï0ØÆgìy€Àó §–à¡<°Q¥˜Ç¹z°èDðp._ä+£ÕFòloÉqÖ³‰ 5i¶WMOH&—ã-k%ZzT¢öÕ›Ø]*§OðþÀçò×z×4–—oö]ïuÀq!uìËT&\Š] šË~1=Süz5ñyk³îR¹áCá–(F6ÓȚ î̓øÝA%ìÖ²‚ZšïY pÆ›×1y®%–ã²h$ÖöÆœíé«Yfk \kd·,¦/ϪHq£hüö©´¡ørß•ó^UuÕƒëÆUE™žôúé*¢m¥Ø,µóóˆ§ éÄk®)Úz¹J׌²þlòå»"ëá– W÷wh¤È5“ÍÄëúø‡Ê´ú m¸U¡ l5 ;NQ †cÏöÊh,ÁR†fMäI¶¡,¨z¡x nÓ„ôîsKðzB¯_=0Ú{;"{€jŽM—ЈZöL)Îæ7\‹ UξžD<Èk}ãKms°Z¥"ÐT¼C¯é…wNÛñä±£1yÁVNÁV)…‘h§æá(Ù2KÐýz@“Ei‚ÜŠE_ֻ¥ZU>x…}±Ã›„!ìNfñXÏbHÎßq±ô¼‚6V6GËlÍyÚ'Vmb¢/ê´jöìÁn°žN[}qtçKÆ¢îÝCæ…ÃOWç´®½^zÜ<ê«‹:€½=et+‰7!Æ»Ócù„ì¹û¹ƒ·Â¹½!j„K™7;%§¬r‹[(.g¢Oœý°ŸÃ3l]\‘Ð(í'K>¯ºù,{WV98µ—dãõÔbåºr«=0ÏÞî)F}É{¦ï‹üòI¾°l3ÂåMÝnÌՄ¬Ã½Ê˜NŒ=xzo ð)RžÙXJõ½A«ÇHô 4~tQ¬Õý:Uw1Ö…¼šhÅÕvô2øIsCÔ,ZP7aØ‹3MT³ëÇh'Ý\ƘèW"—–—hÉST-„´wÊÑöúÐÅœLYÕ£"ÎãºëÆ’ }ÆôB 2“}‹¦Q’æ_„$ÞšÚÌ ¨b¯ìk#,ÊTI,òçéñ’<Á!´™t’lè óiݘ4)0D•jŠqU6Œ*Zb›¿áÜ£«ºèVyÿ¢ß@ò ;H˜u\¸ ¥á0-# sʚ܂ˆã7$k#÷CÅe½‹bSNp›dŽMØÏ’¼„¼ý†ÒަSnöµ÷i´“­Í‘XϾ7êÄ3¸Ðð4òœÕÖcG˜ž%¿­ÊÇÓ¶/PK_eÎ"çKz–™"jK¼"*#B›3O|dߢë+šhÌ3D§®‘ÝÂÜ/’ÎÆÂýá²Ëä ÚíÊö"Ší¨,v’oæÑ„0;D]‘ˆ/ †êâóy)î)HžÃ´Õ£·ù^ ƒ^±ßLaï½3²”ȶeiNÛ1† F8à ’Գݮp÷zã`ñ K  ;¹‰!º¸ccà!Œá*™æÃ}9­ž<òRíÆÅ"ßôô°ÏÒ$£â­ã/rz½HZ`â¡öð ùÙËÓä!àÐZI²Oô‘¾ÐýByÛ‡Ào°ã™ãˆŸÄ ‹Ú¬<-x°'.¯™¹žèÓÂkJt qM.7–ÛLÖÐÌĤ Í7V†Êj<»ŒUÙ"ܞ̻c£jiÎfMJ¯Ta7Ha®,p³ktÔrQ*˜y->i9ºMá\¥CF!ãhw¹1J6ç†ætp$YÈèÕEo O¿Ë2ê÷6Ù«-9Á{“eÒÈ·µ•ê´êei>?e±î~‚]vꕇÑy™×eÍê{©$ì·(¥ÞzðÈÅ _ëhoI¾šU÷}GØÿ²Ï§;çÚµ¡ÑsµYµ”a‰Ž„,Û1Ü]Æ€cäzö ôU=ÊçTϸãåBÓCî4}BâŠÓÜ âžh¡ì S¼­¾öZv=kŠ€­_°ã>;í8ëÃs†…Éyoh+à`¯R¨ µ¼½×•©µÌ\Lr$Ü’÷éÊuµFÖ¹[º Q“¨ßÞ`@€'Äõ¼C+[­î·¡ø^Èíˆk;õî½[¸3]"ËÅóaY½÷êò¼¤Ý±.îY?OböðA‚p¬ ;{ƒ¬Xàí’0y¿#u¸r€.Åå]Ÿٓ멬z SÐS±ŒWû,†\Ðæ“)›ìnÀDm@Š|÷F’™ï³¥%°elSK¾•Ì£¹˜ÄÛИŠì+;À|z¡=ñÌOÀ3 ŸÁN΃ ¶Ýf‘ Ku«¡©ˆ='_õ!G$¿‚ÍFt­} Ý1hË»\l˜ïÙ¬8029ÑEÜ[yï™txèE…,Ï'ŽCfÚ›/Cât¢‹;ù•î ½z)©—pĆ‚¦é+³¸†‘#«šMO³èk„jãèbŒ¡³]w;™"!Ñß[¿¢4Ág‚˜ïºiÆx¬C”žCÕÊfxÁå+Ò#<|µØ÷Z5A®³Ì_½‘J:Ó·£{ïØ–gÅžûv wíƒJši欓fÖ˜QöÀ+›^‚àÈþdŸà“ý´”“›ÖH"fÇ\Í“ðyR”¶OcÙc%¡ßæ®‘í« ·wøNºgÍ D@ŒzvnXi•×RÚç%8Ò=ÀîǯŸ7©ÚÁCDØ2zSMù‚æRýXƒ•".9Y16 Íæ.Qï’u]ß»×nm%v‹<åK=ÓWéZ3Ó½/}Qõï!oÜš*Q;b Ç9ƒ0òŒ†`iPð $óRçÔ„G5 £¶ØMÙsZÜŽ Ê)pêØWÛ$‰RhË=mÀ€(ý 9ŸtB¶æþÏvo[@+s/-9zè[ô3mд§ÒçÆï¦ô“âM“‹ü2½¯mŸÉÂ# G°‰7BþÀßôéyö!ÈËW¢èkΫÙ6‡{Xù¶_ ú!-»ÍÕKIÝ™ððÎUÍb §6ž´‡Wý21$«žq`>ŸÜ·rw9í08x£¥[·øTÇ {o·°¨éQŒõˆ@ÀµñrËT¿ÑáAxç EØ{ÜÊš ã[}ÏŸ1>‘sHÐÎN^…0OÐsÝè‚yO'¯û¡ÜØ·"¬úEžÃ{ÝBOQ¯µ¡gõFúÖ6m†Ž9iŽ=ùܪʳRt¼ª©s|b_E6sÁªW¸“ù¢AÀfålC¹Ü8Û”…ÈúÒ+=9.ògðÞ(•˜¸»î©ÎÝ‘Y?2i±=Mî2V÷Átk§Á‰…ž07ŒNæêœ.µç/uF6t©ä­]ßjÍÛjÓd –̰áQ¼ÓÎ;íæWH4ÏåA?~L‹þa8LÊö=}ërø‚5Õeku 'ò´@¥çhã¾G­>Çt‡ÀâæÖftt #X)^H¸˜(ÖÖq‘Á¡ÇË8ë…[ä=Y“ pÕv‚{ÊGÔöWfIž@ˆôœÜììh½ ÊPó©ÐÕrEmxu²‘s¡4’#áÇÓIjéü<áFï~ÿ‚â2Qzk£Þ¬*–5åÖ;¦«<€ÝÕRÂø¸û"¨8QÔí¬Rèô–!/=W uŽ"Ì.XlRÏ‹õÐg9Ëfáä½ñq3t0X÷ŠŠNK!xÀ\þÒ‘¦NUd8VÜ Ω¬@Ï×ïì–›¬šêqS9çÕaQ£`‹scõ‡´q¹ÜÉÿîý6aC$6Wë»MîA7Tçîw*¬€Gç¹ZV[öþúänWŠd,ô1Ü tÜ?.XDà¹\?@¹+Ød'f^æp~ mBLŒÎÙnæoöÖÔ=Dº¡öJ®`¦Ç¥NŽÐOQû9>ž¬à~y-^ÏFŽžuÂê$Y™EÒ^ª$`·¤!•œГ(Bt5çpóî† Ö)¼Ç {¬$×Ï_¨”E×&à6”fzqK6 :*>+}`4-OhöÒ]®ý)sœ@¸®ëlçÆžC_çã§d(·ºÏ2lL€o©O«K8×VÖâ­ñ['­)4ð·Å4<Õ}”Ge$Ù% Ïq_›[AqzÂJmáȸ°?÷ê5«L=t]²çÈm@૽¥P°fÈB’ÄùÝs F — c’D!¥Ï¹Ž"‹c.r{º½bì6•fyƒôiÉqž-Í¡jŒ¿;>Ýžá×÷ÒÓÄj£¶YôU¥Ž†8J4ß‘ ‚²Jd“Ì]›–J•G=‰XV"»‰ÅtÝ:QW ÂÚ2®s…’Ћiôgm)Žõž¬°y<©Ñ|•/Ñ6`ày)’w¾l4ØmÐ.?ÎåÞ•º×å"èóòÁdèš®LF0ïùrkŒ FðêÄSî,„Çï,î +Y†k¢ïù齘ùÄ_ä ]Œ‰çþ®3Øßµ7Kòd>æß^*Y§$%ÒÃíkW«Ù0®„Ê smñF„›°B’oo( «+$w€)0—º'ŸŽg¯T¿ñØ7¼:h 5©cæå¥P×¾¾èr2œ‘T9-wzðª=ãh¡(Énl¼UÀ/3ëéÍÃùWúâ¿}ãY–{@°¿^.YEh&†U X …à¡xÕâ¸j» G…™;Ê[ Fónß¡Eåν/:+ø)¨|«| ]¡Nsà§±Fõ(b°‘©vr‘ž£¾^¬´Ót2V‹zÙC[¼Šä¯#"Ü€GŸæe _ä3žw9צ-1!hrCô*äw´:‰îsE˜m2FêA¸,ƒ˜Ï¸Þ;§Þ{ÕY õPÕ¥nÌã…!<.tó| ÌO޻شq KFxIsŒdêOðFÐÚeð$+#z&‰ ¯uR5™”ïyךOµrõƒÚ+FëSØŽwJ»Fa _._Í÷XéMQë%ŒžR»$HÅAxû½Ìœ ïmOô²_7÷ئK¾¨*Î7@„Ø—v¸ã6)Æ«$Îà­PØ“«É•zb!Wœí,ÃËùPwÞÈ´/7‚õ°  ³•@ïcyI¨.€¯%8º”ÜÑ<3¥£`3•‚B{ò¦ÍÑ‰Ž¬•w_ˆLA6™ZÂAÛyÐ’ÇÙËw–'Vϰ  $rù¡C¢±nQfe0O¥ÔQ°X¢Nð;†ÛËdz;“”gIæ–¥E#‡Ïšº³4š˜ «L'“.éé]܈—¸øyp ×E„ÍyE`ä¿Q :Â3mz‚YäøöÙe.4Iz×EkÆ<ا«£±ž¬òtì$Ý; ÃVX¦×ËäÇЯkîåØ*ô¡¦?ÿ>þè·ðE–K|\Æ/¯ß#|d•ö«ý½¡go@JýQ8†ö“³•îwÏãê˜å4¢ËnÕÄ,°™áç‚âÎé#’ØW¼ô£Î˜Þ `gÊjâ4™vÊRóÊ‘¨=¯™á0™²ö€I¯jçn£»ÇLÁÃÂan*Ë Pt÷:ÁŸåSÜqŸê=Ägö|¼Ç£úµ„m ¼ÞQ@8•K“DÞZV»ë¥öRWãŒ9iØÖ‚®{»Š½z Õ~Ï•çNÄÉL‹pÎÛîºùyŠÖY º§à£ª#r ÊcÝI—Õ?ïÿPφeq›D½"àtx€ÈÉ¡9·0MY€äx?¨hÖH‹8»5š7Øw±¯I®W÷Éбré.*èHzâAÜ”ŒW¶'À ûjRÀ 1„Ûé®û^=6rÝ:¹sâþÔ£ÅèP"£X4˜Å®< !jÓÕQá:Íñ¦¬dW4W¤rñj³¦Qd›µa •]ð˜5ûÕ¡áD\õÕ¾œ«\N%·âwËØ²ëûrÐ1ÆÎ¡ ‹·ßäõà€öë0T€]Õg§<êíJl²âÂô±¡û`ú´CÁ f‹¶- j~2ºE­wM¼ìœ$ø¬¤³.% 26_‚3\ɃÄô)®>g_Úc½ç ¤%ˆS¼$e2¹ÕEåNdÁeʤ`Íœ‰=W BH©áÙQž‹é;*_=²~ã5莜ö¨aVÐΊ‚,OŒ“®ääÍz"ä‘õ-~ŽCN6Çå#3òT[†Éa–+`¹¡ž›§ºïñ:¾¦8 §e¯H¼W{t[¢•ø`ÏôZEC«»°ån¸ ¸Õuóôy¯•ɼN‰ÏÎ$(\ Ì ê¼Œ!ý1[)VÄí ™¶l©:lÇ¸Ô ´¨;1Ò(4’ØP;b¬xÀš P*1–CSkº¼²â+…¦Ê‡GÕ(åäÉR…Í¢zìâºÛ÷ž” Iá2‚o‰>«bÃèV§È]BìĬi'ŒQ {]$©… XO¦ŽýÏ=@ƒ€ÕŒPìÁˆ«‚ÈÃ}<ôŒe. üÍ«~”„*ÍNجžà>a/[íUf€$äR èAµäœf^,Ž÷X—Ë ª\…õ´ Ëäe³ƒ(>$¶Wt½£áÊ ´Ú,z5njFøv¬s"ŸŸe¸ =•|ì.\½oŶR`ZLiߣG~õ€ÞTë4@“!”†é¡qƸ`VÎl+vÎ!´_\â£kØrÜÎãF-y©wKƒÈcØ›³Ï«€ßs‘L\['Ï yD(5pNΤ˜âò"ßSÕQqP•h޲s˜6N •#šä[BkÉUt0ÖŸ6 +”…Û{1Ä£µÌ¨ÙE[ùŽ–ø|•4µqn8{ëuÌ‚`¿=xØæ jxfâÍ%1Ä8óöZƒ©uE»aé6!ÔϬŽ'ýUÜP–Q1íó€jÏ-xch~¹õn1!1¸POé½q´¼{³6™¡ÇiO¶j¼ã:ÚQÒ7.›ŸÜ3?|Î9áyQ…äîæÐ³4äÒá˜RÔ_¿©‹Çx®:«%{CºNðÒg”KÞô»&jQuc´~ꠦȔ,ê ¨sñ]A|±ñ„ðj‡ž¨åYa”$§¡8 êÄ1®ùÚ>{â霯§ª¢ÑoàE])ŽMM¸©¸dÉlªMŠ‘?!`Ÿ8Ü•üaÜ„ðÃó§'º|K¢/´ôyS¯Aǽ5ñL‡ögtï—'sUš†Ö:!T²m/qÃ4W¾Ñ;¨“ª *—#á1aê~‰™ÂjµJS W΀öVH#}8x21tR[õh »´aà*‡ÔåEy?¥ÎÄÊMλÜa}s:>R¸å,{„è^´‡yŽ˜H‡¢µeùÜ3W‚¶Ù°ôq&¦µæà¾P4öÆ=)wÚý.ã^“iüRV¦=äÀá&ÅOø EoC\4XèzTÌM=*ÇðÄ\OŒÈ4Š©Œ ®Ii¸áScJ®,+§‡Å£¸EÅÓ…¯ARÜ"κ’ÊçÖÞ¬3<+bìÂ`Mν«F)MÉÚ'ÀƦ1B©™µÑ&^TÇl:··÷–T-‘Á\¨`à™Ïñ»2ªBE˜|9òø½„íncGß*ž{Ê9ú¨bZÈpã`ÆnóãŤw„! êu®ÖF¦ÉÐY ½CW›}=Ž Ä%Ãé¦l)û~)_" ÇÕt"r{‚lUVQcböÜüfúnÄï^A¤â(¨5qø^•\—‘:ÒYø>$„·lI3Š©uSω§”joR÷l†Pz…^’©Àœ €¿ìíêñŠ $qî‚Jh0N*iGM»pVøµ…öó}ö:Zæp0¢7N¤JLÌu«G]p²ÃâqæÂãÀ:.Ì›§{ð¬å¬1²/´T·/{¸_uGú*ĬÜõ,ÌÁš™Âø0>$ÒÇvB];îÁNh*ƒï=쀇ÏJeF8V›>^èq½N&«È¥‰êóˆKÐ]H´mÈ·*¶d}2œ"}܇  ñͳ‹ò)iî§Ì×þÞ":QÑCõl{#Æ>øJžÝÈf½xP,’=3š Âbú=•r£•§ºáwª.Çϸî{ðoœYúLt,Uc5+Ã}Œ[%Šf]P0£­ïTÂNQtnæyGš: *Ù¤M"NðB䌔zê‚cÏ{Ð\·Öóœê˜RÜ'O êYª87'ç;Ú…Ãe6²x )YxevÓÉQr`•®õ{ÖUì_¿'íê,O7…˜V`Bõë$]|¯U¢öILøŠ3Îq¿S ‚áñž]«Ã„|Ìòx·[ýîåžÔht¬["¶®`Ìb2èK„vr2r?Û—ð$g=ŽáõWêÔœ ¯ø¡_^5’SS¥SÍž ìõ!ÌŸbX«fZ …³²ÜýxúÕ5z>€)ßÊ1Ø^ A|Ôò†KðqÏ;‘t òÚðVÖ}qÊ÷jF„ã a=cl†kÁ³9tÈ\}‡APYOoÕFP›—ó†€d4of@'S¢Dkéн«åE@œv‚¢7=$ŽÂ ôÆÞåÀö±=„‚·àÒkÊÞâjÚòœÂ// ÃpÛ¥P9ÙÃLƒ§ý”­·…^è:ìÒUi¹CÍ ­˜»9†!Á-˜Y×uI{7ÏÁÝ|Ô2œbSÑ9Ší „¡2Q„€Cº½.Ï_q"Ÿæ‚H»¼‚0ßÎTCðÜÞ·æM`Ø â—œB,â1†;¤ýPy:žâ;°>V¹x ‰ávÆúrh–ħ£#^d?#Õ[Qn(z…Ë£²Ç ÅR/sS3¨EŸî0´„•p>0¾'r­Mt6+$%ÀxôÀåoÍÆXöF±øÚZ7ñót7…ÅGP@io"Êè¦?¤è÷¬@” è¹²Ç<Ùƒðšx5m,[ÎöEô-lwàâ\MvTuHAÔÛñ5n—Šjß  ¥£}OÁ›¹‘Þâ‘*á£m(È'4kS8ýœÅð”+›®'6ÛÈjŠ_&Å›¹6|Š3]ïÜS ¤¶£ÖÚÇ}CîY]˜Šœ¥IöpG’¹tÝ9šâ¤Ï•‚ >Å0[ùCÍ„«’Q Õ{ë¯Ñ,óÒ³ ½§¥Y#"õ8ÚµˆàÄ:ð×<ödLJñtIõœ41žÙeN²¦TÔëjŽÍ9s­w<2ÌK´9£SPÁÈM¸³ID~Vá»vH)  dû\‰5$œÞfdíëÁꪺgmÜy¤æ RWØÁáa›€'z—ð´ŒÊi%ôI“-î¬:¶ðx4Jѯ©›¹*€9ÏìÚ…X›×ùïâÒ¦,4 ˆsÆ GÕž¼[hË^MA,‚KrMØ‘~0I8MrûfÊî€ ÷°áÞvAc ˆ°½73’äs&¾ôدY™n.O8WÄ/Ša‹|jõ‰®O˜Â{¥¾xN‰<6µW“-`úf]Ãk+:xr!9nS/5ÓùÁ}‹.”CHŸ¤‡Pm×cßYUrPµ~;èr-ê¹â‹R’bY7Ρ Á»Ò.Ïùè±w¼E˜rèÑ\pÕÇøP€F¯§`Ï;Íhs²W˜ÊÕ*gïÕA_‰}vǧt(û¹Ö`V {8Í) ]H¹+BWŸÎ>$ÈQº WH§hºð¡WïÉ`NŽE±ùIÇ8)“dt4lí{qÉÁ%ÇOh2^ùË"÷æy¸q÷¼›‰QÚÓ¨0ÑxOV ¼n$ <´›!T\µÕT@÷Â÷´È(Ž8…Ãïd^ñ‹—é£ ü Yi.Y:bÛ4PÍ5 ÃH1œSU Fú¡FÎì¼/8|*bï;<µ[¡†p@Rò¨qwtÔî,b×W¥–*º4ázÔ«wÓFaâ×s¡ª¦0º¢Ø"¼È8p4öÎî‘ñ ‘L¦![]†B½îåä{ÂhZŃ5¸*ÌôʧIš¢»Á­¹Y–¹ºK©ÏöOÄ ÁÍ´‡!D˜=£$önßÂS'–Z¥t ó¤¨Z:S,å›3+–šØ=ó†yâ¯÷¤x\cÌÖ”‰Ÿ f¯¼Ã“©BMÒ®}£—,Â@éwÀ)sBË—™+$#ÆåÅÉåžYÃ5pS¶5ØaX< àjÑÉw.`jØRfãÉØy]3Òmêû¬3›+õò“ê¢:í£Ûèî:MérÖÜñÚ‹l8|§î¤i8Þ1F~Q+鄸"vûåºf™ñÀ8±´^Zã{”LSå’#ÏØAëQRÕ>{T;Â~ÜÊ$´ûÜ$™Ó“ …&¯6|C÷2ÞZªW'ÄNzsS•_OîŒm w2¨–F±?Ï[}.¥QýrC{ô¥<òp{÷@ûIÐÍ«ã‘T&vNA‘»{OHÈ­­¦¡èÆ8¶0ÏÑòz†®í].U¶ˆ„ŠsÙc]³Ã'úróû7%>™$§93Y1Z.ºj3ñî%T¾CÛ>ë€Õ«~°õË%’½ÇRÇK»â*(nölHªv”Ý%}Èd™ºI`)¼idÖ©7 7ø¢¦fkä!ìåö;xê]vÞ[,Sá^Ô>$ë‘ä6«ýðå›7’q·MÃsoT#ž(µËò˜Ô”j˜‰­ìyö¦?dBº†gF4‚õæá±©êdiëÑ $‘¬SÛËšo|ÊâͰ0컨Š:oï*žÂötà2ANqRà5·£ñê"VX¶¬g?"‘g„ôPÞË’uqŧP6H[»g.õ(o\LS'M9}GÇß±–‘Çl¢žé°˜9 àŒ‚ÃØ»,3×Ì~“T*`GÔI¢üìO XµðEç¯Éú¸eÞNsI>¸o$Ô½«ô4Ö<n*ÖÆ¨’†¢É™ ¹ö–\35s§y¦Å|%×òx• ‹ãz(š1'ÆŽ®¼m¬¹º}†VQ¬£µQ£dnЇjH´KޥޣÆûÔŠ°àXä"¡]ËV«hg§ßŒkûžžÖieô5çƒUxfqЭOŽÉÁÚ« …uVBjÖÔÔs¾€Í­Ë ƒÞ-oñ”ƒÃ°Û¢/ÓwyNÆu´ð˜rÌmýeé`ö1=yO!ºCí2æ1Zz²b1¦P@Mî’)-ÊË7õÖËœ_.H‚œ¥ Ƶû‰iǹ­‹“lòÔ2f#=,¶Ü©›çRÊîeŠô@—D"½Àž A`‚‘nb<¸}Ä*žÛ/åÎåj'v“Vi—Šå s"±“f|C·ŠÁ·5 ,{CX?òÔ)/IŠ_Ò ½ñ"ÑUÎhjš÷Ø/ÆÅmæPN=І'¹É°¡m¦^¢ÃIT6> )ŽÅÈ*·Ó J(,Fnn§c㫇ïàPcˆž@•€Å3_xv€…A yÝ{ˆ5JEófÅr z¡à¥KJ!‡ÞÀPG„¨]Ä€ôø=˜j":a“pE¹ÝÇò\1zöYvó˜Ï:â?µñ£lÞH~­{,MDÚ«sýîlÖݹçÑtà»=83ц"iô8Ê¡|¤aY“.˜Žî˜ÐÞ×áõÚà‰r¿Z”[n®8„¹z}` ëís·–ðÄáìI æ|w-wñ £Cú^&¿iqVã.ɨS©91 ”ó™x’‰¯îòªWÁŸTÙͤÞKdj¯ Íê§‘H Ü7ú9=ÊÁ!Ÿƒ‚¨÷=N‡\E´¸u^¸Ë w4ïÒT´!ÛánÀ0HNÆÁô¡™^Öªä,ë€Q¡ð!ÓcBôèõÆ&Z¤w›«é=h©ØJøþ¼yX~»\%Q<ã>Xjbú”!‚‡’jìI$mØì8!â›gDqÍ'Ñvh“µ;„°€ã/òa?l>‡=ÕO³âù®[ÞØ³™~¦: †TÈ {ïI<‰H¸ÔÞéw=‘f\{®oÞ¶ïòÁÙ^óH5ÑÄ nަ;$ Hd<šá”ô˜U¦QYÙæ¬'`/q©ÙÇSüQ< ¶õçë®ö–µÊko}#{ãâ¾Ê„(¸ò†¾´ÇÝ*þ43´fR÷ávÙÀ˜Ýª`÷“í§ÐØŒÇsé/”òíîA6´â£ {šð(4Añ­Wj‡{#½µÎÂCãÒê´ð¶^9C“¤”ºÌ˜Gs}²B(bµQ©Ç%ã Ï­z»ˆï‚Ï „yÇE{<‘̸… F^ÏmnäqmLž­–Z¤–;&™'>áYC zÌadÄM:k8øÉš"]ž ÛCÛkÞÇiŠ]¬Áù²h¡˜Ò“{R¶:Æ^D=ÛR|¯mOØ€–ý§^JúÑ–D¾Fã¹PͱçsPý6˜ÑÍd]‡Rž«°…C{„½R™X&¢Œ×މòÄã]÷ÑøOáBÚótÑ{ûº}›üöNhÊ¥Ut{‰!(„eh©ú…5Õ¬÷M‡0F±n>vŠy–b\§„lV¯Ø{[o’ÞQË’^m»×'Þ§@´7gôž¿ŽawÕh_âxO¡k\K·©ÍÛø¢XîñË^ˆCy×úˆk×3Ë{D׋]§+£A¬ß…LúøaCžùîÛñ—”ÛÐA¡»ú2§œÏ“w=­»“w—à%ĦÃ{ÀyÛ a«6p¾ž1OñiCJx’ãòT/Èõ4 Á–ÇOby¯”Y¨EMΊꭈ¸¸¢¯>-N¸<©î @àäXQ|¶¹4xhy%ìÛ9Y“ñ¶ƒ›‘8¿.ˆ§™×±'ÝÄÎôXcÇ. ².¬–hÇž&,9? ¦J·Þg`a5.§Lá½Îéçowœ¨˜zY€YÀ‹žÇËÔe|ÝëBÜäP,ô\öè²7íN0âpy€ø¡R¡†bÁ…/뺢ä¾㉷oŽ i ªòå2¥Ú nËë)²˜°È^Í£¼$Nñò¾›iêð«å”EŠʾDGyÇ=ôºÆ9› #šžlØÞsƒ#mC €îGBQk1|&,Vs÷¼¢dÎMKÄ´›ìŠ ^àÔ1p‘6M¨±MO¼Dè zt$>(lxsCÒ︹¸;ð*?‘@Ÿ*™Ü¤â1ôÑBzI´Š Ã=MìCwÝ×ͽðéÍ †7š&,T JòœÜIŽóe¨Ót¼¼ r2 |„h@•zœÓŽzÛUpÑÌZæR',ÔWÜÍ˨Ҷ ÂzÙo6kQf߯\å¡ñëÙ"‘hsGÂT Z rQU$Óvì QŸÄÈÔxRlwc–Lm kâM6O8 îàjeÏ·‚¬z8.Õ‹#ŒlÚ1²FB¦`AÜøÎif²<„˜³Ö±Þ\¬ø˜ŽKN8‚é ñ§µÀÃ$Š"! ²\\勨9oKÖª`0. þ„ÂKbš{. *´¸í//öì²uÎ^äÂ%¥—„á¼7²€¶=‚Ò°aÃÚ-Ôo@F¢Å@‰“\yn%Þ cÍPËçlÇKÍ>5õpë’½îyä+d5ñÍ]åÌðÜÎNdÅm{ šD‡¤ÖçØú“µÄëëz2«ûl´µÞ6‚¢í#؉7rwŒx7Õ”¼ø)Eç½g-^à”Ü€6 ]Ë%Ör…ÁâBÇ ¥Æé!Ía—Lvîb$7~nœ%î^ûÌ—@ˆ³ç~Éäɼh€ÌV2zóð³åÓȘ·Àd|‚BW[V%‰Ëd¥È;z€Ã§H²‡»/` úÉô;¥²ñ>Œ±Øz§h@Îo¡=6Ù+íR •š‡î¸IףʌB=éÂÃUq¢€5¡ 6‰VS)ì(] i„»Ç*·OÈSæTÉoìÌœ­Ü¡QŸ[íq¨Ç@6»Zåéu‚ߦ‡ƒèt¡¡v1f'©UOT‘½ šw½ÁVÒY¶Æ|(Wåòní\3ö¬IA£ÓbÌq°Ûƒ†½+Ø Š/ß(ªÃôͯùÏ(˜ßÏ{àPÛ–O¢•OŸé½4y$ÝT¿ ñ7ˇu‹„RÐj>6%Çs¤'Ã4ÀxT½teXT–Ë9‚= DŸPàO©llݘ·WœÑ&•®ÚÓÒØ ç¤8áì¢32˜ §èœWK“g Ï;·ûê40¢µ÷7ÄK:ž—¢·’D `bÇc³+sò˜3,T=Ù°BLußé {Ó‰9ãpäȦÁ½a‹|ú`ZzÌ7³(©Ñ0ÊÖ|0fÎ`‚Yxž™ mµÅ»ÀkV­XKK—:¢‹naŒ7ž¹QG˜Éó±ÛÊd2>p{)ú|q߉ŠJƒõƒ•žCË÷ÞÚì¶EK"ê¸Ø»ÀÐÅî¶Þ2ÒkW»áØÞZ­sð·ža!‡g"2 §f³î½kkUNqï-÷Ö9¡yÄ@žÛ³Ø*zØÌo®œšÕ´Q´@}½Îy3àqáì.g­^ÀÔÂÞõÖq—Uðxz!XK5aø3«=·SÈ}µéš-ЩªY÷Lï]rã–”7YNSqÇ,×ôs0¾ãŠ0A/æ[Ž‚áåsêÛX|{FúÄTS¸6ýMÑ•Ø3=¶fôš‘{ÐŽ¬mñ¦Ë—_[ÖAáI¡?3í*ŒV©læT§m—+½ ïpyS.V†ê(AÓžì•N–€ Ý¥å4›mä²pË¢_ŒòΠØà^š×=GV?ä±h ™WR¿TÝET#lyý˜»7KÒŠ]D¸ˆ’cÉuDÉkÔŠçø’Ý£±<íµó3Ê€¬{Ѷ9þΪ­‘Æ4¼+8}U>Rç離¡°QEÇTð;à+Èg>÷Õí&<ˆK§Qâ¼UÙŽµ0ã»$}Ó’ +7ª¡÷`åZó å„ÛC>îC¬C5‚òUÓ vÚ¬#” ){tW³:A¸}T«­1Þíï#ªr<'C…•` ]ê´qÜߌœfÕ‘ó‰Gðˆt¬f§³•Ÿ ?~jê‚@UD‘ÜÃ4ìÁøJ9»P2[å†CùñÍÁ«µ ]TìÒ ް™ôÓ+)žxßXøÔËbyaxݹÆ$Óo;ö€_Tï´–²Ù‹MTwñÔåÈF0\=NIeéD^o3ÖQD} þ:@ÛËu;fvÕŠ @».[s—ì9­Ü!_ìx ”OP;‘‰uRîÌA Wû¨ÒCò’yRY@ƒVÄâcþ@OªlÖ¤¤¡Ò…‹W9ààFLómæHTcâc¡¢MR¥¸rxmÔ¯ G!°"qyVÇ7™lt«ÐÓ+ÑD̓SAbLÞÙÅ:oµéYÑÕ’óØC2çòPl†÷‹Ž£ <µØc hF~¯0(^¨ð ó€^oÉÊí¦ôƒnx7œÆ¦|Tu÷ŒÀåq^Q¾¸¸pÒFkIwªK¸æñë¿­ñ7ç~6×t†Ò^`Sx¯¨KÏ ý<üöÂP;¡‹’ËOøÄ¦Þ½*¥ç‘Iž–q[³ôÀc¹Øb¢Ï›ÑKÙûÖVÁâl»Iî½%\}`ÀFZÌ·¸”jÖy§x¢î´zÚõÌŸs‚Ô½âž(§7û@ü²HäµHÍc©Ì*WFfF@0µ¬Í¸Oï(Ç&I[¤jNS´Xš­s™pÚÒóåÜE7~=¹yˆÊúŽRê11-2^ žVÜ‘i„G¡ÕqgL¿ì­á{o|³Àßê»»ˆ¾锵ærU$=ìÉHZ¿±ÀGWú,Ma(ù!ÍMJÀc¹z¯Ø×·åÄwqkwy´jÎÖ=·È"dÞâ&^?¶QO÷zF—Þ­ h©tÄ ‰ã€÷D¼ý—"›ÙƒŠ´ˆÈå²ÖE¥ ÏÄí6Šb”d››4Ä£b<ÀF8£ŒnÖîz'n˜©Ð=Þ½¸Ù+ZC+ùƒè§WàEÆ÷,àU潡G X3Ê'F—‰Uö½oQ '×M&¡a”Z¢iš[Ó±æ5ë£, G'¬7ùÒ+ùuèò¸r6ó"è"®q›5¾À:™ ¡X Q«ÓDìÓ WU9DçÁZ'ŽÜ :.¨Dƒ)H‚EAQ7üÊÅû¡?k¿9ˆÂS™6O$)éä¹JpÀꜹD}Ô^ʶÙWÌÌå’Ìgä 6 #`Éç¤âæ®§{<[âÞ`¢#ûŽc0-Çhá h¨ä ûô½B7o $ZNg_’x›Ž­W÷çÎðz,÷…Ⱦ~}ÓMÆ9Ëz/®ìíkpY8xÏ19]ÒßËÇ…•XõEt§VJº6>p¡óC{WmѤ.+ öY8kûåëI6)è~£Dïh‡u‡¦ÓäÙle­Huî{¾ÍÏß«A7ŵóõn‡xÓ¬(f÷r…].³$òæ¶Ž$œmvåöÛ°×ø‰§@FÑ4ÍÊ¥žMƒ;"zJHºKlO¶·Øê O…Ãk«#æTOÈÀN×3~UO¯öaó„>=Õ†"‚~¢1FU{¶cà_½S©ÈÍf‰Dìp}]¢Æî¢ó*kÉ¡ê‰òéëe ó{0%»7ܼGE:%{U+Í‹O¨éNÄ3CÒ!žÈ#ã¨yÏÇ£.â¤[ÙM··Û;•7¹J ù`‚ßsôôÙw©Þ’D¼·þ<${WsléØŽYÀœ€ 2ë@»À„^ $Pz3X9éëÒ€y#Ñ„T|o(=k#|×h–œÀ§+;Ÿ•ŸvH‘txéƒtÄÎ\æ’¹|çª|¥æW8F3sqýì—/S1ÒGÅÚèRöšh©NïÁÛSÅìe_#Í^ÞC ½×Q!øîë~znjwŠLš­¶4ûd´%ÃXóŠŠX99ŽRœŒ¡™ÞŽƒÖ êf=‰Ä&cq¶Ý£ÖOžÑeˆ@œ=ˆ¹îO4(ž’ÚQšœwî¹oï³îy ¨@ø¬À¢ŒÌ«epµecu°ÄeW8`6‡ ×+Ñf{Ct Uåî/DK“ê4‰¿1ÔÐ K^ [Æž]ö—Èï€\PÞ¼æ´qE„ ˘K°³ž`½dyJ 43/¦üb‰§&“ž:€½Í—ÁO··.åQ\©Ý‹FïÊ|yºÃuü~qî²ÑPù¶…Å2ºÒÚÔ:%(Þw–1û lodP:À36ì•0Òƒˆv×ÙÄ,îJ“kË}÷°{ž"n'ëÓz>ýùÛx{õNó¦ý¦iÚSà iÖr úÆåÜxüˆ_J{Ž’¯øˆ>ÇŸ3­kHÈ%ˆ¡é÷L˜.r×Û–Ç=‰xè~¼&43ÍÄ0ÏÊ™YòÀWà%Pº˜8Yh>ž¹Q.éÀÒè‰z÷l.eÞKˆ»NW˜>Bí÷Vl’Äã lûÔpºP z]A'£—"ÅÅÊÉŸ hJÜ“%e”2«7Ç!Lȇç…mƳP=èü:‡ê:O&׳bÌ^ÀÌ<Ä— 'hJЄž˜4'²zžIì»tÔhؼ^á]œ/D/ÃÖóŵN‚ÝÌè³P§)ËWpÏ‹ ëj$õuèv{ñà½AÂ"a­êNž>Tz1y—hVزž2¿¹×‰€Ž„Ѧ¹âÏn6“îÞE¸ü¢dªzB€£n÷¥ø‹»F3{SXuÙoó_…áKxÛë‹Vïih¦ªû‚WȦ‚:h5$ UeŽ"Fa‰GÑÓà mÍå…ßCµqg ßapG¦GC5ˆOpnK4QáH„`ŠŠæ© ¿»I©2e²‡n8óò˜€ó*E ´ƒjóÏÇL•óžeŽJë(^îãU¹-&„¼ÕN¡÷vyæ¥H§Üت`¶!zÃÍär½åçú2»Ç{Ã̘Bµz²b¡ng•ºb‰ïìêšgÓ ˆDXVzC‹¹yVJÚ'ìS>ï‹Ÿš ²‰¥yÈ¢â»zñò][Àñ)øDO1'ŽTp¹¯ãeóÍIs0¿Cª@lwe }!‚è±y§Ý“-ʦEa1|¦»ûP‚øÉvùààcsS·ÑÊ~bð´ `/×{[î½Ò{ØÙ‹ÙF®'åNÖ©‰¯ôêDˆg@ö@:Íx¨‚i¦ÞƒÛÜöÈ”Õx pþ^¾¬Èw«@c²V‹z÷äé´2¹=7€ÇïÐ=kR7ROn`°×FL¤ã.U ò Ô8è/(ŠjÀ8f;¢™wÒd¿~ ðízƒVÀ–*„²/"”ËÙþÂ/¾ŠSow”f)46§Íw%ËBù“®<+ÔǸ£œd¢¹åš€KV½/2íõ˹~³¡Ø°8‚’ôˆ«,&qä’höŽuøà€Ìéq-ßös1ñz³dîk¸Ób¤چeNùt$Ù«N°ùxM£f0:Ùl.E4$ 4! *¼–}×­BVé„KQôúEh½yôt¡Ë’SL±(nÁÐ轺Ge%3•ÈÂèLu$à'‚ÑÈà =ö{tÓ}Ï@±ü! Ûw\õ)] äèQ³½šÌ1Sؼކx^É€F)ЊZ&™<öÂ5½²+'g)ÈxМÉH´}¹ßVWÇ"¤úë2K{k­¾ˆÎ΄ÌxgÐU-HCC©”9šÁžüf,ü0ÅtNléîäD£Wæ1(&¹ÖK).¼Y]"‰^Æ'QŸW¤ûë¾!¾§ZãeJñFÞ´wï8´¼íRzØGEˆó@âòü&éý‚î <:¹FÙr¸„ÃîºM”neʪG‘Êyç8C’ÏçÅRÖBS´§ié•L NAäÃdÚ×`®¥‰D‚†r>Oöž{³*a=‘46Z‰ÑDUÅ öñ´Æâ±|XBxr-‰N ¥7™S÷;bö=ÌIõÊKVäsE²«còÐ.Å^ò=r½RBl¥ïÝÁ?5ôø/ÂCOLWe;EŽBú²ÇéH3wÄÔçÞ ê<|¸ôH¬’Oxgã١ǽ°¡ »ÞH8)Æññ˜±Û(jýÊJë¢C¬FM餩Zð…±U•Ê+ŽÐwØnûzî5WÈxæ.Dµ_]ª;­¾ydîâX×x8ÞJº4°³NžÒ,iŽ/Ç”å…ÅVĽÈËíÁV*Ò>2gáÄ*µ4Æ6ËÖÒ¢ 9>x¥#ÞwÐ ÓþC£;¤]q;w»°'Í×o£ ¤…Ù¹²C°ÌœwàÉ•›ï‹‡¨-îZ.õ¸êÉÃÛ­m*7ÕJä[¶]XÇÉQ¯G d–75"ËHʉ‡uÞ>{U‡WǘNýbÇ™„B9Á8«óÐIê{ùˆî0GÄéÒÀ¦|iw$ÃPÆÖ‘^ao8¿á$+Á0µ2ŠwŽA³jzЃñzt Owåœ Âß¡@Út?åFVA³¬ðn ¨NÇ Çœ·áË6o\¤!=$ 24‚ eDº*7ÛkF…IØ£ÜÙpËP öœñµ®ÈÇ!gÐ;kÐ K³Ýeá[âÁxäÍ…ÔÏë­tò-¥õQ‡ÑQ`HÅÆšzìS>7§Ðcò¦ -Ž5ÍW©ïnúõ;ƒ¼ª—8‡Û¬ÄÕÐ7ƒýÍõÝ@è"^sÒ«bî„d’mêº&á÷… z³<甡4/ )^OH³É®2Æ…jbb7@q{‹|Î…Û¸ïrËŸŸ<ÜÞX[Ù«ç8·2®5¾%ØÇÍ:Á»×ö&_4Ùæ.Øþ¦'Õ-ÞúfáB…>‹RX1¤1šoagÈÞ³‚yq±p8Š¢s½(«‘eª0Ͻ»ôr/’áT4ÒŸ$XË.A<í]ä»§ÁI52îÑîé8ÏОÍÀuÃÌ`çÛ ‘×ç=iK PLúZ#[ å±LÖP( ç¸>7ÒÁÚk®&Ùc39xh•o+î.Þ‹ée‰U> ~«Ï†ü1Ü)ö£’5¹·Nr#Ú*·5¸«¡Ðæ¯ôÙ¤Ûîã¡—.cé,G†ÑÒ»mðxº_ÃõŒ½G -Êb»ìK€Ò ™;)a·!¬ÎÐOC¢yh)X$L/|Jnœp³«±^‰•²SÇÒˆï™.úùÕ%1®RDÒ„«/¡ä3}ó(¦J÷j*y7ŒåѼmË8H4d硃 À¸®Òd‡¬­kÐ|8-y~uXBîϼϙW”^¤^S?´¦nqloßœÄVÑõ:?Õçv¥š ²E`;)>õzvÍÇgcº|ƒCN\ÏM‚äÌHÛÚe3A`žš3}#">Õ4ºâN/ë¥ä -Þál.8϶8\Ø@ª¹ËÜ:qÅ\6æ‚©ñë}j‚¯SðtN’Eò åF³.8{’È I˜]ÒœõÊù(ÛúpI½«{Ï^¯àC¢*[l^«\æ)¢¶ž ŒØç\è|‰\ žx-1Q/|jã= ±—¦Ï2^ÖúÑR±£éð<Ô21;–§œÏ ßܲÀ€NúéeˆºEBŠômÄ¿MÙd³JÚ(æîð&~¤ˆyñV„X¦ŠYÔAŒ­ähÃᨸ¥CѸ|¼ÒIKôøñ{éå(>´­š€/LðnŽ@:Zþ„Ħ<(ëM0öÃ\[i‡ A†‘ ‡Q?v[`ð„A›g1ÁÀm´ô‘¢±dq3nÂÇ‘»®ŠNs¦¤cL¥%Þ<úBplJ”að˜ÕÆ hÁñqÐcÌ=ò+;€ƒ]MÕ6z‡ä/LgŸ8âúbå)¼#ï‹·¡Ù§[Û=úú9Ù4)6 kxQ÷‰ë½*ÀÌ[õAòÅ«™’Š r娩ªøÅÖZ[ÄÕ¼ŠDᛲS·z€ 4!ó²·¯‹±õYÑsãDm9Iýª¨ èêÕÄ+•Ån°V\ÌQk8)–&êp\ÑÞm|01D-“žŒð$ç±…Ï>ô•ËÔÞÎÒƒô„Ií€;ÛÞ-$ܺ=dºšžÈ£›%}£e V®=“堇ΖµIÒV¼ZF9øÕ<oy,cò­—ؽ&Œˆsìô|/HÕ‰ffãj[ÞëxÏ1ð=X“ó›ý"qRõ±È­Up¾@A^‘ð™d— 0÷»É­0ëôu$ôy›!MáØk:/žšWËà¼âäd„ÙV ˜¾ Ȳ‰ó±[ÃÂÄ}¯®iô¶uÄ."(dMà{3t—zЯÞ ´¯ŸËã”\=|ì¥nŽçÅiÒ.,n ºÄ€¢ãPÖÀOØÀSŽ5g—ˆÞä°½î‘xõXßæ†F¶ Ã$>%5øÀÝ,¥.ï©(ø¦Ú[v‚ÆLcèÖ}~Œ}´ÂrTÑ–#»Uû Pù»vž‹ôk£o\^¢ÀIß7Jº(7Î!”+ý±rz,ó&³£àT)W3‹E0N(0…ÑÀ†-€xRs$—$BóÀü‚ƒF•f ÏÉ5:ŸU xÙ®ãâóFC¦ì[çzpû@m·KØ8eXúfãxh/Þè€H„ÇÃàñô‡>¥ã(Ÿâ<€1d£1v?âgŒZê¡dÃ"÷Á°³«]%Ë=·qBËÊ󤊓AYêÐT×fåþÔÕIž/óñ85€Hƒ$¯Üè ùÌöLµºé8jÓ‹”ÕÈ'…Ü©O:ÐE—É{ÛP¹Æ¤N!¯Ì3¡Ùo«´˜ƒB^c6«°#bâž ãsLÄÏ3‘zot›ØSÞ˜ŠòÁ´s€x* ’9ɰy1ÖˆÏã(YÞ•`H¥*¾±|'ŽV‹”e '¾çž„ &ÙÀò²upzTö!²«4çœy…Ó–­ßó4Ô¬jSM¬,tqelïJJôJqN¼éw©Ø¤)ÚÏã‰uÃÛ‰¨V‡ÌézñÜãø>}„ùË*{)µDñL¬ÞвÔê>ˆ=àמÂt;ºÕ ’vHT0ãÕÄ.¤;¹oñm£¯;Ùœ%µÛ6ëôcœ]p#®&ò¦Ôn ³$X’šzRì«w23;g‚‡³§øæ-#L&%t° ^$Sž* ¹ yÊ‹<Ï\dtðöj+…Î~ZÎÙèLºgü´…mƒÓ ü³ëš“üÉæŸ<ÈÔ{W^'¨²ƒÏH¯ —49ÒH‘b3iÛ‰A£°I _Q–»4¼V†Š3uÝ‘‹gËØ×c¡·ÜO´еßSÔ¸{b!¼5騰rŠë7…–Á€ˆ‡T0âtŠFøä=×jðEÒy†¡–ËRnnj‹–éëO§gѵÇô<^5{ óËÕô)Ó¾=¸]Ýãr(Y Ý“rÈ•pðBÜä%pðp ìëVkÆÐºÅSAfhu|}BJqAsx+8(ˆsš”š©B~¬›o’N¹žtÇ®ç€,=TŽpkRrÛ7„“f;yJoÌvßðŽpÄ«ä€$ž1¦émQ› ±Áñ¦Z"ˆ{’«øLPMÓ<«8â"ž2î7vƒ™¤kÏùbŸ¼¹·Dãê í”… ‹Ü€Å¥‘­ÓÂY$3þQ7C[nÝý½zcèïj£è¨¯vvñÅ8r£a>°ë° Å-{;= Ò´T(Ä A™"Pí}ç³Ô2†ò½Ý'á:@‚Qñ€ îâbg¦ŒØ ÔÆoqpÌÓìp›y‰v,s†•ÚFMW €2^ £éó¾p¹ #¢º-+Mks%+ÛzK'­¯S^2¬>¶p~Ç}ê)œÈ¹E"äð$¡j(鑼ôib^Ž· •[Å+°a÷8ËRÏ¢‚Ð~Ø·háD•råb&ØlH×ñ¼XMIP‹g’VR‘-XSK;³Á™­tÍM˜›%DÄôùæ>;ÁRÉÜ ^OC£È¨… ßï}â}Šk¹^Gˆ$q1X†pZDçF'ª ÜçpO¼¯™Ü d0`™° £2ÕžQ%´xÖø¢3O©yeò;"¹w òÔCQzJð+*ZªËðé'‰¬º>– dïu½ªÊKáÓȈ##Ù•™Ü×ï …Õ„(ɉ7{ª]Àbe^?D;@Usr BŸÔ#ÆÑ ¸Æž"yEp¹,Cì/x°”ž¼Ydc¸W.¹ò"f¶ íÍzé@åÃÈù¨Jᎉ‡bŠNœdã¤bÂEcɬLÒ ËÉçžFyr‰ê1T–˜±È 5‰v _‚V¤õ>n#´D{ó§Â~çZÎn àÏYÂo'ZÔ ]oIÚgS0[bÈí=ÑÁ\õL5“{’"Qf^6ÄÚÆD©çìJ6´/eDvpÝD1…5_Zc€WÕö#ÚœyüÆ.›RÞkÔÕ§§ºSúòÖ•`_ug ,sFŸÒpoÜsÈ—ö²Þ  Г£7kÈ®¶~ÀóLÙý^¦¬¾)/%~n œFö(«lQ‚¥N*´íe†Ð”RxB8ÉÊÎDPД$껥åN!ד¹~ikàX¾¿nnÄ2ÑÂ0ÓÓé·±Dd¾i{æ0$©äŒ%#c¼­ûªÀ¨Dž[*cTkžI Òy»›4Ùk|CñÆÎAÁßVd¼4W`¯‹ÔÄf?ö ½Z¯JzñÔ¿VjŽB|9†åÛü2ÒîÙ»'Ž!+m‰0Ñq˜äº@\ûÒ#÷y õ2Š>Ķ‰Ñ½zjã÷ªÙK2M­ÏŸFꇮٞÆ]•hû¾„ÛTŽ2Cm5Þ ×J…ˆí@‰s\–û€¤MìU•D¬êZOô1Ûñáál)²€o-»LÑV¸‚µÛl*\&ÂWŠô2<^°âBâçÊöª­´µéÔAуñB…¢çüõ ì ?} GJËn—SU10é÷Æhƒ¡%­ø.Á˜iH:Úc7VGµ_ûí;¸ûFŧÂV´w†©‹Ë«hW9!#·Q§QK«ÑfÌQQVàÍꉖka;¸=ôl+‚AµÏÞrJ`¨çzâÓ7ª¢ƒ`°Øí“¤‹çŒ©‘–ê¯Åa4çáDR^ãA…Òb§daÐâãÄšÃ76XqÇ+áÉÅ‚q†ƒö‹Áne©D`lŸº÷€ õQ&Š’MD¾f€;Ó£',òÜçÙ‘ìª6æ¯.ù|hÈ=›*läà,–…ÑDH´¨0EC E–eÉ=Ÿã/H«Ã(¨‚ª¥ %6±Æ’‘»¸,1›òÔO`,:ÚyMàlà]¦x]þ íDA5AÖfsææëàΖyT5¥Ü ùæ@^Y‡ÚŠ%›^>jjTh62ìÊi°dMkX(ïõ"²ÎÖ·Æ‹Pê­W…$l½n¥ übt ‰¸ ^=ôÆQu]Zo»î×<Û@\q«.öŠeÅgCêh>zƒ”°3“,/9+KU»ä¹Ï ¤À ©×FÌ«ö~,üâV†:º]ñ6ÞóÕ­+›i!d/!Øw·(T~ ¶C‹Y¹¡Ff:,Œ #rÄNûñ;ë2{w :€0(šC2;Æä"bZØ–L fé^u¢¥B!…Jl¸ bó¬$J„w»'²ü‹- @Ë9•È>õí±Ì(ºmV/“†óª*pr'ôòÚž‚seη5ˆ7¾8”'¥<ñj[ùfö®&‚žvN딃½dr BˆVò“Fd›x4æ\íˆÑjÛEÒ:_ÀꙀçð¶~åFé~yÊš{JêœUUᙞejÙ<ÚsJ8 ÕŠÓþÞ½S<èxºðˆ²Œ}=MDùjÊ€¢g(ù•E­rÕ$GÀÕ¤È ‘,ÑIÌ…­v>ôyø¶ÌpûöY=•ô]ÏŽ‰#®¼gÑEè[WÉa½f¨³9Y÷dÎ*Hí¥%m³NÞzÙÝ#BÅ«À“êô˜â‘{Í蘭{…þæ#b®ö¡4#:…gGÇæa"]wÏP¨ƒ²É+}²ÌFx&ÞÏØFMØyî2E.e_œåÁ â¸l^ó=xQ†Ö¾Y1,Lï—Ji(^êð ¡’,ªCJªá˜3âUpq÷PêÀf•LUV¾0yÍK8fT}ÜÈÅd6I{wþ¸°ë]½Áeí€X}ºó&7·Mm)Iµ _vGm%Ý£Æfì®ë]hD^ #;‘°†:—8hS[t€—ëKÑOŸâÝì‹C• H®¡}+eK¯àXæ(3)‚ÞQÚ\H)\ºáË÷ ¯ó({­±ðO_ÈÑ\V©î~öpã.°›ÄcX@„DG¢ÜB+‚?>KŽê|® ”c`Òª@”%²ñ”ÜpfDƒiDý\í=â.ã¤sa^³%¤|±WIjGiÊ“àÙO 2EE?ÜóG‹«mÔ``$Zêþ<³µýäÞ{Ç-^D½‰™JÌÓD—î)µÝO©¬ë€…ÌÁ‘Û¬ß{¼¢Hóº¦Ù7Õfa@‹#’Üý„äƒÆÚ5¾aGeÄÜÓˆEL´;Ñ—›jn|7Jµ `¯Ráä镼əbܶõ‡šýÒ¢jŸ-¡äÛçg úÓÅ£ ÈÔi“ÃY?Gìê‡2"‹§Ã'š9äxWò"ÙÜS“—AcµbÕïLñ¥¢dÛËÛ6ÅX¸§`8žÔ‡WìÊa#y°ËrÅ™°`°båžÙ ûÎÕ™ÌyÓa*I‘*JS¼^2#wÁy¹ÎÖºY2Ó“¶!ŒÝÚï`U×sÅDgå¹²ÜfÂúaËéA e•½s °¤H»¤¶õj{õÈÆË±wÐâu>(Sâ2‹*‹ i2ŽÌ4 Y¡»¾"Å}C‹ê—` ɨ7b&aæ‚p^í „$]È2&D‹àº"Nì£çŒÎKš–0©³f)Sø8“ùí4ãÓ~§VXœ0»Ÿ¸ào­M£OØ„ç–ÎMR}çúˆaTÓ³Ô.FZØ5CýÅ\6ˆùóõR¢-ö1z1UÀBN»ãµæ:‚´»olÏÃÜÄŽ\Lò¹A#óÛ1x¹ÜÆzzÂÏX]ä= µ.ÌbC~Š»T›CÇSˆN/†¶ö¸š=ýX•¦ª“°µé Xï `c†;;uºyÐyÏpóQà˜B‡€!Lq\<|w¿JàÅ´ÉëEwµòhö9gÕ={„kÙ¢v°%«ïm•k×#“Š­šC|x¼Ï£‹ž¿\ÚÌV”·óx^Ç«\ISñ'/…š£¬àÍ­ðM½ ãÒ>BÈVý×#·³&ÐZkŠR]. ¦ëô"ZÞ«iä«lÔwñ¬ “7uÆt™  íÕˆ†¨–WÃC àôí©'{©Ï_@"ßÓ—²¯áŠŒˆªæ1=2‚¾a¸FÅ&Û-k ÓÊÂC…Nó«Ð>$R=_“ëÇüöuåòI+»ªÖµ]ʤÛZà ;ê‹77¢õª‹œŠîÂ]Ê3Á…„ D›Ú¢„)ráð6Ë¥‹ëö£‡e¢`.+K½H9²¾(I/M²ïyÏ 5l>k¤Ðº˜gFõJJÕâ.À~O_´ƒ˜Íª½b.Æ(¤|S:jn6Ñ °‘'Gãž´{£g³lÂXNŠ'¼*›~¦sY/PyÑ™+'³KÉ8ËdÖí;’Àzí‡ˆÉ ÚÞòÆ¥¸Áè¦êž\;šøCîD{W·ØZÈl*ôŽä± ŸQô2ÉY ˜Ëô(û¾ ,ey’n.G ʬ­Õ¸u‰ÑÖ+Oëó-‰ôXcGï¨0 ç{øê¥›ú±¿…S/Þ÷–ߎŸ`““ÉÅ%K#Q ŸZÔaLÇ"Ì™Ÿ-€#Ö Üä£U“ ÷¼fa—ºgØ~S„šôÊÛF§Œ¼(˜²ýÊZo]Ó™¯M9„†â‰†‹&u5L6ÍSÈæØ^ 5T,^ûjï5é£"OÕ§ºÙ›ÔÔÇ}¢JÏÖ|›¢W„qÙ‘ßí‘Cž âN´’=¾D%çãÂÁ®¦Ãvyð¼+ÒG³cW¼Õâ ÆaŒOdè§ê¨ç©™x+DR]¾Ž;ÚÙÓ¡¯ìΟ³ì–k˜)@ŸAUú’…"ã.1,]¯óKòÈ« À¤šn ¼·61+´"OD¡¼=SD@¾Î§-Bq7§¤f–={Ñ“±>=Å‚Y¶—LYó¸Ð_M8v^[ !P·ÞPë³O¸ŸÖŠåÙhõŽœãXÞÂ~.j÷âdÀœŠÑªBë¥èA{v*½y Ñ™M§xV,ªer8„w¼Ê dÞ»™iO“Ò¹‰Žl£§VŸ–KB‚rzúˆ®Pæ!¼y4sts–J.©¦˜D—ü.}¦Æ%:ÀKÈT£é`ã ™{_¶ØÉØ »èŽå;õ2¢87ìu(³wôZ'=çõ>H/ðKÜͱ&Ób0ƒ0 „8·5Z¦ó5b?·&§—¶÷ªV,"k§Oìm:Ä#:ýó<¥ˆ(¹ïF˜Ÿ› øR¤Øœ§¢X?uW´ôIå öw’޶04·Œ}G„Ç#Ka’|™ÊÊ-žÜ’¹àëqB{×Ôý(4={ê:ÅTÄ±ÎætL^ð#ƒ(‚)G}PqªP’éoS;\E'ŸĤËò6 ôÛÌ{™³“¯¡r. õ¬_.Ť&j ˆ`YÓ“çÎ=± «îb£CeÇç"¢È0ÄbÃË!߀$Ž’†ñ»zÂDÉø°Lý šÁÊ=SmusVê8ÓYò_Èá™å{Z!f\#[ÆvÊ,ãÀŒl»ä…Ï<ÞqAaÐcƒbáóÃ* ËwªYHGû¨ÃæÅKsóÅ×Ë–Šq}ûdÜ ¡žÍ1\›LŽXE¿åÎÍ z;ò:ËïfCv„Ô bãFÄ'¾´y"™I4Æû^ ­x°î[¢s!ÏÝej“¿ÁòRšw¦!ÑÚíqò…AY2Ê{îx«ªÄSÄSD¥/u 憽߭ð"s)\ËPµÁ³æÂ·šà–±“ìéóy`þzl–7<_ÌÓí вî^šÛyÁFáZ»s¾fB¯ÆðJ 4‚Š ê<•[‰B• õŠªQ!vvUg[Ó§o »vý 9½ʛĞY'çc”xË6RŽC_ë˵}rÏ8äö©¿í¡²(Q2çkó€ǛÛ'.&Yú8Q?u“i8bÍÍhb›6R´Û ,­(“››Êö4á@LL§‡BÇñЕŠ`+#¸¹è€@!¬&ˆYùËð¼òè]—àŽiŒµ¸½òw}ƒÏË’+‚õ8;’É|qu±¤ô«¿ÀAUGpyñ;–öÙök´¬Ç™¤FA†ò¼+p4:Ã29`¨ÖnäxÄ*Ñøj÷Ð[¨goïݱj¾CõGc*±À9Чõh¦ÓëHò<^]y†¼9ÞyÂwÙòú Ûíí¡ì!^n„ÚµöC_ë¬ò¤Ç]5gǘùòQTé-Š—Ööý"f2³ Ϙ'8(TuQ• £Ç•¬ùL06Öh…ÐLêðd•Ø–ÑeÁ¼Î„’¢Ó|G+¨_®À¹Û«~¦,wd‘¹×Ô†0‹ŠÏ‘4Ÿú hUïËäySвSh8w<ÇgÃq híœfpãlvÙ£Š¼û½×”àᇖ0‰Ãõœ ­¬©ÉÞͽä+VG0A]Êé<Õ÷ÐÓH9B5y4^3Óš^/"Ê]m|õk æíšr-»’Iì@Vg¬D§ð½#ϳ½¶Z¿H\Á2˽º‹©Ø‘¬Â÷ÀúÈÏ®¢ÒlÌôæ¨.³?ÁáŸ"\ˆž$rqx•!‹qñuš›ú)·²š`‘Pv¼Ê~Mù|3 nø‘2`Â[¥íÇô„Æ•ºr•^Œµ%žoÇ@.‰s¦ÎèÛÄëqÂâÊšHžzÃ{“ÆÒŠËHà‹¢¹«ˆd¨“bÊï½ D·©·w›#ŠðF1jž¦¢Vݤ‰€\L@q£Ã`>"©@!ß_LÄ…ò³€â¹è,¸}5ó‚dpW#+KX̦î츉÷ƒ[“Ø+"dìƒõxâvëè¶rÕbæZ¶^à¡ø:HçhžíU­µ«Ñ¡‚ÖŽÜ‘ëqZ–úÎI¹lá G²\V?q–œä‹|‰uênâ“Æ’¹ÊãvO=Rß#ÉIRw ›ò1#mA{’ð–Ëô4cݧu䤒ƒV%Ö¨Ûe¶¼7VR> FÏI%@tÍ™ø{›g ªèsSùÔ¤xsô´Þž?]“ðªñÆM”FWžÇAêñËaMk–[û q®:Ý'ˆÞÆ&ç ÔúRXVBò¾J—£K‰ˆ-2‡ƒyG2¦©T€  zMÅ"À¦bo‘•;\Ýž9GN¡r±—SluFÞæìÒ)ej'h+IÄ{2UÉÙ\vô«h!*äÂñU&%¸–Dîò$¡{wÒ{¦7L–uùNûRíòñÔƒâÌÙèõUï,â_™€•?Ñï èyäùól—€×>¡‘ð,ÂÇyuüôi½5ðà}õÜò±@_ö!'ÌäJêJøk¢p<²y4²À²‹{ï9]y)™g ·L0£>K{¯Ÿ¿;–·OÒ6|4z—)(Áž Z( ?u¾'¡ã‰Þ/‘…P@8ñì€ð]™¯‚ŸÛfºQízfˆ†GèÖC2ÙzÅ{BÌ€l¶XÔ)|e&ÒúÂÖ;Tiq±¾sbnŒ½>ïW©LOóÙ‚¾Ò—â¦z­S<¯51ž+pšŒÛÔ²ßj`4Etë6yÚ/Én³)•_Å Š@^˜AÓó<ûsï¨|…½Uꉑgé7mÔEhà³7'Ó‚p]ðrO ‹ZÖžø¸N;ì”P*3"T¬¿~wh{òÈVóx$lyxeûm†/ 6¡3¼‘ºÓÕ#QÉR†¨Óó&e-:UQ`k…& ʳ{ãs( §Ç<·4#ŠvKQ“J¾<3i†k†„žB9Û5u6Ú·™Àéd@ܺ kÐ~ý˜ ØÖŽðBÀò‡ÕѼ‡¥´I3>18C .¡{æh0¢CºñTÏ©ì08œ¥0HϺZ°×…YëoTŠv[ ŠôTT"°s‚ï…žI¬‹×Yf¼ðzÇg'M¨ÖȲO›áteºÇ­ý±ÜyEYƲ= UôÝ¡«Ö[–*z¦;†Ð‰Ï“ú]F9á¥^RáSrh®Üy4®—íxáí8 ˜*H‹§Âz ²ž§‹òОŒ¿xhzžÝœ»Jà >%å@yìYÜ)ªÑB°^Y#ÔÉl¿yõ²æ s_Ie¹(¹æD{È#NP6²Oàæ@·ì&€‹²_¾ÌÒÝ&¥IƼñ·È;b›”e­‚Çé`˜zè%¬RÖ¬Н»ÀMH£·¹úb"jI(W¬®(oŸlߣÔ> ” €½>‰–7/¢E ¡E)àɃAmã}óð)Ç‹ZÖ¸4‚¨Ÿ!h‹RqçƒG~¯tÕd]—8ÉÃͥ&g%TÞpCJ»Ô°ð nÜM69Ê oì1½Ì–¦æ[gè&ƒ>WqHD3¯ÚÉÄ,ÑÁ|[êœù"öéd䤿;ŠŠË;»JSŠÆ³z‰+ 7gÒ–Ê…sŽEI¢Xs¼ð¯%N;F\¶õ=®z­µ•/T×Ýߨ“)8V¸±úZîà^ÀÖ@@®?±žN,>ˆ ‹ö¹~˜ìã)ÔSõ´yJØ®A÷ö]¸ÀÎÓ};˜¸e J/©z9æ îtÔ|#b „<ÊN"åVº H÷Ø÷e± •ì£ö—xÚ¤›•…÷šTŸ p¼¶@SX2”­tÈ |'K‹i>¸³ïÒnº*÷ÑIN½wyV½zðnÏMØÍïi[ÛÔ 02•Á(éCË:ÛÓ åò²æ Vfâì.y´ÒÕíøSùö2ŽñnŠ|b|d!ckɧ{å=Qy% {>¾k3hRñ"+1ØáE é¾×‹iJÄ’˜[Þ2çYd=<¡M`}ÓÙçy¸Qøl:Ükö¦b•ÇÕÃ.0 OdÛÜ3²7!þž…¬çÇÌî±wB‚—€756Î T&Πwi~¥­>Å7ÇÐÈJèýæ…ö`J5.âf¨•=‹—”v•à!îCW"røÞY^qD&5Ó‚ÕÐøÅm8<¤Fã!›Š«öí!ôšôL‘w´« %_ðI ïLX­½•ó`z¾ëšØ1ï®T:nà6¹ÒU6ùPgO­G‡„4¶³;™&ÓS ½%fggF¡zÃÜ̯f­Om½"‚7ćºÑF n,ù<Þ~Ñ[ÇPÂq/H»µ14ËiÛ›Åež/áÐöI•DÖãzÝà+˜Q=RÕ—ñÞ*x§-eæŽQ³@@´WÔ¿×éÚ’ÒÔ©Ä…Fô¾ññ©ÉòˆŸEw ÜÖ6X:†À—ê±³?ÍÛ5=Ã\¬j1(é¶m½ ˆF«“Ú›±ÖJÝPï{èùЏFúâY–³.y2T£Il,9jšÈiÄɨ€•lνx·{e$lë JjМø¬.aQ»FçÉã,Ü$#âLU&Y »†•fÄ­ê¥×¡Øt¬×ámûklŽj¬mö5Ù~©­G;´RÆ8HL!Ö¢²ãù ¼°ú]òõ?ŽÓ»â ùò„¼^`º-QÀ&;§ ]yû¡ô‚èÊÊùm­,^IŒC8d‚vzB?81|Å=+ô6^–ÇA.þ ‹mÍSv±•{²TÕVO¤}ÇÎyÐkË­íöÝ,Lídyp<üĹG2Ò’ìÕLwE³9²Å†i™€«û´’9uƶe\9†ÚÃö~œwRäÂBå’xvm’ðb!†%¦ðà n¼µ˜6ÂR| ¡u4G0 g¢Nœ UÁñ˜6ÛPaZÑŸ¼4¯hFƾ{¬Ø Þæƒ%¾à( VˆdÉrÀ’UãÂϳOdë>ßV{úTep5µ|+‡ÊqHÍ  ™€*žò<™ÛE®g¾ïkšå‹ÞäméHØÙʈ}‘ekž¼¬Ç´è.*è½:† úà<Î[؃´#s: ³óBØmϬ~PoÖ‡rÖh_Úš/÷65DNx<¶VóG.˜“¬0 “/,yËf*ÕÑöá+V¯õµ‰ÉÓÐbeèØÛbÂS”Èfr¶¨Va«yÆŽ†Ç¹™ùö`ƶ»8kê-X– “ N×Áâ»Aâ‹—rá¼é^䯖7P‡»¸òßÍ()½‰9,ó5( y6é†s©ÝÂV’ x–hÔi¼Œ•Ax,¹F€h¬Î:Ð#|häÕc(gŽÁW o×N âIØa Ei$Ï]$¬N-±e#’)á Ê…=´”º}­bQMÍ|n³óho[0•?‚ŸÂµº«kZ‚€¶›_:‰â‘RŽÉ¦;®=æs¸qx#{–˜¼V×—‡:'D_‘ÌØhcnIÑÁ yÕÂÉ Uï…[æëT{«Ñ¯Œ¨]á^¼æ{è"VVñ°™ÔJÇn úXx·"Z²ÇŠ)Ñ8ã-”£ÃÜ0ÄS|Æw'Hi'þøÍ "à§5<¾ç¤²<ëÊͤ×pÓT.¾»´/úíè©ÀSM+ây +;L¾ 8ïV+&¤*âˆùZö¤‚Ɖs‰dÓ¤¼ã*6?™I}±4oÈø-ɱkÍ¡¼'¢¯Èšâ†¼üÄzg80ü~o A"¸æšF"–*#”ÝR[.Ñߤ_Î=j‹Òq T¦1A.º¬Tò×Ý«e VÙp®h:}1v8=Ï€ŒçeùâÆå•Í6\È»fÑŽµëI‡>HÖÞð<Ý(qO20ÆO„<þDˆÞL_ObÒ‹õ—%°ôJN`ëI»QË<q…t’ÜÞÕ§œIšlü"Þk./Ê€IT q‚ò0'l^+€{ýè å¦ ÆåÊ  š [ÉóI vŽ­”G]œÄÁ=¸í;¥Èj~"E®~Í2ã¸l[ø²îe¶‘ÌÉà4æDXï5“– ÷ndà =rµ[ç¼;²š%ï÷@[_³1‘ #¸›µQ¹ÕÖ[M$«kÐ|úŒ!"aDxÒÏÆÞ£dï:Â_ƒ3q«½Å”–ÔÕ ËP{"¶‡fê‘(p¸ËvN[?&;zm†Gœäâ–Ìé¯eh,:óÙª¶ßé_ñ5Ñ‚ØEµ˜«Ë­–éîdFÎÍ/SüØÔç1&¸FRÚ¨¿™ »B"y§$Û4bNΕš”1íºG~B Ì·N€a˜ý%Ú“¦W'òâzU¥ã^ã3v¦ò åq‘Å §Mâ³Q]Œ}VzõhCú2= Bµ”õŒbέخLا¨Ùôò´4ûJû'»Ôò­€½çÕ” ¯6àœx«âéŭܧ†bÙ F(Q±/c3&¸õŠVjBi®3‡û@kM–îQ">·òW­Š^º“¦0/Ç ·©øåãm\0¨^Øm›ÖÖÃØ—Zi—YöfБ½7œÛ2W':3€ÐýDݰ½oÜÌ/Ó&‡ø©s,Bã(l1 #œœ,›‚ºXÜN‹k|B„Þ÷! Õî„ ¸)cãŠH(L¢YgSÞLnä¸2xiIx¬"#W?Èâ|–ä1îtÈ{W)ajÜ>†zËŒ+ªˆPú…°·ûü´ÚWÀ\VÌÜw"±¥äñ:Á¼Edïx;†HKe%=ú,kÊ‹b†G=`a70‚.^‘pºŸ¼'ØÂºÊL<Ñ4ÆÂ|®‚VòÍ;¼B–âERë0")xÁÜ^FCÃæñŒ.™¯ÂÇ‚’v‘ˆit–ç“lî[ƒ¥$â¨ôæÝLY¨Jï0xä!uÜÃÓa¦ttP>´ÜŽÀKŸÖ¼Ê©%$?rÕ{ïTÕð‰ÔC0á¥qœ^“^?ô(!^-ŠLÁu²æ7sm¸Š†=ðn±¦®ÐLJÚ„wxÓŽäZ˜vÑ'ç‰"ú¦"'j£Hñs³Ä©—6‹"¹8®Y½M,p¼o·ÃÉÏCøÑžÒÓÁšP ˜ˆ®”õçu)ŒæûœÅŸ:’Ò1š}oöåòÕ,z–Vó! RÖ³FóD÷Rdµ}Ô¥ZˆÕL†\K`Ã_sPNÕµpER9‘?"ML¨‡‰BâG¤”‹~ªÚ&F#Ò|ƒŽýbµûf•6IrNÜ¥¯!iœóÕ[žyÌ¡S汪„½glá™XÕÃb¼ UÉÀcÊõÎ)sZµ½8¡'ä±6>qÃæCdt H™9ÀÇšÐÉÔ𫇓RLß$ã“DJ?ŽÝG;z™-¦MWиOT ÇÑ®Ÿ§¼“bг·üx–L[TºÓÍĞ餔5oÙ‚ Ú[zî` oñ®ŽÈ\È|,¦ŸêiJ­VÁrÆÛÞ­Üú¿ù÷ÿßÿüóï÷?lxd-2.0.0/dist/src/golang.org/x/crypto/sha3/doc.go0000644061062106075000000000616612702772344024237 0ustar00stgraberdomain admins00000000000000// Copyright 2014 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 sha3 implements the SHA-3 fixed-output-length hash functions and // the SHAKE variable-output-length hash functions defined by FIPS-202. // // Both types of hash function use the "sponge" construction and the Keccak // permutation. For a detailed specification see http://keccak.noekeon.org/ // // // Guidance // // If you aren't sure what function you need, use SHAKE256 with at least 64 // bytes of output. The SHAKE instances are faster than the SHA3 instances; // the latter have to allocate memory to conform to the hash.Hash interface. // // If you need a secret-key MAC (message authentication code), prepend the // secret key to the input, hash with SHAKE256 and read at least 32 bytes of // output. // // // Security strengths // // The SHA3-x (x equals 224, 256, 384, or 512) functions have a security // strength against preimage attacks of x bits. Since they only produce "x" // bits of output, their collision-resistance is only "x/2" bits. // // The SHAKE-256 and -128 functions have a generic security strength of 256 and // 128 bits against all attacks, provided that at least 2x bits of their output // is used. Requesting more than 64 or 32 bytes of output, respectively, does // not increase the collision-resistance of the SHAKE functions. // // // The sponge construction // // A sponge builds a pseudo-random function from a public pseudo-random // permutation, by applying the permutation to a state of "rate + capacity" // bytes, but hiding "capacity" of the bytes. // // A sponge starts out with a zero state. To hash an input using a sponge, up // to "rate" bytes of the input are XORed into the sponge's state. The sponge // is then "full" and the permutation is applied to "empty" it. This process is // repeated until all the input has been "absorbed". The input is then padded. // The digest is "squeezed" from the sponge in the same way, except that output // output is copied out instead of input being XORed in. // // A sponge is parameterized by its generic security strength, which is equal // to half its capacity; capacity + rate is equal to the permutation's width. // Since the KeccakF-1600 permutation is 1600 bits (200 bytes) wide, this means // that the security strength of a sponge instance is equal to (1600 - bitrate) / 2. // // // Recommendations // // The SHAKE functions are recommended for most new uses. They can produce // output of arbitrary length. SHAKE256, with an output length of at least // 64 bytes, provides 256-bit security against all attacks. The Keccak team // recommends it for most applications upgrading from SHA2-512. (NIST chose a // much stronger, but much slower, sponge instance for SHA3-512.) // // The SHA-3 functions are "drop-in" replacements for the SHA-2 functions. // They produce output of the same length, with the same security strengths // against all attacks. This means, in particular, that SHA3-256 only has // 128-bit collision resistance, because its output length is 32 bytes. package sha3 // import "golang.org/x/crypto/sha3" lxd-2.0.0/dist/src/golang.org/x/crypto/sha3/shake.go0000644061062106075000000000346712702772344024566 0ustar00stgraberdomain admins00000000000000// Copyright 2014 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 sha3 // This file defines the ShakeHash interface, and provides // functions for creating SHAKE instances, as well as utility // functions for hashing bytes to arbitrary-length output. import ( "io" ) // ShakeHash defines the interface to hash functions that // support arbitrary-length output. type ShakeHash interface { // Write absorbs more data into the hash's state. It panics if input is // written to it after output has been read from it. io.Writer // Read reads more output from the hash; reading affects the hash's // state. (ShakeHash.Read is thus very different from Hash.Sum) // It never returns an error. io.Reader // Clone returns a copy of the ShakeHash in its current state. Clone() ShakeHash // Reset resets the ShakeHash to its initial state. Reset() } func (d *state) Clone() ShakeHash { return d.clone() } // NewShake128 creates a new SHAKE128 variable-output-length ShakeHash. // Its generic security strength is 128 bits against all attacks if at // least 32 bytes of its output are used. func NewShake128() ShakeHash { return &state{rate: 168, dsbyte: 0x1f} } // NewShake256 creates a new SHAKE128 variable-output-length ShakeHash. // Its generic security strength is 256 bits against all attacks if // at least 64 bytes of its output are used. func NewShake256() ShakeHash { return &state{rate: 136, dsbyte: 0x1f} } // ShakeSum128 writes an arbitrary-length digest of data into hash. func ShakeSum128(hash, data []byte) { h := NewShake128() h.Write(data) h.Read(hash) } // ShakeSum256 writes an arbitrary-length digest of data into hash. func ShakeSum256(hash, data []byte) { h := NewShake256() h.Write(data) h.Read(hash) } lxd-2.0.0/dist/src/golang.org/x/crypto/sha3/xor.go0000644061062106075000000000063512702772344024275 0ustar00stgraberdomain admins00000000000000// Copyright 2015 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. // +build !amd64,!386,!ppc64,!ppc64le appengine package sha3 var ( xorIn = xorInGeneric copyOut = copyOutGeneric xorInUnaligned = xorInGeneric copyOutUnaligned = copyOutGeneric ) const xorImplementationUnaligned = "generic" lxd-2.0.0/dist/src/golang.org/x/crypto/sha3/xor_generic.go0000644061062106075000000000125012702772344025763 0ustar00stgraberdomain admins00000000000000// Copyright 2015 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 sha3 import "encoding/binary" // xorInGeneric xors the bytes in buf into the state; it // makes no non-portable assumptions about memory layout // or alignment. func xorInGeneric(d *state, buf []byte) { n := len(buf) / 8 for i := 0; i < n; i++ { a := binary.LittleEndian.Uint64(buf) d.a[i] ^= a buf = buf[8:] } } // copyOutGeneric copies ulint64s to a byte buffer. func copyOutGeneric(d *state, b []byte) { for i := 0; len(b) >= 8; i++ { binary.LittleEndian.PutUint64(b, d.a[i]) b = b[8:] } } lxd-2.0.0/dist/src/golang.org/x/crypto/codereview.cfg0000644061062106075000000000002512702772344025106 0ustar00stgraberdomain admins00000000000000issuerepo: golang/go lxd-2.0.0/dist/src/golang.org/x/crypto/pkcs12/0000755061062106075000000000000012702772344023377 5ustar00stgraberdomain admins00000000000000lxd-2.0.0/dist/src/golang.org/x/crypto/pkcs12/pbkdf_test.go0000644061062106075000000000247512702772344026063 0ustar00stgraberdomain admins00000000000000// Copyright 2015 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 pkcs12 import ( "bytes" "testing" ) func TestThatPBKDFWorksCorrectlyForLongKeys(t *testing.T) { cipherInfo := shaWithTripleDESCBC{} salt := []byte("\xff\xff\xff\xff\xff\xff\xff\xff") password, _ := bmpString("sesame") key := cipherInfo.deriveKey(salt, password, 2048) if expected := []byte("\x7c\xd9\xfd\x3e\x2b\x3b\xe7\x69\x1a\x44\xe3\xbe\xf0\xf9\xea\x0f\xb9\xb8\x97\xd4\xe3\x25\xd9\xd1"); bytes.Compare(key, expected) != 0 { t.Fatalf("expected key '%x', but found '%x'", expected, key) } } func TestThatPBKDFHandlesLeadingZeros(t *testing.T) { // This test triggers a case where I_j (in step 6C) ends up with leading zero // byte, meaning that len(Ijb) < v (leading zeros get stripped by big.Int). // This was previously causing bug whereby certain inputs would break the // derivation and produce the wrong output. key := pbkdf(sha1Sum, 20, 64, []byte("\xf3\x7e\x05\xb5\x18\x32\x4b\x4b"), []byte("\x00\x00"), 2048, 1, 24) expected := []byte("\x00\xf7\x59\xff\x47\xd1\x4d\xd0\x36\x65\xd5\x94\x3c\xb3\xc4\xa3\x9a\x25\x55\xc0\x2a\xed\x66\xe1") if bytes.Compare(key, expected) != 0 { t.Fatalf("expected key '%x', but found '%x'", expected, key) } } lxd-2.0.0/dist/src/golang.org/x/crypto/pkcs12/bmp-string.go0000644061062106075000000000272412702772344026015 0ustar00stgraberdomain admins00000000000000// Copyright 2015 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 pkcs12 import ( "errors" "unicode/utf16" ) // bmpString returns s encoded in UCS-2 with a zero terminator. func bmpString(s string) ([]byte, error) { // References: // https://tools.ietf.org/html/rfc7292#appendix-B.1 // http://en.wikipedia.org/wiki/Plane_(Unicode)#Basic_Multilingual_Plane // - non-BMP characters are encoded in UTF 16 by using a surrogate pair of 16-bit codes // EncodeRune returns 0xfffd if the rune does not need special encoding // - the above RFC provides the info that BMPStrings are NULL terminated. ret := make([]byte, 0, 2*len(s)+2) for _, r := range s { if t, _ := utf16.EncodeRune(r); t != 0xfffd { return nil, errors.New("pkcs12: string contains characters that cannot be encoded in UCS-2") } ret = append(ret, byte(r/256), byte(r%256)) } return append(ret, 0, 0), nil } func decodeBMPString(bmpString []byte) (string, error) { if len(bmpString)%2 != 0 { return "", errors.New("pkcs12: odd-length BMP string") } // strip terminator if present if l := len(bmpString); l >= 2 && bmpString[l-1] == 0 && bmpString[l-2] == 0 { bmpString = bmpString[:l-2] } s := make([]uint16, 0, len(bmpString)/2) for len(bmpString) > 0 { s = append(s, uint16(bmpString[0])<<8+uint16(bmpString[1])) bmpString = bmpString[2:] } return string(utf16.Decode(s)), nil } lxd-2.0.0/dist/src/golang.org/x/crypto/pkcs12/mac_test.go0000644061062106075000000000212212702772344025522 0ustar00stgraberdomain admins00000000000000// Copyright 2015 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 pkcs12 import ( "encoding/asn1" "testing" ) func TestVerifyMac(t *testing.T) { td := macData{ Mac: digestInfo{ Digest: []byte{0x18, 0x20, 0x3d, 0xff, 0x1e, 0x16, 0xf4, 0x92, 0xf2, 0xaf, 0xc8, 0x91, 0xa9, 0xba, 0xd6, 0xca, 0x9d, 0xee, 0x51, 0x93}, }, MacSalt: []byte{1, 2, 3, 4, 5, 6, 7, 8}, Iterations: 2048, } message := []byte{11, 12, 13, 14, 15} password, _ := bmpString("") td.Mac.Algorithm.Algorithm = asn1.ObjectIdentifier([]int{1, 2, 3}) err := verifyMac(&td, message, password) if _, ok := err.(NotImplementedError); !ok { t.Errorf("err: %v", err) } td.Mac.Algorithm.Algorithm = asn1.ObjectIdentifier([]int{1, 3, 14, 3, 2, 26}) err = verifyMac(&td, message, password) if err != ErrIncorrectPassword { t.Errorf("Expected incorrect password, got err: %v", err) } password, _ = bmpString("Sesame open") err = verifyMac(&td, message, password) if err != nil { t.Errorf("err: %v", err) } } lxd-2.0.0/dist/src/golang.org/x/crypto/pkcs12/safebags.go0000644061062106075000000000345512702772344025510 0ustar00stgraberdomain admins00000000000000// Copyright 2015 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 pkcs12 import ( "crypto/x509" "encoding/asn1" "errors" ) var ( // see https://tools.ietf.org/html/rfc7292#appendix-D oidCertTypeX509Certificate = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 9, 22, 1}) oidPKCS8ShroundedKeyBag = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 12, 10, 1, 2}) oidCertBag = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 12, 10, 1, 3}) ) type certBag struct { Id asn1.ObjectIdentifier Data []byte `asn1:"tag:0,explicit"` } func decodePkcs8ShroudedKeyBag(asn1Data, password []byte) (privateKey interface{}, err error) { pkinfo := new(encryptedPrivateKeyInfo) if err = unmarshal(asn1Data, pkinfo); err != nil { return nil, errors.New("pkcs12: error decoding PKCS#8 shrouded key bag: " + err.Error()) } pkData, err := pbDecrypt(pkinfo, password) if err != nil { return nil, errors.New("pkcs12: error decrypting PKCS#8 shrouded key bag: " + err.Error()) } ret := new(asn1.RawValue) if err = unmarshal(pkData, ret); err != nil { return nil, errors.New("pkcs12: error unmarshaling decrypted private key: " + err.Error()) } if privateKey, err = x509.ParsePKCS8PrivateKey(pkData); err != nil { return nil, errors.New("pkcs12: error parsing PKCS#8 private key: " + err.Error()) } return privateKey, nil } func decodeCertBag(asn1Data []byte) (x509Certificates []byte, err error) { bag := new(certBag) if err := unmarshal(asn1Data, bag); err != nil { return nil, errors.New("pkcs12: error decoding cert bag: " + err.Error()) } if !bag.Id.Equal(oidCertTypeX509Certificate) { return nil, NotImplementedError("only X509 certificates are supported") } return bag.Data, nil } lxd-2.0.0/dist/src/golang.org/x/crypto/pkcs12/bmp-string_test.go0000644061062106075000000000317312702772344027053 0ustar00stgraberdomain admins00000000000000// Copyright 2015 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 pkcs12 import ( "bytes" "encoding/hex" "testing" ) var bmpStringTests = []struct { in string expectedHex string shouldFail bool }{ {"", "0000", false}, // Example from https://tools.ietf.org/html/rfc7292#appendix-B. {"Beavis", "0042006500610076006900730000", false}, // Some characters from the "Letterlike Symbols Unicode block". {"\u2115 - Double-struck N", "21150020002d00200044006f00750062006c0065002d00730074007200750063006b0020004e0000", false}, // any character outside the BMP should trigger an error. {"\U0001f000 East wind (Mahjong)", "", true}, } func TestBMPString(t *testing.T) { for i, test := range bmpStringTests { expected, err := hex.DecodeString(test.expectedHex) if err != nil { t.Fatalf("#%d: failed to decode expectation", i) } out, err := bmpString(test.in) if err == nil && test.shouldFail { t.Errorf("#%d: expected to fail, but produced %x", i, out) continue } if err != nil && !test.shouldFail { t.Errorf("#%d: failed unexpectedly: %s", i, err) continue } if !test.shouldFail { if !bytes.Equal(out, expected) { t.Errorf("#%d: expected %s, got %x", i, test.expectedHex, out) continue } roundTrip, err := decodeBMPString(out) if err != nil { t.Errorf("#%d: decoding output gave an error: %s", i, err) continue } if roundTrip != test.in { t.Errorf("#%d: decoding output resulted in %q, but it should have been %q", i, roundTrip, test.in) continue } } } } lxd-2.0.0/dist/src/golang.org/x/crypto/pkcs12/errors.go0000644061062106075000000000135712702772344025250 0ustar00stgraberdomain admins00000000000000// Copyright 2015 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 pkcs12 import "errors" var ( // ErrDecryption represents a failure to decrypt the input. ErrDecryption = errors.New("pkcs12: decryption error, incorrect padding") // ErrIncorrectPassword is returned when an incorrect password is detected. // Usually, P12/PFX data is signed to be able to verify the password. ErrIncorrectPassword = errors.New("pkcs12: decryption password incorrect") ) // NotImplementedError indicates that the input is not currently supported. type NotImplementedError string func (e NotImplementedError) Error() string { return "pkcs12: " + string(e) } lxd-2.0.0/dist/src/golang.org/x/crypto/pkcs12/crypto_test.go0000644061062106075000000000623112702772344026307 0ustar00stgraberdomain admins00000000000000// Copyright 2015 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 pkcs12 import ( "bytes" "crypto/x509/pkix" "encoding/asn1" "testing" ) var sha1WithTripleDES = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 12, 1, 3}) func TestPbDecrypterFor(t *testing.T) { params, _ := asn1.Marshal(pbeParams{ Salt: []byte{1, 2, 3, 4, 5, 6, 7, 8}, Iterations: 2048, }) alg := pkix.AlgorithmIdentifier{ Algorithm: asn1.ObjectIdentifier([]int{1, 2, 3}), Parameters: asn1.RawValue{ FullBytes: params, }, } pass, _ := bmpString("Sesame open") _, _, err := pbDecrypterFor(alg, pass) if _, ok := err.(NotImplementedError); !ok { t.Errorf("expected not implemented error, got: %T %s", err, err) } alg.Algorithm = sha1WithTripleDES cbc, blockSize, err := pbDecrypterFor(alg, pass) if err != nil { t.Errorf("unexpected error from pbDecrypterFor %v", err) } if blockSize != 8 { t.Errorf("unexpected block size %d, wanted 8", blockSize) } plaintext := []byte{1, 2, 3, 4, 5, 6, 7, 8} expectedCiphertext := []byte{185, 73, 135, 249, 137, 1, 122, 247} ciphertext := make([]byte, len(plaintext)) cbc.CryptBlocks(ciphertext, plaintext) if bytes.Compare(ciphertext, expectedCiphertext) != 0 { t.Errorf("bad ciphertext, got %x but wanted %x", ciphertext, expectedCiphertext) } } var pbDecryptTests = []struct { in []byte expected []byte expectedError error }{ { []byte("\x33\x73\xf3\x9f\xda\x49\xae\xfc\xa0\x9a\xdf\x5a\x58\xa0\xea\x46"), // 7 padding bytes []byte("A secret!"), nil, }, { []byte("\x33\x73\xf3\x9f\xda\x49\xae\xfc\x96\x24\x2f\x71\x7e\x32\x3f\xe7"), // 8 padding bytes []byte("A secret"), nil, }, { []byte("\x35\x0c\xc0\x8d\xab\xa9\x5d\x30\x7f\x9a\xec\x6a\xd8\x9b\x9c\xd9"), // 9 padding bytes, incorrect nil, ErrDecryption, }, { []byte("\xb2\xf9\x6e\x06\x60\xae\x20\xcf\x08\xa0\x7b\xd9\x6b\x20\xef\x41"), // incorrect padding bytes: [ ... 0x04 0x02 ] nil, ErrDecryption, }, } func TestPbDecrypt(t *testing.T) { for i, test := range pbDecryptTests { decryptable := testDecryptable{ data: test.in, algorithm: pkix.AlgorithmIdentifier{ Algorithm: sha1WithTripleDES, Parameters: pbeParams{ Salt: []byte("\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8"), Iterations: 4096, }.RawASN1(), }, } password, _ := bmpString("sesame") plaintext, err := pbDecrypt(decryptable, password) if err != test.expectedError { t.Errorf("#%d: got error %q, but wanted %q", i, err, test.expectedError) continue } if !bytes.Equal(plaintext, test.expected) { t.Errorf("#%d: got %x, but wanted %x", i, plaintext, test.expected) } } } type testDecryptable struct { data []byte algorithm pkix.AlgorithmIdentifier } func (d testDecryptable) Algorithm() pkix.AlgorithmIdentifier { return d.algorithm } func (d testDecryptable) Data() []byte { return d.data } func (params pbeParams) RawASN1() (raw asn1.RawValue) { asn1Bytes, err := asn1.Marshal(params) if err != nil { panic(err) } _, err = asn1.Unmarshal(asn1Bytes, &raw) if err != nil { panic(err) } return } lxd-2.0.0/dist/src/golang.org/x/crypto/pkcs12/pkcs12.go0000644061062106075000000002220112702772344025026 0ustar00stgraberdomain admins00000000000000// Copyright 2015 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 pkcs12 implements some of PKCS#12. // // This implementation is distilled from https://tools.ietf.org/html/rfc7292 // and referenced documents. It is intended for decoding P12/PFX-stored // certificates and keys for use with the crypto/tls package. package pkcs12 import ( "crypto/ecdsa" "crypto/rsa" "crypto/x509" "crypto/x509/pkix" "encoding/asn1" "encoding/hex" "encoding/pem" "errors" ) var ( oidDataContentType = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 7, 1}) oidEncryptedDataContentType = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 7, 6}) oidFriendlyName = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 9, 20}) oidLocalKeyID = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 9, 21}) oidMicrosoftCSPName = asn1.ObjectIdentifier([]int{1, 3, 6, 1, 4, 1, 311, 17, 1}) ) type pfxPdu struct { Version int AuthSafe contentInfo MacData macData `asn1:"optional"` } type contentInfo struct { ContentType asn1.ObjectIdentifier Content asn1.RawValue `asn1:"tag:0,explicit,optional"` } type encryptedData struct { Version int EncryptedContentInfo encryptedContentInfo } type encryptedContentInfo struct { ContentType asn1.ObjectIdentifier ContentEncryptionAlgorithm pkix.AlgorithmIdentifier EncryptedContent []byte `asn1:"tag:0,optional"` } func (i encryptedContentInfo) Algorithm() pkix.AlgorithmIdentifier { return i.ContentEncryptionAlgorithm } func (i encryptedContentInfo) Data() []byte { return i.EncryptedContent } type safeBag struct { Id asn1.ObjectIdentifier Value asn1.RawValue `asn1:"tag:0,explicit"` Attributes []pkcs12Attribute `asn1:"set,optional"` } type pkcs12Attribute struct { Id asn1.ObjectIdentifier Value asn1.RawValue `asn1:"set"` } type encryptedPrivateKeyInfo struct { AlgorithmIdentifier pkix.AlgorithmIdentifier EncryptedData []byte } func (i encryptedPrivateKeyInfo) Algorithm() pkix.AlgorithmIdentifier { return i.AlgorithmIdentifier } func (i encryptedPrivateKeyInfo) Data() []byte { return i.EncryptedData } // PEM block types const ( certificateType = "CERTIFICATE" privateKeyType = "PRIVATE KEY" ) // unmarshal calls asn1.Unmarshal, but also returns an error if there is any // trailing data after unmarshaling. func unmarshal(in []byte, out interface{}) error { trailing, err := asn1.Unmarshal(in, out) if err != nil { return err } if len(trailing) != 0 { return errors.New("pkcs12: trailing data found") } return nil } // ConvertToPEM converts all "safe bags" contained in pfxData to PEM blocks. func ToPEM(pfxData []byte, password string) ([]*pem.Block, error) { encodedPassword, err := bmpString(password) if err != nil { return nil, ErrIncorrectPassword } bags, encodedPassword, err := getSafeContents(pfxData, encodedPassword) blocks := make([]*pem.Block, 0, len(bags)) for _, bag := range bags { block, err := convertBag(&bag, encodedPassword) if err != nil { return nil, err } blocks = append(blocks, block) } return blocks, nil } func convertBag(bag *safeBag, password []byte) (*pem.Block, error) { block := &pem.Block{ Headers: make(map[string]string), } for _, attribute := range bag.Attributes { k, v, err := convertAttribute(&attribute) if err != nil { return nil, err } block.Headers[k] = v } switch { case bag.Id.Equal(oidCertBag): block.Type = certificateType certsData, err := decodeCertBag(bag.Value.Bytes) if err != nil { return nil, err } block.Bytes = certsData case bag.Id.Equal(oidPKCS8ShroundedKeyBag): block.Type = privateKeyType key, err := decodePkcs8ShroudedKeyBag(bag.Value.Bytes, password) if err != nil { return nil, err } switch key := key.(type) { case *rsa.PrivateKey: block.Bytes = x509.MarshalPKCS1PrivateKey(key) case *ecdsa.PrivateKey: block.Bytes, err = x509.MarshalECPrivateKey(key) if err != nil { return nil, err } default: return nil, errors.New("found unknown private key type in PKCS#8 wrapping") } default: return nil, errors.New("don't know how to convert a safe bag of type " + bag.Id.String()) } return block, nil } func convertAttribute(attribute *pkcs12Attribute) (key, value string, err error) { isString := false switch { case attribute.Id.Equal(oidFriendlyName): key = "friendlyName" isString = true case attribute.Id.Equal(oidLocalKeyID): key = "localKeyId" case attribute.Id.Equal(oidMicrosoftCSPName): // This key is chosen to match OpenSSL. key = "Microsoft CSP Name" isString = true default: return "", "", errors.New("pkcs12: unknown attribute with OID " + attribute.Id.String()) } if isString { if err := unmarshal(attribute.Value.Bytes, &attribute.Value); err != nil { return "", "", err } if value, err = decodeBMPString(attribute.Value.Bytes); err != nil { return "", "", err } } else { var id []byte if err := unmarshal(attribute.Value.Bytes, &id); err != nil { return "", "", err } value = hex.EncodeToString(id) } return key, value, nil } // Decode extracts a certificate and private key from pfxData. This function // assumes that there is only one certificate and only one private key in the // pfxData. func Decode(pfxData []byte, password string) (privateKey interface{}, certificate *x509.Certificate, err error) { encodedPassword, err := bmpString(password) if err != nil { return nil, nil, err } bags, encodedPassword, err := getSafeContents(pfxData, encodedPassword) if err != nil { return nil, nil, err } if len(bags) != 2 { err = errors.New("pkcs12: expected exactly two safe bags in the PFX PDU") return } for _, bag := range bags { switch { case bag.Id.Equal(oidCertBag): if certificate != nil { err = errors.New("pkcs12: expected exactly one certificate bag") } certsData, err := decodeCertBag(bag.Value.Bytes) if err != nil { return nil, nil, err } certs, err := x509.ParseCertificates(certsData) if err != nil { return nil, nil, err } if len(certs) != 1 { err = errors.New("pkcs12: expected exactly one certificate in the certBag") return nil, nil, err } certificate = certs[0] case bag.Id.Equal(oidPKCS8ShroundedKeyBag): if privateKey != nil { err = errors.New("pkcs12: expected exactly one key bag") } if privateKey, err = decodePkcs8ShroudedKeyBag(bag.Value.Bytes, encodedPassword); err != nil { return nil, nil, err } } } if certificate == nil { return nil, nil, errors.New("pkcs12: certificate missing") } if privateKey == nil { return nil, nil, errors.New("pkcs12: private key missing") } return } func getSafeContents(p12Data, password []byte) (bags []safeBag, updatedPassword []byte, err error) { pfx := new(pfxPdu) if err := unmarshal(p12Data, pfx); err != nil { return nil, nil, errors.New("pkcs12: error reading P12 data: " + err.Error()) } if pfx.Version != 3 { return nil, nil, NotImplementedError("can only decode v3 PFX PDU's") } if !pfx.AuthSafe.ContentType.Equal(oidDataContentType) { return nil, nil, NotImplementedError("only password-protected PFX is implemented") } // unmarshal the explicit bytes in the content for type 'data' if err := unmarshal(pfx.AuthSafe.Content.Bytes, &pfx.AuthSafe.Content); err != nil { return nil, nil, err } if len(pfx.MacData.Mac.Algorithm.Algorithm) == 0 { return nil, nil, errors.New("pkcs12: no MAC in data") } if err := verifyMac(&pfx.MacData, pfx.AuthSafe.Content.Bytes, password); err != nil { if err == ErrIncorrectPassword && len(password) == 2 && password[0] == 0 && password[1] == 0 { // some implementations use an empty byte array // for the empty string password try one more // time with empty-empty password password = nil err = verifyMac(&pfx.MacData, pfx.AuthSafe.Content.Bytes, password) } if err != nil { return nil, nil, err } } var authenticatedSafe []contentInfo if err := unmarshal(pfx.AuthSafe.Content.Bytes, &authenticatedSafe); err != nil { return nil, nil, err } if len(authenticatedSafe) != 2 { return nil, nil, NotImplementedError("expected exactly two items in the authenticated safe") } for _, ci := range authenticatedSafe { var data []byte switch { case ci.ContentType.Equal(oidDataContentType): if err := unmarshal(ci.Content.Bytes, &data); err != nil { return nil, nil, err } case ci.ContentType.Equal(oidEncryptedDataContentType): var encryptedData encryptedData if err := unmarshal(ci.Content.Bytes, &encryptedData); err != nil { return nil, nil, err } if encryptedData.Version != 0 { return nil, nil, NotImplementedError("only version 0 of EncryptedData is supported") } if data, err = pbDecrypt(encryptedData.EncryptedContentInfo, password); err != nil { return nil, nil, err } default: return nil, nil, NotImplementedError("only data and encryptedData content types are supported in authenticated safe") } var safeContents []safeBag if err := unmarshal(data, &safeContents); err != nil { return nil, nil, err } bags = append(bags, safeContents...) } return bags, password, nil } lxd-2.0.0/dist/src/golang.org/x/crypto/pkcs12/pkcs12_test.go0000644061062106075000000002142312702772344026072 0ustar00stgraberdomain admins00000000000000// Copyright 2015 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 pkcs12 import ( "crypto/rsa" "crypto/tls" "encoding/base64" "encoding/pem" "testing" ) func TestPfx(t *testing.T) { for commonName, base64P12 := range testdata { p12, _ := base64.StdEncoding.DecodeString(base64P12) priv, cert, err := Decode(p12, "") if err != nil { t.Fatal(err) } if err := priv.(*rsa.PrivateKey).Validate(); err != nil { t.Errorf("error while validating private key: %v", err) } if cert.Subject.CommonName != commonName { t.Errorf("expected common name to be %q, but found %q", commonName, cert.Subject.CommonName) } } } func TestPEM(t *testing.T) { for commonName, base64P12 := range testdata { p12, _ := base64.StdEncoding.DecodeString(base64P12) blocks, err := ToPEM(p12, "") if err != nil { t.Fatalf("error while converting to PEM: %s", err) } var pemData []byte for _, b := range blocks { pemData = append(pemData, pem.EncodeToMemory(b)...) } cert, err := tls.X509KeyPair(pemData, pemData) if err != nil { t.Errorf("err while converting to key pair: %v", err) } config := tls.Config{ Certificates: []tls.Certificate{cert}, } config.BuildNameToCertificate() if _, exists := config.NameToCertificate[commonName]; !exists { t.Errorf("did not find our cert in PEM?: %v", config.NameToCertificate) } } } func ExampleToPEM() { p12, _ := base64.StdEncoding.DecodeString(`MIIJzgIBAzCCCZQGCS ... CA+gwggPk==`) blocks, err := ToPEM(p12, "password") if err != nil { panic(err) } var pemData []byte for _, b := range blocks { pemData = append(pemData, pem.EncodeToMemory(b)...) } // then use PEM data for tls to construct tls certificate: cert, err := tls.X509KeyPair(pemData, pemData) if err != nil { panic(err) } config := &tls.Config{ Certificates: []tls.Certificate{cert}, } _ = config } var testdata = map[string]string{ // 'null' password test case "Windows Azure Tools": `MIIKDAIBAzCCCcwGCSqGSIb3DQEHAaCCCb0Eggm5MIIJtTCCBe4GCSqGSIb3DQEHAaCCBd8EggXbMIIF1zCCBdMGCyqGSIb3DQEMCgECoIIE7jCCBOowHAYKKoZIhvcNAQwBAzAOBAhStUNnlTGV+gICB9AEggTIJ81JIossF6boFWpPtkiQRPtI6DW6e9QD4/WvHAVrM2bKdpMzSMsCML5NyuddANTKHBVq00Jc9keqGNAqJPKkjhSUebzQFyhe0E1oI9T4zY5UKr/I8JclOeccH4QQnsySzYUG2SnniXnQ+JrG3juetli7EKth9h6jLc6xbubPadY5HMB3wL/eG/kJymiXwU2KQ9Mgd4X6jbcV+NNCE/8jbZHvSTCPeYTJIjxfeX61Sj5kFKUCzERbsnpyevhY3X0eYtEDezZQarvGmXtMMdzf8HJHkWRdk9VLDLgjk8uiJif/+X4FohZ37ig0CpgC2+dP4DGugaZZ51hb8tN9GeCKIsrmWogMXDIVd0OACBp/EjJVmFB6y0kUCXxUE0TZt0XA1tjAGJcjDUpBvTntZjPsnH/4ZySy+s2d9OOhJ6pzRQBRm360TzkFdSwk9DLiLdGfv4pwMMu/vNGBlqjP/1sQtj+jprJiD1sDbCl4AdQZVoMBQHadF2uSD4/o17XG/Ci0r2h6Htc2yvZMAbEY4zMjjIn2a+vqIxD6onexaek1R3zbkS9j19D6EN9EWn8xgz80YRCyW65znZk8xaIhhvlU/mg7sTxeyuqroBZNcq6uDaQTehDpyH7bY2l4zWRpoj10a6JfH2q5shYz8Y6UZC/kOTfuGqbZDNZWro/9pYquvNNW0M847E5t9bsf9VkAAMHRGBbWoVoU9VpI0UnoXSfvpOo+aXa2DSq5sHHUTVY7A9eov3z5IqT+pligx11xcs+YhDWcU8di3BTJisohKvv5Y8WSkm/rloiZd4ig269k0jTRk1olP/vCksPli4wKG2wdsd5o42nX1yL7mFfXocOANZbB+5qMkiwdyoQSk+Vq+C8nAZx2bbKhUq2MbrORGMzOe0Hh0x2a0PeObycN1Bpyv7Mp3ZI9h5hBnONKCnqMhtyQHUj/nNvbJUnDVYNfoOEqDiEqqEwB7YqWzAKz8KW0OIqdlM8uiQ4JqZZlFllnWJUfaiDrdFM3lYSnFQBkzeVlts6GpDOOBjCYd7dcCNS6kq6pZC6p6HN60Twu0JnurZD6RT7rrPkIGE8vAenFt4iGe/yF52fahCSY8Ws4K0UTwN7bAS+4xRHVCWvE8sMRZsRCHizb5laYsVrPZJhE6+hux6OBb6w8kwPYXc+ud5v6UxawUWgt6uPwl8mlAtU9Z7Miw4Nn/wtBkiLL/ke1UI1gqJtcQXgHxx6mzsjh41+nAgTvdbsSEyU6vfOmxGj3Rwc1eOrIhJUqn5YjOWfzzsz/D5DzWKmwXIwdspt1p+u+kol1N3f2wT9fKPnd/RGCb4g/1hc3Aju4DQYgGY782l89CEEdalpQ/35bQczMFk6Fje12HykakWEXd/bGm9Unh82gH84USiRpeOfQvBDYoqEyrY3zkFZzBjhDqa+jEcAj41tcGx47oSfDq3iVYCdL7HSIjtnyEktVXd7mISZLoMt20JACFcMw+mrbjlug+eU7o2GR7T+LwtOp/p4LZqyLa7oQJDwde1BNZtm3TCK2P1mW94QDL0nDUps5KLtr1DaZXEkRbjSJub2ZE9WqDHyU3KA8G84Tq/rN1IoNu/if45jacyPje1Npj9IftUZSP22nV7HMwZtwQ4P4MYHRMBMGCSqGSIb3DQEJFTEGBAQBAAAAMFsGCSqGSIb3DQEJFDFOHkwAewBCADQAQQA0AEYARQBCADAALQBBADEAOABBAC0ANAA0AEIAQgAtAEIANQBGADIALQA0ADkAMQBFAEYAMQA1ADIAQgBBADEANgB9MF0GCSsGAQQBgjcRATFQHk4ATQBpAGMAcgBvAHMAbwBmAHQAIABTAG8AZgB0AHcAYQByAGUAIABLAGUAeQAgAFMAdABvAHIAYQBnAGUAIABQAHIAbwB2AGkAZABlAHIwggO/BgkqhkiG9w0BBwagggOwMIIDrAIBADCCA6UGCSqGSIb3DQEHATAcBgoqhkiG9w0BDAEGMA4ECEBk5ZAYpu0WAgIH0ICCA3hik4mQFGpw9Ha8TQPtk+j2jwWdxfF0+sTk6S8PTsEfIhB7wPltjiCK92Uv2tCBQnodBUmatIfkpnRDEySmgmdglmOCzj204lWAMRs94PoALGn3JVBXbO1vIDCbAPOZ7Z0Hd0/1t2hmk8v3//QJGUg+qr59/4y/MuVfIg4qfkPcC2QSvYWcK3oTf6SFi5rv9B1IOWFgN5D0+C+x/9Lb/myPYX+rbOHrwtJ4W1fWKoz9g7wwmGFA9IJ2DYGuH8ifVFbDFT1Vcgsvs8arSX7oBsJVW0qrP7XkuDRe3EqCmKW7rBEwYrFznhxZcRDEpMwbFoSvgSIZ4XhFY9VKYglT+JpNH5iDceYEBOQL4vBLpxNUk3l5jKaBNxVa14AIBxq18bVHJ+STInhLhad4u10v/Xbx7wIL3f9DX1yLAkPrpBYbNHS2/ew6H/ySDJnoIDxkw2zZ4qJ+qUJZ1S0lbZVG+VT0OP5uF6tyOSpbMlcGkdl3z254n6MlCrTifcwkzscysDsgKXaYQw06rzrPW6RDub+t+hXzGny799fS9jhQMLDmOggaQ7+LA4oEZsfT89HLMWxJYDqjo3gIfjciV2mV54R684qLDS+AO09U49e6yEbwGlq8lpmO/pbXCbpGbB1b3EomcQbxdWxW2WEkkEd/VBn81K4M3obmywwXJkw+tPXDXfBmzzaqqCR+onMQ5ME1nMkY8ybnfoCc1bDIupjVWsEL2Wvq752RgI6KqzVNr1ew1IdqV5AWN2fOfek+0vi3Jd9FHF3hx8JMwjJL9dZsETV5kHtYJtE7wJ23J68BnCt2eI0GEuwXcCf5EdSKN/xXCTlIokc4Qk/gzRdIZsvcEJ6B1lGovKG54X4IohikqTjiepjbsMWj38yxDmK3mtENZ9ci8FPfbbvIEcOCZIinuY3qFUlRSbx7VUerEoV1IP3clUwexVQo4lHFee2jd7ocWsdSqSapW7OWUupBtDzRkqVhE7tGria+i1W2d6YLlJ21QTjyapWJehAMO637OdbJCCzDs1cXbodRRE7bsP492ocJy8OX66rKdhYbg8srSFNKdb3pF3UDNbN9jhI/t8iagRhNBhlQtTr1me2E/c86Q18qcRXl4bcXTt6acgCeffK6Y26LcVlrgjlD33AEYRRUeyC+rpxbT0aMjdFderlndKRIyG23mSp0HaUwNzAfMAcGBSsOAwIaBBRlviCbIyRrhIysg2dc/KbLFTc2vQQUg4rfwHMM4IKYRD/fsd1x6dda+wQ=`, // empty string password test case "testing@example.com": `MIIJzgIBAzCCCZQGCSqGSIb3DQEHAaCCCYUEggmBMIIJfTCCA/cGCSqGSIb3DQEHBqCCA+gwggPk AgEAMIID3QYJKoZIhvcNAQcBMBwGCiqGSIb3DQEMAQYwDgQIIszfRGqcmPcCAggAgIIDsOZ9Eg1L s5Wx8JhYoV3HAL4aRnkAWvTYB5NISZOgSgIQTssmt/3A7134dibTmaT/93LikkL3cTKLnQzJ4wDf YZ1bprpVJvUqz+HFT79m27bP9zYXFrvxWBJbxjYKTSjQMgz+h8LAEpXXGajCmxMJ1oCOtdXkhhzc LdZN6SAYgtmtyFnCdMEDskSggGuLb3fw84QEJ/Sj6FAULXunW/CPaS7Ce0TMsKmNU/jfFWj3yXXw ro0kwjKiVLpVFlnBlHo2OoVU7hmkm59YpGhLgS7nxLD3n7nBroQ0ID1+8R01NnV9XLGoGzxMm1te 6UyTCkr5mj+kEQ8EP1Ys7g/TC411uhVWySMt/rcpkx7Vz1r9kYEAzJpONAfr6cuEVkPKrxpq4Fh0 2fzlKBky0i/hrfIEUmngh+ERHUb/Mtv/fkv1j5w9suESbhsMLLiCXAlsP1UWMX+3bNizi3WVMEts FM2k9byn+p8IUD/A8ULlE4kEaWeoc+2idkCNQkLGuIdGUXUFVm58se0auUkVRoRJx8x4CkMesT8j b1H831W66YRWoEwwDQp2kK1lA2vQXxdVHWlFevMNxJeromLzj3ayiaFrfByeUXhR2S+Hpm+c0yNR 4UVU9WED2kacsZcpRm9nlEa5sr28mri5JdBrNa/K02OOhvKCxr5ZGmbOVzUQKla2z4w+Ku9k8POm dfDNU/fGx1b5hcFWtghXe3msWVsSJrQihnN6q1ughzNiYZlJUGcHdZDRtiWwCFI0bR8h/Dmg9uO9 4rawQQrjIRT7B8yF3UbkZyAqs8Ppb1TsMeNPHh1rxEfGVQknh/48ouJYsmtbnzugTUt3mJCXXiL+ XcPMV6bBVAUu4aaVKSmg9+yJtY4/VKv10iw88ktv29fViIdBe3t6l/oPuvQgbQ8dqf4T8w0l/uKZ 9lS1Na9jfT1vCoS7F5TRi+tmyj1vL5kr/amEIW6xKEP6oeAMvCMtbPAzVEj38zdJ1R22FfuIBxkh f0Zl7pdVbmzRxl/SBx9iIBJSqAvcXItiT0FIj8HxQ+0iZKqMQMiBuNWJf5pYOLWGrIyntCWwHuaQ wrx0sTGuEL9YXLEAsBDrsvzLkx/56E4INGZFrH8G7HBdW6iGqb22IMI4GHltYSyBRKbB0gadYTyv abPEoqww8o7/85aPSzOTJ/53ozD438Q+d0u9SyDuOb60SzCD/zPuCEd78YgtXJwBYTuUNRT27FaM 3LGMX8Hz+6yPNRnmnA2XKPn7dx/IlaqAjIs8MIIFfgYJKoZIhvcNAQcBoIIFbwSCBWswggVnMIIF YwYLKoZIhvcNAQwKAQKgggTuMIIE6jAcBgoqhkiG9w0BDAEDMA4ECJr0cClYqOlcAgIIAASCBMhe OQSiP2s0/46ONXcNeVAkz2ksW3u/+qorhSiskGZ0b3dFa1hhgBU2Q7JVIkc4Hf7OXaT1eVQ8oqND uhqsNz83/kqYo70+LS8Hocj49jFgWAKrf/yQkdyP1daHa2yzlEw4mkpqOfnIORQHvYCa8nEApspZ wVu8y6WVuLHKU67mel7db2xwstQp7PRuSAYqGjTfAylElog8ASdaqqYbYIrCXucF8iF9oVgmb/Qo xrXshJ9aSLO4MuXlTPELmWgj07AXKSb90FKNihE+y0bWb9LPVFY1Sly3AX9PfrtkSXIZwqW3phpv MxGxQl/R6mr1z+hlTfY9Wdpb5vlKXPKA0L0Rt8d2pOesylFi6esJoS01QgP1kJILjbrV731kvDc0 Jsd+Oxv4BMwA7ClG8w1EAOInc/GrV1MWFGw/HeEqj3CZ/l/0jv9bwkbVeVCiIhoL6P6lVx9pXq4t KZ0uKg/tk5TVJmG2vLcMLvezD0Yk3G2ZOMrywtmskrwoF7oAUpO9e87szoH6fEvUZlkDkPVW1NV4 cZk3DBSQiuA3VOOg8qbo/tx/EE3H59P0axZWno2GSB0wFPWd1aj+b//tJEJHaaNR6qPRj4IWj9ru Qbc8eRAcVWleHg8uAehSvUXlFpyMQREyrnpvMGddpiTC8N4UMrrBRhV7+UbCOWhxPCbItnInBqgl 1JpSZIP7iUtsIMdu3fEC2cdbXMTRul+4rdzUR7F9OaezV3jjvcAbDvgbK1CpyC+MJ1Mxm/iTgk9V iUArydhlR8OniN84GyGYoYCW9O/KUwb6ASmeFOu/msx8x6kAsSQHIkKqMKv0TUR3kZnkxUvdpBGP KTl4YCTvNGX4dYALBqrAETRDhua2KVBD/kEttDHwBNVbN2xi81+Mc7ml461aADfk0c66R/m2sjHB 2tN9+wG12OIWFQjL6wF/UfJMYamxx2zOOExiId29Opt57uYiNVLOO4ourPewHPeH0u8Gz35aero7 lkt7cZAe1Q0038JUuE/QGlnK4lESK9UkSIQAjSaAlTsrcfwtQxB2EjoOoLhwH5mvxUEmcNGNnXUc 9xj3M5BD3zBz3Ft7G3YMMDwB1+zC2l+0UG0MGVjMVaeoy32VVNvxgX7jk22OXG1iaOB+PY9kdk+O X+52BGSf/rD6X0EnqY7XuRPkMGgjtpZeAYxRQnFtCZgDY4wYheuxqSSpdF49yNczSPLkgB3CeCfS +9NTKN7aC6hBbmW/8yYh6OvSiCEwY0lFS/T+7iaVxr1loE4zI1y/FFp4Pe1qfLlLttVlkygga2UU SCunTQ8UB/M5IXWKkhMOO11dP4niWwb39Y7pCWpau7mwbXOKfRPX96cgHnQJK5uG+BesDD1oYnX0 6frN7FOnTSHKruRIwuI8KnOQ/I+owmyz71wiv5LMQt+yM47UrEjB/EZa5X8dpEwOZvkdqL7utcyo l0XH5kWMXdW856LL/FYftAqJIDAmtX1TXF/rbP6mPyN/IlDC0gjP84Uzd/a2UyTIWr+wk49Ek3vQ /uDamq6QrwAxVmNh5Tset5Vhpc1e1kb7mRMZIzxSP8JcTuYd45oFKi98I8YjvueHVZce1g7OudQP SbFQoJvdT46iBg1TTatlltpOiH2mFaxWVS0xYjAjBgkqhkiG9w0BCRUxFgQUdA9eVqvETX4an/c8 p8SsTugkit8wOwYJKoZIhvcNAQkUMS4eLABGAHIAaQBlAG4AZABsAHkAIABuAGEAbQBlACAAZgBv AHIAIABjAGUAcgB0MDEwITAJBgUrDgMCGgUABBRFsNz3Zd1O1GI8GTuFwCWuDOjEEwQIuBEfIcAy HQ8CAggA`, } lxd-2.0.0/dist/src/golang.org/x/crypto/pkcs12/mac.go0000644061062106075000000000200212702772344024460 0ustar00stgraberdomain admins00000000000000// Copyright 2015 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 pkcs12 import ( "crypto/hmac" "crypto/sha1" "crypto/x509/pkix" "encoding/asn1" ) type macData struct { Mac digestInfo MacSalt []byte Iterations int `asn1:"optional,default:1"` } // from PKCS#7: type digestInfo struct { Algorithm pkix.AlgorithmIdentifier Digest []byte } var ( oidSHA1 = asn1.ObjectIdentifier([]int{1, 3, 14, 3, 2, 26}) ) func verifyMac(macData *macData, message, password []byte) error { if !macData.Mac.Algorithm.Algorithm.Equal(oidSHA1) { return NotImplementedError("unknown digest algorithm: " + macData.Mac.Algorithm.Algorithm.String()) } key := pbkdf(sha1Sum, 20, 64, macData.MacSalt, password, macData.Iterations, 3, 20) mac := hmac.New(sha1.New, key) mac.Write(message) expectedMAC := mac.Sum(nil) if !hmac.Equal(macData.Mac.Digest, expectedMAC) { return ErrIncorrectPassword } return nil } lxd-2.0.0/dist/src/golang.org/x/crypto/pkcs12/crypto.go0000644061062106075000000000732012702772344025250 0ustar00stgraberdomain admins00000000000000// Copyright 2015 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 pkcs12 import ( "bytes" "crypto/cipher" "crypto/des" "crypto/x509/pkix" "encoding/asn1" "errors" "golang.org/x/crypto/pkcs12/internal/rc2" ) var ( oidPBEWithSHAAnd3KeyTripleDESCBC = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 12, 1, 3}) oidPBEWithSHAAnd40BitRC2CBC = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 12, 1, 6}) ) // pbeCipher is an abstraction of a PKCS#12 cipher. type pbeCipher interface { // create returns a cipher.Block given a key. create(key []byte) (cipher.Block, error) // deriveKey returns a key derived from the given password and salt. deriveKey(salt, password []byte, iterations int) []byte // deriveKey returns an IV derived from the given password and salt. deriveIV(salt, password []byte, iterations int) []byte } type shaWithTripleDESCBC struct{} func (shaWithTripleDESCBC) create(key []byte) (cipher.Block, error) { return des.NewTripleDESCipher(key) } func (shaWithTripleDESCBC) deriveKey(salt, password []byte, iterations int) []byte { return pbkdf(sha1Sum, 20, 64, salt, password, iterations, 1, 24) } func (shaWithTripleDESCBC) deriveIV(salt, password []byte, iterations int) []byte { return pbkdf(sha1Sum, 20, 64, salt, password, iterations, 2, 8) } type shaWith40BitRC2CBC struct{} func (shaWith40BitRC2CBC) create(key []byte) (cipher.Block, error) { return rc2.New(key, len(key)*8) } func (shaWith40BitRC2CBC) deriveKey(salt, password []byte, iterations int) []byte { return pbkdf(sha1Sum, 20, 64, salt, password, iterations, 1, 5) } func (shaWith40BitRC2CBC) deriveIV(salt, password []byte, iterations int) []byte { return pbkdf(sha1Sum, 20, 64, salt, password, iterations, 2, 8) } type pbeParams struct { Salt []byte Iterations int } func pbDecrypterFor(algorithm pkix.AlgorithmIdentifier, password []byte) (cipher.BlockMode, int, error) { var cipherType pbeCipher switch { case algorithm.Algorithm.Equal(oidPBEWithSHAAnd3KeyTripleDESCBC): cipherType = shaWithTripleDESCBC{} case algorithm.Algorithm.Equal(oidPBEWithSHAAnd40BitRC2CBC): cipherType = shaWith40BitRC2CBC{} default: return nil, 0, NotImplementedError("algorithm " + algorithm.Algorithm.String() + " is not supported") } var params pbeParams if err := unmarshal(algorithm.Parameters.FullBytes, ¶ms); err != nil { return nil, 0, err } key := cipherType.deriveKey(params.Salt, password, params.Iterations) iv := cipherType.deriveIV(params.Salt, password, params.Iterations) block, err := cipherType.create(key) if err != nil { return nil, 0, err } return cipher.NewCBCDecrypter(block, iv), block.BlockSize(), nil } func pbDecrypt(info decryptable, password []byte) (decrypted []byte, err error) { cbc, blockSize, err := pbDecrypterFor(info.Algorithm(), password) if err != nil { return nil, err } encrypted := info.Data() if len(encrypted) == 0 { return nil, errors.New("pkcs12: empty encrypted data") } if len(encrypted)%blockSize != 0 { return nil, errors.New("pkcs12: input is not a multiple of the block size") } decrypted = make([]byte, len(encrypted)) cbc.CryptBlocks(decrypted, encrypted) psLen := int(decrypted[len(decrypted)-1]) if psLen == 0 || psLen > blockSize { return nil, ErrDecryption } if len(decrypted) < psLen { return nil, ErrDecryption } ps := decrypted[len(decrypted)-psLen:] decrypted = decrypted[:len(decrypted)-psLen] if bytes.Compare(ps, bytes.Repeat([]byte{byte(psLen)}, psLen)) != 0 { return nil, ErrDecryption } return } // decryptable abstracts a object that contains ciphertext. type decryptable interface { Algorithm() pkix.AlgorithmIdentifier Data() []byte } lxd-2.0.0/dist/src/golang.org/x/crypto/pkcs12/internal/0000755061062106075000000000000012702772344025213 5ustar00stgraberdomain admins00000000000000lxd-2.0.0/dist/src/golang.org/x/crypto/pkcs12/internal/rc2/0000755061062106075000000000000012702772344025701 5ustar00stgraberdomain admins00000000000000lxd-2.0.0/dist/src/golang.org/x/crypto/pkcs12/internal/rc2/rc2_test.go0000644061062106075000000000307712702772344027764 0ustar00stgraberdomain admins00000000000000// Copyright 2015 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 rc2 import ( "bytes" "encoding/hex" "testing" ) func TestEncryptDecrypt(t *testing.T) { // TODO(dgryski): add the rest of the test vectors from the RFC var tests = []struct { key string plain string cipher string t1 int }{ { "0000000000000000", "0000000000000000", "ebb773f993278eff", 63, }, { "ffffffffffffffff", "ffffffffffffffff", "278b27e42e2f0d49", 64, }, { "3000000000000000", "1000000000000001", "30649edf9be7d2c2", 64, }, { "88", "0000000000000000", "61a8a244adacccf0", 64, }, { "88bca90e90875a", "0000000000000000", "6ccf4308974c267f", 64, }, { "88bca90e90875a7f0f79c384627bafb2", "0000000000000000", "1a807d272bbe5db1", 64, }, { "88bca90e90875a7f0f79c384627bafb2", "0000000000000000", "2269552ab0f85ca6", 128, }, { "88bca90e90875a7f0f79c384627bafb216f80a6f85920584c42fceb0be255daf1e", "0000000000000000", "5b78d3a43dfff1f1", 129, }, } for _, tt := range tests { k, _ := hex.DecodeString(tt.key) p, _ := hex.DecodeString(tt.plain) c, _ := hex.DecodeString(tt.cipher) b, _ := New(k, tt.t1) var dst [8]byte b.Encrypt(dst[:], p) if !bytes.Equal(dst[:], c) { t.Errorf("encrypt failed: got % 2x wanted % 2x\n", dst, c) } b.Decrypt(dst[:], c) if !bytes.Equal(dst[:], p) { t.Errorf("decrypt failed: got % 2x wanted % 2x\n", dst, p) } } } lxd-2.0.0/dist/src/golang.org/x/crypto/pkcs12/internal/rc2/bench_test.go0000644061062106075000000000105712702772344030351 0ustar00stgraberdomain admins00000000000000// Copyright 2015 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 rc2 import ( "testing" ) func BenchmarkEncrypt(b *testing.B) { r, _ := New([]byte{0, 0, 0, 0, 0, 0, 0, 0}, 64) b.ResetTimer() var src [8]byte for i := 0; i < b.N; i++ { r.Encrypt(src[:], src[:]) } } func BenchmarkDecrypt(b *testing.B) { r, _ := New([]byte{0, 0, 0, 0, 0, 0, 0, 0}, 64) b.ResetTimer() var src [8]byte for i := 0; i < b.N; i++ { r.Decrypt(src[:], src[:]) } } lxd-2.0.0/dist/src/golang.org/x/crypto/pkcs12/internal/rc2/rc2.go0000644061062106075000000001427512702772344026727 0ustar00stgraberdomain admins00000000000000// Copyright 2015 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 rc2 implements the RC2 cipher /* https://www.ietf.org/rfc/rfc2268.txt http://people.csail.mit.edu/rivest/pubs/KRRR98.pdf This code is licensed under the MIT license. */ package rc2 import ( "crypto/cipher" "encoding/binary" ) // The rc2 block size in bytes const BlockSize = 8 type rc2Cipher struct { k [64]uint16 } // New returns a new rc2 cipher with the given key and effective key length t1 func New(key []byte, t1 int) (cipher.Block, error) { // TODO(dgryski): error checking for key length return &rc2Cipher{ k: expandKey(key, t1), }, nil } func (*rc2Cipher) BlockSize() int { return BlockSize } var piTable = [256]byte{ 0xd9, 0x78, 0xf9, 0xc4, 0x19, 0xdd, 0xb5, 0xed, 0x28, 0xe9, 0xfd, 0x79, 0x4a, 0xa0, 0xd8, 0x9d, 0xc6, 0x7e, 0x37, 0x83, 0x2b, 0x76, 0x53, 0x8e, 0x62, 0x4c, 0x64, 0x88, 0x44, 0x8b, 0xfb, 0xa2, 0x17, 0x9a, 0x59, 0xf5, 0x87, 0xb3, 0x4f, 0x13, 0x61, 0x45, 0x6d, 0x8d, 0x09, 0x81, 0x7d, 0x32, 0xbd, 0x8f, 0x40, 0xeb, 0x86, 0xb7, 0x7b, 0x0b, 0xf0, 0x95, 0x21, 0x22, 0x5c, 0x6b, 0x4e, 0x82, 0x54, 0xd6, 0x65, 0x93, 0xce, 0x60, 0xb2, 0x1c, 0x73, 0x56, 0xc0, 0x14, 0xa7, 0x8c, 0xf1, 0xdc, 0x12, 0x75, 0xca, 0x1f, 0x3b, 0xbe, 0xe4, 0xd1, 0x42, 0x3d, 0xd4, 0x30, 0xa3, 0x3c, 0xb6, 0x26, 0x6f, 0xbf, 0x0e, 0xda, 0x46, 0x69, 0x07, 0x57, 0x27, 0xf2, 0x1d, 0x9b, 0xbc, 0x94, 0x43, 0x03, 0xf8, 0x11, 0xc7, 0xf6, 0x90, 0xef, 0x3e, 0xe7, 0x06, 0xc3, 0xd5, 0x2f, 0xc8, 0x66, 0x1e, 0xd7, 0x08, 0xe8, 0xea, 0xde, 0x80, 0x52, 0xee, 0xf7, 0x84, 0xaa, 0x72, 0xac, 0x35, 0x4d, 0x6a, 0x2a, 0x96, 0x1a, 0xd2, 0x71, 0x5a, 0x15, 0x49, 0x74, 0x4b, 0x9f, 0xd0, 0x5e, 0x04, 0x18, 0xa4, 0xec, 0xc2, 0xe0, 0x41, 0x6e, 0x0f, 0x51, 0xcb, 0xcc, 0x24, 0x91, 0xaf, 0x50, 0xa1, 0xf4, 0x70, 0x39, 0x99, 0x7c, 0x3a, 0x85, 0x23, 0xb8, 0xb4, 0x7a, 0xfc, 0x02, 0x36, 0x5b, 0x25, 0x55, 0x97, 0x31, 0x2d, 0x5d, 0xfa, 0x98, 0xe3, 0x8a, 0x92, 0xae, 0x05, 0xdf, 0x29, 0x10, 0x67, 0x6c, 0xba, 0xc9, 0xd3, 0x00, 0xe6, 0xcf, 0xe1, 0x9e, 0xa8, 0x2c, 0x63, 0x16, 0x01, 0x3f, 0x58, 0xe2, 0x89, 0xa9, 0x0d, 0x38, 0x34, 0x1b, 0xab, 0x33, 0xff, 0xb0, 0xbb, 0x48, 0x0c, 0x5f, 0xb9, 0xb1, 0xcd, 0x2e, 0xc5, 0xf3, 0xdb, 0x47, 0xe5, 0xa5, 0x9c, 0x77, 0x0a, 0xa6, 0x20, 0x68, 0xfe, 0x7f, 0xc1, 0xad, } func expandKey(key []byte, t1 int) [64]uint16 { l := make([]byte, 128) copy(l, key) var t = len(key) var t8 = (t1 + 7) / 8 var tm = byte(255 % uint(1<<(8+uint(t1)-8*uint(t8)))) for i := len(key); i < 128; i++ { l[i] = piTable[l[i-1]+l[uint8(i-t)]] } l[128-t8] = piTable[l[128-t8]&tm] for i := 127 - t8; i >= 0; i-- { l[i] = piTable[l[i+1]^l[i+t8]] } var k [64]uint16 for i := range k { k[i] = uint16(l[2*i]) + uint16(l[2*i+1])*256 } return k } func rotl16(x uint16, b uint) uint16 { return (x >> (16 - b)) | (x << b) } func (c *rc2Cipher) Encrypt(dst, src []byte) { r0 := binary.LittleEndian.Uint16(src[0:]) r1 := binary.LittleEndian.Uint16(src[2:]) r2 := binary.LittleEndian.Uint16(src[4:]) r3 := binary.LittleEndian.Uint16(src[6:]) var j int for j <= 16 { // mix r0 r0 = r0 + c.k[j] + (r3 & r2) + ((^r3) & r1) r0 = rotl16(r0, 1) j++ // mix r1 r1 = r1 + c.k[j] + (r0 & r3) + ((^r0) & r2) r1 = rotl16(r1, 2) j++ // mix r2 r2 = r2 + c.k[j] + (r1 & r0) + ((^r1) & r3) r2 = rotl16(r2, 3) j++ // mix r3 r3 = r3 + c.k[j] + (r2 & r1) + ((^r2) & r0) r3 = rotl16(r3, 5) j++ } r0 = r0 + c.k[r3&63] r1 = r1 + c.k[r0&63] r2 = r2 + c.k[r1&63] r3 = r3 + c.k[r2&63] for j <= 40 { // mix r0 r0 = r0 + c.k[j] + (r3 & r2) + ((^r3) & r1) r0 = rotl16(r0, 1) j++ // mix r1 r1 = r1 + c.k[j] + (r0 & r3) + ((^r0) & r2) r1 = rotl16(r1, 2) j++ // mix r2 r2 = r2 + c.k[j] + (r1 & r0) + ((^r1) & r3) r2 = rotl16(r2, 3) j++ // mix r3 r3 = r3 + c.k[j] + (r2 & r1) + ((^r2) & r0) r3 = rotl16(r3, 5) j++ } r0 = r0 + c.k[r3&63] r1 = r1 + c.k[r0&63] r2 = r2 + c.k[r1&63] r3 = r3 + c.k[r2&63] for j <= 60 { // mix r0 r0 = r0 + c.k[j] + (r3 & r2) + ((^r3) & r1) r0 = rotl16(r0, 1) j++ // mix r1 r1 = r1 + c.k[j] + (r0 & r3) + ((^r0) & r2) r1 = rotl16(r1, 2) j++ // mix r2 r2 = r2 + c.k[j] + (r1 & r0) + ((^r1) & r3) r2 = rotl16(r2, 3) j++ // mix r3 r3 = r3 + c.k[j] + (r2 & r1) + ((^r2) & r0) r3 = rotl16(r3, 5) j++ } binary.LittleEndian.PutUint16(dst[0:], r0) binary.LittleEndian.PutUint16(dst[2:], r1) binary.LittleEndian.PutUint16(dst[4:], r2) binary.LittleEndian.PutUint16(dst[6:], r3) } func (c *rc2Cipher) Decrypt(dst, src []byte) { r0 := binary.LittleEndian.Uint16(src[0:]) r1 := binary.LittleEndian.Uint16(src[2:]) r2 := binary.LittleEndian.Uint16(src[4:]) r3 := binary.LittleEndian.Uint16(src[6:]) j := 63 for j >= 44 { // unmix r3 r3 = rotl16(r3, 16-5) r3 = r3 - c.k[j] - (r2 & r1) - ((^r2) & r0) j-- // unmix r2 r2 = rotl16(r2, 16-3) r2 = r2 - c.k[j] - (r1 & r0) - ((^r1) & r3) j-- // unmix r1 r1 = rotl16(r1, 16-2) r1 = r1 - c.k[j] - (r0 & r3) - ((^r0) & r2) j-- // unmix r0 r0 = rotl16(r0, 16-1) r0 = r0 - c.k[j] - (r3 & r2) - ((^r3) & r1) j-- } r3 = r3 - c.k[r2&63] r2 = r2 - c.k[r1&63] r1 = r1 - c.k[r0&63] r0 = r0 - c.k[r3&63] for j >= 20 { // unmix r3 r3 = rotl16(r3, 16-5) r3 = r3 - c.k[j] - (r2 & r1) - ((^r2) & r0) j-- // unmix r2 r2 = rotl16(r2, 16-3) r2 = r2 - c.k[j] - (r1 & r0) - ((^r1) & r3) j-- // unmix r1 r1 = rotl16(r1, 16-2) r1 = r1 - c.k[j] - (r0 & r3) - ((^r0) & r2) j-- // unmix r0 r0 = rotl16(r0, 16-1) r0 = r0 - c.k[j] - (r3 & r2) - ((^r3) & r1) j-- } r3 = r3 - c.k[r2&63] r2 = r2 - c.k[r1&63] r1 = r1 - c.k[r0&63] r0 = r0 - c.k[r3&63] for j >= 0 { // unmix r3 r3 = rotl16(r3, 16-5) r3 = r3 - c.k[j] - (r2 & r1) - ((^r2) & r0) j-- // unmix r2 r2 = rotl16(r2, 16-3) r2 = r2 - c.k[j] - (r1 & r0) - ((^r1) & r3) j-- // unmix r1 r1 = rotl16(r1, 16-2) r1 = r1 - c.k[j] - (r0 & r3) - ((^r0) & r2) j-- // unmix r0 r0 = rotl16(r0, 16-1) r0 = r0 - c.k[j] - (r3 & r2) - ((^r3) & r1) j-- } binary.LittleEndian.PutUint16(dst[0:], r0) binary.LittleEndian.PutUint16(dst[2:], r1) binary.LittleEndian.PutUint16(dst[4:], r2) binary.LittleEndian.PutUint16(dst[6:], r3) } lxd-2.0.0/dist/src/golang.org/x/crypto/pkcs12/pbkdf.go0000644061062106075000000001303712702772344025020 0ustar00stgraberdomain admins00000000000000// Copyright 2015 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 pkcs12 import ( "bytes" "crypto/sha1" "math/big" ) var ( one = big.NewInt(1) ) // sha1Sum returns the SHA-1 hash of in. func sha1Sum(in []byte) []byte { sum := sha1.Sum(in) return sum[:] } // fillWithRepeats returns v*ceiling(len(pattern) / v) bytes consisting of // repeats of pattern. func fillWithRepeats(pattern []byte, v int) []byte { if len(pattern) == 0 { return nil } outputLen := v * ((len(pattern) + v - 1) / v) return bytes.Repeat(pattern, (outputLen+len(pattern)-1)/len(pattern))[:outputLen] } func pbkdf(hash func([]byte) []byte, u, v int, salt, password []byte, r int, ID byte, size int) (key []byte) { // implementation of https://tools.ietf.org/html/rfc7292#appendix-B.2 , RFC text verbatim in comments // Let H be a hash function built around a compression function f: // Z_2^u x Z_2^v -> Z_2^u // (that is, H has a chaining variable and output of length u bits, and // the message input to the compression function of H is v bits). The // values for u and v are as follows: // HASH FUNCTION VALUE u VALUE v // MD2, MD5 128 512 // SHA-1 160 512 // SHA-224 224 512 // SHA-256 256 512 // SHA-384 384 1024 // SHA-512 512 1024 // SHA-512/224 224 1024 // SHA-512/256 256 1024 // Furthermore, let r be the iteration count. // We assume here that u and v are both multiples of 8, as are the // lengths of the password and salt strings (which we denote by p and s, // respectively) and the number n of pseudorandom bits required. In // addition, u and v are of course non-zero. // For information on security considerations for MD5 [19], see [25] and // [1], and on those for MD2, see [18]. // The following procedure can be used to produce pseudorandom bits for // a particular "purpose" that is identified by a byte called "ID". // This standard specifies 3 different values for the ID byte: // 1. If ID=1, then the pseudorandom bits being produced are to be used // as key material for performing encryption or decryption. // 2. If ID=2, then the pseudorandom bits being produced are to be used // as an IV (Initial Value) for encryption or decryption. // 3. If ID=3, then the pseudorandom bits being produced are to be used // as an integrity key for MACing. // 1. Construct a string, D (the "diversifier"), by concatenating v/8 // copies of ID. var D []byte for i := 0; i < v; i++ { D = append(D, ID) } // 2. Concatenate copies of the salt together to create a string S of // length v(ceiling(s/v)) bits (the final copy of the salt may be // truncated to create S). Note that if the salt is the empty // string, then so is S. S := fillWithRepeats(salt, v) // 3. Concatenate copies of the password together to create a string P // of length v(ceiling(p/v)) bits (the final copy of the password // may be truncated to create P). Note that if the password is the // empty string, then so is P. P := fillWithRepeats(password, v) // 4. Set I=S||P to be the concatenation of S and P. I := append(S, P...) // 5. Set c=ceiling(n/u). c := (size + u - 1) / u // 6. For i=1, 2, ..., c, do the following: A := make([]byte, c*20) var IjBuf []byte for i := 0; i < c; i++ { // A. Set A2=H^r(D||I). (i.e., the r-th hash of D||1, // H(H(H(... H(D||I)))) Ai := hash(append(D, I...)) for j := 1; j < r; j++ { Ai = hash(Ai) } copy(A[i*20:], Ai[:]) if i < c-1 { // skip on last iteration // B. Concatenate copies of Ai to create a string B of length v // bits (the final copy of Ai may be truncated to create B). var B []byte for len(B) < v { B = append(B, Ai[:]...) } B = B[:v] // C. Treating I as a concatenation I_0, I_1, ..., I_(k-1) of v-bit // blocks, where k=ceiling(s/v)+ceiling(p/v), modify I by // setting I_j=(I_j+B+1) mod 2^v for each j. { Bbi := new(big.Int).SetBytes(B) Ij := new(big.Int) for j := 0; j < len(I)/v; j++ { Ij.SetBytes(I[j*v : (j+1)*v]) Ij.Add(Ij, Bbi) Ij.Add(Ij, one) Ijb := Ij.Bytes() // We expect Ijb to be exactly v bytes, // if it is longer or shorter we must // adjust it accordingly. if len(Ijb) > v { Ijb = Ijb[len(Ijb)-v:] } if len(Ijb) < v { if IjBuf == nil { IjBuf = make([]byte, v) } bytesShort := v - len(Ijb) for i := 0; i < bytesShort; i++ { IjBuf[i] = 0 } copy(IjBuf[bytesShort:], Ijb) Ijb = IjBuf } copy(I[j*v:(j+1)*v], Ijb) } } } } // 7. Concatenate A_1, A_2, ..., A_c together to form a pseudorandom // bit string, A. // 8. Use the first n bits of A as the output of this entire process. return A[:size] // If the above process is being used to generate a DES key, the process // should be used to create 64 random bits, and the key's parity bits // should be set after the 64 bits have been produced. Similar concerns // hold for 2-key and 3-key triple-DES keys, for CDMF keys, and for any // similar keys with parity bits "built into them". } lxd-2.0.0/dist/src/golang.org/x/crypto/openpgp/0000755061062106075000000000000012702772344023744 5ustar00stgraberdomain admins00000000000000lxd-2.0.0/dist/src/golang.org/x/crypto/openpgp/canonical_text.go0000644061062106075000000000216712702772344027274 0ustar00stgraberdomain admins00000000000000// 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" // 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, 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(in []byte) []byte { return cth.h.Sum(in) } func (cth *canonicalTextHash) Reset() { cth.h.Reset() cth.s = 0 } func (cth *canonicalTextHash) Size() int { return cth.h.Size() } func (cth *canonicalTextHash) BlockSize() int { return cth.h.BlockSize() } lxd-2.0.0/dist/src/golang.org/x/crypto/openpgp/armor/0000755061062106075000000000000012702772344025064 5ustar00stgraberdomain admins00000000000000lxd-2.0.0/dist/src/golang.org/x/crypto/openpgp/armor/armor.go0000644061062106075000000001164212702772344026537 0ustar00stgraberdomain admins00000000000000// Copyright 2010 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Package armor implements OpenPGP ASCII Armor, see RFC 4880. OpenPGP Armor is // very similar to PEM except that it has an additional CRC checksum. package armor // import "golang.org/x/crypto/openpgp/armor" import ( "bufio" "bytes" "encoding/base64" "golang.org/x/crypto/openpgp/errors" "io" ) // A Block represents an OpenPGP armored structure. // // The encoded form is: // -----BEGIN Type----- // Headers // // base64-encoded Bytes // '=' base64 encoded checksum // -----END Type----- // where Headers is a possibly empty sequence of Key: Value lines. // // Since the armored data can be very large, this package presents a streaming // interface. type Block struct { Type string // The type, taken from the preamble (i.e. "PGP SIGNATURE"). Header map[string]string // Optional headers. Body io.Reader // A Reader from which the contents can be read lReader lineReader oReader openpgpReader } var ArmorCorrupt error = errors.StructuralError("armor invalid") const crc24Init = 0xb704ce const crc24Poly = 0x1864cfb const crc24Mask = 0xffffff // crc24 calculates the OpenPGP checksum as specified in RFC 4880, section 6.1 func crc24(crc uint32, d []byte) uint32 { for _, b := range d { crc ^= uint32(b) << 16 for i := 0; i < 8; i++ { crc <<= 1 if crc&0x1000000 != 0 { crc ^= crc24Poly } } } return crc } var armorStart = []byte("-----BEGIN ") var armorEnd = []byte("-----END ") var armorEndOfLine = []byte("-----") // lineReader wraps a line based reader. It watches for the end of an armor // block and records the expected CRC value. type lineReader struct { in *bufio.Reader buf []byte eof bool crc uint32 } func (l *lineReader) Read(p []byte) (n int, err error) { if l.eof { return 0, io.EOF } if len(l.buf) > 0 { n = copy(p, l.buf) l.buf = l.buf[n:] return } line, isPrefix, err := l.in.ReadLine() if err != nil { return } if isPrefix { return 0, ArmorCorrupt } if len(line) == 5 && line[0] == '=' { // This is the checksum line var expectedBytes [3]byte var m int m, err = base64.StdEncoding.Decode(expectedBytes[0:], line[1:]) if m != 3 || err != nil { return } l.crc = uint32(expectedBytes[0])<<16 | uint32(expectedBytes[1])<<8 | uint32(expectedBytes[2]) line, _, err = l.in.ReadLine() if err != nil && err != io.EOF { return } if !bytes.HasPrefix(line, armorEnd) { return 0, ArmorCorrupt } l.eof = true return 0, io.EOF } if len(line) > 96 { return 0, ArmorCorrupt } n = copy(p, line) bytesToSave := len(line) - n if bytesToSave > 0 { if cap(l.buf) < bytesToSave { l.buf = make([]byte, 0, bytesToSave) } l.buf = l.buf[0:bytesToSave] copy(l.buf, line[n:]) } return } // openpgpReader passes Read calls to the underlying base64 decoder, but keeps // a running CRC of the resulting data and checks the CRC against the value // found by the lineReader at EOF. type openpgpReader struct { lReader *lineReader b64Reader io.Reader currentCRC uint32 } func (r *openpgpReader) Read(p []byte) (n int, err error) { n, err = r.b64Reader.Read(p) r.currentCRC = crc24(r.currentCRC, p[:n]) if err == io.EOF { if r.lReader.crc != uint32(r.currentCRC&crc24Mask) { return 0, ArmorCorrupt } } return } // Decode reads a PGP armored block from the given Reader. It will ignore // leading garbage. If it doesn't find a block, it will return nil, io.EOF. The // given Reader is not usable after calling this function: an arbitrary amount // of data may have been read past the end of the block. func Decode(in io.Reader) (p *Block, err error) { r := bufio.NewReaderSize(in, 100) var line []byte ignoreNext := false TryNextBlock: p = nil // Skip leading garbage for { ignoreThis := ignoreNext line, ignoreNext, err = r.ReadLine() if err != nil { return } if ignoreNext || ignoreThis { continue } line = bytes.TrimSpace(line) if len(line) > len(armorStart)+len(armorEndOfLine) && bytes.HasPrefix(line, armorStart) { break } } p = new(Block) p.Type = string(line[len(armorStart) : len(line)-len(armorEndOfLine)]) p.Header = make(map[string]string) nextIsContinuation := false var lastKey string // Read headers for { isContinuation := nextIsContinuation line, nextIsContinuation, err = r.ReadLine() if err != nil { p = nil return } if isContinuation { p.Header[lastKey] += string(line) continue } line = bytes.TrimSpace(line) if len(line) == 0 { break } i := bytes.Index(line, []byte(": ")) if i == -1 { goto TryNextBlock } lastKey = string(line[:i]) p.Header[lastKey] = string(line[i+2:]) } p.lReader.in = r p.oReader.currentCRC = crc24Init p.oReader.lReader = &p.lReader p.oReader.b64Reader = base64.NewDecoder(base64.StdEncoding, &p.lReader) p.Body = &p.oReader return } lxd-2.0.0/dist/src/golang.org/x/crypto/openpgp/armor/armor_test.go0000644061062106075000000000603612702772344027577 0ustar00stgraberdomain admins00000000000000// Copyright 2010 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package armor import ( "bytes" "hash/adler32" "io/ioutil" "testing" ) func TestDecodeEncode(t *testing.T) { buf := bytes.NewBuffer([]byte(armorExample1)) result, err := Decode(buf) if err != nil { t.Error(err) } expectedType := "PGP SIGNATURE" if result.Type != expectedType { t.Errorf("result.Type: got:%s want:%s", result.Type, expectedType) } if len(result.Header) != 1 { t.Errorf("len(result.Header): got:%d want:1", len(result.Header)) } v, ok := result.Header["Version"] if !ok || v != "GnuPG v1.4.10 (GNU/Linux)" { t.Errorf("result.Header: got:%#v", result.Header) } contents, err := ioutil.ReadAll(result.Body) if err != nil { t.Error(err) } if adler32.Checksum(contents) != 0x27b144be { t.Errorf("contents: got: %x", contents) } buf = bytes.NewBuffer(nil) w, err := Encode(buf, result.Type, result.Header) if err != nil { t.Error(err) } _, err = w.Write(contents) if err != nil { t.Error(err) } w.Close() if !bytes.Equal(buf.Bytes(), []byte(armorExample1)) { t.Errorf("got: %s\nwant: %s", string(buf.Bytes()), armorExample1) } } func TestLongHeader(t *testing.T) { buf := bytes.NewBuffer([]byte(armorLongLine)) result, err := Decode(buf) if err != nil { t.Error(err) return } value, ok := result.Header["Version"] if !ok { t.Errorf("missing Version header") } if value != longValueExpected { t.Errorf("got: %s want: %s", value, longValueExpected) } } const armorExample1 = `-----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.10 (GNU/Linux) iJwEAAECAAYFAk1Fv/0ACgkQo01+GMIMMbsYTwQAiAw+QAaNfY6WBdplZ/uMAccm 4g+81QPmTSGHnetSb6WBiY13kVzK4HQiZH8JSkmmroMLuGeJwsRTEL4wbjRyUKEt p1xwUZDECs234F1xiG5enc5SGlRtP7foLBz9lOsjx+LEcA4sTl5/2eZR9zyFZqWW TxRjs+fJCIFuo71xb1g= =/teI -----END PGP SIGNATURE-----` const armorLongLine = `-----BEGIN PGP SIGNATURE----- Version: 0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz iQEcBAABAgAGBQJMtFESAAoJEKsQXJGvOPsVj40H/1WW6jaMXv4BW+1ueDSMDwM8 kx1fLOXbVM5/Kn5LStZNt1jWWnpxdz7eq3uiqeCQjmqUoRde3YbB2EMnnwRbAhpp cacnAvy9ZQ78OTxUdNW1mhX5bS6q1MTEJnl+DcyigD70HG/yNNQD7sOPMdYQw0TA byQBwmLwmTsuZsrYqB68QyLHI+DUugn+kX6Hd2WDB62DKa2suoIUIHQQCd/ofwB3 WfCYInXQKKOSxu2YOg2Eb4kLNhSMc1i9uKUWAH+sdgJh7NBgdoE4MaNtBFkHXRvv okWuf3+xA9ksp1npSY/mDvgHijmjvtpRDe6iUeqfCn8N9u9CBg8geANgaG8+QA4= =wfQG -----END PGP SIGNATURE-----` const longValueExpected = "0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz" lxd-2.0.0/dist/src/golang.org/x/crypto/openpgp/armor/encode.go0000644061062106075000000000650012702772344026651 0ustar00stgraberdomain admins00000000000000// Copyright 2010 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package armor import ( "encoding/base64" "io" ) var armorHeaderSep = []byte(": ") var blockEnd = []byte("\n=") var newline = []byte("\n") var armorEndOfLineOut = []byte("-----\n") // writeSlices writes its arguments to the given Writer. func writeSlices(out io.Writer, slices ...[]byte) (err error) { for _, s := range slices { _, err = out.Write(s) if err != nil { return err } } return } // lineBreaker breaks data across several lines, all of the same byte length // (except possibly the last). Lines are broken with a single '\n'. type lineBreaker struct { lineLength int line []byte used int out io.Writer haveWritten bool } func newLineBreaker(out io.Writer, lineLength int) *lineBreaker { return &lineBreaker{ lineLength: lineLength, line: make([]byte, lineLength), used: 0, out: out, } } func (l *lineBreaker) Write(b []byte) (n int, err error) { n = len(b) if n == 0 { return } if l.used == 0 && l.haveWritten { _, err = l.out.Write([]byte{'\n'}) if err != nil { return } } if l.used+len(b) < l.lineLength { l.used += copy(l.line[l.used:], b) return } l.haveWritten = true _, err = l.out.Write(l.line[0:l.used]) if err != nil { return } excess := l.lineLength - l.used l.used = 0 _, err = l.out.Write(b[0:excess]) if err != nil { return } _, err = l.Write(b[excess:]) return } func (l *lineBreaker) Close() (err error) { if l.used > 0 { _, err = l.out.Write(l.line[0:l.used]) if err != nil { return } } return } // encoding keeps track of a running CRC24 over the data which has been written // to it and outputs a OpenPGP checksum when closed, followed by an armor // trailer. // // It's built into a stack of io.Writers: // encoding -> base64 encoder -> lineBreaker -> out type encoding struct { out io.Writer breaker *lineBreaker b64 io.WriteCloser crc uint32 blockType []byte } func (e *encoding) Write(data []byte) (n int, err error) { e.crc = crc24(e.crc, data) return e.b64.Write(data) } func (e *encoding) Close() (err error) { err = e.b64.Close() if err != nil { return } e.breaker.Close() var checksumBytes [3]byte checksumBytes[0] = byte(e.crc >> 16) checksumBytes[1] = byte(e.crc >> 8) checksumBytes[2] = byte(e.crc) var b64ChecksumBytes [4]byte base64.StdEncoding.Encode(b64ChecksumBytes[:], checksumBytes[:]) return writeSlices(e.out, blockEnd, b64ChecksumBytes[:], newline, armorEnd, e.blockType, armorEndOfLine) } // Encode returns a WriteCloser which will encode the data written to it in // OpenPGP armor. func Encode(out io.Writer, blockType string, headers map[string]string) (w io.WriteCloser, err error) { bType := []byte(blockType) err = writeSlices(out, armorStart, bType, armorEndOfLineOut) if err != nil { return } for k, v := range headers { err = writeSlices(out, []byte(k), armorHeaderSep, []byte(v), newline) if err != nil { return } } _, err = out.Write(newline) if err != nil { return } e := &encoding{ out: out, breaker: newLineBreaker(out, 64), crc: crc24Init, blockType: bType, } e.b64 = base64.NewEncoder(base64.StdEncoding, e.breaker) return e, nil } lxd-2.0.0/dist/src/golang.org/x/crypto/openpgp/write_test.go0000644061062106075000000001531112702772344026465 0ustar00stgraberdomain admins00000000000000// 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" "io" "io/ioutil" "testing" "time" "golang.org/x/crypto/openpgp/packet" ) func TestSignDetached(t *testing.T) { kring, _ := ReadKeyRing(readerFromHex(testKeys1And2PrivateHex)) out := bytes.NewBuffer(nil) message := bytes.NewBufferString(signedInput) err := DetachSign(out, kring[0], message, nil) if err != nil { t.Error(err) } testDetachedSignature(t, kring, out, signedInput, "check", testKey1KeyId) } func TestSignTextDetached(t *testing.T) { kring, _ := ReadKeyRing(readerFromHex(testKeys1And2PrivateHex)) out := bytes.NewBuffer(nil) message := bytes.NewBufferString(signedInput) err := DetachSignText(out, kring[0], message, nil) if err != nil { t.Error(err) } testDetachedSignature(t, kring, out, signedInput, "check", testKey1KeyId) } func TestSignDetachedDSA(t *testing.T) { kring, _ := ReadKeyRing(readerFromHex(dsaTestKeyPrivateHex)) out := bytes.NewBuffer(nil) message := bytes.NewBufferString(signedInput) err := DetachSign(out, kring[0], message, nil) if err != nil { t.Error(err) } testDetachedSignature(t, kring, out, signedInput, "check", testKey3KeyId) } func TestSignDetachedP256(t *testing.T) { kring, _ := ReadKeyRing(readerFromHex(p256TestKeyPrivateHex)) kring[0].PrivateKey.Decrypt([]byte("passphrase")) out := bytes.NewBuffer(nil) message := bytes.NewBufferString(signedInput) err := DetachSign(out, kring[0], message, nil) if err != nil { t.Error(err) } testDetachedSignature(t, kring, out, signedInput, "check", testKeyP256KeyId) } func TestNewEntity(t *testing.T) { if testing.Short() { return } // Check bit-length with no config. e, err := NewEntity("Test User", "test", "test@example.com", nil) if err != nil { t.Errorf("failed to create entity: %s", err) return } bl, err := e.PrimaryKey.BitLength() if err != nil { t.Errorf("failed to find bit length: %s", err) } if int(bl) != defaultRSAKeyBits { t.Errorf("BitLength %v, expected %v", defaultRSAKeyBits) } // Check bit-length with a config. cfg := &packet.Config{RSABits: 1024} e, err = NewEntity("Test User", "test", "test@example.com", cfg) if err != nil { t.Errorf("failed to create entity: %s", err) return } bl, err = e.PrimaryKey.BitLength() if err != nil { t.Errorf("failed to find bit length: %s", err) } if int(bl) != cfg.RSABits { t.Errorf("BitLength %v, expected %v", bl, cfg.RSABits) } w := bytes.NewBuffer(nil) if err := e.SerializePrivate(w, nil); err != nil { t.Errorf("failed to serialize entity: %s", err) return } serialized := w.Bytes() el, err := ReadKeyRing(w) if err != nil { t.Errorf("failed to reparse entity: %s", err) return } if len(el) != 1 { t.Errorf("wrong number of entities found, got %d, want 1", len(el)) } w = bytes.NewBuffer(nil) if err := e.SerializePrivate(w, nil); err != nil { t.Errorf("failed to serialize entity second time: %s", err) return } if !bytes.Equal(w.Bytes(), serialized) { t.Errorf("results differed") } } func TestSymmetricEncryption(t *testing.T) { buf := new(bytes.Buffer) plaintext, err := SymmetricallyEncrypt(buf, []byte("testing"), nil, nil) if err != nil { t.Errorf("error writing headers: %s", err) return } message := []byte("hello world\n") _, err = plaintext.Write(message) if err != nil { t.Errorf("error writing to plaintext writer: %s", err) } err = plaintext.Close() if err != nil { t.Errorf("error closing plaintext writer: %s", err) } md, err := ReadMessage(buf, nil, func(keys []Key, symmetric bool) ([]byte, error) { return []byte("testing"), nil }, nil) if err != nil { t.Errorf("error rereading message: %s", err) } messageBuf := bytes.NewBuffer(nil) _, err = io.Copy(messageBuf, md.UnverifiedBody) if err != nil { t.Errorf("error rereading message: %s", err) } if !bytes.Equal(message, messageBuf.Bytes()) { t.Errorf("recovered message incorrect got '%s', want '%s'", messageBuf.Bytes(), message) } } var testEncryptionTests = []struct { keyRingHex string isSigned bool }{ { testKeys1And2PrivateHex, false, }, { testKeys1And2PrivateHex, true, }, { dsaElGamalTestKeysHex, false, }, { dsaElGamalTestKeysHex, true, }, } func TestEncryption(t *testing.T) { for i, test := range testEncryptionTests { kring, _ := ReadKeyRing(readerFromHex(test.keyRingHex)) passphrase := []byte("passphrase") for _, entity := range kring { if entity.PrivateKey != nil && entity.PrivateKey.Encrypted { err := entity.PrivateKey.Decrypt(passphrase) if err != nil { t.Errorf("#%d: failed to decrypt key", i) } } for _, subkey := range entity.Subkeys { if subkey.PrivateKey != nil && subkey.PrivateKey.Encrypted { err := subkey.PrivateKey.Decrypt(passphrase) if err != nil { t.Errorf("#%d: failed to decrypt subkey", i) } } } } var signed *Entity if test.isSigned { signed = kring[0] } buf := new(bytes.Buffer) w, err := Encrypt(buf, kring[:1], signed, nil /* no hints */, nil) if err != nil { t.Errorf("#%d: error in Encrypt: %s", i, err) continue } const message = "testing" _, err = w.Write([]byte(message)) if err != nil { t.Errorf("#%d: error writing plaintext: %s", i, err) continue } err = w.Close() if err != nil { t.Errorf("#%d: error closing WriteCloser: %s", i, err) continue } md, err := ReadMessage(buf, kring, nil /* no prompt */, nil) if err != nil { t.Errorf("#%d: error reading message: %s", i, err) continue } testTime, _ := time.Parse("2006-01-02", "2013-07-01") if test.isSigned { signKey, _ := kring[0].signingKey(testTime) expectedKeyId := signKey.PublicKey.KeyId if md.SignedByKeyId != expectedKeyId { t.Errorf("#%d: message signed by wrong key id, got: %d, want: %d", i, *md.SignedBy, expectedKeyId) } if md.SignedBy == nil { t.Errorf("#%d: failed to find the signing Entity", i) } } plaintext, err := ioutil.ReadAll(md.UnverifiedBody) if err != nil { t.Errorf("#%d: error reading encrypted contents: %s", i, err) continue } encryptKey, _ := kring[0].encryptionKey(testTime) expectedKeyId := encryptKey.PublicKey.KeyId if len(md.EncryptedToKeyIds) != 1 || md.EncryptedToKeyIds[0] != expectedKeyId { t.Errorf("#%d: expected message to be encrypted to %v, but got %#v", i, expectedKeyId, md.EncryptedToKeyIds) } if string(plaintext) != message { t.Errorf("#%d: got: %s, want: %s", i, string(plaintext), message) } if test.isSigned { if md.SignatureError != nil { t.Errorf("#%d: signature error: %s", i, md.SignatureError) } if md.Signature == nil { t.Error("signature missing") } } } } lxd-2.0.0/dist/src/golang.org/x/crypto/openpgp/errors/0000755061062106075000000000000012702772344025260 5ustar00stgraberdomain admins00000000000000lxd-2.0.0/dist/src/golang.org/x/crypto/openpgp/errors/errors.go0000644061062106075000000000353312702772344027127 0ustar00stgraberdomain admins00000000000000// Copyright 2010 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Package errors contains common error types for the OpenPGP packages. package errors // import "golang.org/x/crypto/openpgp/errors" import ( "strconv" ) // A StructuralError is returned when OpenPGP data is found to be syntactically // invalid. type StructuralError string func (s StructuralError) Error() string { return "openpgp: invalid data: " + string(s) } // UnsupportedError indicates that, although the OpenPGP data is valid, it // makes use of currently unimplemented features. type UnsupportedError string func (s UnsupportedError) Error() string { return "openpgp: unsupported feature: " + string(s) } // InvalidArgumentError indicates that the caller is in error and passed an // incorrect value. type InvalidArgumentError string func (i InvalidArgumentError) Error() string { return "openpgp: invalid argument: " + string(i) } // SignatureError indicates that a syntactically valid signature failed to // validate. type SignatureError string func (b SignatureError) Error() string { return "openpgp: invalid signature: " + string(b) } type keyIncorrectError int func (ki keyIncorrectError) Error() string { return "openpgp: incorrect key" } var ErrKeyIncorrect error = keyIncorrectError(0) type unknownIssuerError int func (unknownIssuerError) Error() string { return "openpgp: signature made by unknown entity" } var ErrUnknownIssuer error = unknownIssuerError(0) type keyRevokedError int func (keyRevokedError) Error() string { return "openpgp: signature made by revoked key" } var ErrKeyRevoked error = keyRevokedError(0) type UnknownPacketTypeError uint8 func (upte UnknownPacketTypeError) Error() string { return "openpgp: unknown packet type: " + strconv.Itoa(int(upte)) } lxd-2.0.0/dist/src/golang.org/x/crypto/openpgp/keys.go0000644061062106075000000004317112702772344025254 0ustar00stgraberdomain admins00000000000000// 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/rsa" "io" "time" "golang.org/x/crypto/openpgp/armor" "golang.org/x/crypto/openpgp/errors" "golang.org/x/crypto/openpgp/packet" ) // PublicKeyType is the armor type for a PGP public key. var PublicKeyType = "PGP PUBLIC KEY BLOCK" // PrivateKeyType is the armor type for a PGP private key. var PrivateKeyType = "PGP PRIVATE 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 Revocations []*packet.Signature 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) " 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 // KeysByIdAndUsage returns the set of keys with the given id // that also meet the key usage given by requiredUsage. // The requiredUsage is expressed as the bitwise-OR of // packet.KeyFlag* values. KeysByIdUsage(id uint64, requiredUsage byte) []Key // DecryptionKeys returns all private keys that are valid for // decryption. DecryptionKeys() []Key } // primaryIdentity returns the Identity marked as primary or the first identity // if none are so marked. func (e *Entity) primaryIdentity() *Identity { var firstIdentity *Identity for _, ident := range e.Identities { if firstIdentity == nil { firstIdentity = ident } if ident.SelfSignature.IsPrimaryId != nil && *ident.SelfSignature.IsPrimaryId { return ident } } return firstIdentity } // encryptionKey returns the best candidate Key for encrypting a message to the // given Entity. func (e *Entity) encryptionKey(now time.Time) (Key, bool) { candidateSubkey := -1 // Iterate the keys to find the newest key var maxTime time.Time for i, subkey := range e.Subkeys { if subkey.Sig.FlagsValid && subkey.Sig.FlagEncryptCommunications && subkey.PublicKey.PubKeyAlgo.CanEncrypt() && !subkey.Sig.KeyExpired(now) && (maxTime.IsZero() || subkey.Sig.CreationTime.After(maxTime)) { candidateSubkey = i maxTime = subkey.Sig.CreationTime } } if candidateSubkey != -1 { subkey := e.Subkeys[candidateSubkey] return Key{e, subkey.PublicKey, subkey.PrivateKey, subkey.Sig}, true } // If we don't have any candidate subkeys for encryption and // the primary key doesn't have any usage metadata then we // assume that the primary key is ok. Or, if the primary key is // marked as ok to encrypt to, then we can obviously use it. i := e.primaryIdentity() if !i.SelfSignature.FlagsValid || i.SelfSignature.FlagEncryptCommunications && e.PrimaryKey.PubKeyAlgo.CanEncrypt() && !i.SelfSignature.KeyExpired(now) { return Key{e, e.PrimaryKey, e.PrivateKey, i.SelfSignature}, true } // This Entity appears to be signing only. return Key{}, false } // signingKey return the best candidate Key for signing a message with this // Entity. func (e *Entity) signingKey(now time.Time) (Key, bool) { candidateSubkey := -1 for i, subkey := range e.Subkeys { if subkey.Sig.FlagsValid && subkey.Sig.FlagSign && subkey.PublicKey.PubKeyAlgo.CanSign() && !subkey.Sig.KeyExpired(now) { candidateSubkey = i break } } if candidateSubkey != -1 { subkey := e.Subkeys[candidateSubkey] return Key{e, subkey.PublicKey, subkey.PrivateKey, subkey.Sig}, true } // If we have no candidate subkey then we assume that it's ok to sign // with the primary key. i := e.primaryIdentity() if !i.SelfSignature.FlagsValid || i.SelfSignature.FlagSign && !i.SelfSignature.KeyExpired(now) { return Key{e, e.PrimaryKey, e.PrivateKey, i.SelfSignature}, true } return Key{}, false } // 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 } // KeysByIdAndUsage returns the set of keys with the given id that also meet // the key usage given by requiredUsage. The requiredUsage is expressed as // the bitwise-OR of packet.KeyFlag* values. func (el EntityList) KeysByIdUsage(id uint64, requiredUsage byte) (keys []Key) { for _, key := range el.KeysById(id) { if len(key.Entity.Revocations) > 0 { continue } if key.SelfSignature.RevocationReason != nil { continue } if key.SelfSignature.FlagsValid && requiredUsage != 0 { var usage byte if key.SelfSignature.FlagCertify { usage |= packet.KeyFlagCertify } if key.SelfSignature.FlagSign { usage |= packet.KeyFlagSign } if key.SelfSignature.FlagEncryptCommunications { usage |= packet.KeyFlagEncryptCommunications } if key.SelfSignature.FlagEncryptStorage { usage |= packet.KeyFlagEncryptStorage } if usage&requiredUsage != requiredUsage { continue } } keys = append(keys, key) } 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, error) { block, err := armor.Decode(r) if err == io.EOF { return nil, errors.InvalidArgumentError("no armored data found") } if err != nil { return nil, err } if block.Type != PublicKeyType && block.Type != PrivateKeyType { return nil, errors.InvalidArgumentError("expected public or private key block, got: " + block.Type) } return ReadKeyRing(block.Body) } // ReadKeyRing reads one or more public/private keys. Unsupported keys are // ignored as long as at least a single valid key is found. func ReadKeyRing(r io.Reader) (el EntityList, err error) { packets := packet.NewReader(r) var lastUnsupportedError error for { var e *Entity e, err = ReadEntity(packets) if err != nil { // TODO: warn about skipped unsupported/unreadable keys if _, ok := err.(errors.UnsupportedError); ok { lastUnsupportedError = err err = readToNextPublicKey(packets) } else if _, ok := err.(errors.StructuralError); ok { // Skip unreadable, badly-formatted keys lastUnsupportedError = err err = readToNextPublicKey(packets) } if err == io.EOF { err = nil break } if err != nil { el = nil break } } else { el = append(el, e) } } if len(el) == 0 && err == nil { err = lastUnsupportedError } 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 error) { var p packet.Packet for { p, err = packets.Next() if err == io.EOF { return } else if err != nil { if _, ok := err.(errors.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, 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, errors.StructuralError("first packet was not a public/private key") } else { e.PrimaryKey = &e.PrivateKey.PublicKey } } if !e.PrimaryKey.PubKeyAlgo.CanSign() { return nil, errors.StructuralError("primary key cannot be used for signatures") } var current *Identity var revocations []*packet.Signature EachPacket: for { p, err := packets.Next() if err == io.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 for { p, err = packets.Next() if err == io.EOF { return nil, io.ErrUnexpectedEOF } else if err != nil { return nil, err } sig, ok := p.(*packet.Signature) if !ok { return nil, errors.StructuralError("user ID packet not followed by self-signature") } if (sig.SigType == packet.SigTypePositiveCert || sig.SigType == packet.SigTypeGenericCert) && sig.IssuerKeyId != nil && *sig.IssuerKeyId == e.PrimaryKey.KeyId { if err = e.PrimaryKey.VerifyUserIdSignature(pkt.Id, e.PrimaryKey, sig); err != nil { return nil, errors.StructuralError("user ID self-signature invalid: " + err.Error()) } current.SelfSignature = sig break } current.Signatures = append(current.Signatures, sig) } case *packet.Signature: if pkt.SigType == packet.SigTypeKeyRevocation { revocations = append(revocations, pkt) } else if pkt.SigType == packet.SigTypeDirectSignature { // TODO: RFC4880 5.2.1 permits signatures // directly on keys (eg. to bind additional // revocation keys). } else if current == nil { return nil, errors.StructuralError("signature packet found before user id packet") } else { 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, errors.StructuralError("entity without any identities") } for _, revocation := range revocations { err = e.PrimaryKey.VerifyRevocationSignature(revocation) if err == nil { e.Revocations = append(e.Revocations, revocation) } else { // TODO: RFC 4880 5.2.3.15 defines revocation keys. return nil, errors.StructuralError("revocation signature signed by alternate key") } } return e, nil } func addSubkey(e *Entity, packets *packet.Reader, pub *packet.PublicKey, priv *packet.PrivateKey) error { var subKey Subkey subKey.PublicKey = pub subKey.PrivateKey = priv p, err := packets.Next() if err == io.EOF { return io.ErrUnexpectedEOF } if err != nil { return errors.StructuralError("subkey signature invalid: " + err.Error()) } var ok bool subKey.Sig, ok = p.(*packet.Signature) if !ok { return errors.StructuralError("subkey packet not followed by signature") } if subKey.Sig.SigType != packet.SigTypeSubkeyBinding && subKey.Sig.SigType != packet.SigTypeSubkeyRevocation { return errors.StructuralError("subkey signature with wrong type") } err = e.PrimaryKey.VerifyKeySignature(subKey.PublicKey, subKey.Sig) if err != nil { return errors.StructuralError("subkey signature invalid: " + err.Error()) } e.Subkeys = append(e.Subkeys, subKey) return nil } const defaultRSAKeyBits = 2048 // NewEntity returns an Entity that contains a fresh RSA/RSA keypair with a // single identity composed of the given full name, comment and email, any of // which may be empty but must not contain any of "()<>\x00". // If config is nil, sensible defaults will be used. func NewEntity(name, comment, email string, config *packet.Config) (*Entity, error) { currentTime := config.Now() bits := defaultRSAKeyBits if config != nil && config.RSABits != 0 { bits = config.RSABits } uid := packet.NewUserId(name, comment, email) if uid == nil { return nil, errors.InvalidArgumentError("user id field contained invalid characters") } signingPriv, err := rsa.GenerateKey(config.Random(), bits) if err != nil { return nil, err } encryptingPriv, err := rsa.GenerateKey(config.Random(), bits) if err != nil { return nil, err } e := &Entity{ PrimaryKey: packet.NewRSAPublicKey(currentTime, &signingPriv.PublicKey), PrivateKey: packet.NewRSAPrivateKey(currentTime, signingPriv), Identities: make(map[string]*Identity), } isPrimaryId := true e.Identities[uid.Id] = &Identity{ Name: uid.Name, UserId: uid, SelfSignature: &packet.Signature{ CreationTime: currentTime, SigType: packet.SigTypePositiveCert, PubKeyAlgo: packet.PubKeyAlgoRSA, Hash: config.Hash(), IsPrimaryId: &isPrimaryId, FlagsValid: true, FlagSign: true, FlagCertify: true, IssuerKeyId: &e.PrimaryKey.KeyId, }, } e.Subkeys = make([]Subkey, 1) e.Subkeys[0] = Subkey{ PublicKey: packet.NewRSAPublicKey(currentTime, &encryptingPriv.PublicKey), PrivateKey: packet.NewRSAPrivateKey(currentTime, encryptingPriv), Sig: &packet.Signature{ CreationTime: currentTime, SigType: packet.SigTypeSubkeyBinding, PubKeyAlgo: packet.PubKeyAlgoRSA, Hash: config.Hash(), FlagsValid: true, FlagEncryptStorage: true, FlagEncryptCommunications: true, IssuerKeyId: &e.PrimaryKey.KeyId, }, } e.Subkeys[0].PublicKey.IsSubkey = true e.Subkeys[0].PrivateKey.IsSubkey = true return e, nil } // SerializePrivate serializes an Entity, including private key material, to // the given Writer. For now, it must only be used on an Entity returned from // NewEntity. // If config is nil, sensible defaults will be used. func (e *Entity) SerializePrivate(w io.Writer, config *packet.Config) (err error) { err = e.PrivateKey.Serialize(w) if err != nil { return } for _, ident := range e.Identities { err = ident.UserId.Serialize(w) if err != nil { return } err = ident.SelfSignature.SignUserId(ident.UserId.Id, e.PrimaryKey, e.PrivateKey, config) if err != nil { return } err = ident.SelfSignature.Serialize(w) if err != nil { return } } for _, subkey := range e.Subkeys { err = subkey.PrivateKey.Serialize(w) if err != nil { return } err = subkey.Sig.SignKey(subkey.PublicKey, e.PrivateKey, config) if err != nil { return } err = subkey.Sig.Serialize(w) if err != nil { return } } return nil } // Serialize writes the public part of the given Entity to w. (No private // key material will be output). func (e *Entity) Serialize(w io.Writer) error { err := e.PrimaryKey.Serialize(w) if err != nil { return err } for _, ident := range e.Identities { err = ident.UserId.Serialize(w) if err != nil { return err } err = ident.SelfSignature.Serialize(w) if err != nil { return err } for _, sig := range ident.Signatures { err = sig.Serialize(w) if err != nil { return err } } } for _, subkey := range e.Subkeys { err = subkey.PublicKey.Serialize(w) if err != nil { return err } err = subkey.Sig.Serialize(w) if err != nil { return err } } return nil } // SignIdentity adds a signature to e, from signer, attesting that identity is // associated with e. The provided identity must already be an element of // e.Identities and the private key of signer must have been decrypted if // necessary. // If config is nil, sensible defaults will be used. func (e *Entity) SignIdentity(identity string, signer *Entity, config *packet.Config) error { if signer.PrivateKey == nil { return errors.InvalidArgumentError("signing Entity must have a private key") } if signer.PrivateKey.Encrypted { return errors.InvalidArgumentError("signing Entity's private key must be decrypted") } ident, ok := e.Identities[identity] if !ok { return errors.InvalidArgumentError("given identity string not found in Entity") } sig := &packet.Signature{ SigType: packet.SigTypeGenericCert, PubKeyAlgo: signer.PrivateKey.PubKeyAlgo, Hash: config.Hash(), CreationTime: config.Now(), IssuerKeyId: &signer.PrivateKey.KeyId, } if err := sig.SignUserId(identity, e.PrimaryKey, signer.PrivateKey, config); err != nil { return err } ident.Signatures = append(ident.Signatures, sig) return nil } lxd-2.0.0/dist/src/golang.org/x/crypto/openpgp/clearsign/0000755061062106075000000000000012702772344025713 5ustar00stgraberdomain admins00000000000000lxd-2.0.0/dist/src/golang.org/x/crypto/openpgp/clearsign/clearsign.go0000644061062106075000000002267312702772344030223 0ustar00stgraberdomain admins00000000000000// Copyright 2012 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 clearsign generates and processes OpenPGP, clear-signed data. See // RFC 4880, section 7. // // Clearsigned messages are cryptographically signed, but the contents of the // message are kept in plaintext so that it can be read without special tools. package clearsign // import "golang.org/x/crypto/openpgp/clearsign" import ( "bufio" "bytes" "crypto" "hash" "io" "net/textproto" "strconv" "golang.org/x/crypto/openpgp/armor" "golang.org/x/crypto/openpgp/errors" "golang.org/x/crypto/openpgp/packet" ) // A Block represents a clearsigned message. A signature on a Block can // be checked by passing Bytes into openpgp.CheckDetachedSignature. type Block struct { Headers textproto.MIMEHeader // Optional message headers Plaintext []byte // The original message text Bytes []byte // The signed message ArmoredSignature *armor.Block // The signature block } // start is the marker which denotes the beginning of a clearsigned message. var start = []byte("\n-----BEGIN PGP SIGNED MESSAGE-----") // dashEscape is prefixed to any lines that begin with a hyphen so that they // can't be confused with endText. var dashEscape = []byte("- ") // endText is a marker which denotes the end of the message and the start of // an armored signature. var endText = []byte("-----BEGIN PGP SIGNATURE-----") // end is a marker which denotes the end of the armored signature. var end = []byte("\n-----END PGP SIGNATURE-----") var crlf = []byte("\r\n") var lf = byte('\n') // getLine returns the first \r\n or \n delineated line from the given byte // array. The line does not include the \r\n or \n. The remainder of the byte // array (also not including the new line bytes) is also returned and this will // always be smaller than the original argument. func getLine(data []byte) (line, rest []byte) { i := bytes.Index(data, []byte{'\n'}) var j int if i < 0 { i = len(data) j = i } else { j = i + 1 if i > 0 && data[i-1] == '\r' { i-- } } return data[0:i], data[j:] } // Decode finds the first clearsigned message in data and returns it, as well // as the suffix of data which remains after the message. func Decode(data []byte) (b *Block, rest []byte) { // start begins with a newline. However, at the very beginning of // the byte array, we'll accept the start string without it. rest = data if bytes.HasPrefix(data, start[1:]) { rest = rest[len(start)-1:] } else if i := bytes.Index(data, start); i >= 0 { rest = rest[i+len(start):] } else { return nil, data } // Consume the start line. _, rest = getLine(rest) var line []byte b = &Block{ Headers: make(textproto.MIMEHeader), } // Next come a series of header lines. for { // This loop terminates because getLine's second result is // always smaller than its argument. if len(rest) == 0 { return nil, data } // An empty line marks the end of the headers. if line, rest = getLine(rest); len(line) == 0 { break } i := bytes.Index(line, []byte{':'}) if i == -1 { return nil, data } key, val := line[0:i], line[i+1:] key = bytes.TrimSpace(key) val = bytes.TrimSpace(val) b.Headers.Add(string(key), string(val)) } firstLine := true for { start := rest line, rest = getLine(rest) if len(line) == 0 && len(rest) == 0 { // No armored data was found, so this isn't a complete message. return nil, data } if bytes.Equal(line, endText) { // Back up to the start of the line because armor expects to see the // header line. rest = start break } // The final CRLF isn't included in the hash so we don't write it until // we've seen the next line. if firstLine { firstLine = false } else { b.Bytes = append(b.Bytes, crlf...) } if bytes.HasPrefix(line, dashEscape) { line = line[2:] } line = bytes.TrimRight(line, " \t") b.Bytes = append(b.Bytes, line...) b.Plaintext = append(b.Plaintext, line...) b.Plaintext = append(b.Plaintext, lf) } // We want to find the extent of the armored data (including any newlines at // the end). i := bytes.Index(rest, end) if i == -1 { return nil, data } i += len(end) for i < len(rest) && (rest[i] == '\r' || rest[i] == '\n') { i++ } armored := rest[:i] rest = rest[i:] var err error b.ArmoredSignature, err = armor.Decode(bytes.NewBuffer(armored)) if err != nil { return nil, data } return b, rest } // A dashEscaper is an io.WriteCloser which processes the body of a clear-signed // message. The clear-signed message is written to buffered and a hash, suitable // for signing, is maintained in h. // // When closed, an armored signature is created and written to complete the // message. type dashEscaper struct { buffered *bufio.Writer h hash.Hash hashType crypto.Hash atBeginningOfLine bool isFirstLine bool whitespace []byte byteBuf []byte // a one byte buffer to save allocations privateKey *packet.PrivateKey config *packet.Config } func (d *dashEscaper) Write(data []byte) (n int, err error) { for _, b := range data { d.byteBuf[0] = b if d.atBeginningOfLine { // The final CRLF isn't included in the hash so we have to wait // until this point (the start of the next line) before writing it. if !d.isFirstLine { d.h.Write(crlf) } d.isFirstLine = false } // Any whitespace at the end of the line has to be removed so we // buffer it until we find out whether there's more on this line. if b == ' ' || b == '\t' || b == '\r' { d.whitespace = append(d.whitespace, b) d.atBeginningOfLine = false continue } if d.atBeginningOfLine { // At the beginning of a line, hyphens have to be escaped. if b == '-' { // The signature isn't calculated over the dash-escaped text so // the escape is only written to buffered. if _, err = d.buffered.Write(dashEscape); err != nil { return } d.h.Write(d.byteBuf) d.atBeginningOfLine = false } else if b == '\n' { // Nothing to do because we delay writing CRLF to the hash. } else { d.h.Write(d.byteBuf) d.atBeginningOfLine = false } if err = d.buffered.WriteByte(b); err != nil { return } } else { if b == '\n' { // We got a raw \n. Drop any trailing whitespace and write a // CRLF. d.whitespace = d.whitespace[:0] // We delay writing CRLF to the hash until the start of the // next line. if err = d.buffered.WriteByte(b); err != nil { return } d.atBeginningOfLine = true } else { // Any buffered whitespace wasn't at the end of the line so // we need to write it out. if len(d.whitespace) > 0 { d.h.Write(d.whitespace) if _, err = d.buffered.Write(d.whitespace); err != nil { return } d.whitespace = d.whitespace[:0] } d.h.Write(d.byteBuf) if err = d.buffered.WriteByte(b); err != nil { return } } } } n = len(data) return } func (d *dashEscaper) Close() (err error) { if !d.atBeginningOfLine { if err = d.buffered.WriteByte(lf); err != nil { return } } sig := new(packet.Signature) sig.SigType = packet.SigTypeText sig.PubKeyAlgo = d.privateKey.PubKeyAlgo sig.Hash = d.hashType sig.CreationTime = d.config.Now() sig.IssuerKeyId = &d.privateKey.KeyId if err = sig.Sign(d.h, d.privateKey, d.config); err != nil { return } out, err := armor.Encode(d.buffered, "PGP SIGNATURE", nil) if err != nil { return } if err = sig.Serialize(out); err != nil { return } if err = out.Close(); err != nil { return } if err = d.buffered.Flush(); err != nil { return } return } // Encode returns a WriteCloser which will clear-sign a message with privateKey // and write it to w. If config is nil, sensible defaults are used. func Encode(w io.Writer, privateKey *packet.PrivateKey, config *packet.Config) (plaintext io.WriteCloser, err error) { if privateKey.Encrypted { return nil, errors.InvalidArgumentError("signing key is encrypted") } hashType := config.Hash() name := nameOfHash(hashType) if len(name) == 0 { return nil, errors.UnsupportedError("unknown hash type: " + strconv.Itoa(int(hashType))) } if !hashType.Available() { return nil, errors.UnsupportedError("unsupported hash type: " + strconv.Itoa(int(hashType))) } h := hashType.New() buffered := bufio.NewWriter(w) // start has a \n at the beginning that we don't want here. if _, err = buffered.Write(start[1:]); err != nil { return } if err = buffered.WriteByte(lf); err != nil { return } if _, err = buffered.WriteString("Hash: "); err != nil { return } if _, err = buffered.WriteString(name); err != nil { return } if err = buffered.WriteByte(lf); err != nil { return } if err = buffered.WriteByte(lf); err != nil { return } plaintext = &dashEscaper{ buffered: buffered, h: h, hashType: hashType, atBeginningOfLine: true, isFirstLine: true, byteBuf: make([]byte, 1), privateKey: privateKey, config: config, } return } // nameOfHash returns the OpenPGP name for the given hash, or the empty string // if the name isn't known. See RFC 4880, section 9.4. func nameOfHash(h crypto.Hash) string { switch h { case crypto.MD5: return "MD5" case crypto.SHA1: return "SHA1" case crypto.RIPEMD160: return "RIPEMD160" case crypto.SHA224: return "SHA224" case crypto.SHA256: return "SHA256" case crypto.SHA384: return "SHA384" case crypto.SHA512: return "SHA512" } return "" } lxd-2.0.0/dist/src/golang.org/x/crypto/openpgp/clearsign/clearsign_test.go0000644061062106075000000001503012702772344031247 0ustar00stgraberdomain admins00000000000000// Copyright 2012 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 clearsign import ( "bytes" "golang.org/x/crypto/openpgp" "testing" ) func testParse(t *testing.T, input []byte, expected, expectedPlaintext string) { b, rest := Decode(input) if b == nil { t.Fatal("failed to decode clearsign message") } if !bytes.Equal(rest, []byte("trailing")) { t.Errorf("unexpected remaining bytes returned: %s", string(rest)) } if b.ArmoredSignature.Type != "PGP SIGNATURE" { t.Errorf("bad armor type, got:%s, want:PGP SIGNATURE", b.ArmoredSignature.Type) } if !bytes.Equal(b.Bytes, []byte(expected)) { t.Errorf("bad body, got:%x want:%x", b.Bytes, expected) } if !bytes.Equal(b.Plaintext, []byte(expectedPlaintext)) { t.Errorf("bad plaintext, got:%x want:%x", b.Plaintext, expectedPlaintext) } keyring, err := openpgp.ReadArmoredKeyRing(bytes.NewBufferString(signingKey)) if err != nil { t.Errorf("failed to parse public key: %s", err) } if _, err := openpgp.CheckDetachedSignature(keyring, bytes.NewBuffer(b.Bytes), b.ArmoredSignature.Body); err != nil { t.Errorf("failed to check signature: %s", err) } } func TestParse(t *testing.T) { testParse(t, clearsignInput, "Hello world\r\nline 2", "Hello world\nline 2\n") testParse(t, clearsignInput2, "\r\n\r\n(This message has a couple of blank lines at the start and end.)\r\n\r\n", "\n\n(This message has a couple of blank lines at the start and end.)\n\n\n") } func TestParseInvalid(t *testing.T) { if b, _ := Decode(clearsignInput3); b != nil { t.Fatal("decoded a bad clearsigned message without any error") } } func TestParseWithNoNewlineAtEnd(t *testing.T) { input := clearsignInput input = input[:len(input)-len("trailing")-1] b, rest := Decode(input) if b == nil { t.Fatal("failed to decode clearsign message") } if len(rest) > 0 { t.Errorf("unexpected remaining bytes returned: %s", string(rest)) } } var signingTests = []struct { in, signed, plaintext string }{ {"", "", ""}, {"a", "a", "a\n"}, {"a\n", "a", "a\n"}, {"-a\n", "-a", "-a\n"}, {"--a\nb", "--a\r\nb", "--a\nb\n"}, // leading whitespace {" a\n", " a", " a\n"}, {" a\n", " a", " a\n"}, // trailing whitespace (should be stripped) {"a \n", "a", "a\n"}, {"a ", "a", "a\n"}, // whitespace-only lines (should be stripped) {" \n", "", "\n"}, {" ", "", "\n"}, {"a\n \n \nb\n", "a\r\n\r\n\r\nb", "a\n\n\nb\n"}, } func TestSigning(t *testing.T) { keyring, err := openpgp.ReadArmoredKeyRing(bytes.NewBufferString(signingKey)) if err != nil { t.Errorf("failed to parse public key: %s", err) } for i, test := range signingTests { var buf bytes.Buffer plaintext, err := Encode(&buf, keyring[0].PrivateKey, nil) if err != nil { t.Errorf("#%d: error from Encode: %s", i, err) continue } if _, err := plaintext.Write([]byte(test.in)); err != nil { t.Errorf("#%d: error from Write: %s", i, err) continue } if err := plaintext.Close(); err != nil { t.Fatalf("#%d: error from Close: %s", i, err) continue } b, _ := Decode(buf.Bytes()) if b == nil { t.Errorf("#%d: failed to decode clearsign message", i) continue } if !bytes.Equal(b.Bytes, []byte(test.signed)) { t.Errorf("#%d: bad result, got:%x, want:%x", i, b.Bytes, test.signed) continue } if !bytes.Equal(b.Plaintext, []byte(test.plaintext)) { t.Errorf("#%d: bad result, got:%x, want:%x", i, b.Plaintext, test.plaintext) continue } if _, err := openpgp.CheckDetachedSignature(keyring, bytes.NewBuffer(b.Bytes), b.ArmoredSignature.Body); err != nil { t.Errorf("#%d: failed to check signature: %s", i, err) } } } var clearsignInput = []byte(` ;lasjlkfdsa -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Hello world line 2 -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.10 (GNU/Linux) iJwEAQECAAYFAk8kMuEACgkQO9o98PRieSpMsAQAhmY/vwmNpflrPgmfWsYhk5O8 pjnBUzZwqTDoDeINjZEoPDSpQAHGhjFjgaDx/Gj4fAl0dM4D0wuUEBb6QOrwflog 2A2k9kfSOMOtk0IH/H5VuFN1Mie9L/erYXjTQIptv9t9J7NoRBMU0QOOaFU0JaO9 MyTpno24AjIAGb+mH1U= =hIJ6 -----END PGP SIGNATURE----- trailing`) var clearsignInput2 = []byte(` asdlfkjasdlkfjsadf -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA256 (This message has a couple of blank lines at the start and end.) -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.11 (GNU/Linux) iJwEAQEIAAYFAlPpSREACgkQO9o98PRieSpZTAP+M8QUoCt/7Rf3YbXPcdzIL32v pt1I+cMNeopzfLy0u4ioEFi8s5VkwpL1AFmirvgViCwlf82inoRxzZRiW05JQ5LI ESEzeCoy2LIdRCQ2hcrG8pIUPzUO4TqO5D/dMbdHwNH4h5nNmGJUAEG6FpURlPm+ qZg6BaTvOxepqOxnhVU= =e+C6 -----END PGP SIGNATURE----- trailing`) var clearsignInput3 = []byte(` -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA256 (This message was truncated.) `) var signingKey = `-----BEGIN PGP PRIVATE KEY BLOCK----- Version: GnuPG v1.4.10 (GNU/Linux) lQHYBE2rFNoBBADFwqWQIW/DSqcB4yCQqnAFTJ27qS5AnB46ccAdw3u4Greeu3Bp idpoHdjULy7zSKlwR1EA873dO/k/e11Ml3dlAFUinWeejWaK2ugFP6JjiieSsrKn vWNicdCS4HTWn0X4sjl0ZiAygw6GNhqEQ3cpLeL0g8E9hnYzJKQ0LWJa0QARAQAB AAP/TB81EIo2VYNmTq0pK1ZXwUpxCrvAAIG3hwKjEzHcbQznsjNvPUihZ+NZQ6+X 0HCfPAdPkGDCLCb6NavcSW+iNnLTrdDnSI6+3BbIONqWWdRDYJhqZCkqmG6zqSfL IdkJgCw94taUg5BWP/AAeQrhzjChvpMQTVKQL5mnuZbUCeMCAN5qrYMP2S9iKdnk VANIFj7656ARKt/nf4CBzxcpHTyB8+d2CtPDKCmlJP6vL8t58Jmih+kHJMvC0dzn gr5f5+sCAOOe5gt9e0am7AvQWhdbHVfJU0TQJx+m2OiCJAqGTB1nvtBLHdJnfdC9 TnXXQ6ZXibqLyBies/xeY2sCKL5qtTMCAKnX9+9d/5yQxRyrQUHt1NYhaXZnJbHx q4ytu0eWz+5i68IYUSK69jJ1NWPM0T6SkqpB3KCAIv68VFm9PxqG1KmhSrQIVGVz dCBLZXmIuAQTAQIAIgUCTasU2gIbAwYLCQgHAwIGFQgCCQoLBBYCAwECHgECF4AA CgkQO9o98PRieSoLhgQAkLEZex02Qt7vGhZzMwuN0R22w3VwyYyjBx+fM3JFETy1 ut4xcLJoJfIaF5ZS38UplgakHG0FQ+b49i8dMij0aZmDqGxrew1m4kBfjXw9B/v+ eIqpODryb6cOSwyQFH0lQkXC040pjq9YqDsO5w0WYNXYKDnzRV0p4H1pweo2VDid AdgETasU2gEEAN46UPeWRqKHvA99arOxee38fBt2CI08iiWyI8T3J6ivtFGixSqV bRcPxYO/qLpVe5l84Nb3X71GfVXlc9hyv7CD6tcowL59hg1E/DC5ydI8K8iEpUmK /UnHdIY5h8/kqgGxkY/T/hgp5fRQgW1ZoZxLajVlMRZ8W4tFtT0DeA+JABEBAAEA A/0bE1jaaZKj6ndqcw86jd+QtD1SF+Cf21CWRNeLKnUds4FRRvclzTyUMuWPkUeX TaNNsUOFqBsf6QQ2oHUBBK4VCHffHCW4ZEX2cd6umz7mpHW6XzN4DECEzOVksXtc lUC1j4UB91DC/RNQqwX1IV2QLSwssVotPMPqhOi0ZLNY7wIA3n7DWKInxYZZ4K+6 rQ+POsz6brEoRHwr8x6XlHenq1Oki855pSa1yXIARoTrSJkBtn5oI+f8AzrnN0BN oyeQAwIA/7E++3HDi5aweWrViiul9cd3rcsS0dEnksPhvS0ozCJiHsq/6GFmy7J8 QSHZPteedBnZyNp5jR+H7cIfVN3KgwH/Skq4PsuPhDq5TKK6i8Pc1WW8MA6DXTdU nLkX7RGmMwjC0DBf7KWAlPjFaONAX3a8ndnz//fy1q7u2l9AZwrj1qa1iJ8EGAEC AAkFAk2rFNoCGwwACgkQO9o98PRieSo2/QP/WTzr4ioINVsvN1akKuekmEMI3LAp BfHwatufxxP1U+3Si/6YIk7kuPB9Hs+pRqCXzbvPRrI8NHZBmc8qIGthishdCYad AHcVnXjtxrULkQFGbGvhKURLvS9WnzD/m1K2zzwxzkPTzT9/Yf06O6Mal5AdugPL VrM0m72/jnpKo04= =zNCn -----END PGP PRIVATE KEY BLOCK----- ` lxd-2.0.0/dist/src/golang.org/x/crypto/openpgp/s2k/0000755061062106075000000000000012702772344024443 5ustar00stgraberdomain admins00000000000000lxd-2.0.0/dist/src/golang.org/x/crypto/openpgp/s2k/s2k_test.go0000644061062106075000000000625412702772344026537 0ustar00stgraberdomain admins00000000000000// 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 s2k import ( "bytes" "crypto" _ "crypto/md5" "crypto/rand" "crypto/sha1" _ "crypto/sha256" _ "crypto/sha512" "encoding/hex" "testing" _ "golang.org/x/crypto/ripemd160" ) var saltedTests = []struct { in, out string }{ {"hello", "10295ac1"}, {"world", "ac587a5e"}, {"foo", "4dda8077"}, {"bar", "bd8aac6b9ea9cae04eae6a91c6133b58b5d9a61c14f355516ed9370456"}, {"x", "f1d3f289"}, {"xxxxxxxxxxxxxxxxxxxxxxx", "e00d7b45"}, } func TestSalted(t *testing.T) { h := sha1.New() salt := [4]byte{1, 2, 3, 4} for i, test := range saltedTests { expected, _ := hex.DecodeString(test.out) out := make([]byte, len(expected)) Salted(out, h, []byte(test.in), salt[:]) if !bytes.Equal(expected, out) { t.Errorf("#%d, got: %x want: %x", i, out, expected) } } } var iteratedTests = []struct { in, out string }{ {"hello", "83126105"}, {"world", "6fa317f9"}, {"foo", "8fbc35b9"}, {"bar", "2af5a99b54f093789fd657f19bd245af7604d0f6ae06f66602a46a08ae"}, {"x", "5a684dfe"}, {"xxxxxxxxxxxxxxxxxxxxxxx", "18955174"}, } func TestIterated(t *testing.T) { h := sha1.New() salt := [4]byte{4, 3, 2, 1} for i, test := range iteratedTests { expected, _ := hex.DecodeString(test.out) out := make([]byte, len(expected)) Iterated(out, h, []byte(test.in), salt[:], 31) if !bytes.Equal(expected, out) { t.Errorf("#%d, got: %x want: %x", i, out, expected) } } } var parseTests = []struct { spec, in, out string }{ /* Simple with SHA1 */ {"0002", "hello", "aaf4c61d"}, /* Salted with SHA1 */ {"01020102030405060708", "hello", "f4f7d67e"}, /* Iterated with SHA1 */ {"03020102030405060708f1", "hello", "f2a57b7c"}, } func TestParse(t *testing.T) { for i, test := range parseTests { spec, _ := hex.DecodeString(test.spec) buf := bytes.NewBuffer(spec) f, err := Parse(buf) if err != nil { t.Errorf("%d: Parse returned error: %s", i, err) continue } expected, _ := hex.DecodeString(test.out) out := make([]byte, len(expected)) f(out, []byte(test.in)) if !bytes.Equal(out, expected) { t.Errorf("%d: output got: %x want: %x", i, out, expected) } if testing.Short() { break } } } func TestSerialize(t *testing.T) { hashes := []crypto.Hash{crypto.MD5, crypto.SHA1, crypto.RIPEMD160, crypto.SHA256, crypto.SHA384, crypto.SHA512, crypto.SHA224} testCounts := []int{-1, 0, 1024, 65536, 4063232, 65011712} for _, h := range hashes { for _, c := range testCounts { testSerializeConfig(t, &Config{Hash: h, S2KCount: c}) } } } func testSerializeConfig(t *testing.T, c *Config) { t.Logf("Running testSerializeConfig() with config: %+v", c) buf := bytes.NewBuffer(nil) key := make([]byte, 16) passphrase := []byte("testing") err := Serialize(buf, key, rand.Reader, passphrase, c) if err != nil { t.Errorf("failed to serialize: %s", err) return } f, err := Parse(buf) if err != nil { t.Errorf("failed to reparse: %s", err) return } key2 := make([]byte, len(key)) f(key2, passphrase) if !bytes.Equal(key2, key) { t.Errorf("keys don't match: %x (serialied) vs %x (parsed)", key, key2) } } lxd-2.0.0/dist/src/golang.org/x/crypto/openpgp/s2k/s2k.go0000644061062106075000000001602712702772344025477 0ustar00stgraberdomain admins00000000000000// 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 s2k implements the various OpenPGP string-to-key transforms as // specified in RFC 4800 section 3.7.1. package s2k // import "golang.org/x/crypto/openpgp/s2k" import ( "crypto" "hash" "io" "strconv" "golang.org/x/crypto/openpgp/errors" ) // Config collects configuration parameters for s2k key-stretching // transformatioms. A nil *Config is valid and results in all default // values. Currently, Config is used only by the Serialize function in // this package. type Config struct { // Hash is the default hash function to be used. If // nil, SHA1 is used. Hash crypto.Hash // S2KCount is only used for symmetric encryption. It // determines the strength of the passphrase stretching when // the said passphrase is hashed to produce a key. S2KCount // should be between 1024 and 65011712, inclusive. If Config // is nil or S2KCount is 0, the value 65536 used. Not all // values in the above range can be represented. S2KCount will // be rounded up to the next representable value if it cannot // be encoded exactly. When set, it is strongly encrouraged to // use a value that is at least 65536. See RFC 4880 Section // 3.7.1.3. S2KCount int } func (c *Config) hash() crypto.Hash { if c == nil || uint(c.Hash) == 0 { // SHA1 is the historical default in this package. return crypto.SHA1 } return c.Hash } func (c *Config) encodedCount() uint8 { if c == nil || c.S2KCount == 0 { return 96 // The common case. Correspoding to 65536 } i := c.S2KCount switch { // Behave like GPG. Should we make 65536 the lowest value used? case i < 1024: i = 1024 case i > 65011712: i = 65011712 } return encodeCount(i) } // encodeCount converts an iterative "count" in the range 1024 to // 65011712, inclusive, to an encoded count. The return value is the // octet that is actually stored in the GPG file. encodeCount panics // if i is not in the above range (encodedCount above takes care to // pass i in the correct range). See RFC 4880 Section 3.7.7.1. func encodeCount(i int) uint8 { if i < 1024 || i > 65011712 { panic("count arg i outside the required range") } for encoded := 0; encoded < 256; encoded++ { count := decodeCount(uint8(encoded)) if count >= i { return uint8(encoded) } } return 255 } // decodeCount returns the s2k mode 3 iterative "count" corresponding to // the encoded octet c. func decodeCount(c uint8) int { return (16 + int(c&15)) << (uint32(c>>4) + 6) } // Simple writes to out the result of computing the Simple S2K function (RFC // 4880, section 3.7.1.1) using the given hash and input passphrase. func Simple(out []byte, h hash.Hash, in []byte) { Salted(out, h, in, nil) } var zero [1]byte // Salted writes to out the result of computing the Salted S2K function (RFC // 4880, section 3.7.1.2) using the given hash, input passphrase and salt. func Salted(out []byte, h hash.Hash, in []byte, salt []byte) { done := 0 var digest []byte for i := 0; done < len(out); i++ { h.Reset() for j := 0; j < i; j++ { h.Write(zero[:]) } h.Write(salt) h.Write(in) digest = h.Sum(digest[:0]) n := copy(out[done:], digest) done += n } } // Iterated writes to out the result of computing the Iterated and Salted S2K // function (RFC 4880, section 3.7.1.3) using the given hash, input passphrase, // salt and iteration count. func Iterated(out []byte, h hash.Hash, in []byte, salt []byte, count int) { combined := make([]byte, len(in)+len(salt)) copy(combined, salt) copy(combined[len(salt):], in) if count < len(combined) { count = len(combined) } done := 0 var digest []byte for i := 0; done < len(out); i++ { h.Reset() for j := 0; j < i; j++ { h.Write(zero[:]) } written := 0 for written < count { if written+len(combined) > count { todo := count - written h.Write(combined[:todo]) written = count } else { h.Write(combined) written += len(combined) } } digest = h.Sum(digest[:0]) n := copy(out[done:], digest) done += n } } // Parse reads a binary specification for a string-to-key transformation from r // and returns a function which performs that transform. func Parse(r io.Reader) (f func(out, in []byte), err error) { var buf [9]byte _, err = io.ReadFull(r, buf[:2]) if err != nil { return } hash, ok := HashIdToHash(buf[1]) if !ok { return nil, errors.UnsupportedError("hash for S2K function: " + strconv.Itoa(int(buf[1]))) } if !hash.Available() { return nil, errors.UnsupportedError("hash not available: " + strconv.Itoa(int(hash))) } h := hash.New() switch buf[0] { case 0: f := func(out, in []byte) { Simple(out, h, in) } return f, nil case 1: _, err = io.ReadFull(r, buf[:8]) if err != nil { return } f := func(out, in []byte) { Salted(out, h, in, buf[:8]) } return f, nil case 3: _, err = io.ReadFull(r, buf[:9]) if err != nil { return } count := decodeCount(buf[8]) f := func(out, in []byte) { Iterated(out, h, in, buf[:8], count) } return f, nil } return nil, errors.UnsupportedError("S2K function") } // Serialize salts and stretches the given passphrase and writes the // resulting key into key. It also serializes an S2K descriptor to // w. The key stretching can be configured with c, which may be // nil. In that case, sensible defaults will be used. func Serialize(w io.Writer, key []byte, rand io.Reader, passphrase []byte, c *Config) error { var buf [11]byte buf[0] = 3 /* iterated and salted */ buf[1], _ = HashToHashId(c.hash()) salt := buf[2:10] if _, err := io.ReadFull(rand, salt); err != nil { return err } encodedCount := c.encodedCount() count := decodeCount(encodedCount) buf[10] = encodedCount if _, err := w.Write(buf[:]); err != nil { return err } Iterated(key, c.hash().New(), passphrase, salt, count) return nil } // hashToHashIdMapping contains pairs relating OpenPGP's hash identifier with // Go's crypto.Hash type. See RFC 4880, section 9.4. var hashToHashIdMapping = []struct { id byte hash crypto.Hash name string }{ {1, crypto.MD5, "MD5"}, {2, crypto.SHA1, "SHA1"}, {3, crypto.RIPEMD160, "RIPEMD160"}, {8, crypto.SHA256, "SHA256"}, {9, crypto.SHA384, "SHA384"}, {10, crypto.SHA512, "SHA512"}, {11, crypto.SHA224, "SHA224"}, } // HashIdToHash returns a crypto.Hash which corresponds to the given OpenPGP // hash id. func HashIdToHash(id byte) (h crypto.Hash, ok bool) { for _, m := range hashToHashIdMapping { if m.id == id { return m.hash, true } } return 0, false } // HashIdToString returns the name of the hash function corresponding to the // given OpenPGP hash id, or panics if id is unknown. func HashIdToString(id byte) (name string, ok bool) { for _, m := range hashToHashIdMapping { if m.id == id { return m.name, true } } return "", 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 } lxd-2.0.0/dist/src/golang.org/x/crypto/openpgp/read.go0000644061062106075000000003241612702772344025214 0ustar00stgraberdomain admins00000000000000// 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 implements high level operations on OpenPGP messages. package openpgp // import "golang.org/x/crypto/openpgp" import ( "crypto" _ "crypto/sha256" "hash" "io" "strconv" "golang.org/x/crypto/openpgp/armor" "golang.org/x/crypto/openpgp/errors" "golang.org/x/crypto/openpgp/packet" ) // 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 error) { block, err := armor.Decode(r) if err != nil { return } if block.Type != expectedType { return nil, errors.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 available. 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 error // nil if the signature is good. Signature *packet.Signature // the signature packet itself, if v4 (default) SignatureV3 *packet.SignatureV3 // the signature packet if it is a v2 or v3 signature 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, 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. // If config is nil, sensible defaults will be used. func ReadMessage(r io.Reader, keyring KeyRing, prompt PromptFunction, config *packet.Config) (md *MessageDetails, err 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) switch p.Algo { case packet.PubKeyAlgoRSA, packet.PubKeyAlgoRSAEncryptOnly, packet.PubKeyAlgoElGamal: break default: 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, errors.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 available 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.Decrypt(pk.key.PrivateKey, config) } if len(pk.encryptedKey.Key) == 0 { continue } decrypted, err = se.Decrypt(pk.encryptedKey.CipherFunc, pk.encryptedKey.Key) if err != nil && err != errors.ErrKeyIncorrect { 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, errors.ErrKeyIncorrect } if prompt == nil { return nil, errors.ErrKeyIncorrect } 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 { key, cipherFunc, err := s.Decrypt(passphrase) if err == nil { decrypted, err = se.Decrypt(cipherFunc, key) if err != nil && err != errors.ErrKeyIncorrect { return nil, err } if decrypted != nil { break FindKey } } } } } md.decrypted = decrypted if err := packets.Push(decrypted); err != nil { return nil, err } return readSignedMessage(packets, md, keyring) } // readSignedMessage reads a possibly 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 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: if err := packets.Push(p.Body); err != nil { return nil, err } case *packet.OnePassSignature: if !p.IsLast { return nil, errors.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.KeysByIdUsage(p.KeyId, packet.KeyFlagSign) if len(keys) > 0 { md.SignedBy = &keys[0] } 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 normalize 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, error) { if !hashId.Available() { return nil, nil, errors.UnsupportedError("hash not available: " + strconv.Itoa(int(hashId))) } h := hashId.New() switch sigType { case packet.SigTypeBinary: return h, h, nil case packet.SigTypeText: return h, NewCanonicalTextHash(h), nil } return nil, nil, errors.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 error) { n, err = cr.md.LiteralData.Body.Read(buf) if err == io.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 error) { n, err = scr.md.LiteralData.Body.Read(buf) scr.wrappedHash.Write(buf[:n]) if err == io.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 = scr.md.SignedBy.PublicKey.VerifySignature(scr.h, scr.md.Signature) } else if scr.md.SignatureV3, ok = p.(*packet.SignatureV3); ok { scr.md.SignatureError = scr.md.SignedBy.PublicKey.VerifySignatureV3(scr.h, scr.md.SignatureV3) } else { scr.md.SignatureError = errors.StructuralError("LiteralData not followed by Signature") return } // 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 known, // ErrUnknownIssuer is returned. func CheckDetachedSignature(keyring KeyRing, signed, signature io.Reader) (signer *Entity, err error) { var issuerKeyId uint64 var hashFunc crypto.Hash var sigType packet.SignatureType var keys []Key var p packet.Packet packets := packet.NewReader(signature) for { p, err = packets.Next() if err == io.EOF { return nil, errors.ErrUnknownIssuer } if err != nil { return nil, err } switch sig := p.(type) { case *packet.Signature: if sig.IssuerKeyId == nil { return nil, errors.StructuralError("signature doesn't have an issuer") } issuerKeyId = *sig.IssuerKeyId hashFunc = sig.Hash sigType = sig.SigType case *packet.SignatureV3: issuerKeyId = sig.IssuerKeyId hashFunc = sig.Hash sigType = sig.SigType default: return nil, errors.StructuralError("non signature packet found") } keys = keyring.KeysByIdUsage(issuerKeyId, packet.KeyFlagSign) if len(keys) > 0 { break } } if len(keys) == 0 { panic("unreachable") } h, wrappedHash, err := hashForSignature(hashFunc, sigType) if err != nil { return nil, err } if _, err := io.Copy(wrappedHash, signed); err != nil && err != io.EOF { return nil, err } for _, key := range keys { switch sig := p.(type) { case *packet.Signature: err = key.PublicKey.VerifySignature(h, sig) case *packet.SignatureV3: err = key.PublicKey.VerifySignatureV3(h, sig) default: panic("unreachable") } if err == nil { return key.Entity, nil } } return nil, err } // 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 error) { body, err := readArmored(signature, SignatureType) if err != nil { return } return CheckDetachedSignature(keyring, signed, body) } lxd-2.0.0/dist/src/golang.org/x/crypto/openpgp/canonical_text_test.go0000644061062106075000000000226212702772344030327 0ustar00stgraberdomain admins00000000000000// 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" ) type recordingHash struct { buf *bytes.Buffer } func (r recordingHash) Write(b []byte) (n int, err error) { return r.buf.Write(b) } func (r recordingHash) Sum(in []byte) []byte { return append(in, r.buf.Bytes()...) } func (r recordingHash) Reset() { panic("shouldn't be called") } func (r recordingHash) Size() int { panic("shouldn't be called") } func (r recordingHash) BlockSize() 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(nil) 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") } lxd-2.0.0/dist/src/golang.org/x/crypto/openpgp/elgamal/0000755061062106075000000000000012702772344025346 5ustar00stgraberdomain admins00000000000000lxd-2.0.0/dist/src/golang.org/x/crypto/openpgp/elgamal/elgamal.go0000644061062106075000000000672712702772344027313 0ustar00stgraberdomain admins00000000000000// 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 elgamal implements ElGamal encryption, suitable for OpenPGP, // as specified in "A Public-Key Cryptosystem and a Signature Scheme Based on // Discrete Logarithms," IEEE Transactions on Information Theory, v. IT-31, // n. 4, 1985, pp. 469-472. // // This form of ElGamal embeds PKCS#1 v1.5 padding, which may make it // unsuitable for other protocols. RSA should be used in preference in any // case. package elgamal // import "golang.org/x/crypto/openpgp/elgamal" import ( "crypto/rand" "crypto/subtle" "errors" "io" "math/big" ) // PublicKey represents an ElGamal public key. type PublicKey struct { G, P, Y *big.Int } // PrivateKey represents an ElGamal private key. type PrivateKey struct { PublicKey X *big.Int } // Encrypt encrypts the given message to the given public key. The result is a // pair of integers. Errors can result from reading random, or because msg is // too large to be encrypted to the public key. func Encrypt(random io.Reader, pub *PublicKey, msg []byte) (c1, c2 *big.Int, err error) { pLen := (pub.P.BitLen() + 7) / 8 if len(msg) > pLen-11 { err = errors.New("elgamal: message too long") return } // EM = 0x02 || PS || 0x00 || M em := make([]byte, pLen-1) em[0] = 2 ps, mm := em[1:len(em)-len(msg)-1], em[len(em)-len(msg):] err = nonZeroRandomBytes(ps, random) if err != nil { return } em[len(em)-len(msg)-1] = 0 copy(mm, msg) m := new(big.Int).SetBytes(em) k, err := rand.Int(random, pub.P) if err != nil { return } c1 = new(big.Int).Exp(pub.G, k, pub.P) s := new(big.Int).Exp(pub.Y, k, pub.P) c2 = s.Mul(s, m) c2.Mod(c2, pub.P) return } // Decrypt takes two integers, resulting from an ElGamal encryption, and // returns the plaintext of the message. An error can result only if the // ciphertext is invalid. Users should keep in mind that this is a padding // oracle and thus, if exposed to an adaptive chosen ciphertext attack, can // be used to break the cryptosystem. See ``Chosen Ciphertext Attacks // Against Protocols Based on the RSA Encryption Standard PKCS #1'', Daniel // Bleichenbacher, Advances in Cryptology (Crypto '98), func Decrypt(priv *PrivateKey, c1, c2 *big.Int) (msg []byte, err error) { s := new(big.Int).Exp(c1, priv.X, priv.P) s.ModInverse(s, priv.P) s.Mul(s, c2) s.Mod(s, priv.P) em := s.Bytes() firstByteIsTwo := subtle.ConstantTimeByteEq(em[0], 2) // The remainder of the plaintext must be a string of non-zero random // octets, followed by a 0, followed by the message. // lookingForIndex: 1 iff we are still looking for the zero. // index: the offset of the first zero byte. var lookingForIndex, index int lookingForIndex = 1 for i := 1; i < len(em); i++ { equals0 := subtle.ConstantTimeByteEq(em[i], 0) index = subtle.ConstantTimeSelect(lookingForIndex&equals0, i, index) lookingForIndex = subtle.ConstantTimeSelect(equals0, 0, lookingForIndex) } if firstByteIsTwo != 1 || lookingForIndex != 0 || index < 9 { return nil, errors.New("elgamal: decryption error") } return em[index+1:], nil } // nonZeroRandomBytes fills the given slice with non-zero random octets. func nonZeroRandomBytes(s []byte, rand io.Reader) (err error) { _, err = io.ReadFull(rand, s) if err != nil { return } for i := 0; i < len(s); i++ { for s[i] == 0 { _, err = io.ReadFull(rand, s[i:i+1]) if err != nil { return } } } return } lxd-2.0.0/dist/src/golang.org/x/crypto/openpgp/elgamal/elgamal_test.go0000644061062106075000000000306512702772344030342 0ustar00stgraberdomain admins00000000000000// 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 elgamal import ( "bytes" "crypto/rand" "math/big" "testing" ) // This is the 1024-bit MODP group from RFC 5114, section 2.1: const primeHex = "B10B8F96A080E01DDE92DE5EAE5D54EC52C99FBCFB06A3C69A6A9DCA52D23B616073E28675A23D189838EF1E2EE652C013ECB4AEA906112324975C3CD49B83BFACCBDD7D90C4BD7098488E9C219A73724EFFD6FAE5644738FAA31A4FF55BCCC0A151AF5F0DC8B4BD45BF37DF365C1A65E68CFDA76D4DA708DF1FB2BC2E4A4371" const generatorHex = "A4D1CBD5C3FD34126765A442EFB99905F8104DD258AC507FD6406CFF14266D31266FEA1E5C41564B777E690F5504F213160217B4B01B886A5E91547F9E2749F4D7FBD7D3B9A92EE1909D0D2263F80A76A6A24C087A091F531DBF0A0169B6A28AD662A4D18E73AFA32D779D5918D08BC8858F4DCEF97C2A24855E6EEB22B3B2E5" func fromHex(hex string) *big.Int { n, ok := new(big.Int).SetString(hex, 16) if !ok { panic("failed to parse hex number") } return n } func TestEncryptDecrypt(t *testing.T) { priv := &PrivateKey{ PublicKey: PublicKey{ G: fromHex(generatorHex), P: fromHex(primeHex), }, X: fromHex("42"), } priv.Y = new(big.Int).Exp(priv.G, priv.X, priv.P) message := []byte("hello world") c1, c2, err := Encrypt(rand.Reader, &priv.PublicKey, message) if err != nil { t.Errorf("error encrypting: %s", err) } message2, err := Decrypt(priv, c1, c2) if err != nil { t.Errorf("error decrypting: %s", err) } if !bytes.Equal(message2, message) { t.Errorf("decryption failed, got: %x, want: %x", message2, message) } } lxd-2.0.0/dist/src/golang.org/x/crypto/openpgp/write.go0000644061062106075000000002662712702772344025442 0ustar00stgraberdomain admins00000000000000// 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" "hash" "io" "strconv" "time" "golang.org/x/crypto/openpgp/armor" "golang.org/x/crypto/openpgp/errors" "golang.org/x/crypto/openpgp/packet" "golang.org/x/crypto/openpgp/s2k" ) // DetachSign signs message with the private key from signer (which must // already have been decrypted) and writes the signature to w. // If config is nil, sensible defaults will be used. func DetachSign(w io.Writer, signer *Entity, message io.Reader, config *packet.Config) error { return detachSign(w, signer, message, packet.SigTypeBinary, config) } // ArmoredDetachSign signs message with the private key from signer (which // must already have been decrypted) and writes an armored signature to w. // If config is nil, sensible defaults will be used. func ArmoredDetachSign(w io.Writer, signer *Entity, message io.Reader, config *packet.Config) (err error) { return armoredDetachSign(w, signer, message, packet.SigTypeBinary, config) } // 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. // If config is nil, sensible defaults will be used. func DetachSignText(w io.Writer, signer *Entity, message io.Reader, config *packet.Config) error { return detachSign(w, signer, message, packet.SigTypeText, config) } // 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. // If config is nil, sensible defaults will be used. func ArmoredDetachSignText(w io.Writer, signer *Entity, message io.Reader, config *packet.Config) error { return armoredDetachSign(w, signer, message, packet.SigTypeText, config) } func armoredDetachSign(w io.Writer, signer *Entity, message io.Reader, sigType packet.SignatureType, config *packet.Config) (err error) { out, err := armor.Encode(w, SignatureType, nil) if err != nil { return } err = detachSign(out, signer, message, sigType, config) if err != nil { return } return out.Close() } func detachSign(w io.Writer, signer *Entity, message io.Reader, sigType packet.SignatureType, config *packet.Config) (err error) { if signer.PrivateKey == nil { return errors.InvalidArgumentError("signing key doesn't have a private key") } if signer.PrivateKey.Encrypted { return errors.InvalidArgumentError("signing key is encrypted") } sig := new(packet.Signature) sig.SigType = sigType sig.PubKeyAlgo = signer.PrivateKey.PubKeyAlgo sig.Hash = config.Hash() sig.CreationTime = config.Now() sig.IssuerKeyId = &signer.PrivateKey.KeyId h, wrappedHash, err := hashForSignature(sig.Hash, sig.SigType) if err != nil { return } io.Copy(wrappedHash, message) err = sig.Sign(h, signer.PrivateKey, config) if err != nil { return } return sig.Serialize(w) } // FileHints contains metadata about encrypted files. This metadata is, itself, // encrypted. type FileHints struct { // IsBinary can be set to hint that the contents are binary data. IsBinary bool // FileName hints at the name of the file that should be written. It's // truncated to 255 bytes if longer. It may be empty to suggest that the // file should not be written to disk. It may be equal to "_CONSOLE" to // suggest the data should not be written to disk. FileName string // ModTime contains the modification time of the file, or the zero time if not applicable. ModTime time.Time } // SymmetricallyEncrypt acts like gpg -c: it encrypts a file with a passphrase. // The resulting WriteCloser must be closed after the contents of the file have // been written. // If config is nil, sensible defaults will be used. func SymmetricallyEncrypt(ciphertext io.Writer, passphrase []byte, hints *FileHints, config *packet.Config) (plaintext io.WriteCloser, err error) { if hints == nil { hints = &FileHints{} } key, err := packet.SerializeSymmetricKeyEncrypted(ciphertext, passphrase, config) if err != nil { return } w, err := packet.SerializeSymmetricallyEncrypted(ciphertext, config.Cipher(), key, config) if err != nil { return } literaldata := w if algo := config.Compression(); algo != packet.CompressionNone { var compConfig *packet.CompressionConfig if config != nil { compConfig = config.CompressionConfig } literaldata, err = packet.SerializeCompressed(w, algo, compConfig) if err != nil { return } } var epochSeconds uint32 if !hints.ModTime.IsZero() { epochSeconds = uint32(hints.ModTime.Unix()) } return packet.SerializeLiteral(literaldata, hints.IsBinary, hints.FileName, epochSeconds) } // intersectPreferences mutates and returns a prefix of a that contains only // the values in the intersection of a and b. The order of a is preserved. func intersectPreferences(a []uint8, b []uint8) (intersection []uint8) { var j int for _, v := range a { for _, v2 := range b { if v == v2 { a[j] = v j++ break } } } return a[:j] } func hashToHashId(h crypto.Hash) uint8 { v, ok := s2k.HashToHashId(h) if !ok { panic("tried to convert unknown hash") } return v } // Encrypt encrypts a message to a number of recipients and, optionally, signs // it. hints contains optional information, that is also encrypted, that aids // the recipients in processing the message. The resulting WriteCloser must // be closed after the contents of the file have been written. // If config is nil, sensible defaults will be used. func Encrypt(ciphertext io.Writer, to []*Entity, signed *Entity, hints *FileHints, config *packet.Config) (plaintext io.WriteCloser, err error) { var signer *packet.PrivateKey if signed != nil { signKey, ok := signed.signingKey(config.Now()) if !ok { return nil, errors.InvalidArgumentError("no valid signing keys") } signer = signKey.PrivateKey if signer == nil { return nil, errors.InvalidArgumentError("no private key in signing key") } if signer.Encrypted { return nil, errors.InvalidArgumentError("signing key must be decrypted") } } // These are the possible ciphers that we'll use for the message. candidateCiphers := []uint8{ uint8(packet.CipherAES128), uint8(packet.CipherAES256), uint8(packet.CipherCAST5), } // These are the possible hash functions that we'll use for the signature. candidateHashes := []uint8{ hashToHashId(crypto.SHA256), hashToHashId(crypto.SHA512), hashToHashId(crypto.SHA1), hashToHashId(crypto.RIPEMD160), } // In the event that a recipient doesn't specify any supported ciphers // or hash functions, these are the ones that we assume that every // implementation supports. defaultCiphers := candidateCiphers[len(candidateCiphers)-1:] defaultHashes := candidateHashes[len(candidateHashes)-1:] encryptKeys := make([]Key, len(to)) for i := range to { var ok bool encryptKeys[i], ok = to[i].encryptionKey(config.Now()) if !ok { return nil, errors.InvalidArgumentError("cannot encrypt a message to key id " + strconv.FormatUint(to[i].PrimaryKey.KeyId, 16) + " because it has no encryption keys") } sig := to[i].primaryIdentity().SelfSignature preferredSymmetric := sig.PreferredSymmetric if len(preferredSymmetric) == 0 { preferredSymmetric = defaultCiphers } preferredHashes := sig.PreferredHash if len(preferredHashes) == 0 { preferredHashes = defaultHashes } candidateCiphers = intersectPreferences(candidateCiphers, preferredSymmetric) candidateHashes = intersectPreferences(candidateHashes, preferredHashes) } if len(candidateCiphers) == 0 || len(candidateHashes) == 0 { return nil, errors.InvalidArgumentError("cannot encrypt because recipient set shares no common algorithms") } cipher := packet.CipherFunction(candidateCiphers[0]) // If the cipher specifed by config is a candidate, we'll use that. configuredCipher := config.Cipher() for _, c := range candidateCiphers { cipherFunc := packet.CipherFunction(c) if cipherFunc == configuredCipher { cipher = cipherFunc break } } var hash crypto.Hash for _, hashId := range candidateHashes { if h, ok := s2k.HashIdToHash(hashId); ok && h.Available() { hash = h break } } // If the hash specified by config is a candidate, we'll use that. if configuredHash := config.Hash(); configuredHash.Available() { for _, hashId := range candidateHashes { if h, ok := s2k.HashIdToHash(hashId); ok && h == configuredHash { hash = h break } } } if hash == 0 { hashId := candidateHashes[0] name, ok := s2k.HashIdToString(hashId) if !ok { name = "#" + strconv.Itoa(int(hashId)) } return nil, errors.InvalidArgumentError("cannot encrypt because no candidate hash functions are compiled in. (Wanted " + name + " in this case.)") } symKey := make([]byte, cipher.KeySize()) if _, err := io.ReadFull(config.Random(), symKey); err != nil { return nil, err } for _, key := range encryptKeys { if err := packet.SerializeEncryptedKey(ciphertext, key.PublicKey, cipher, symKey, config); err != nil { return nil, err } } encryptedData, err := packet.SerializeSymmetricallyEncrypted(ciphertext, cipher, symKey, config) if err != nil { return } if signer != nil { ops := &packet.OnePassSignature{ SigType: packet.SigTypeBinary, Hash: hash, PubKeyAlgo: signer.PubKeyAlgo, KeyId: signer.KeyId, IsLast: true, } if err := ops.Serialize(encryptedData); err != nil { return nil, err } } if hints == nil { hints = &FileHints{} } w := encryptedData if signer != nil { // If we need to write a signature packet after the literal // data then we need to stop literalData from closing // encryptedData. w = noOpCloser{encryptedData} } var epochSeconds uint32 if !hints.ModTime.IsZero() { epochSeconds = uint32(hints.ModTime.Unix()) } literalData, err := packet.SerializeLiteral(w, hints.IsBinary, hints.FileName, epochSeconds) if err != nil { return nil, err } if signer != nil { return signatureWriter{encryptedData, literalData, hash, hash.New(), signer, config}, nil } return literalData, nil } // signatureWriter hashes the contents of a message while passing it along to // literalData. When closed, it closes literalData, writes a signature packet // to encryptedData and then also closes encryptedData. type signatureWriter struct { encryptedData io.WriteCloser literalData io.WriteCloser hashType crypto.Hash h hash.Hash signer *packet.PrivateKey config *packet.Config } func (s signatureWriter) Write(data []byte) (int, error) { s.h.Write(data) return s.literalData.Write(data) } func (s signatureWriter) Close() error { sig := &packet.Signature{ SigType: packet.SigTypeBinary, PubKeyAlgo: s.signer.PubKeyAlgo, Hash: s.hashType, CreationTime: s.config.Now(), IssuerKeyId: &s.signer.KeyId, } if err := sig.Sign(s.h, s.signer, s.config); err != nil { return err } if err := s.literalData.Close(); err != nil { return err } if err := sig.Serialize(s.encryptedData); err != nil { return err } return s.encryptedData.Close() } // noOpCloser is like an ioutil.NopCloser, but for an io.Writer. // TODO: we have two of these in OpenPGP packages alone. This probably needs // to be promoted somewhere more common. type noOpCloser struct { w io.Writer } func (c noOpCloser) Write(data []byte) (n int, err error) { return c.w.Write(data) } func (c noOpCloser) Close() error { return nil } lxd-2.0.0/dist/src/golang.org/x/crypto/openpgp/read_test.go0000644061062106075000000012325512702772344026255 0ustar00stgraberdomain admins00000000000000// 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" _ "crypto/sha512" "encoding/hex" "io" "io/ioutil" "strings" "testing" "golang.org/x/crypto/openpgp/armor" "golang.org/x/crypto/openpgp/errors" ) func readerFromHex(s string) io.Reader { data, err := hex.DecodeString(s) if err != nil { panic("readerFromHex: bad input") } return bytes.NewBuffer(data) } func TestReadKeyRing(t *testing.T) { kring, err := ReadKeyRing(readerFromHex(testKeys1And2Hex)) if err != nil { t.Error(err) return } if len(kring) != 2 || uint32(kring[0].PrimaryKey.KeyId) != 0xC20C31BB || uint32(kring[1].PrimaryKey.KeyId) != 0x1E35246B { t.Errorf("bad keyring: %#v", kring) } } func TestRereadKeyRing(t *testing.T) { kring, err := ReadKeyRing(readerFromHex(testKeys1And2Hex)) if err != nil { t.Errorf("error in initial parse: %s", err) return } out := new(bytes.Buffer) err = kring[0].Serialize(out) if err != nil { t.Errorf("error in serialization: %s", err) return } kring, err = ReadKeyRing(out) if err != nil { t.Errorf("error in second parse: %s", err) return } if len(kring) != 1 || uint32(kring[0].PrimaryKey.KeyId) != 0xC20C31BB { t.Errorf("bad keyring: %#v", kring) } } func TestReadPrivateKeyRing(t *testing.T) { kring, err := ReadKeyRing(readerFromHex(testKeys1And2PrivateHex)) if err != nil { t.Error(err) return } if len(kring) != 2 || uint32(kring[0].PrimaryKey.KeyId) != 0xC20C31BB || uint32(kring[1].PrimaryKey.KeyId) != 0x1E35246B || kring[0].PrimaryKey == nil { t.Errorf("bad keyring: %#v", kring) } } func TestReadDSAKey(t *testing.T) { kring, err := ReadKeyRing(readerFromHex(dsaTestKeyHex)) if err != nil { t.Error(err) return } if len(kring) != 1 || uint32(kring[0].PrimaryKey.KeyId) != 0x0CCC0360 { t.Errorf("bad parse: %#v", kring) } } func TestReadP256Key(t *testing.T) { kring, err := ReadKeyRing(readerFromHex(p256TestKeyHex)) if err != nil { t.Error(err) return } if len(kring) != 1 || uint32(kring[0].PrimaryKey.KeyId) != 0x5918513E { t.Errorf("bad parse: %#v", kring) } } func TestDSAHashTruncatation(t *testing.T) { // dsaKeyWithSHA512 was generated with GnuPG and --cert-digest-algo // SHA512 in order to require DSA hash truncation to verify correctly. _, err := ReadKeyRing(readerFromHex(dsaKeyWithSHA512)) if err != nil { t.Error(err) } } func TestGetKeyById(t *testing.T) { kring, _ := ReadKeyRing(readerFromHex(testKeys1And2Hex)) keys := kring.KeysById(0xa34d7e18c20c31bb) if len(keys) != 1 || keys[0].Entity != kring[0] { t.Errorf("bad result for 0xa34d7e18c20c31bb: %#v", keys) } keys = kring.KeysById(0xfd94408d4543314f) if len(keys) != 1 || keys[0].Entity != kring[0] { t.Errorf("bad result for 0xa34d7e18c20c31bb: %#v", keys) } } func checkSignedMessage(t *testing.T, signedHex, expected string) { kring, _ := ReadKeyRing(readerFromHex(testKeys1And2Hex)) md, err := ReadMessage(readerFromHex(signedHex), kring, nil, nil) if err != nil { t.Error(err) return } if !md.IsSigned || md.SignedByKeyId != 0xa34d7e18c20c31bb || md.SignedBy == nil || md.IsEncrypted || md.IsSymmetricallyEncrypted || len(md.EncryptedToKeyIds) != 0 || md.IsSymmetricallyEncrypted { t.Errorf("bad MessageDetails: %#v", md) } contents, err := ioutil.ReadAll(md.UnverifiedBody) if err != nil { t.Errorf("error reading UnverifiedBody: %s", err) } if string(contents) != expected { t.Errorf("bad UnverifiedBody got:%s want:%s", string(contents), expected) } if md.SignatureError != nil || md.Signature == nil { t.Errorf("failed to validate: %s", md.SignatureError) } } func TestSignedMessage(t *testing.T) { checkSignedMessage(t, signedMessageHex, signedInput) } func TestTextSignedMessage(t *testing.T) { checkSignedMessage(t, signedTextMessageHex, signedTextInput) } // The reader should detect "compressed quines", which are compressed // packets that expand into themselves and cause an infinite recursive // parsing loop. // The packet in this test case comes from Taylor R. Campbell at // http://mumble.net/~campbell/misc/pgp-quine/ func TestCampbellQuine(t *testing.T) { md, err := ReadMessage(readerFromHex(campbellQuine), nil, nil, nil) if md != nil { t.Errorf("Reading a compressed quine should not return any data: %#v", md) } structural, ok := err.(errors.StructuralError) if !ok { t.Fatalf("Unexpected class of error: %T", err) } if !strings.Contains(string(structural), "too many layers of packets") { t.Fatalf("Unexpected error: %s", err) } } var signedEncryptedMessageTests = []struct { keyRingHex string messageHex string signedByKeyId uint64 encryptedToKeyId uint64 }{ { testKeys1And2PrivateHex, signedEncryptedMessageHex, 0xa34d7e18c20c31bb, 0x2a67d68660df41c7, }, { dsaElGamalTestKeysHex, signedEncryptedMessage2Hex, 0x33af447ccd759b09, 0xcf6a7abcd43e3673, }, } func TestSignedEncryptedMessage(t *testing.T) { for i, test := range signedEncryptedMessageTests { expected := "Signed and encrypted message\n" kring, _ := ReadKeyRing(readerFromHex(test.keyRingHex)) prompt := func(keys []Key, symmetric bool) ([]byte, error) { if symmetric { t.Errorf("prompt: message was marked as symmetrically encrypted") return nil, errors.ErrKeyIncorrect } if len(keys) == 0 { t.Error("prompt: no keys requested") return nil, errors.ErrKeyIncorrect } err := keys[0].PrivateKey.Decrypt([]byte("passphrase")) if err != nil { t.Errorf("prompt: error decrypting key: %s", err) return nil, errors.ErrKeyIncorrect } return nil, nil } md, err := ReadMessage(readerFromHex(test.messageHex), kring, prompt, nil) if err != nil { t.Errorf("#%d: error reading message: %s", i, err) return } if !md.IsSigned || md.SignedByKeyId != test.signedByKeyId || md.SignedBy == nil || !md.IsEncrypted || md.IsSymmetricallyEncrypted || len(md.EncryptedToKeyIds) == 0 || md.EncryptedToKeyIds[0] != test.encryptedToKeyId { t.Errorf("#%d: bad MessageDetails: %#v", i, md) } contents, err := ioutil.ReadAll(md.UnverifiedBody) if err != nil { t.Errorf("#%d: error reading UnverifiedBody: %s", i, err) } if string(contents) != expected { t.Errorf("#%d: bad UnverifiedBody got:%s want:%s", i, string(contents), expected) } if md.SignatureError != nil || md.Signature == nil { t.Errorf("#%d: failed to validate: %s", i, md.SignatureError) } } } func TestUnspecifiedRecipient(t *testing.T) { expected := "Recipient unspecified\n" kring, _ := ReadKeyRing(readerFromHex(testKeys1And2PrivateHex)) md, err := ReadMessage(readerFromHex(recipientUnspecifiedHex), kring, nil, nil) if err != nil { t.Errorf("error reading message: %s", err) return } contents, err := ioutil.ReadAll(md.UnverifiedBody) if err != nil { t.Errorf("error reading UnverifiedBody: %s", err) } if string(contents) != expected { t.Errorf("bad UnverifiedBody got:%s want:%s", string(contents), expected) } } func TestSymmetricallyEncrypted(t *testing.T) { firstTimeCalled := true prompt := func(keys []Key, symmetric bool) ([]byte, error) { if len(keys) != 0 { t.Errorf("prompt: len(keys) = %d (want 0)", len(keys)) } if !symmetric { t.Errorf("symmetric is not set") } if firstTimeCalled { firstTimeCalled = false return []byte("wrongpassword"), nil } return []byte("password"), nil } md, err := ReadMessage(readerFromHex(symmetricallyEncryptedCompressedHex), nil, prompt, nil) if err != nil { t.Errorf("ReadMessage: %s", err) return } contents, err := ioutil.ReadAll(md.UnverifiedBody) if err != nil { t.Errorf("ReadAll: %s", err) } expectedCreationTime := uint32(1295992998) if md.LiteralData.Time != expectedCreationTime { t.Errorf("LiteralData.Time is %d, want %d", md.LiteralData.Time, expectedCreationTime) } const expected = "Symmetrically encrypted.\n" if string(contents) != expected { t.Errorf("contents got: %s want: %s", string(contents), expected) } } func testDetachedSignature(t *testing.T, kring KeyRing, signature io.Reader, sigInput, tag string, expectedSignerKeyId uint64) { signed := bytes.NewBufferString(sigInput) signer, err := CheckDetachedSignature(kring, signed, signature) if err != nil { t.Errorf("%s: signature error: %s", tag, err) return } if signer == nil { t.Errorf("%s: signer is nil", tag) return } if signer.PrimaryKey.KeyId != expectedSignerKeyId { t.Errorf("%s: wrong signer got:%x want:%x", tag, signer.PrimaryKey.KeyId, expectedSignerKeyId) } } func TestDetachedSignature(t *testing.T) { kring, _ := ReadKeyRing(readerFromHex(testKeys1And2Hex)) testDetachedSignature(t, kring, readerFromHex(detachedSignatureHex), signedInput, "binary", testKey1KeyId) testDetachedSignature(t, kring, readerFromHex(detachedSignatureTextHex), signedInput, "text", testKey1KeyId) testDetachedSignature(t, kring, readerFromHex(detachedSignatureV3TextHex), signedInput, "v3", testKey1KeyId) incorrectSignedInput := signedInput + "X" _, err := CheckDetachedSignature(kring, bytes.NewBufferString(incorrectSignedInput), readerFromHex(detachedSignatureHex)) if err == nil { t.Fatal("CheckDetachedSignature returned without error for bad signature") } if err == errors.ErrUnknownIssuer { t.Fatal("CheckDetachedSignature returned ErrUnknownIssuer when the signer was known, but the signature invalid") } } func TestDetachedSignatureDSA(t *testing.T) { kring, _ := ReadKeyRing(readerFromHex(dsaTestKeyHex)) testDetachedSignature(t, kring, readerFromHex(detachedSignatureDSAHex), signedInput, "binary", testKey3KeyId) } func TestMultipleSignaturePacketsDSA(t *testing.T) { kring, _ := ReadKeyRing(readerFromHex(dsaTestKeyHex)) testDetachedSignature(t, kring, readerFromHex(missingHashFunctionHex+detachedSignatureDSAHex), signedInput, "binary", testKey3KeyId) } func TestDetachedSignatureP256(t *testing.T) { kring, _ := ReadKeyRing(readerFromHex(p256TestKeyHex)) testDetachedSignature(t, kring, readerFromHex(detachedSignatureP256Hex), signedInput, "binary", testKeyP256KeyId) } func testHashFunctionError(t *testing.T, signatureHex string) { kring, _ := ReadKeyRing(readerFromHex(testKeys1And2Hex)) _, err := CheckDetachedSignature(kring, nil, readerFromHex(signatureHex)) if err == nil { t.Fatal("Packet with bad hash type was correctly parsed") } unsupported, ok := err.(errors.UnsupportedError) if !ok { t.Fatalf("Unexpected class of error: %s", err) } if !strings.Contains(string(unsupported), "hash ") { t.Fatalf("Unexpected error: %s", err) } } func TestUnknownHashFunction(t *testing.T) { // unknownHashFunctionHex contains a signature packet with hash // function type 153 (which isn't a real hash function id). testHashFunctionError(t, unknownHashFunctionHex) } func TestMissingHashFunction(t *testing.T) { // missingHashFunctionHex contains a signature packet that uses // RIPEMD160, which isn't compiled in. Since that's the only signature // packet we don't find any suitable packets and end up with ErrUnknownIssuer kring, _ := ReadKeyRing(readerFromHex(testKeys1And2Hex)) _, err := CheckDetachedSignature(kring, nil, readerFromHex(missingHashFunctionHex)) if err == nil { t.Fatal("Packet with missing hash type was correctly parsed") } if err != errors.ErrUnknownIssuer { t.Fatalf("Unexpected class of error: %s", err) } } func TestReadingArmoredPrivateKey(t *testing.T) { el, err := ReadArmoredKeyRing(bytes.NewBufferString(armoredPrivateKeyBlock)) if err != nil { t.Error(err) } if len(el) != 1 { t.Errorf("got %d entities, wanted 1\n", len(el)) } } func TestReadingArmoredPublicKey(t *testing.T) { el, err := ReadArmoredKeyRing(bytes.NewBufferString(e2ePublicKey)) if err != nil { t.Error(err) } if len(el) != 1 { t.Errorf("didn't get a valid entity") } } func TestNoArmoredData(t *testing.T) { _, err := ReadArmoredKeyRing(bytes.NewBufferString("foo")) if _, ok := err.(errors.InvalidArgumentError); !ok { t.Errorf("error was not an InvalidArgumentError: %s", err) } } func testReadMessageError(t *testing.T, messageHex string) { buf, err := hex.DecodeString(messageHex) if err != nil { t.Errorf("hex.DecodeString(): %v", err) } kr, err := ReadKeyRing(new(bytes.Buffer)) if err != nil { t.Errorf("ReadKeyring(): %v", err) } _, err = ReadMessage(bytes.NewBuffer(buf), kr, func([]Key, bool) ([]byte, error) { return []byte("insecure"), nil }, nil) if err == nil { t.Errorf("ReadMessage(): Unexpected nil error") } } func TestIssue11503(t *testing.T) { testReadMessageError(t, "8c040402000aa430aa8228b9248b01fc899a91197130303030") } func TestIssue11504(t *testing.T) { testReadMessageError(t, "9303000130303030303030303030983002303030303030030000000130") } // TestSignatureV3Message tests the verification of V3 signature, generated // with a modern V4-style key. Some people have their clients set to generate // V3 signatures, so it's useful to be able to verify them. func TestSignatureV3Message(t *testing.T) { sig, err := armor.Decode(strings.NewReader(signedMessageV3)) if err != nil { t.Error(err) return } key, err := ReadArmoredKeyRing(strings.NewReader(keyV4forVerifyingSignedMessageV3)) if err != nil { t.Error(err) return } md, err := ReadMessage(sig.Body, key, nil, nil) if err != nil { t.Error(err) return } _, err = ioutil.ReadAll(md.UnverifiedBody) if err != nil { t.Error(err) return } // We'll see a sig error here after reading in the UnverifiedBody above, // if there was one to see. if err = md.SignatureError; err != nil { t.Error(err) return } if md.SignatureV3 == nil { t.Errorf("No available signature after checking signature") return } if md.Signature != nil { t.Errorf("Did not expect a signature V4 back") return } return } const testKey1KeyId = 0xA34D7E18C20C31BB const testKey3KeyId = 0x338934250CCC0360 const testKeyP256KeyId = 0xd44a2c495918513e const signedInput = "Signed message\nline 2\nline 3\n" const signedTextInput = "Signed message\r\nline 2\r\nline 3\r\n" const recipientUnspecifiedHex = "848c0300000000000000000103ff62d4d578d03cf40c3da998dfe216c074fa6ddec5e31c197c9666ba292830d91d18716a80f699f9d897389a90e6d62d0238f5f07a5248073c0f24920e4bc4a30c2d17ee4e0cae7c3d4aaa4e8dced50e3010a80ee692175fa0385f62ecca4b56ee6e9980aa3ec51b61b077096ac9e800edaf161268593eedb6cc7027ff5cb32745d250010d407a6221ae22ef18469b444f2822478c4d190b24d36371a95cb40087cdd42d9399c3d06a53c0673349bfb607927f20d1e122bde1e2bf3aa6cae6edf489629bcaa0689539ae3b718914d88ededc3b" const detachedSignatureHex = "889c04000102000605024d449cd1000a0910a34d7e18c20c31bb167603ff57718d09f28a519fdc7b5a68b6a3336da04df85e38c5cd5d5bd2092fa4629848a33d85b1729402a2aab39c3ac19f9d573f773cc62c264dc924c067a79dfd8a863ae06c7c8686120760749f5fd9b1e03a64d20a7df3446ddc8f0aeadeaeba7cbaee5c1e366d65b6a0c6cc749bcb912d2f15013f812795c2e29eb7f7b77f39ce77" const detachedSignatureTextHex = "889c04010102000605024d449d21000a0910a34d7e18c20c31bbc8c60400a24fbef7342603a41cb1165767bd18985d015fb72fe05db42db36cfb2f1d455967f1e491194fbf6cf88146222b23bf6ffbd50d17598d976a0417d3192ff9cc0034fd00f287b02e90418bbefe609484b09231e4e7a5f3562e199bf39909ab5276c4d37382fe088f6b5c3426fc1052865da8b3ab158672d58b6264b10823dc4b39" const detachedSignatureV3TextHex = "8900950305005255c25ca34d7e18c20c31bb0102bb3f04009f6589ef8a028d6e54f6eaf25432e590d31c3a41f4710897585e10c31e5e332c7f9f409af8512adceaff24d0da1474ab07aa7bce4f674610b010fccc5b579ae5eb00a127f272fb799f988ab8e4574c141da6dbfecfef7e6b2c478d9a3d2551ba741f260ee22bec762812f0053e05380bfdd55ad0f22d8cdf71b233fe51ae8a24" const detachedSignatureDSAHex = "884604001102000605024d6c4eac000a0910338934250ccc0360f18d00a087d743d6405ed7b87755476629600b8b694a39e900a0abff8126f46faf1547c1743c37b21b4ea15b8f83" const detachedSignatureP256Hex = "885e0400130a0006050256e5bb00000a0910d44a2c495918513edef001009841a4f792beb0befccb35c8838a6a87d9b936beaa86db6745ddc7b045eee0cf00fd1ac1f78306b17e965935dd3f8bae4587a76587e4af231efe19cc4011a8434817" const testKeys1And2Hex = "988d044d3c5c10010400b1d13382944bd5aba23a4312968b5095d14f947f600eb478e14a6fcb16b0e0cac764884909c020bc495cfcc39a935387c661507bdb236a0612fb582cac3af9b29cc2c8c70090616c41b662f4da4c1201e195472eb7f4ae1ccbcbf9940fe21d985e379a5563dde5b9a23d35f1cfaa5790da3b79db26f23695107bfaca8e7b5bcd0011010001b41054657374204b6579203120285253412988b804130102002205024d3c5c10021b03060b090807030206150802090a0b0416020301021e01021780000a0910a34d7e18c20c31bbb5b304009cc45fe610b641a2c146331be94dade0a396e73ca725e1b25c21708d9cab46ecca5ccebc23055879df8f99eea39b377962a400f2ebdc36a7c99c333d74aeba346315137c3ff9d0a09b0273299090343048afb8107cf94cbd1400e3026f0ccac7ecebbc4d78588eb3e478fe2754d3ca664bcf3eac96ca4a6b0c8d7df5102f60f6b0020003b88d044d3c5c10010400b201df61d67487301f11879d514f4248ade90c8f68c7af1284c161098de4c28c2850f1ec7b8e30f959793e571542ffc6532189409cb51c3d30dad78c4ad5165eda18b20d9826d8707d0f742e2ab492103a85bbd9ddf4f5720f6de7064feb0d39ee002219765bb07bcfb8b877f47abe270ddeda4f676108cecb6b9bb2ad484a4f0011010001889f04180102000905024d3c5c10021b0c000a0910a34d7e18c20c31bb1a03040085c8d62e16d05dc4e9dad64953c8a2eed8b6c12f92b1575eeaa6dcf7be9473dd5b24b37b6dffbb4e7c99ed1bd3cb11634be19b3e6e207bed7505c7ca111ccf47cb323bf1f8851eb6360e8034cbff8dd149993c959de89f8f77f38e7e98b8e3076323aa719328e2b408db5ec0d03936efd57422ba04f925cdc7b4c1af7590e40ab0020003988d044d3c5c33010400b488c3e5f83f4d561f317817538d9d0397981e9aef1321ca68ebfae1cf8b7d388e19f4b5a24a82e2fbbf1c6c26557a6c5845307a03d815756f564ac7325b02bc83e87d5480a8fae848f07cb891f2d51ce7df83dcafdc12324517c86d472cc0ee10d47a68fd1d9ae49a6c19bbd36d82af597a0d88cc9c49de9df4e696fc1f0b5d0011010001b42754657374204b6579203220285253412c20656e637279707465642070726976617465206b65792988b804130102002205024d3c5c33021b03060b090807030206150802090a0b0416020301021e01021780000a0910d4984f961e35246b98940400908a73b6a6169f700434f076c6c79015a49bee37130eaf23aaa3cfa9ce60bfe4acaa7bc95f1146ada5867e0079babb38804891f4f0b8ebca57a86b249dee786161a755b7a342e68ccf3f78ed6440a93a6626beb9a37aa66afcd4f888790cb4bb46d94a4ae3eb3d7d3e6b00f6bfec940303e89ec5b32a1eaaacce66497d539328b0020003b88d044d3c5c33010400a4e913f9442abcc7f1804ccab27d2f787ffa592077ca935a8bb23165bd8d57576acac647cc596b2c3f814518cc8c82953c7a4478f32e0cf645630a5ba38d9618ef2bc3add69d459ae3dece5cab778938d988239f8c5ae437807075e06c828019959c644ff05ef6a5a1dab72227c98e3a040b0cf219026640698d7a13d8538a570011010001889f04180102000905024d3c5c33021b0c000a0910d4984f961e35246b26c703ff7ee29ef53bc1ae1ead533c408fa136db508434e233d6e62be621e031e5940bbd4c08142aed0f82217e7c3e1ec8de574bc06ccf3c36633be41ad78a9eacd209f861cae7b064100758545cc9dd83db71806dc1cfd5fb9ae5c7474bba0c19c44034ae61bae5eca379383339dece94ff56ff7aa44a582f3e5c38f45763af577c0934b0020003" const testKeys1And2PrivateHex = "9501d8044d3c5c10010400b1d13382944bd5aba23a4312968b5095d14f947f600eb478e14a6fcb16b0e0cac764884909c020bc495cfcc39a935387c661507bdb236a0612fb582cac3af9b29cc2c8c70090616c41b662f4da4c1201e195472eb7f4ae1ccbcbf9940fe21d985e379a5563dde5b9a23d35f1cfaa5790da3b79db26f23695107bfaca8e7b5bcd00110100010003ff4d91393b9a8e3430b14d6209df42f98dc927425b881f1209f319220841273a802a97c7bdb8b3a7740b3ab5866c4d1d308ad0d3a79bd1e883aacf1ac92dfe720285d10d08752a7efe3c609b1d00f17f2805b217be53999a7da7e493bfc3e9618fd17018991b8128aea70a05dbce30e4fbe626aa45775fa255dd9177aabf4df7cf0200c1ded12566e4bc2bb590455e5becfb2e2c9796482270a943343a7835de41080582c2be3caf5981aa838140e97afa40ad652a0b544f83eb1833b0957dce26e47b0200eacd6046741e9ce2ec5beb6fb5e6335457844fb09477f83b050a96be7da043e17f3a9523567ed40e7a521f818813a8b8a72209f1442844843ccc7eb9805442570200bdafe0438d97ac36e773c7162028d65844c4d463e2420aa2228c6e50dc2743c3d6c72d0d782a5173fe7be2169c8a9f4ef8a7cf3e37165e8c61b89c346cdc6c1799d2b41054657374204b6579203120285253412988b804130102002205024d3c5c10021b03060b090807030206150802090a0b0416020301021e01021780000a0910a34d7e18c20c31bbb5b304009cc45fe610b641a2c146331be94dade0a396e73ca725e1b25c21708d9cab46ecca5ccebc23055879df8f99eea39b377962a400f2ebdc36a7c99c333d74aeba346315137c3ff9d0a09b0273299090343048afb8107cf94cbd1400e3026f0ccac7ecebbc4d78588eb3e478fe2754d3ca664bcf3eac96ca4a6b0c8d7df5102f60f6b00200009d01d8044d3c5c10010400b201df61d67487301f11879d514f4248ade90c8f68c7af1284c161098de4c28c2850f1ec7b8e30f959793e571542ffc6532189409cb51c3d30dad78c4ad5165eda18b20d9826d8707d0f742e2ab492103a85bbd9ddf4f5720f6de7064feb0d39ee002219765bb07bcfb8b877f47abe270ddeda4f676108cecb6b9bb2ad484a4f00110100010003fd17a7490c22a79c59281fb7b20f5e6553ec0c1637ae382e8adaea295f50241037f8997cf42c1ce26417e015091451b15424b2c59eb8d4161b0975630408e394d3b00f88d4b4e18e2cc85e8251d4753a27c639c83f5ad4a571c4f19d7cd460b9b73c25ade730c99df09637bd173d8e3e981ac64432078263bb6dc30d3e974150dd0200d0ee05be3d4604d2146fb0457f31ba17c057560785aa804e8ca5530a7cd81d3440d0f4ba6851efcfd3954b7e68908fc0ba47f7ac37bf559c6c168b70d3a7c8cd0200da1c677c4bce06a068070f2b3733b0a714e88d62aa3f9a26c6f5216d48d5c2b5624144f3807c0df30be66b3268eeeca4df1fbded58faf49fc95dc3c35f134f8b01fd1396b6c0fc1b6c4f0eb8f5e44b8eace1e6073e20d0b8bc5385f86f1cf3f050f66af789f3ef1fc107b7f4421e19e0349c730c68f0a226981f4e889054fdb4dc149e8e889f04180102000905024d3c5c10021b0c000a0910a34d7e18c20c31bb1a03040085c8d62e16d05dc4e9dad64953c8a2eed8b6c12f92b1575eeaa6dcf7be9473dd5b24b37b6dffbb4e7c99ed1bd3cb11634be19b3e6e207bed7505c7ca111ccf47cb323bf1f8851eb6360e8034cbff8dd149993c959de89f8f77f38e7e98b8e3076323aa719328e2b408db5ec0d03936efd57422ba04f925cdc7b4c1af7590e40ab00200009501fe044d3c5c33010400b488c3e5f83f4d561f317817538d9d0397981e9aef1321ca68ebfae1cf8b7d388e19f4b5a24a82e2fbbf1c6c26557a6c5845307a03d815756f564ac7325b02bc83e87d5480a8fae848f07cb891f2d51ce7df83dcafdc12324517c86d472cc0ee10d47a68fd1d9ae49a6c19bbd36d82af597a0d88cc9c49de9df4e696fc1f0b5d0011010001fe030302e9030f3c783e14856063f16938530e148bc57a7aa3f3e4f90df9dceccdc779bc0835e1ad3d006e4a8d7b36d08b8e0de5a0d947254ecfbd22037e6572b426bcfdc517796b224b0036ff90bc574b5509bede85512f2eefb520fb4b02aa523ba739bff424a6fe81c5041f253f8d757e69a503d3563a104d0d49e9e890b9d0c26f96b55b743883b472caa7050c4acfd4a21f875bdf1258d88bd61224d303dc9df77f743137d51e6d5246b88c406780528fd9a3e15bab5452e5b93970d9dcc79f48b38651b9f15bfbcf6da452837e9cc70683d1bdca94507870f743e4ad902005812488dd342f836e72869afd00ce1850eea4cfa53ce10e3608e13d3c149394ee3cbd0e23d018fcbcb6e2ec5a1a22972d1d462ca05355d0d290dd2751e550d5efb38c6c89686344df64852bf4ff86638708f644e8ec6bd4af9b50d8541cb91891a431326ab2e332faa7ae86cfb6e0540aa63160c1e5cdd5a4add518b303fff0a20117c6bc77f7cfbaf36b04c865c6c2b42754657374204b6579203220285253412c20656e637279707465642070726976617465206b65792988b804130102002205024d3c5c33021b03060b090807030206150802090a0b0416020301021e01021780000a0910d4984f961e35246b98940400908a73b6a6169f700434f076c6c79015a49bee37130eaf23aaa3cfa9ce60bfe4acaa7bc95f1146ada5867e0079babb38804891f4f0b8ebca57a86b249dee786161a755b7a342e68ccf3f78ed6440a93a6626beb9a37aa66afcd4f888790cb4bb46d94a4ae3eb3d7d3e6b00f6bfec940303e89ec5b32a1eaaacce66497d539328b00200009d01fe044d3c5c33010400a4e913f9442abcc7f1804ccab27d2f787ffa592077ca935a8bb23165bd8d57576acac647cc596b2c3f814518cc8c82953c7a4478f32e0cf645630a5ba38d9618ef2bc3add69d459ae3dece5cab778938d988239f8c5ae437807075e06c828019959c644ff05ef6a5a1dab72227c98e3a040b0cf219026640698d7a13d8538a570011010001fe030302e9030f3c783e148560f936097339ae381d63116efcf802ff8b1c9360767db5219cc987375702a4123fd8657d3e22700f23f95020d1b261eda5257e9a72f9a918e8ef22dd5b3323ae03bbc1923dd224db988cadc16acc04b120a9f8b7e84da9716c53e0334d7b66586ddb9014df604b41be1e960dcfcbc96f4ed150a1a0dd070b9eb14276b9b6be413a769a75b519a53d3ecc0c220e85cd91ca354d57e7344517e64b43b6e29823cbd87eae26e2b2e78e6dedfbb76e3e9f77bcb844f9a8932eb3db2c3f9e44316e6f5d60e9e2a56e46b72abe6b06dc9a31cc63f10023d1f5e12d2a3ee93b675c96f504af0001220991c88db759e231b3320dcedf814dcf723fd9857e3d72d66a0f2af26950b915abdf56c1596f46a325bf17ad4810d3535fb02a259b247ac3dbd4cc3ecf9c51b6c07cebb009c1506fba0a89321ec8683e3fd009a6e551d50243e2d5092fefb3321083a4bad91320dc624bd6b5dddf93553e3d53924c05bfebec1fb4bd47e89a1a889f04180102000905024d3c5c33021b0c000a0910d4984f961e35246b26c703ff7ee29ef53bc1ae1ead533c408fa136db508434e233d6e62be621e031e5940bbd4c08142aed0f82217e7c3e1ec8de574bc06ccf3c36633be41ad78a9eacd209f861cae7b064100758545cc9dd83db71806dc1cfd5fb9ae5c7474bba0c19c44034ae61bae5eca379383339dece94ff56ff7aa44a582f3e5c38f45763af577c0934b0020000" const dsaElGamalTestKeysHex = "9501e1044dfcb16a110400aa3e5c1a1f43dd28c2ffae8abf5cfce555ee874134d8ba0a0f7b868ce2214beddc74e5e1e21ded354a95d18acdaf69e5e342371a71fbb9093162e0c5f3427de413a7f2c157d83f5cd2f9d791256dc4f6f0e13f13c3302af27f2384075ab3021dff7a050e14854bbde0a1094174855fc02f0bae8e00a340d94a1f22b32e48485700a0cec672ac21258fb95f61de2ce1af74b2c4fa3e6703ff698edc9be22c02ae4d916e4fa223f819d46582c0516235848a77b577ea49018dcd5e9e15cff9dbb4663a1ae6dd7580fa40946d40c05f72814b0f88481207e6c0832c3bded4853ebba0a7e3bd8e8c66df33d5a537cd4acf946d1080e7a3dcea679cb2b11a72a33a2b6a9dc85f466ad2ddf4c3db6283fa645343286971e3dd700703fc0c4e290d45767f370831a90187e74e9972aae5bff488eeff7d620af0362bfb95c1a6c3413ab5d15a2e4139e5d07a54d72583914661ed6a87cce810be28a0aa8879a2dd39e52fb6fe800f4f181ac7e328f740cde3d09a05cecf9483e4cca4253e60d4429ffd679d9996a520012aad119878c941e3cf151459873bdfc2a9563472fe0303027a728f9feb3b864260a1babe83925ce794710cfd642ee4ae0e5b9d74cee49e9c67b6cd0ea5dfbb582132195a121356a1513e1bca73e5b80c58c7ccb4164453412f456c47616d616c2054657374204b65792031886204131102002205024dfcb16a021b03060b090807030206150802090a0b0416020301021e01021780000a091033af447ccd759b09fadd00a0b8fd6f5a790bad7e9f2dbb7632046dc4493588db009c087c6a9ba9f7f49fab221587a74788c00db4889ab00200009d0157044dfcb16a1004008dec3f9291205255ccff8c532318133a6840739dd68b03ba942676f9038612071447bf07d00d559c5c0875724ea16a4c774f80d8338b55fca691a0522e530e604215b467bbc9ccfd483a1da99d7bc2648b4318fdbd27766fc8bfad3fddb37c62b8ae7ccfe9577e9b8d1e77c1d417ed2c2ef02d52f4da11600d85d3229607943700030503ff506c94c87c8cab778e963b76cf63770f0a79bf48fb49d3b4e52234620fc9f7657f9f8d56c96a2b7c7826ae6b57ebb2221a3fe154b03b6637cea7e6d98e3e45d87cf8dc432f723d3d71f89c5192ac8d7290684d2c25ce55846a80c9a7823f6acd9bb29fa6cd71f20bc90eccfca20451d0c976e460e672b000df49466408d527affe0303027a728f9feb3b864260abd761730327bca2aaa4ea0525c175e92bf240682a0e83b226f97ecb2e935b62c9a133858ce31b271fa8eb41f6a1b3cd72a63025ce1a75ee4180dcc284884904181102000905024dfcb16a021b0c000a091033af447ccd759b09dd0b009e3c3e7296092c81bee5a19929462caaf2fff3ae26009e218c437a2340e7ea628149af1ec98ec091a43992b00200009501e1044dfcb1be1104009f61faa61aa43df75d128cbe53de528c4aec49ce9360c992e70c77072ad5623de0a3a6212771b66b39a30dad6781799e92608316900518ec01184a85d872365b7d2ba4bacfb5882ea3c2473d3750dc6178cc1cf82147fb58caa28b28e9f12f6d1efcb0534abed644156c91cca4ab78834268495160b2400bc422beb37d237c2300a0cac94911b6d493bda1e1fbc6feeca7cb7421d34b03fe22cec6ccb39675bb7b94a335c2b7be888fd3906a1125f33301d8aa6ec6ee6878f46f73961c8d57a3e9544d8ef2a2cbfd4d52da665b1266928cfe4cb347a58c412815f3b2d2369dec04b41ac9a71cc9547426d5ab941cccf3b18575637ccfb42df1a802df3cfe0a999f9e7109331170e3a221991bf868543960f8c816c28097e503fe319db10fb98049f3a57d7c80c420da66d56f3644371631fad3f0ff4040a19a4fedc2d07727a1b27576f75a4d28c47d8246f27071e12d7a8de62aad216ddbae6aa02efd6b8a3e2818cda48526549791ab277e447b3a36c57cefe9b592f5eab73959743fcc8e83cbefec03a329b55018b53eec196765ae40ef9e20521a603c551efe0303020950d53a146bf9c66034d00c23130cce95576a2ff78016ca471276e8227fb30b1ffbd92e61804fb0c3eff9e30b1a826ee8f3e4730b4d86273ca977b4164453412f456c47616d616c2054657374204b65792032886204131102002205024dfcb1be021b03060b090807030206150802090a0b0416020301021e01021780000a0910a86bf526325b21b22bd9009e34511620415c974750a20df5cb56b182f3b48e6600a0a9466cb1a1305a84953445f77d461593f1d42bc1b00200009d0157044dfcb1be1004009565a951da1ee87119d600c077198f1c1bceb0f7aa54552489298e41ff788fa8f0d43a69871f0f6f77ebdfb14a4260cf9fbeb65d5844b4272a1904dd95136d06c3da745dc46327dd44a0f16f60135914368c8039a34033862261806bb2c5ce1152e2840254697872c85441ccb7321431d75a747a4bfb1d2c66362b51ce76311700030503fc0ea76601c196768070b7365a200e6ddb09307f262d5f39eec467b5f5784e22abdf1aa49226f59ab37cb49969d8f5230ea65caf56015abda62604544ed526c5c522bf92bed178a078789f6c807b6d34885688024a5bed9e9f8c58d11d4b82487b44c5f470c5606806a0443b79cadb45e0f897a561a53f724e5349b9267c75ca17fe0303020950d53a146bf9c660bc5f4ce8f072465e2d2466434320c1e712272fafc20e342fe7608101580fa1a1a367e60486a7cd1246b7ef5586cf5e10b32762b710a30144f12dd17dd4884904181102000905024dfcb1be021b0c000a0910a86bf526325b21b2904c00a0b2b66b4b39ccffda1d10f3ea8d58f827e30a8b8e009f4255b2d8112a184e40cde43a34e8655ca7809370b0020000" const signedMessageHex = "a3019bc0cbccc0c4b8d8b74ee2108fe16ec6d3ca490cbe362d3f8333d3f352531472538b8b13d353b97232f352158c20943157c71c16064626063656269052062e4e01987e9b6fccff4b7df3a34c534b23e679cbec3bc0f8f6e64dfb4b55fe3f8efa9ce110ddb5cd79faf1d753c51aecfa669f7e7aa043436596cccc3359cb7dd6bbe9ecaa69e5989d9e57209571edc0b2fa7f57b9b79a64ee6e99ce1371395fee92fec2796f7b15a77c386ff668ee27f6d38f0baa6c438b561657377bf6acff3c5947befd7bf4c196252f1d6e5c524d0300" const signedTextMessageHex = "a3019bc0cbccc8c4b8d8b74ee2108fe16ec6d36a250cbece0c178233d3f352531472538b8b13d35379b97232f352158ca0b4312f57c71c1646462606365626906a062e4e019811591798ff99bf8afee860b0d8a8c2a85c3387e3bcf0bb3b17987f2bbcfab2aa526d930cbfd3d98757184df3995c9f3e7790e36e3e9779f06089d4c64e9e47dd6202cb6e9bc73c5d11bb59fbaf89d22d8dc7cf199ddf17af96e77c5f65f9bbed56f427bd8db7af37f6c9984bf9385efaf5f184f986fb3e6adb0ecfe35bbf92d16a7aa2a344fb0bc52fb7624f0200" const signedEncryptedMessageHex = "848c032a67d68660df41c70103ff5789d0de26b6a50c985a02a13131ca829c413a35d0e6fa8d6842599252162808ac7439c72151c8c6183e76923fe3299301414d0c25a2f06a2257db3839e7df0ec964773f6e4c4ac7ff3b48c444237166dd46ba8ff443a5410dc670cb486672fdbe7c9dfafb75b4fea83af3a204fe2a7dfa86bd20122b4f3d2646cbeecb8f7be8d2c03b018bd210b1d3791e1aba74b0f1034e122ab72e760492c192383cf5e20b5628bd043272d63df9b923f147eb6091cd897553204832aba48fec54aa447547bb16305a1024713b90e77fd0065f1918271947549205af3c74891af22ee0b56cd29bfec6d6e351901cd4ab3ece7c486f1e32a792d4e474aed98ee84b3f591c7dff37b64e0ecd68fd036d517e412dcadf85840ce184ad7921ad446c4ee28db80447aea1ca8d4f574db4d4e37688158ddd19e14ee2eab4873d46947d65d14a23e788d912cf9a19624ca7352469b72a83866b7c23cb5ace3deab3c7018061b0ba0f39ed2befe27163e5083cf9b8271e3e3d52cc7ad6e2a3bd81d4c3d7022f8d" const signedEncryptedMessage2Hex = "85010e03cf6a7abcd43e36731003fb057f5495b79db367e277cdbe4ab90d924ddee0c0381494112ff8c1238fb0184af35d1731573b01bc4c55ecacd2aafbe2003d36310487d1ecc9ac994f3fada7f9f7f5c3a64248ab7782906c82c6ff1303b69a84d9a9529c31ecafbcdb9ba87e05439897d87e8a2a3dec55e14df19bba7f7bd316291c002ae2efd24f83f9e3441203fc081c0c23dc3092a454ca8a082b27f631abf73aca341686982e8fbda7e0e7d863941d68f3de4a755c2964407f4b5e0477b3196b8c93d551dd23c8beef7d0f03fbb1b6066f78907faf4bf1677d8fcec72651124080e0b7feae6b476e72ab207d38d90b958759fdedfc3c6c35717c9dbfc979b3cfbbff0a76d24a5e57056bb88acbd2a901ef64bc6e4db02adc05b6250ff378de81dca18c1910ab257dff1b9771b85bb9bbe0a69f5989e6d1710a35e6dfcceb7d8fb5ccea8db3932b3d9ff3fe0d327597c68b3622aec8e3716c83a6c93f497543b459b58ba504ed6bcaa747d37d2ca746fe49ae0a6ce4a8b694234e941b5159ff8bd34b9023da2814076163b86f40eed7c9472f81b551452d5ab87004a373c0172ec87ea6ce42ccfa7dbdad66b745496c4873d8019e8c28d6b3" const symmetricallyEncryptedCompressedHex = "8c0d04030302eb4a03808145d0d260c92f714339e13de5a79881216431925bf67ee2898ea61815f07894cd0703c50d0a76ef64d482196f47a8bc729af9b80bb6" const dsaTestKeyHex = "9901a2044d6c49de110400cb5ce438cf9250907ac2ba5bf6547931270b89f7c4b53d9d09f4d0213a5ef2ec1f26806d3d259960f872a4a102ef1581ea3f6d6882d15134f21ef6a84de933cc34c47cc9106efe3bd84c6aec12e78523661e29bc1a61f0aab17fa58a627fd5fd33f5149153fbe8cd70edf3d963bc287ef875270ff14b5bfdd1bca4483793923b00a0fe46d76cb6e4cbdc568435cd5480af3266d610d303fe33ae8273f30a96d4d34f42fa28ce1112d425b2e3bf7ea553d526e2db6b9255e9dc7419045ce817214d1a0056dbc8d5289956a4b1b69f20f1105124096e6a438f41f2e2495923b0f34b70642607d45559595c7fe94d7fa85fc41bf7d68c1fd509ebeaa5f315f6059a446b9369c277597e4f474a9591535354c7e7f4fd98a08aa60400b130c24ff20bdfbf683313f5daebf1c9b34b3bdadfc77f2ddd72ee1fb17e56c473664bc21d66467655dd74b9005e3a2bacce446f1920cd7017231ae447b67036c9b431b8179deacd5120262d894c26bc015bffe3d827ba7087ad9b700d2ca1f6d16cc1786581e5dd065f293c31209300f9b0afcc3f7c08dd26d0a22d87580b4db41054657374204b65792033202844534129886204131102002205024d6c49de021b03060b090807030206150802090a0b0416020301021e01021780000a0910338934250ccc03607e0400a0bdb9193e8a6b96fc2dfc108ae848914b504481f100a09c4dc148cb693293a67af24dd40d2b13a9e36794" const dsaTestKeyPrivateHex = "9501bb044d6c49de110400cb5ce438cf9250907ac2ba5bf6547931270b89f7c4b53d9d09f4d0213a5ef2ec1f26806d3d259960f872a4a102ef1581ea3f6d6882d15134f21ef6a84de933cc34c47cc9106efe3bd84c6aec12e78523661e29bc1a61f0aab17fa58a627fd5fd33f5149153fbe8cd70edf3d963bc287ef875270ff14b5bfdd1bca4483793923b00a0fe46d76cb6e4cbdc568435cd5480af3266d610d303fe33ae8273f30a96d4d34f42fa28ce1112d425b2e3bf7ea553d526e2db6b9255e9dc7419045ce817214d1a0056dbc8d5289956a4b1b69f20f1105124096e6a438f41f2e2495923b0f34b70642607d45559595c7fe94d7fa85fc41bf7d68c1fd509ebeaa5f315f6059a446b9369c277597e4f474a9591535354c7e7f4fd98a08aa60400b130c24ff20bdfbf683313f5daebf1c9b34b3bdadfc77f2ddd72ee1fb17e56c473664bc21d66467655dd74b9005e3a2bacce446f1920cd7017231ae447b67036c9b431b8179deacd5120262d894c26bc015bffe3d827ba7087ad9b700d2ca1f6d16cc1786581e5dd065f293c31209300f9b0afcc3f7c08dd26d0a22d87580b4d00009f592e0619d823953577d4503061706843317e4fee083db41054657374204b65792033202844534129886204131102002205024d6c49de021b03060b090807030206150802090a0b0416020301021e01021780000a0910338934250ccc03607e0400a0bdb9193e8a6b96fc2dfc108ae848914b504481f100a09c4dc148cb693293a67af24dd40d2b13a9e36794" const p256TestKeyHex = "98520456e5b83813082a8648ce3d030107020304a2072cd6d21321266c758cc5b83fab0510f751cb8d91897cddb7047d8d6f185546e2107111b0a95cb8ef063c33245502af7a65f004d5919d93ee74eb71a66253b424502d3235362054657374204b6579203c696e76616c6964406578616d706c652e636f6d3e8879041313080021050256e5b838021b03050b09080702061508090a0b020416020301021e01021780000a0910d44a2c495918513e54e50100dfa64f97d9b47766fc1943c6314ba3f2b2a103d71ad286dc5b1efb96a345b0c80100dbc8150b54241f559da6ef4baacea6d31902b4f4b1bdc09b34bf0502334b7754b8560456e5b83812082a8648ce3d030107020304bfe3cea9cee13486f8d518aa487fecab451f25467d2bf08e58f63e5fa525d5482133e6a79299c274b068ef0be448152ad65cf11cf764348588ca4f6a0bcf22b6030108078861041813080009050256e5b838021b0c000a0910d44a2c495918513e4a4800ff49d589fa64024ad30be363a032e3a0e0e6f5db56ba4c73db850518bf0121b8f20100fd78e065f4c70ea5be9df319ea67e493b936fc78da834a71828043d3154af56e" const p256TestKeyPrivateHex = "94a50456e5b83813082a8648ce3d030107020304a2072cd6d21321266c758cc5b83fab0510f751cb8d91897cddb7047d8d6f185546e2107111b0a95cb8ef063c33245502af7a65f004d5919d93ee74eb71a66253fe070302f0c2bfb0b6c30f87ee1599472b8636477eab23ced13b271886a4b50ed34c9d8436af5af5b8f88921f0efba6ef8c37c459bbb88bc1c6a13bbd25c4ce9b1e97679569ee77645d469bf4b43de637f5561b424502d3235362054657374204b6579203c696e76616c6964406578616d706c652e636f6d3e8879041313080021050256e5b838021b03050b09080702061508090a0b020416020301021e01021780000a0910d44a2c495918513e54e50100dfa64f97d9b47766fc1943c6314ba3f2b2a103d71ad286dc5b1efb96a345b0c80100dbc8150b54241f559da6ef4baacea6d31902b4f4b1bdc09b34bf0502334b77549ca90456e5b83812082a8648ce3d030107020304bfe3cea9cee13486f8d518aa487fecab451f25467d2bf08e58f63e5fa525d5482133e6a79299c274b068ef0be448152ad65cf11cf764348588ca4f6a0bcf22b603010807fe0703027510012471a603cfee2968dce19f732721ddf03e966fd133b4e3c7a685b788705cbc46fb026dc94724b830c9edbaecd2fb2c662f23169516cacd1fe423f0475c364ecc10abcabcfd4bbbda1a36a1bd8861041813080009050256e5b838021b0c000a0910d44a2c495918513e4a4800ff49d589fa64024ad30be363a032e3a0e0e6f5db56ba4c73db850518bf0121b8f20100fd78e065f4c70ea5be9df319ea67e493b936fc78da834a71828043d3154af56e" const armoredPrivateKeyBlock = `-----BEGIN PGP PRIVATE KEY BLOCK----- Version: GnuPG v1.4.10 (GNU/Linux) lQHYBE2rFNoBBADFwqWQIW/DSqcB4yCQqnAFTJ27qS5AnB46ccAdw3u4Greeu3Bp idpoHdjULy7zSKlwR1EA873dO/k/e11Ml3dlAFUinWeejWaK2ugFP6JjiieSsrKn vWNicdCS4HTWn0X4sjl0ZiAygw6GNhqEQ3cpLeL0g8E9hnYzJKQ0LWJa0QARAQAB AAP/TB81EIo2VYNmTq0pK1ZXwUpxCrvAAIG3hwKjEzHcbQznsjNvPUihZ+NZQ6+X 0HCfPAdPkGDCLCb6NavcSW+iNnLTrdDnSI6+3BbIONqWWdRDYJhqZCkqmG6zqSfL IdkJgCw94taUg5BWP/AAeQrhzjChvpMQTVKQL5mnuZbUCeMCAN5qrYMP2S9iKdnk VANIFj7656ARKt/nf4CBzxcpHTyB8+d2CtPDKCmlJP6vL8t58Jmih+kHJMvC0dzn gr5f5+sCAOOe5gt9e0am7AvQWhdbHVfJU0TQJx+m2OiCJAqGTB1nvtBLHdJnfdC9 TnXXQ6ZXibqLyBies/xeY2sCKL5qtTMCAKnX9+9d/5yQxRyrQUHt1NYhaXZnJbHx q4ytu0eWz+5i68IYUSK69jJ1NWPM0T6SkqpB3KCAIv68VFm9PxqG1KmhSrQIVGVz dCBLZXmIuAQTAQIAIgUCTasU2gIbAwYLCQgHAwIGFQgCCQoLBBYCAwECHgECF4AA CgkQO9o98PRieSoLhgQAkLEZex02Qt7vGhZzMwuN0R22w3VwyYyjBx+fM3JFETy1 ut4xcLJoJfIaF5ZS38UplgakHG0FQ+b49i8dMij0aZmDqGxrew1m4kBfjXw9B/v+ eIqpODryb6cOSwyQFH0lQkXC040pjq9YqDsO5w0WYNXYKDnzRV0p4H1pweo2VDid AdgETasU2gEEAN46UPeWRqKHvA99arOxee38fBt2CI08iiWyI8T3J6ivtFGixSqV bRcPxYO/qLpVe5l84Nb3X71GfVXlc9hyv7CD6tcowL59hg1E/DC5ydI8K8iEpUmK /UnHdIY5h8/kqgGxkY/T/hgp5fRQgW1ZoZxLajVlMRZ8W4tFtT0DeA+JABEBAAEA A/0bE1jaaZKj6ndqcw86jd+QtD1SF+Cf21CWRNeLKnUds4FRRvclzTyUMuWPkUeX TaNNsUOFqBsf6QQ2oHUBBK4VCHffHCW4ZEX2cd6umz7mpHW6XzN4DECEzOVksXtc lUC1j4UB91DC/RNQqwX1IV2QLSwssVotPMPqhOi0ZLNY7wIA3n7DWKInxYZZ4K+6 rQ+POsz6brEoRHwr8x6XlHenq1Oki855pSa1yXIARoTrSJkBtn5oI+f8AzrnN0BN oyeQAwIA/7E++3HDi5aweWrViiul9cd3rcsS0dEnksPhvS0ozCJiHsq/6GFmy7J8 QSHZPteedBnZyNp5jR+H7cIfVN3KgwH/Skq4PsuPhDq5TKK6i8Pc1WW8MA6DXTdU nLkX7RGmMwjC0DBf7KWAlPjFaONAX3a8ndnz//fy1q7u2l9AZwrj1qa1iJ8EGAEC AAkFAk2rFNoCGwwACgkQO9o98PRieSo2/QP/WTzr4ioINVsvN1akKuekmEMI3LAp BfHwatufxxP1U+3Si/6YIk7kuPB9Hs+pRqCXzbvPRrI8NHZBmc8qIGthishdCYad AHcVnXjtxrULkQFGbGvhKURLvS9WnzD/m1K2zzwxzkPTzT9/Yf06O6Mal5AdugPL VrM0m72/jnpKo04= =zNCn -----END PGP PRIVATE KEY BLOCK-----` const e2ePublicKey = `-----BEGIN PGP PUBLIC KEY BLOCK----- Charset: UTF-8 xv8AAABSBAAAAAATCCqGSM49AwEHAgME1LRoXSpOxtHXDUdmuvzchyg6005qIBJ4 sfaSxX7QgH9RV2ONUhC+WiayCNADq+UMzuR/vunSr4aQffXvuGnR383/AAAAFDxk Z2lsQHlhaG9vLWluYy5jb20+wv8AAACGBBATCAA4/wAAAAWCVGvAG/8AAAACiwn/ AAAACZC2VkQCOjdvYf8AAAAFlQgJCgv/AAAAA5YBAv8AAAACngEAAE1BAP0X8veD 24IjmI5/C6ZAfVNXxgZZFhTAACFX75jUA3oD6AEAzoSwKf1aqH6oq62qhCN/pekX +WAsVMBhNwzLpqtCRjLO/wAAAFYEAAAAABIIKoZIzj0DAQcCAwT50ain7vXiIRv8 B1DO3x3cE/aattZ5sHNixJzRCXi2vQIA5QmOxZ6b5jjUekNbdHG3SZi1a2Ak5mfX fRxC/5VGAwEIB8L/AAAAZQQYEwgAGP8AAAAFglRrwBz/AAAACZC2VkQCOjdvYQAA FJAA9isX3xtGyMLYwp2F3nXm7QEdY5bq5VUcD/RJlj792VwA/1wH0pCzVLl4Q9F9 ex7En5r7rHR5xwX82Msc+Rq9dSyO =7MrZ -----END PGP PUBLIC KEY BLOCK-----` const dsaKeyWithSHA512 = `9901a2044f04b07f110400db244efecc7316553ee08d179972aab87bb1214de7692593fcf5b6feb1c80fba268722dd464748539b85b81d574cd2d7ad0ca2444de4d849b8756bad7768c486c83a824f9bba4af773d11742bdfb4ac3b89ef8cc9452d4aad31a37e4b630d33927bff68e879284a1672659b8b298222fc68f370f3e24dccacc4a862442b9438b00a0ea444a24088dc23e26df7daf8f43cba3bffc4fe703fe3d6cd7fdca199d54ed8ae501c30e3ec7871ea9cdd4cf63cfe6fc82281d70a5b8bb493f922cd99fba5f088935596af087c8d818d5ec4d0b9afa7f070b3d7c1dd32a84fca08d8280b4890c8da1dde334de8e3cad8450eed2a4a4fcc2db7b8e5528b869a74a7f0189e11ef097ef1253582348de072bb07a9fa8ab838e993cef0ee203ff49298723e2d1f549b00559f886cd417a41692ce58d0ac1307dc71d85a8af21b0cf6eaa14baf2922d3a70389bedf17cc514ba0febbd107675a372fe84b90162a9e88b14d4b1c6be855b96b33fb198c46f058568817780435b6936167ebb3724b680f32bf27382ada2e37a879b3d9de2abe0c3f399350afd1ad438883f4791e2e3b4184453412068617368207472756e636174696f6e207465737488620413110a002205024f04b07f021b03060b090807030206150802090a0b0416020301021e01021780000a0910ef20e0cefca131581318009e2bf3bf047a44d75a9bacd00161ee04d435522397009a03a60d51bd8a568c6c021c8d7cf1be8d990d6417b0020003` const unknownHashFunctionHex = `8a00000040040001990006050253863c24000a09103b4fe6acc0b21f32ffff01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101` const missingHashFunctionHex = `8a00000040040001030006050253863c24000a09103b4fe6acc0b21f32ffff0101010101010101010101010101010101010101010101010101010101010101010101010101` const campbellQuine = `a0b001000300fcffa0b001000d00f2ff000300fcffa0b001000d00f2ff8270a01c00000500faff8270a01c00000500faff000500faff001400ebff8270a01c00000500faff000500faff001400ebff428821c400001400ebff428821c400001400ebff428821c400001400ebff428821c400001400ebff428821c400000000ffff000000ffff000b00f4ff428821c400000000ffff000000ffff000b00f4ff0233214c40000100feff000233214c40000100feff0000` const keyV4forVerifyingSignedMessageV3 = `-----BEGIN PGP PUBLIC KEY BLOCK----- Comment: GPGTools - https://gpgtools.org mI0EVfxoFQEEAMBIqmbDfYygcvP6Phr1wr1XI41IF7Qixqybs/foBF8qqblD9gIY BKpXjnBOtbkcVOJ0nljd3/sQIfH4E0vQwK5/4YRQSI59eKOqd6Fx+fWQOLG+uu6z tewpeCj9LLHvibx/Sc7VWRnrznia6ftrXxJ/wHMezSab3tnGC0YPVdGNABEBAAG0 JEdvY3J5cHRvIFRlc3QgS2V5IDx0aGVtYXhAZ21haWwuY29tPoi5BBMBCgAjBQJV /GgVAhsDBwsJCAcDAgEGFQgCCQoLBBYCAwECHgECF4AACgkQeXnQmhdGW9PFVAP+ K7TU0qX5ArvIONIxh/WAweyOk884c5cE8f+3NOPOOCRGyVy0FId5A7MmD5GOQh4H JseOZVEVCqlmngEvtHZb3U1VYtVGE5WZ+6rQhGsMcWP5qaT4soYwMBlSYxgYwQcx YhN9qOr292f9j2Y//TTIJmZT4Oa+lMxhWdqTfX+qMgG4jQRV/GgVAQQArhFSiij1 b+hT3dnapbEU+23Z1yTu1DfF6zsxQ4XQWEV3eR8v+8mEDDNcz8oyyF56k6UQ3rXi UMTIwRDg4V6SbZmaFbZYCOwp/EmXJ3rfhm7z7yzXj2OFN22luuqbyVhuL7LRdB0M pxgmjXb4tTvfgKd26x34S+QqUJ7W6uprY4sAEQEAAYifBBgBCgAJBQJV/GgVAhsM AAoJEHl50JoXRlvT7y8D/02ckx4OMkKBZo7viyrBw0MLG92i+DC2bs35PooHR6zz 786mitjOp5z2QWNLBvxC70S0qVfCIz8jKupO1J6rq6Z8CcbLF3qjm6h1omUBf8Nd EfXKD2/2HV6zMKVknnKzIEzauh+eCKS2CeJUSSSryap/QLVAjRnckaES/OsEWhNB =RZia -----END PGP PUBLIC KEY BLOCK----- ` const signedMessageV3 = `-----BEGIN PGP MESSAGE----- Comment: GPGTools - https://gpgtools.org owGbwMvMwMVYWXlhlrhb9GXG03JJDKF/MtxDMjKLFYAoUaEktbhEITe1uDgxPVWP q5NhKjMrWAVcC9evD8z/bF/uWNjqtk/X3y5/38XGRQHm/57rrDRYuGnTw597Xqka uM3137/hH3Os+Jf2dc0fXOITKwJvXJvecPVs0ta+Vg7ZO1MLn8w58Xx+6L58mbka DGHyU9yTueZE8D+QF/Tz28Y78dqtF56R1VPn9Xw4uJqrWYdd7b3vIZ1V6R4Nh05d iT57d/OhWwA= =hG7R -----END PGP MESSAGE----- ` lxd-2.0.0/dist/src/golang.org/x/crypto/openpgp/packet/0000755061062106075000000000000012702772344025213 5ustar00stgraberdomain admins00000000000000lxd-2.0.0/dist/src/golang.org/x/crypto/openpgp/packet/symmetric_key_encrypted_test.go0000644061062106075000000000510312702772344033541 0ustar00stgraberdomain admins00000000000000// 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" "io/ioutil" "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 } key, cipherFunc, 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(cipherFunc, key) if err != nil { t.Error(err) return } contents, err := ioutil.ReadAll(r) if err != nil && err != io.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" func TestSerializeSymmetricKeyEncrypted(t *testing.T) { buf := bytes.NewBuffer(nil) passphrase := []byte("testing") const cipherFunc = CipherAES128 config := &Config{ DefaultCipher: cipherFunc, } key, err := SerializeSymmetricKeyEncrypted(buf, passphrase, config) if err != nil { t.Errorf("failed to serialize: %s", err) return } p, err := Read(buf) if err != nil { t.Errorf("failed to reparse: %s", err) return } ske, ok := p.(*SymmetricKeyEncrypted) if !ok { t.Errorf("parsed a different packet type: %#v", p) return } if ske.CipherFunc != config.DefaultCipher { t.Errorf("SKE cipher function is %d (expected %d)", ske.CipherFunc, config.DefaultCipher) } parsedKey, parsedCipherFunc, err := ske.Decrypt(passphrase) if err != nil { t.Errorf("failed to decrypt reparsed SKE: %s", err) return } if !bytes.Equal(key, parsedKey) { t.Errorf("keys don't match after Decrypt: %x (original) vs %x (parsed)", key, parsedKey) } if parsedCipherFunc != cipherFunc { t.Errorf("cipher function doesn't match after Decrypt: %d (original) vs %d (parsed)", cipherFunc, parsedCipherFunc) } } lxd-2.0.0/dist/src/golang.org/x/crypto/openpgp/packet/packet_test.go0000644061062106075000000001430612702772344030054 0ustar00stgraberdomain admins00000000000000// 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" "fmt" "golang.org/x/crypto/openpgp/errors" "io" "io/ioutil" "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 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 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.(errors.StructuralError); ok { continue } t.Errorf("%d: expected StructuralError, got:%s", i, err) continue } if err != nil { if len(test.hexInput) == 0 && err == io.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) } } } func TestSerializeHeader(t *testing.T) { tag := packetTypePublicKey lengths := []int{0, 1, 2, 64, 192, 193, 8000, 8384, 8385, 10000} for _, length := range lengths { buf := bytes.NewBuffer(nil) serializeHeader(buf, tag, length) tag2, length2, _, err := readHeader(buf) if err != nil { t.Errorf("length %d, err: %s", length, err) } if tag2 != tag { t.Errorf("length %d, tag incorrect (got %d, want %d)", length, tag2, tag) } if int(length2) != length { t.Errorf("length %d, length incorrect (got %d)", length, length2) } } } func TestPartialLengths(t *testing.T) { buf := bytes.NewBuffer(nil) w := new(partialLengthWriter) w.w = noOpCloser{buf} const maxChunkSize = 64 var b [maxChunkSize]byte var n uint8 for l := 1; l <= maxChunkSize; l++ { for i := 0; i < l; i++ { b[i] = n n++ } m, err := w.Write(b[:l]) if m != l { t.Errorf("short write got: %d want: %d", m, l) } if err != nil { t.Errorf("error from write: %s", err) } } w.Close() want := (maxChunkSize * (maxChunkSize + 1)) / 2 copyBuf := bytes.NewBuffer(nil) r := &partialLengthReader{buf, 0, true} m, err := io.Copy(copyBuf, r) if m != int64(want) { t.Errorf("short copy got: %d want: %d", m, want) } if err != nil { t.Errorf("error from copy: %s", err) } copyBytes := copyBuf.Bytes() for i := 0; i < want; i++ { if copyBytes[i] != uint8(i) { t.Errorf("bad pattern in copy at %d", i) break } } } lxd-2.0.0/dist/src/golang.org/x/crypto/openpgp/packet/signature_test.go0000644061062106075000000000313112702772344030600 0ustar00stgraberdomain admins00000000000000// 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) { packet, err := Read(readerFromHex(signatureDataHex)) 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) } } func TestSignatureReserialize(t *testing.T) { packet, _ := Read(readerFromHex(signatureDataHex)) sig := packet.(*Signature) out := new(bytes.Buffer) err := sig.Serialize(out) if err != nil { t.Errorf("error reserializing: %s", err) return } expected, _ := hex.DecodeString(signatureDataHex) if !bytes.Equal(expected, out.Bytes()) { t.Errorf("output doesn't match input (got vs expected):\n%s\n%s", hex.Dump(out.Bytes()), hex.Dump(expected)) } } const signatureDataHex = "c2c05c04000102000605024cb45112000a0910ab105c91af38fb158f8d07ff5596ea368c5efe015bed6e78348c0f033c931d5f2ce5db54ce7f2a7e4b4ad64db758d65a7a71773edeab7ba2a9e0908e6a94a1175edd86c1d843279f045b021a6971a72702fcbd650efc393c5474d5b59a15f96d2eaad4c4c426797e0dcca2803ef41c6ff234d403eec38f31d610c344c06f2401c262f0993b2e66cad8a81ebc4322c723e0d4ba09fe917e8777658307ad8329adacba821420741009dfe87f007759f0982275d028a392c6ed983a0d846f890b36148c7358bdb8a516007fac760261ecd06076813831a36d0459075d1befa245ae7f7fb103d92ca759e9498fe60ef8078a39a3beda510deea251ea9f0a7f0df6ef42060f20780360686f3e400e" lxd-2.0.0/dist/src/golang.org/x/crypto/openpgp/packet/private_key_test.go0000644061062106075000000001054412702772344031127 0ustar00stgraberdomain admins00000000000000// 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" "crypto/ecdsa" "crypto/elliptic" "crypto/rand" "hash" "testing" "time" ) var privateKeyTests = []struct { privateKeyHex string creationTime time.Time }{ { privKeyRSAHex, time.Unix(0x4cc349a8, 0), }, { privKeyElGamalHex, time.Unix(0x4df9ee1a, 0), }, } func TestPrivateKeyRead(t *testing.T) { for i, test := range privateKeyTests { packet, err := Read(readerFromHex(test.privateKeyHex)) if err != nil { t.Errorf("#%d: failed to parse: %s", i, err) continue } privKey := packet.(*PrivateKey) if !privKey.Encrypted { t.Errorf("#%d: private key isn't encrypted", i) continue } err = privKey.Decrypt([]byte("wrong password")) if err == nil { t.Errorf("#%d: decrypted with incorrect key", i) continue } err = privKey.Decrypt([]byte("testing")) if err != nil { t.Errorf("#%d: failed to decrypt: %s", i, err) continue } if !privKey.CreationTime.Equal(test.creationTime) || privKey.Encrypted { t.Errorf("#%d: bad result, got: %#v", i, privKey) } } } func populateHash(hashFunc crypto.Hash, msg []byte) (hash.Hash, error) { h := hashFunc.New() if _, err := h.Write(msg); err != nil { return nil, err } return h, nil } func TestECDSAPrivateKey(t *testing.T) { ecdsaPriv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) if err != nil { t.Fatal(err) } var buf bytes.Buffer if err := NewECDSAPrivateKey(time.Now(), ecdsaPriv).Serialize(&buf); err != nil { t.Fatal(err) } p, err := Read(&buf) if err != nil { t.Fatal(err) } priv, ok := p.(*PrivateKey) if !ok { t.Fatal("didn't parse private key") } sig := &Signature{ PubKeyAlgo: PubKeyAlgoECDSA, Hash: crypto.SHA256, } msg := []byte("Hello World!") h, err := populateHash(sig.Hash, msg) if err != nil { t.Fatal(err) } if err := sig.Sign(h, priv, nil); err != nil { t.Fatal(err) } if h, err = populateHash(sig.Hash, msg); err != nil { t.Fatal(err) } if err := priv.VerifySignature(h, sig); err != nil { t.Fatal(err) } } func TestIssue11505(t *testing.T) { // parsing a rsa private key with p or q == 1 used to panic due to a divide by zero _, _ = Read(readerFromHex("9c3004303030300100000011303030000000000000010130303030303030303030303030303030303030303030303030303030303030303030303030303030303030")) } // Generated with `gpg --export-secret-keys "Test Key 2"` const privKeyRSAHex = "9501fe044cc349a8010400b70ca0010e98c090008d45d1ee8f9113bd5861fd57b88bacb7c68658747663f1e1a3b5a98f32fda6472373c024b97359cd2efc88ff60f77751adfbf6af5e615e6a1408cfad8bf0cea30b0d5f53aa27ad59089ba9b15b7ebc2777a25d7b436144027e3bcd203909f147d0e332b240cf63d3395f5dfe0df0a6c04e8655af7eacdf0011010001fe0303024a252e7d475fd445607de39a265472aa74a9320ba2dac395faa687e9e0336aeb7e9a7397e511b5afd9dc84557c80ac0f3d4d7bfec5ae16f20d41c8c84a04552a33870b930420e230e179564f6d19bb153145e76c33ae993886c388832b0fa042ddda7f133924f3854481533e0ede31d51278c0519b29abc3bf53da673e13e3e1214b52413d179d7f66deee35cac8eacb060f78379d70ef4af8607e68131ff529439668fc39c9ce6dfef8a5ac234d234802cbfb749a26107db26406213ae5c06d4673253a3cbee1fcbae58d6ab77e38d6e2c0e7c6317c48e054edadb5a40d0d48acb44643d998139a8a66bb820be1f3f80185bc777d14b5954b60effe2448a036d565c6bc0b915fcea518acdd20ab07bc1529f561c58cd044f723109b93f6fd99f876ff891d64306b5d08f48bab59f38695e9109c4dec34013ba3153488ce070268381ba923ee1eb77125b36afcb4347ec3478c8f2735b06ef17351d872e577fa95d0c397c88c71b59629a36aec" // Generated by `gpg --export-secret-keys` followed by a manual extraction of // the ElGamal subkey from the packets. const privKeyElGamalHex = "9d0157044df9ee1a100400eb8e136a58ec39b582629cdadf830bc64e0a94ed8103ca8bb247b27b11b46d1d25297ef4bcc3071785ba0c0bedfe89eabc5287fcc0edf81ab5896c1c8e4b20d27d79813c7aede75320b33eaeeaa586edc00fd1036c10133e6ba0ff277245d0d59d04b2b3421b7244aca5f4a8d870c6f1c1fbff9e1c26699a860b9504f35ca1d700030503fd1ededd3b840795be6d9ccbe3c51ee42e2f39233c432b831ddd9c4e72b7025a819317e47bf94f9ee316d7273b05d5fcf2999c3a681f519b1234bbfa6d359b4752bd9c3f77d6b6456cde152464763414ca130f4e91d91041432f90620fec0e6d6b5116076c2985d5aeaae13be492b9b329efcaf7ee25120159a0a30cd976b42d7afe030302dae7eb80db744d4960c4df930d57e87fe81412eaace9f900e6c839817a614ddb75ba6603b9417c33ea7b6c93967dfa2bcff3fa3c74a5ce2c962db65b03aece14c96cbd0038fc" lxd-2.0.0/dist/src/golang.org/x/crypto/openpgp/packet/opaque_test.go0000644061062106075000000000470512702772344030101 0ustar00stgraberdomain admins00000000000000// 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" "testing" ) // Test packet.Read error handling in OpaquePacket.Parse, // which attempts to re-read an OpaquePacket as a supported // Packet type. func TestOpaqueParseReason(t *testing.T) { buf, err := hex.DecodeString(UnsupportedKeyHex) if err != nil { t.Fatal(err) } or := NewOpaqueReader(bytes.NewBuffer(buf)) count := 0 badPackets := 0 var uid *UserId for { op, err := or.Next() if err == io.EOF { break } else if err != nil { t.Errorf("#%d: opaque read error: %v", count, err) break } // try to parse opaque packet p, err := op.Parse() switch pkt := p.(type) { case *UserId: uid = pkt case *OpaquePacket: // If an OpaquePacket can't re-parse, packet.Read // certainly had its reasons. if pkt.Reason == nil { t.Errorf("#%d: opaque packet, no reason", count) } else { badPackets++ } } count++ } const expectedBad = 3 // Test post-conditions, make sure we actually parsed packets as expected. if badPackets != expectedBad { t.Errorf("unexpected # unparseable packets: %d (want %d)", badPackets, expectedBad) } if uid == nil { t.Errorf("failed to find expected UID in unsupported keyring") } else if uid.Id != "Armin M. Warda " { t.Errorf("unexpected UID: %v", uid.Id) } } // This key material has public key and signature packet versions modified to // an unsupported value (1), so that trying to parse the OpaquePacket to // a typed packet will get an error. It also contains a GnuPG trust packet. // (Created with: od -An -t x1 pubring.gpg | xargs | sed 's/ //g') const UnsupportedKeyHex = `988d012e7a18a20000010400d6ac00d92b89c1f4396c243abb9b76d2e9673ad63483291fed88e22b82e255e441c078c6abbbf7d2d195e50b62eeaa915b85b0ec20c225ce2c64c167cacb6e711daf2e45da4a8356a059b8160e3b3628ac0dd8437b31f06d53d6e8ea4214d4a26406a6b63e1001406ef23e0bb3069fac9a99a91f77dfafd5de0f188a5da5e3c9000511b42741726d696e204d2e205761726461203c7761726461406e657068696c696d2e727568722e64653e8900950105102e8936c705d1eb399e58489901013f0e03ff5a0c4f421e34fcfa388129166420c08cd76987bcdec6f01bd0271459a85cc22048820dd4e44ac2c7d23908d540f54facf1b36b0d9c20488781ce9dca856531e76e2e846826e9951338020a03a09b57aa5faa82e9267458bd76105399885ac35af7dc1cbb6aaed7c39e1039f3b5beda2c0e916bd38560509bab81235d1a0ead83b0020000` lxd-2.0.0/dist/src/golang.org/x/crypto/openpgp/packet/compressed_test.go0000644061062106075000000000160112702772344030743 0ustar00stgraberdomain admins00000000000000// 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" "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 != io.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" lxd-2.0.0/dist/src/golang.org/x/crypto/openpgp/packet/signature_v3_test.go0000644061062106075000000000532012702772344031212 0ustar00stgraberdomain admins00000000000000// Copyright 2013 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" "io" "io/ioutil" "testing" "golang.org/x/crypto/openpgp/armor" ) func TestSignatureV3Read(t *testing.T) { r := v3KeyReader(t) Read(r) // Skip public key Read(r) // Skip uid packet, err := Read(r) // Signature if err != nil { t.Error(err) return } sig, ok := packet.(*SignatureV3) if !ok || sig.SigType != SigTypeGenericCert || sig.PubKeyAlgo != PubKeyAlgoRSA || sig.Hash != crypto.MD5 { t.Errorf("failed to parse, got: %#v", packet) } } func TestSignatureV3Reserialize(t *testing.T) { r := v3KeyReader(t) Read(r) // Skip public key Read(r) // Skip uid packet, err := Read(r) if err != nil { t.Error(err) return } sig := packet.(*SignatureV3) out := new(bytes.Buffer) if err = sig.Serialize(out); err != nil { t.Errorf("error reserializing: %s", err) return } expected, err := ioutil.ReadAll(v3KeyReader(t)) if err != nil { t.Error(err) return } expected = expected[4+141+4+39:] // See pgpdump offsets below, this is where the sig starts if !bytes.Equal(expected, out.Bytes()) { t.Errorf("output doesn't match input (got vs expected):\n%s\n%s", hex.Dump(out.Bytes()), hex.Dump(expected)) } } func v3KeyReader(t *testing.T) io.Reader { armorBlock, err := armor.Decode(bytes.NewBufferString(keySigV3Armor)) if err != nil { t.Fatalf("armor Decode failed: %v", err) } return armorBlock.Body } // keySigV3Armor is some V3 public key I found in an SKS dump. // Old: Public Key Packet(tag 6)(141 bytes) // Ver 4 - new // Public key creation time - Fri Sep 16 17:13:54 CDT 1994 // Pub alg - unknown(pub 0) // Unknown public key(pub 0) // Old: User ID Packet(tag 13)(39 bytes) // User ID - Armin M. Warda // Old: Signature Packet(tag 2)(149 bytes) // Ver 4 - new // Sig type - unknown(05) // Pub alg - ElGamal Encrypt-Only(pub 16) // Hash alg - unknown(hash 46) // Hashed Sub: unknown(sub 81, critical)(1988 bytes) const keySigV3Armor = `-----BEGIN PGP PUBLIC KEY BLOCK----- Version: SKS 1.0.10 mI0CLnoYogAAAQQA1qwA2SuJwfQ5bCQ6u5t20ulnOtY0gykf7YjiK4LiVeRBwHjGq7v30tGV 5Qti7qqRW4Ww7CDCJc4sZMFnystucR2vLkXaSoNWoFm4Fg47NiisDdhDezHwbVPW6OpCFNSi ZAamtj4QAUBu8j4LswafrJqZqR9336/V3g8Yil2l48kABRG0J0FybWluIE0uIFdhcmRhIDx3 YXJkYUBuZXBoaWxpbS5ydWhyLmRlPoiVAgUQLok2xwXR6zmeWEiZAQE/DgP/WgxPQh40/Po4 gSkWZCDAjNdph7zexvAb0CcUWahcwiBIgg3U5ErCx9I5CNVA9U+s8bNrDZwgSIeBzp3KhWUx 524uhGgm6ZUTOAIKA6CbV6pfqoLpJnRYvXYQU5mIWsNa99wcu2qu18OeEDnztb7aLA6Ra9OF YFCbq4EjXRoOrYM= =LPjs -----END PGP PUBLIC KEY BLOCK-----` lxd-2.0.0/dist/src/golang.org/x/crypto/openpgp/packet/userid_test.go0000644061062106075000000000440412702772344030076 0ustar00stgraberdomain admins00000000000000// 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", ""}, {" sdfk", "", "", "email"}, {" John Smith ( Comment ) asdkflj < email > lksdfj", "John Smith", "Comment", "email"}, {" John Smith < email > lksdfj", "John Smith", "", "email"}, {"("}, {"foo", "bar", "", "foo (bar)"}, {"foo", "", "baz", "foo "}, {"", "bar", "baz", "(bar) "}, {"foo", "bar", "baz", "foo (bar) "}, } func TestNewUserId(t *testing.T) { for i, test := range newUserIdTests { uid := NewUserId(test.name, test.comment, test.email) if uid == nil { t.Errorf("#%d: returned nil", i) continue } if uid.Id != test.id { t.Errorf("#%d: got '%s', want '%s'", i, uid.Id, test.id) } } } var invalidNewUserIdTests = []struct { name, comment, email string }{ {"foo(", "", ""}, {"foo<", "", ""}, {"", "bar)", ""}, {"", "bar<", ""}, {"", "", "baz>"}, {"", "", "baz)"}, {"", "", "baz\x00"}, } func TestNewUserIdWithInvalidInput(t *testing.T) { for i, test := range invalidNewUserIdTests { if uid := NewUserId(test.name, test.comment, test.email); uid != nil { t.Errorf("#%d: returned non-nil value: %#v", i, uid) } } } lxd-2.0.0/dist/src/golang.org/x/crypto/openpgp/packet/userattribute_test.go0000644061062106075000000001336112702772344031507 0ustar00stgraberdomain admins00000000000000// 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/base64" "image/color" "image/jpeg" "testing" ) func TestParseUserAttribute(t *testing.T) { r := base64.NewDecoder(base64.StdEncoding, bytes.NewBufferString(userAttributePacket)) for i := 0; i < 2; i++ { p, err := Read(r) if err != nil { t.Fatal(err) } uat := p.(*UserAttribute) imgs := uat.ImageData() if len(imgs) != 1 { t.Errorf("Unexpected number of images in user attribute packet: %d", len(imgs)) } if len(imgs[0]) != 3395 { t.Errorf("Unexpected JPEG image size: %d", len(imgs[0])) } img, err := jpeg.Decode(bytes.NewBuffer(imgs[0])) if err != nil { t.Errorf("Error decoding JPEG image: %v", err) } // A pixel in my right eye. pixel := color.NRGBAModel.Convert(img.At(56, 36)) ref := color.NRGBA{R: 157, G: 128, B: 124, A: 255} if pixel != ref { t.Errorf("Unexpected pixel color: %v", pixel) } w := bytes.NewBuffer(nil) err = uat.Serialize(w) if err != nil { t.Errorf("Error writing user attribute: %v", err) } r = bytes.NewBuffer(w.Bytes()) } } const userAttributePacket = ` 0cyWzJQBEAABAQAAAAAAAAAAAAAAAP/Y/+AAEEpGSUYAAQIAAAEAAQAA/9sAQwAFAwQEBAMFBAQE BQUFBgcMCAcHBwcPCgsJDBEPEhIRDxEQExYcFxMUGhUQERghGBocHR8fHxMXIiQiHiQcHh8e/9sA QwEFBQUHBgcOCAgOHhQRFB4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4e Hh4eHh4eHh4e/8AAEQgAZABkAwEiAAIRAQMRAf/EAB8AAAEFAQEBAQEBAAAAAAAAAAABAgMEBQYH CAkKC//EALUQAAIBAwMCBAMFBQQEAAABfQECAwAEEQUSITFBBhNRYQcicRQygZGhCCNCscEVUtHw JDNicoIJChYXGBkaJSYnKCkqNDU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6 g4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2drh4uPk 5ebn6Onq8fLz9PX29/j5+v/EAB8BAAMBAQEBAQEBAQEAAAAAAAABAgMEBQYHCAkKC//EALURAAIB AgQEAwQHBQQEAAECdwABAgMRBAUhMQYSQVEHYXETIjKBCBRCkaGxwQkjM1LwFWJy0QoWJDThJfEX GBkaJicoKSo1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2d3h5eoKDhIWGh4iJipKT lJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uLj5OXm5+jp6vLz9PX2 9/j5+v/aAAwDAQACEQMRAD8A5uGP06VehQ4pIox04q5EnHSvAep+hIIl4zVuMHGPWmRrUWtalaaN pU2oXsgSGJSxPr6ClvoitErs0Itqjc7BQOpPAFYmrfEnwjojtHNqaXEynBjtx5hH4jj9a8B8d+Od W8UXZjWR4LJT+7t0Jwfc+prnIdO1CWZEW2mZ3HyDactXXDB3V5s8evm1namj6r0H4weCLtxG+ova ueP30RA/MV6not1bX0Ed1ZzxzwyDKvGwZSPqK+Ff+ES8R8t/ZV2oHUmM10Hgbxp4m8BatEfNnWBH /eWshOxx9Kmpg4te49RUM1kn+8Wh9zQ4P1FaMC7l465rjPh14y0fxnoseoaXOpfaPOgJ+eI98j09 67W19M15bi4uzPSqTU480WXkjZkAyAR61DPE6OCSOalWRRgZxjvTb598sfU4FBwx5uY4T4feIm8P TeJbAgc65NIM+8cX+FFeLfF3Vr3SfiNrMFrMypJMJcDPUqP8KK+kpVFyLU+ar037SXqX4hxVpMY7 1UhPpVlT2rybKx9smWYz3NeH/EDVLzxt40j8O6bITaQybPlbKkjq39K9O8fasdH8IahfKxWQRFIy Ou9uB/OuE/Z/0y3j1d9TuyoZCMs5xjuea1pLli5nn46q240l13PcfhN8EvDNtpcEl/CklyVBLuMk mvU/Dfwo0BL/AO13FjEDD/qyV7Vn+CvGPg8zRpJrVm8ikLtEg6+1ew2dxZ3EQaJgysuQPasH7eXW 1zzsbVhT92kk/PsYieEND+zlPs6c/wCyAPyryH4wfCPRtW0u6j+xRLOxLxSoADkDpXY+MPjJ4c0S 9k082d3O8ZKkxw5XI96ytK+IGk+IpFjRpod+Qq3C7QT6A1E6NenaXbqRg6rlLlqS0fRnxjpd1r/w w8afa7GWRPKbZLGeBKmeVNfZngLxNaeKfDdprVjxHcLlkJ5Vh1H5185/tDad9h8XOsqAw3Cb0cjq CfX61P8AsveKf7L8T3fhe5nxa3g324YniQdh9R/KuivTdSmp9TXB1/Z1nRlsfU249QBx1pWfcwI7 Cq6u2Ovamb9rYz16V5x7Psz5q/aJhZfibcupIElvE3H+7j+lFbXx9szP45jlUfeso8/99OKK9elL 3EeNVopzZVharCtxVRGGMk02S5JyFOB69zWTieypnL/GksfB+0cr9oQt69awPhPpD69Y3Ky3DWth CWluGU4LAdq3vibGs/g68BJygVxjrwRW5+ztoRv/AAs8EeCZnO/J/hzz/Kumi4wp3kePjlOdZKPY ml8Mvo6WM9ppi7J0EkQYMzkb1X0wW+bJHGACa+ivg14huZPCkjXUO6SImIYOQAP6UQ2sGneHmiWF CYoSAAuM8etXfhBpMr+EZ3SSNRcMx6ZxWdes6ytBGSwkMNFuo7pnP614Ut9Zn1C4uLySKcwObGFA Qnm4+XcR71h+CfDHiKCQWuv2YWFtw+bBZQD8rcE8n2Ney+GbGGQSM6I7xvtI681rXdp8hKRRp6t3 FYPE1VDlsY1nQjWdl+J8w/tOeDZZ/AMd/EGefTHyxxyYjwfyODXg3waRh8UtEcFh+8Jb8FNfZPxh Ak8J6nbPIsiyW7LnseK+Ofh99ptPHFnf2lu0y2twGcKuSEPB/Q1WHk50miq1o14TXU+xop+On61H NMC6Nis1LgsAcUTSt1APFcXJZn0EqmhyvxA037friTYziBV6f7Tf40Vr3k4aXLx5OMZIzRXZB2ik efJXbPHJJcnaD9aN2R1qoGO8/WkuLlIV+YjdjpXSonQ5lTxfiTwzqCnkeQxx9BWx+zPrQsrBFYja zEfrXL6lfie3khcjY6lSPUGud+G3iA6FrY0uQ/KJsA9gCa0jSvFpnBi6tpKSPu++nsIfDFxeXciR qIicscY4rxTwB8RUkn1axsPEf2LTYx85kTGzqCUP8VcJ47+JOs+I0Hhq1njjt/ufIeSvq1VtE+Gs eoaUbSHUrkHdu3WtuX5Ix81XRh7OL5jirVpV5Whdn0F8C/iX4auVn0i612T7bASoe8wjTAd89K9g vtSt5NMa4t5lkRhgOh3Dn6V8aaz8KZrIR3OlQ6r56LySmSxxz06Vo/CHx34h0rxBP4XvJ5AjK2RP nEbAEj6ZxjPrWM6fMmoswqJxqJ1VZnqHxn1NLPwveqWHmNC2BnnNcD8DfDkGi+CH1m+ijN1qMzNA 4GSIiAMf+hVxPxU8Tapc3c0F9MGCn5GU5BX0Pau3+HmrT3XgXSIJCBHDGdgAx1NYSpezha52Yauq 1dya2Wh2onAIwTj1p0lxxWWLkhRyCKWa5O3ORXOos9KVQluZm83j0oqi84JyWH50Vdmc7ep43d3I t1Z2Iz2FYdxeSTsxyRnvTdVuDNcNluM9KrKcg817NOnZGNbEXdkNckjrXGeIIprPxFFdRHAlIwem COtdmxrG8Q2cd/ZNExw45RvQ1bVjim+dWNzw7eaTD4mN3dndCQCo6hmI5zXpj/Ea/wBHjkh0kwRW xXEfl4yTxXzXZalJDL9nuWKMmRnHcV2Hh3WreCyYXW2SWQhd5P3F6n+lS43d2cTm6d7Ox9EWPxH1 ODQxPqWpCaSU/ukUc4z3/WvKW8UhviAdaMewYZG98gj9c1ymoa8LyWOJHwkTDaVPb0qpr+q2m6Nb cfvNo349az9mou9iZVXNWbub3jm98/Vza2ReV7lsJg/e3dsV654UR9N0K0sZP9ZDGFbHr3rzL4P+ H7rXfEEWr3I3W1qf3IYdW9fwqDxf4k8UeH/G95p08kscHmk25dPlZT0we9YTj7SXKjpw1aNG8mj3 FLv5ccU959ycnmvKPDnxB82YQarGsZPAlTp+IrvIr1ZIgySKwIyCOhFYTpyg9T0qWIhVV4svzPvf IdhgY4orPachj81FRdmtzxqdiZmJ9aQEgdqZcPtmbJ71DJcAZ5r20kkeXJtsfPIQDwPzrG1a+S3i LyHAHvmp7y7HOD1rlNdm+1T7Acovf3o+J2RMpezjzMvrob67pX9o2ShZlYgg/wAWKxZLLWLZ/Ke3 mVh14yK9M+BMC3dre2ko3LHKCB7EV7EngeGQJdQ7HyBkMKS0djgq1W3c+XtK03U522RwzsTwNiEk ntXoHgf4calql9El/G8UZbLfLyfr7V9FeGvh+s+0Lbxxcglu2K1NW1nwN4Gk/wBLuI57tV5jjwzE /QVNS+0dWYRqNvXRFv4eeCodKsY1ggVIY1G3K4z714h+1Jqul3GpwaXYeXJLbzgyyrg4b+6D+HNb vjz436zq9m+naHF/ZdkeGfOZXH17V4Vqt2b29K+ZuOc5bnce5zWdPBShL2lTfojSeJhy+zp/NjVz 1Bwa6DSfFGq6fbJFDKrov8DjPFcu97ZxsUe4jVhwVJ5Bpp1mwQiLewJPXacVq6fNpYyjOUXdHoKf EG8VQHsInbuVcgflRXnt5fIs2FYHgcgUVi8LG+xusdW/mN7U2KgEVkTzPt60UVfQ9eHxGHrV1MGi iD4V25x1qvdgLAMd6KK0pbHm4x++dp8FtUubLxJ5EIjMc+A4Za+qfD8pe1JZVOBmiinW3RyRPMfi R8QPE638+k2l6LK0Hylbddhb6nOa80mlkcmWR2kcnlnOSaKK7qCXKcNdu5narcSrAoBxvODWJIga VckjDdqKKwq/EaQ0gUdbjQ6mr7QGBUcd6tPBC6gtGpOOuKKKie5qn7qIpEXd0HSiiimSf//Z` lxd-2.0.0/dist/src/golang.org/x/crypto/openpgp/packet/signature_v3.go0000644061062106075000000000754012702772344030161 0ustar00stgraberdomain admins00000000000000// Copyright 2013 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" "encoding/binary" "fmt" "io" "strconv" "time" "golang.org/x/crypto/openpgp/errors" "golang.org/x/crypto/openpgp/s2k" ) // SignatureV3 represents older version 3 signatures. These signatures are less secure // than version 4 and should not be used to create new signatures. They are included // here for backwards compatibility to read and validate with older key material. // See RFC 4880, section 5.2.2. type SignatureV3 struct { SigType SignatureType CreationTime time.Time IssuerKeyId uint64 PubKeyAlgo PublicKeyAlgorithm Hash crypto.Hash HashTag [2]byte RSASignature parsedMPI DSASigR, DSASigS parsedMPI } func (sig *SignatureV3) parse(r io.Reader) (err error) { // RFC 4880, section 5.2.2 var buf [8]byte if _, err = readFull(r, buf[:1]); err != nil { return } if buf[0] < 2 || buf[0] > 3 { err = errors.UnsupportedError("signature packet version " + strconv.Itoa(int(buf[0]))) return } if _, err = readFull(r, buf[:1]); err != nil { return } if buf[0] != 5 { err = errors.UnsupportedError( "invalid hashed material length " + strconv.Itoa(int(buf[0]))) return } // Read hashed material: signature type + creation time if _, err = readFull(r, buf[:5]); err != nil { return } sig.SigType = SignatureType(buf[0]) t := binary.BigEndian.Uint32(buf[1:5]) sig.CreationTime = time.Unix(int64(t), 0) // Eight-octet Key ID of signer. if _, err = readFull(r, buf[:8]); err != nil { return } sig.IssuerKeyId = binary.BigEndian.Uint64(buf[:]) // Public-key and hash algorithm if _, err = readFull(r, buf[:2]); err != nil { return } sig.PubKeyAlgo = PublicKeyAlgorithm(buf[0]) switch sig.PubKeyAlgo { case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoDSA: default: err = errors.UnsupportedError("public key algorithm " + strconv.Itoa(int(sig.PubKeyAlgo))) return } var ok bool if sig.Hash, ok = s2k.HashIdToHash(buf[1]); !ok { return errors.UnsupportedError("hash function " + strconv.Itoa(int(buf[2]))) } // Two-octet field holding left 16 bits of signed hash value. if _, err = readFull(r, sig.HashTag[:2]); err != nil { return } switch sig.PubKeyAlgo { case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: sig.RSASignature.bytes, sig.RSASignature.bitLength, err = readMPI(r) case PubKeyAlgoDSA: if sig.DSASigR.bytes, sig.DSASigR.bitLength, err = readMPI(r); err != nil { return } sig.DSASigS.bytes, sig.DSASigS.bitLength, err = readMPI(r) default: panic("unreachable") } return } // Serialize marshals sig to w. Sign, SignUserId or SignKey must have been // called first. func (sig *SignatureV3) Serialize(w io.Writer) (err error) { buf := make([]byte, 8) // Write the sig type and creation time buf[0] = byte(sig.SigType) binary.BigEndian.PutUint32(buf[1:5], uint32(sig.CreationTime.Unix())) if _, err = w.Write(buf[:5]); err != nil { return } // Write the issuer long key ID binary.BigEndian.PutUint64(buf[:8], sig.IssuerKeyId) if _, err = w.Write(buf[:8]); err != nil { return } // Write public key algorithm, hash ID, and hash value buf[0] = byte(sig.PubKeyAlgo) hashId, ok := s2k.HashToHashId(sig.Hash) if !ok { return errors.UnsupportedError(fmt.Sprintf("hash function %v", sig.Hash)) } buf[1] = hashId copy(buf[2:4], sig.HashTag[:]) if _, err = w.Write(buf[:4]); err != nil { return } if sig.RSASignature.bytes == nil && sig.DSASigR.bytes == nil { return errors.InvalidArgumentError("Signature: need to call Sign, SignUserId or SignKey before Serialize") } switch sig.PubKeyAlgo { case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: err = writeMPIs(w, sig.RSASignature) case PubKeyAlgoDSA: err = writeMPIs(w, sig.DSASigR, sig.DSASigS) default: panic("impossible") } return } lxd-2.0.0/dist/src/golang.org/x/crypto/openpgp/packet/opaque.go0000644061062106075000000001001612702772344027032 0ustar00stgraberdomain admins00000000000000// Copyright 2012 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" "io" "io/ioutil" "golang.org/x/crypto/openpgp/errors" ) // OpaquePacket represents an OpenPGP packet as raw, unparsed data. This is // useful for splitting and storing the original packet contents separately, // handling unsupported packet types or accessing parts of the packet not yet // implemented by this package. type OpaquePacket struct { // Packet type Tag uint8 // Reason why the packet was parsed opaquely Reason error // Binary contents of the packet data Contents []byte } func (op *OpaquePacket) parse(r io.Reader) (err error) { op.Contents, err = ioutil.ReadAll(r) return } // Serialize marshals the packet to a writer in its original form, including // the packet header. func (op *OpaquePacket) Serialize(w io.Writer) (err error) { err = serializeHeader(w, packetType(op.Tag), len(op.Contents)) if err == nil { _, err = w.Write(op.Contents) } return } // Parse attempts to parse the opaque contents into a structure supported by // this package. If the packet is not known then the result will be another // OpaquePacket. func (op *OpaquePacket) Parse() (p Packet, err error) { hdr := bytes.NewBuffer(nil) err = serializeHeader(hdr, packetType(op.Tag), len(op.Contents)) if err != nil { op.Reason = err return op, err } p, err = Read(io.MultiReader(hdr, bytes.NewBuffer(op.Contents))) if err != nil { op.Reason = err p = op } return } // OpaqueReader reads OpaquePackets from an io.Reader. type OpaqueReader struct { r io.Reader } func NewOpaqueReader(r io.Reader) *OpaqueReader { return &OpaqueReader{r: r} } // Read the next OpaquePacket. func (or *OpaqueReader) Next() (op *OpaquePacket, err error) { tag, _, contents, err := readHeader(or.r) if err != nil { return } op = &OpaquePacket{Tag: uint8(tag), Reason: err} err = op.parse(contents) if err != nil { consumeAll(contents) } return } // OpaqueSubpacket represents an unparsed OpenPGP subpacket, // as found in signature and user attribute packets. type OpaqueSubpacket struct { SubType uint8 Contents []byte } // OpaqueSubpackets extracts opaque, unparsed OpenPGP subpackets from // their byte representation. func OpaqueSubpackets(contents []byte) (result []*OpaqueSubpacket, err error) { var ( subHeaderLen int subPacket *OpaqueSubpacket ) for len(contents) > 0 { subHeaderLen, subPacket, err = nextSubpacket(contents) if err != nil { break } result = append(result, subPacket) contents = contents[subHeaderLen+len(subPacket.Contents):] } return } func nextSubpacket(contents []byte) (subHeaderLen int, subPacket *OpaqueSubpacket, err error) { // RFC 4880, section 5.2.3.1 var subLen uint32 if len(contents) < 1 { goto Truncated } subPacket = &OpaqueSubpacket{} switch { case contents[0] < 192: subHeaderLen = 2 // 1 length byte, 1 subtype byte if len(contents) < subHeaderLen { goto Truncated } subLen = uint32(contents[0]) contents = contents[1:] case contents[0] < 255: subHeaderLen = 3 // 2 length bytes, 1 subtype if len(contents) < subHeaderLen { goto Truncated } subLen = uint32(contents[0]-192)<<8 + uint32(contents[1]) + 192 contents = contents[2:] default: subHeaderLen = 6 // 5 length bytes, 1 subtype if len(contents) < subHeaderLen { goto Truncated } subLen = uint32(contents[1])<<24 | uint32(contents[2])<<16 | uint32(contents[3])<<8 | uint32(contents[4]) contents = contents[5:] } if subLen > uint32(len(contents)) || subLen == 0 { goto Truncated } subPacket.SubType = contents[0] subPacket.Contents = contents[1:subLen] return Truncated: err = errors.StructuralError("subpacket truncated") return } func (osp *OpaqueSubpacket) Serialize(w io.Writer) (err error) { buf := make([]byte, 6) n := serializeSubpacketLength(buf, len(osp.Contents)+1) buf[n] = osp.SubType if _, err = w.Write(buf[:n+1]); err != nil { return } _, err = w.Write(osp.Contents) return } lxd-2.0.0/dist/src/golang.org/x/crypto/openpgp/packet/encrypted_key.go0000644061062106075000000001404212702772344030410 0ustar00stgraberdomain admins00000000000000// 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/rsa" "encoding/binary" "io" "math/big" "strconv" "golang.org/x/crypto/openpgp/elgamal" "golang.org/x/crypto/openpgp/errors" ) const encryptedKeyVersion = 3 // EncryptedKey represents a public-key encrypted session key. See RFC 4880, // section 5.1. type EncryptedKey struct { KeyId uint64 Algo PublicKeyAlgorithm CipherFunc CipherFunction // only valid after a successful Decrypt Key []byte // only valid after a successful Decrypt encryptedMPI1, encryptedMPI2 parsedMPI } func (e *EncryptedKey) parse(r io.Reader) (err error) { var buf [10]byte _, err = readFull(r, buf[:]) if err != nil { return } if buf[0] != encryptedKeyVersion { return errors.UnsupportedError("unknown EncryptedKey version " + strconv.Itoa(int(buf[0]))) } e.KeyId = binary.BigEndian.Uint64(buf[1:9]) e.Algo = PublicKeyAlgorithm(buf[9]) switch e.Algo { case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly: e.encryptedMPI1.bytes, e.encryptedMPI1.bitLength, err = readMPI(r) case PubKeyAlgoElGamal: e.encryptedMPI1.bytes, e.encryptedMPI1.bitLength, err = readMPI(r) if err != nil { return } e.encryptedMPI2.bytes, e.encryptedMPI2.bitLength, err = readMPI(r) } _, err = consumeAll(r) return } func checksumKeyMaterial(key []byte) uint16 { var checksum uint16 for _, v := range key { checksum += uint16(v) } return checksum } // Decrypt decrypts an encrypted session key with the given private key. The // private key must have been decrypted first. // If config is nil, sensible defaults will be used. func (e *EncryptedKey) Decrypt(priv *PrivateKey, config *Config) error { var err error var b []byte // TODO(agl): use session key decryption routines here to avoid // padding oracle attacks. switch priv.PubKeyAlgo { case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly: b, err = rsa.DecryptPKCS1v15(config.Random(), priv.PrivateKey.(*rsa.PrivateKey), e.encryptedMPI1.bytes) case PubKeyAlgoElGamal: c1 := new(big.Int).SetBytes(e.encryptedMPI1.bytes) c2 := new(big.Int).SetBytes(e.encryptedMPI2.bytes) b, err = elgamal.Decrypt(priv.PrivateKey.(*elgamal.PrivateKey), c1, c2) default: err = errors.InvalidArgumentError("cannot decrypted encrypted session key with private key of type " + strconv.Itoa(int(priv.PubKeyAlgo))) } if err != nil { return err } e.CipherFunc = CipherFunction(b[0]) e.Key = b[1 : len(b)-2] expectedChecksum := uint16(b[len(b)-2])<<8 | uint16(b[len(b)-1]) checksum := checksumKeyMaterial(e.Key) if checksum != expectedChecksum { return errors.StructuralError("EncryptedKey checksum incorrect") } return nil } // Serialize writes the encrypted key packet, e, to w. func (e *EncryptedKey) Serialize(w io.Writer) error { var mpiLen int switch e.Algo { case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly: mpiLen = 2 + len(e.encryptedMPI1.bytes) case PubKeyAlgoElGamal: mpiLen = 2 + len(e.encryptedMPI1.bytes) + 2 + len(e.encryptedMPI2.bytes) default: return errors.InvalidArgumentError("don't know how to serialize encrypted key type " + strconv.Itoa(int(e.Algo))) } serializeHeader(w, packetTypeEncryptedKey, 1 /* version */ +8 /* key id */ +1 /* algo */ +mpiLen) w.Write([]byte{encryptedKeyVersion}) binary.Write(w, binary.BigEndian, e.KeyId) w.Write([]byte{byte(e.Algo)}) switch e.Algo { case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly: writeMPIs(w, e.encryptedMPI1) case PubKeyAlgoElGamal: writeMPIs(w, e.encryptedMPI1, e.encryptedMPI2) default: panic("internal error") } return nil } // SerializeEncryptedKey serializes an encrypted key packet to w that contains // key, encrypted to pub. // If config is nil, sensible defaults will be used. func SerializeEncryptedKey(w io.Writer, pub *PublicKey, cipherFunc CipherFunction, key []byte, config *Config) error { var buf [10]byte buf[0] = encryptedKeyVersion binary.BigEndian.PutUint64(buf[1:9], pub.KeyId) buf[9] = byte(pub.PubKeyAlgo) keyBlock := make([]byte, 1 /* cipher type */ +len(key)+2 /* checksum */) keyBlock[0] = byte(cipherFunc) copy(keyBlock[1:], key) checksum := checksumKeyMaterial(key) keyBlock[1+len(key)] = byte(checksum >> 8) keyBlock[1+len(key)+1] = byte(checksum) switch pub.PubKeyAlgo { case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly: return serializeEncryptedKeyRSA(w, config.Random(), buf, pub.PublicKey.(*rsa.PublicKey), keyBlock) case PubKeyAlgoElGamal: return serializeEncryptedKeyElGamal(w, config.Random(), buf, pub.PublicKey.(*elgamal.PublicKey), keyBlock) case PubKeyAlgoDSA, PubKeyAlgoRSASignOnly: return errors.InvalidArgumentError("cannot encrypt to public key of type " + strconv.Itoa(int(pub.PubKeyAlgo))) } return errors.UnsupportedError("encrypting a key to public key of type " + strconv.Itoa(int(pub.PubKeyAlgo))) } func serializeEncryptedKeyRSA(w io.Writer, rand io.Reader, header [10]byte, pub *rsa.PublicKey, keyBlock []byte) error { cipherText, err := rsa.EncryptPKCS1v15(rand, pub, keyBlock) if err != nil { return errors.InvalidArgumentError("RSA encryption failed: " + err.Error()) } packetLen := 10 /* header length */ + 2 /* mpi size */ + len(cipherText) err = serializeHeader(w, packetTypeEncryptedKey, packetLen) if err != nil { return err } _, err = w.Write(header[:]) if err != nil { return err } return writeMPI(w, 8*uint16(len(cipherText)), cipherText) } func serializeEncryptedKeyElGamal(w io.Writer, rand io.Reader, header [10]byte, pub *elgamal.PublicKey, keyBlock []byte) error { c1, c2, err := elgamal.Encrypt(rand, pub, keyBlock) if err != nil { return errors.InvalidArgumentError("ElGamal encryption failed: " + err.Error()) } packetLen := 10 /* header length */ packetLen += 2 /* mpi size */ + (c1.BitLen()+7)/8 packetLen += 2 /* mpi size */ + (c2.BitLen()+7)/8 err = serializeHeader(w, packetTypeEncryptedKey, packetLen) if err != nil { return err } _, err = w.Write(header[:]) if err != nil { return err } err = writeBig(w, c1) if err != nil { return err } return writeBig(w, c2) } lxd-2.0.0/dist/src/golang.org/x/crypto/openpgp/packet/userid.go0000644061062106075000000000667612702772344027054 0ustar00stgraberdomain admins00000000000000// 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" "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) " type UserId struct { Id string // By convention, this takes the form "Full Name (Comment) " which is split out in the fields below. Name, Comment, Email string } func hasInvalidCharacters(s string) bool { for _, c := range s { switch c { case '(', ')', '<', '>', 0: return true } } return false } // NewUserId returns a UserId or nil if any of the arguments contain invalid // characters. The invalid characters are '\x00', '(', ')', '<' and '>' func NewUserId(name, comment, email string) *UserId { // RFC 4880 doesn't deal with the structure of userid strings; the // name, comment and email form is just a convention. However, there's // no convention about escaping the metacharacters and GPG just refuses // to create user ids where, say, the name contains a '('. We mirror // this behaviour. if hasInvalidCharacters(name) || hasInvalidCharacters(comment) || hasInvalidCharacters(email) { return nil } uid := new(UserId) uid.Name, uid.Comment, uid.Email = name, comment, email uid.Id = name if len(comment) > 0 { if len(uid.Id) > 0 { uid.Id += " " } uid.Id += "(" uid.Id += comment uid.Id += ")" } if len(email) > 0 { if len(uid.Id) > 0 { uid.Id += " " } uid.Id += "<" uid.Id += email uid.Id += ">" } return uid } func (uid *UserId) parse(r io.Reader) (err 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 } // Serialize marshals uid to w in the form of an OpenPGP packet, including // header. func (uid *UserId) Serialize(w io.Writer) error { err := serializeHeader(w, packetTypeUserId, len(uid.Id)) if err != nil { return err } _, err = w.Write([]byte(uid.Id)) return err } // parseUserId extracts the name, comment and email from a user id string that // is formatted as "Full Name (Comment) ". 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 } lxd-2.0.0/dist/src/golang.org/x/crypto/openpgp/packet/config.go0000644061062106075000000000501112702772344027004 0ustar00stgraberdomain admins00000000000000// Copyright 2012 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/rand" "io" "time" ) // Config collects a number of parameters along with sensible defaults. // A nil *Config is valid and results in all default values. type Config struct { // Rand provides the source of entropy. // If nil, the crypto/rand Reader is used. Rand io.Reader // DefaultHash is the default hash function to be used. // If zero, SHA-256 is used. DefaultHash crypto.Hash // DefaultCipher is the cipher to be used. // If zero, AES-128 is used. DefaultCipher CipherFunction // Time returns the current time as the number of seconds since the // epoch. If Time is nil, time.Now is used. Time func() time.Time // DefaultCompressionAlgo is the compression algorithm to be // applied to the plaintext before encryption. If zero, no // compression is done. DefaultCompressionAlgo CompressionAlgo // CompressionConfig configures the compression settings. CompressionConfig *CompressionConfig // S2KCount is only used for symmetric encryption. It // determines the strength of the passphrase stretching when // the said passphrase is hashed to produce a key. S2KCount // should be between 1024 and 65011712, inclusive. If Config // is nil or S2KCount is 0, the value 65536 used. Not all // values in the above range can be represented. S2KCount will // be rounded up to the next representable value if it cannot // be encoded exactly. When set, it is strongly encrouraged to // use a value that is at least 65536. See RFC 4880 Section // 3.7.1.3. S2KCount int // RSABits is the number of bits in new RSA keys made with NewEntity. // If zero, then 2048 bit keys are created. RSABits int } func (c *Config) Random() io.Reader { if c == nil || c.Rand == nil { return rand.Reader } return c.Rand } func (c *Config) Hash() crypto.Hash { if c == nil || uint(c.DefaultHash) == 0 { return crypto.SHA256 } return c.DefaultHash } func (c *Config) Cipher() CipherFunction { if c == nil || uint8(c.DefaultCipher) == 0 { return CipherAES128 } return c.DefaultCipher } func (c *Config) Now() time.Time { if c == nil || c.Time == nil { return time.Now() } return c.Time() } func (c *Config) Compression() CompressionAlgo { if c == nil { return CompressionNone } return c.DefaultCompressionAlgo } func (c *Config) PasswordHashIterations() int { if c == nil || c.S2KCount == 0 { return 0 } return c.S2KCount } lxd-2.0.0/dist/src/golang.org/x/crypto/openpgp/packet/compressed.go0000644061062106075000000000633112702772344027711 0ustar00stgraberdomain admins00000000000000// 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/bzip2" "compress/flate" "compress/zlib" "golang.org/x/crypto/openpgp/errors" "io" "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 } const ( NoCompression = flate.NoCompression BestSpeed = flate.BestSpeed BestCompression = flate.BestCompression DefaultCompression = flate.DefaultCompression ) // CompressionConfig contains compressor configuration settings. type CompressionConfig struct { // Level is the compression level to use. It must be set to // between -1 and 9, with -1 causing the compressor to use the // default compression level, 0 causing the compressor to use // no compression and 1 to 9 representing increasing (better, // slower) compression levels. If Level is less than -1 or // more then 9, a non-nil error will be returned during // encryption. See the constants above for convenient common // settings for Level. Level int } func (c *Compressed) parse(r io.Reader) 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) case 3: c.Body = bzip2.NewReader(r) default: err = errors.UnsupportedError("unknown compression algorithm: " + strconv.Itoa(int(buf[0]))) } return err } // compressedWriterCloser represents the serialized compression stream // header and the compressor. Its Close() method ensures that both the // compressor and serialized stream header are closed. Its Write() // method writes to the compressor. type compressedWriteCloser struct { sh io.Closer // Stream Header c io.WriteCloser // Compressor } func (cwc compressedWriteCloser) Write(p []byte) (int, error) { return cwc.c.Write(p) } func (cwc compressedWriteCloser) Close() (err error) { err = cwc.c.Close() if err != nil { return err } return cwc.sh.Close() } // SerializeCompressed serializes a compressed data packet to w and // returns a WriteCloser to which the literal data packets themselves // can be written and which MUST be closed on completion. If cc is // nil, sensible defaults will be used to configure the compression // algorithm. func SerializeCompressed(w io.WriteCloser, algo CompressionAlgo, cc *CompressionConfig) (literaldata io.WriteCloser, err error) { compressed, err := serializeStreamHeader(w, packetTypeCompressed) if err != nil { return } _, err = compressed.Write([]byte{uint8(algo)}) if err != nil { return } level := DefaultCompression if cc != nil { level = cc.Level } var compressor io.WriteCloser switch algo { case CompressionZIP: compressor, err = flate.NewWriter(compressed, level) case CompressionZLIB: compressor, err = zlib.NewWriterLevel(compressed, level) default: s := strconv.Itoa(int(algo)) err = errors.UnsupportedError("Unsupported compression algorithm: " + s) } if err != nil { return } literaldata = compressedWriteCloser{compressed, compressor} return } lxd-2.0.0/dist/src/golang.org/x/crypto/openpgp/packet/reader.go0000644061062106075000000000423312702772344027006 0ustar00stgraberdomain admins00000000000000// 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 ( "golang.org/x/crypto/openpgp/errors" "io" ) // 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 } // New io.Readers are pushed when a compressed or encrypted packet is processed // and recursively treated as a new source of packets. However, a carefully // crafted packet can trigger an infinite recursive sequence of packets. See // http://mumble.net/~campbell/misc/pgp-quine // https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2013-4402 // This constant limits the number of recursive packets that may be pushed. const maxReaders = 32 // 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 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 == io.EOF { r.readers = r.readers[:len(r.readers)-1] continue } if _, ok := err.(errors.UnknownPacketTypeError); !ok { return nil, err } } return nil, io.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. Push returns a StructuralError // if pushing the reader would exceed the maximum recursion level, otherwise it // returns nil. func (r *Reader) Push(reader io.Reader) (err error) { if len(r.readers) >= maxReaders { return errors.StructuralError("too many layers of packets") } r.readers = append(r.readers, reader) return nil } // 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}, } } lxd-2.0.0/dist/src/golang.org/x/crypto/openpgp/packet/symmetrically_encrypted.go0000644061062106075000000001611412702772344032520 0ustar00stgraberdomain admins00000000000000// 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/sha1" "crypto/subtle" "golang.org/x/crypto/openpgp/errors" "hash" "io" "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 } const symmetricallyEncryptedVersion = 1 func (se *SymmetricallyEncrypted) parse(r io.Reader) 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] != symmetricallyEncryptedVersion { return errors.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, error) { keySize := c.KeySize() if keySize == 0 { return nil, errors.UnsupportedError("unknown cipher: " + strconv.Itoa(int(c))) } if len(key) != keySize { return nil, errors.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, errors.InvalidArgumentError("can't try ciphers with different block lengths") } ocfbResync := OCFBResync if se.MDC { // MDC packets use a different form of OCFB mode. ocfbResync = OCFBNoResync } s := NewOCFBDecrypter(c.new(key), se.prefix, ocfbResync) if s == nil { return nil, errors.ErrKeyIncorrect } 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, error) { return ser.in.Read(buf) } func (ser seReader) Close() 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 error) { if ser.error { err = io.ErrUnexpectedEOF return } if ser.eof { err = io.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 == io.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 = io.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 == io.EOF { ser.eof = true } return } // This is a new-format packet tag byte for a type 19 (MDC) packet. const mdcPacketTagByte = byte(0x80) | 0x40 | 19 func (ser *seMDCReader) Close() error { if ser.error { return errors.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 == io.EOF { break } if err != nil { return errors.SignatureError("error during reading") } } if ser.trailer[0] != mdcPacketTagByte || ser.trailer[1] != sha1.Size { return errors.SignatureError("MDC packet not found") } ser.h.Write(ser.trailer[:2]) final := ser.h.Sum(nil) if subtle.ConstantTimeCompare(final, ser.trailer[2:]) != 1 { return errors.SignatureError("hash mismatch") } return nil } // An seMDCWriter writes through to an io.WriteCloser while maintains a running // hash of the data written. On close, it emits an MDC packet containing the // running hash. type seMDCWriter struct { w io.WriteCloser h hash.Hash } func (w *seMDCWriter) Write(buf []byte) (n int, err error) { w.h.Write(buf) return w.w.Write(buf) } func (w *seMDCWriter) Close() (err error) { var buf [mdcTrailerSize]byte buf[0] = mdcPacketTagByte buf[1] = sha1.Size w.h.Write(buf[:2]) digest := w.h.Sum(nil) copy(buf[2:], digest) _, err = w.w.Write(buf[:]) if err != nil { return } return w.w.Close() } // noOpCloser is like an ioutil.NopCloser, but for an io.Writer. type noOpCloser struct { w io.Writer } func (c noOpCloser) Write(data []byte) (n int, err error) { return c.w.Write(data) } func (c noOpCloser) Close() error { return nil } // SerializeSymmetricallyEncrypted serializes a symmetrically encrypted packet // to w and returns a WriteCloser to which the to-be-encrypted packets can be // written. // If config is nil, sensible defaults will be used. func SerializeSymmetricallyEncrypted(w io.Writer, c CipherFunction, key []byte, config *Config) (contents io.WriteCloser, err error) { if c.KeySize() != len(key) { return nil, errors.InvalidArgumentError("SymmetricallyEncrypted.Serialize: bad key length") } writeCloser := noOpCloser{w} ciphertext, err := serializeStreamHeader(writeCloser, packetTypeSymmetricallyEncryptedMDC) if err != nil { return } _, err = ciphertext.Write([]byte{symmetricallyEncryptedVersion}) if err != nil { return } block := c.new(key) blockSize := block.BlockSize() iv := make([]byte, blockSize) _, err = config.Random().Read(iv) if err != nil { return } s, prefix := NewOCFBEncrypter(block, iv, OCFBNoResync) _, err = ciphertext.Write(prefix) if err != nil { return } plaintext := cipher.StreamWriter{S: s, W: ciphertext} h := sha1.New() h.Write(iv) h.Write(iv[blockSize-2:]) contents = &seMDCWriter{w: plaintext, h: h} return } lxd-2.0.0/dist/src/golang.org/x/crypto/openpgp/packet/public_key_v3_test.go0000644061062106075000000000447612702772344031352 0ustar00stgraberdomain admins00000000000000// Copyright 2013 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" "time" ) var pubKeyV3Test = struct { hexFingerprint string creationTime time.Time pubKeyAlgo PublicKeyAlgorithm keyId uint64 keyIdString string keyIdShort string }{ "103BECF5BD1E837C89D19E98487767F7", time.Unix(779753634, 0), PubKeyAlgoRSA, 0xDE0F188A5DA5E3C9, "DE0F188A5DA5E3C9", "5DA5E3C9"} func TestPublicKeyV3Read(t *testing.T) { i, test := 0, pubKeyV3Test packet, err := Read(v3KeyReader(t)) if err != nil { t.Fatalf("#%d: Read error: %s", i, err) } pk, ok := packet.(*PublicKeyV3) if !ok { t.Fatalf("#%d: failed to parse, got: %#v", i, packet) } if pk.PubKeyAlgo != test.pubKeyAlgo { t.Errorf("#%d: bad public key algorithm got:%x want:%x", i, pk.PubKeyAlgo, test.pubKeyAlgo) } if !pk.CreationTime.Equal(test.creationTime) { t.Errorf("#%d: bad creation time got:%v want:%v", 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) } if g, e := pk.KeyIdString(), test.keyIdString; g != e { t.Errorf("#%d: bad KeyIdString got:%q want:%q", i, g, e) } if g, e := pk.KeyIdShortString(), test.keyIdShort; g != e { t.Errorf("#%d: bad KeyIdShortString got:%q want:%q", i, g, e) } } func TestPublicKeyV3Serialize(t *testing.T) { //for i, test := range pubKeyV3Tests { i := 0 packet, err := Read(v3KeyReader(t)) if err != nil { t.Fatalf("#%d: Read error: %s", i, err) } pk, ok := packet.(*PublicKeyV3) if !ok { t.Fatalf("#%d: failed to parse, got: %#v", i, packet) } var serializeBuf bytes.Buffer if err = pk.Serialize(&serializeBuf); err != nil { t.Fatalf("#%d: failed to serialize: %s", i, err) } if packet, err = Read(bytes.NewBuffer(serializeBuf.Bytes())); err != nil { t.Fatalf("#%d: Read error (from serialized data): %s", i, err) } if pk, ok = packet.(*PublicKeyV3); !ok { t.Fatalf("#%d: failed to parse serialized data, got: %#v", i, packet) } } lxd-2.0.0/dist/src/golang.org/x/crypto/openpgp/packet/packet.go0000644061062106075000000003247112702772344027020 0ustar00stgraberdomain admins00000000000000// 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 implements parsing and serialization of OpenPGP packets, as // specified in RFC 4880. package packet // import "golang.org/x/crypto/openpgp/packet" import ( "bufio" "crypto/aes" "crypto/cipher" "crypto/des" "golang.org/x/crypto/cast5" "golang.org/x/crypto/openpgp/errors" "io" "math/big" ) // 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 error) { n, err = io.ReadFull(r, buf) if err == io.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 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 error) { for r.remaining == 0 { if !r.isPartial { return 0, io.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 == io.EOF { err = io.ErrUnexpectedEOF } return } // partialLengthWriter writes a stream of data using OpenPGP partial lengths. // See RFC 4880, section 4.2.2.4. type partialLengthWriter struct { w io.WriteCloser lengthByte [1]byte } func (w *partialLengthWriter) Write(p []byte) (n int, err error) { for len(p) > 0 { for power := uint(14); power < 32; power-- { l := 1 << power if len(p) >= l { w.lengthByte[0] = 224 + uint8(power) _, err = w.w.Write(w.lengthByte[:]) if err != nil { return } var m int m, err = w.w.Write(p[:l]) n += m if err != nil { return } p = p[l:] break } } } return } func (w *partialLengthWriter) Close() error { w.lengthByte[0] = 0 _, err := w.w.Write(w.lengthByte[:]) if err != nil { return err } return w.w.Close() } // 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 error) { if l.n <= 0 { return 0, io.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 == io.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 error) { var buf [4]byte _, err = io.ReadFull(r, buf[:1]) if err != nil { return } if buf[0]&0x80 == 0 { err = errors.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 } // serializeHeader writes an OpenPGP packet header to w. See RFC 4880, section // 4.2. func serializeHeader(w io.Writer, ptype packetType, length int) (err error) { var buf [6]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] = 192 + byte(length>>8) buf[2] = byte(length) n = 3 } else { buf[1] = 255 buf[2] = byte(length >> 24) buf[3] = byte(length >> 16) buf[4] = byte(length >> 8) buf[5] = byte(length) n = 6 } _, err = w.Write(buf[:n]) return } // serializeStreamHeader writes an OpenPGP packet header to w where the // length of the packet is unknown. It returns a io.WriteCloser which can be // used to write the contents of the packet. See RFC 4880, section 4.2. func serializeStreamHeader(w io.WriteCloser, ptype packetType) (out io.WriteCloser, err error) { var buf [1]byte buf[0] = 0x80 | 0x40 | byte(ptype) _, err = w.Write(buf[:]) if err != nil { return } out = &partialLengthWriter{w: w} 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) error } // consumeAll reads from the given Reader until error, returning the number of // bytes read. func consumeAll(r io.Reader) (n int64, err error) { var m int var buf [1024]byte for { m, err = r.Read(buf[:]) n += int64(m) if err == io.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 packetTypeUserAttribute packetType = 17 packetTypeSymmetricallyEncryptedMDC packetType = 18 ) // peekVersion detects the version of a public key packet about to // be read. A bufio.Reader at the original position of the io.Reader // is returned. func peekVersion(r io.Reader) (bufr *bufio.Reader, ver byte, err error) { bufr = bufio.NewReader(r) var verBuf []byte if verBuf, err = bufr.Peek(1); err != nil { return } ver = verBuf[0] return } // 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 error) { tag, _, contents, err := readHeader(r) if err != nil { return } switch tag { case packetTypeEncryptedKey: p = new(EncryptedKey) case packetTypeSignature: var version byte // Detect signature version if contents, version, err = peekVersion(contents); err != nil { return } if version < 4 { p = new(SignatureV3) } else { 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: var version byte if contents, version, err = peekVersion(contents); err != nil { return } isSubkey := tag == packetTypePublicSubkey if version < 4 { p = &PublicKeyV3{IsSubkey: isSubkey} } else { p = &PublicKey{IsSubkey: isSubkey} } case packetTypeCompressed: p = new(Compressed) case packetTypeSymmetricallyEncrypted: p = new(SymmetricallyEncrypted) case packetTypeLiteralData: p = new(LiteralData) case packetTypeUserId: p = new(UserId) case packetTypeUserAttribute: p = new(UserAttribute) case packetTypeSymmetricallyEncryptedMDC: se := new(SymmetricallyEncrypted) se.MDC = true p = se default: err = errors.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 SigTypePrimaryKeyBinding = 0x19 SigTypeDirectSignature = 0x1F SigTypeKeyRevocation = 0x20 SigTypeSubkeyRevocation = 0x28 ) // 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 // RFC 6637, Section 5. PubKeyAlgoECDH PublicKeyAlgorithm = 18 PubKeyAlgoECDSA PublicKeyAlgorithm = 19 ) // CanEncrypt returns true if it's possible to encrypt a message to a public // key of the given type. func (pka PublicKeyAlgorithm) CanEncrypt() bool { switch pka { case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoElGamal: return true } return false } // CanSign returns true if it's possible for a public key of the given type to // sign a message. func (pka PublicKeyAlgorithm) CanSign() bool { switch pka { case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoDSA, PubKeyAlgoECDSA: return true } return false } // 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 ( Cipher3DES CipherFunction = 2 CipherCAST5 CipherFunction = 3 CipherAES128 CipherFunction = 7 CipherAES192 CipherFunction = 8 CipherAES256 CipherFunction = 9 ) // KeySize returns the key size, in bytes, of cipher. func (cipher CipherFunction) KeySize() int { switch cipher { case Cipher3DES: return 24 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 Cipher3DES: return des.BlockSize 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 Cipher3DES: block, _ = des.NewTripleDESCipher(key) 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 // reserialized exactly. func readMPI(r io.Reader) (mpi []byte, bitLength uint16, err 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 } // mpiLength returns the length of the given *big.Int when serialized as an // MPI. func mpiLength(n *big.Int) (mpiLengthInBytes int) { mpiLengthInBytes = 2 /* MPI length */ mpiLengthInBytes += (n.BitLen() + 7) / 8 return } // writeMPI serializes a big integer to w. func writeMPI(w io.Writer, bitLength uint16, mpiBytes []byte) (err error) { _, err = w.Write([]byte{byte(bitLength >> 8), byte(bitLength)}) if err == nil { _, err = w.Write(mpiBytes) } return } // writeBig serializes a *big.Int to w. func writeBig(w io.Writer, i *big.Int) error { return writeMPI(w, uint16(i.BitLen()), i.Bytes()) } // CompressionAlgo Represents the different compression algorithms // supported by OpenPGP (except for BZIP2, which is not currently // supported). See Section 9.3 of RFC 4880. type CompressionAlgo uint8 const ( CompressionNone CompressionAlgo = 0 CompressionZIP CompressionAlgo = 1 CompressionZLIB CompressionAlgo = 2 ) lxd-2.0.0/dist/src/golang.org/x/crypto/openpgp/packet/symmetric_key_encrypted.go0000644061062106075000000001115212702772344032503 0ustar00stgraberdomain admins00000000000000// 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/cipher" "io" "strconv" "golang.org/x/crypto/openpgp/errors" "golang.org/x/crypto/openpgp/s2k" ) // 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 s2k func(out, in []byte) encryptedKey []byte } const symmetricKeyEncryptedVersion = 4 func (ske *SymmetricKeyEncrypted) parse(r io.Reader) error { // RFC 4880, section 5.3. var buf [2]byte if _, err := readFull(r, buf[:]); err != nil { return err } if buf[0] != symmetricKeyEncryptedVersion { return errors.UnsupportedError("SymmetricKeyEncrypted version") } ske.CipherFunc = CipherFunction(buf[1]) if ske.CipherFunc.KeySize() == 0 { return errors.UnsupportedError("unknown cipher: " + strconv.Itoa(int(buf[1]))) } var err error ske.s2k, err = s2k.Parse(r) if err != nil { return err } 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 } if n != 0 { if n == maxSessionKeySizeInBytes { return errors.UnsupportedError("oversized encrypted session key") } ske.encryptedKey = encryptedKey[:n] } return nil } // Decrypt attempts to decrypt an encrypted session key and returns the key and // the cipher to use when decrypting a subsequent Symmetrically Encrypted Data // packet. func (ske *SymmetricKeyEncrypted) Decrypt(passphrase []byte) ([]byte, CipherFunction, error) { key := make([]byte, ske.CipherFunc.KeySize()) ske.s2k(key, passphrase) if len(ske.encryptedKey) == 0 { return key, ske.CipherFunc, nil } // the IV is all zeros iv := make([]byte, ske.CipherFunc.blockSize()) c := cipher.NewCFBDecrypter(ske.CipherFunc.new(key), iv) plaintextKey := make([]byte, len(ske.encryptedKey)) c.XORKeyStream(plaintextKey, ske.encryptedKey) cipherFunc := CipherFunction(plaintextKey[0]) if cipherFunc.blockSize() == 0 { return nil, ske.CipherFunc, errors.UnsupportedError("unknown cipher: " + strconv.Itoa(int(cipherFunc))) } plaintextKey = plaintextKey[1:] if l := len(plaintextKey); l == 0 || l%cipherFunc.blockSize() != 0 { return nil, cipherFunc, errors.StructuralError("length of decrypted key not a multiple of block size") } return plaintextKey, cipherFunc, nil } // SerializeSymmetricKeyEncrypted serializes a symmetric key packet to w. The // packet contains a random session key, encrypted by a key derived from the // given passphrase. The session key is returned and must be passed to // SerializeSymmetricallyEncrypted. // If config is nil, sensible defaults will be used. func SerializeSymmetricKeyEncrypted(w io.Writer, passphrase []byte, config *Config) (key []byte, err error) { cipherFunc := config.Cipher() keySize := cipherFunc.KeySize() if keySize == 0 { return nil, errors.UnsupportedError("unknown cipher: " + strconv.Itoa(int(cipherFunc))) } s2kBuf := new(bytes.Buffer) keyEncryptingKey := make([]byte, keySize) // s2k.Serialize salts and stretches the passphrase, and writes the // resulting key to keyEncryptingKey and the s2k descriptor to s2kBuf. err = s2k.Serialize(s2kBuf, keyEncryptingKey, config.Random(), passphrase, &s2k.Config{Hash: config.Hash(), S2KCount: config.PasswordHashIterations()}) if err != nil { return } s2kBytes := s2kBuf.Bytes() packetLength := 2 /* header */ + len(s2kBytes) + 1 /* cipher type */ + keySize err = serializeHeader(w, packetTypeSymmetricKeyEncrypted, packetLength) if err != nil { return } var buf [2]byte buf[0] = symmetricKeyEncryptedVersion buf[1] = byte(cipherFunc) _, err = w.Write(buf[:]) if err != nil { return } _, err = w.Write(s2kBytes) if err != nil { return } sessionKey := make([]byte, keySize) _, err = io.ReadFull(config.Random(), sessionKey) if err != nil { return } iv := make([]byte, cipherFunc.blockSize()) c := cipher.NewCFBEncrypter(cipherFunc.new(keyEncryptingKey), iv) encryptedCipherAndKey := make([]byte, keySize+1) c.XORKeyStream(encryptedCipherAndKey, buf[1:]) c.XORKeyStream(encryptedCipherAndKey[1:], sessionKey) _, err = w.Write(encryptedCipherAndKey) if err != nil { return } key = sessionKey return } lxd-2.0.0/dist/src/golang.org/x/crypto/openpgp/packet/signature.go0000644061062106075000000005121012702772344027542 0ustar00stgraberdomain admins00000000000000// 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" "crypto/dsa" "crypto/ecdsa" "crypto/rsa" "encoding/binary" "hash" "io" "strconv" "time" "golang.org/x/crypto/openpgp/errors" "golang.org/x/crypto/openpgp/s2k" ) const ( // See RFC 4880, section 5.2.3.21 for details. KeyFlagCertify = 1 << iota KeyFlagSign KeyFlagEncryptCommunications KeyFlagEncryptStorage ) // 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 time.Time RSASignature parsedMPI DSASigR, DSASigS parsedMPI ECDSASigR, ECDSASigS parsedMPI // rawSubpackets contains the unparsed subpackets, in order. rawSubpackets []outputSubpacket // 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 // RevocationReason is set if this signature has been revoked. // See RFC 4880, section 5.2.3.23 for details. RevocationReason *uint8 RevocationReasonText string // MDC is set if this signature has a feature packet that indicates // support for MDC subpackets. MDC bool // EmbeddedSignature, if non-nil, is a signature of the parent key, by // this key. This prevents an attacker from claiming another's signing // subkey as their own. EmbeddedSignature *Signature outSubpackets []outputSubpacket } func (sig *Signature) parse(r io.Reader) (err 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 = errors.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, PubKeyAlgoDSA, PubKeyAlgoECDSA: default: err = errors.UnsupportedError("public key algorithm " + strconv.Itoa(int(sig.PubKeyAlgo))) return } var ok bool sig.Hash, ok = s2k.HashIdToHash(buf[2]) if !ok { return errors.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 } switch sig.PubKeyAlgo { case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: sig.RSASignature.bytes, sig.RSASignature.bitLength, err = readMPI(r) case PubKeyAlgoDSA: sig.DSASigR.bytes, sig.DSASigR.bitLength, err = readMPI(r) if err == nil { sig.DSASigS.bytes, sig.DSASigS.bitLength, err = readMPI(r) } case PubKeyAlgoECDSA: sig.ECDSASigR.bytes, sig.ECDSASigR.bitLength, err = readMPI(r) if err == nil { sig.ECDSASigS.bytes, sig.ECDSASigS.bitLength, err = readMPI(r) } default: panic("unreachable") } 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 error) { for len(subpackets) > 0 { subpackets, err = parseSignatureSubpacket(sig, subpackets, isHashed) if err != nil { return } } if sig.CreationTime.IsZero() { err = errors.StructuralError("no creation time in signature") } return } type signatureSubpacketType uint8 const ( creationTimeSubpacket signatureSubpacketType = 2 signatureExpirationSubpacket signatureSubpacketType = 3 keyExpirationSubpacket signatureSubpacketType = 9 prefSymmetricAlgosSubpacket signatureSubpacketType = 11 issuerSubpacket signatureSubpacketType = 16 prefHashAlgosSubpacket signatureSubpacketType = 21 prefCompressionSubpacket signatureSubpacketType = 22 primaryUserIdSubpacket signatureSubpacketType = 25 keyFlagsSubpacket signatureSubpacketType = 27 reasonForRevocationSubpacket signatureSubpacketType = 29 featuresSubpacket signatureSubpacketType = 30 embeddedSignatureSubpacket signatureSubpacketType = 32 ) // parseSignatureSubpacket parses a single subpacket. len(subpacket) is >= 1. func parseSignatureSubpacket(sig *Signature, subpacket []byte, isHashed bool) (rest []byte, err error) { // RFC 4880, section 5.2.3.1 var ( length uint32 packetType signatureSubpacketType isCritical bool ) 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 = errors.StructuralError("zero length signature subpacket") return } packetType = signatureSubpacketType(subpacket[0] & 0x7f) isCritical = subpacket[0]&0x80 == 0x80 subpacket = subpacket[1:] sig.rawSubpackets = append(sig.rawSubpackets, outputSubpacket{isHashed, packetType, isCritical, subpacket}) switch packetType { case creationTimeSubpacket: if !isHashed { err = errors.StructuralError("signature creation time in non-hashed area") return } if len(subpacket) != 4 { err = errors.StructuralError("signature creation time not four bytes") return } t := binary.BigEndian.Uint32(subpacket) sig.CreationTime = time.Unix(int64(t), 0) case signatureExpirationSubpacket: // Signature expiration time, section 5.2.3.10 if !isHashed { return } if len(subpacket) != 4 { err = errors.StructuralError("expiration subpacket with bad length") return } sig.SigLifetimeSecs = new(uint32) *sig.SigLifetimeSecs = binary.BigEndian.Uint32(subpacket) case keyExpirationSubpacket: // Key expiration time, section 5.2.3.6 if !isHashed { return } if len(subpacket) != 4 { err = errors.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 = errors.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 = errors.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 = errors.StructuralError("empty key flags subpacket") return } sig.FlagsValid = true if subpacket[0]&KeyFlagCertify != 0 { sig.FlagCertify = true } if subpacket[0]&KeyFlagSign != 0 { sig.FlagSign = true } if subpacket[0]&KeyFlagEncryptCommunications != 0 { sig.FlagEncryptCommunications = true } if subpacket[0]&KeyFlagEncryptStorage != 0 { sig.FlagEncryptStorage = true } case reasonForRevocationSubpacket: // Reason For Revocation, section 5.2.3.23 if !isHashed { return } if len(subpacket) == 0 { err = errors.StructuralError("empty revocation reason subpacket") return } sig.RevocationReason = new(uint8) *sig.RevocationReason = subpacket[0] sig.RevocationReasonText = string(subpacket[1:]) case featuresSubpacket: // Features subpacket, section 5.2.3.24 specifies a very general // mechanism for OpenPGP implementations to signal support for new // features. In practice, the subpacket is used exclusively to // indicate support for MDC-protected encryption. sig.MDC = len(subpacket) >= 1 && subpacket[0]&1 == 1 case embeddedSignatureSubpacket: // Only usage is in signatures that cross-certify // signing subkeys. section 5.2.3.26 describes the // format, with its usage described in section 11.1 if sig.EmbeddedSignature != nil { err = errors.StructuralError("Cannot have multiple embedded signatures") return } sig.EmbeddedSignature = new(Signature) // Embedded signatures are required to be v4 signatures see // section 12.1. However, we only parse v4 signatures in this // file anyway. if err := sig.EmbeddedSignature.parse(bytes.NewBuffer(subpacket)); err != nil { return nil, err } if sigType := sig.EmbeddedSignature.SigType; sigType != SigTypePrimaryKeyBinding { return nil, errors.StructuralError("cross-signature has unexpected type " + strconv.Itoa(int(sigType))) } default: if isCritical { err = errors.UnsupportedError("unknown critical signature subpacket type " + strconv.Itoa(int(packetType))) return } } return Truncated: err = errors.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 } // serializeSubpacketLength marshals the given length into to. func serializeSubpacketLength(to []byte, length int) int { // RFC 4880, Section 4.2.2. if length < 192 { to[0] = byte(length) return 1 } if length < 16320 { length -= 192 to[0] = byte((length >> 8) + 192) 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 serialized 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 } // serializeSubpackets marshals the given subpackets into to. func serializeSubpackets(to []byte, subpackets []outputSubpacket, hashed bool) { for _, subpacket := range subpackets { if subpacket.hashed == hashed { n := serializeSubpacketLength(to, len(subpacket.contents)+1) to[n] = byte(subpacket.subpacketType) to = to[1+n:] n = copy(to, subpacket.contents) to = to[n:] } } return } // KeyExpired returns whether sig is a self-signature of a key that has // expired. func (sig *Signature) KeyExpired(currentTime time.Time) bool { if sig.KeyLifetimeSecs == nil { return false } expiry := sig.CreationTime.Add(time.Duration(*sig.KeyLifetimeSecs) * time.Second) return currentTime.After(expiry) } // buildHashSuffix constructs the HashSuffix member of sig in preparation for signing. func (sig *Signature) buildHashSuffix() (err error) { 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 errors.InvalidArgumentError("hash cannot be represented in OpenPGP: " + strconv.Itoa(int(sig.Hash))) } sig.HashSuffix[4] = byte(hashedSubpacketsLen >> 8) sig.HashSuffix[5] = byte(hashedSubpacketsLen) serializeSubpackets(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 } func (sig *Signature) signPrepareHash(h hash.Hash) (digest []byte, err error) { err = sig.buildHashSuffix() if err != nil { return } h.Write(sig.HashSuffix) digest = h.Sum(nil) copy(sig.HashTag[:], digest) return } // Sign signs a message with a private key. The hash, h, must contain // the hash of the message to be signed and will be mutated by this function. // On success, the signature is stored in sig. Call Serialize to write it out. // If config is nil, sensible defaults will be used. func (sig *Signature) Sign(h hash.Hash, priv *PrivateKey, config *Config) (err error) { sig.outSubpackets = sig.buildSubpackets() digest, err := sig.signPrepareHash(h) if err != nil { return } switch priv.PubKeyAlgo { case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: sig.RSASignature.bytes, err = rsa.SignPKCS1v15(config.Random(), priv.PrivateKey.(*rsa.PrivateKey), sig.Hash, digest) sig.RSASignature.bitLength = uint16(8 * len(sig.RSASignature.bytes)) case PubKeyAlgoDSA: dsaPriv := priv.PrivateKey.(*dsa.PrivateKey) // Need to truncate hashBytes to match FIPS 186-3 section 4.6. subgroupSize := (dsaPriv.Q.BitLen() + 7) / 8 if len(digest) > subgroupSize { digest = digest[:subgroupSize] } r, s, err := dsa.Sign(config.Random(), dsaPriv, digest) if err == nil { sig.DSASigR.bytes = r.Bytes() sig.DSASigR.bitLength = uint16(8 * len(sig.DSASigR.bytes)) sig.DSASigS.bytes = s.Bytes() sig.DSASigS.bitLength = uint16(8 * len(sig.DSASigS.bytes)) } case PubKeyAlgoECDSA: r, s, err := ecdsa.Sign(config.Random(), priv.PrivateKey.(*ecdsa.PrivateKey), digest) if err == nil { sig.ECDSASigR = fromBig(r) sig.ECDSASigS = fromBig(s) } default: err = errors.UnsupportedError("public key algorithm: " + strconv.Itoa(int(sig.PubKeyAlgo))) } return } // SignUserId computes a signature from priv, asserting that pub is a valid // key for the identity id. On success, the signature is stored in sig. Call // Serialize to write it out. // If config is nil, sensible defaults will be used. func (sig *Signature) SignUserId(id string, pub *PublicKey, priv *PrivateKey, config *Config) error { h, err := userIdSignatureHash(id, pub, sig.Hash) if err != nil { return nil } return sig.Sign(h, priv, config) } // SignKey computes a signature from priv, asserting that pub is a subkey. On // success, the signature is stored in sig. Call Serialize to write it out. // If config is nil, sensible defaults will be used. func (sig *Signature) SignKey(pub *PublicKey, priv *PrivateKey, config *Config) error { h, err := keySignatureHash(&priv.PublicKey, pub, sig.Hash) if err != nil { return err } return sig.Sign(h, priv, config) } // Serialize marshals sig to w. Sign, SignUserId or SignKey must have been // called first. func (sig *Signature) Serialize(w io.Writer) (err error) { if len(sig.outSubpackets) == 0 { sig.outSubpackets = sig.rawSubpackets } if sig.RSASignature.bytes == nil && sig.DSASigR.bytes == nil && sig.ECDSASigR.bytes == nil { return errors.InvalidArgumentError("Signature: need to call Sign, SignUserId or SignKey before Serialize") } sigLength := 0 switch sig.PubKeyAlgo { case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: sigLength = 2 + len(sig.RSASignature.bytes) case PubKeyAlgoDSA: sigLength = 2 + len(sig.DSASigR.bytes) sigLength += 2 + len(sig.DSASigS.bytes) case PubKeyAlgoECDSA: sigLength = 2 + len(sig.ECDSASigR.bytes) sigLength += 2 + len(sig.ECDSASigS.bytes) default: panic("impossible") } unhashedSubpacketsLen := subpacketsLength(sig.outSubpackets, false) length := len(sig.HashSuffix) - 6 /* trailer not included */ + 2 /* length of unhashed subpackets */ + unhashedSubpacketsLen + 2 /* hash tag */ + sigLength err = serializeHeader(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) serializeSubpackets(unhashedSubpackets[2:], sig.outSubpackets, false) _, err = w.Write(unhashedSubpackets) if err != nil { return } _, err = w.Write(sig.HashTag[:]) if err != nil { return } switch sig.PubKeyAlgo { case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: err = writeMPIs(w, sig.RSASignature) case PubKeyAlgoDSA: err = writeMPIs(w, sig.DSASigR, sig.DSASigS) case PubKeyAlgoECDSA: err = writeMPIs(w, sig.ECDSASigR, sig.ECDSASigS) default: panic("impossible") } return } // outputSubpacket represents a subpacket to be marshaled. type outputSubpacket struct { hashed bool // true if this subpacket is in the hashed area. subpacketType signatureSubpacketType isCritical bool contents []byte } func (sig *Signature) buildSubpackets() (subpackets []outputSubpacket) { creationTime := make([]byte, 4) binary.BigEndian.PutUint32(creationTime, uint32(sig.CreationTime.Unix())) subpackets = append(subpackets, outputSubpacket{true, creationTimeSubpacket, false, creationTime}) if sig.IssuerKeyId != nil { keyId := make([]byte, 8) binary.BigEndian.PutUint64(keyId, *sig.IssuerKeyId) subpackets = append(subpackets, outputSubpacket{true, issuerSubpacket, false, keyId}) } if sig.SigLifetimeSecs != nil && *sig.SigLifetimeSecs != 0 { sigLifetime := make([]byte, 4) binary.BigEndian.PutUint32(sigLifetime, *sig.SigLifetimeSecs) subpackets = append(subpackets, outputSubpacket{true, signatureExpirationSubpacket, true, sigLifetime}) } // Key flags may only appear in self-signatures or certification signatures. if sig.FlagsValid { var flags byte if sig.FlagCertify { flags |= KeyFlagCertify } if sig.FlagSign { flags |= KeyFlagSign } if sig.FlagEncryptCommunications { flags |= KeyFlagEncryptCommunications } if sig.FlagEncryptStorage { flags |= KeyFlagEncryptStorage } subpackets = append(subpackets, outputSubpacket{true, keyFlagsSubpacket, false, []byte{flags}}) } // The following subpackets may only appear in self-signatures if sig.KeyLifetimeSecs != nil && *sig.KeyLifetimeSecs != 0 { keyLifetime := make([]byte, 4) binary.BigEndian.PutUint32(keyLifetime, *sig.KeyLifetimeSecs) subpackets = append(subpackets, outputSubpacket{true, keyExpirationSubpacket, true, keyLifetime}) } if sig.IsPrimaryId != nil && *sig.IsPrimaryId { subpackets = append(subpackets, outputSubpacket{true, primaryUserIdSubpacket, false, []byte{1}}) } if len(sig.PreferredSymmetric) > 0 { subpackets = append(subpackets, outputSubpacket{true, prefSymmetricAlgosSubpacket, false, sig.PreferredSymmetric}) } if len(sig.PreferredHash) > 0 { subpackets = append(subpackets, outputSubpacket{true, prefHashAlgosSubpacket, false, sig.PreferredHash}) } if len(sig.PreferredCompression) > 0 { subpackets = append(subpackets, outputSubpacket{true, prefCompressionSubpacket, false, sig.PreferredCompression}) } return } lxd-2.0.0/dist/src/golang.org/x/crypto/openpgp/packet/literal.go0000644061062106075000000000360412702772344027201 0ustar00stgraberdomain admins00000000000000// 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" ) // 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 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 } // SerializeLiteral serializes a literal data packet to w and returns a // WriteCloser to which the data itself can be written and which MUST be closed // on completion. The fileName is truncated to 255 bytes. func SerializeLiteral(w io.WriteCloser, isBinary bool, fileName string, time uint32) (plaintext io.WriteCloser, err error) { var buf [4]byte buf[0] = 't' if isBinary { buf[0] = 'b' } if len(fileName) > 255 { fileName = fileName[:255] } buf[1] = byte(len(fileName)) inner, err := serializeStreamHeader(w, packetTypeLiteralData) if err != nil { return } _, err = inner.Write(buf[:2]) if err != nil { return } _, err = inner.Write([]byte(fileName)) if err != nil { return } binary.BigEndian.PutUint32(buf[:], time) _, err = inner.Write(buf[:]) if err != nil { return } plaintext = inner return } lxd-2.0.0/dist/src/golang.org/x/crypto/openpgp/packet/public_key.go0000644061062106075000000005131412702772344027674 0ustar00stgraberdomain admins00000000000000// 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" "crypto/dsa" "crypto/ecdsa" "crypto/elliptic" "crypto/rsa" "crypto/sha1" _ "crypto/sha256" _ "crypto/sha512" "encoding/binary" "fmt" "hash" "io" "math/big" "strconv" "time" "golang.org/x/crypto/openpgp/elgamal" "golang.org/x/crypto/openpgp/errors" ) var ( // NIST curve P-256 oidCurveP256 []byte = []byte{0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07} // NIST curve P-384 oidCurveP384 []byte = []byte{0x2B, 0x81, 0x04, 0x00, 0x22} // NIST curve P-521 oidCurveP521 []byte = []byte{0x2B, 0x81, 0x04, 0x00, 0x23} ) const maxOIDLength = 8 // ecdsaKey stores the algorithm-specific fields for ECDSA keys. // as defined in RFC 6637, Section 9. type ecdsaKey struct { // oid contains the OID byte sequence identifying the elliptic curve used oid []byte // p contains the elliptic curve point that represents the public key p parsedMPI } // parseOID reads the OID for the curve as defined in RFC 6637, Section 9. func parseOID(r io.Reader) (oid []byte, err error) { buf := make([]byte, maxOIDLength) if _, err = readFull(r, buf[:1]); err != nil { return } oidLen := buf[0] if int(oidLen) > len(buf) { err = errors.UnsupportedError("invalid oid length: " + strconv.Itoa(int(oidLen))) return } oid = buf[:oidLen] _, err = readFull(r, oid) return } func (f *ecdsaKey) parse(r io.Reader) (err error) { if f.oid, err = parseOID(r); err != nil { return err } f.p.bytes, f.p.bitLength, err = readMPI(r) return } func (f *ecdsaKey) serialize(w io.Writer) (err error) { buf := make([]byte, maxOIDLength+1) buf[0] = byte(len(f.oid)) copy(buf[1:], f.oid) if _, err = w.Write(buf[:len(f.oid)+1]); err != nil { return } return writeMPIs(w, f.p) } func (f *ecdsaKey) newECDSA() (*ecdsa.PublicKey, error) { var c elliptic.Curve if bytes.Equal(f.oid, oidCurveP256) { c = elliptic.P256() } else if bytes.Equal(f.oid, oidCurveP384) { c = elliptic.P384() } else if bytes.Equal(f.oid, oidCurveP521) { c = elliptic.P521() } else { return nil, errors.UnsupportedError(fmt.Sprintf("unsupported oid: %x", f.oid)) } x, y := elliptic.Unmarshal(c, f.p.bytes) if x == nil { return nil, errors.UnsupportedError("failed to parse EC point") } return &ecdsa.PublicKey{Curve: c, X: x, Y: y}, nil } func (f *ecdsaKey) byteLen() int { return 1 + len(f.oid) + 2 + len(f.p.bytes) } type kdfHashFunction byte type kdfAlgorithm byte // ecdhKdf stores key derivation function parameters // used for ECDH encryption. See RFC 6637, Section 9. type ecdhKdf struct { KdfHash kdfHashFunction KdfAlgo kdfAlgorithm } func (f *ecdhKdf) parse(r io.Reader) (err error) { buf := make([]byte, 1) if _, err = readFull(r, buf); err != nil { return } kdfLen := int(buf[0]) if kdfLen < 3 { return errors.UnsupportedError("Unsupported ECDH KDF length: " + strconv.Itoa(kdfLen)) } buf = make([]byte, kdfLen) if _, err = readFull(r, buf); err != nil { return } reserved := int(buf[0]) f.KdfHash = kdfHashFunction(buf[1]) f.KdfAlgo = kdfAlgorithm(buf[2]) if reserved != 0x01 { return errors.UnsupportedError("Unsupported KDF reserved field: " + strconv.Itoa(reserved)) } return } func (f *ecdhKdf) serialize(w io.Writer) (err error) { buf := make([]byte, 4) // See RFC 6637, Section 9, Algorithm-Specific Fields for ECDH keys. buf[0] = byte(0x03) // Length of the following fields buf[1] = byte(0x01) // Reserved for future extensions, must be 1 for now buf[2] = byte(f.KdfHash) buf[3] = byte(f.KdfAlgo) _, err = w.Write(buf[:]) return } func (f *ecdhKdf) byteLen() int { return 4 } // PublicKey represents an OpenPGP public key. See RFC 4880, section 5.5.2. type PublicKey struct { CreationTime time.Time PubKeyAlgo PublicKeyAlgorithm PublicKey interface{} // *rsa.PublicKey, *dsa.PublicKey or *ecdsa.PublicKey Fingerprint [20]byte KeyId uint64 IsSubkey bool n, e, p, q, g, y parsedMPI // RFC 6637 fields ec *ecdsaKey ecdh *ecdhKdf } // signingKey provides a convenient abstraction over signature verification // for v3 and v4 public keys. type signingKey interface { SerializeSignaturePrefix(io.Writer) serializeWithoutHeaders(io.Writer) error } func fromBig(n *big.Int) parsedMPI { return parsedMPI{ bytes: n.Bytes(), bitLength: uint16(n.BitLen()), } } // NewRSAPublicKey returns a PublicKey that wraps the given rsa.PublicKey. func NewRSAPublicKey(creationTime time.Time, pub *rsa.PublicKey) *PublicKey { pk := &PublicKey{ CreationTime: creationTime, PubKeyAlgo: PubKeyAlgoRSA, PublicKey: pub, n: fromBig(pub.N), e: fromBig(big.NewInt(int64(pub.E))), } pk.setFingerPrintAndKeyId() return pk } // NewDSAPublicKey returns a PublicKey that wraps the given dsa.PublicKey. func NewDSAPublicKey(creationTime time.Time, pub *dsa.PublicKey) *PublicKey { pk := &PublicKey{ CreationTime: creationTime, PubKeyAlgo: PubKeyAlgoDSA, PublicKey: pub, p: fromBig(pub.P), q: fromBig(pub.Q), g: fromBig(pub.G), y: fromBig(pub.Y), } pk.setFingerPrintAndKeyId() return pk } // NewElGamalPublicKey returns a PublicKey that wraps the given elgamal.PublicKey. func NewElGamalPublicKey(creationTime time.Time, pub *elgamal.PublicKey) *PublicKey { pk := &PublicKey{ CreationTime: creationTime, PubKeyAlgo: PubKeyAlgoElGamal, PublicKey: pub, p: fromBig(pub.P), g: fromBig(pub.G), y: fromBig(pub.Y), } pk.setFingerPrintAndKeyId() return pk } func NewECDSAPublicKey(creationTime time.Time, pub *ecdsa.PublicKey) *PublicKey { pk := &PublicKey{ CreationTime: creationTime, PubKeyAlgo: PubKeyAlgoECDSA, PublicKey: pub, ec: new(ecdsaKey), } switch pub.Curve { case elliptic.P256(): pk.ec.oid = oidCurveP256 case elliptic.P384(): pk.ec.oid = oidCurveP384 case elliptic.P521(): pk.ec.oid = oidCurveP521 default: panic("unknown elliptic curve") } pk.ec.p.bytes = elliptic.Marshal(pub.Curve, pub.X, pub.Y) pk.ec.p.bitLength = uint16(8 * len(pk.ec.p.bytes)) pk.setFingerPrintAndKeyId() return pk } func (pk *PublicKey) parse(r io.Reader) (err error) { // RFC 4880, section 5.5.2 var buf [6]byte _, err = readFull(r, buf[:]) if err != nil { return } if buf[0] != 4 { return errors.UnsupportedError("public key version") } pk.CreationTime = time.Unix(int64(uint32(buf[1])<<24|uint32(buf[2])<<16|uint32(buf[3])<<8|uint32(buf[4])), 0) pk.PubKeyAlgo = PublicKeyAlgorithm(buf[5]) switch pk.PubKeyAlgo { case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: err = pk.parseRSA(r) case PubKeyAlgoDSA: err = pk.parseDSA(r) case PubKeyAlgoElGamal: err = pk.parseElGamal(r) case PubKeyAlgoECDSA: pk.ec = new(ecdsaKey) if err = pk.ec.parse(r); err != nil { return err } pk.PublicKey, err = pk.ec.newECDSA() case PubKeyAlgoECDH: pk.ec = new(ecdsaKey) if err = pk.ec.parse(r); err != nil { return } pk.ecdh = new(ecdhKdf) if err = pk.ecdh.parse(r); err != nil { return } // The ECDH key is stored in an ecdsa.PublicKey for convenience. pk.PublicKey, err = pk.ec.newECDSA() default: err = errors.UnsupportedError("public key type: " + strconv.Itoa(int(pk.PubKeyAlgo))) } if err != nil { return } pk.setFingerPrintAndKeyId() return } func (pk *PublicKey) setFingerPrintAndKeyId() { // RFC 4880, section 12.2 fingerPrint := sha1.New() pk.SerializeSignaturePrefix(fingerPrint) pk.serializeWithoutHeaders(fingerPrint) copy(pk.Fingerprint[:], fingerPrint.Sum(nil)) pk.KeyId = binary.BigEndian.Uint64(pk.Fingerprint[12:20]) } // 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 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 = errors.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 } // parseDSA parses DSA public key material from the given Reader. See RFC 4880, // section 5.5.2. func (pk *PublicKey) parseDSA(r io.Reader) (err 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 } // parseElGamal parses ElGamal public key material from the given Reader. See // RFC 4880, section 5.5.2. func (pk *PublicKey) parseElGamal(r io.Reader) (err error) { pk.p.bytes, pk.p.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 } elgamal := new(elgamal.PublicKey) elgamal.P = new(big.Int).SetBytes(pk.p.bytes) elgamal.G = new(big.Int).SetBytes(pk.g.bytes) elgamal.Y = new(big.Int).SetBytes(pk.y.bytes) pk.PublicKey = elgamal 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 io.Writer) { 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)) case PubKeyAlgoElGamal: pLength += 2 + uint16(len(pk.p.bytes)) pLength += 2 + uint16(len(pk.g.bytes)) pLength += 2 + uint16(len(pk.y.bytes)) case PubKeyAlgoECDSA: pLength += uint16(pk.ec.byteLen()) case PubKeyAlgoECDH: pLength += uint16(pk.ec.byteLen()) pLength += uint16(pk.ecdh.byteLen()) default: panic("unknown public key algorithm") } pLength += 6 h.Write([]byte{0x99, byte(pLength >> 8), byte(pLength)}) return } func (pk *PublicKey) Serialize(w io.Writer) (err error) { length := 6 // 6 byte header switch pk.PubKeyAlgo { case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: length += 2 + len(pk.n.bytes) length += 2 + len(pk.e.bytes) case PubKeyAlgoDSA: length += 2 + len(pk.p.bytes) length += 2 + len(pk.q.bytes) length += 2 + len(pk.g.bytes) length += 2 + len(pk.y.bytes) case PubKeyAlgoElGamal: length += 2 + len(pk.p.bytes) length += 2 + len(pk.g.bytes) length += 2 + len(pk.y.bytes) case PubKeyAlgoECDSA: length += pk.ec.byteLen() case PubKeyAlgoECDH: length += pk.ec.byteLen() length += pk.ecdh.byteLen() default: panic("unknown public key algorithm") } packetType := packetTypePublicKey if pk.IsSubkey { packetType = packetTypePublicSubkey } err = serializeHeader(w, packetType, length) if err != nil { return } return pk.serializeWithoutHeaders(w) } // serializeWithoutHeaders marshals the PublicKey to w in the form of an // OpenPGP public key packet, not including the packet header. func (pk *PublicKey) serializeWithoutHeaders(w io.Writer) (err error) { var buf [6]byte buf[0] = 4 t := uint32(pk.CreationTime.Unix()) buf[1] = byte(t >> 24) buf[2] = byte(t >> 16) buf[3] = byte(t >> 8) buf[4] = byte(t) 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) case PubKeyAlgoElGamal: return writeMPIs(w, pk.p, pk.g, pk.y) case PubKeyAlgoECDSA: return pk.ec.serialize(w) case PubKeyAlgoECDH: if err = pk.ec.serialize(w); err != nil { return } return pk.ecdh.serialize(w) } return errors.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 error) { if !pk.CanSign() { return errors.InvalidArgumentError("public key cannot generate signatures") } signed.Write(sig.HashSuffix) hashBytes := signed.Sum(nil) if hashBytes[0] != sig.HashTag[0] || hashBytes[1] != sig.HashTag[1] { return errors.SignatureError("hash tag doesn't match") } if pk.PubKeyAlgo != sig.PubKeyAlgo { return errors.InvalidArgumentError("public key and signature use different algorithms") } switch pk.PubKeyAlgo { case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: rsaPublicKey, _ := pk.PublicKey.(*rsa.PublicKey) err = rsa.VerifyPKCS1v15(rsaPublicKey, sig.Hash, hashBytes, sig.RSASignature.bytes) if err != nil { return errors.SignatureError("RSA verification failure") } return nil case PubKeyAlgoDSA: dsaPublicKey, _ := pk.PublicKey.(*dsa.PublicKey) // Need to truncate hashBytes to match FIPS 186-3 section 4.6. subgroupSize := (dsaPublicKey.Q.BitLen() + 7) / 8 if len(hashBytes) > subgroupSize { hashBytes = hashBytes[:subgroupSize] } if !dsa.Verify(dsaPublicKey, hashBytes, new(big.Int).SetBytes(sig.DSASigR.bytes), new(big.Int).SetBytes(sig.DSASigS.bytes)) { return errors.SignatureError("DSA verification failure") } return nil case PubKeyAlgoECDSA: ecdsaPublicKey := pk.PublicKey.(*ecdsa.PublicKey) if !ecdsa.Verify(ecdsaPublicKey, hashBytes, new(big.Int).SetBytes(sig.ECDSASigR.bytes), new(big.Int).SetBytes(sig.ECDSASigS.bytes)) { return errors.SignatureError("ECDSA verification failure") } return nil default: return errors.SignatureError("Unsupported public key algorithm used in signature") } panic("unreachable") } // VerifySignatureV3 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) VerifySignatureV3(signed hash.Hash, sig *SignatureV3) (err error) { if !pk.CanSign() { return errors.InvalidArgumentError("public key cannot generate signatures") } suffix := make([]byte, 5) suffix[0] = byte(sig.SigType) binary.BigEndian.PutUint32(suffix[1:], uint32(sig.CreationTime.Unix())) signed.Write(suffix) hashBytes := signed.Sum(nil) if hashBytes[0] != sig.HashTag[0] || hashBytes[1] != sig.HashTag[1] { return errors.SignatureError("hash tag doesn't match") } if pk.PubKeyAlgo != sig.PubKeyAlgo { return errors.InvalidArgumentError("public key and signature use different algorithms") } switch pk.PubKeyAlgo { case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: rsaPublicKey := pk.PublicKey.(*rsa.PublicKey) if err = rsa.VerifyPKCS1v15(rsaPublicKey, sig.Hash, hashBytes, sig.RSASignature.bytes); err != nil { return errors.SignatureError("RSA verification failure") } return case PubKeyAlgoDSA: dsaPublicKey := pk.PublicKey.(*dsa.PublicKey) // Need to truncate hashBytes to match FIPS 186-3 section 4.6. subgroupSize := (dsaPublicKey.Q.BitLen() + 7) / 8 if len(hashBytes) > subgroupSize { hashBytes = hashBytes[:subgroupSize] } if !dsa.Verify(dsaPublicKey, hashBytes, new(big.Int).SetBytes(sig.DSASigR.bytes), new(big.Int).SetBytes(sig.DSASigS.bytes)) { return errors.SignatureError("DSA verification failure") } return nil default: panic("shouldn't happen") } panic("unreachable") } // keySignatureHash returns a Hash of the message that needs to be signed for // pk to assert a subkey relationship to signed. func keySignatureHash(pk, signed signingKey, hashFunc crypto.Hash) (h hash.Hash, err error) { if !hashFunc.Available() { return nil, errors.UnsupportedError("hash function") } h = hashFunc.New() // RFC 4880, section 5.2.4 pk.SerializeSignaturePrefix(h) pk.serializeWithoutHeaders(h) signed.SerializeSignaturePrefix(h) signed.serializeWithoutHeaders(h) return } // VerifyKeySignature returns nil iff sig is a valid signature, made by this // public key, of signed. func (pk *PublicKey) VerifyKeySignature(signed *PublicKey, sig *Signature) error { h, err := keySignatureHash(pk, signed, sig.Hash) if err != nil { return err } if err = pk.VerifySignature(h, sig); err != nil { return err } if sig.FlagSign { // Signing subkeys must be cross-signed. See // https://www.gnupg.org/faq/subkey-cross-certify.html. if sig.EmbeddedSignature == nil { return errors.StructuralError("signing subkey is missing cross-signature") } // Verify the cross-signature. This is calculated over the same // data as the main signature, so we cannot just recursively // call signed.VerifyKeySignature(...) if h, err = keySignatureHash(pk, signed, sig.EmbeddedSignature.Hash); err != nil { return errors.StructuralError("error while hashing for cross-signature: " + err.Error()) } if err := signed.VerifySignature(h, sig.EmbeddedSignature); err != nil { return errors.StructuralError("error while verifying cross-signature: " + err.Error()) } } return nil } func keyRevocationHash(pk signingKey, hashFunc crypto.Hash) (h hash.Hash, err error) { if !hashFunc.Available() { return nil, errors.UnsupportedError("hash function") } h = hashFunc.New() // RFC 4880, section 5.2.4 pk.SerializeSignaturePrefix(h) pk.serializeWithoutHeaders(h) return } // VerifyRevocationSignature returns nil iff sig is a valid signature, made by this // public key. func (pk *PublicKey) VerifyRevocationSignature(sig *Signature) (err error) { h, err := keyRevocationHash(pk, sig.Hash) if err != nil { return err } return pk.VerifySignature(h, sig) } // userIdSignatureHash returns a Hash of the message that needs to be signed // to assert that pk is a valid key for id. func userIdSignatureHash(id string, pk *PublicKey, hashFunc crypto.Hash) (h hash.Hash, err error) { if !hashFunc.Available() { return nil, errors.UnsupportedError("hash function") } h = hashFunc.New() // RFC 4880, section 5.2.4 pk.SerializeSignaturePrefix(h) pk.serializeWithoutHeaders(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 } // VerifyUserIdSignature returns nil iff sig is a valid signature, made by this // public key, that id is the identity of pub. func (pk *PublicKey) VerifyUserIdSignature(id string, pub *PublicKey, sig *Signature) (err error) { h, err := userIdSignatureHash(id, pub, sig.Hash) if err != nil { return err } return pk.VerifySignature(h, sig) } // VerifyUserIdSignatureV3 returns nil iff sig is a valid signature, made by this // public key, that id is the identity of pub. func (pk *PublicKey) VerifyUserIdSignatureV3(id string, pub *PublicKey, sig *SignatureV3) (err error) { h, err := userIdSignatureV3Hash(id, pub, sig.Hash) if err != nil { return err } return pk.VerifySignatureV3(h, sig) } // KeyIdString returns the public key's fingerprint in capital hex // (e.g. "6C7EE1B8621CC013"). func (pk *PublicKey) KeyIdString() string { return fmt.Sprintf("%X", pk.Fingerprint[12:20]) } // KeyIdShortString returns the short form of public key's fingerprint // in capital hex, as shown by gpg --list-keys (e.g. "621CC013"). func (pk *PublicKey) KeyIdShortString() string { return fmt.Sprintf("%X", pk.Fingerprint[16:20]) } // 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 reserialized exactly. type parsedMPI struct { bytes []byte bitLength uint16 } // writeMPIs is a utility function for serializing several big integers to the // given Writer. func writeMPIs(w io.Writer, mpis ...parsedMPI) (err error) { for _, mpi := range mpis { err = writeMPI(w, mpi.bitLength, mpi.bytes) if err != nil { return } } return } // BitLength returns the bit length for the given public key. func (pk *PublicKey) BitLength() (bitLength uint16, err error) { switch pk.PubKeyAlgo { case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: bitLength = pk.n.bitLength case PubKeyAlgoDSA: bitLength = pk.p.bitLength case PubKeyAlgoElGamal: bitLength = pk.p.bitLength default: err = errors.InvalidArgumentError("bad public-key algorithm") } return } lxd-2.0.0/dist/src/golang.org/x/crypto/openpgp/packet/ocfb_test.go0000644061062106075000000000236512702772344027520 0ustar00stgraberdomain admins00000000000000// Copyright 2010 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package packet import ( "bytes" "crypto/aes" "crypto/rand" "testing" ) var commonKey128 = []byte{0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c} func testOCFB(t *testing.T, resync OCFBResyncOption) { block, err := aes.NewCipher(commonKey128) if err != nil { t.Error(err) return } plaintext := []byte("this is the plaintext, which is long enough to span several blocks.") randData := make([]byte, block.BlockSize()) rand.Reader.Read(randData) ocfb, prefix := NewOCFBEncrypter(block, randData, resync) ciphertext := make([]byte, len(plaintext)) ocfb.XORKeyStream(ciphertext, plaintext) ocfbdec := NewOCFBDecrypter(block, prefix, resync) if ocfbdec == nil { t.Errorf("NewOCFBDecrypter failed (resync: %t)", resync) return } plaintextCopy := make([]byte, len(plaintext)) ocfbdec.XORKeyStream(plaintextCopy, ciphertext) if !bytes.Equal(plaintextCopy, plaintext) { t.Errorf("got: %x, want: %x (resync: %t)", plaintextCopy, plaintext, resync) } } func TestOCFB(t *testing.T) { testOCFB(t, OCFBNoResync) testOCFB(t, OCFBResync) } lxd-2.0.0/dist/src/golang.org/x/crypto/openpgp/packet/public_key_test.go0000644061062106075000000001775212702772344030743 0ustar00stgraberdomain admins00000000000000// 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" "time" ) var pubKeyTests = []struct { hexData string hexFingerprint string creationTime time.Time pubKeyAlgo PublicKeyAlgorithm keyId uint64 keyIdString string keyIdShort string }{ {rsaPkDataHex, rsaFingerprintHex, time.Unix(0x4d3c5c10, 0), PubKeyAlgoRSA, 0xa34d7e18c20c31bb, "A34D7E18C20C31BB", "C20C31BB"}, {dsaPkDataHex, dsaFingerprintHex, time.Unix(0x4d432f89, 0), PubKeyAlgoDSA, 0x8e8fbe54062f19ed, "8E8FBE54062F19ED", "062F19ED"}, {ecdsaPkDataHex, ecdsaFingerprintHex, time.Unix(0x5071c294, 0), PubKeyAlgoECDSA, 0x43fe956c542ca00b, "43FE956C542CA00B", "542CA00B"}, } 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) continue } pk, ok := packet.(*PublicKey) if !ok { t.Errorf("#%d: failed to parse, got: %#v", i, packet) continue } if pk.PubKeyAlgo != test.pubKeyAlgo { t.Errorf("#%d: bad public key algorithm got:%x want:%x", i, pk.PubKeyAlgo, test.pubKeyAlgo) } if !pk.CreationTime.Equal(test.creationTime) { t.Errorf("#%d: bad creation time got:%v want:%v", 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) } if g, e := pk.KeyIdString(), test.keyIdString; g != e { t.Errorf("#%d: bad KeyIdString got:%q want:%q", i, g, e) } if g, e := pk.KeyIdShortString(), test.keyIdShort; g != e { t.Errorf("#%d: bad KeyIdShortString got:%q want:%q", i, g, e) } } } func TestPublicKeySerialize(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) continue } pk, ok := packet.(*PublicKey) if !ok { t.Errorf("#%d: failed to parse, got: %#v", i, packet) continue } serializeBuf := bytes.NewBuffer(nil) err = pk.Serialize(serializeBuf) if err != nil { t.Errorf("#%d: failed to serialize: %s", i, err) continue } packet, err = Read(serializeBuf) if err != nil { t.Errorf("#%d: Read error (from serialized data): %s", i, err) continue } pk, ok = packet.(*PublicKey) if !ok { t.Errorf("#%d: failed to parse serialized data, got: %#v", i, packet) continue } } } func TestEcc384Serialize(t *testing.T) { r := readerFromHex(ecc384PubHex) var w bytes.Buffer for i := 0; i < 2; i++ { // Public key p, err := Read(r) if err != nil { t.Error(err) } pubkey := p.(*PublicKey) if !bytes.Equal(pubkey.ec.oid, []byte{0x2b, 0x81, 0x04, 0x00, 0x22}) { t.Errorf("Unexpected pubkey OID: %x", pubkey.ec.oid) } if !bytes.Equal(pubkey.ec.p.bytes[:5], []byte{0x04, 0xf6, 0xb8, 0xc5, 0xac}) { t.Errorf("Unexpected pubkey P[:5]: %x", pubkey.ec.p.bytes) } if pubkey.KeyId != 0x098033880F54719F { t.Errorf("Unexpected pubkey ID: %x", pubkey.KeyId) } err = pubkey.Serialize(&w) if err != nil { t.Error(err) } // User ID p, err = Read(r) if err != nil { t.Error(err) } uid := p.(*UserId) if uid.Id != "ec_dsa_dh_384 " { t.Error("Unexpected UID:", uid.Id) } err = uid.Serialize(&w) if err != nil { t.Error(err) } // User ID Sig p, err = Read(r) if err != nil { t.Error(err) } uidSig := p.(*Signature) err = pubkey.VerifyUserIdSignature(uid.Id, pubkey, uidSig) if err != nil { t.Error(err, ": UID") } err = uidSig.Serialize(&w) if err != nil { t.Error(err) } // Subkey p, err = Read(r) if err != nil { t.Error(err) } subkey := p.(*PublicKey) if !bytes.Equal(subkey.ec.oid, []byte{0x2b, 0x81, 0x04, 0x00, 0x22}) { t.Errorf("Unexpected subkey OID: %x", subkey.ec.oid) } if !bytes.Equal(subkey.ec.p.bytes[:5], []byte{0x04, 0x2f, 0xaa, 0x84, 0x02}) { t.Errorf("Unexpected subkey P[:5]: %x", subkey.ec.p.bytes) } if subkey.ecdh.KdfHash != 0x09 { t.Error("Expected KDF hash function SHA384 (0x09), got", subkey.ecdh.KdfHash) } if subkey.ecdh.KdfAlgo != 0x09 { t.Error("Expected KDF symmetric alg AES256 (0x09), got", subkey.ecdh.KdfAlgo) } if subkey.KeyId != 0xAA8B938F9A201946 { t.Errorf("Unexpected subkey ID: %x", subkey.KeyId) } err = subkey.Serialize(&w) if err != nil { t.Error(err) } // Subkey Sig p, err = Read(r) if err != nil { t.Error(err) } subkeySig := p.(*Signature) err = pubkey.VerifyKeySignature(subkey, subkeySig) if err != nil { t.Error(err) } err = subkeySig.Serialize(&w) if err != nil { t.Error(err) } // Now read back what we've written again r = bytes.NewBuffer(w.Bytes()) w.Reset() } } const rsaFingerprintHex = "5fb74b1d03b1e3cb31bc2f8aa34d7e18c20c31bb" const rsaPkDataHex = "988d044d3c5c10010400b1d13382944bd5aba23a4312968b5095d14f947f600eb478e14a6fcb16b0e0cac764884909c020bc495cfcc39a935387c661507bdb236a0612fb582cac3af9b29cc2c8c70090616c41b662f4da4c1201e195472eb7f4ae1ccbcbf9940fe21d985e379a5563dde5b9a23d35f1cfaa5790da3b79db26f23695107bfaca8e7b5bcd0011010001" const dsaFingerprintHex = "eece4c094db002103714c63c8e8fbe54062f19ed" const dsaPkDataHex = "9901a2044d432f89110400cd581334f0d7a1e1bdc8b9d6d8c0baf68793632735d2bb0903224cbaa1dfbf35a60ee7a13b92643421e1eb41aa8d79bea19a115a677f6b8ba3c7818ce53a6c2a24a1608bd8b8d6e55c5090cbde09dd26e356267465ae25e69ec8bdd57c7bbb2623e4d73336f73a0a9098f7f16da2e25252130fd694c0e8070c55a812a423ae7f00a0ebf50e70c2f19c3520a551bd4b08d30f23530d3d03ff7d0bf4a53a64a09dc5e6e6e35854b7d70c882b0c60293401958b1bd9e40abec3ea05ba87cf64899299d4bd6aa7f459c201d3fbbd6c82004bdc5e8a9eb8082d12054cc90fa9d4ec251a843236a588bf49552441817436c4f43326966fe85447d4e6d0acf8fa1ef0f014730770603ad7634c3088dc52501c237328417c31c89ed70400b2f1a98b0bf42f11fefc430704bebbaa41d9f355600c3facee1e490f64208e0e094ea55e3a598a219a58500bf78ac677b670a14f4e47e9cf8eab4f368cc1ddcaa18cc59309d4cc62dd4f680e73e6cc3e1ce87a84d0925efbcb26c575c093fc42eecf45135fabf6403a25c2016e1774c0484e440a18319072c617cc97ac0a3bb0" const ecdsaFingerprintHex = "9892270b38b8980b05c8d56d43fe956c542ca00b" const ecdsaPkDataHex = "9893045071c29413052b8104002304230401f4867769cedfa52c325018896245443968e52e51d0c2df8d939949cb5b330f2921711fbee1c9b9dddb95d15cb0255e99badeddda7cc23d9ddcaacbc290969b9f24019375d61c2e4e3b36953a28d8b2bc95f78c3f1d592fb24499be348656a7b17e3963187b4361afe497bc5f9f81213f04069f8e1fb9e6a6290ae295ca1a92b894396cb4" // Source: https://sites.google.com/site/brainhub/pgpecckeys#TOC-ECC-NIST-P-384-key const ecc384PubHex = `99006f044d53059213052b81040022030304f6b8c5aced5b84ef9f4a209db2e4a9dfb70d28cb8c10ecd57674a9fa5a67389942b62d5e51367df4c7bfd3f8e500feecf07ed265a621a8ebbbe53e947ec78c677eba143bd1533c2b350e1c29f82313e1e1108eba063be1e64b10e6950e799c2db42465635f6473615f64685f333834203c6f70656e70677040627261696e6875622e6f72673e8900cb04101309005305024d530592301480000000002000077072656665727265642d656d61696c2d656e636f64696e67407067702e636f6d7067706d696d65040b090807021901051b03000000021602051e010000000415090a08000a0910098033880f54719fca2b0180aa37350968bd5f115afd8ce7bc7b103822152dbff06d0afcda835329510905b98cb469ba208faab87c7412b799e7b633017f58364ea480e8a1a3f253a0c5f22c446e8be9a9fce6210136ee30811abbd49139de28b5bdf8dc36d06ae748579e9ff503b90073044d53059212052b810400220303042faa84024a20b6735c4897efa5bfb41bf85b7eefeab5ca0cb9ffc8ea04a46acb25534a577694f9e25340a4ab5223a9dd1eda530c8aa2e6718db10d7e672558c7736fe09369ea5739a2a3554bf16d41faa50562f11c6d39bbd5dffb6b9a9ec9180301090989008404181309000c05024d530592051b0c000000000a0910098033880f54719f80970180eee7a6d8fcee41ee4f9289df17f9bcf9d955dca25c583b94336f3a2b2d4986dc5cf417b8d2dc86f741a9e1a6d236c0e3017d1c76575458a0cfb93ae8a2b274fcc65ceecd7a91eec83656ba13219969f06945b48c56bd04152c3a0553c5f2f4bd1267` lxd-2.0.0/dist/src/golang.org/x/crypto/openpgp/packet/one_pass_signature.go0000644061062106075000000000336212702772344031436 0ustar00stgraberdomain admins00000000000000// 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" "encoding/binary" "golang.org/x/crypto/openpgp/errors" "golang.org/x/crypto/openpgp/s2k" "io" "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 } const onePassSignatureVersion = 3 func (ops *OnePassSignature) parse(r io.Reader) (err error) { var buf [13]byte _, err = readFull(r, buf[:]) if err != nil { return } if buf[0] != onePassSignatureVersion { err = errors.UnsupportedError("one-pass-signature packet version " + strconv.Itoa(int(buf[0]))) } var ok bool ops.Hash, ok = s2k.HashIdToHash(buf[2]) if !ok { return errors.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 } // Serialize marshals the given OnePassSignature to w. func (ops *OnePassSignature) Serialize(w io.Writer) error { var buf [13]byte buf[0] = onePassSignatureVersion buf[1] = uint8(ops.SigType) var ok bool buf[2], ok = s2k.HashToHashId(ops.Hash) if !ok { return errors.UnsupportedError("hash type: " + strconv.Itoa(int(ops.Hash))) } buf[3] = uint8(ops.PubKeyAlgo) binary.BigEndian.PutUint64(buf[4:12], ops.KeyId) if ops.IsLast { buf[12] = 1 } if err := serializeHeader(w, packetTypeOnePassSignature, len(buf)); err != nil { return err } _, err := w.Write(buf[:]) return err } lxd-2.0.0/dist/src/golang.org/x/crypto/openpgp/packet/ocfb.go0000644061062106075000000000717312702772344026463 0ustar00stgraberdomain admins00000000000000// Copyright 2010 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // OpenPGP CFB Mode. http://tools.ietf.org/html/rfc4880#section-13.9 package packet import ( "crypto/cipher" ) type ocfbEncrypter struct { b cipher.Block fre []byte 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 cipher.Stream which encrypts data with OpenPGP's // cipher feedback mode using the given cipher.Block, and an initial amount of // ciphertext. randData must be random bytes and be the same length as the // cipher.Block's block size. Resync determines if the "resynchronization step" // from RFC 4880, 13.9 step 7 is performed. Different parts of OpenPGP vary on // this point. func NewOCFBEncrypter(block cipher.Block, randData []byte, resync OCFBResyncOption) (cipher.Stream, []byte) { blockSize := block.BlockSize() if len(randData) != blockSize { return nil, nil } x := &ocfbEncrypter{ b: block, fre: make([]byte, blockSize), outUsed: 0, } prefix := make([]byte, blockSize+2) block.Encrypt(x.fre, x.fre) for i := 0; i < blockSize; i++ { prefix[i] = randData[i] ^ x.fre[i] } block.Encrypt(x.fre, prefix[:blockSize]) prefix[blockSize] = x.fre[0] ^ randData[blockSize-2] prefix[blockSize+1] = x.fre[1] ^ randData[blockSize-1] if resync { block.Encrypt(x.fre, prefix[2:]) } else { x.fre[0] = prefix[blockSize] x.fre[1] = prefix[blockSize+1] x.outUsed = 2 } return x, prefix } func (x *ocfbEncrypter) XORKeyStream(dst, src []byte) { for i := 0; i < len(src); i++ { if x.outUsed == len(x.fre) { x.b.Encrypt(x.fre, x.fre) x.outUsed = 0 } x.fre[x.outUsed] ^= src[i] dst[i] = x.fre[x.outUsed] x.outUsed++ } } type ocfbDecrypter struct { b cipher.Block fre []byte outUsed int } // NewOCFBDecrypter returns a cipher.Stream which decrypts data with OpenPGP's // cipher feedback mode using the given cipher.Block. Prefix must be the first // blockSize + 2 bytes of the ciphertext, where blockSize is the cipher.Block's // block size. If an incorrect key is detected then nil is returned. On // successful exit, blockSize+2 bytes of decrypted data are written into // prefix. Resync determines if the "resynchronization step" from RFC 4880, // 13.9 step 7 is performed. Different parts of OpenPGP vary on this point. func NewOCFBDecrypter(block cipher.Block, prefix []byte, resync OCFBResyncOption) cipher.Stream { blockSize := block.BlockSize() if len(prefix) != blockSize+2 { return nil } x := &ocfbDecrypter{ b: block, fre: make([]byte, blockSize), outUsed: 0, } prefixCopy := make([]byte, len(prefix)) copy(prefixCopy, prefix) block.Encrypt(x.fre, x.fre) for i := 0; i < blockSize; i++ { prefixCopy[i] ^= x.fre[i] } block.Encrypt(x.fre, prefix[:blockSize]) prefixCopy[blockSize] ^= x.fre[0] prefixCopy[blockSize+1] ^= x.fre[1] if prefixCopy[blockSize-2] != prefixCopy[blockSize] || prefixCopy[blockSize-1] != prefixCopy[blockSize+1] { return nil } if resync { block.Encrypt(x.fre, prefix[2:]) } else { x.fre[0] = prefix[blockSize] x.fre[1] = prefix[blockSize+1] x.outUsed = 2 } copy(prefix, prefixCopy) return x } func (x *ocfbDecrypter) XORKeyStream(dst, src []byte) { for i := 0; i < len(src); i++ { if x.outUsed == len(x.fre) { x.b.Encrypt(x.fre, x.fre) x.outUsed = 0 } c := src[i] dst[i] = x.fre[x.outUsed] ^ src[i] x.fre[x.outUsed] = c x.outUsed++ } } lxd-2.0.0/dist/src/golang.org/x/crypto/openpgp/packet/private_key.go0000644061062106075000000002005312702772344030064 0ustar00stgraberdomain admins00000000000000// 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/cipher" "crypto/dsa" "crypto/ecdsa" "crypto/rsa" "crypto/sha1" "io" "io/ioutil" "math/big" "strconv" "time" "golang.org/x/crypto/openpgp/elgamal" "golang.org/x/crypto/openpgp/errors" "golang.org/x/crypto/openpgp/s2k" ) // 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 or *dsa.PrivateKey. sha1Checksum bool iv []byte } func NewRSAPrivateKey(currentTime time.Time, priv *rsa.PrivateKey) *PrivateKey { pk := new(PrivateKey) pk.PublicKey = *NewRSAPublicKey(currentTime, &priv.PublicKey) pk.PrivateKey = priv return pk } func NewDSAPrivateKey(currentTime time.Time, priv *dsa.PrivateKey) *PrivateKey { pk := new(PrivateKey) pk.PublicKey = *NewDSAPublicKey(currentTime, &priv.PublicKey) pk.PrivateKey = priv return pk } func NewElGamalPrivateKey(currentTime time.Time, priv *elgamal.PrivateKey) *PrivateKey { pk := new(PrivateKey) pk.PublicKey = *NewElGamalPublicKey(currentTime, &priv.PublicKey) pk.PrivateKey = priv return pk } func NewECDSAPrivateKey(currentTime time.Time, priv *ecdsa.PrivateKey) *PrivateKey { pk := new(PrivateKey) pk.PublicKey = *NewECDSAPublicKey(currentTime, &priv.PublicKey) pk.PrivateKey = priv return pk } func (pk *PrivateKey) parse(r io.Reader) (err 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 errors.UnsupportedError("deprecated s2k function in private key") } if pk.Encrypted { blockSize := pk.cipher.blockSize() if blockSize == 0 { return errors.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 } func mod64kHash(d []byte) uint16 { var h uint16 for _, b := range d { h += uint16(b) } return h } func (pk *PrivateKey) Serialize(w io.Writer) (err error) { // TODO(agl): support encrypted private keys buf := bytes.NewBuffer(nil) err = pk.PublicKey.serializeWithoutHeaders(buf) if err != nil { return } buf.WriteByte(0 /* no encryption */) privateKeyBuf := bytes.NewBuffer(nil) switch priv := pk.PrivateKey.(type) { case *rsa.PrivateKey: err = serializeRSAPrivateKey(privateKeyBuf, priv) case *dsa.PrivateKey: err = serializeDSAPrivateKey(privateKeyBuf, priv) case *elgamal.PrivateKey: err = serializeElGamalPrivateKey(privateKeyBuf, priv) case *ecdsa.PrivateKey: err = serializeECDSAPrivateKey(privateKeyBuf, priv) default: err = errors.InvalidArgumentError("unknown private key type") } if err != nil { return } ptype := packetTypePrivateKey contents := buf.Bytes() privateKeyBytes := privateKeyBuf.Bytes() if pk.IsSubkey { ptype = packetTypePrivateSubkey } err = serializeHeader(w, ptype, len(contents)+len(privateKeyBytes)+2) if err != nil { return } _, err = w.Write(contents) if err != nil { return } _, err = w.Write(privateKeyBytes) if err != nil { return } checksum := mod64kHash(privateKeyBytes) var checksumBytes [2]byte checksumBytes[0] = byte(checksum >> 8) checksumBytes[1] = byte(checksum) _, err = w.Write(checksumBytes[:]) return } func serializeRSAPrivateKey(w io.Writer, priv *rsa.PrivateKey) error { err := writeBig(w, priv.D) if err != nil { return err } err = writeBig(w, priv.Primes[1]) if err != nil { return err } err = writeBig(w, priv.Primes[0]) if err != nil { return err } return writeBig(w, priv.Precomputed.Qinv) } func serializeDSAPrivateKey(w io.Writer, priv *dsa.PrivateKey) error { return writeBig(w, priv.X) } func serializeElGamalPrivateKey(w io.Writer, priv *elgamal.PrivateKey) error { return writeBig(w, priv.X) } func serializeECDSAPrivateKey(w io.Writer, priv *ecdsa.PrivateKey) error { return writeBig(w, priv.D) } // Decrypt decrypts an encrypted private key using a passphrase. func (pk *PrivateKey) Decrypt(passphrase []byte) 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 := make([]byte, len(pk.encryptedData)) cfb.XORKeyStream(data, pk.encryptedData) if pk.sha1Checksum { if len(data) < sha1.Size { return errors.StructuralError("truncated private key data") } h := sha1.New() h.Write(data[:len(data)-sha1.Size]) sum := h.Sum(nil) if !bytes.Equal(sum, data[len(data)-sha1.Size:]) { return errors.StructuralError("private key checksum failure") } data = data[:len(data)-sha1.Size] } else { if len(data) < 2 { return errors.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 errors.StructuralError("private key checksum failure") } data = data[:len(data)-2] } return pk.parsePrivateKey(data) } func (pk *PrivateKey) parsePrivateKey(data []byte) (err error) { switch pk.PublicKey.PubKeyAlgo { case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoRSAEncryptOnly: return pk.parseRSAPrivateKey(data) case PubKeyAlgoDSA: return pk.parseDSAPrivateKey(data) case PubKeyAlgoElGamal: return pk.parseElGamalPrivateKey(data) case PubKeyAlgoECDSA: return pk.parseECDSAPrivateKey(data) } panic("impossible") } func (pk *PrivateKey) parseRSAPrivateKey(data []byte) (err error) { 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.Primes = make([]*big.Int, 2) rsaPriv.Primes[0] = new(big.Int).SetBytes(p) rsaPriv.Primes[1] = new(big.Int).SetBytes(q) if err := rsaPriv.Validate(); err != nil { return err } rsaPriv.Precompute() pk.PrivateKey = rsaPriv pk.Encrypted = false pk.encryptedData = nil return nil } func (pk *PrivateKey) parseDSAPrivateKey(data []byte) (err error) { dsaPub := pk.PublicKey.PublicKey.(*dsa.PublicKey) dsaPriv := new(dsa.PrivateKey) dsaPriv.PublicKey = *dsaPub buf := bytes.NewBuffer(data) x, _, err := readMPI(buf) if err != nil { return } dsaPriv.X = new(big.Int).SetBytes(x) pk.PrivateKey = dsaPriv pk.Encrypted = false pk.encryptedData = nil return nil } func (pk *PrivateKey) parseElGamalPrivateKey(data []byte) (err error) { pub := pk.PublicKey.PublicKey.(*elgamal.PublicKey) priv := new(elgamal.PrivateKey) priv.PublicKey = *pub buf := bytes.NewBuffer(data) x, _, err := readMPI(buf) if err != nil { return } priv.X = new(big.Int).SetBytes(x) pk.PrivateKey = priv pk.Encrypted = false pk.encryptedData = nil return nil } func (pk *PrivateKey) parseECDSAPrivateKey(data []byte) (err error) { ecdsaPub := pk.PublicKey.PublicKey.(*ecdsa.PublicKey) buf := bytes.NewBuffer(data) d, _, err := readMPI(buf) if err != nil { return } pk.PrivateKey = &ecdsa.PrivateKey{ PublicKey: *ecdsaPub, D: new(big.Int).SetBytes(d), } pk.Encrypted = false pk.encryptedData = nil return nil } lxd-2.0.0/dist/src/golang.org/x/crypto/openpgp/packet/encrypted_key_test.go0000644061062106075000000001046512702772344031454 0ustar00stgraberdomain admins00000000000000// 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/rsa" "encoding/hex" "fmt" "math/big" "testing" ) func bigFromBase10(s string) *big.Int { b, ok := new(big.Int).SetString(s, 10) if !ok { panic("bigFromBase10 failed") } return b } var encryptedKeyPub = rsa.PublicKey{ E: 65537, N: bigFromBase10("115804063926007623305902631768113868327816898845124614648849934718568541074358183759250136204762053879858102352159854352727097033322663029387610959884180306668628526686121021235757016368038585212410610742029286439607686208110250133174279811431933746643015923132833417396844716207301518956640020862630546868823"), } var encryptedKeyRSAPriv = &rsa.PrivateKey{ PublicKey: encryptedKeyPub, D: bigFromBase10("32355588668219869544751561565313228297765464314098552250409557267371233892496951383426602439009993875125222579159850054973310859166139474359774543943714622292329487391199285040721944491839695981199720170366763547754915493640685849961780092241140181198779299712578774460837139360803883139311171713302987058393"), } var encryptedKeyPriv = &PrivateKey{ PublicKey: PublicKey{ PubKeyAlgo: PubKeyAlgoRSA, }, PrivateKey: encryptedKeyRSAPriv, } func TestDecryptingEncryptedKey(t *testing.T) { const encryptedKeyHex = "c18c032a67d68660df41c70104005789d0de26b6a50c985a02a13131ca829c413a35d0e6fa8d6842599252162808ac7439c72151c8c6183e76923fe3299301414d0c25a2f06a2257db3839e7df0ec964773f6e4c4ac7ff3b48c444237166dd46ba8ff443a5410dc670cb486672fdbe7c9dfafb75b4fea83af3a204fe2a7dfa86bd20122b4f3d2646cbeecb8f7be8" const expectedKeyHex = "d930363f7e0308c333b9618617ea728963d8df993665ae7be1092d4926fd864b" 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 } err = ek.Decrypt(encryptedKeyPriv, nil) if err != nil { t.Errorf("error from Decrypt: %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) } } func TestEncryptingEncryptedKey(t *testing.T) { key := []byte{1, 2, 3, 4} const expectedKeyHex = "01020304" const keyId = 42 pub := &PublicKey{ PublicKey: &encryptedKeyPub, KeyId: keyId, PubKeyAlgo: PubKeyAlgoRSAEncryptOnly, } buf := new(bytes.Buffer) err := SerializeEncryptedKey(buf, pub, CipherAES128, key, nil) if err != nil { t.Errorf("error writing encrypted key packet: %s", err) } p, err := Read(buf) 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 != keyId || ek.Algo != PubKeyAlgoRSAEncryptOnly { t.Errorf("unexpected EncryptedKey contents: %#v", ek) return } err = ek.Decrypt(encryptedKeyPriv, nil) if err != nil { t.Errorf("error from Decrypt: %s", err) return } if ek.CipherFunc != CipherAES128 { 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) } } func TestSerializingEncryptedKey(t *testing.T) { const encryptedKeyHex = "c18c032a67d68660df41c70104005789d0de26b6a50c985a02a13131ca829c413a35d0e6fa8d6842599252162808ac7439c72151c8c6183e76923fe3299301414d0c25a2f06a2257db3839e7df0ec964773f6e4c4ac7ff3b48c444237166dd46ba8ff443a5410dc670cb486672fdbe7c9dfafb75b4fea83af3a204fe2a7dfa86bd20122b4f3d2646cbeecb8f7be8" p, err := Read(readerFromHex(encryptedKeyHex)) if err != nil { t.Fatalf("error from Read: %s", err) } ek, ok := p.(*EncryptedKey) if !ok { t.Fatalf("didn't parse an EncryptedKey, got %#v", p) } var buf bytes.Buffer ek.Serialize(&buf) if bufHex := hex.EncodeToString(buf.Bytes()); bufHex != encryptedKeyHex { t.Fatalf("serialization of encrypted key differed from original. Original was %s, but reserialized as %s", encryptedKeyHex, bufHex) } } lxd-2.0.0/dist/src/golang.org/x/crypto/openpgp/packet/userattribute.go0000644061062106075000000000474612702772344030457 0ustar00stgraberdomain admins00000000000000// Copyright 2013 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" "image" "image/jpeg" "io" "io/ioutil" ) const UserAttrImageSubpacket = 1 // UserAttribute is capable of storing other types of data about a user // beyond name, email and a text comment. In practice, user attributes are typically used // to store a signed thumbnail photo JPEG image of the user. // See RFC 4880, section 5.12. type UserAttribute struct { Contents []*OpaqueSubpacket } // NewUserAttributePhoto creates a user attribute packet // containing the given images. func NewUserAttributePhoto(photos ...image.Image) (uat *UserAttribute, err error) { uat = new(UserAttribute) for _, photo := range photos { var buf bytes.Buffer // RFC 4880, Section 5.12.1. data := []byte{ 0x10, 0x00, // Little-endian image header length (16 bytes) 0x01, // Image header version 1 0x01, // JPEG 0, 0, 0, 0, // 12 reserved octets, must be all zero. 0, 0, 0, 0, 0, 0, 0, 0} if _, err = buf.Write(data); err != nil { return } if err = jpeg.Encode(&buf, photo, nil); err != nil { return } uat.Contents = append(uat.Contents, &OpaqueSubpacket{ SubType: UserAttrImageSubpacket, Contents: buf.Bytes()}) } return } // NewUserAttribute creates a new user attribute packet containing the given subpackets. func NewUserAttribute(contents ...*OpaqueSubpacket) *UserAttribute { return &UserAttribute{Contents: contents} } func (uat *UserAttribute) parse(r io.Reader) (err error) { // RFC 4880, section 5.13 b, err := ioutil.ReadAll(r) if err != nil { return } uat.Contents, err = OpaqueSubpackets(b) return } // Serialize marshals the user attribute to w in the form of an OpenPGP packet, including // header. func (uat *UserAttribute) Serialize(w io.Writer) (err error) { var buf bytes.Buffer for _, sp := range uat.Contents { sp.Serialize(&buf) } if err = serializeHeader(w, packetTypeUserAttribute, buf.Len()); err != nil { return err } _, err = w.Write(buf.Bytes()) return } // ImageData returns zero or more byte slices, each containing // JPEG File Interchange Format (JFIF), for each photo in the // the user attribute packet. func (uat *UserAttribute) ImageData() (imageData [][]byte) { for _, sp := range uat.Contents { if sp.SubType == UserAttrImageSubpacket && len(sp.Contents) > 16 { imageData = append(imageData, sp.Contents[16:]) } } return } lxd-2.0.0/dist/src/golang.org/x/crypto/openpgp/packet/public_key_v3.go0000644061062106075000000001777612702772344030322 0ustar00stgraberdomain admins00000000000000// Copyright 2013 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/md5" "crypto/rsa" "encoding/binary" "fmt" "hash" "io" "math/big" "strconv" "time" "golang.org/x/crypto/openpgp/errors" ) // PublicKeyV3 represents older, version 3 public keys. These keys are less secure and // should not be used for signing or encrypting. They are supported here only for // parsing version 3 key material and validating signatures. // See RFC 4880, section 5.5.2. type PublicKeyV3 struct { CreationTime time.Time DaysToExpire uint16 PubKeyAlgo PublicKeyAlgorithm PublicKey *rsa.PublicKey Fingerprint [16]byte KeyId uint64 IsSubkey bool n, e parsedMPI } // newRSAPublicKeyV3 returns a PublicKey that wraps the given rsa.PublicKey. // Included here for testing purposes only. RFC 4880, section 5.5.2: // "an implementation MUST NOT generate a V3 key, but MAY accept it." func newRSAPublicKeyV3(creationTime time.Time, pub *rsa.PublicKey) *PublicKeyV3 { pk := &PublicKeyV3{ CreationTime: creationTime, PublicKey: pub, n: fromBig(pub.N), e: fromBig(big.NewInt(int64(pub.E))), } pk.setFingerPrintAndKeyId() return pk } func (pk *PublicKeyV3) parse(r io.Reader) (err error) { // RFC 4880, section 5.5.2 var buf [8]byte if _, err = readFull(r, buf[:]); err != nil { return } if buf[0] < 2 || buf[0] > 3 { return errors.UnsupportedError("public key version") } pk.CreationTime = time.Unix(int64(uint32(buf[1])<<24|uint32(buf[2])<<16|uint32(buf[3])<<8|uint32(buf[4])), 0) pk.DaysToExpire = binary.BigEndian.Uint16(buf[5:7]) pk.PubKeyAlgo = PublicKeyAlgorithm(buf[7]) switch pk.PubKeyAlgo { case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: err = pk.parseRSA(r) default: err = errors.UnsupportedError("public key type: " + strconv.Itoa(int(pk.PubKeyAlgo))) } if err != nil { return } pk.setFingerPrintAndKeyId() return } func (pk *PublicKeyV3) setFingerPrintAndKeyId() { // RFC 4880, section 12.2 fingerPrint := md5.New() fingerPrint.Write(pk.n.bytes) fingerPrint.Write(pk.e.bytes) fingerPrint.Sum(pk.Fingerprint[:0]) pk.KeyId = binary.BigEndian.Uint64(pk.n.bytes[len(pk.n.bytes)-8:]) } // parseRSA parses RSA public key material from the given Reader. See RFC 4880, // section 5.5.2. func (pk *PublicKeyV3) parseRSA(r io.Reader) (err error) { if pk.n.bytes, pk.n.bitLength, err = readMPI(r); err != nil { return } if pk.e.bytes, pk.e.bitLength, err = readMPI(r); err != nil { return } // RFC 4880 Section 12.2 requires the low 8 bytes of the // modulus to form the key id. if len(pk.n.bytes) < 8 { return errors.StructuralError("v3 public key modulus is too short") } if len(pk.e.bytes) > 3 { err = errors.UnsupportedError("large public exponent") return } rsa := &rsa.PublicKey{N: new(big.Int).SetBytes(pk.n.bytes)} for i := 0; i < len(pk.e.bytes); i++ { rsa.E <<= 8 rsa.E |= int(pk.e.bytes[i]) } pk.PublicKey = rsa 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 *PublicKeyV3) SerializeSignaturePrefix(w io.Writer) { var pLength uint16 switch pk.PubKeyAlgo { case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: pLength += 2 + uint16(len(pk.n.bytes)) pLength += 2 + uint16(len(pk.e.bytes)) default: panic("unknown public key algorithm") } pLength += 6 w.Write([]byte{0x99, byte(pLength >> 8), byte(pLength)}) return } func (pk *PublicKeyV3) Serialize(w io.Writer) (err error) { length := 8 // 8 byte header switch pk.PubKeyAlgo { case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: length += 2 + len(pk.n.bytes) length += 2 + len(pk.e.bytes) default: panic("unknown public key algorithm") } packetType := packetTypePublicKey if pk.IsSubkey { packetType = packetTypePublicSubkey } if err = serializeHeader(w, packetType, length); err != nil { return } return pk.serializeWithoutHeaders(w) } // serializeWithoutHeaders marshals the PublicKey to w in the form of an // OpenPGP public key packet, not including the packet header. func (pk *PublicKeyV3) serializeWithoutHeaders(w io.Writer) (err error) { var buf [8]byte // Version 3 buf[0] = 3 // Creation time t := uint32(pk.CreationTime.Unix()) buf[1] = byte(t >> 24) buf[2] = byte(t >> 16) buf[3] = byte(t >> 8) buf[4] = byte(t) // Days to expire buf[5] = byte(pk.DaysToExpire >> 8) buf[6] = byte(pk.DaysToExpire) // Public key algorithm buf[7] = byte(pk.PubKeyAlgo) if _, err = w.Write(buf[:]); err != nil { return } switch pk.PubKeyAlgo { case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: return writeMPIs(w, pk.n, pk.e) } return errors.InvalidArgumentError("bad public-key algorithm") } // CanSign returns true iff this public key can generate signatures func (pk *PublicKeyV3) CanSign() bool { return pk.PubKeyAlgo != PubKeyAlgoRSAEncryptOnly } // VerifySignatureV3 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 *PublicKeyV3) VerifySignatureV3(signed hash.Hash, sig *SignatureV3) (err error) { if !pk.CanSign() { return errors.InvalidArgumentError("public key cannot generate signatures") } suffix := make([]byte, 5) suffix[0] = byte(sig.SigType) binary.BigEndian.PutUint32(suffix[1:], uint32(sig.CreationTime.Unix())) signed.Write(suffix) hashBytes := signed.Sum(nil) if hashBytes[0] != sig.HashTag[0] || hashBytes[1] != sig.HashTag[1] { return errors.SignatureError("hash tag doesn't match") } if pk.PubKeyAlgo != sig.PubKeyAlgo { return errors.InvalidArgumentError("public key and signature use different algorithms") } switch pk.PubKeyAlgo { case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: if err = rsa.VerifyPKCS1v15(pk.PublicKey, sig.Hash, hashBytes, sig.RSASignature.bytes); err != nil { return errors.SignatureError("RSA verification failure") } return default: // V3 public keys only support RSA. panic("shouldn't happen") } panic("unreachable") } // VerifyUserIdSignatureV3 returns nil iff sig is a valid signature, made by this // public key, that id is the identity of pub. func (pk *PublicKeyV3) VerifyUserIdSignatureV3(id string, pub *PublicKeyV3, sig *SignatureV3) (err error) { h, err := userIdSignatureV3Hash(id, pk, sig.Hash) if err != nil { return err } return pk.VerifySignatureV3(h, sig) } // VerifyKeySignatureV3 returns nil iff sig is a valid signature, made by this // public key, of signed. func (pk *PublicKeyV3) VerifyKeySignatureV3(signed *PublicKeyV3, sig *SignatureV3) (err error) { h, err := keySignatureHash(pk, signed, sig.Hash) if err != nil { return err } return pk.VerifySignatureV3(h, sig) } // userIdSignatureV3Hash returns a Hash of the message that needs to be signed // to assert that pk is a valid key for id. func userIdSignatureV3Hash(id string, pk signingKey, hfn crypto.Hash) (h hash.Hash, err error) { if !hfn.Available() { return nil, errors.UnsupportedError("hash function") } h = hfn.New() // RFC 4880, section 5.2.4 pk.SerializeSignaturePrefix(h) pk.serializeWithoutHeaders(h) h.Write([]byte(id)) return } // KeyIdString returns the public key's fingerprint in capital hex // (e.g. "6C7EE1B8621CC013"). func (pk *PublicKeyV3) KeyIdString() string { return fmt.Sprintf("%X", pk.KeyId) } // KeyIdShortString returns the short form of public key's fingerprint // in capital hex, as shown by gpg --list-keys (e.g. "621CC013"). func (pk *PublicKeyV3) KeyIdShortString() string { return fmt.Sprintf("%X", pk.KeyId&0xFFFFFFFF) } // BitLength returns the bit length for the given public key. func (pk *PublicKeyV3) BitLength() (bitLength uint16, err error) { switch pk.PubKeyAlgo { case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: bitLength = pk.n.bitLength default: err = errors.InvalidArgumentError("bad public-key algorithm") } return } lxd-2.0.0/dist/src/golang.org/x/crypto/openpgp/packet/symmetrically_encrypted_test.go0000644061062106075000000000537312702772344033564 0ustar00stgraberdomain admins00000000000000// 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/sha1" "encoding/hex" "golang.org/x/crypto/openpgp/errors" "io" "io/ioutil" "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 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 = io.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.(*errors.SignatureError); !ok { t.Errorf("corruption: expected SignatureError, got: %s", err) } } const mdcPlaintextHex = "a302789c3b2d93c4e0eb9aba22283539b3203335af44a134afb800c849cb4c4de10200aff40b45d31432c80cb384299a0655966d6939dfdeed1dddf980" func TestSerialize(t *testing.T) { buf := bytes.NewBuffer(nil) c := CipherAES128 key := make([]byte, c.KeySize()) w, err := SerializeSymmetricallyEncrypted(buf, c, key, nil) if err != nil { t.Errorf("error from SerializeSymmetricallyEncrypted: %s", err) return } contents := []byte("hello world\n") w.Write(contents) w.Close() p, err := Read(buf) if err != nil { t.Errorf("error from Read: %s", err) return } se, ok := p.(*SymmetricallyEncrypted) if !ok { t.Errorf("didn't read a *SymmetricallyEncrypted") return } r, err := se.Decrypt(c, key) if err != nil { t.Errorf("error from Decrypt: %s", err) return } contentsCopy := bytes.NewBuffer(nil) _, err = io.Copy(contentsCopy, r) if err != nil { t.Errorf("error from io.Copy: %s", err) return } if !bytes.Equal(contentsCopy.Bytes(), contents) { t.Errorf("contents not equal got: %x want: %x", contentsCopy.Bytes(), contents) } } lxd-2.0.0/dist/src/golang.org/x/crypto/openpgp/keys_test.go0000644061062106075000000006625312702772344026321 0ustar00stgraberdomain admins00000000000000package openpgp import ( "bytes" "strings" "testing" "time" "golang.org/x/crypto/openpgp/errors" "golang.org/x/crypto/openpgp/packet" ) func TestKeyExpiry(t *testing.T) { kring, _ := ReadKeyRing(readerFromHex(expiringKeyHex)) entity := kring[0] const timeFormat = "2006-01-02" time1, _ := time.Parse(timeFormat, "2013-07-01") // The expiringKeyHex key is structured as: // // pub 1024R/5E237D8C created: 2013-07-01 expires: 2013-07-31 usage: SC // sub 1024R/1ABB25A0 created: 2013-07-01 23:11:07 +0200 CEST expires: 2013-07-08 usage: E // sub 1024R/96A672F5 created: 2013-07-01 23:11:23 +0200 CEST expires: 2013-07-31 usage: E // // So this should select the newest, non-expired encryption key. key, _ := entity.encryptionKey(time1) if id := key.PublicKey.KeyIdShortString(); id != "96A672F5" { t.Errorf("Expected key 1ABB25A0 at time %s, but got key %s", time1.Format(timeFormat), id) } // Once the first encryption subkey has expired, the second should be // selected. time2, _ := time.Parse(timeFormat, "2013-07-09") key, _ = entity.encryptionKey(time2) if id := key.PublicKey.KeyIdShortString(); id != "96A672F5" { t.Errorf("Expected key 96A672F5 at time %s, but got key %s", time2.Format(timeFormat), id) } // Once all the keys have expired, nothing should be returned. time3, _ := time.Parse(timeFormat, "2013-08-01") if key, ok := entity.encryptionKey(time3); ok { t.Errorf("Expected no key at time %s, but got key %s", time3.Format(timeFormat), key.PublicKey.KeyIdShortString()) } } func TestMissingCrossSignature(t *testing.T) { // This public key has a signing subkey, but the subkey does not // contain a cross-signature. keys, err := ReadArmoredKeyRing(bytes.NewBufferString(missingCrossSignatureKey)) if len(keys) != 0 { t.Errorf("Accepted key with missing cross signature") } if err == nil { t.Fatal("Failed to detect error in keyring with missing cross signature") } structural, ok := err.(errors.StructuralError) if !ok { t.Fatalf("Unexpected class of error: %T. Wanted StructuralError", err) } const expectedMsg = "signing subkey is missing cross-signature" if !strings.Contains(string(structural), expectedMsg) { t.Fatalf("Unexpected error: %q. Expected it to contain %q", err, expectedMsg) } } func TestInvalidCrossSignature(t *testing.T) { // This public key has a signing subkey, and the subkey has an // embedded cross-signature. However, the cross-signature does // not correctly validate over the primary and subkey. keys, err := ReadArmoredKeyRing(bytes.NewBufferString(invalidCrossSignatureKey)) if len(keys) != 0 { t.Errorf("Accepted key with invalid cross signature") } if err == nil { t.Fatal("Failed to detect error in keyring with an invalid cross signature") } structural, ok := err.(errors.StructuralError) if !ok { t.Fatalf("Unexpected class of error: %T. Wanted StructuralError", err) } const expectedMsg = "subkey signature invalid" if !strings.Contains(string(structural), expectedMsg) { t.Fatalf("Unexpected error: %q. Expected it to contain %q", err, expectedMsg) } } func TestGoodCrossSignature(t *testing.T) { // This public key has a signing subkey, and the subkey has an // embedded cross-signature which correctly validates over the // primary and subkey. keys, err := ReadArmoredKeyRing(bytes.NewBufferString(goodCrossSignatureKey)) if err != nil { t.Fatal(err) } if len(keys) != 1 { t.Errorf("Failed to accept key with good cross signature, %d", len(keys)) } if len(keys[0].Subkeys) != 1 { t.Errorf("Failed to accept good subkey, %d", len(keys[0].Subkeys)) } } // TestExternallyRevokableKey attempts to load and parse a key with a third party revocation permission. func TestExternallyRevocableKey(t *testing.T) { kring, _ := ReadKeyRing(readerFromHex(subkeyUsageHex)) // The 0xA42704B92866382A key can be revoked by 0xBE3893CB843D0FE70C // according to this signature that appears within the key: // :signature packet: algo 1, keyid A42704B92866382A // version 4, created 1396409682, md5len 0, sigclass 0x1f // digest algo 2, begin of digest a9 84 // hashed subpkt 2 len 4 (sig created 2014-04-02) // hashed subpkt 12 len 22 (revocation key: c=80 a=1 f=CE094AA433F7040BB2DDF0BE3893CB843D0FE70C) // hashed subpkt 7 len 1 (not revocable) // subpkt 16 len 8 (issuer key ID A42704B92866382A) // data: [1024 bits] id := uint64(0xA42704B92866382A) keys := kring.KeysById(id) if len(keys) != 1 { t.Errorf("Expected to find key id %X, but got %d matches", id, len(keys)) } } func TestKeyRevocation(t *testing.T) { kring, _ := ReadKeyRing(readerFromHex(revokedKeyHex)) // revokedKeyHex contains these keys: // pub 1024R/9A34F7C0 2014-03-25 [revoked: 2014-03-25] // sub 1024R/1BA3CD60 2014-03-25 [revoked: 2014-03-25] ids := []uint64{0xA401D9F09A34F7C0, 0x5CD3BE0A1BA3CD60} for _, id := range ids { keys := kring.KeysById(id) if len(keys) != 1 { t.Errorf("Expected KeysById to find revoked key %X, but got %d matches", id, len(keys)) } keys = kring.KeysByIdUsage(id, 0) if len(keys) != 0 { t.Errorf("Expected KeysByIdUsage to filter out revoked key %X, but got %d matches", id, len(keys)) } } } func TestSubkeyRevocation(t *testing.T) { kring, _ := ReadKeyRing(readerFromHex(revokedSubkeyHex)) // revokedSubkeyHex contains these keys: // pub 1024R/4EF7E4BECCDE97F0 2014-03-25 // sub 1024R/D63636E2B96AE423 2014-03-25 // sub 1024D/DBCE4EE19529437F 2014-03-25 // sub 1024R/677815E371C2FD23 2014-03-25 [revoked: 2014-03-25] validKeys := []uint64{0x4EF7E4BECCDE97F0, 0xD63636E2B96AE423, 0xDBCE4EE19529437F} revokedKey := uint64(0x677815E371C2FD23) for _, id := range validKeys { keys := kring.KeysById(id) if len(keys) != 1 { t.Errorf("Expected KeysById to find key %X, but got %d matches", id, len(keys)) } keys = kring.KeysByIdUsage(id, 0) if len(keys) != 1 { t.Errorf("Expected KeysByIdUsage to find key %X, but got %d matches", id, len(keys)) } } keys := kring.KeysById(revokedKey) if len(keys) != 1 { t.Errorf("Expected KeysById to find key %X, but got %d matches", revokedKey, len(keys)) } keys = kring.KeysByIdUsage(revokedKey, 0) if len(keys) != 0 { t.Errorf("Expected KeysByIdUsage to filter out revoked key %X, but got %d matches", revokedKey, len(keys)) } } func TestKeyUsage(t *testing.T) { kring, _ := ReadKeyRing(readerFromHex(subkeyUsageHex)) // subkeyUsageHex contains these keys: // pub 1024R/2866382A created: 2014-04-01 expires: never usage: SC // sub 1024R/936C9153 created: 2014-04-01 expires: never usage: E // sub 1024R/64D5F5BB created: 2014-04-02 expires: never usage: E // sub 1024D/BC0BA992 created: 2014-04-02 expires: never usage: S certifiers := []uint64{0xA42704B92866382A} signers := []uint64{0xA42704B92866382A, 0x42CE2C64BC0BA992} encrypters := []uint64{0x09C0C7D9936C9153, 0xC104E98664D5F5BB} for _, id := range certifiers { keys := kring.KeysByIdUsage(id, packet.KeyFlagCertify) if len(keys) == 1 { if keys[0].PublicKey.KeyId != id { t.Errorf("Expected to find certifier key id %X, but got %X", id, keys[0].PublicKey.KeyId) } } else { t.Errorf("Expected one match for certifier key id %X, but got %d matches", id, len(keys)) } } for _, id := range signers { keys := kring.KeysByIdUsage(id, packet.KeyFlagSign) if len(keys) == 1 { if keys[0].PublicKey.KeyId != id { t.Errorf("Expected to find signing key id %X, but got %X", id, keys[0].PublicKey.KeyId) } } else { t.Errorf("Expected one match for signing key id %X, but got %d matches", id, len(keys)) } // This keyring contains no encryption keys that are also good for signing. keys = kring.KeysByIdUsage(id, packet.KeyFlagEncryptStorage|packet.KeyFlagEncryptCommunications) if len(keys) != 0 { t.Errorf("Unexpected match for encryption key id %X", id) } } for _, id := range encrypters { keys := kring.KeysByIdUsage(id, packet.KeyFlagEncryptStorage|packet.KeyFlagEncryptCommunications) if len(keys) == 1 { if keys[0].PublicKey.KeyId != id { t.Errorf("Expected to find encryption key id %X, but got %X", id, keys[0].PublicKey.KeyId) } } else { t.Errorf("Expected one match for encryption key id %X, but got %d matches", id, len(keys)) } // This keyring contains no encryption keys that are also good for signing. keys = kring.KeysByIdUsage(id, packet.KeyFlagSign) if len(keys) != 0 { t.Errorf("Unexpected match for signing key id %X", id) } } } func TestIdVerification(t *testing.T) { kring, err := ReadKeyRing(readerFromHex(testKeys1And2PrivateHex)) if err != nil { t.Fatal(err) } if err := kring[1].PrivateKey.Decrypt([]byte("passphrase")); err != nil { t.Fatal(err) } const identity = "Test Key 1 (RSA)" if err := kring[0].SignIdentity(identity, kring[1], nil); err != nil { t.Fatal(err) } ident, ok := kring[0].Identities[identity] if !ok { t.Fatal("identity missing from key after signing") } checked := false for _, sig := range ident.Signatures { if sig.IssuerKeyId == nil || *sig.IssuerKeyId != kring[1].PrimaryKey.KeyId { continue } if err := kring[1].PrimaryKey.VerifyUserIdSignature(identity, kring[0].PrimaryKey, sig); err != nil { t.Fatalf("error verifying new identity signature: %s", err) } checked = true break } if !checked { t.Fatal("didn't find identity signature in Entity") } } const expiringKeyHex = "988d0451d1ec5d010400ba3385721f2dc3f4ab096b2ee867ab77213f0a27a8538441c35d2fa225b08798a1439a66a5150e6bdc3f40f5d28d588c712394c632b6299f77db8c0d48d37903fb72ebd794d61be6aa774688839e5fdecfe06b2684cc115d240c98c66cb1ef22ae84e3aa0c2b0c28665c1e7d4d044e7f270706193f5223c8d44e0d70b7b8da830011010001b40f4578706972792074657374206b657988be041301020028050251d1ec5d021b03050900278d00060b090807030206150802090a0b0416020301021e01021780000a091072589ad75e237d8c033503fd10506d72837834eb7f994117740723adc39227104b0d326a1161871c0b415d25b4aedef946ca77ea4c05af9c22b32cf98be86ab890111fced1ee3f75e87b7cc3c00dc63bbc85dfab91c0dc2ad9de2c4d13a34659333a85c6acc1a669c5e1d6cecb0cf1e56c10e72d855ae177ddc9e766f9b2dda57ccbb75f57156438bbdb4e42b88d0451d1ec5d0104009c64906559866c5cb61578f5846a94fcee142a489c9b41e67b12bb54cfe86eb9bc8566460f9a720cb00d6526fbccfd4f552071a8e3f7744b1882d01036d811ee5a3fb91a1c568055758f43ba5d2c6a9676b012f3a1a89e47bbf624f1ad571b208f3cc6224eb378f1645dd3d47584463f9eadeacfd1ce6f813064fbfdcc4b5a53001101000188a504180102000f021b0c050251d1f06b050900093e89000a091072589ad75e237d8c20e00400ab8310a41461425b37889c4da28129b5fae6084fafbc0a47dd1adc74a264c6e9c9cc125f40462ee1433072a58384daef88c961c390ed06426a81b464a53194c4e291ddd7e2e2ba3efced01537d713bd111f48437bde2363446200995e8e0d4e528dda377fd1e8f8ede9c8e2198b393bd86852ce7457a7e3daf74d510461a5b77b88d0451d1ece8010400b3a519f83ab0010307e83bca895170acce8964a044190a2b368892f7a244758d9fc193482648acb1fb9780d28cc22d171931f38bb40279389fc9bf2110876d4f3db4fcfb13f22f7083877fe56592b3b65251312c36f83ffcb6d313c6a17f197dd471f0712aad15a8537b435a92471ba2e5b0c72a6c72536c3b567c558d7b6051001101000188a504180102000f021b0c050251d1f07b050900279091000a091072589ad75e237d8ce69e03fe286026afacf7c97ee20673864d4459a2240b5655219950643c7dba0ac384b1d4359c67805b21d98211f7b09c2a0ccf6410c8c04d4ff4a51293725d8d6570d9d8bb0e10c07d22357caeb49626df99c180be02d77d1fe8ed25e7a54481237646083a9f89a11566cd20b9e995b1487c5f9e02aeb434f3a1897cd416dd0a87861838da3e9e" const subkeyUsageHex = "988d04533a52bc010400d26af43085558f65b9e7dbc90cb9238015259aed5e954637adcfa2181548b2d0b60c65f1f42ec5081cbf1bc0a8aa4900acfb77070837c58f26012fbce297d70afe96e759ad63531f0037538e70dbf8e384569b9720d99d8eb39d8d0a2947233ed242436cb6ac7dfe74123354b3d0119b5c235d3dd9c9d6c004f8ffaf67ad8583001101000188b7041f010200210502533b8552170c8001ce094aa433f7040bb2ddf0be3893cb843d0fe70c020700000a0910a42704b92866382aa98404009d63d916a27543da4221c60087c33f1c44bec9998c5438018ed370cca4962876c748e94b73eb39c58eb698063f3fd6346d58dd2a11c0247934c4a9d71f24754f7468f96fb24c3e791dd2392b62f626148ad724189498cbf993db2df7c0cdc2d677c35da0f16cb16c9ce7c33b4de65a4a91b1d21a130ae9cc26067718910ef8e2b417556d627261203c756d627261407379642e65642e61753e88b80413010200220502533a52bc021b03060b090807030206150802090a0b0416020301021e01021780000a0910a42704b92866382a47840400c0c2bd04f5fca586de408b395b3c280a278259c93eaaa8b79a53b97003f8ed502a8a00446dd9947fb462677e4fcac0dac2f0701847d15130aadb6cd9e0705ea0cf5f92f129136c7be21a718d46c8e641eb7f044f2adae573e11ae423a0a9ca51324f03a8a2f34b91fa40c3cc764bee4dccadedb54c768ba0469b683ea53f1c29b88d04533a52bc01040099c92a5d6f8b744224da27bc2369127c35269b58bec179de6bbc038f749344222f85a31933224f26b70243c4e4b2d242f0c4777eaef7b5502f9dad6d8bf3aaeb471210674b74de2d7078af497d55f5cdad97c7bedfbc1b41e8065a97c9c3d344b21fc81d27723af8e374bc595da26ea242dccb6ae497be26eea57e563ed517e90011010001889f0418010200090502533a52bc021b0c000a0910a42704b92866382afa1403ff70284c2de8a043ff51d8d29772602fa98009b7861c540535f874f2c230af8caf5638151a636b21f8255003997ccd29747fdd06777bb24f9593bd7d98a3e887689bf902f999915fcc94625ae487e5d13e6616f89090ebc4fdc7eb5cad8943e4056995bb61c6af37f8043016876a958ec7ebf39c43d20d53b7f546cfa83e8d2604b88d04533b8283010400c0b529316dbdf58b4c54461e7e669dc11c09eb7f73819f178ccd4177b9182b91d138605fcf1e463262fabefa73f94a52b5e15d1904635541c7ea540f07050ce0fb51b73e6f88644cec86e91107c957a114f69554548a85295d2b70bd0b203992f76eb5d493d86d9eabcaa7ef3fc7db7e458438db3fcdb0ca1cc97c638439a9170011010001889f0418010200090502533b8283021b0c000a0910a42704b92866382adc6d0400cfff6258485a21675adb7a811c3e19ebca18851533f75a7ba317950b9997fda8d1a4c8c76505c08c04b6c2cc31dc704d33da36a21273f2b388a1a706f7c3378b66d887197a525936ed9a69acb57fe7f718133da85ec742001c5d1864e9c6c8ea1b94f1c3759cebfd93b18606066c063a63be86085b7e37bdbc65f9a915bf084bb901a204533b85cd110400aed3d2c52af2b38b5b67904b0ef73d6dd7aef86adb770e2b153cd22489654dcc91730892087bb9856ae2d9f7ed1eb48f214243fe86bfe87b349ebd7c30e630e49c07b21fdabf78b7a95c8b7f969e97e3d33f2e074c63552ba64a2ded7badc05ce0ea2be6d53485f6900c7860c7aa76560376ce963d7271b9b54638a4028b573f00a0d8854bfcdb04986141568046202192263b9b67350400aaa1049dbc7943141ef590a70dcb028d730371d92ea4863de715f7f0f16d168bd3dc266c2450457d46dcbbf0b071547e5fbee7700a820c3750b236335d8d5848adb3c0da010e998908dfd93d961480084f3aea20b247034f8988eccb5546efaa35a92d0451df3aaf1aee5aa36a4c4d462c760ecd9cebcabfbe1412b1f21450f203fd126687cd486496e971a87fd9e1a8a765fe654baa219a6871ab97768596ab05c26c1aeea8f1a2c72395a58dbc12ef9640d2b95784e974a4d2d5a9b17c25fedacfe551bda52602de8f6d2e48443f5dd1a2a2a8e6a5e70ecdb88cd6e766ad9745c7ee91d78cc55c3d06536b49c3fee6c3d0b6ff0fb2bf13a314f57c953b8f4d93bf88e70418010200090502533b85cd021b0200520910a42704b92866382a47200419110200060502533b85cd000a091042ce2c64bc0ba99214b2009e26b26852c8b13b10c35768e40e78fbbb48bd084100a0c79d9ea0844fa5853dd3c85ff3ecae6f2c9dd6c557aa04008bbbc964cd65b9b8299d4ebf31f41cc7264b8cf33a00e82c5af022331fac79efc9563a822497ba012953cefe2629f1242fcdcb911dbb2315985bab060bfd58261ace3c654bdbbe2e8ed27a46e836490145c86dc7bae15c011f7e1ffc33730109b9338cd9f483e7cef3d2f396aab5bd80efb6646d7e778270ee99d934d187dd98" const revokedKeyHex = "988d045331ce82010400c4fdf7b40a5477f206e6ee278eaef888ca73bf9128a9eef9f2f1ddb8b7b71a4c07cfa241f028a04edb405e4d916c61d6beabc333813dc7b484d2b3c52ee233c6a79b1eea4e9cc51596ba9cd5ac5aeb9df62d86ea051055b79d03f8a4fa9f38386f5bd17529138f3325d46801514ea9047977e0829ed728e68636802796801be10011010001889f04200102000905025331d0e3021d03000a0910a401d9f09a34f7c042aa040086631196405b7e6af71026b88e98012eab44aa9849f6ef3fa930c7c9f23deaedba9db1538830f8652fb7648ec3fcade8dbcbf9eaf428e83c6cbcc272201bfe2fbb90d41963397a7c0637a1a9d9448ce695d9790db2dc95433ad7be19eb3de72dacf1d6db82c3644c13eae2a3d072b99bb341debba012c5ce4006a7d34a1f4b94b444526567205265766f6b657220283c52656727732022424d204261726973746122204b657920262530305c303e5c29203c72656740626d626172697374612e636f2e61753e88b704130102002205025331ce82021b03060b090807030206150802090a0b0416020301021e01021780000a0910a401d9f09a34f7c0019c03f75edfbeb6a73e7225ad3cc52724e2872e04260d7daf0d693c170d8c4b243b8767bc7785763533febc62ec2600c30603c433c095453ede59ff2fcabeb84ce32e0ed9d5cf15ffcbc816202b64370d4d77c1e9077d74e94a16fb4fa2e5bec23a56d7a73cf275f91691ae1801a976fcde09e981a2f6327ac27ea1fecf3185df0d56889c04100102000605025331cfb5000a0910fe9645554e8266b64b4303fc084075396674fb6f778d302ac07cef6bc0b5d07b66b2004c44aef711cbac79617ef06d836b4957522d8772dd94bf41a2f4ac8b1ee6d70c57503f837445a74765a076d07b829b8111fc2a918423ddb817ead7ca2a613ef0bfb9c6b3562aec6c3cf3c75ef3031d81d95f6563e4cdcc9960bcb386c5d757b104fcca5fe11fc709df884604101102000605025331cfe7000a09107b15a67f0b3ddc0317f6009e360beea58f29c1d963a22b962b80788c3fa6c84e009d148cfde6b351469b8eae91187eff07ad9d08fcaab88d045331ce820104009f25e20a42b904f3fa555530fe5c46737cf7bd076c35a2a0d22b11f7e0b61a69320b768f4a80fe13980ce380d1cfc4a0cd8fbe2d2e2ef85416668b77208baa65bf973fe8e500e78cc310d7c8705cdb34328bf80e24f0385fce5845c33bc7943cf6b11b02348a23da0bf6428e57c05135f2dc6bd7c1ce325d666d5a5fd2fd5e410011010001889f04180102000905025331ce82021b0c000a0910a401d9f09a34f7c0418003fe34feafcbeaef348a800a0d908a7a6809cc7304017d820f70f0474d5e23cb17e38b67dc6dca282c6ca00961f4ec9edf2738d0f087b1d81e4871ef08e1798010863afb4eac4c44a376cb343be929c5be66a78cfd4456ae9ec6a99d97f4e1c3ff3583351db2147a65c0acef5c003fb544ab3a2e2dc4d43646f58b811a6c3a369d1f" const revokedSubkeyHex = "988d04533121f6010400aefc803a3e4bb1a61c86e8a86d2726c6a43e0079e9f2713f1fa017e9854c83877f4aced8e331d675c67ea83ddab80aacbfa0b9040bb12d96f5a3d6be09455e2a76546cbd21677537db941cab710216b6d24ec277ee0bd65b910f416737ed120f6b93a9d3b306245c8cfd8394606fdb462e5cf43c551438d2864506c63367fc890011010001b41d416c696365203c616c69636540626d626172697374612e636f2e61753e88bb041301020025021b03060b090807030206150802090a0b0416020301021e01021780050253312798021901000a09104ef7e4beccde97f015a803ff5448437780f63263b0df8442a995e7f76c221351a51edd06f2063d8166cf3157aada4923dfc44aa0f2a6a4da5cf83b7fe722ba8ab416c976e77c6b5682e7f1069026673bd0de56ba06fd5d7a9f177607f277d9b55ff940a638c3e68525c67517e2b3d976899b93ca267f705b3e5efad7d61220e96b618a4497eab8d04403d23f8846041011020006050253312910000a09107b15a67f0b3ddc03d96e009f50b6365d86c4be5d5e9d0ea42d5e56f5794c617700a0ab274e19c2827780016d23417ce89e0a2c0d987d889c04100102000605025331cf7a000a0910a401d9f09a34f7c0ee970400aca292f213041c9f3b3fc49148cbda9d84afee6183c8dd6c5ff2600b29482db5fecd4303797be1ee6d544a20a858080fec43412061c9a71fae4039fd58013b4ae341273e6c66ad4c7cdd9e68245bedb260562e7b166f2461a1032f2b38c0e0e5715fb3d1656979e052b55ca827a76f872b78a9fdae64bc298170bfcebedc1271b41a416c696365203c616c696365407379646973702e6f722e61753e88b804130102002205025331278b021b03060b090807030206150802090a0b0416020301021e01021780000a09104ef7e4beccde97f06a7003fa03c3af68d272ebc1fa08aa72a03b02189c26496a2833d90450801c4e42c5b5f51ad96ce2d2c9cef4b7c02a6a2fcf1412d6a2d486098eb762f5010a201819c17fd2888aec8eda20c65a3b75744de7ee5cc8ac7bfc470cbe3cb982720405a27a3c6a8c229cfe36905f881b02ed5680f6a8f05866efb9d6c5844897e631deb949ca8846041011020006050253312910000a09107b15a67f0b3ddc0347bc009f7fa35db59147469eb6f2c5aaf6428accb138b22800a0caa2f5f0874bacc5909c652a57a31beda65eddd5889c04100102000605025331cf7a000a0910a401d9f09a34f7c0316403ff46f2a5c101256627f16384d34a38fb47a6c88ba60506843e532d91614339fccae5f884a5741e7582ffaf292ba38ee10a270a05f139bde3814b6a077e8cd2db0f105ebea2a83af70d385f13b507fac2ad93ff79d84950328bb86f3074745a8b7f9b64990fb142e2a12976e27e8d09a28dc5621f957ac49091116da410ac3cbde1b88d04533121f6010400cbd785b56905e4192e2fb62a720727d43c4fa487821203cf72138b884b78b701093243e1d8c92a0248a6c0203a5a88693da34af357499abacaf4b3309c640797d03093870a323b4b6f37865f6eaa2838148a67df4735d43a90ca87942554cdf1c4a751b1e75f9fd4ce4e97e278d6c1c7ed59d33441df7d084f3f02beb68896c70011010001889f0418010200090502533121f6021b0c000a09104ef7e4beccde97f0b98b03fc0a5ccf6a372995835a2f5da33b282a7d612c0ab2a97f59cf9fff73e9110981aac2858c41399afa29624a7fd8a0add11654e3d882c0fd199e161bdad65e5e2548f7b68a437ea64293db1246e3011cbb94dc1bcdeaf0f2539bd88ff16d95547144d97cead6a8c5927660a91e6db0d16eb36b7b49a3525b54d1644e65599b032b7eb901a204533127a0110400bd3edaa09eff9809c4edc2c2a0ebe52e53c50a19c1e49ab78e6167bf61473bb08f2050d78a5cbbc6ed66aff7b42cd503f16b4a0b99fa1609681fca9b7ce2bbb1a5b3864d6cdda4d7ef7849d156d534dea30fb0efb9e4cf8959a2b2ce623905882d5430b995a15c3b9fe92906086788b891002924f94abe139b42cbbfaaabe42f00a0b65dc1a1ad27d798adbcb5b5ad02d2688c89477b03ff4eebb6f7b15a73b96a96bed201c0e5e4ea27e4c6e2dd1005b94d4b90137a5b1cf5e01c6226c070c4cc999938101578877ee76d296b9aab8246d57049caacf489e80a3f40589cade790a020b1ac146d6f7a6241184b8c7fcde680eae3188f5dcbe846d7f7bdad34f6fcfca08413e19c1d5df83fc7c7c627d493492e009c2f52a80400a2fe82de87136fd2e8845888c4431b032ba29d9a29a804277e31002a8201fb8591a3e55c7a0d0881496caf8b9fb07544a5a4879291d0dc026a0ea9e5bd88eb4aa4947bbd694b25012e208a250d65ddc6f1eea59d3aed3b4ec15fcab85e2afaa23a40ab1ef9ce3e11e1bc1c34a0e758e7aa64deb8739276df0af7d4121f834a9b88e70418010200090502533127a0021b02005209104ef7e4beccde97f047200419110200060502533127a0000a0910dbce4ee19529437fe045009c0b32f5ead48ee8a7e98fac0dea3d3e6c0e2c552500a0ad71fadc5007cfaf842d9b7db3335a8cdad15d3d1a6404009b08e2c68fe8f3b45c1bb72a4b3278cdf3012aa0f229883ad74aa1f6000bb90b18301b2f85372ca5d6b9bf478d235b733b1b197d19ccca48e9daf8e890cb64546b4ce1b178faccfff07003c172a2d4f5ebaba9f57153955f3f61a9b80a4f5cb959908f8b211b03b7026a8a82fc612bfedd3794969bcf458c4ce92be215a1176ab88d045331d144010400a5063000c5aaf34953c1aa3bfc95045b3aab9882b9a8027fecfe2142dc6b47ba8aca667399990244d513dd0504716908c17d92c65e74219e004f7b83fc125e575dd58efec3ab6dd22e3580106998523dea42ec75bf9aa111734c82df54630bebdff20fe981cfc36c76f865eb1c2fb62c9e85bc3a6e5015a361a2eb1c8431578d0011010001889f04280102000905025331d433021d03000a09104ef7e4beccde97f02e5503ff5e0630d1b65291f4882b6d40a29da4616bb5088717d469fbcc3648b8276de04a04988b1f1b9f3e18f52265c1f8b6c85861691c1a6b8a3a25a1809a0b32ad330aec5667cb4262f4450649184e8113849b05e5ad06a316ea80c001e8e71838190339a6e48bbde30647bcf245134b9a97fa875c1d83a9862cae87ffd7e2c4ce3a1b89013d04180102000905025331d144021b0200a809104ef7e4beccde97f09d2004190102000605025331d144000a0910677815e371c2fd23522203fe22ab62b8e7a151383cea3edd3a12995693911426f8ccf125e1f6426388c0010f88d9ca7da2224aee8d1c12135998640c5e1813d55a93df472faae75bef858457248db41b4505827590aeccf6f9eb646da7f980655dd3050c6897feddddaca90676dee856d66db8923477d251712bb9b3186b4d0114daf7d6b59272b53218dd1da94a03ff64006fcbe71211e5daecd9961fba66cdb6de3f914882c58ba5beddeba7dcb950c1156d7fba18c19ea880dccc800eae335deec34e3b84ac75ffa24864f782f87815cda1c0f634b3dd2fa67cea30811d21723d21d9551fa12ccbcfa62b6d3a15d01307b99925707992556d50065505b090aadb8579083a20fe65bd2a270da9b011" const missingCrossSignatureKey = `-----BEGIN PGP PUBLIC KEY BLOCK----- Charset: UTF-8 mQENBFMYynYBCACVOZ3/e8Bm2b9KH9QyIlHGo/i1bnkpqsgXj8tpJ2MIUOnXMMAY ztW7kKFLCmgVdLIC0vSoLA4yhaLcMojznh/2CcUglZeb6Ao8Gtelr//Rd5DRfPpG zqcfUo+m+eO1co2Orabw0tZDfGpg5p3AYl0hmxhUyYSc/xUq93xL1UJzBFgYXY54 QsM8dgeQgFseSk/YvdP5SMx1ev+eraUyiiUtWzWrWC1TdyRa5p4UZg6Rkoppf+WJ QrW6BWrhAtqATHc8ozV7uJjeONjUEq24roRc/OFZdmQQGK6yrzKnnbA6MdHhqpdo 9kWDcXYb7pSE63Lc+OBa5X2GUVvXJLS/3nrtABEBAAG0F2ludmFsaWQtc2lnbmlu Zy1zdWJrZXlziQEoBBMBAgASBQJTnKB5AhsBAgsHAhUIAh4BAAoJEO3UDQUIHpI/ dN4H/idX4FQ1LIZCnpHS/oxoWQWfpRgdKAEM0qCqjMgiipJeEwSQbqjTCynuh5/R JlODDz85ABR06aoF4l5ebGLQWFCYifPnJZ/Yf5OYcMGtb7dIbqxWVFL9iLMO/oDL ioI3dotjPui5e+2hI9pVH1UHB/bZ/GvMGo6Zg0XxLPolKQODMVjpjLAQ0YJ3spew RAmOGre6tIvbDsMBnm8qREt7a07cBJ6XK7xjxYaZHQBiHVxyEWDa6gyANONx8duW /fhQ/zDTnyVM/ik6VO0Ty9BhPpcEYLFwh5c1ilFari1ta3e6qKo6ZGa9YMk/REhu yBHd9nTkI+0CiQUmbckUiVjDKKe5AQ0EUxjKdgEIAJcXQeP+NmuciE99YcJoffxv 2gVLU4ZXBNHEaP0mgaJ1+tmMD089vUQAcyGRvw8jfsNsVZQIOAuRxY94aHQhIRHR bUzBN28ofo/AJJtfx62C15xt6fDKRV6HXYqAiygrHIpEoRLyiN69iScUsjIJeyFL C8wa72e8pSL6dkHoaV1N9ZH/xmrJ+k0vsgkQaAh9CzYufncDxcwkoP+aOlGtX1gP WwWoIbz0JwLEMPHBWvDDXQcQPQTYQyj+LGC9U6f9VZHN25E94subM1MjuT9OhN9Y MLfWaaIc5WyhLFyQKW2Upofn9wSFi8ubyBnv640Dfd0rVmaWv7LNTZpoZ/GbJAMA EQEAAYkBHwQYAQIACQUCU5ygeQIbAgAKCRDt1A0FCB6SP0zCB/sEzaVR38vpx+OQ MMynCBJrakiqDmUZv9xtplY7zsHSQjpd6xGflbU2n+iX99Q+nav0ETQZifNUEd4N 1ljDGQejcTyKD6Pkg6wBL3x9/RJye7Zszazm4+toJXZ8xJ3800+BtaPoI39akYJm +ijzbskvN0v/j5GOFJwQO0pPRAFtdHqRs9Kf4YanxhedB4dIUblzlIJuKsxFit6N lgGRblagG3Vv2eBszbxzPbJjHCgVLR3RmrVezKOsZjr/2i7X+xLWIR0uD3IN1qOW CXQxLBizEEmSNVNxsp7KPGTLnqO3bPtqFirxS9PJLIMPTPLNBY7ZYuPNTMqVIUWF 4artDmrG =7FfJ -----END PGP PUBLIC KEY BLOCK-----` const invalidCrossSignatureKey = `-----BEGIN PGP PUBLIC KEY BLOCK----- mQENBFMYynYBCACVOZ3/e8Bm2b9KH9QyIlHGo/i1bnkpqsgXj8tpJ2MIUOnXMMAY ztW7kKFLCmgVdLIC0vSoLA4yhaLcMojznh/2CcUglZeb6Ao8Gtelr//Rd5DRfPpG zqcfUo+m+eO1co2Orabw0tZDfGpg5p3AYl0hmxhUyYSc/xUq93xL1UJzBFgYXY54 QsM8dgeQgFseSk/YvdP5SMx1ev+eraUyiiUtWzWrWC1TdyRa5p4UZg6Rkoppf+WJ QrW6BWrhAtqATHc8ozV7uJjeONjUEq24roRc/OFZdmQQGK6yrzKnnbA6MdHhqpdo 9kWDcXYb7pSE63Lc+OBa5X2GUVvXJLS/3nrtABEBAAG0F2ludmFsaWQtc2lnbmlu Zy1zdWJrZXlziQEoBBMBAgASBQJTnKB5AhsBAgsHAhUIAh4BAAoJEO3UDQUIHpI/ dN4H/idX4FQ1LIZCnpHS/oxoWQWfpRgdKAEM0qCqjMgiipJeEwSQbqjTCynuh5/R JlODDz85ABR06aoF4l5ebGLQWFCYifPnJZ/Yf5OYcMGtb7dIbqxWVFL9iLMO/oDL ioI3dotjPui5e+2hI9pVH1UHB/bZ/GvMGo6Zg0XxLPolKQODMVjpjLAQ0YJ3spew RAmOGre6tIvbDsMBnm8qREt7a07cBJ6XK7xjxYaZHQBiHVxyEWDa6gyANONx8duW /fhQ/zDTnyVM/ik6VO0Ty9BhPpcEYLFwh5c1ilFari1ta3e6qKo6ZGa9YMk/REhu yBHd9nTkI+0CiQUmbckUiVjDKKe5AQ0EUxjKdgEIAIINDqlj7X6jYKc6DjwrOkjQ UIRWbQQar0LwmNilehmt70g5DCL1SYm9q4LcgJJ2Nhxj0/5qqsYib50OSWMcKeEe iRXpXzv1ObpcQtI5ithp0gR53YPXBib80t3bUzomQ5UyZqAAHzMp3BKC54/vUrSK FeRaxDzNLrCeyI00+LHNUtwghAqHvdNcsIf8VRumK8oTm3RmDh0TyjASWYbrt9c8 R1Um3zuoACOVy+mEIgIzsfHq0u7dwYwJB5+KeM7ZLx+HGIYdUYzHuUE1sLwVoELh +SHIGHI1HDicOjzqgajShuIjj5hZTyQySVprrsLKiXS6NEwHAP20+XjayJ/R3tEA EQEAAYkCPgQYAQIBKAUCU5ygeQIbAsBdIAQZAQIABgUCU5ygeQAKCRCpVlnFZmhO 52RJB/9uD1MSa0wjY6tHOIgquZcP3bHBvHmrHNMw9HR2wRCMO91ZkhrpdS3ZHtgb u3/55etj0FdvDo1tb8P8FGSVtO5Vcwf5APM8sbbqoi8L951Q3i7qt847lfhu6sMl w0LWFvPTOLHrliZHItPRjOltS1WAWfr2jUYhsU9ytaDAJmvf9DujxEOsN5G1YJep 54JCKVCkM/y585Zcnn+yxk/XwqoNQ0/iJUT9qRrZWvoeasxhl1PQcwihCwss44A+ YXaAt3hbk+6LEQuZoYS73yR3WHj+42tfm7YxRGeubXfgCEz/brETEWXMh4pe0vCL bfWrmfSPq2rDegYcAybxRQz0lF8PAAoJEO3UDQUIHpI/exkH/0vQfdHA8g/N4T6E i6b1CUVBAkvtdJpCATZjWPhXmShOw62gkDw306vHPilL4SCvEEi4KzG72zkp6VsB DSRcpxCwT4mHue+duiy53/aRMtSJ+vDfiV1Vhq+3sWAck/yUtfDU9/u4eFaiNok1 8/Gd7reyuZt5CiJnpdPpjCwelK21l2w7sHAnJF55ITXdOxI8oG3BRKufz0z5lyDY s2tXYmhhQIggdgelN8LbcMhWs/PBbtUr6uZlNJG2lW1yscD4aI529VjwJlCeo745 U7pO4eF05VViUJ2mmfoivL3tkhoTUWhx8xs8xCUcCg8DoEoSIhxtOmoTPR22Z9BL 6LCg2mg= =Dhm4 -----END PGP PUBLIC KEY BLOCK-----` const goodCrossSignatureKey = `-----BEGIN PGP PUBLIC KEY BLOCK----- Version: GnuPG v1 mI0EVUqeVwEEAMufHRrMPWK3gyvi0O0tABCs/oON9zV9KDZlr1a1M91ShCSFwCPo 7r80PxdWVWcj0V5h50/CJYtpN3eE/mUIgW2z1uDYQF1OzrQ8ubrksfsJvpAhENom lTQEppv9mV8qhcM278teb7TX0pgrUHLYF5CfPdp1L957JLLXoQR/lwLVABEBAAG0 E2dvb2Qtc2lnbmluZy1zdWJrZXmIuAQTAQIAIgUCVUqeVwIbAwYLCQgHAwIGFQgC CQoLBBYCAwECHgECF4AACgkQNRjL95IRWP69XQQAlH6+eyXJN4DZTLX78KGjHrsw 6FCvxxClEPtPUjcJy/1KCRQmtLAt9PbbA78dvgzjDeZMZqRAwdjyJhjyg/fkU2OH 7wq4ktjUu+dLcOBb+BFMEY+YjKZhf6EJuVfxoTVr5f82XNPbYHfTho9/OABKH6kv X70PaKZhbwnwij8Nts65AaIEVUqftREEAJ3WxZfqAX0bTDbQPf2CMT2IVMGDfhK7 GyubOZgDFFjwUJQvHNvsrbeGLZ0xOBumLINyPO1amIfTgJNm1iiWFWfmnHReGcDl y5mpYG60Mb79Whdcer7CMm3AqYh/dW4g6IB02NwZMKoUHo3PXmFLxMKXnWyJ0clw R0LI/Qn509yXAKDh1SO20rqrBM+EAP2c5bfI98kyNwQAi3buu94qo3RR1ZbvfxgW CKXDVm6N99jdZGNK7FbRifXqzJJDLcXZKLnstnC4Sd3uyfyf1uFhmDLIQRryn5m+ LBYHfDBPN3kdm7bsZDDq9GbTHiFZUfm/tChVKXWxkhpAmHhU/tH6GGzNSMXuIWSO aOz3Rqq0ED4NXyNKjdF9MiwD/i83S0ZBc0LmJYt4Z10jtH2B6tYdqnAK29uQaadx yZCX2scE09UIm32/w7pV77CKr1Cp/4OzAXS1tmFzQ+bX7DR+Gl8t4wxr57VeEMvl BGw4Vjh3X8//m3xynxycQU18Q1zJ6PkiMyPw2owZ/nss3hpSRKFJsxMLhW3fKmKr Ey2KiOcEGAECAAkFAlVKn7UCGwIAUgkQNRjL95IRWP5HIAQZEQIABgUCVUqftQAK CRD98VjDN10SqkWrAKDTpEY8D8HC02E/KVC5YUI01B30wgCgurpILm20kXEDCeHp C5pygfXw1DJrhAP+NyPJ4um/bU1I+rXaHHJYroYJs8YSweiNcwiHDQn0Engh/mVZ SqLHvbKh2dL/RXymC3+rjPvQf5cup9bPxNMa6WagdYBNAfzWGtkVISeaQW+cTEp/ MtgVijRGXR/lGLGETPg2X3Afwn9N9bLMBkBprKgbBqU7lpaoPupxT61bL70= =vtbN -----END PGP PUBLIC KEY BLOCK-----` lxd-2.0.0/dist/src/golang.org/x/crypto/blowfish/0000755061062106075000000000000012702772344024111 5ustar00stgraberdomain admins00000000000000lxd-2.0.0/dist/src/golang.org/x/crypto/blowfish/cipher.go0000644061062106075000000000604512702772344025717 0ustar00stgraberdomain admins00000000000000// Copyright 2010 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Package blowfish implements Bruce Schneier's Blowfish encryption algorithm. package blowfish // import "golang.org/x/crypto/blowfish" // The code is a port of Bruce Schneier's C implementation. // See http://www.schneier.com/blowfish.html. import "strconv" // The Blowfish block size in bytes. const BlockSize = 8 // A Cipher is an instance of Blowfish encryption using a particular key. type Cipher struct { p [18]uint32 s0, s1, s2, s3 [256]uint32 } type KeySizeError int func (k KeySizeError) Error() string { return "crypto/blowfish: invalid key size " + strconv.Itoa(int(k)) } // NewCipher creates and returns a Cipher. // The key argument should be the Blowfish key, from 1 to 56 bytes. func NewCipher(key []byte) (*Cipher, error) { var result Cipher if k := len(key); k < 1 || k > 56 { return nil, KeySizeError(k) } initCipher(&result) ExpandKey(key, &result) return &result, nil } // NewSaltedCipher creates a returns a Cipher that folds a salt into its key // schedule. For most purposes, NewCipher, instead of NewSaltedCipher, is // sufficient and desirable. For bcrypt compatiblity, the key can be over 56 // bytes. func NewSaltedCipher(key, salt []byte) (*Cipher, error) { if len(salt) == 0 { return NewCipher(key) } var result Cipher if k := len(key); k < 1 { return nil, KeySizeError(k) } initCipher(&result) expandKeyWithSalt(key, salt, &result) return &result, nil } // BlockSize returns the Blowfish block size, 8 bytes. // It is necessary to satisfy the Block interface in the // package "crypto/cipher". func (c *Cipher) BlockSize() int { return BlockSize } // Encrypt encrypts the 8-byte buffer src using the key k // and stores the result in dst. // Note that for amounts of data larger than a block, // it is not safe to just call Encrypt on successive blocks; // instead, use an encryption mode like CBC (see crypto/cipher/cbc.go). func (c *Cipher) Encrypt(dst, src []byte) { l := uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3]) r := uint32(src[4])<<24 | uint32(src[5])<<16 | uint32(src[6])<<8 | uint32(src[7]) l, r = encryptBlock(l, r, c) dst[0], dst[1], dst[2], dst[3] = byte(l>>24), byte(l>>16), byte(l>>8), byte(l) dst[4], dst[5], dst[6], dst[7] = byte(r>>24), byte(r>>16), byte(r>>8), byte(r) } // Decrypt decrypts the 8-byte buffer src using the key k // and stores the result in dst. func (c *Cipher) Decrypt(dst, src []byte) { l := uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3]) r := uint32(src[4])<<24 | uint32(src[5])<<16 | uint32(src[6])<<8 | uint32(src[7]) l, r = decryptBlock(l, r, c) dst[0], dst[1], dst[2], dst[3] = byte(l>>24), byte(l>>16), byte(l>>8), byte(l) dst[4], dst[5], dst[6], dst[7] = byte(r>>24), byte(r>>16), byte(r>>8), byte(r) } func initCipher(c *Cipher) { copy(c.p[0:], p[0:]) copy(c.s0[0:], s0[0:]) copy(c.s1[0:], s1[0:]) copy(c.s2[0:], s2[0:]) copy(c.s3[0:], s3[0:]) } lxd-2.0.0/dist/src/golang.org/x/crypto/blowfish/block.go0000644061062106075000000001402112702772344025530 0ustar00stgraberdomain admins00000000000000// Copyright 2010 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package blowfish // getNextWord returns the next big-endian uint32 value from the byte slice // at the given position in a circular manner, updating the position. func getNextWord(b []byte, pos *int) uint32 { var w uint32 j := *pos for i := 0; i < 4; i++ { w = w<<8 | uint32(b[j]) j++ if j >= len(b) { j = 0 } } *pos = j return w } // ExpandKey performs a key expansion on the given *Cipher. Specifically, it // performs the Blowfish algorithm's key schedule which sets up the *Cipher's // pi and substitution tables for calls to Encrypt. This is used, primarily, // by the bcrypt package to reuse the Blowfish key schedule during its // set up. It's unlikely that you need to use this directly. func ExpandKey(key []byte, c *Cipher) { j := 0 for i := 0; i < 18; i++ { // Using inlined getNextWord for performance. var d uint32 for k := 0; k < 4; k++ { d = d<<8 | uint32(key[j]) j++ if j >= len(key) { j = 0 } } c.p[i] ^= d } var l, r uint32 for i := 0; i < 18; i += 2 { l, r = encryptBlock(l, r, c) c.p[i], c.p[i+1] = l, r } for i := 0; i < 256; i += 2 { l, r = encryptBlock(l, r, c) c.s0[i], c.s0[i+1] = l, r } for i := 0; i < 256; i += 2 { l, r = encryptBlock(l, r, c) c.s1[i], c.s1[i+1] = l, r } for i := 0; i < 256; i += 2 { l, r = encryptBlock(l, r, c) c.s2[i], c.s2[i+1] = l, r } for i := 0; i < 256; i += 2 { l, r = encryptBlock(l, r, c) c.s3[i], c.s3[i+1] = l, r } } // This is similar to ExpandKey, but folds the salt during the key // schedule. While ExpandKey is essentially expandKeyWithSalt with an all-zero // salt passed in, reusing ExpandKey turns out to be a place of inefficiency // and specializing it here is useful. func expandKeyWithSalt(key []byte, salt []byte, c *Cipher) { j := 0 for i := 0; i < 18; i++ { c.p[i] ^= getNextWord(key, &j) } j = 0 var l, r uint32 for i := 0; i < 18; i += 2 { l ^= getNextWord(salt, &j) r ^= getNextWord(salt, &j) l, r = encryptBlock(l, r, c) c.p[i], c.p[i+1] = l, r } for i := 0; i < 256; i += 2 { l ^= getNextWord(salt, &j) r ^= getNextWord(salt, &j) l, r = encryptBlock(l, r, c) c.s0[i], c.s0[i+1] = l, r } for i := 0; i < 256; i += 2 { l ^= getNextWord(salt, &j) r ^= getNextWord(salt, &j) l, r = encryptBlock(l, r, c) c.s1[i], c.s1[i+1] = l, r } for i := 0; i < 256; i += 2 { l ^= getNextWord(salt, &j) r ^= getNextWord(salt, &j) l, r = encryptBlock(l, r, c) c.s2[i], c.s2[i+1] = l, r } for i := 0; i < 256; i += 2 { l ^= getNextWord(salt, &j) r ^= getNextWord(salt, &j) l, r = encryptBlock(l, r, c) c.s3[i], c.s3[i+1] = l, r } } func encryptBlock(l, r uint32, c *Cipher) (uint32, uint32) { xl, xr := l, r xl ^= c.p[0] xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[1] xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[2] xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[3] xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[4] xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[5] xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[6] xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[7] xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[8] xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[9] xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[10] xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[11] xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[12] xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[13] xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[14] xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[15] xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[16] xr ^= c.p[17] return xr, xl } func decryptBlock(l, r uint32, c *Cipher) (uint32, uint32) { xl, xr := l, r xl ^= c.p[17] xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[16] xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[15] xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[14] xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[13] xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[12] xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[11] xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[10] xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[9] xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[8] xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[7] xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[6] xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[5] xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[4] xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[3] xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[2] xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[1] xr ^= c.p[0] return xr, xl } lxd-2.0.0/dist/src/golang.org/x/crypto/blowfish/blowfish_test.go0000644061062106075000000002372512702772344027325 0ustar00stgraberdomain admins00000000000000// Copyright 2010 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package blowfish import "testing" type CryptTest struct { key []byte in []byte out []byte } // Test vector values are from http://www.schneier.com/code/vectors.txt. var encryptTests = []CryptTest{ { []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, []byte{0x4E, 0xF9, 0x97, 0x45, 0x61, 0x98, 0xDD, 0x78}}, { []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, []byte{0x51, 0x86, 0x6F, 0xD5, 0xB8, 0x5E, 0xCB, 0x8A}}, { []byte{0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, []byte{0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, []byte{0x7D, 0x85, 0x6F, 0x9A, 0x61, 0x30, 0x63, 0xF2}}, { []byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11}, []byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11}, []byte{0x24, 0x66, 0xDD, 0x87, 0x8B, 0x96, 0x3C, 0x9D}}, { []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF}, []byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11}, []byte{0x61, 0xF9, 0xC3, 0x80, 0x22, 0x81, 0xB0, 0x96}}, { []byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11}, []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF}, []byte{0x7D, 0x0C, 0xC6, 0x30, 0xAF, 0xDA, 0x1E, 0xC7}}, { []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, []byte{0x4E, 0xF9, 0x97, 0x45, 0x61, 0x98, 0xDD, 0x78}}, { []byte{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}, []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF}, []byte{0x0A, 0xCE, 0xAB, 0x0F, 0xC6, 0xA0, 0xA2, 0x8D}}, { []byte{0x7C, 0xA1, 0x10, 0x45, 0x4A, 0x1A, 0x6E, 0x57}, []byte{0x01, 0xA1, 0xD6, 0xD0, 0x39, 0x77, 0x67, 0x42}, []byte{0x59, 0xC6, 0x82, 0x45, 0xEB, 0x05, 0x28, 0x2B}}, { []byte{0x01, 0x31, 0xD9, 0x61, 0x9D, 0xC1, 0x37, 0x6E}, []byte{0x5C, 0xD5, 0x4C, 0xA8, 0x3D, 0xEF, 0x57, 0xDA}, []byte{0xB1, 0xB8, 0xCC, 0x0B, 0x25, 0x0F, 0x09, 0xA0}}, { []byte{0x07, 0xA1, 0x13, 0x3E, 0x4A, 0x0B, 0x26, 0x86}, []byte{0x02, 0x48, 0xD4, 0x38, 0x06, 0xF6, 0x71, 0x72}, []byte{0x17, 0x30, 0xE5, 0x77, 0x8B, 0xEA, 0x1D, 0xA4}}, { []byte{0x38, 0x49, 0x67, 0x4C, 0x26, 0x02, 0x31, 0x9E}, []byte{0x51, 0x45, 0x4B, 0x58, 0x2D, 0xDF, 0x44, 0x0A}, []byte{0xA2, 0x5E, 0x78, 0x56, 0xCF, 0x26, 0x51, 0xEB}}, { []byte{0x04, 0xB9, 0x15, 0xBA, 0x43, 0xFE, 0xB5, 0xB6}, []byte{0x42, 0xFD, 0x44, 0x30, 0x59, 0x57, 0x7F, 0xA2}, []byte{0x35, 0x38, 0x82, 0xB1, 0x09, 0xCE, 0x8F, 0x1A}}, { []byte{0x01, 0x13, 0xB9, 0x70, 0xFD, 0x34, 0xF2, 0xCE}, []byte{0x05, 0x9B, 0x5E, 0x08, 0x51, 0xCF, 0x14, 0x3A}, []byte{0x48, 0xF4, 0xD0, 0x88, 0x4C, 0x37, 0x99, 0x18}}, { []byte{0x01, 0x70, 0xF1, 0x75, 0x46, 0x8F, 0xB5, 0xE6}, []byte{0x07, 0x56, 0xD8, 0xE0, 0x77, 0x47, 0x61, 0xD2}, []byte{0x43, 0x21, 0x93, 0xB7, 0x89, 0x51, 0xFC, 0x98}}, { []byte{0x43, 0x29, 0x7F, 0xAD, 0x38, 0xE3, 0x73, 0xFE}, []byte{0x76, 0x25, 0x14, 0xB8, 0x29, 0xBF, 0x48, 0x6A}, []byte{0x13, 0xF0, 0x41, 0x54, 0xD6, 0x9D, 0x1A, 0xE5}}, { []byte{0x07, 0xA7, 0x13, 0x70, 0x45, 0xDA, 0x2A, 0x16}, []byte{0x3B, 0xDD, 0x11, 0x90, 0x49, 0x37, 0x28, 0x02}, []byte{0x2E, 0xED, 0xDA, 0x93, 0xFF, 0xD3, 0x9C, 0x79}}, { []byte{0x04, 0x68, 0x91, 0x04, 0xC2, 0xFD, 0x3B, 0x2F}, []byte{0x26, 0x95, 0x5F, 0x68, 0x35, 0xAF, 0x60, 0x9A}, []byte{0xD8, 0x87, 0xE0, 0x39, 0x3C, 0x2D, 0xA6, 0xE3}}, { []byte{0x37, 0xD0, 0x6B, 0xB5, 0x16, 0xCB, 0x75, 0x46}, []byte{0x16, 0x4D, 0x5E, 0x40, 0x4F, 0x27, 0x52, 0x32}, []byte{0x5F, 0x99, 0xD0, 0x4F, 0x5B, 0x16, 0x39, 0x69}}, { []byte{0x1F, 0x08, 0x26, 0x0D, 0x1A, 0xC2, 0x46, 0x5E}, []byte{0x6B, 0x05, 0x6E, 0x18, 0x75, 0x9F, 0x5C, 0xCA}, []byte{0x4A, 0x05, 0x7A, 0x3B, 0x24, 0xD3, 0x97, 0x7B}}, { []byte{0x58, 0x40, 0x23, 0x64, 0x1A, 0xBA, 0x61, 0x76}, []byte{0x00, 0x4B, 0xD6, 0xEF, 0x09, 0x17, 0x60, 0x62}, []byte{0x45, 0x20, 0x31, 0xC1, 0xE4, 0xFA, 0xDA, 0x8E}}, { []byte{0x02, 0x58, 0x16, 0x16, 0x46, 0x29, 0xB0, 0x07}, []byte{0x48, 0x0D, 0x39, 0x00, 0x6E, 0xE7, 0x62, 0xF2}, []byte{0x75, 0x55, 0xAE, 0x39, 0xF5, 0x9B, 0x87, 0xBD}}, { []byte{0x49, 0x79, 0x3E, 0xBC, 0x79, 0xB3, 0x25, 0x8F}, []byte{0x43, 0x75, 0x40, 0xC8, 0x69, 0x8F, 0x3C, 0xFA}, []byte{0x53, 0xC5, 0x5F, 0x9C, 0xB4, 0x9F, 0xC0, 0x19}}, { []byte{0x4F, 0xB0, 0x5E, 0x15, 0x15, 0xAB, 0x73, 0xA7}, []byte{0x07, 0x2D, 0x43, 0xA0, 0x77, 0x07, 0x52, 0x92}, []byte{0x7A, 0x8E, 0x7B, 0xFA, 0x93, 0x7E, 0x89, 0xA3}}, { []byte{0x49, 0xE9, 0x5D, 0x6D, 0x4C, 0xA2, 0x29, 0xBF}, []byte{0x02, 0xFE, 0x55, 0x77, 0x81, 0x17, 0xF1, 0x2A}, []byte{0xCF, 0x9C, 0x5D, 0x7A, 0x49, 0x86, 0xAD, 0xB5}}, { []byte{0x01, 0x83, 0x10, 0xDC, 0x40, 0x9B, 0x26, 0xD6}, []byte{0x1D, 0x9D, 0x5C, 0x50, 0x18, 0xF7, 0x28, 0xC2}, []byte{0xD1, 0xAB, 0xB2, 0x90, 0x65, 0x8B, 0xC7, 0x78}}, { []byte{0x1C, 0x58, 0x7F, 0x1C, 0x13, 0x92, 0x4F, 0xEF}, []byte{0x30, 0x55, 0x32, 0x28, 0x6D, 0x6F, 0x29, 0x5A}, []byte{0x55, 0xCB, 0x37, 0x74, 0xD1, 0x3E, 0xF2, 0x01}}, { []byte{0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}, []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF}, []byte{0xFA, 0x34, 0xEC, 0x48, 0x47, 0xB2, 0x68, 0xB2}}, { []byte{0x1F, 0x1F, 0x1F, 0x1F, 0x0E, 0x0E, 0x0E, 0x0E}, []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF}, []byte{0xA7, 0x90, 0x79, 0x51, 0x08, 0xEA, 0x3C, 0xAE}}, { []byte{0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1, 0xFE}, []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF}, []byte{0xC3, 0x9E, 0x07, 0x2D, 0x9F, 0xAC, 0x63, 0x1D}}, { []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, []byte{0x01, 0x49, 0x33, 0xE0, 0xCD, 0xAF, 0xF6, 0xE4}}, { []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, []byte{0xF2, 0x1E, 0x9A, 0x77, 0xB7, 0x1C, 0x49, 0xBC}}, { []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF}, []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, []byte{0x24, 0x59, 0x46, 0x88, 0x57, 0x54, 0x36, 0x9A}}, { []byte{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}, []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, []byte{0x6B, 0x5C, 0x5A, 0x9C, 0x5D, 0x9E, 0x0A, 0x5A}}, } func TestCipherEncrypt(t *testing.T) { for i, tt := range encryptTests { c, err := NewCipher(tt.key) if err != nil { t.Errorf("NewCipher(%d bytes) = %s", len(tt.key), err) continue } ct := make([]byte, len(tt.out)) c.Encrypt(ct, tt.in) for j, v := range ct { if v != tt.out[j] { t.Errorf("Cipher.Encrypt, test vector #%d: cipher-text[%d] = %#x, expected %#x", i, j, v, tt.out[j]) break } } } } func TestCipherDecrypt(t *testing.T) { for i, tt := range encryptTests { c, err := NewCipher(tt.key) if err != nil { t.Errorf("NewCipher(%d bytes) = %s", len(tt.key), err) continue } pt := make([]byte, len(tt.in)) c.Decrypt(pt, tt.out) for j, v := range pt { if v != tt.in[j] { t.Errorf("Cipher.Decrypt, test vector #%d: plain-text[%d] = %#x, expected %#x", i, j, v, tt.in[j]) break } } } } func TestSaltedCipherKeyLength(t *testing.T) { if _, err := NewSaltedCipher(nil, []byte{'a'}); err != KeySizeError(0) { t.Errorf("NewSaltedCipher with short key, gave error %#v, expected %#v", err, KeySizeError(0)) } // A 57-byte key. One over the typical blowfish restriction. key := []byte("012345678901234567890123456789012345678901234567890123456") if _, err := NewSaltedCipher(key, []byte{'a'}); err != nil { t.Errorf("NewSaltedCipher with long key, gave error %#v", err) } } // Test vectors generated with Blowfish from OpenSSH. var saltedVectors = [][8]byte{ {0x0c, 0x82, 0x3b, 0x7b, 0x8d, 0x01, 0x4b, 0x7e}, {0xd1, 0xe1, 0x93, 0xf0, 0x70, 0xa6, 0xdb, 0x12}, {0xfc, 0x5e, 0xba, 0xde, 0xcb, 0xf8, 0x59, 0xad}, {0x8a, 0x0c, 0x76, 0xe7, 0xdd, 0x2c, 0xd3, 0xa8}, {0x2c, 0xcb, 0x7b, 0xee, 0xac, 0x7b, 0x7f, 0xf8}, {0xbb, 0xf6, 0x30, 0x6f, 0xe1, 0x5d, 0x62, 0xbf}, {0x97, 0x1e, 0xc1, 0x3d, 0x3d, 0xe0, 0x11, 0xe9}, {0x06, 0xd7, 0x4d, 0xb1, 0x80, 0xa3, 0xb1, 0x38}, {0x67, 0xa1, 0xa9, 0x75, 0x0e, 0x5b, 0xc6, 0xb4}, {0x51, 0x0f, 0x33, 0x0e, 0x4f, 0x67, 0xd2, 0x0c}, {0xf1, 0x73, 0x7e, 0xd8, 0x44, 0xea, 0xdb, 0xe5}, {0x14, 0x0e, 0x16, 0xce, 0x7f, 0x4a, 0x9c, 0x7b}, {0x4b, 0xfe, 0x43, 0xfd, 0xbf, 0x36, 0x04, 0x47}, {0xb1, 0xeb, 0x3e, 0x15, 0x36, 0xa7, 0xbb, 0xe2}, {0x6d, 0x0b, 0x41, 0xdd, 0x00, 0x98, 0x0b, 0x19}, {0xd3, 0xce, 0x45, 0xce, 0x1d, 0x56, 0xb7, 0xfc}, {0xd9, 0xf0, 0xfd, 0xda, 0xc0, 0x23, 0xb7, 0x93}, {0x4c, 0x6f, 0xa1, 0xe4, 0x0c, 0xa8, 0xca, 0x57}, {0xe6, 0x2f, 0x28, 0xa7, 0x0c, 0x94, 0x0d, 0x08}, {0x8f, 0xe3, 0xf0, 0xb6, 0x29, 0xe3, 0x44, 0x03}, {0xff, 0x98, 0xdd, 0x04, 0x45, 0xb4, 0x6d, 0x1f}, {0x9e, 0x45, 0x4d, 0x18, 0x40, 0x53, 0xdb, 0xef}, {0xb7, 0x3b, 0xef, 0x29, 0xbe, 0xa8, 0x13, 0x71}, {0x02, 0x54, 0x55, 0x41, 0x8e, 0x04, 0xfc, 0xad}, {0x6a, 0x0a, 0xee, 0x7c, 0x10, 0xd9, 0x19, 0xfe}, {0x0a, 0x22, 0xd9, 0x41, 0xcc, 0x23, 0x87, 0x13}, {0x6e, 0xff, 0x1f, 0xff, 0x36, 0x17, 0x9c, 0xbe}, {0x79, 0xad, 0xb7, 0x40, 0xf4, 0x9f, 0x51, 0xa6}, {0x97, 0x81, 0x99, 0xa4, 0xde, 0x9e, 0x9f, 0xb6}, {0x12, 0x19, 0x7a, 0x28, 0xd0, 0xdc, 0xcc, 0x92}, {0x81, 0xda, 0x60, 0x1e, 0x0e, 0xdd, 0x65, 0x56}, {0x7d, 0x76, 0x20, 0xb2, 0x73, 0xc9, 0x9e, 0xee}, } func TestSaltedCipher(t *testing.T) { var key, salt [32]byte for i := range key { key[i] = byte(i) salt[i] = byte(i + 32) } for i, v := range saltedVectors { c, err := NewSaltedCipher(key[:], salt[:i]) if err != nil { t.Fatal(err) } var buf [8]byte c.Encrypt(buf[:], buf[:]) if v != buf { t.Errorf("%d: expected %x, got %x", i, v, buf) } } } func BenchmarkExpandKeyWithSalt(b *testing.B) { key := make([]byte, 32) salt := make([]byte, 16) c, _ := NewCipher(key) for i := 0; i < b.N; i++ { expandKeyWithSalt(key, salt, c) } } func BenchmarkExpandKey(b *testing.B) { key := make([]byte, 32) c, _ := NewCipher(key) for i := 0; i < b.N; i++ { ExpandKey(key, c) } } lxd-2.0.0/dist/src/golang.org/x/crypto/blowfish/const.go0000644061062106075000000003151312702772344025571 0ustar00stgraberdomain admins00000000000000// Copyright 2010 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // The startup permutation array and substitution boxes. // They are the hexadecimal digits of PI; see: // http://www.schneier.com/code/constants.txt. package blowfish var s0 = [256]uint32{ 0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, 0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99, 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16, 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e, 0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee, 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013, 0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, 0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e, 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60, 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440, 0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce, 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a, 0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, 0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677, 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193, 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032, 0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88, 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239, 0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, 0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0, 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3, 0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98, 0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88, 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe, 0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, 0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d, 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b, 0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7, 0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba, 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463, 0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, 0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09, 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3, 0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb, 0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279, 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8, 0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, 0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82, 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db, 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573, 0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0, 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b, 0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, 0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8, 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4, 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0, 0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7, 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c, 0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, 0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1, 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299, 0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, 0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477, 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf, 0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, 0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af, 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa, 0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5, 0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41, 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915, 0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, 0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915, 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664, 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a, } var s1 = [256]uint32{ 0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, 0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266, 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1, 0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e, 0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6, 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1, 0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, 0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1, 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737, 0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8, 0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff, 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd, 0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, 0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7, 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41, 0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331, 0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf, 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af, 0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, 0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87, 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c, 0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2, 0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16, 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd, 0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, 0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509, 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e, 0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3, 0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f, 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a, 0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, 0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960, 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66, 0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28, 0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802, 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84, 0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, 0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf, 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14, 0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e, 0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50, 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7, 0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, 0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281, 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99, 0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696, 0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128, 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73, 0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, 0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0, 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105, 0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250, 0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3, 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285, 0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00, 0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061, 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb, 0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e, 0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735, 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc, 0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, 0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340, 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20, 0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7, } var s2 = [256]uint32{ 0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, 0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068, 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af, 0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840, 0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45, 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504, 0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a, 0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb, 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee, 0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6, 0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42, 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b, 0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, 0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb, 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527, 0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b, 0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33, 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c, 0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3, 0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc, 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17, 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564, 0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b, 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115, 0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922, 0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728, 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0, 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e, 0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37, 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d, 0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804, 0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b, 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3, 0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb, 0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d, 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c, 0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350, 0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9, 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a, 0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe, 0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d, 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc, 0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, 0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61, 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2, 0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9, 0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2, 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c, 0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e, 0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633, 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10, 0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169, 0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52, 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027, 0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5, 0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62, 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634, 0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76, 0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24, 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc, 0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4, 0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c, 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837, 0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0, } var s3 = [256]uint32{ 0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, 0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe, 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b, 0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4, 0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8, 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6, 0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, 0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22, 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4, 0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6, 0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9, 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59, 0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, 0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51, 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28, 0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c, 0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b, 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28, 0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, 0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd, 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a, 0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319, 0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb, 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f, 0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, 0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32, 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680, 0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166, 0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae, 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb, 0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, 0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47, 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370, 0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d, 0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84, 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048, 0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8, 0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd, 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9, 0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7, 0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38, 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f, 0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, 0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525, 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1, 0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442, 0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964, 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e, 0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, 0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d, 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f, 0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299, 0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02, 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc, 0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, 0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a, 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6, 0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b, 0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0, 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060, 0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, 0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9, 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f, 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6, } var p = [18]uint32{ 0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, 0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89, 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c, 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, 0x9216d5d9, 0x8979fb1b, } lxd-2.0.0/dist/src/golang.org/x/crypto/xts/0000755061062106075000000000000012702772344023112 5ustar00stgraberdomain admins00000000000000lxd-2.0.0/dist/src/golang.org/x/crypto/xts/xts.go0000644061062106075000000001062412702772344024262 0ustar00stgraberdomain admins00000000000000// Copyright 2012 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 xts implements the XTS cipher mode as specified in IEEE P1619/D16. // // XTS mode is typically used for disk encryption, which presents a number of // novel problems that make more common modes inapplicable. The disk is // conceptually an array of sectors and we must be able to encrypt and decrypt // a sector in isolation. However, an attacker must not be able to transpose // two sectors of plaintext by transposing their ciphertext. // // XTS wraps a block cipher with Rogaway's XEX mode in order to build a // tweakable block cipher. This allows each sector to have a unique tweak and // effectively create a unique key for each sector. // // XTS does not provide any authentication. An attacker can manipulate the // ciphertext and randomise a block (16 bytes) of the plaintext. // // (Note: this package does not implement ciphertext-stealing so sectors must // be a multiple of 16 bytes.) package xts // import "golang.org/x/crypto/xts" import ( "crypto/cipher" "errors" ) // Cipher contains an expanded key structure. It doesn't contain mutable state // and therefore can be used concurrently. type Cipher struct { k1, k2 cipher.Block } // blockSize is the block size that the underlying cipher must have. XTS is // only defined for 16-byte ciphers. const blockSize = 16 // NewCipher creates a Cipher given a function for creating the underlying // block cipher (which must have a block size of 16 bytes). The key must be // twice the length of the underlying cipher's key. func NewCipher(cipherFunc func([]byte) (cipher.Block, error), key []byte) (c *Cipher, err error) { c = new(Cipher) if c.k1, err = cipherFunc(key[:len(key)/2]); err != nil { return } c.k2, err = cipherFunc(key[len(key)/2:]) if c.k1.BlockSize() != blockSize { err = errors.New("xts: cipher does not have a block size of 16") } return } // Encrypt encrypts a sector of plaintext and puts the result into ciphertext. // Plaintext and ciphertext may be the same slice but should not overlap. // Sectors must be a multiple of 16 bytes and less than 2²ⴠbytes. func (c *Cipher) Encrypt(ciphertext, plaintext []byte, sectorNum uint64) { if len(ciphertext) < len(plaintext) { panic("xts: ciphertext is smaller than plaintext") } if len(plaintext)%blockSize != 0 { panic("xts: plaintext is not a multiple of the block size") } var tweak [blockSize]byte for i := 0; i < 8; i++ { tweak[i] = byte(sectorNum) sectorNum >>= 8 } c.k2.Encrypt(tweak[:], tweak[:]) for i := 0; i < len(plaintext); i += blockSize { for j := 0; j < blockSize; j++ { ciphertext[i+j] = plaintext[i+j] ^ tweak[j] } c.k1.Encrypt(ciphertext[i:], ciphertext[i:]) for j := 0; j < blockSize; j++ { ciphertext[i+j] ^= tweak[j] } mul2(&tweak) } } // Decrypt decrypts a sector of ciphertext and puts the result into plaintext. // Plaintext and ciphertext may be the same slice but should not overlap. // Sectors must be a multiple of 16 bytes and less than 2²ⴠbytes. func (c *Cipher) Decrypt(plaintext, ciphertext []byte, sectorNum uint64) { if len(plaintext) < len(ciphertext) { panic("xts: plaintext is smaller than ciphertext") } if len(ciphertext)%blockSize != 0 { panic("xts: ciphertext is not a multiple of the block size") } var tweak [blockSize]byte for i := 0; i < 8; i++ { tweak[i] = byte(sectorNum) sectorNum >>= 8 } c.k2.Encrypt(tweak[:], tweak[:]) for i := 0; i < len(plaintext); i += blockSize { for j := 0; j < blockSize; j++ { plaintext[i+j] = ciphertext[i+j] ^ tweak[j] } c.k1.Decrypt(plaintext[i:], plaintext[i:]) for j := 0; j < blockSize; j++ { plaintext[i+j] ^= tweak[j] } mul2(&tweak) } } // mul2 multiplies tweak by 2 in GF(2¹²â¸) with an irreducible polynomial of // x¹²⸠+ xâ· + x² + x + 1. func mul2(tweak *[blockSize]byte) { var carryIn byte for j := range tweak { carryOut := tweak[j] >> 7 tweak[j] = (tweak[j] << 1) + carryIn carryIn = carryOut } if carryIn != 0 { // If we have a carry bit then we need to subtract a multiple // of the irreducible polynomial (x¹²⸠+ xâ· + x² + x + 1). // By dropping the carry bit, we're subtracting the x^128 term // so all that remains is to subtract xâ· + x² + x + 1. // Subtraction (and addition) in this representation is just // XOR. tweak[0] ^= 1<<7 | 1<<2 | 1<<1 | 1 } } lxd-2.0.0/dist/src/golang.org/x/crypto/xts/xts_test.go0000644061062106075000000002047712702772344025330 0ustar00stgraberdomain admins00000000000000// Copyright 2012 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 xts import ( "bytes" "crypto/aes" "encoding/hex" "testing" ) // These test vectors have been taken from IEEE P1619/D16, Annex B. var xtsTestVectors = []struct { key string sector uint64 plaintext string ciphertext string }{ { "0000000000000000000000000000000000000000000000000000000000000000", 0, "0000000000000000000000000000000000000000000000000000000000000000", "917cf69ebd68b2ec9b9fe9a3eadda692cd43d2f59598ed858c02c2652fbf922e", }, { "1111111111111111111111111111111122222222222222222222222222222222", 0x3333333333, "4444444444444444444444444444444444444444444444444444444444444444", "c454185e6a16936e39334038acef838bfb186fff7480adc4289382ecd6d394f0", }, { "fffefdfcfbfaf9f8f7f6f5f4f3f2f1f022222222222222222222222222222222", 0x3333333333, "4444444444444444444444444444444444444444444444444444444444444444", "af85336b597afc1a900b2eb21ec949d292df4c047e0b21532186a5971a227a89", }, { "2718281828459045235360287471352631415926535897932384626433832795", 0, "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff", "27a7479befa1d476489f308cd4cfa6e2a96e4bbe3208ff25287dd3819616e89cc78cf7f5e543445f8333d8fa7f56000005279fa5d8b5e4ad40e736ddb4d35412328063fd2aab53e5ea1e0a9f332500a5df9487d07a5c92cc512c8866c7e860ce93fdf166a24912b422976146ae20ce846bb7dc9ba94a767aaef20c0d61ad02655ea92dc4c4e41a8952c651d33174be51a10c421110e6d81588ede82103a252d8a750e8768defffed9122810aaeb99f9172af82b604dc4b8e51bcb08235a6f4341332e4ca60482a4ba1a03b3e65008fc5da76b70bf1690db4eae29c5f1badd03c5ccf2a55d705ddcd86d449511ceb7ec30bf12b1fa35b913f9f747a8afd1b130e94bff94effd01a91735ca1726acd0b197c4e5b03393697e126826fb6bbde8ecc1e08298516e2c9ed03ff3c1b7860f6de76d4cecd94c8119855ef5297ca67e9f3e7ff72b1e99785ca0a7e7720c5b36dc6d72cac9574c8cbbc2f801e23e56fd344b07f22154beba0f08ce8891e643ed995c94d9a69c9f1b5f499027a78572aeebd74d20cc39881c213ee770b1010e4bea718846977ae119f7a023ab58cca0ad752afe656bb3c17256a9f6e9bf19fdd5a38fc82bbe872c5539edb609ef4f79c203ebb140f2e583cb2ad15b4aa5b655016a8449277dbd477ef2c8d6c017db738b18deb4a427d1923ce3ff262735779a418f20a282df920147beabe421ee5319d0568", }, { "2718281828459045235360287471352631415926535897932384626433832795", 1, "27a7479befa1d476489f308cd4cfa6e2a96e4bbe3208ff25287dd3819616e89cc78cf7f5e543445f8333d8fa7f56000005279fa5d8b5e4ad40e736ddb4d35412328063fd2aab53e5ea1e0a9f332500a5df9487d07a5c92cc512c8866c7e860ce93fdf166a24912b422976146ae20ce846bb7dc9ba94a767aaef20c0d61ad02655ea92dc4c4e41a8952c651d33174be51a10c421110e6d81588ede82103a252d8a750e8768defffed9122810aaeb99f9172af82b604dc4b8e51bcb08235a6f4341332e4ca60482a4ba1a03b3e65008fc5da76b70bf1690db4eae29c5f1badd03c5ccf2a55d705ddcd86d449511ceb7ec30bf12b1fa35b913f9f747a8afd1b130e94bff94effd01a91735ca1726acd0b197c4e5b03393697e126826fb6bbde8ecc1e08298516e2c9ed03ff3c1b7860f6de76d4cecd94c8119855ef5297ca67e9f3e7ff72b1e99785ca0a7e7720c5b36dc6d72cac9574c8cbbc2f801e23e56fd344b07f22154beba0f08ce8891e643ed995c94d9a69c9f1b5f499027a78572aeebd74d20cc39881c213ee770b1010e4bea718846977ae119f7a023ab58cca0ad752afe656bb3c17256a9f6e9bf19fdd5a38fc82bbe872c5539edb609ef4f79c203ebb140f2e583cb2ad15b4aa5b655016a8449277dbd477ef2c8d6c017db738b18deb4a427d1923ce3ff262735779a418f20a282df920147beabe421ee5319d0568", "264d3ca8512194fec312c8c9891f279fefdd608d0c027b60483a3fa811d65ee59d52d9e40ec5672d81532b38b6b089ce951f0f9c35590b8b978d175213f329bb1c2fd30f2f7f30492a61a532a79f51d36f5e31a7c9a12c286082ff7d2394d18f783e1a8e72c722caaaa52d8f065657d2631fd25bfd8e5baad6e527d763517501c68c5edc3cdd55435c532d7125c8614deed9adaa3acade5888b87bef641c4c994c8091b5bcd387f3963fb5bc37aa922fbfe3df4e5b915e6eb514717bdd2a74079a5073f5c4bfd46adf7d282e7a393a52579d11a028da4d9cd9c77124f9648ee383b1ac763930e7162a8d37f350b2f74b8472cf09902063c6b32e8c2d9290cefbd7346d1c779a0df50edcde4531da07b099c638e83a755944df2aef1aa31752fd323dcb710fb4bfbb9d22b925bc3577e1b8949e729a90bbafeacf7f7879e7b1147e28ba0bae940db795a61b15ecf4df8db07b824bb062802cc98a9545bb2aaeed77cb3fc6db15dcd7d80d7d5bc406c4970a3478ada8899b329198eb61c193fb6275aa8ca340344a75a862aebe92eee1ce032fd950b47d7704a3876923b4ad62844bf4a09c4dbe8b4397184b7471360c9564880aedddb9baa4af2e75394b08cd32ff479c57a07d3eab5d54de5f9738b8d27f27a9f0ab11799d7b7ffefb2704c95c6ad12c39f1e867a4b7b1d7818a4b753dfd2a89ccb45e001a03a867b187f225dd", }, { "27182818284590452353602874713526624977572470936999595749669676273141592653589793238462643383279502884197169399375105820974944592", 0xff, "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff", "1c3b3a102f770386e4836c99e370cf9bea00803f5e482357a4ae12d414a3e63b5d31e276f8fe4a8d66b317f9ac683f44680a86ac35adfc3345befecb4bb188fd5776926c49a3095eb108fd1098baec70aaa66999a72a82f27d848b21d4a741b0c5cd4d5fff9dac89aeba122961d03a757123e9870f8acf1000020887891429ca2a3e7a7d7df7b10355165c8b9a6d0a7de8b062c4500dc4cd120c0f7418dae3d0b5781c34803fa75421c790dfe1de1834f280d7667b327f6c8cd7557e12ac3a0f93ec05c52e0493ef31a12d3d9260f79a289d6a379bc70c50841473d1a8cc81ec583e9645e07b8d9670655ba5bbcfecc6dc3966380ad8fecb17b6ba02469a020a84e18e8f84252070c13e9f1f289be54fbc481457778f616015e1327a02b140f1505eb309326d68378f8374595c849d84f4c333ec4423885143cb47bd71c5edae9be69a2ffeceb1bec9de244fbe15992b11b77c040f12bd8f6a975a44a0f90c29a9abc3d4d893927284c58754cce294529f8614dcd2aba991925fedc4ae74ffac6e333b93eb4aff0479da9a410e4450e0dd7ae4c6e2910900575da401fc07059f645e8b7e9bfdef33943054ff84011493c27b3429eaedb4ed5376441a77ed43851ad77f16f541dfd269d50d6a5f14fb0aab1cbb4c1550be97f7ab4066193c4caa773dad38014bd2092fa755c824bb5e54c4f36ffda9fcea70b9c6e693e148c151", }, } func fromHex(s string) []byte { ret, err := hex.DecodeString(s) if err != nil { panic("xts: invalid hex in test") } return ret } func TestXTS(t *testing.T) { for i, test := range xtsTestVectors { c, err := NewCipher(aes.NewCipher, fromHex(test.key)) if err != nil { t.Errorf("#%d: failed to create cipher: %s", i, err) continue } plaintext := fromHex(test.plaintext) ciphertext := make([]byte, len(plaintext)) c.Encrypt(ciphertext, plaintext, test.sector) expectedCiphertext := fromHex(test.ciphertext) if !bytes.Equal(ciphertext, expectedCiphertext) { t.Errorf("#%d: encrypted failed, got: %x, want: %x", i, ciphertext, expectedCiphertext) continue } decrypted := make([]byte, len(ciphertext)) c.Decrypt(decrypted, ciphertext, test.sector) if !bytes.Equal(decrypted, plaintext) { t.Errorf("#%d: decryption failed, got: %x, want: %x", i, decrypted, plaintext) } } } lxd-2.0.0/dist/src/golang.org/x/crypto/pbkdf2/0000755061062106075000000000000012702772344023444 5ustar00stgraberdomain admins00000000000000lxd-2.0.0/dist/src/golang.org/x/crypto/pbkdf2/pbkdf2.go0000644061062106075000000000466412702772344025155 0ustar00stgraberdomain admins00000000000000// Copyright 2012 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 pbkdf2 implements the key derivation function PBKDF2 as defined in RFC 2898 / PKCS #5 v2.0. A key derivation function is useful when encrypting data based on a password or any other not-fully-random data. It uses a pseudorandom function to derive a secure encryption key based on the password. While v2.0 of the standard defines only one pseudorandom function to use, HMAC-SHA1, the drafted v2.1 specification allows use of all five FIPS Approved Hash Functions SHA-1, SHA-224, SHA-256, SHA-384 and SHA-512 for HMAC. To choose, you can pass the `New` functions from the different SHA packages to pbkdf2.Key. */ package pbkdf2 // import "golang.org/x/crypto/pbkdf2" import ( "crypto/hmac" "hash" ) // Key derives a key from the password, salt and iteration count, returning a // []byte of length keylen that can be used as cryptographic key. The key is // derived based on the method described as PBKDF2 with the HMAC variant using // the supplied hash function. // // For example, to use a HMAC-SHA-1 based PBKDF2 key derivation function, you // can get a derived key for e.g. AES-256 (which needs a 32-byte key) by // doing: // // dk := pbkdf2.Key([]byte("some password"), salt, 4096, 32, sha1.New) // // Remember to get a good random salt. At least 8 bytes is recommended by the // RFC. // // Using a higher iteration count will increase the cost of an exhaustive // search but will also make derivation proportionally slower. func Key(password, salt []byte, iter, keyLen int, h func() hash.Hash) []byte { prf := hmac.New(h, password) hashLen := prf.Size() numBlocks := (keyLen + hashLen - 1) / hashLen var buf [4]byte dk := make([]byte, 0, numBlocks*hashLen) U := make([]byte, hashLen) for block := 1; block <= numBlocks; block++ { // N.B.: || means concatenation, ^ means XOR // for each block T_i = U_1 ^ U_2 ^ ... ^ U_iter // U_1 = PRF(password, salt || uint(i)) prf.Reset() prf.Write(salt) buf[0] = byte(block >> 24) buf[1] = byte(block >> 16) buf[2] = byte(block >> 8) buf[3] = byte(block) prf.Write(buf[:4]) dk = prf.Sum(dk) T := dk[len(dk)-hashLen:] copy(U, T) // U_n = PRF(password, U_(n-1)) for n := 2; n <= iter; n++ { prf.Reset() prf.Write(U) U = U[:0] U = prf.Sum(U) for x := range U { T[x] ^= U[x] } } } return dk[:keyLen] } lxd-2.0.0/dist/src/golang.org/x/crypto/pbkdf2/pbkdf2_test.go0000644061062106075000000000627512702772344026214 0ustar00stgraberdomain admins00000000000000// Copyright 2012 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 pbkdf2 import ( "bytes" "crypto/sha1" "crypto/sha256" "hash" "testing" ) type testVector struct { password string salt string iter int output []byte } // Test vectors from RFC 6070, http://tools.ietf.org/html/rfc6070 var sha1TestVectors = []testVector{ { "password", "salt", 1, []byte{ 0x0c, 0x60, 0xc8, 0x0f, 0x96, 0x1f, 0x0e, 0x71, 0xf3, 0xa9, 0xb5, 0x24, 0xaf, 0x60, 0x12, 0x06, 0x2f, 0xe0, 0x37, 0xa6, }, }, { "password", "salt", 2, []byte{ 0xea, 0x6c, 0x01, 0x4d, 0xc7, 0x2d, 0x6f, 0x8c, 0xcd, 0x1e, 0xd9, 0x2a, 0xce, 0x1d, 0x41, 0xf0, 0xd8, 0xde, 0x89, 0x57, }, }, { "password", "salt", 4096, []byte{ 0x4b, 0x00, 0x79, 0x01, 0xb7, 0x65, 0x48, 0x9a, 0xbe, 0xad, 0x49, 0xd9, 0x26, 0xf7, 0x21, 0xd0, 0x65, 0xa4, 0x29, 0xc1, }, }, // // This one takes too long // { // "password", // "salt", // 16777216, // []byte{ // 0xee, 0xfe, 0x3d, 0x61, 0xcd, 0x4d, 0xa4, 0xe4, // 0xe9, 0x94, 0x5b, 0x3d, 0x6b, 0xa2, 0x15, 0x8c, // 0x26, 0x34, 0xe9, 0x84, // }, // }, { "passwordPASSWORDpassword", "saltSALTsaltSALTsaltSALTsaltSALTsalt", 4096, []byte{ 0x3d, 0x2e, 0xec, 0x4f, 0xe4, 0x1c, 0x84, 0x9b, 0x80, 0xc8, 0xd8, 0x36, 0x62, 0xc0, 0xe4, 0x4a, 0x8b, 0x29, 0x1a, 0x96, 0x4c, 0xf2, 0xf0, 0x70, 0x38, }, }, { "pass\000word", "sa\000lt", 4096, []byte{ 0x56, 0xfa, 0x6a, 0xa7, 0x55, 0x48, 0x09, 0x9d, 0xcc, 0x37, 0xd7, 0xf0, 0x34, 0x25, 0xe0, 0xc3, }, }, } // Test vectors from // http://stackoverflow.com/questions/5130513/pbkdf2-hmac-sha2-test-vectors var sha256TestVectors = []testVector{ { "password", "salt", 1, []byte{ 0x12, 0x0f, 0xb6, 0xcf, 0xfc, 0xf8, 0xb3, 0x2c, 0x43, 0xe7, 0x22, 0x52, 0x56, 0xc4, 0xf8, 0x37, 0xa8, 0x65, 0x48, 0xc9, }, }, { "password", "salt", 2, []byte{ 0xae, 0x4d, 0x0c, 0x95, 0xaf, 0x6b, 0x46, 0xd3, 0x2d, 0x0a, 0xdf, 0xf9, 0x28, 0xf0, 0x6d, 0xd0, 0x2a, 0x30, 0x3f, 0x8e, }, }, { "password", "salt", 4096, []byte{ 0xc5, 0xe4, 0x78, 0xd5, 0x92, 0x88, 0xc8, 0x41, 0xaa, 0x53, 0x0d, 0xb6, 0x84, 0x5c, 0x4c, 0x8d, 0x96, 0x28, 0x93, 0xa0, }, }, { "passwordPASSWORDpassword", "saltSALTsaltSALTsaltSALTsaltSALTsalt", 4096, []byte{ 0x34, 0x8c, 0x89, 0xdb, 0xcb, 0xd3, 0x2b, 0x2f, 0x32, 0xd8, 0x14, 0xb8, 0x11, 0x6e, 0x84, 0xcf, 0x2b, 0x17, 0x34, 0x7e, 0xbc, 0x18, 0x00, 0x18, 0x1c, }, }, { "pass\000word", "sa\000lt", 4096, []byte{ 0x89, 0xb6, 0x9d, 0x05, 0x16, 0xf8, 0x29, 0x89, 0x3c, 0x69, 0x62, 0x26, 0x65, 0x0a, 0x86, 0x87, }, }, } func testHash(t *testing.T, h func() hash.Hash, hashName string, vectors []testVector) { for i, v := range vectors { o := Key([]byte(v.password), []byte(v.salt), v.iter, len(v.output), h) if !bytes.Equal(o, v.output) { t.Errorf("%s %d: expected %x, got %x", hashName, i, v.output, o) } } } func TestWithHMACSHA1(t *testing.T) { testHash(t, sha1.New, "SHA1", sha1TestVectors) } func TestWithHMACSHA256(t *testing.T) { testHash(t, sha256.New, "SHA256", sha256TestVectors) } lxd-2.0.0/dist/src/golang.org/x/crypto/poly1305/0000755061062106075000000000000012702772344023570 5ustar00stgraberdomain admins00000000000000lxd-2.0.0/dist/src/golang.org/x/crypto/poly1305/poly1305_test.go0000644061062106075000000000405112702772344026452 0ustar00stgraberdomain admins00000000000000// Copyright 2012 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 poly1305 import ( "bytes" "testing" "unsafe" ) var testData = []struct { in, k, correct []byte }{ { []byte("Hello world!"), []byte("this is 32-byte key for Poly1305"), []byte{0xa6, 0xf7, 0x45, 0x00, 0x8f, 0x81, 0xc9, 0x16, 0xa2, 0x0d, 0xcc, 0x74, 0xee, 0xf2, 0xb2, 0xf0}, }, { make([]byte, 32), []byte("this is 32-byte key for Poly1305"), []byte{0x49, 0xec, 0x78, 0x09, 0x0e, 0x48, 0x1e, 0xc6, 0xc2, 0x6b, 0x33, 0xb9, 0x1c, 0xcc, 0x03, 0x07}, }, { make([]byte, 2007), []byte("this is 32-byte key for Poly1305"), []byte{0xda, 0x84, 0xbc, 0xab, 0x02, 0x67, 0x6c, 0x38, 0xcd, 0xb0, 0x15, 0x60, 0x42, 0x74, 0xc2, 0xaa}, }, { make([]byte, 2007), make([]byte, 32), make([]byte, 16), }, } func testSum(t *testing.T, unaligned bool) { var out [16]byte var key [32]byte for i, v := range testData { in := v.in if unaligned { in = unalignBytes(in) } copy(key[:], v.k) Sum(&out, in, &key) if !bytes.Equal(out[:], v.correct) { t.Errorf("%d: expected %x, got %x", i, v.correct, out[:]) } } } func TestSum(t *testing.T) { testSum(t, false) } func TestSumUnaligned(t *testing.T) { testSum(t, true) } func benchmark(b *testing.B, size int, unaligned bool) { var out [16]byte var key [32]byte in := make([]byte, size) if unaligned { in = unalignBytes(in) } b.SetBytes(int64(len(in))) b.ResetTimer() for i := 0; i < b.N; i++ { Sum(&out, in, &key) } } func Benchmark64(b *testing.B) { benchmark(b, 64, false) } func Benchmark1K(b *testing.B) { benchmark(b, 1024, false) } func Benchmark64Unaligned(b *testing.B) { benchmark(b, 64, true) } func Benchmark1KUnaligned(b *testing.B) { benchmark(b, 1024, true) } func unalignBytes(in []byte) []byte { out := make([]byte, len(in)+1) if uintptr(unsafe.Pointer(&out[0]))&(unsafe.Alignof(uint32(0))-1) == 0 { out = out[1:] } else { out = out[:len(in)] } copy(out, in) return out } lxd-2.0.0/dist/src/golang.org/x/crypto/poly1305/sum_arm.go0000644061062106075000000000131712702772344025564 0ustar00stgraberdomain admins00000000000000// Copyright 2015 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. // +build arm,!gccgo,!appengine package poly1305 // This function is implemented in poly1305_arm.s //go:noescape func poly1305_auth_armv6(out *[16]byte, m *byte, mlen uint32, key *[32]byte) // Sum generates an authenticator for m using a one-time key and puts the // 16-byte result into out. Authenticating two different messages with the same // key allows an attacker to forge messages at will. func Sum(out *[16]byte, m []byte, key *[32]byte) { var mPtr *byte if len(m) > 0 { mPtr = &m[0] } poly1305_auth_armv6(out, mPtr, uint32(len(m)), key) } lxd-2.0.0/dist/src/golang.org/x/crypto/poly1305/const_amd64.s0000644061062106075000000000307412702772344026101 0ustar00stgraberdomain admins00000000000000// Copyright 2012 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 code was translated into a form compatible with 6a from the public // domain sources in SUPERCOP: http://bench.cr.yp.to/supercop.html // +build amd64,!gccgo,!appengine DATA ·SCALE(SB)/8, $0x37F4000000000000 GLOBL ·SCALE(SB), 8, $8 DATA ·TWO32(SB)/8, $0x41F0000000000000 GLOBL ·TWO32(SB), 8, $8 DATA ·TWO64(SB)/8, $0x43F0000000000000 GLOBL ·TWO64(SB), 8, $8 DATA ·TWO96(SB)/8, $0x45F0000000000000 GLOBL ·TWO96(SB), 8, $8 DATA ·ALPHA32(SB)/8, $0x45E8000000000000 GLOBL ·ALPHA32(SB), 8, $8 DATA ·ALPHA64(SB)/8, $0x47E8000000000000 GLOBL ·ALPHA64(SB), 8, $8 DATA ·ALPHA96(SB)/8, $0x49E8000000000000 GLOBL ·ALPHA96(SB), 8, $8 DATA ·ALPHA130(SB)/8, $0x4C08000000000000 GLOBL ·ALPHA130(SB), 8, $8 DATA ·DOFFSET0(SB)/8, $0x4330000000000000 GLOBL ·DOFFSET0(SB), 8, $8 DATA ·DOFFSET1(SB)/8, $0x4530000000000000 GLOBL ·DOFFSET1(SB), 8, $8 DATA ·DOFFSET2(SB)/8, $0x4730000000000000 GLOBL ·DOFFSET2(SB), 8, $8 DATA ·DOFFSET3(SB)/8, $0x4930000000000000 GLOBL ·DOFFSET3(SB), 8, $8 DATA ·DOFFSET3MINUSTWO128(SB)/8, $0x492FFFFE00000000 GLOBL ·DOFFSET3MINUSTWO128(SB), 8, $8 DATA ·HOFFSET0(SB)/8, $0x43300001FFFFFFFB GLOBL ·HOFFSET0(SB), 8, $8 DATA ·HOFFSET1(SB)/8, $0x45300001FFFFFFFE GLOBL ·HOFFSET1(SB), 8, $8 DATA ·HOFFSET2(SB)/8, $0x47300001FFFFFFFE GLOBL ·HOFFSET2(SB), 8, $8 DATA ·HOFFSET3(SB)/8, $0x49300003FFFFFFFE GLOBL ·HOFFSET3(SB), 8, $8 DATA ·ROUNDING(SB)/2, $0x137f GLOBL ·ROUNDING(SB), 8, $2 lxd-2.0.0/dist/src/golang.org/x/crypto/poly1305/sum_amd64.go0000644061062106075000000000127512702772344025723 0ustar00stgraberdomain admins00000000000000// Copyright 2012 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. // +build amd64,!gccgo,!appengine package poly1305 // This function is implemented in poly1305_amd64.s //go:noescape func poly1305(out *[16]byte, m *byte, mlen uint64, key *[32]byte) // Sum generates an authenticator for m using a one-time key and puts the // 16-byte result into out. Authenticating two different messages with the same // key allows an attacker to forge messages at will. func Sum(out *[16]byte, m []byte, key *[32]byte) { var mPtr *byte if len(m) > 0 { mPtr = &m[0] } poly1305(out, mPtr, uint64(len(m)), key) } lxd-2.0.0/dist/src/golang.org/x/crypto/poly1305/poly1305_arm.s0000644061062106075000000002242412702772344026113 0ustar00stgraberdomain admins00000000000000// Copyright 2015 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 code was translated into a form compatible with 5a from the public // domain source by Andrew Moon: github.com/floodyberry/poly1305-opt/blob/master/app/extensions/poly1305. // +build arm,!gccgo,!appengine DATA poly1305_init_constants_armv6<>+0x00(SB)/4, $0x3ffffff DATA poly1305_init_constants_armv6<>+0x04(SB)/4, $0x3ffff03 DATA poly1305_init_constants_armv6<>+0x08(SB)/4, $0x3ffc0ff DATA poly1305_init_constants_armv6<>+0x0c(SB)/4, $0x3f03fff DATA poly1305_init_constants_armv6<>+0x10(SB)/4, $0x00fffff GLOBL poly1305_init_constants_armv6<>(SB), 8, $20 // Warning: the linker may use R11 to synthesize certain instructions. Please // take care and verify that no synthetic instructions use it. TEXT poly1305_init_ext_armv6<>(SB),4,$-4 MOVM.DB.W [R4-R11], (R13) MOVM.IA.W (R1), [R2-R5] MOVW $poly1305_init_constants_armv6<>(SB), R7 MOVW R2, R8 MOVW R2>>26, R9 MOVW R3>>20, g MOVW R4>>14, R11 MOVW R5>>8, R12 ORR R3<<6, R9, R9 ORR R4<<12, g, g ORR R5<<18, R11, R11 MOVM.IA (R7), [R2-R6] AND R8, R2, R2 AND R9, R3, R3 AND g, R4, R4 AND R11, R5, R5 AND R12, R6, R6 MOVM.IA.W [R2-R6], (R0) EOR R2, R2, R2 EOR R3, R3, R3 EOR R4, R4, R4 EOR R5, R5, R5 EOR R6, R6, R6 MOVM.IA.W [R2-R6], (R0) MOVM.IA.W (R1), [R2-R5] MOVM.IA [R2-R6], (R0) MOVM.IA.W (R13), [R4-R11] RET #define MOVW_UNALIGNED(Rsrc, Rdst, Rtmp, offset) \ MOVBU (offset+0)(Rsrc), Rtmp; \ MOVBU Rtmp, (offset+0)(Rdst); \ MOVBU (offset+1)(Rsrc), Rtmp; \ MOVBU Rtmp, (offset+1)(Rdst); \ MOVBU (offset+2)(Rsrc), Rtmp; \ MOVBU Rtmp, (offset+2)(Rdst); \ MOVBU (offset+3)(Rsrc), Rtmp; \ MOVBU Rtmp, (offset+3)(Rdst) TEXT poly1305_blocks_armv6<>(SB),4,$-4 MOVM.DB.W [R4, R5, R6, R7, R8, R9, g, R11, R14], (R13) SUB $128, R13 MOVW R0, 36(R13) MOVW R1, 40(R13) MOVW R2, 44(R13) MOVW R1, R14 MOVW R2, R12 MOVW 56(R0), R8 WORD $0xe1180008 // TST R8, R8 not working see issue 5921 EOR R6, R6, R6 MOVW.EQ $(1<<24), R6 MOVW R6, 32(R13) ADD $64, R13, g MOVM.IA (R0), [R0-R9] MOVM.IA [R0-R4], (g) CMP $16, R12 BLO poly1305_blocks_armv6_done poly1305_blocks_armv6_mainloop: WORD $0xe31e0003 // TST R14, #3 not working see issue 5921 BEQ poly1305_blocks_armv6_mainloop_aligned ADD $48, R13, g MOVW_UNALIGNED(R14, g, R0, 0) MOVW_UNALIGNED(R14, g, R0, 4) MOVW_UNALIGNED(R14, g, R0, 8) MOVW_UNALIGNED(R14, g, R0, 12) MOVM.IA (g), [R0-R3] ADD $16, R14 B poly1305_blocks_armv6_mainloop_loaded poly1305_blocks_armv6_mainloop_aligned: MOVM.IA.W (R14), [R0-R3] poly1305_blocks_armv6_mainloop_loaded: MOVW R0>>26, g MOVW R1>>20, R11 MOVW R2>>14, R12 MOVW R14, 40(R13) MOVW R3>>8, R4 ORR R1<<6, g, g ORR R2<<12, R11, R11 ORR R3<<18, R12, R12 BIC $0xfc000000, R0, R0 BIC $0xfc000000, g, g MOVW 32(R13), R3 BIC $0xfc000000, R11, R11 BIC $0xfc000000, R12, R12 ADD R0, R5, R5 ADD g, R6, R6 ORR R3, R4, R4 ADD R11, R7, R7 ADD $64, R13, R14 ADD R12, R8, R8 ADD R4, R9, R9 MOVM.IA (R14), [R0-R4] MULLU R4, R5, (R11, g) MULLU R3, R5, (R14, R12) MULALU R3, R6, (R11, g) MULALU R2, R6, (R14, R12) MULALU R2, R7, (R11, g) MULALU R1, R7, (R14, R12) ADD R4<<2, R4, R4 ADD R3<<2, R3, R3 MULALU R1, R8, (R11, g) MULALU R0, R8, (R14, R12) MULALU R0, R9, (R11, g) MULALU R4, R9, (R14, R12) MOVW g, 24(R13) MOVW R11, 28(R13) MOVW R12, 16(R13) MOVW R14, 20(R13) MULLU R2, R5, (R11, g) MULLU R1, R5, (R14, R12) MULALU R1, R6, (R11, g) MULALU R0, R6, (R14, R12) MULALU R0, R7, (R11, g) MULALU R4, R7, (R14, R12) ADD R2<<2, R2, R2 ADD R1<<2, R1, R1 MULALU R4, R8, (R11, g) MULALU R3, R8, (R14, R12) MULALU R3, R9, (R11, g) MULALU R2, R9, (R14, R12) MOVW g, 8(R13) MOVW R11, 12(R13) MOVW R12, 0(R13) MOVW R14, w+4(SP) MULLU R0, R5, (R11, g) MULALU R4, R6, (R11, g) MULALU R3, R7, (R11, g) MULALU R2, R8, (R11, g) MULALU R1, R9, (R11, g) MOVM.IA (R13), [R0-R7] MOVW g>>26, R12 MOVW R4>>26, R14 ORR R11<<6, R12, R12 ORR R5<<6, R14, R14 BIC $0xfc000000, g, g BIC $0xfc000000, R4, R4 ADD.S R12, R0, R0 ADC $0, R1, R1 ADD.S R14, R6, R6 ADC $0, R7, R7 MOVW R0>>26, R12 MOVW R6>>26, R14 ORR R1<<6, R12, R12 ORR R7<<6, R14, R14 BIC $0xfc000000, R0, R0 BIC $0xfc000000, R6, R6 ADD R14<<2, R14, R14 ADD.S R12, R2, R2 ADC $0, R3, R3 ADD R14, g, g MOVW R2>>26, R12 MOVW g>>26, R14 ORR R3<<6, R12, R12 BIC $0xfc000000, g, R5 BIC $0xfc000000, R2, R7 ADD R12, R4, R4 ADD R14, R0, R0 MOVW R4>>26, R12 BIC $0xfc000000, R4, R8 ADD R12, R6, R9 MOVW w+44(SP), R12 MOVW w+40(SP), R14 MOVW R0, R6 CMP $32, R12 SUB $16, R12, R12 MOVW R12, 44(R13) BHS poly1305_blocks_armv6_mainloop poly1305_blocks_armv6_done: MOVW 36(R13), R12 MOVW R5, 20(R12) MOVW R6, 24(R12) MOVW R7, 28(R12) MOVW R8, 32(R12) MOVW R9, 36(R12) ADD $128, R13, R13 MOVM.IA.W (R13), [R4, R5, R6, R7, R8, R9, g, R11, R14] RET #define MOVHUP_UNALIGNED(Rsrc, Rdst, Rtmp) \ MOVBU.P 1(Rsrc), Rtmp; \ MOVBU.P Rtmp, 1(Rdst); \ MOVBU.P 1(Rsrc), Rtmp; \ MOVBU.P Rtmp, 1(Rdst) #define MOVWP_UNALIGNED(Rsrc, Rdst, Rtmp) \ MOVHUP_UNALIGNED(Rsrc, Rdst, Rtmp); \ MOVHUP_UNALIGNED(Rsrc, Rdst, Rtmp) TEXT poly1305_finish_ext_armv6<>(SB),4,$-4 MOVM.DB.W [R4, R5, R6, R7, R8, R9, g, R11, R14], (R13) SUB $16, R13, R13 MOVW R0, R5 MOVW R1, R6 MOVW R2, R7 MOVW R3, R8 AND.S R2, R2, R2 BEQ poly1305_finish_ext_armv6_noremaining EOR R0, R0 MOVW R13, R9 MOVW R0, 0(R13) MOVW R0, 4(R13) MOVW R0, 8(R13) MOVW R0, 12(R13) WORD $0xe3110003 // TST R1, #3 not working see issue 5921 BEQ poly1305_finish_ext_armv6_aligned WORD $0xe3120008 // TST R2, #8 not working see issue 5921 BEQ poly1305_finish_ext_armv6_skip8 MOVWP_UNALIGNED(R1, R9, g) MOVWP_UNALIGNED(R1, R9, g) poly1305_finish_ext_armv6_skip8: WORD $0xe3120004 // TST $4, R2 not working see issue 5921 BEQ poly1305_finish_ext_armv6_skip4 MOVWP_UNALIGNED(R1, R9, g) poly1305_finish_ext_armv6_skip4: WORD $0xe3120002 // TST $2, R2 not working see issue 5921 BEQ poly1305_finish_ext_armv6_skip2 MOVHUP_UNALIGNED(R1, R9, g) B poly1305_finish_ext_armv6_skip2 poly1305_finish_ext_armv6_aligned: WORD $0xe3120008 // TST R2, #8 not working see issue 5921 BEQ poly1305_finish_ext_armv6_skip8_aligned MOVM.IA.W (R1), [g-R11] MOVM.IA.W [g-R11], (R9) poly1305_finish_ext_armv6_skip8_aligned: WORD $0xe3120004 // TST $4, R2 not working see issue 5921 BEQ poly1305_finish_ext_armv6_skip4_aligned MOVW.P 4(R1), g MOVW.P g, 4(R9) poly1305_finish_ext_armv6_skip4_aligned: WORD $0xe3120002 // TST $2, R2 not working see issue 5921 BEQ poly1305_finish_ext_armv6_skip2 MOVHU.P 2(R1), g MOVH.P g, 2(R9) poly1305_finish_ext_armv6_skip2: WORD $0xe3120001 // TST $1, R2 not working see issue 5921 BEQ poly1305_finish_ext_armv6_skip1 MOVBU.P 1(R1), g MOVBU.P g, 1(R9) poly1305_finish_ext_armv6_skip1: MOVW $1, R11 MOVBU R11, 0(R9) MOVW R11, 56(R5) MOVW R5, R0 MOVW R13, R1 MOVW $16, R2 BL poly1305_blocks_armv6<>(SB) poly1305_finish_ext_armv6_noremaining: MOVW 20(R5), R0 MOVW 24(R5), R1 MOVW 28(R5), R2 MOVW 32(R5), R3 MOVW 36(R5), R4 MOVW R4>>26, R12 BIC $0xfc000000, R4, R4 ADD R12<<2, R12, R12 ADD R12, R0, R0 MOVW R0>>26, R12 BIC $0xfc000000, R0, R0 ADD R12, R1, R1 MOVW R1>>26, R12 BIC $0xfc000000, R1, R1 ADD R12, R2, R2 MOVW R2>>26, R12 BIC $0xfc000000, R2, R2 ADD R12, R3, R3 MOVW R3>>26, R12 BIC $0xfc000000, R3, R3 ADD R12, R4, R4 ADD $5, R0, R6 MOVW R6>>26, R12 BIC $0xfc000000, R6, R6 ADD R12, R1, R7 MOVW R7>>26, R12 BIC $0xfc000000, R7, R7 ADD R12, R2, g MOVW g>>26, R12 BIC $0xfc000000, g, g ADD R12, R3, R11 MOVW $-(1<<26), R12 ADD R11>>26, R12, R12 BIC $0xfc000000, R11, R11 ADD R12, R4, R14 MOVW R14>>31, R12 SUB $1, R12 AND R12, R6, R6 AND R12, R7, R7 AND R12, g, g AND R12, R11, R11 AND R12, R14, R14 MVN R12, R12 AND R12, R0, R0 AND R12, R1, R1 AND R12, R2, R2 AND R12, R3, R3 AND R12, R4, R4 ORR R6, R0, R0 ORR R7, R1, R1 ORR g, R2, R2 ORR R11, R3, R3 ORR R14, R4, R4 ORR R1<<26, R0, R0 MOVW R1>>6, R1 ORR R2<<20, R1, R1 MOVW R2>>12, R2 ORR R3<<14, R2, R2 MOVW R3>>18, R3 ORR R4<<8, R3, R3 MOVW 40(R5), R6 MOVW 44(R5), R7 MOVW 48(R5), g MOVW 52(R5), R11 ADD.S R6, R0, R0 ADC.S R7, R1, R1 ADC.S g, R2, R2 ADC.S R11, R3, R3 MOVM.IA [R0-R3], (R8) MOVW R5, R12 EOR R0, R0, R0 EOR R1, R1, R1 EOR R2, R2, R2 EOR R3, R3, R3 EOR R4, R4, R4 EOR R5, R5, R5 EOR R6, R6, R6 EOR R7, R7, R7 MOVM.IA.W [R0-R7], (R12) MOVM.IA [R0-R7], (R12) ADD $16, R13, R13 MOVM.IA.W (R13), [R4, R5, R6, R7, R8, R9, g, R11, R14] RET // func poly1305_auth_armv6(out *[16]byte, m *byte, mlen uint32, key *[32]key) TEXT ·poly1305_auth_armv6(SB),0,$280-16 MOVW out+0(FP), R4 MOVW m+4(FP), R5 MOVW mlen+8(FP), R6 MOVW key+12(FP), R7 MOVW R13, R8 BIC $63, R13 SUB $64, R13, R13 MOVW R13, R0 MOVW R7, R1 BL poly1305_init_ext_armv6<>(SB) BIC.S $15, R6, R2 BEQ poly1305_auth_armv6_noblocks MOVW R13, R0 MOVW R5, R1 ADD R2, R5, R5 SUB R2, R6, R6 BL poly1305_blocks_armv6<>(SB) poly1305_auth_armv6_noblocks: MOVW R13, R0 MOVW R5, R1 MOVW R6, R2 MOVW R4, R3 BL poly1305_finish_ext_armv6<>(SB) MOVW R8, R13 RET lxd-2.0.0/dist/src/golang.org/x/crypto/poly1305/sum_ref.go0000644061062106075000000005055512702772344025571 0ustar00stgraberdomain admins00000000000000// Copyright 2012 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. // +build !amd64,!arm gccgo appengine package poly1305 // Based on original, public domain implementation from NaCl by D. J. // Bernstein. import "math" const ( alpham80 = 0.00000000558793544769287109375 alpham48 = 24.0 alpham16 = 103079215104.0 alpha0 = 6755399441055744.0 alpha18 = 1770887431076116955136.0 alpha32 = 29014219670751100192948224.0 alpha50 = 7605903601369376408980219232256.0 alpha64 = 124615124604835863084731911901282304.0 alpha82 = 32667107224410092492483962313449748299776.0 alpha96 = 535217884764734955396857238543560676143529984.0 alpha112 = 35076039295941670036888435985190792471742381031424.0 alpha130 = 9194973245195333150150082162901855101712434733101613056.0 scale = 0.0000000000000000000000000000000000000036734198463196484624023016788195177431833298649127735047148490821200539357960224151611328125 offset0 = 6755408030990331.0 offset1 = 29014256564239239022116864.0 offset2 = 124615283061160854719918951570079744.0 offset3 = 535219245894202480694386063513315216128475136.0 ) // Sum generates an authenticator for m using a one-time key and puts the // 16-byte result into out. Authenticating two different messages with the same // key allows an attacker to forge messages at will. func Sum(out *[16]byte, m []byte, key *[32]byte) { r := key s := key[16:] var ( y7 float64 y6 float64 y1 float64 y0 float64 y5 float64 y4 float64 x7 float64 x6 float64 x1 float64 x0 float64 y3 float64 y2 float64 x5 float64 r3lowx0 float64 x4 float64 r0lowx6 float64 x3 float64 r3highx0 float64 x2 float64 r0highx6 float64 r0lowx0 float64 sr1lowx6 float64 r0highx0 float64 sr1highx6 float64 sr3low float64 r1lowx0 float64 sr2lowx6 float64 r1highx0 float64 sr2highx6 float64 r2lowx0 float64 sr3lowx6 float64 r2highx0 float64 sr3highx6 float64 r1highx4 float64 r1lowx4 float64 r0highx4 float64 r0lowx4 float64 sr3highx4 float64 sr3lowx4 float64 sr2highx4 float64 sr2lowx4 float64 r0lowx2 float64 r0highx2 float64 r1lowx2 float64 r1highx2 float64 r2lowx2 float64 r2highx2 float64 sr3lowx2 float64 sr3highx2 float64 z0 float64 z1 float64 z2 float64 z3 float64 m0 int64 m1 int64 m2 int64 m3 int64 m00 uint32 m01 uint32 m02 uint32 m03 uint32 m10 uint32 m11 uint32 m12 uint32 m13 uint32 m20 uint32 m21 uint32 m22 uint32 m23 uint32 m30 uint32 m31 uint32 m32 uint32 m33 uint64 lbelow2 int32 lbelow3 int32 lbelow4 int32 lbelow5 int32 lbelow6 int32 lbelow7 int32 lbelow8 int32 lbelow9 int32 lbelow10 int32 lbelow11 int32 lbelow12 int32 lbelow13 int32 lbelow14 int32 lbelow15 int32 s00 uint32 s01 uint32 s02 uint32 s03 uint32 s10 uint32 s11 uint32 s12 uint32 s13 uint32 s20 uint32 s21 uint32 s22 uint32 s23 uint32 s30 uint32 s31 uint32 s32 uint32 s33 uint32 bits32 uint64 f uint64 f0 uint64 f1 uint64 f2 uint64 f3 uint64 f4 uint64 g uint64 g0 uint64 g1 uint64 g2 uint64 g3 uint64 g4 uint64 ) var p int32 l := int32(len(m)) r00 := uint32(r[0]) r01 := uint32(r[1]) r02 := uint32(r[2]) r0 := int64(2151) r03 := uint32(r[3]) r03 &= 15 r0 <<= 51 r10 := uint32(r[4]) r10 &= 252 r01 <<= 8 r0 += int64(r00) r11 := uint32(r[5]) r02 <<= 16 r0 += int64(r01) r12 := uint32(r[6]) r03 <<= 24 r0 += int64(r02) r13 := uint32(r[7]) r13 &= 15 r1 := int64(2215) r0 += int64(r03) d0 := r0 r1 <<= 51 r2 := int64(2279) r20 := uint32(r[8]) r20 &= 252 r11 <<= 8 r1 += int64(r10) r21 := uint32(r[9]) r12 <<= 16 r1 += int64(r11) r22 := uint32(r[10]) r13 <<= 24 r1 += int64(r12) r23 := uint32(r[11]) r23 &= 15 r2 <<= 51 r1 += int64(r13) d1 := r1 r21 <<= 8 r2 += int64(r20) r30 := uint32(r[12]) r30 &= 252 r22 <<= 16 r2 += int64(r21) r31 := uint32(r[13]) r23 <<= 24 r2 += int64(r22) r32 := uint32(r[14]) r2 += int64(r23) r3 := int64(2343) d2 := r2 r3 <<= 51 r33 := uint32(r[15]) r33 &= 15 r31 <<= 8 r3 += int64(r30) r32 <<= 16 r3 += int64(r31) r33 <<= 24 r3 += int64(r32) r3 += int64(r33) h0 := alpha32 - alpha32 d3 := r3 h1 := alpha32 - alpha32 h2 := alpha32 - alpha32 h3 := alpha32 - alpha32 h4 := alpha32 - alpha32 r0low := math.Float64frombits(uint64(d0)) h5 := alpha32 - alpha32 r1low := math.Float64frombits(uint64(d1)) h6 := alpha32 - alpha32 r2low := math.Float64frombits(uint64(d2)) h7 := alpha32 - alpha32 r0low -= alpha0 r1low -= alpha32 r2low -= alpha64 r0high := r0low + alpha18 r3low := math.Float64frombits(uint64(d3)) r1high := r1low + alpha50 sr1low := scale * r1low r2high := r2low + alpha82 sr2low := scale * r2low r0high -= alpha18 r0high_stack := r0high r3low -= alpha96 r1high -= alpha50 r1high_stack := r1high sr1high := sr1low + alpham80 r0low -= r0high r2high -= alpha82 sr3low = scale * r3low sr2high := sr2low + alpham48 r1low -= r1high r1low_stack := r1low sr1high -= alpham80 sr1high_stack := sr1high r2low -= r2high r2low_stack := r2low sr2high -= alpham48 sr2high_stack := sr2high r3high := r3low + alpha112 r0low_stack := r0low sr1low -= sr1high sr1low_stack := sr1low sr3high := sr3low + alpham16 r2high_stack := r2high sr2low -= sr2high sr2low_stack := sr2low r3high -= alpha112 r3high_stack := r3high sr3high -= alpham16 sr3high_stack := sr3high r3low -= r3high r3low_stack := r3low sr3low -= sr3high sr3low_stack := sr3low if l < 16 { goto addatmost15bytes } m00 = uint32(m[p+0]) m0 = 2151 m0 <<= 51 m1 = 2215 m01 = uint32(m[p+1]) m1 <<= 51 m2 = 2279 m02 = uint32(m[p+2]) m2 <<= 51 m3 = 2343 m03 = uint32(m[p+3]) m10 = uint32(m[p+4]) m01 <<= 8 m0 += int64(m00) m11 = uint32(m[p+5]) m02 <<= 16 m0 += int64(m01) m12 = uint32(m[p+6]) m03 <<= 24 m0 += int64(m02) m13 = uint32(m[p+7]) m3 <<= 51 m0 += int64(m03) m20 = uint32(m[p+8]) m11 <<= 8 m1 += int64(m10) m21 = uint32(m[p+9]) m12 <<= 16 m1 += int64(m11) m22 = uint32(m[p+10]) m13 <<= 24 m1 += int64(m12) m23 = uint32(m[p+11]) m1 += int64(m13) m30 = uint32(m[p+12]) m21 <<= 8 m2 += int64(m20) m31 = uint32(m[p+13]) m22 <<= 16 m2 += int64(m21) m32 = uint32(m[p+14]) m23 <<= 24 m2 += int64(m22) m33 = uint64(m[p+15]) m2 += int64(m23) d0 = m0 m31 <<= 8 m3 += int64(m30) d1 = m1 m32 <<= 16 m3 += int64(m31) d2 = m2 m33 += 256 m33 <<= 24 m3 += int64(m32) m3 += int64(m33) d3 = m3 p += 16 l -= 16 z0 = math.Float64frombits(uint64(d0)) z1 = math.Float64frombits(uint64(d1)) z2 = math.Float64frombits(uint64(d2)) z3 = math.Float64frombits(uint64(d3)) z0 -= alpha0 z1 -= alpha32 z2 -= alpha64 z3 -= alpha96 h0 += z0 h1 += z1 h3 += z2 h5 += z3 if l < 16 { goto multiplyaddatmost15bytes } multiplyaddatleast16bytes: m2 = 2279 m20 = uint32(m[p+8]) y7 = h7 + alpha130 m2 <<= 51 m3 = 2343 m21 = uint32(m[p+9]) y6 = h6 + alpha130 m3 <<= 51 m0 = 2151 m22 = uint32(m[p+10]) y1 = h1 + alpha32 m0 <<= 51 m1 = 2215 m23 = uint32(m[p+11]) y0 = h0 + alpha32 m1 <<= 51 m30 = uint32(m[p+12]) y7 -= alpha130 m21 <<= 8 m2 += int64(m20) m31 = uint32(m[p+13]) y6 -= alpha130 m22 <<= 16 m2 += int64(m21) m32 = uint32(m[p+14]) y1 -= alpha32 m23 <<= 24 m2 += int64(m22) m33 = uint64(m[p+15]) y0 -= alpha32 m2 += int64(m23) m00 = uint32(m[p+0]) y5 = h5 + alpha96 m31 <<= 8 m3 += int64(m30) m01 = uint32(m[p+1]) y4 = h4 + alpha96 m32 <<= 16 m02 = uint32(m[p+2]) x7 = h7 - y7 y7 *= scale m33 += 256 m03 = uint32(m[p+3]) x6 = h6 - y6 y6 *= scale m33 <<= 24 m3 += int64(m31) m10 = uint32(m[p+4]) x1 = h1 - y1 m01 <<= 8 m3 += int64(m32) m11 = uint32(m[p+5]) x0 = h0 - y0 m3 += int64(m33) m0 += int64(m00) m12 = uint32(m[p+6]) y5 -= alpha96 m02 <<= 16 m0 += int64(m01) m13 = uint32(m[p+7]) y4 -= alpha96 m03 <<= 24 m0 += int64(m02) d2 = m2 x1 += y7 m0 += int64(m03) d3 = m3 x0 += y6 m11 <<= 8 m1 += int64(m10) d0 = m0 x7 += y5 m12 <<= 16 m1 += int64(m11) x6 += y4 m13 <<= 24 m1 += int64(m12) y3 = h3 + alpha64 m1 += int64(m13) d1 = m1 y2 = h2 + alpha64 x0 += x1 x6 += x7 y3 -= alpha64 r3low = r3low_stack y2 -= alpha64 r0low = r0low_stack x5 = h5 - y5 r3lowx0 = r3low * x0 r3high = r3high_stack x4 = h4 - y4 r0lowx6 = r0low * x6 r0high = r0high_stack x3 = h3 - y3 r3highx0 = r3high * x0 sr1low = sr1low_stack x2 = h2 - y2 r0highx6 = r0high * x6 sr1high = sr1high_stack x5 += y3 r0lowx0 = r0low * x0 r1low = r1low_stack h6 = r3lowx0 + r0lowx6 sr1lowx6 = sr1low * x6 r1high = r1high_stack x4 += y2 r0highx0 = r0high * x0 sr2low = sr2low_stack h7 = r3highx0 + r0highx6 sr1highx6 = sr1high * x6 sr2high = sr2high_stack x3 += y1 r1lowx0 = r1low * x0 r2low = r2low_stack h0 = r0lowx0 + sr1lowx6 sr2lowx6 = sr2low * x6 r2high = r2high_stack x2 += y0 r1highx0 = r1high * x0 sr3low = sr3low_stack h1 = r0highx0 + sr1highx6 sr2highx6 = sr2high * x6 sr3high = sr3high_stack x4 += x5 r2lowx0 = r2low * x0 z2 = math.Float64frombits(uint64(d2)) h2 = r1lowx0 + sr2lowx6 sr3lowx6 = sr3low * x6 x2 += x3 r2highx0 = r2high * x0 z3 = math.Float64frombits(uint64(d3)) h3 = r1highx0 + sr2highx6 sr3highx6 = sr3high * x6 r1highx4 = r1high * x4 z2 -= alpha64 h4 = r2lowx0 + sr3lowx6 r1lowx4 = r1low * x4 r0highx4 = r0high * x4 z3 -= alpha96 h5 = r2highx0 + sr3highx6 r0lowx4 = r0low * x4 h7 += r1highx4 sr3highx4 = sr3high * x4 h6 += r1lowx4 sr3lowx4 = sr3low * x4 h5 += r0highx4 sr2highx4 = sr2high * x4 h4 += r0lowx4 sr2lowx4 = sr2low * x4 h3 += sr3highx4 r0lowx2 = r0low * x2 h2 += sr3lowx4 r0highx2 = r0high * x2 h1 += sr2highx4 r1lowx2 = r1low * x2 h0 += sr2lowx4 r1highx2 = r1high * x2 h2 += r0lowx2 r2lowx2 = r2low * x2 h3 += r0highx2 r2highx2 = r2high * x2 h4 += r1lowx2 sr3lowx2 = sr3low * x2 h5 += r1highx2 sr3highx2 = sr3high * x2 p += 16 l -= 16 h6 += r2lowx2 h7 += r2highx2 z1 = math.Float64frombits(uint64(d1)) h0 += sr3lowx2 z0 = math.Float64frombits(uint64(d0)) h1 += sr3highx2 z1 -= alpha32 z0 -= alpha0 h5 += z3 h3 += z2 h1 += z1 h0 += z0 if l >= 16 { goto multiplyaddatleast16bytes } multiplyaddatmost15bytes: y7 = h7 + alpha130 y6 = h6 + alpha130 y1 = h1 + alpha32 y0 = h0 + alpha32 y7 -= alpha130 y6 -= alpha130 y1 -= alpha32 y0 -= alpha32 y5 = h5 + alpha96 y4 = h4 + alpha96 x7 = h7 - y7 y7 *= scale x6 = h6 - y6 y6 *= scale x1 = h1 - y1 x0 = h0 - y0 y5 -= alpha96 y4 -= alpha96 x1 += y7 x0 += y6 x7 += y5 x6 += y4 y3 = h3 + alpha64 y2 = h2 + alpha64 x0 += x1 x6 += x7 y3 -= alpha64 r3low = r3low_stack y2 -= alpha64 r0low = r0low_stack x5 = h5 - y5 r3lowx0 = r3low * x0 r3high = r3high_stack x4 = h4 - y4 r0lowx6 = r0low * x6 r0high = r0high_stack x3 = h3 - y3 r3highx0 = r3high * x0 sr1low = sr1low_stack x2 = h2 - y2 r0highx6 = r0high * x6 sr1high = sr1high_stack x5 += y3 r0lowx0 = r0low * x0 r1low = r1low_stack h6 = r3lowx0 + r0lowx6 sr1lowx6 = sr1low * x6 r1high = r1high_stack x4 += y2 r0highx0 = r0high * x0 sr2low = sr2low_stack h7 = r3highx0 + r0highx6 sr1highx6 = sr1high * x6 sr2high = sr2high_stack x3 += y1 r1lowx0 = r1low * x0 r2low = r2low_stack h0 = r0lowx0 + sr1lowx6 sr2lowx6 = sr2low * x6 r2high = r2high_stack x2 += y0 r1highx0 = r1high * x0 sr3low = sr3low_stack h1 = r0highx0 + sr1highx6 sr2highx6 = sr2high * x6 sr3high = sr3high_stack x4 += x5 r2lowx0 = r2low * x0 h2 = r1lowx0 + sr2lowx6 sr3lowx6 = sr3low * x6 x2 += x3 r2highx0 = r2high * x0 h3 = r1highx0 + sr2highx6 sr3highx6 = sr3high * x6 r1highx4 = r1high * x4 h4 = r2lowx0 + sr3lowx6 r1lowx4 = r1low * x4 r0highx4 = r0high * x4 h5 = r2highx0 + sr3highx6 r0lowx4 = r0low * x4 h7 += r1highx4 sr3highx4 = sr3high * x4 h6 += r1lowx4 sr3lowx4 = sr3low * x4 h5 += r0highx4 sr2highx4 = sr2high * x4 h4 += r0lowx4 sr2lowx4 = sr2low * x4 h3 += sr3highx4 r0lowx2 = r0low * x2 h2 += sr3lowx4 r0highx2 = r0high * x2 h1 += sr2highx4 r1lowx2 = r1low * x2 h0 += sr2lowx4 r1highx2 = r1high * x2 h2 += r0lowx2 r2lowx2 = r2low * x2 h3 += r0highx2 r2highx2 = r2high * x2 h4 += r1lowx2 sr3lowx2 = sr3low * x2 h5 += r1highx2 sr3highx2 = sr3high * x2 h6 += r2lowx2 h7 += r2highx2 h0 += sr3lowx2 h1 += sr3highx2 addatmost15bytes: if l == 0 { goto nomorebytes } lbelow2 = l - 2 lbelow3 = l - 3 lbelow2 >>= 31 lbelow4 = l - 4 m00 = uint32(m[p+0]) lbelow3 >>= 31 p += lbelow2 m01 = uint32(m[p+1]) lbelow4 >>= 31 p += lbelow3 m02 = uint32(m[p+2]) p += lbelow4 m0 = 2151 m03 = uint32(m[p+3]) m0 <<= 51 m1 = 2215 m0 += int64(m00) m01 &^= uint32(lbelow2) m02 &^= uint32(lbelow3) m01 -= uint32(lbelow2) m01 <<= 8 m03 &^= uint32(lbelow4) m0 += int64(m01) lbelow2 -= lbelow3 m02 += uint32(lbelow2) lbelow3 -= lbelow4 m02 <<= 16 m03 += uint32(lbelow3) m03 <<= 24 m0 += int64(m02) m0 += int64(m03) lbelow5 = l - 5 lbelow6 = l - 6 lbelow7 = l - 7 lbelow5 >>= 31 lbelow8 = l - 8 lbelow6 >>= 31 p += lbelow5 m10 = uint32(m[p+4]) lbelow7 >>= 31 p += lbelow6 m11 = uint32(m[p+5]) lbelow8 >>= 31 p += lbelow7 m12 = uint32(m[p+6]) m1 <<= 51 p += lbelow8 m13 = uint32(m[p+7]) m10 &^= uint32(lbelow5) lbelow4 -= lbelow5 m10 += uint32(lbelow4) lbelow5 -= lbelow6 m11 &^= uint32(lbelow6) m11 += uint32(lbelow5) m11 <<= 8 m1 += int64(m10) m1 += int64(m11) m12 &^= uint32(lbelow7) lbelow6 -= lbelow7 m13 &^= uint32(lbelow8) m12 += uint32(lbelow6) lbelow7 -= lbelow8 m12 <<= 16 m13 += uint32(lbelow7) m13 <<= 24 m1 += int64(m12) m1 += int64(m13) m2 = 2279 lbelow9 = l - 9 m3 = 2343 lbelow10 = l - 10 lbelow11 = l - 11 lbelow9 >>= 31 lbelow12 = l - 12 lbelow10 >>= 31 p += lbelow9 m20 = uint32(m[p+8]) lbelow11 >>= 31 p += lbelow10 m21 = uint32(m[p+9]) lbelow12 >>= 31 p += lbelow11 m22 = uint32(m[p+10]) m2 <<= 51 p += lbelow12 m23 = uint32(m[p+11]) m20 &^= uint32(lbelow9) lbelow8 -= lbelow9 m20 += uint32(lbelow8) lbelow9 -= lbelow10 m21 &^= uint32(lbelow10) m21 += uint32(lbelow9) m21 <<= 8 m2 += int64(m20) m2 += int64(m21) m22 &^= uint32(lbelow11) lbelow10 -= lbelow11 m23 &^= uint32(lbelow12) m22 += uint32(lbelow10) lbelow11 -= lbelow12 m22 <<= 16 m23 += uint32(lbelow11) m23 <<= 24 m2 += int64(m22) m3 <<= 51 lbelow13 = l - 13 lbelow13 >>= 31 lbelow14 = l - 14 lbelow14 >>= 31 p += lbelow13 lbelow15 = l - 15 m30 = uint32(m[p+12]) lbelow15 >>= 31 p += lbelow14 m31 = uint32(m[p+13]) p += lbelow15 m2 += int64(m23) m32 = uint32(m[p+14]) m30 &^= uint32(lbelow13) lbelow12 -= lbelow13 m30 += uint32(lbelow12) lbelow13 -= lbelow14 m3 += int64(m30) m31 &^= uint32(lbelow14) m31 += uint32(lbelow13) m32 &^= uint32(lbelow15) m31 <<= 8 lbelow14 -= lbelow15 m3 += int64(m31) m32 += uint32(lbelow14) d0 = m0 m32 <<= 16 m33 = uint64(lbelow15 + 1) d1 = m1 m33 <<= 24 m3 += int64(m32) d2 = m2 m3 += int64(m33) d3 = m3 z3 = math.Float64frombits(uint64(d3)) z2 = math.Float64frombits(uint64(d2)) z1 = math.Float64frombits(uint64(d1)) z0 = math.Float64frombits(uint64(d0)) z3 -= alpha96 z2 -= alpha64 z1 -= alpha32 z0 -= alpha0 h5 += z3 h3 += z2 h1 += z1 h0 += z0 y7 = h7 + alpha130 y6 = h6 + alpha130 y1 = h1 + alpha32 y0 = h0 + alpha32 y7 -= alpha130 y6 -= alpha130 y1 -= alpha32 y0 -= alpha32 y5 = h5 + alpha96 y4 = h4 + alpha96 x7 = h7 - y7 y7 *= scale x6 = h6 - y6 y6 *= scale x1 = h1 - y1 x0 = h0 - y0 y5 -= alpha96 y4 -= alpha96 x1 += y7 x0 += y6 x7 += y5 x6 += y4 y3 = h3 + alpha64 y2 = h2 + alpha64 x0 += x1 x6 += x7 y3 -= alpha64 r3low = r3low_stack y2 -= alpha64 r0low = r0low_stack x5 = h5 - y5 r3lowx0 = r3low * x0 r3high = r3high_stack x4 = h4 - y4 r0lowx6 = r0low * x6 r0high = r0high_stack x3 = h3 - y3 r3highx0 = r3high * x0 sr1low = sr1low_stack x2 = h2 - y2 r0highx6 = r0high * x6 sr1high = sr1high_stack x5 += y3 r0lowx0 = r0low * x0 r1low = r1low_stack h6 = r3lowx0 + r0lowx6 sr1lowx6 = sr1low * x6 r1high = r1high_stack x4 += y2 r0highx0 = r0high * x0 sr2low = sr2low_stack h7 = r3highx0 + r0highx6 sr1highx6 = sr1high * x6 sr2high = sr2high_stack x3 += y1 r1lowx0 = r1low * x0 r2low = r2low_stack h0 = r0lowx0 + sr1lowx6 sr2lowx6 = sr2low * x6 r2high = r2high_stack x2 += y0 r1highx0 = r1high * x0 sr3low = sr3low_stack h1 = r0highx0 + sr1highx6 sr2highx6 = sr2high * x6 sr3high = sr3high_stack x4 += x5 r2lowx0 = r2low * x0 h2 = r1lowx0 + sr2lowx6 sr3lowx6 = sr3low * x6 x2 += x3 r2highx0 = r2high * x0 h3 = r1highx0 + sr2highx6 sr3highx6 = sr3high * x6 r1highx4 = r1high * x4 h4 = r2lowx0 + sr3lowx6 r1lowx4 = r1low * x4 r0highx4 = r0high * x4 h5 = r2highx0 + sr3highx6 r0lowx4 = r0low * x4 h7 += r1highx4 sr3highx4 = sr3high * x4 h6 += r1lowx4 sr3lowx4 = sr3low * x4 h5 += r0highx4 sr2highx4 = sr2high * x4 h4 += r0lowx4 sr2lowx4 = sr2low * x4 h3 += sr3highx4 r0lowx2 = r0low * x2 h2 += sr3lowx4 r0highx2 = r0high * x2 h1 += sr2highx4 r1lowx2 = r1low * x2 h0 += sr2lowx4 r1highx2 = r1high * x2 h2 += r0lowx2 r2lowx2 = r2low * x2 h3 += r0highx2 r2highx2 = r2high * x2 h4 += r1lowx2 sr3lowx2 = sr3low * x2 h5 += r1highx2 sr3highx2 = sr3high * x2 h6 += r2lowx2 h7 += r2highx2 h0 += sr3lowx2 h1 += sr3highx2 nomorebytes: y7 = h7 + alpha130 y0 = h0 + alpha32 y1 = h1 + alpha32 y2 = h2 + alpha64 y7 -= alpha130 y3 = h3 + alpha64 y4 = h4 + alpha96 y5 = h5 + alpha96 x7 = h7 - y7 y7 *= scale y0 -= alpha32 y1 -= alpha32 y2 -= alpha64 h6 += x7 y3 -= alpha64 y4 -= alpha96 y5 -= alpha96 y6 = h6 + alpha130 x0 = h0 - y0 x1 = h1 - y1 x2 = h2 - y2 y6 -= alpha130 x0 += y7 x3 = h3 - y3 x4 = h4 - y4 x5 = h5 - y5 x6 = h6 - y6 y6 *= scale x2 += y0 x3 += y1 x4 += y2 x0 += y6 x5 += y3 x6 += y4 x2 += x3 x0 += x1 x4 += x5 x6 += y5 x2 += offset1 d1 = int64(math.Float64bits(x2)) x0 += offset0 d0 = int64(math.Float64bits(x0)) x4 += offset2 d2 = int64(math.Float64bits(x4)) x6 += offset3 d3 = int64(math.Float64bits(x6)) f0 = uint64(d0) f1 = uint64(d1) bits32 = math.MaxUint64 f2 = uint64(d2) bits32 >>= 32 f3 = uint64(d3) f = f0 >> 32 f0 &= bits32 f &= 255 f1 += f g0 = f0 + 5 g = g0 >> 32 g0 &= bits32 f = f1 >> 32 f1 &= bits32 f &= 255 g1 = f1 + g g = g1 >> 32 f2 += f f = f2 >> 32 g1 &= bits32 f2 &= bits32 f &= 255 f3 += f g2 = f2 + g g = g2 >> 32 g2 &= bits32 f4 = f3 >> 32 f3 &= bits32 f4 &= 255 g3 = f3 + g g = g3 >> 32 g3 &= bits32 g4 = f4 + g g4 = g4 - 4 s00 = uint32(s[0]) f = uint64(int64(g4) >> 63) s01 = uint32(s[1]) f0 &= f g0 &^= f s02 = uint32(s[2]) f1 &= f f0 |= g0 s03 = uint32(s[3]) g1 &^= f f2 &= f s10 = uint32(s[4]) f3 &= f g2 &^= f s11 = uint32(s[5]) g3 &^= f f1 |= g1 s12 = uint32(s[6]) f2 |= g2 f3 |= g3 s13 = uint32(s[7]) s01 <<= 8 f0 += uint64(s00) s20 = uint32(s[8]) s02 <<= 16 f0 += uint64(s01) s21 = uint32(s[9]) s03 <<= 24 f0 += uint64(s02) s22 = uint32(s[10]) s11 <<= 8 f1 += uint64(s10) s23 = uint32(s[11]) s12 <<= 16 f1 += uint64(s11) s30 = uint32(s[12]) s13 <<= 24 f1 += uint64(s12) s31 = uint32(s[13]) f0 += uint64(s03) f1 += uint64(s13) s32 = uint32(s[14]) s21 <<= 8 f2 += uint64(s20) s33 = uint32(s[15]) s22 <<= 16 f2 += uint64(s21) s23 <<= 24 f2 += uint64(s22) s31 <<= 8 f3 += uint64(s30) s32 <<= 16 f3 += uint64(s31) s33 <<= 24 f3 += uint64(s32) f2 += uint64(s23) f3 += uint64(s33) out[0] = byte(f0) f0 >>= 8 out[1] = byte(f0) f0 >>= 8 out[2] = byte(f0) f0 >>= 8 out[3] = byte(f0) f0 >>= 8 f1 += f0 out[4] = byte(f1) f1 >>= 8 out[5] = byte(f1) f1 >>= 8 out[6] = byte(f1) f1 >>= 8 out[7] = byte(f1) f1 >>= 8 f2 += f1 out[8] = byte(f2) f2 >>= 8 out[9] = byte(f2) f2 >>= 8 out[10] = byte(f2) f2 >>= 8 out[11] = byte(f2) f2 >>= 8 f3 += f2 out[12] = byte(f3) f3 >>= 8 out[13] = byte(f3) f3 >>= 8 out[14] = byte(f3) f3 >>= 8 out[15] = byte(f3) } lxd-2.0.0/dist/src/golang.org/x/crypto/poly1305/poly1305_amd64.s0000644061062106075000000002050012702772344026240 0ustar00stgraberdomain admins00000000000000// Copyright 2012 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 code was translated into a form compatible with 6a from the public // domain sources in SUPERCOP: http://bench.cr.yp.to/supercop.html // +build amd64,!gccgo,!appengine // func poly1305(out *[16]byte, m *byte, mlen uint64, key *[32]key) TEXT ·poly1305(SB),0,$224-32 MOVQ out+0(FP),DI MOVQ m+8(FP),SI MOVQ mlen+16(FP),DX MOVQ key+24(FP),CX MOVQ SP,R11 MOVQ $31,R9 NOTQ R9 ANDQ R9,SP ADDQ $32,SP MOVQ R11,32(SP) MOVQ R12,40(SP) MOVQ R13,48(SP) MOVQ R14,56(SP) MOVQ R15,64(SP) MOVQ BX,72(SP) MOVQ BP,80(SP) FLDCW ·ROUNDING(SB) MOVL 0(CX),R8 MOVL 4(CX),R9 MOVL 8(CX),AX MOVL 12(CX),R10 MOVQ DI,88(SP) MOVQ CX,96(SP) MOVL $0X43300000,108(SP) MOVL $0X45300000,116(SP) MOVL $0X47300000,124(SP) MOVL $0X49300000,132(SP) ANDL $0X0FFFFFFF,R8 ANDL $0X0FFFFFFC,R9 ANDL $0X0FFFFFFC,AX ANDL $0X0FFFFFFC,R10 MOVL R8,104(SP) MOVL R9,112(SP) MOVL AX,120(SP) MOVL R10,128(SP) FMOVD 104(SP), F0 FSUBD ·DOFFSET0(SB), F0 FMOVD 112(SP), F0 FSUBD ·DOFFSET1(SB), F0 FMOVD 120(SP), F0 FSUBD ·DOFFSET2(SB), F0 FMOVD 128(SP), F0 FSUBD ·DOFFSET3(SB), F0 FXCHD F0, F3 FMOVDP F0, 136(SP) FXCHD F0, F1 FMOVD F0, 144(SP) FMULD ·SCALE(SB), F0 FMOVDP F0, 152(SP) FMOVD F0, 160(SP) FMULD ·SCALE(SB), F0 FMOVDP F0, 168(SP) FMOVD F0, 176(SP) FMULD ·SCALE(SB), F0 FMOVDP F0, 184(SP) FLDZ FLDZ FLDZ FLDZ CMPQ DX,$16 JB ADDATMOST15BYTES INITIALATLEAST16BYTES: MOVL 12(SI),DI MOVL 8(SI),CX MOVL 4(SI),R8 MOVL 0(SI),R9 MOVL DI,128(SP) MOVL CX,120(SP) MOVL R8,112(SP) MOVL R9,104(SP) ADDQ $16,SI SUBQ $16,DX FXCHD F0, F3 FADDD 128(SP), F0 FSUBD ·DOFFSET3MINUSTWO128(SB), F0 FXCHD F0, F1 FADDD 112(SP), F0 FSUBD ·DOFFSET1(SB), F0 FXCHD F0, F2 FADDD 120(SP), F0 FSUBD ·DOFFSET2(SB), F0 FXCHD F0, F3 FADDD 104(SP), F0 FSUBD ·DOFFSET0(SB), F0 CMPQ DX,$16 JB MULTIPLYADDATMOST15BYTES MULTIPLYADDATLEAST16BYTES: MOVL 12(SI),DI MOVL 8(SI),CX MOVL 4(SI),R8 MOVL 0(SI),R9 MOVL DI,128(SP) MOVL CX,120(SP) MOVL R8,112(SP) MOVL R9,104(SP) ADDQ $16,SI SUBQ $16,DX FMOVD ·ALPHA130(SB), F0 FADDD F2,F0 FSUBD ·ALPHA130(SB), F0 FSUBD F0,F2 FMULD ·SCALE(SB), F0 FMOVD ·ALPHA32(SB), F0 FADDD F2,F0 FSUBD ·ALPHA32(SB), F0 FSUBD F0,F2 FXCHD F0, F2 FADDDP F0,F1 FMOVD ·ALPHA64(SB), F0 FADDD F4,F0 FSUBD ·ALPHA64(SB), F0 FSUBD F0,F4 FMOVD ·ALPHA96(SB), F0 FADDD F6,F0 FSUBD ·ALPHA96(SB), F0 FSUBD F0,F6 FXCHD F0, F6 FADDDP F0,F1 FXCHD F0, F3 FADDDP F0,F5 FXCHD F0, F3 FADDDP F0,F1 FMOVD 176(SP), F0 FMULD F3,F0 FMOVD 160(SP), F0 FMULD F4,F0 FMOVD 144(SP), F0 FMULD F5,F0 FMOVD 136(SP), F0 FMULDP F0,F6 FMOVD 160(SP), F0 FMULD F4,F0 FADDDP F0,F3 FMOVD 144(SP), F0 FMULD F4,F0 FADDDP F0,F2 FMOVD 136(SP), F0 FMULD F4,F0 FADDDP F0,F1 FMOVD 184(SP), F0 FMULDP F0,F4 FXCHD F0, F3 FADDDP F0,F5 FMOVD 144(SP), F0 FMULD F4,F0 FADDDP F0,F2 FMOVD 136(SP), F0 FMULD F4,F0 FADDDP F0,F1 FMOVD 184(SP), F0 FMULD F4,F0 FADDDP F0,F3 FMOVD 168(SP), F0 FMULDP F0,F4 FXCHD F0, F3 FADDDP F0,F4 FMOVD 136(SP), F0 FMULD F5,F0 FADDDP F0,F1 FXCHD F0, F3 FMOVD 184(SP), F0 FMULD F5,F0 FADDDP F0,F3 FXCHD F0, F1 FMOVD 168(SP), F0 FMULD F5,F0 FADDDP F0,F1 FMOVD 152(SP), F0 FMULDP F0,F5 FXCHD F0, F4 FADDDP F0,F1 CMPQ DX,$16 FXCHD F0, F2 FMOVD 128(SP), F0 FSUBD ·DOFFSET3MINUSTWO128(SB), F0 FADDDP F0,F1 FXCHD F0, F1 FMOVD 120(SP), F0 FSUBD ·DOFFSET2(SB), F0 FADDDP F0,F1 FXCHD F0, F3 FMOVD 112(SP), F0 FSUBD ·DOFFSET1(SB), F0 FADDDP F0,F1 FXCHD F0, F2 FMOVD 104(SP), F0 FSUBD ·DOFFSET0(SB), F0 FADDDP F0,F1 JAE MULTIPLYADDATLEAST16BYTES MULTIPLYADDATMOST15BYTES: FMOVD ·ALPHA130(SB), F0 FADDD F2,F0 FSUBD ·ALPHA130(SB), F0 FSUBD F0,F2 FMULD ·SCALE(SB), F0 FMOVD ·ALPHA32(SB), F0 FADDD F2,F0 FSUBD ·ALPHA32(SB), F0 FSUBD F0,F2 FMOVD ·ALPHA64(SB), F0 FADDD F5,F0 FSUBD ·ALPHA64(SB), F0 FSUBD F0,F5 FMOVD ·ALPHA96(SB), F0 FADDD F7,F0 FSUBD ·ALPHA96(SB), F0 FSUBD F0,F7 FXCHD F0, F7 FADDDP F0,F1 FXCHD F0, F5 FADDDP F0,F1 FXCHD F0, F3 FADDDP F0,F5 FADDDP F0,F1 FMOVD 176(SP), F0 FMULD F1,F0 FMOVD 160(SP), F0 FMULD F2,F0 FMOVD 144(SP), F0 FMULD F3,F0 FMOVD 136(SP), F0 FMULDP F0,F4 FMOVD 160(SP), F0 FMULD F5,F0 FADDDP F0,F3 FMOVD 144(SP), F0 FMULD F5,F0 FADDDP F0,F2 FMOVD 136(SP), F0 FMULD F5,F0 FADDDP F0,F1 FMOVD 184(SP), F0 FMULDP F0,F5 FXCHD F0, F4 FADDDP F0,F3 FMOVD 144(SP), F0 FMULD F5,F0 FADDDP F0,F2 FMOVD 136(SP), F0 FMULD F5,F0 FADDDP F0,F1 FMOVD 184(SP), F0 FMULD F5,F0 FADDDP F0,F4 FMOVD 168(SP), F0 FMULDP F0,F5 FXCHD F0, F4 FADDDP F0,F2 FMOVD 136(SP), F0 FMULD F5,F0 FADDDP F0,F1 FMOVD 184(SP), F0 FMULD F5,F0 FADDDP F0,F4 FMOVD 168(SP), F0 FMULD F5,F0 FADDDP F0,F3 FMOVD 152(SP), F0 FMULDP F0,F5 FXCHD F0, F4 FADDDP F0,F1 ADDATMOST15BYTES: CMPQ DX,$0 JE NOMOREBYTES MOVL $0,0(SP) MOVL $0, 4 (SP) MOVL $0, 8 (SP) MOVL $0, 12 (SP) LEAQ 0(SP),DI MOVQ DX,CX REP; MOVSB MOVB $1,0(DI) MOVL 12 (SP),DI MOVL 8 (SP),SI MOVL 4 (SP),DX MOVL 0(SP),CX MOVL DI,128(SP) MOVL SI,120(SP) MOVL DX,112(SP) MOVL CX,104(SP) FXCHD F0, F3 FADDD 128(SP), F0 FSUBD ·DOFFSET3(SB), F0 FXCHD F0, F2 FADDD 120(SP), F0 FSUBD ·DOFFSET2(SB), F0 FXCHD F0, F1 FADDD 112(SP), F0 FSUBD ·DOFFSET1(SB), F0 FXCHD F0, F3 FADDD 104(SP), F0 FSUBD ·DOFFSET0(SB), F0 FMOVD ·ALPHA130(SB), F0 FADDD F3,F0 FSUBD ·ALPHA130(SB), F0 FSUBD F0,F3 FMULD ·SCALE(SB), F0 FMOVD ·ALPHA32(SB), F0 FADDD F2,F0 FSUBD ·ALPHA32(SB), F0 FSUBD F0,F2 FMOVD ·ALPHA64(SB), F0 FADDD F6,F0 FSUBD ·ALPHA64(SB), F0 FSUBD F0,F6 FMOVD ·ALPHA96(SB), F0 FADDD F5,F0 FSUBD ·ALPHA96(SB), F0 FSUBD F0,F5 FXCHD F0, F4 FADDDP F0,F3 FXCHD F0, F6 FADDDP F0,F1 FXCHD F0, F3 FADDDP F0,F5 FXCHD F0, F3 FADDDP F0,F1 FMOVD 176(SP), F0 FMULD F3,F0 FMOVD 160(SP), F0 FMULD F4,F0 FMOVD 144(SP), F0 FMULD F5,F0 FMOVD 136(SP), F0 FMULDP F0,F6 FMOVD 160(SP), F0 FMULD F5,F0 FADDDP F0,F3 FMOVD 144(SP), F0 FMULD F5,F0 FADDDP F0,F2 FMOVD 136(SP), F0 FMULD F5,F0 FADDDP F0,F1 FMOVD 184(SP), F0 FMULDP F0,F5 FXCHD F0, F4 FADDDP F0,F5 FMOVD 144(SP), F0 FMULD F6,F0 FADDDP F0,F2 FMOVD 136(SP), F0 FMULD F6,F0 FADDDP F0,F1 FMOVD 184(SP), F0 FMULD F6,F0 FADDDP F0,F4 FMOVD 168(SP), F0 FMULDP F0,F6 FXCHD F0, F5 FADDDP F0,F4 FMOVD 136(SP), F0 FMULD F2,F0 FADDDP F0,F1 FMOVD 184(SP), F0 FMULD F2,F0 FADDDP F0,F5 FMOVD 168(SP), F0 FMULD F2,F0 FADDDP F0,F3 FMOVD 152(SP), F0 FMULDP F0,F2 FXCHD F0, F1 FADDDP F0,F3 FXCHD F0, F3 FXCHD F0, F2 NOMOREBYTES: MOVL $0,R10 FMOVD ·ALPHA130(SB), F0 FADDD F4,F0 FSUBD ·ALPHA130(SB), F0 FSUBD F0,F4 FMULD ·SCALE(SB), F0 FMOVD ·ALPHA32(SB), F0 FADDD F2,F0 FSUBD ·ALPHA32(SB), F0 FSUBD F0,F2 FMOVD ·ALPHA64(SB), F0 FADDD F4,F0 FSUBD ·ALPHA64(SB), F0 FSUBD F0,F4 FMOVD ·ALPHA96(SB), F0 FADDD F6,F0 FSUBD ·ALPHA96(SB), F0 FXCHD F0, F6 FSUBD F6,F0 FXCHD F0, F4 FADDDP F0,F3 FXCHD F0, F4 FADDDP F0,F1 FXCHD F0, F2 FADDDP F0,F3 FXCHD F0, F4 FADDDP F0,F3 FXCHD F0, F3 FADDD ·HOFFSET0(SB), F0 FXCHD F0, F3 FADDD ·HOFFSET1(SB), F0 FXCHD F0, F1 FADDD ·HOFFSET2(SB), F0 FXCHD F0, F2 FADDD ·HOFFSET3(SB), F0 FXCHD F0, F3 FMOVDP F0, 104(SP) FMOVDP F0, 112(SP) FMOVDP F0, 120(SP) FMOVDP F0, 128(SP) MOVL 108(SP),DI ANDL $63,DI MOVL 116(SP),SI ANDL $63,SI MOVL 124(SP),DX ANDL $63,DX MOVL 132(SP),CX ANDL $63,CX MOVL 112(SP),R8 ADDL DI,R8 MOVQ R8,112(SP) MOVL 120(SP),DI ADCL SI,DI MOVQ DI,120(SP) MOVL 128(SP),DI ADCL DX,DI MOVQ DI,128(SP) MOVL R10,DI ADCL CX,DI MOVQ DI,136(SP) MOVQ $5,DI MOVL 104(SP),SI ADDL SI,DI MOVQ DI,104(SP) MOVL R10,DI MOVQ 112(SP),DX ADCL DX,DI MOVQ DI,112(SP) MOVL R10,DI MOVQ 120(SP),CX ADCL CX,DI MOVQ DI,120(SP) MOVL R10,DI MOVQ 128(SP),R8 ADCL R8,DI MOVQ DI,128(SP) MOVQ $0XFFFFFFFC,DI MOVQ 136(SP),R9 ADCL R9,DI SARL $16,DI MOVQ DI,R9 XORL $0XFFFFFFFF,R9 ANDQ DI,SI MOVQ 104(SP),AX ANDQ R9,AX ORQ AX,SI ANDQ DI,DX MOVQ 112(SP),AX ANDQ R9,AX ORQ AX,DX ANDQ DI,CX MOVQ 120(SP),AX ANDQ R9,AX ORQ AX,CX ANDQ DI,R8 MOVQ 128(SP),DI ANDQ R9,DI ORQ DI,R8 MOVQ 88(SP),DI MOVQ 96(SP),R9 ADDL 16(R9),SI ADCL 20(R9),DX ADCL 24(R9),CX ADCL 28(R9),R8 MOVL SI,0(DI) MOVL DX,4(DI) MOVL CX,8(DI) MOVL R8,12(DI) MOVQ 32(SP),R11 MOVQ 40(SP),R12 MOVQ 48(SP),R13 MOVQ 56(SP),R14 MOVQ 64(SP),R15 MOVQ 72(SP),BX MOVQ 80(SP),BP MOVQ R11,SP RET lxd-2.0.0/dist/src/golang.org/x/crypto/poly1305/poly1305.go0000644061062106075000000000240012702772344025407 0ustar00stgraberdomain admins00000000000000// Copyright 2012 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 poly1305 implements Poly1305 one-time message authentication code as specified in http://cr.yp.to/mac/poly1305-20050329.pdf. Poly1305 is a fast, one-time authentication function. It is infeasible for an attacker to generate an authenticator for a message without the key. However, a key must only be used for a single message. Authenticating two different messages with the same key allows an attacker to forge authenticators for other messages with the same key. Poly1305 was originally coupled with AES in order to make Poly1305-AES. AES was used with a fixed key in order to generate one-time keys from an nonce. However, in this package AES isn't used and the one-time key is specified directly. */ package poly1305 // import "golang.org/x/crypto/poly1305" import "crypto/subtle" // TagSize is the size, in bytes, of a poly1305 authenticator. const TagSize = 16 // Verify returns true if mac is a valid authenticator for m with the given // key. func Verify(mac *[16]byte, m []byte, key *[32]byte) bool { var tmp [16]byte Sum(&tmp, m, key) return subtle.ConstantTimeCompare(tmp[:], mac[:]) == 1 } lxd-2.0.0/dist/src/golang.org/x/crypto/ocsp/0000755061062106075000000000000012702772344023240 5ustar00stgraberdomain admins00000000000000lxd-2.0.0/dist/src/golang.org/x/crypto/ocsp/ocsp_test.go0000644061062106075000000007413012702772344025577 0ustar00stgraberdomain admins00000000000000// Copyright 2013 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 ocsp import ( "bytes" "crypto" "crypto/sha1" "crypto/x509" "crypto/x509/pkix" "encoding/asn1" "encoding/hex" "math/big" "reflect" "testing" "time" ) func TestOCSPDecode(t *testing.T) { responseBytes, _ := hex.DecodeString(ocspResponseHex) resp, err := ParseResponse(responseBytes, nil) if err != nil { t.Error(err) } expected := Response{ Status: Good, SerialNumber: big.NewInt(0x1d0fa), RevocationReason: Unspecified, ThisUpdate: time.Date(2010, 7, 7, 15, 1, 5, 0, time.UTC), NextUpdate: time.Date(2010, 7, 7, 18, 35, 17, 0, time.UTC), } if !reflect.DeepEqual(resp.ThisUpdate, expected.ThisUpdate) { t.Errorf("resp.ThisUpdate: got %d, want %d", resp.ThisUpdate, expected.ThisUpdate) } if !reflect.DeepEqual(resp.NextUpdate, expected.NextUpdate) { t.Errorf("resp.NextUpdate: got %d, want %d", resp.NextUpdate, expected.NextUpdate) } if resp.Status != expected.Status { t.Errorf("resp.Status: got %d, want %d", resp.Status, expected.Status) } if resp.SerialNumber.Cmp(expected.SerialNumber) != 0 { t.Errorf("resp.SerialNumber: got %x, want %x", resp.SerialNumber, expected.SerialNumber) } if resp.RevocationReason != expected.RevocationReason { t.Errorf("resp.RevocationReason: got %d, want %d", resp.RevocationReason, expected.RevocationReason) } } func TestOCSPDecodeWithoutCert(t *testing.T) { responseBytes, _ := hex.DecodeString(ocspResponseWithoutCertHex) _, err := ParseResponse(responseBytes, nil) if err != nil { t.Error(err) } } func TestOCSPDecodeWithExtensions(t *testing.T) { responseBytes, _ := hex.DecodeString(ocspResponseWithCriticalExtensionHex) _, err := ParseResponse(responseBytes, nil) if err == nil { t.Error(err) } responseBytes, _ = hex.DecodeString(ocspResponseWithExtensionHex) response, err := ParseResponse(responseBytes, nil) if err != nil { t.Fatal(err) } if len(response.Extensions) != 1 { t.Errorf("len(response.Extensions): got %v, want %v", len(response.Extensions), 1) } extensionBytes := response.Extensions[0].Value expectedBytes, _ := hex.DecodeString(ocspExtensionValueHex) if !bytes.Equal(extensionBytes, expectedBytes) { t.Errorf("response.Extensions[0]: got %x, want %x", extensionBytes, expectedBytes) } } func TestOCSPSignature(t *testing.T) { issuerCert, _ := hex.DecodeString(startComHex) issuer, err := x509.ParseCertificate(issuerCert) if err != nil { t.Fatal(err) } response, _ := hex.DecodeString(ocspResponseHex) if _, err := ParseResponse(response, issuer); err != nil { t.Error(err) } } func TestOCSPRequest(t *testing.T) { leafCert, _ := hex.DecodeString(leafCertHex) cert, err := x509.ParseCertificate(leafCert) if err != nil { t.Fatal(err) } issuerCert, _ := hex.DecodeString(issuerCertHex) issuer, err := x509.ParseCertificate(issuerCert) if err != nil { t.Fatal(err) } request, err := CreateRequest(cert, issuer, nil) if err != nil { t.Fatal(err) } expectedBytes, _ := hex.DecodeString(ocspRequestHex) if !bytes.Equal(request, expectedBytes) { t.Errorf("request: got %x, wanted %x", request, expectedBytes) } decodedRequest, err := ParseRequest(expectedBytes) if err != nil { t.Fatal(err) } if decodedRequest.HashAlgorithm != crypto.SHA1 { t.Errorf("request.HashAlgorithm: got %v, want %v", decodedRequest.HashAlgorithm, crypto.SHA1) } var publicKeyInfo struct { Algorithm pkix.AlgorithmIdentifier PublicKey asn1.BitString } _, err = asn1.Unmarshal(issuer.RawSubjectPublicKeyInfo, &publicKeyInfo) if err != nil { t.Fatal(err) } h := sha1.New() h.Write(publicKeyInfo.PublicKey.RightAlign()) issuerKeyHash := h.Sum(nil) h.Reset() h.Write(issuer.RawSubject) issuerNameHash := h.Sum(nil) if got := decodedRequest.IssuerKeyHash; !bytes.Equal(got, issuerKeyHash) { t.Errorf("request.IssuerKeyHash: got %x, want %x", got, issuerKeyHash) } if got := decodedRequest.IssuerNameHash; !bytes.Equal(got, issuerNameHash) { t.Errorf("request.IssuerKeyHash: got %x, want %x", got, issuerNameHash) } if got := decodedRequest.SerialNumber; got.Cmp(cert.SerialNumber) != 0 { t.Errorf("request.SerialNumber: got %x, want %x", got, cert.SerialNumber) } } func TestOCSPResponse(t *testing.T) { leafCert, _ := hex.DecodeString(leafCertHex) leaf, err := x509.ParseCertificate(leafCert) if err != nil { t.Fatal(err) } issuerCert, _ := hex.DecodeString(issuerCertHex) issuer, err := x509.ParseCertificate(issuerCert) if err != nil { t.Fatal(err) } responderCert, _ := hex.DecodeString(responderCertHex) responder, err := x509.ParseCertificate(responderCert) if err != nil { t.Fatal(err) } responderPrivateKeyDER, _ := hex.DecodeString(responderPrivateKeyHex) responderPrivateKey, err := x509.ParsePKCS1PrivateKey(responderPrivateKeyDER) if err != nil { t.Fatal(err) } extensionBytes, _ := hex.DecodeString(ocspExtensionValueHex) extensions := []pkix.Extension{ pkix.Extension{ Id: ocspExtensionOID, Critical: false, Value: extensionBytes, }, } producedAt := time.Now().Truncate(time.Minute) thisUpdate := time.Date(2010, 7, 7, 15, 1, 5, 0, time.UTC) nextUpdate := time.Date(2010, 7, 7, 18, 35, 17, 0, time.UTC) template := Response{ Status: Revoked, SerialNumber: leaf.SerialNumber, ThisUpdate: thisUpdate, NextUpdate: nextUpdate, RevokedAt: thisUpdate, RevocationReason: KeyCompromise, Certificate: responder, ExtraExtensions: extensions, } responseBytes, err := CreateResponse(issuer, responder, template, responderPrivateKey) if err != nil { t.Fatal(err) } resp, err := ParseResponse(responseBytes, nil) if err != nil { t.Fatal(err) } if !reflect.DeepEqual(resp.ThisUpdate, template.ThisUpdate) { t.Errorf("resp.ThisUpdate: got %d, want %d", resp.ThisUpdate, template.ThisUpdate) } if !reflect.DeepEqual(resp.NextUpdate, template.NextUpdate) { t.Errorf("resp.NextUpdate: got %d, want %d", resp.NextUpdate, template.NextUpdate) } if !reflect.DeepEqual(resp.RevokedAt, template.RevokedAt) { t.Errorf("resp.RevokedAt: got %d, want %d", resp.RevokedAt, template.RevokedAt) } if !reflect.DeepEqual(resp.Extensions, template.ExtraExtensions) { t.Errorf("resp.Extensions: got %v, want %v", resp.Extensions, template.ExtraExtensions) } if !resp.ProducedAt.Equal(producedAt) { t.Errorf("resp.ProducedAt: got %d, want %d", resp.ProducedAt, producedAt) } if resp.Status != template.Status { t.Errorf("resp.Status: got %d, want %d", resp.Status, template.Status) } if resp.SerialNumber.Cmp(template.SerialNumber) != 0 { t.Errorf("resp.SerialNumber: got %x, want %x", resp.SerialNumber, template.SerialNumber) } if resp.RevocationReason != template.RevocationReason { t.Errorf("resp.RevocationReason: got %d, want %d", resp.RevocationReason, template.RevocationReason) } } func TestErrorResponse(t *testing.T) { responseBytes, _ := hex.DecodeString(errorResponseHex) _, err := ParseResponse(responseBytes, nil) respErr, ok := err.(ResponseError) if !ok { t.Fatalf("expected ResponseError from ParseResponse but got %#v", err) } if respErr.Status != Malformed { t.Fatalf("expected Malformed status from ParseResponse but got %d", respErr.Status) } } // This OCSP response was taken from Thawte's public OCSP responder. // To recreate: // $ openssl s_client -tls1 -showcerts -servername www.google.com -connect www.google.com:443 // Copy and paste the first certificate into /tmp/cert.crt and the second into // /tmp/intermediate.crt // $ openssl ocsp -issuer /tmp/intermediate.crt -cert /tmp/cert.crt -url http://ocsp.thawte.com -resp_text -respout /tmp/ocsp.der // Then hex encode the result: // $ python -c 'print file("/tmp/ocsp.der", "r").read().encode("hex")' const ocspResponseHex = "308206bc0a0100a08206b5308206b106092b0601050507300101048206a23082069e3081" + "c9a14e304c310b300906035504061302494c31163014060355040a130d5374617274436f" + "6d204c74642e312530230603550403131c5374617274436f6d20436c6173732031204f43" + "5350205369676e6572180f32303130303730373137333531375a30663064303c30090605" + "2b0e03021a050004146568874f40750f016a3475625e1f5c93e5a26d580414eb4234d098" + "b0ab9ff41b6b08f7cc642eef0e2c45020301d0fa8000180f323031303037303731353031" + "30355aa011180f32303130303730373138333531375a300d06092a864886f70d01010505" + "000382010100ab557ff070d1d7cebbb5f0ec91a15c3fed22eb2e1b8244f1b84545f013a4" + "fb46214c5e3fbfbebb8a56acc2b9db19f68fd3c3201046b3824d5ba689f99864328710cb" + "467195eb37d84f539e49f859316b32964dc3e47e36814ce94d6c56dd02733b1d0802f7ff" + "4eebdbbd2927dcf580f16cbc290f91e81b53cb365e7223f1d6e20a88ea064104875e0145" + "672b20fc14829d51ca122f5f5d77d3ad6c83889c55c7dc43680ba2fe3cef8b05dbcabdc0" + "d3e09aaf9725597f8c858c2fa38c0d6aed2e6318194420dd1a1137445d13e1c97ab47896" + "17a4e08925f46f867b72e3a4dc1f08cb870b2b0717f7207faa0ac512e628a029aba7457a" + "e63dcf3281e2162d9349a08204ba308204b6308204b23082039aa003020102020101300d" + "06092a864886f70d010105050030818c310b300906035504061302494c31163014060355" + "040a130d5374617274436f6d204c74642e312b3029060355040b13225365637572652044" + "69676974616c204365727469666963617465205369676e696e6731383036060355040313" + "2f5374617274436f6d20436c6173732031205072696d61727920496e7465726d65646961" + "746520536572766572204341301e170d3037313032353030323330365a170d3132313032" + "333030323330365a304c310b300906035504061302494c31163014060355040a130d5374" + "617274436f6d204c74642e312530230603550403131c5374617274436f6d20436c617373" + "2031204f435350205369676e657230820122300d06092a864886f70d0101010500038201" + "0f003082010a0282010100b9561b4c45318717178084e96e178df2255e18ed8d8ecc7c2b" + "7b51a6c1c2e6bf0aa3603066f132fe10ae97b50e99fa24b83fc53dd2777496387d14e1c3" + "a9b6a4933e2ac12413d085570a95b8147414a0bc007c7bcf222446ef7f1a156d7ea1c577" + "fc5f0facdfd42eb0f5974990cb2f5cefebceef4d1bdc7ae5c1075c5a99a93171f2b0845b" + "4ff0864e973fcfe32f9d7511ff87a3e943410c90a4493a306b6944359340a9ca96f02b66" + "ce67f028df2980a6aaee8d5d5d452b8b0eb93f923cc1e23fcccbdbe7ffcb114d08fa7a6a" + "3c404f825d1a0e715935cf623a8c7b59670014ed0622f6089a9447a7a19010f7fe58f841" + "29a2765ea367824d1c3bb2fda308530203010001a382015c30820158300c0603551d1301" + "01ff04023000300b0603551d0f0404030203a8301e0603551d250417301506082b060105" + "0507030906092b0601050507300105301d0603551d0e0416041445e0a36695414c5dd449" + "bc00e33cdcdbd2343e173081a80603551d230481a030819d8014eb4234d098b0ab9ff41b" + "6b08f7cc642eef0e2c45a18181a47f307d310b300906035504061302494c311630140603" + "55040a130d5374617274436f6d204c74642e312b3029060355040b132253656375726520" + "4469676974616c204365727469666963617465205369676e696e67312930270603550403" + "13205374617274436f6d2043657274696669636174696f6e20417574686f726974798201" + "0a30230603551d12041c301a8618687474703a2f2f7777772e737461727473736c2e636f" + "6d2f302c06096086480186f842010d041f161d5374617274436f6d205265766f63617469" + "6f6e20417574686f72697479300d06092a864886f70d01010505000382010100182d2215" + "8f0fc0291324fa8574c49bb8ff2835085adcbf7b7fc4191c397ab6951328253fffe1e5ec" + "2a7da0d50fca1a404e6968481366939e666c0a6209073eca57973e2fefa9ed1718e8176f" + "1d85527ff522c08db702e3b2b180f1cbff05d98128252cf0f450f7dd2772f4188047f19d" + "c85317366f94bc52d60f453a550af58e308aaab00ced33040b62bf37f5b1ab2a4f7f0f80" + "f763bf4d707bc8841d7ad9385ee2a4244469260b6f2bf085977af9074796048ecc2f9d48" + "a1d24ce16e41a9941568fec5b42771e118f16c106a54ccc339a4b02166445a167902e75e" + "6d8620b0825dcd18a069b90fd851d10fa8effd409deec02860d26d8d833f304b10669b42" const startComHex = "308206343082041ca003020102020118300d06092a864886f70d0101050500307d310b30" + "0906035504061302494c31163014060355040a130d5374617274436f6d204c74642e312b" + "3029060355040b1322536563757265204469676974616c20436572746966696361746520" + "5369676e696e6731293027060355040313205374617274436f6d20436572746966696361" + "74696f6e20417574686f72697479301e170d3037313032343230353431375a170d313731" + "3032343230353431375a30818c310b300906035504061302494c31163014060355040a13" + "0d5374617274436f6d204c74642e312b3029060355040b13225365637572652044696769" + "74616c204365727469666963617465205369676e696e67313830360603550403132f5374" + "617274436f6d20436c6173732031205072696d61727920496e7465726d65646961746520" + "53657276657220434130820122300d06092a864886f70d01010105000382010f00308201" + "0a0282010100b689c6acef09527807ac9263d0f44418188480561f91aee187fa3250b4d3" + "4706f0e6075f700e10f71dc0ce103634855a0f92ac83c6ac58523fba38e8fce7a724e240" + "a60876c0926e9e2a6d4d3f6e61200adb59ded27d63b33e46fefa215118d7cd30a6ed076e" + "3b7087b4f9faebee823c056f92f7a4dc0a301e9373fe07cad75f809d225852ae06da8b87" + "2369b0e42ad8ea83d2bdf371db705a280faf5a387045123f304dcd3baf17e50fcba0a95d" + "48aab16150cb34cd3c5cc30be810c08c9bf0030362feb26c3e720eee1c432ac9480e5739" + "c43121c810c12c87fe5495521f523c31129b7fe7c0a0a559d5e28f3ef0d5a8e1d77031a9" + "c4b3cfaf6d532f06f4a70203010001a38201ad308201a9300f0603551d130101ff040530" + "030101ff300e0603551d0f0101ff040403020106301d0603551d0e04160414eb4234d098" + "b0ab9ff41b6b08f7cc642eef0e2c45301f0603551d230418301680144e0bef1aa4405ba5" + "17698730ca346843d041aef2306606082b06010505070101045a3058302706082b060105" + "05073001861b687474703a2f2f6f6373702e737461727473736c2e636f6d2f6361302d06" + "082b060105050730028621687474703a2f2f7777772e737461727473736c2e636f6d2f73" + "667363612e637274305b0603551d1f045430523027a025a0238621687474703a2f2f7777" + "772e737461727473736c2e636f6d2f73667363612e63726c3027a025a023862168747470" + "3a2f2f63726c2e737461727473736c2e636f6d2f73667363612e63726c3081800603551d" + "20047930773075060b2b0601040181b5370102013066302e06082b060105050702011622" + "687474703a2f2f7777772e737461727473736c2e636f6d2f706f6c6963792e7064663034" + "06082b060105050702011628687474703a2f2f7777772e737461727473736c2e636f6d2f" + "696e7465726d6564696174652e706466300d06092a864886f70d01010505000382020100" + "2109493ea5886ee00b8b48da314d8ff75657a2e1d36257e9b556f38545753be5501f048b" + "e6a05a3ee700ae85d0fbff200364cbad02e1c69172f8a34dd6dee8cc3fa18aa2e37c37a7" + "c64f8f35d6f4d66e067bdd21d9cf56ffcb302249fe8904f385e5aaf1e71fe875904dddf9" + "46f74234f745580c110d84b0c6da5d3ef9019ee7e1da5595be741c7bfc4d144fac7e5547" + "7d7bf4a50d491e95e8f712c1ccff76a62547d0f37535be97b75816ebaa5c786fec5330af" + "ea044dcca902e3f0b60412f630b1113d904e5664d7dc3c435f7339ef4baf87ebf6fe6888" + "4472ead207c669b0c1a18bef1749d761b145485f3b2021e95bb2ccf4d7e931f50b15613b" + "7a94e3ebd9bc7f94ae6ae3626296a8647cb887f399327e92a252bebbf865cfc9f230fc8b" + "c1c2a696d75f89e15c3480f58f47072fb491bfb1a27e5f4b5ad05b9f248605515a690365" + "434971c5e06f94346bf61bd8a9b04c7e53eb8f48dfca33b548fa364a1a53a6330cd089cd" + "4915cd89313c90c072d7654b52358a461144b93d8e2865a63e799e5c084429adb035112e" + "214eb8d2e7103e5d8483b3c3c2e4d2c6fd094b7409ddf1b3d3193e800da20b19f038e7c5" + "c2afe223db61e29d5c6e2089492e236ab262c145b49faf8ba7f1223bf87de290d07a19fb" + "4a4ce3d27d5f4a8303ed27d6239e6b8db459a2d9ef6c8229dd75193c3f4c108defbb7527" + "d2ae83a7a8ce5ba7" const ocspResponseWithoutCertHex = "308201d40a0100a08201cd308201c906092b0601050507300101048201ba3082" + "01b630819fa2160414884451ff502a695e2d88f421bad90cf2cecbea7c180f3230313330" + "3631383037323434335a30743072304a300906052b0e03021a0500041448b60d38238df8" + "456e4ee5843ea394111802979f0414884451ff502a695e2d88f421bad90cf2cecbea7c02" + "1100f78b13b946fc9635d8ab49de9d2148218000180f3230313330363138303732343433" + "5aa011180f32303133303632323037323434335a300d06092a864886f70d010105050003" + "82010100103e18b3d297a5e7a6c07a4fc52ac46a15c0eba96f3be17f0ffe84de5b8c8e05" + "5a8f577586a849dc4abd6440eb6fedde4622451e2823c1cbf3558b4e8184959c9fe96eff" + "8bc5f95866c58c6d087519faabfdae37e11d9874f1bc0db292208f645dd848185e4dd38b" + "6a8547dfa7b74d514a8470015719064d35476b95bebb03d4d2845c5ca15202d2784878f2" + "0f904c24f09736f044609e9c271381713400e563023d212db422236440c6f377bbf24b2b" + "9e7dec8698e36a8df68b7592ad3489fb2937afb90eb85d2aa96b81c94c25057dbd4759d9" + "20a1a65c7f0b6427a224b3c98edd96b9b61f706099951188b0289555ad30a216fb774651" + "5a35fca2e054dfa8" // PKIX nonce extension var ocspExtensionOID = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 48, 1, 2} var ocspExtensionValueHex = "0403000000" const ocspResponseWithCriticalExtensionHex = "308204fe0a0100a08204f7308204f306092b0601050507300101048204e4308204e03081" + "dba003020100a11b3019311730150603550403130e4f43535020526573706f6e64657218" + "0f32303136303130343137303130305a3081a53081a23049300906052b0e03021a050004" + "14c0fe0278fc99188891b3f212e9c7e1b21ab7bfc004140dfc1df0a9e0f01ce7f2b21317" + "7e6f8d157cd4f60210017f77deb3bcbb235d44ccc7dba62e72a116180f32303130303730" + "373135303130355aa0030a0101180f32303130303730373135303130355aa011180f3230" + "3130303730373138333531375aa1193017301506092b06010505073001020101ff040504" + "03000000300d06092a864886f70d01010b0500038201010031c730ca60a7a0d92d8e4010" + "911b469de95b4d27e89de6537552436237967694f76f701cf6b45c932bd308bca4a8d092" + "5c604ba94796903091d9e6c000178e72c1f0a24a277dd262835af5d17d3f9d7869606c9f" + "e7c8e708a41645699895beee38bfa63bb46296683761c5d1d65439b8ab868dc3017c9eeb" + "b70b82dbf3a31c55b457d48bb9e82b335ed49f445042eaf606b06a3e0639824924c89c63" + "eccddfe85e6694314138b2536f5e15e07085d0f6e26d4b2f8244bab0d70de07283ac6384" + "a0501fc3dea7cf0adfd4c7f34871080900e252ddc403e3f0265f2a704af905d3727504ed" + "28f3214a219d898a022463c78439799ca81c8cbafdbcec34ea937cd6a08202ea308202e6" + "308202e2308201caa003020102020101300d06092a864886f70d01010b05003019311730" + "150603550403130e4f43535020526573706f6e646572301e170d31353031333031353530" + "33335a170d3136303133303135353033335a3019311730150603550403130e4f43535020" + "526573706f6e64657230820122300d06092a864886f70d01010105000382010f00308201" + "0a0282010100e8155f2d3e6f2e8d14c62a788bd462f9f844e7a6977c83ef1099f0f6616e" + "c5265b56f356e62c5400f0b06a2e7945a82752c636df32a895152d6074df1701dc6ccfbc" + "bec75a70bd2b55ae2be7e6cad3b5fd4cd5b7790ab401a436d3f5f346074ffde8a99d5b72" + "3350f0a112076614b12ef79c78991b119453445acf2416ab0046b540db14c9fc0f27b898" + "9ad0f63aa4b8aefc91aa8a72160c36307c60fec78a93d3fddf4259902aa77e7332971c7d" + "285b6a04f648993c6922a3e9da9adf5f81508c3228791843e5d49f24db2f1290bafd97e6" + "55b1049a199f652cd603c4fafa330c390b0da78fbbc67e8fa021cbd74eb96222b12ace31" + "a77dcf920334dc94581b0203010001a3353033300e0603551d0f0101ff04040302078030" + "130603551d25040c300a06082b06010505070309300c0603551d130101ff04023000300d" + "06092a864886f70d01010b05000382010100718012761b5063e18f0dc44644d8e6ab8612" + "31c15fd5357805425d82aec1de85bf6d3e30fce205e3e3b8b795bbe52e40a439286d2288" + "9064f4aeeb150359b9425f1da51b3a5c939018555d13ac42c565a0603786a919328f3267" + "09dce52c22ad958ecb7873b9771d1148b1c4be2efe80ba868919fc9f68b6090c2f33c156" + "d67156e42766a50b5d51e79637b7e58af74c2a951b1e642fa7741fec982cc937de37eff5" + "9e2005d5939bfc031589ca143e6e8ab83f40ee08cc20a6b4a95a318352c28d18528dcaf9" + "66705de17afa19d6e8ae91ddf33179d16ebb6ac2c69cae8373d408ebf8c55308be6c04d9" + "3a25439a94299a65a709756c7a3e568be049d5c38839" const ocspResponseWithExtensionHex = "308204fb0a0100a08204f4308204f006092b0601050507300101048204e1308204dd3081" + "d8a003020100a11b3019311730150603550403130e4f43535020526573706f6e64657218" + "0f32303136303130343136353930305a3081a230819f3049300906052b0e03021a050004" + "14c0fe0278fc99188891b3f212e9c7e1b21ab7bfc004140dfc1df0a9e0f01ce7f2b21317" + "7e6f8d157cd4f60210017f77deb3bcbb235d44ccc7dba62e72a116180f32303130303730" + "373135303130355aa0030a0101180f32303130303730373135303130355aa011180f3230" + "3130303730373138333531375aa1163014301206092b0601050507300102040504030000" + "00300d06092a864886f70d01010b05000382010100c09a33e0b2324c852421bb83f85ac9" + "9113f5426012bd2d2279a8166e9241d18a33c870894250622ffc7ed0c4601b16d624f90b" + "779265442cdb6868cf40ab304ab4b66e7315ed02cf663b1601d1d4751772b31bc299db23" + "9aebac78ed6797c06ed815a7a8d18d63cfbb609cafb47ec2e89e37db255216eb09307848" + "d01be0a3e943653c78212b96ff524b74c9ec456b17cdfb950cc97645c577b2e09ff41dde" + "b03afb3adaa381cc0f7c1d95663ef22a0f72f2c45613ae8e2b2d1efc96e8463c7d1d8a1d" + "7e3b35df8fe73a301fc3f804b942b2b3afa337ff105fc1462b7b1c1d75eb4566c8665e59" + "f80393b0adbf8004ff6c3327ed34f007cb4a3348a7d55e06e3a08202ea308202e6308202" + "e2308201caa003020102020101300d06092a864886f70d01010b05003019311730150603" + "550403130e4f43535020526573706f6e646572301e170d3135303133303135353033335a" + "170d3136303133303135353033335a3019311730150603550403130e4f43535020526573" + "706f6e64657230820122300d06092a864886f70d01010105000382010f003082010a0282" + "010100e8155f2d3e6f2e8d14c62a788bd462f9f844e7a6977c83ef1099f0f6616ec5265b" + "56f356e62c5400f0b06a2e7945a82752c636df32a895152d6074df1701dc6ccfbcbec75a" + "70bd2b55ae2be7e6cad3b5fd4cd5b7790ab401a436d3f5f346074ffde8a99d5b723350f0" + "a112076614b12ef79c78991b119453445acf2416ab0046b540db14c9fc0f27b8989ad0f6" + "3aa4b8aefc91aa8a72160c36307c60fec78a93d3fddf4259902aa77e7332971c7d285b6a" + "04f648993c6922a3e9da9adf5f81508c3228791843e5d49f24db2f1290bafd97e655b104" + "9a199f652cd603c4fafa330c390b0da78fbbc67e8fa021cbd74eb96222b12ace31a77dcf" + "920334dc94581b0203010001a3353033300e0603551d0f0101ff04040302078030130603" + "551d25040c300a06082b06010505070309300c0603551d130101ff04023000300d06092a" + "864886f70d01010b05000382010100718012761b5063e18f0dc44644d8e6ab861231c15f" + "d5357805425d82aec1de85bf6d3e30fce205e3e3b8b795bbe52e40a439286d22889064f4" + "aeeb150359b9425f1da51b3a5c939018555d13ac42c565a0603786a919328f326709dce5" + "2c22ad958ecb7873b9771d1148b1c4be2efe80ba868919fc9f68b6090c2f33c156d67156" + "e42766a50b5d51e79637b7e58af74c2a951b1e642fa7741fec982cc937de37eff59e2005" + "d5939bfc031589ca143e6e8ab83f40ee08cc20a6b4a95a318352c28d18528dcaf966705d" + "e17afa19d6e8ae91ddf33179d16ebb6ac2c69cae8373d408ebf8c55308be6c04d93a2543" + "9a94299a65a709756c7a3e568be049d5c38839" const ocspRequestHex = "3051304f304d304b3049300906052b0e03021a05000414c0fe0278fc99188891b3f212e9" + "c7e1b21ab7bfc004140dfc1df0a9e0f01ce7f2b213177e6f8d157cd4f60210017f77deb3" + "bcbb235d44ccc7dba62e72" const leafCertHex = "308203c830820331a0030201020210017f77deb3bcbb235d44ccc7dba62e72300d06092a" + "864886f70d01010505003081ba311f301d060355040a1316566572695369676e20547275" + "7374204e6574776f726b31173015060355040b130e566572695369676e2c20496e632e31" + "333031060355040b132a566572695369676e20496e7465726e6174696f6e616c20536572" + "766572204341202d20436c617373203331493047060355040b13407777772e7665726973" + "69676e2e636f6d2f43505320496e636f72702e6279205265662e204c494142494c495459" + "204c54442e286329393720566572695369676e301e170d3132303632313030303030305a" + "170d3133313233313233353935395a3068310b3009060355040613025553311330110603" + "550408130a43616c69666f726e6961311230100603550407130950616c6f20416c746f31" + "173015060355040a130e46616365626f6f6b2c20496e632e311730150603550403140e2a" + "2e66616365626f6f6b2e636f6d30819f300d06092a864886f70d010101050003818d0030" + "818902818100ae94b171e2deccc1693e051063240102e0689ae83c39b6b3e74b97d48d7b" + "23689100b0b496ee62f0e6d356bcf4aa0f50643402f5d1766aa972835a7564723f39bbef" + "5290ded9bcdbf9d3d55dfad23aa03dc604c54d29cf1d4b3bdbd1a809cfae47b44c7eae17" + "c5109bee24a9cf4a8d911bb0fd0415ae4c3f430aa12a557e2ae10203010001a382011e30" + "82011a30090603551d130402300030440603551d20043d303b3039060b6086480186f845" + "01071703302a302806082b06010505070201161c68747470733a2f2f7777772e76657269" + "7369676e2e636f6d2f727061303c0603551d1f043530333031a02fa02d862b687474703a" + "2f2f535652496e746c2d63726c2e766572697369676e2e636f6d2f535652496e746c2e63" + "726c301d0603551d250416301406082b0601050507030106082b06010505070302300b06" + "03551d0f0404030205a0303406082b0601050507010104283026302406082b0601050507" + "30018618687474703a2f2f6f6373702e766572697369676e2e636f6d30270603551d1104" + "20301e820e2a2e66616365626f6f6b2e636f6d820c66616365626f6f6b2e636f6d300d06" + "092a864886f70d0101050500038181005b6c2b75f8ed30aa51aad36aba595e555141951f" + "81a53b447910ac1f76ff78fc2781616b58f3122afc1c87010425e9ed43df1a7ba6498060" + "67e2688af03db58c7df4ee03309a6afc247ccb134dc33e54c6bc1d5133a532a73273b1d7" + "9cadc08e7e1a83116d34523340b0305427a21742827c98916698ee7eaf8c3bdd71700817" const issuerCertHex = "30820383308202eca003020102021046fcebbab4d02f0f926098233f93078f300d06092a" + "864886f70d0101050500305f310b300906035504061302555331173015060355040a130e" + "566572695369676e2c20496e632e31373035060355040b132e436c617373203320507562" + "6c6963205072696d6172792043657274696669636174696f6e20417574686f7269747930" + "1e170d3937303431373030303030305a170d3136313032343233353935395a3081ba311f" + "301d060355040a1316566572695369676e205472757374204e6574776f726b3117301506" + "0355040b130e566572695369676e2c20496e632e31333031060355040b132a5665726953" + "69676e20496e7465726e6174696f6e616c20536572766572204341202d20436c61737320" + "3331493047060355040b13407777772e766572697369676e2e636f6d2f43505320496e63" + "6f72702e6279205265662e204c494142494c495459204c54442e28632939372056657269" + "5369676e30819f300d06092a864886f70d010101050003818d0030818902818100d88280" + "e8d619027d1f85183925a2652be1bfd405d3bce6363baaf04c6c5bb6e7aa3c734555b2f1" + "bdea9742ed9a340a15d4a95cf54025ddd907c132b2756cc4cabba3fe56277143aa63f530" + "3e9328e5faf1093bf3b74d4e39f75c495ab8c11dd3b28afe70309542cbfe2b518b5a3c3a" + "f9224f90b202a7539c4f34e7ab04b27b6f0203010001a381e33081e0300f0603551d1304" + "0830060101ff02010030440603551d20043d303b3039060b6086480186f8450107010130" + "2a302806082b06010505070201161c68747470733a2f2f7777772e766572697369676e2e" + "636f6d2f43505330340603551d25042d302b06082b0601050507030106082b0601050507" + "030206096086480186f8420401060a6086480186f845010801300b0603551d0f04040302" + "0106301106096086480186f842010104040302010630310603551d1f042a30283026a024" + "a0228620687474703a2f2f63726c2e766572697369676e2e636f6d2f706361332e63726c" + "300d06092a864886f70d010105050003818100408e4997968a73dd8e4def3e61b7caa062" + "adf40e0abb753de26ed82cc7bff4b98c369bcaa2d09c724639f6a682036511c4bcbf2da6" + "f5d93b0ab598fab378b91ef22b4c62d5fdb27a1ddf33fd73f9a5d82d8c2aead1fcb028b6" + "e94948134b838a1b487b24f738de6f4154b8ab576b06dfc7a2d4a9f6f136628088f28b75" + "d68071" // Key and certificate for the OCSP responder were not taken from the Thawte // responder, since CreateResponse requires that we have the private key. // Instead, they were generated randomly. const responderPrivateKeyHex = "308204a40201000282010100e8155f2d3e6f2e8d14c62a788bd462f9f844e7a6977c83ef" + "1099f0f6616ec5265b56f356e62c5400f0b06a2e7945a82752c636df32a895152d6074df" + "1701dc6ccfbcbec75a70bd2b55ae2be7e6cad3b5fd4cd5b7790ab401a436d3f5f346074f" + "fde8a99d5b723350f0a112076614b12ef79c78991b119453445acf2416ab0046b540db14" + "c9fc0f27b8989ad0f63aa4b8aefc91aa8a72160c36307c60fec78a93d3fddf4259902aa7" + "7e7332971c7d285b6a04f648993c6922a3e9da9adf5f81508c3228791843e5d49f24db2f" + "1290bafd97e655b1049a199f652cd603c4fafa330c390b0da78fbbc67e8fa021cbd74eb9" + "6222b12ace31a77dcf920334dc94581b02030100010282010100bcf0b93d7238bda329a8" + "72e7149f61bcb37c154330ccb3f42a85c9002c2e2bdea039d77d8581cd19bed94078794e" + "56293d601547fc4bf6a2f9002fe5772b92b21b254403b403585e3130cc99ccf08f0ef81a" + "575b38f597ba4660448b54f44bfbb97072b5a2bf043bfeca828cf7741d13698e3f38162b" + "679faa646b82abd9a72c5c7d722c5fc577a76d2c2daac588accad18516d1bbad10b0dfa2" + "05cfe246b59e28608a43942e1b71b0c80498075121de5b900d727c31c42c78cf1db5c0aa" + "5b491e10ea4ed5c0962aaf2ae025dd81fa4ce490d9d6b4a4465411d8e542fc88617e5695" + "1aa4fc8ea166f2b4d0eb89ef17f2b206bd5f1014bf8fe0e71fe62f2cccf102818100f2dc" + "ddf878d553286daad68bac4070a82ffec3dc4666a2750f47879eec913f91836f1d976b60" + "daf9356e078446dafab5bd2e489e5d64f8572ba24a4ba4f3729b5e106c4dd831cc2497a7" + "e6c7507df05cb64aeb1bbc81c1e340d58b5964cf39cff84ea30c29ec5d3f005ee1362698" + "07395037955955655292c3e85f6187fa1f9502818100f4a33c102630840705f8c778a47b" + "87e8da31e68809af981ac5e5999cf1551685d761cdf0d6520361b99aebd5777a940fa64d" + "327c09fa63746fbb3247ec73a86edf115f1fe5c83598db803881ade71c33c6e956118345" + "497b98b5e07bb5be75971465ec78f2f9467e1b74956ca9d4c7c3e314e742a72d8b33889c" + "6c093a466cef0281801d3df0d02124766dd0be98349b19eb36a508c4e679e793ba0a8bef" + "4d786888c1e9947078b1ea28938716677b4ad8c5052af12eb73ac194915264a913709a0b" + "7b9f98d4a18edd781a13d49899f91c20dbd8eb2e61d991ba19b5cdc08893f5cb9d39e5a6" + "0629ea16d426244673b1b3ee72bd30e41fac8395acac40077403de5efd028180050731dd" + "d71b1a2b96c8d538ba90bb6b62c8b1c74c03aae9a9f59d21a7a82b0d572ef06fa9c807bf" + "c373d6b30d809c7871df96510c577421d9860c7383fda0919ece19996b3ca13562159193" + "c0c246471e287f975e8e57034e5136aaf44254e2650def3d51292474c515b1588969112e" + "0a85cc77073e9d64d2c2fc497844284b02818100d71d63eabf416cf677401ebf965f8314" + "120b568a57dd3bd9116c629c40dc0c6948bab3a13cc544c31c7da40e76132ef5dd3f7534" + "45a635930c74326ae3df0edd1bfb1523e3aa259873ac7cf1ac31151ec8f37b528c275622" + "48f99b8bed59fd4da2576aa6ee20d93a684900bf907e80c66d6e2261ae15e55284b4ed9d" + "6bdaa059" const responderCertHex = "308202e2308201caa003020102020101300d06092a864886f70d01010b05003019311730" + "150603550403130e4f43535020526573706f6e646572301e170d31353031333031353530" + "33335a170d3136303133303135353033335a3019311730150603550403130e4f43535020" + "526573706f6e64657230820122300d06092a864886f70d01010105000382010f00308201" + "0a0282010100e8155f2d3e6f2e8d14c62a788bd462f9f844e7a6977c83ef1099f0f6616e" + "c5265b56f356e62c5400f0b06a2e7945a82752c636df32a895152d6074df1701dc6ccfbc" + "bec75a70bd2b55ae2be7e6cad3b5fd4cd5b7790ab401a436d3f5f346074ffde8a99d5b72" + "3350f0a112076614b12ef79c78991b119453445acf2416ab0046b540db14c9fc0f27b898" + "9ad0f63aa4b8aefc91aa8a72160c36307c60fec78a93d3fddf4259902aa77e7332971c7d" + "285b6a04f648993c6922a3e9da9adf5f81508c3228791843e5d49f24db2f1290bafd97e6" + "55b1049a199f652cd603c4fafa330c390b0da78fbbc67e8fa021cbd74eb96222b12ace31" + "a77dcf920334dc94581b0203010001a3353033300e0603551d0f0101ff04040302078030" + "130603551d25040c300a06082b06010505070309300c0603551d130101ff04023000300d" + "06092a864886f70d01010b05000382010100718012761b5063e18f0dc44644d8e6ab8612" + "31c15fd5357805425d82aec1de85bf6d3e30fce205e3e3b8b795bbe52e40a439286d2288" + "9064f4aeeb150359b9425f1da51b3a5c939018555d13ac42c565a0603786a919328f3267" + "09dce52c22ad958ecb7873b9771d1148b1c4be2efe80ba868919fc9f68b6090c2f33c156" + "d67156e42766a50b5d51e79637b7e58af74c2a951b1e642fa7741fec982cc937de37eff5" + "9e2005d5939bfc031589ca143e6e8ab83f40ee08cc20a6b4a95a318352c28d18528dcaf9" + "66705de17afa19d6e8ae91ddf33179d16ebb6ac2c69cae8373d408ebf8c55308be6c04d9" + "3a25439a94299a65a709756c7a3e568be049d5c38839" const errorResponseHex = "30030a0101" lxd-2.0.0/dist/src/golang.org/x/crypto/ocsp/ocsp.go0000644061062106075000000005146612702772344024547 0ustar00stgraberdomain admins00000000000000// Copyright 2013 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 ocsp parses OCSP responses as specified in RFC 2560. OCSP responses // are signed messages attesting to the validity of a certificate for a small // period of time. This is used to manage revocation for X.509 certificates. package ocsp // import "golang.org/x/crypto/ocsp" import ( "crypto" "crypto/ecdsa" "crypto/elliptic" "crypto/rand" "crypto/rsa" "crypto/sha1" "crypto/x509" "crypto/x509/pkix" "encoding/asn1" "errors" "math/big" "strconv" "time" ) var idPKIXOCSPBasic = asn1.ObjectIdentifier([]int{1, 3, 6, 1, 5, 5, 7, 48, 1, 1}) // ResponseStatus contains the result of an OCSP request. See // https://tools.ietf.org/html/rfc6960#section-2.3 type ResponseStatus int const ( Success ResponseStatus = 0 Malformed ResponseStatus = 1 InternalError ResponseStatus = 2 TryLater ResponseStatus = 3 // Status code four is ununsed in OCSP. See // https://tools.ietf.org/html/rfc6960#section-4.2.1 SignatureRequired ResponseStatus = 5 Unauthorized ResponseStatus = 6 ) func (r ResponseStatus) String() string { switch r { case Success: return "success" case Malformed: return "malformed" case InternalError: return "internal error" case TryLater: return "try later" case SignatureRequired: return "signature required" case Unauthorized: return "unauthorized" default: return "unknown OCSP status: " + strconv.Itoa(int(r)) } } // ResponseError is an error that may be returned by ParseResponse to indicate // that the response itself is an error, not just that its indicating that a // certificate is revoked, unknown, etc. type ResponseError struct { Status ResponseStatus } func (r ResponseError) Error() string { return "ocsp: error from server: " + r.Status.String() } // These are internal structures that reflect the ASN.1 structure of an OCSP // response. See RFC 2560, section 4.2. type certID struct { HashAlgorithm pkix.AlgorithmIdentifier NameHash []byte IssuerKeyHash []byte SerialNumber *big.Int } // https://tools.ietf.org/html/rfc2560#section-4.1.1 type ocspRequest struct { TBSRequest tbsRequest } type tbsRequest struct { Version int `asn1:"explicit,tag:0,default:0,optional"` RequestorName pkix.RDNSequence `asn1:"explicit,tag:1,optional"` RequestList []request } type request struct { Cert certID } type responseASN1 struct { Status asn1.Enumerated Response responseBytes `asn1:"explicit,tag:0,optional"` } type responseBytes struct { ResponseType asn1.ObjectIdentifier Response []byte } type basicResponse struct { TBSResponseData responseData SignatureAlgorithm pkix.AlgorithmIdentifier Signature asn1.BitString Certificates []asn1.RawValue `asn1:"explicit,tag:0,optional"` } type responseData struct { Raw asn1.RawContent Version int `asn1:"optional,default:1,explicit,tag:0"` RawResponderName asn1.RawValue `asn1:"optional,explicit,tag:1"` KeyHash []byte `asn1:"optional,explicit,tag:2"` ProducedAt time.Time `asn1:"generalized"` Responses []singleResponse } type singleResponse struct { CertID certID Good asn1.Flag `asn1:"tag:0,optional"` Revoked revokedInfo `asn1:"tag:1,optional"` Unknown asn1.Flag `asn1:"tag:2,optional"` ThisUpdate time.Time `asn1:"generalized"` NextUpdate time.Time `asn1:"generalized,explicit,tag:0,optional"` SingleExtensions []pkix.Extension `asn1:"explicit,tag:1,optional"` } type revokedInfo struct { RevocationTime time.Time `asn1:"generalized"` Reason asn1.Enumerated `asn1:"explicit,tag:0,optional"` } var ( oidSignatureMD2WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 2} oidSignatureMD5WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 4} oidSignatureSHA1WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 5} oidSignatureSHA256WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 11} oidSignatureSHA384WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 12} oidSignatureSHA512WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 13} oidSignatureDSAWithSHA1 = asn1.ObjectIdentifier{1, 2, 840, 10040, 4, 3} oidSignatureDSAWithSHA256 = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 3, 2} oidSignatureECDSAWithSHA1 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 1} oidSignatureECDSAWithSHA256 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 2} oidSignatureECDSAWithSHA384 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 3} oidSignatureECDSAWithSHA512 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 4} ) var hashOIDs = map[crypto.Hash]asn1.ObjectIdentifier{ crypto.SHA1: asn1.ObjectIdentifier([]int{1, 3, 14, 3, 2, 26}), crypto.SHA256: asn1.ObjectIdentifier([]int{2, 16, 840, 1, 101, 3, 4, 2, 1}), crypto.SHA384: asn1.ObjectIdentifier([]int{2, 16, 840, 1, 101, 3, 4, 2, 2}), crypto.SHA512: asn1.ObjectIdentifier([]int{2, 16, 840, 1, 101, 3, 4, 2, 3}), } // TODO(rlb): This is also from crypto/x509, so same comment as AGL's below var signatureAlgorithmDetails = []struct { algo x509.SignatureAlgorithm oid asn1.ObjectIdentifier pubKeyAlgo x509.PublicKeyAlgorithm hash crypto.Hash }{ {x509.MD2WithRSA, oidSignatureMD2WithRSA, x509.RSA, crypto.Hash(0) /* no value for MD2 */}, {x509.MD5WithRSA, oidSignatureMD5WithRSA, x509.RSA, crypto.MD5}, {x509.SHA1WithRSA, oidSignatureSHA1WithRSA, x509.RSA, crypto.SHA1}, {x509.SHA256WithRSA, oidSignatureSHA256WithRSA, x509.RSA, crypto.SHA256}, {x509.SHA384WithRSA, oidSignatureSHA384WithRSA, x509.RSA, crypto.SHA384}, {x509.SHA512WithRSA, oidSignatureSHA512WithRSA, x509.RSA, crypto.SHA512}, {x509.DSAWithSHA1, oidSignatureDSAWithSHA1, x509.DSA, crypto.SHA1}, {x509.DSAWithSHA256, oidSignatureDSAWithSHA256, x509.DSA, crypto.SHA256}, {x509.ECDSAWithSHA1, oidSignatureECDSAWithSHA1, x509.ECDSA, crypto.SHA1}, {x509.ECDSAWithSHA256, oidSignatureECDSAWithSHA256, x509.ECDSA, crypto.SHA256}, {x509.ECDSAWithSHA384, oidSignatureECDSAWithSHA384, x509.ECDSA, crypto.SHA384}, {x509.ECDSAWithSHA512, oidSignatureECDSAWithSHA512, x509.ECDSA, crypto.SHA512}, } // TODO(rlb): This is also from crypto/x509, so same comment as AGL's below func signingParamsForPublicKey(pub interface{}, requestedSigAlgo x509.SignatureAlgorithm) (hashFunc crypto.Hash, sigAlgo pkix.AlgorithmIdentifier, err error) { var pubType x509.PublicKeyAlgorithm switch pub := pub.(type) { case *rsa.PublicKey: pubType = x509.RSA hashFunc = crypto.SHA256 sigAlgo.Algorithm = oidSignatureSHA256WithRSA sigAlgo.Parameters = asn1.RawValue{ Tag: 5, } case *ecdsa.PublicKey: pubType = x509.ECDSA switch pub.Curve { case elliptic.P224(), elliptic.P256(): hashFunc = crypto.SHA256 sigAlgo.Algorithm = oidSignatureECDSAWithSHA256 case elliptic.P384(): hashFunc = crypto.SHA384 sigAlgo.Algorithm = oidSignatureECDSAWithSHA384 case elliptic.P521(): hashFunc = crypto.SHA512 sigAlgo.Algorithm = oidSignatureECDSAWithSHA512 default: err = errors.New("x509: unknown elliptic curve") } default: err = errors.New("x509: only RSA and ECDSA keys supported") } if err != nil { return } if requestedSigAlgo == 0 { return } found := false for _, details := range signatureAlgorithmDetails { if details.algo == requestedSigAlgo { if details.pubKeyAlgo != pubType { err = errors.New("x509: requested SignatureAlgorithm does not match private key type") return } sigAlgo.Algorithm, hashFunc = details.oid, details.hash if hashFunc == 0 { err = errors.New("x509: cannot sign with hash function requested") return } found = true break } } if !found { err = errors.New("x509: unknown SignatureAlgorithm") } return } // TODO(agl): this is taken from crypto/x509 and so should probably be exported // from crypto/x509 or crypto/x509/pkix. func getSignatureAlgorithmFromOID(oid asn1.ObjectIdentifier) x509.SignatureAlgorithm { for _, details := range signatureAlgorithmDetails { if oid.Equal(details.oid) { return details.algo } } return x509.UnknownSignatureAlgorithm } // TODO(rlb): This is not taken from crypto/x509, but it's of the same general form. func getHashAlgorithmFromOID(target asn1.ObjectIdentifier) crypto.Hash { for hash, oid := range hashOIDs { if oid.Equal(target) { return hash } } return crypto.Hash(0) } // This is the exposed reflection of the internal OCSP structures. // The status values that can be expressed in OCSP. See RFC 6960. const ( // Good means that the certificate is valid. Good = iota // Revoked means that the certificate has been deliberately revoked. Revoked // Unknown means that the OCSP responder doesn't know about the certificate. Unknown // ServerFailed is unused and was never used (see // https://go-review.googlesource.com/#/c/18944). ParseResponse will // return a ResponseError when an error response is parsed. ServerFailed ) // The enumerated reasons for revoking a certificate. See RFC 5280. const ( Unspecified = iota KeyCompromise = iota CACompromise = iota AffiliationChanged = iota Superseded = iota CessationOfOperation = iota CertificateHold = iota _ = iota RemoveFromCRL = iota PrivilegeWithdrawn = iota AACompromise = iota ) // Request represents an OCSP request. See RFC 6960. type Request struct { HashAlgorithm crypto.Hash IssuerNameHash []byte IssuerKeyHash []byte SerialNumber *big.Int } // Response represents an OCSP response containing a single SingleResponse. See // RFC 6960. type Response struct { // Status is one of {Good, Revoked, Unknown} Status int SerialNumber *big.Int ProducedAt, ThisUpdate, NextUpdate, RevokedAt time.Time RevocationReason int Certificate *x509.Certificate // TBSResponseData contains the raw bytes of the signed response. If // Certificate is nil then this can be used to verify Signature. TBSResponseData []byte Signature []byte SignatureAlgorithm x509.SignatureAlgorithm // Extensions contains raw X.509 extensions from the singleExtensions field // of the OCSP response. When parsing certificates, this can be used to // extract non-critical extensions that are not parsed by this package. When // marshaling OCSP responses, the Extensions field is ignored, see // ExtraExtensions. Extensions []pkix.Extension // ExtraExtensions contains extensions to be copied, raw, into any marshaled // OCSP response (in the singleExtensions field). Values override any // extensions that would otherwise be produced based on the other fields. The // ExtraExtensions field is not populated when parsing certificates, see // Extensions. ExtraExtensions []pkix.Extension } // These are pre-serialized error responses for the various non-success codes // defined by OCSP. The Unauthorized code in particular can be used by an OCSP // responder that supports only pre-signed responses as a response to requests // for certificates with unknown status. See RFC 5019. var ( MalformedRequestErrorResponse = []byte{0x30, 0x03, 0x0A, 0x01, 0x01} InternalErrorErrorResponse = []byte{0x30, 0x03, 0x0A, 0x01, 0x02} TryLaterErrorResponse = []byte{0x30, 0x03, 0x0A, 0x01, 0x03} SigRequredErrorResponse = []byte{0x30, 0x03, 0x0A, 0x01, 0x05} UnauthorizedErrorResponse = []byte{0x30, 0x03, 0x0A, 0x01, 0x06} ) // CheckSignatureFrom checks that the signature in resp is a valid signature // from issuer. This should only be used if resp.Certificate is nil. Otherwise, // the OCSP response contained an intermediate certificate that created the // signature. That signature is checked by ParseResponse and only // resp.Certificate remains to be validated. func (resp *Response) CheckSignatureFrom(issuer *x509.Certificate) error { return issuer.CheckSignature(resp.SignatureAlgorithm, resp.TBSResponseData, resp.Signature) } // ParseError results from an invalid OCSP response. type ParseError string func (p ParseError) Error() string { return string(p) } // ParseRequest parses an OCSP request in DER form. It only supports // requests for a single certificate. Signed requests are not supported. // If a request includes a signature, it will result in a ParseError. func ParseRequest(bytes []byte) (*Request, error) { var req ocspRequest rest, err := asn1.Unmarshal(bytes, &req) if err != nil { return nil, err } if len(rest) > 0 { return nil, ParseError("trailing data in OCSP request") } if len(req.TBSRequest.RequestList) == 0 { return nil, ParseError("OCSP request contains no request body") } innerRequest := req.TBSRequest.RequestList[0] hashFunc := getHashAlgorithmFromOID(innerRequest.Cert.HashAlgorithm.Algorithm) if hashFunc == crypto.Hash(0) { return nil, ParseError("OCSP request uses unknown hash function") } return &Request{ HashAlgorithm: hashFunc, IssuerNameHash: innerRequest.Cert.NameHash, IssuerKeyHash: innerRequest.Cert.IssuerKeyHash, SerialNumber: innerRequest.Cert.SerialNumber, }, nil } // ParseResponse parses an OCSP response in DER form. It only supports // responses for a single certificate. If the response contains a certificate // then the signature over the response is checked. If issuer is not nil then // it will be used to validate the signature or embedded certificate. // // Invalid signatures or parse failures will result in a ParseError. Error // responses will result in a ResponseError. func ParseResponse(bytes []byte, issuer *x509.Certificate) (*Response, error) { var resp responseASN1 rest, err := asn1.Unmarshal(bytes, &resp) if err != nil { return nil, err } if len(rest) > 0 { return nil, ParseError("trailing data in OCSP response") } if status := ResponseStatus(resp.Status); status != Success { return nil, ResponseError{status} } if !resp.Response.ResponseType.Equal(idPKIXOCSPBasic) { return nil, ParseError("bad OCSP response type") } var basicResp basicResponse rest, err = asn1.Unmarshal(resp.Response.Response, &basicResp) if err != nil { return nil, err } if len(basicResp.Certificates) > 1 { return nil, ParseError("OCSP response contains bad number of certificates") } if len(basicResp.TBSResponseData.Responses) != 1 { return nil, ParseError("OCSP response contains bad number of responses") } ret := &Response{ TBSResponseData: basicResp.TBSResponseData.Raw, Signature: basicResp.Signature.RightAlign(), SignatureAlgorithm: getSignatureAlgorithmFromOID(basicResp.SignatureAlgorithm.Algorithm), } if len(basicResp.Certificates) > 0 { ret.Certificate, err = x509.ParseCertificate(basicResp.Certificates[0].FullBytes) if err != nil { return nil, err } if err := ret.CheckSignatureFrom(ret.Certificate); err != nil { return nil, ParseError("bad OCSP signature") } if issuer != nil { if err := issuer.CheckSignature(ret.Certificate.SignatureAlgorithm, ret.Certificate.RawTBSCertificate, ret.Certificate.Signature); err != nil { return nil, ParseError("bad signature on embedded certificate") } } } else if issuer != nil { if err := ret.CheckSignatureFrom(issuer); err != nil { return nil, ParseError("bad OCSP signature") } } r := basicResp.TBSResponseData.Responses[0] for _, ext := range r.SingleExtensions { if ext.Critical { return nil, ParseError("unsupported critical extension") } } ret.Extensions = r.SingleExtensions ret.SerialNumber = r.CertID.SerialNumber switch { case bool(r.Good): ret.Status = Good case bool(r.Unknown): ret.Status = Unknown default: ret.Status = Revoked ret.RevokedAt = r.Revoked.RevocationTime ret.RevocationReason = int(r.Revoked.Reason) } ret.ProducedAt = basicResp.TBSResponseData.ProducedAt ret.ThisUpdate = r.ThisUpdate ret.NextUpdate = r.NextUpdate return ret, nil } // RequestOptions contains options for constructing OCSP requests. type RequestOptions struct { // Hash contains the hash function that should be used when // constructing the OCSP request. If zero, SHA-1 will be used. Hash crypto.Hash } func (opts *RequestOptions) hash() crypto.Hash { if opts == nil || opts.Hash == 0 { // SHA-1 is nearly universally used in OCSP. return crypto.SHA1 } return opts.Hash } // CreateRequest returns a DER-encoded, OCSP request for the status of cert. If // opts is nil then sensible defaults are used. func CreateRequest(cert, issuer *x509.Certificate, opts *RequestOptions) ([]byte, error) { hashFunc := opts.hash() // OCSP seems to be the only place where these raw hash identifiers are // used. I took the following from // http://msdn.microsoft.com/en-us/library/ff635603.aspx var hashOID asn1.ObjectIdentifier hashOID, ok := hashOIDs[hashFunc] if !ok { return nil, x509.ErrUnsupportedAlgorithm } if !hashFunc.Available() { return nil, x509.ErrUnsupportedAlgorithm } h := opts.hash().New() var publicKeyInfo struct { Algorithm pkix.AlgorithmIdentifier PublicKey asn1.BitString } if _, err := asn1.Unmarshal(issuer.RawSubjectPublicKeyInfo, &publicKeyInfo); err != nil { return nil, err } h.Write(publicKeyInfo.PublicKey.RightAlign()) issuerKeyHash := h.Sum(nil) h.Reset() h.Write(issuer.RawSubject) issuerNameHash := h.Sum(nil) return asn1.Marshal(ocspRequest{ tbsRequest{ Version: 0, RequestList: []request{ { Cert: certID{ pkix.AlgorithmIdentifier{ Algorithm: hashOID, Parameters: asn1.RawValue{Tag: 5 /* ASN.1 NULL */}, }, issuerNameHash, issuerKeyHash, cert.SerialNumber, }, }, }, }, }) } // CreateResponse returns a DER-encoded OCSP response with the specified contents. // The fields in the response are populated as follows: // // The responder cert is used to populate the ResponderName field, and the certificate // itself is provided alongside the OCSP response signature. // // The issuer cert is used to puplate the IssuerNameHash and IssuerKeyHash fields. // (SHA-1 is used for the hash function; this is not configurable.) // // The template is used to populate the SerialNumber, RevocationStatus, RevokedAt, // RevocationReason, ThisUpdate, and NextUpdate fields. // // The ProducedAt date is automatically set to the current date, to the nearest minute. func CreateResponse(issuer, responderCert *x509.Certificate, template Response, priv crypto.Signer) ([]byte, error) { var publicKeyInfo struct { Algorithm pkix.AlgorithmIdentifier PublicKey asn1.BitString } if _, err := asn1.Unmarshal(issuer.RawSubjectPublicKeyInfo, &publicKeyInfo); err != nil { return nil, err } h := sha1.New() h.Write(publicKeyInfo.PublicKey.RightAlign()) issuerKeyHash := h.Sum(nil) h.Reset() h.Write(issuer.RawSubject) issuerNameHash := h.Sum(nil) innerResponse := singleResponse{ CertID: certID{ HashAlgorithm: pkix.AlgorithmIdentifier{ Algorithm: hashOIDs[crypto.SHA1], Parameters: asn1.RawValue{Tag: 5 /* ASN.1 NULL */}, }, NameHash: issuerNameHash, IssuerKeyHash: issuerKeyHash, SerialNumber: template.SerialNumber, }, ThisUpdate: template.ThisUpdate.UTC(), NextUpdate: template.NextUpdate.UTC(), SingleExtensions: template.ExtraExtensions, } switch template.Status { case Good: innerResponse.Good = true case Unknown: innerResponse.Unknown = true case Revoked: innerResponse.Revoked = revokedInfo{ RevocationTime: template.RevokedAt.UTC(), Reason: asn1.Enumerated(template.RevocationReason), } } responderName := asn1.RawValue{ Class: 2, // context-specific Tag: 1, // explicit tag IsCompound: true, Bytes: responderCert.RawSubject, } tbsResponseData := responseData{ Version: 0, RawResponderName: responderName, ProducedAt: time.Now().Truncate(time.Minute).UTC(), Responses: []singleResponse{innerResponse}, } tbsResponseDataDER, err := asn1.Marshal(tbsResponseData) if err != nil { return nil, err } hashFunc, signatureAlgorithm, err := signingParamsForPublicKey(priv.Public(), template.SignatureAlgorithm) if err != nil { return nil, err } responseHash := hashFunc.New() responseHash.Write(tbsResponseDataDER) signature, err := priv.Sign(rand.Reader, responseHash.Sum(nil), hashFunc) if err != nil { return nil, err } response := basicResponse{ TBSResponseData: tbsResponseData, SignatureAlgorithm: signatureAlgorithm, Signature: asn1.BitString{ Bytes: signature, BitLength: 8 * len(signature), }, } if template.Certificate != nil { response.Certificates = []asn1.RawValue{ asn1.RawValue{FullBytes: template.Certificate.Raw}, } } responseDER, err := asn1.Marshal(response) if err != nil { return nil, err } return asn1.Marshal(responseASN1{ Status: asn1.Enumerated(Success), Response: responseBytes{ ResponseType: idPKIXOCSPBasic, Response: responseDER, }, }) } lxd-2.0.0/dist/src/golang.org/x/crypto/twofish/0000755061062106075000000000000012702772344023757 5ustar00stgraberdomain admins00000000000000lxd-2.0.0/dist/src/golang.org/x/crypto/twofish/twofish_test.go0000644061062106075000000001136312702772344027034 0ustar00stgraberdomain admins00000000000000// 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 twofish import ( "bytes" "testing" ) var qbox = [2][4][16]byte{ { {0x8, 0x1, 0x7, 0xD, 0x6, 0xF, 0x3, 0x2, 0x0, 0xB, 0x5, 0x9, 0xE, 0xC, 0xA, 0x4}, {0xE, 0xC, 0xB, 0x8, 0x1, 0x2, 0x3, 0x5, 0xF, 0x4, 0xA, 0x6, 0x7, 0x0, 0x9, 0xD}, {0xB, 0xA, 0x5, 0xE, 0x6, 0xD, 0x9, 0x0, 0xC, 0x8, 0xF, 0x3, 0x2, 0x4, 0x7, 0x1}, {0xD, 0x7, 0xF, 0x4, 0x1, 0x2, 0x6, 0xE, 0x9, 0xB, 0x3, 0x0, 0x8, 0x5, 0xC, 0xA}, }, { {0x2, 0x8, 0xB, 0xD, 0xF, 0x7, 0x6, 0xE, 0x3, 0x1, 0x9, 0x4, 0x0, 0xA, 0xC, 0x5}, {0x1, 0xE, 0x2, 0xB, 0x4, 0xC, 0x3, 0x7, 0x6, 0xD, 0xA, 0x5, 0xF, 0x9, 0x0, 0x8}, {0x4, 0xC, 0x7, 0x5, 0x1, 0x6, 0x9, 0xA, 0x0, 0xE, 0xD, 0x8, 0x2, 0xB, 0x3, 0xF}, {0xB, 0x9, 0x5, 0x1, 0xC, 0x3, 0xD, 0xE, 0x6, 0x4, 0x7, 0xF, 0x2, 0x0, 0x8, 0xA}, }, } // genSbox generates the variable sbox func genSbox(qi int, x byte) byte { a0, b0 := x/16, x%16 for i := 0; i < 2; i++ { a1 := a0 ^ b0 b1 := (a0 ^ ((b0 << 3) | (b0 >> 1)) ^ (a0 << 3)) & 15 a0 = qbox[qi][2*i][a1] b0 = qbox[qi][2*i+1][b1] } return (b0 << 4) + a0 } func TestSbox(t *testing.T) { for n := range sbox { for m := range sbox[n] { if genSbox(n, byte(m)) != sbox[n][m] { t.Errorf("#%d|%d: sbox value = %d want %d", n, m, sbox[n][m], genSbox(n, byte(m))) } } } } var testVectors = []struct { key []byte dec []byte enc []byte }{ // These tests are extracted from LibTom { []byte{0x9F, 0x58, 0x9F, 0x5C, 0xF6, 0x12, 0x2C, 0x32, 0xB6, 0xBF, 0xEC, 0x2F, 0x2A, 0xE8, 0xC3, 0x5A}, []byte{0xD4, 0x91, 0xDB, 0x16, 0xE7, 0xB1, 0xC3, 0x9E, 0x86, 0xCB, 0x08, 0x6B, 0x78, 0x9F, 0x54, 0x19}, []byte{0x01, 0x9F, 0x98, 0x09, 0xDE, 0x17, 0x11, 0x85, 0x8F, 0xAA, 0xC3, 0xA3, 0xBA, 0x20, 0xFB, 0xC3}, }, { []byte{0x88, 0xB2, 0xB2, 0x70, 0x6B, 0x10, 0x5E, 0x36, 0xB4, 0x46, 0xBB, 0x6D, 0x73, 0x1A, 0x1E, 0x88, 0xEF, 0xA7, 0x1F, 0x78, 0x89, 0x65, 0xBD, 0x44}, []byte{0x39, 0xDA, 0x69, 0xD6, 0xBA, 0x49, 0x97, 0xD5, 0x85, 0xB6, 0xDC, 0x07, 0x3C, 0xA3, 0x41, 0xB2}, []byte{0x18, 0x2B, 0x02, 0xD8, 0x14, 0x97, 0xEA, 0x45, 0xF9, 0xDA, 0xAC, 0xDC, 0x29, 0x19, 0x3A, 0x65}, }, { []byte{0xD4, 0x3B, 0xB7, 0x55, 0x6E, 0xA3, 0x2E, 0x46, 0xF2, 0xA2, 0x82, 0xB7, 0xD4, 0x5B, 0x4E, 0x0D, 0x57, 0xFF, 0x73, 0x9D, 0x4D, 0xC9, 0x2C, 0x1B, 0xD7, 0xFC, 0x01, 0x70, 0x0C, 0xC8, 0x21, 0x6F}, []byte{0x90, 0xAF, 0xE9, 0x1B, 0xB2, 0x88, 0x54, 0x4F, 0x2C, 0x32, 0xDC, 0x23, 0x9B, 0x26, 0x35, 0xE6}, []byte{0x6C, 0xB4, 0x56, 0x1C, 0x40, 0xBF, 0x0A, 0x97, 0x05, 0x93, 0x1C, 0xB6, 0xD4, 0x08, 0xE7, 0xFA}, }, // These test are derived from http://www.schneier.com/code/ecb_ival.txt { []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, []byte{0x9F, 0x58, 0x9F, 0x5C, 0xF6, 0x12, 0x2C, 0x32, 0xB6, 0xBF, 0xEC, 0x2F, 0x2A, 0xE8, 0xC3, 0x5A}, }, { []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, }, []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, []byte{0xCF, 0xD1, 0xD2, 0xE5, 0xA9, 0xBE, 0x9C, 0xDF, 0x50, 0x1F, 0x13, 0xB8, 0x92, 0xBD, 0x22, 0x48}, }, { []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, }, []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, []byte{0x37, 0x52, 0x7B, 0xE0, 0x05, 0x23, 0x34, 0xB8, 0x9F, 0x0C, 0xFC, 0xCA, 0xE8, 0x7C, 0xFA, 0x20}, }, } func TestCipher(t *testing.T) { for n, tt := range testVectors { // Test if the plaintext (dec) is encrypts to the given // ciphertext (enc) using the given key. Test also if enc can // be decrypted again into dec. c, err := NewCipher(tt.key) if err != nil { t.Errorf("#%d: NewCipher: %v", n, err) return } buf := make([]byte, 16) c.Encrypt(buf, tt.dec) if !bytes.Equal(buf, tt.enc) { t.Errorf("#%d: encrypt = %x want %x", n, buf, tt.enc) } c.Decrypt(buf, tt.enc) if !bytes.Equal(buf, tt.dec) { t.Errorf("#%d: decrypt = %x want %x", n, buf, tt.dec) } // Test that 16 zero bytes, encrypted 1000 times then decrypted // 1000 times results in zero bytes again. zero := make([]byte, 16) buf = make([]byte, 16) for i := 0; i < 1000; i++ { c.Encrypt(buf, buf) } for i := 0; i < 1000; i++ { c.Decrypt(buf, buf) } if !bytes.Equal(buf, zero) { t.Errorf("#%d: encrypt/decrypt 1000: have %x want %x", n, buf, zero) } } } lxd-2.0.0/dist/src/golang.org/x/crypto/twofish/twofish.go0000644061062106075000000002727612702772344026007 0ustar00stgraberdomain admins00000000000000// 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 twofish implements Bruce Schneier's Twofish encryption algorithm. package twofish // import "golang.org/x/crypto/twofish" // Twofish is defined in http://www.schneier.com/paper-twofish-paper.pdf [TWOFISH] // This code is a port of the LibTom C implementation. // See http://libtom.org/?page=features&newsitems=5&whatfile=crypt. // LibTomCrypt is free for all purposes under the public domain. // It was heavily inspired by the go blowfish package. import "strconv" // BlockSize is the constant block size of Twofish. const BlockSize = 16 const mdsPolynomial = 0x169 // x^8 + x^6 + x^5 + x^3 + 1, see [TWOFISH] 4.2 const rsPolynomial = 0x14d // x^8 + x^6 + x^3 + x^2 + 1, see [TWOFISH] 4.3 // A Cipher is an instance of Twofish encryption using a particular key. type Cipher struct { s [4][256]uint32 k [40]uint32 } type KeySizeError int func (k KeySizeError) Error() string { return "crypto/twofish: invalid key size " + strconv.Itoa(int(k)) } // NewCipher creates and returns a Cipher. // The key argument should be the Twofish key, 16, 24 or 32 bytes. func NewCipher(key []byte) (*Cipher, error) { keylen := len(key) if keylen != 16 && keylen != 24 && keylen != 32 { return nil, KeySizeError(keylen) } // k is the number of 64 bit words in key k := keylen / 8 // Create the S[..] words var S [4 * 4]byte for i := 0; i < k; i++ { // Computes [y0 y1 y2 y3] = rs . [x0 x1 x2 x3 x4 x5 x6 x7] for j, rsRow := range rs { for k, rsVal := range rsRow { S[4*i+j] ^= gfMult(key[8*i+k], rsVal, rsPolynomial) } } } // Calculate subkeys c := new(Cipher) var tmp [4]byte for i := byte(0); i < 20; i++ { // A = h(p * 2x, Me) for j := range tmp { tmp[j] = 2 * i } A := h(tmp[:], key, 0) // B = rolc(h(p * (2x + 1), Mo), 8) for j := range tmp { tmp[j] = 2*i + 1 } B := h(tmp[:], key, 1) B = rol(B, 8) c.k[2*i] = A + B // K[2i+1] = (A + 2B) <<< 9 c.k[2*i+1] = rol(2*B+A, 9) } // Calculate sboxes switch k { case 2: for i := range c.s[0] { c.s[0][i] = mdsColumnMult(sbox[1][sbox[0][sbox[0][byte(i)]^S[0]]^S[4]], 0) c.s[1][i] = mdsColumnMult(sbox[0][sbox[0][sbox[1][byte(i)]^S[1]]^S[5]], 1) c.s[2][i] = mdsColumnMult(sbox[1][sbox[1][sbox[0][byte(i)]^S[2]]^S[6]], 2) c.s[3][i] = mdsColumnMult(sbox[0][sbox[1][sbox[1][byte(i)]^S[3]]^S[7]], 3) } case 3: for i := range c.s[0] { c.s[0][i] = mdsColumnMult(sbox[1][sbox[0][sbox[0][sbox[1][byte(i)]^S[0]]^S[4]]^S[8]], 0) c.s[1][i] = mdsColumnMult(sbox[0][sbox[0][sbox[1][sbox[1][byte(i)]^S[1]]^S[5]]^S[9]], 1) c.s[2][i] = mdsColumnMult(sbox[1][sbox[1][sbox[0][sbox[0][byte(i)]^S[2]]^S[6]]^S[10]], 2) c.s[3][i] = mdsColumnMult(sbox[0][sbox[1][sbox[1][sbox[0][byte(i)]^S[3]]^S[7]]^S[11]], 3) } default: for i := range c.s[0] { c.s[0][i] = mdsColumnMult(sbox[1][sbox[0][sbox[0][sbox[1][sbox[1][byte(i)]^S[0]]^S[4]]^S[8]]^S[12]], 0) c.s[1][i] = mdsColumnMult(sbox[0][sbox[0][sbox[1][sbox[1][sbox[0][byte(i)]^S[1]]^S[5]]^S[9]]^S[13]], 1) c.s[2][i] = mdsColumnMult(sbox[1][sbox[1][sbox[0][sbox[0][sbox[0][byte(i)]^S[2]]^S[6]]^S[10]]^S[14]], 2) c.s[3][i] = mdsColumnMult(sbox[0][sbox[1][sbox[1][sbox[0][sbox[1][byte(i)]^S[3]]^S[7]]^S[11]]^S[15]], 3) } } return c, nil } // BlockSize returns the Twofish block size, 16 bytes. func (c *Cipher) BlockSize() int { return BlockSize } // store32l stores src in dst in little-endian form. func store32l(dst []byte, src uint32) { dst[0] = byte(src) dst[1] = byte(src >> 8) dst[2] = byte(src >> 16) dst[3] = byte(src >> 24) return } // load32l reads a little-endian uint32 from src. func load32l(src []byte) uint32 { return uint32(src[0]) | uint32(src[1])<<8 | uint32(src[2])<<16 | uint32(src[3])<<24 } // rol returns x after a left circular rotation of y bits. func rol(x, y uint32) uint32 { return (x << (y & 31)) | (x >> (32 - (y & 31))) } // ror returns x after a right circular rotation of y bits. func ror(x, y uint32) uint32 { return (x >> (y & 31)) | (x << (32 - (y & 31))) } // The RS matrix. See [TWOFISH] 4.3 var rs = [4][8]byte{ {0x01, 0xA4, 0x55, 0x87, 0x5A, 0x58, 0xDB, 0x9E}, {0xA4, 0x56, 0x82, 0xF3, 0x1E, 0xC6, 0x68, 0xE5}, {0x02, 0xA1, 0xFC, 0xC1, 0x47, 0xAE, 0x3D, 0x19}, {0xA4, 0x55, 0x87, 0x5A, 0x58, 0xDB, 0x9E, 0x03}, } // sbox tables var sbox = [2][256]byte{ { 0xa9, 0x67, 0xb3, 0xe8, 0x04, 0xfd, 0xa3, 0x76, 0x9a, 0x92, 0x80, 0x78, 0xe4, 0xdd, 0xd1, 0x38, 0x0d, 0xc6, 0x35, 0x98, 0x18, 0xf7, 0xec, 0x6c, 0x43, 0x75, 0x37, 0x26, 0xfa, 0x13, 0x94, 0x48, 0xf2, 0xd0, 0x8b, 0x30, 0x84, 0x54, 0xdf, 0x23, 0x19, 0x5b, 0x3d, 0x59, 0xf3, 0xae, 0xa2, 0x82, 0x63, 0x01, 0x83, 0x2e, 0xd9, 0x51, 0x9b, 0x7c, 0xa6, 0xeb, 0xa5, 0xbe, 0x16, 0x0c, 0xe3, 0x61, 0xc0, 0x8c, 0x3a, 0xf5, 0x73, 0x2c, 0x25, 0x0b, 0xbb, 0x4e, 0x89, 0x6b, 0x53, 0x6a, 0xb4, 0xf1, 0xe1, 0xe6, 0xbd, 0x45, 0xe2, 0xf4, 0xb6, 0x66, 0xcc, 0x95, 0x03, 0x56, 0xd4, 0x1c, 0x1e, 0xd7, 0xfb, 0xc3, 0x8e, 0xb5, 0xe9, 0xcf, 0xbf, 0xba, 0xea, 0x77, 0x39, 0xaf, 0x33, 0xc9, 0x62, 0x71, 0x81, 0x79, 0x09, 0xad, 0x24, 0xcd, 0xf9, 0xd8, 0xe5, 0xc5, 0xb9, 0x4d, 0x44, 0x08, 0x86, 0xe7, 0xa1, 0x1d, 0xaa, 0xed, 0x06, 0x70, 0xb2, 0xd2, 0x41, 0x7b, 0xa0, 0x11, 0x31, 0xc2, 0x27, 0x90, 0x20, 0xf6, 0x60, 0xff, 0x96, 0x5c, 0xb1, 0xab, 0x9e, 0x9c, 0x52, 0x1b, 0x5f, 0x93, 0x0a, 0xef, 0x91, 0x85, 0x49, 0xee, 0x2d, 0x4f, 0x8f, 0x3b, 0x47, 0x87, 0x6d, 0x46, 0xd6, 0x3e, 0x69, 0x64, 0x2a, 0xce, 0xcb, 0x2f, 0xfc, 0x97, 0x05, 0x7a, 0xac, 0x7f, 0xd5, 0x1a, 0x4b, 0x0e, 0xa7, 0x5a, 0x28, 0x14, 0x3f, 0x29, 0x88, 0x3c, 0x4c, 0x02, 0xb8, 0xda, 0xb0, 0x17, 0x55, 0x1f, 0x8a, 0x7d, 0x57, 0xc7, 0x8d, 0x74, 0xb7, 0xc4, 0x9f, 0x72, 0x7e, 0x15, 0x22, 0x12, 0x58, 0x07, 0x99, 0x34, 0x6e, 0x50, 0xde, 0x68, 0x65, 0xbc, 0xdb, 0xf8, 0xc8, 0xa8, 0x2b, 0x40, 0xdc, 0xfe, 0x32, 0xa4, 0xca, 0x10, 0x21, 0xf0, 0xd3, 0x5d, 0x0f, 0x00, 0x6f, 0x9d, 0x36, 0x42, 0x4a, 0x5e, 0xc1, 0xe0, }, { 0x75, 0xf3, 0xc6, 0xf4, 0xdb, 0x7b, 0xfb, 0xc8, 0x4a, 0xd3, 0xe6, 0x6b, 0x45, 0x7d, 0xe8, 0x4b, 0xd6, 0x32, 0xd8, 0xfd, 0x37, 0x71, 0xf1, 0xe1, 0x30, 0x0f, 0xf8, 0x1b, 0x87, 0xfa, 0x06, 0x3f, 0x5e, 0xba, 0xae, 0x5b, 0x8a, 0x00, 0xbc, 0x9d, 0x6d, 0xc1, 0xb1, 0x0e, 0x80, 0x5d, 0xd2, 0xd5, 0xa0, 0x84, 0x07, 0x14, 0xb5, 0x90, 0x2c, 0xa3, 0xb2, 0x73, 0x4c, 0x54, 0x92, 0x74, 0x36, 0x51, 0x38, 0xb0, 0xbd, 0x5a, 0xfc, 0x60, 0x62, 0x96, 0x6c, 0x42, 0xf7, 0x10, 0x7c, 0x28, 0x27, 0x8c, 0x13, 0x95, 0x9c, 0xc7, 0x24, 0x46, 0x3b, 0x70, 0xca, 0xe3, 0x85, 0xcb, 0x11, 0xd0, 0x93, 0xb8, 0xa6, 0x83, 0x20, 0xff, 0x9f, 0x77, 0xc3, 0xcc, 0x03, 0x6f, 0x08, 0xbf, 0x40, 0xe7, 0x2b, 0xe2, 0x79, 0x0c, 0xaa, 0x82, 0x41, 0x3a, 0xea, 0xb9, 0xe4, 0x9a, 0xa4, 0x97, 0x7e, 0xda, 0x7a, 0x17, 0x66, 0x94, 0xa1, 0x1d, 0x3d, 0xf0, 0xde, 0xb3, 0x0b, 0x72, 0xa7, 0x1c, 0xef, 0xd1, 0x53, 0x3e, 0x8f, 0x33, 0x26, 0x5f, 0xec, 0x76, 0x2a, 0x49, 0x81, 0x88, 0xee, 0x21, 0xc4, 0x1a, 0xeb, 0xd9, 0xc5, 0x39, 0x99, 0xcd, 0xad, 0x31, 0x8b, 0x01, 0x18, 0x23, 0xdd, 0x1f, 0x4e, 0x2d, 0xf9, 0x48, 0x4f, 0xf2, 0x65, 0x8e, 0x78, 0x5c, 0x58, 0x19, 0x8d, 0xe5, 0x98, 0x57, 0x67, 0x7f, 0x05, 0x64, 0xaf, 0x63, 0xb6, 0xfe, 0xf5, 0xb7, 0x3c, 0xa5, 0xce, 0xe9, 0x68, 0x44, 0xe0, 0x4d, 0x43, 0x69, 0x29, 0x2e, 0xac, 0x15, 0x59, 0xa8, 0x0a, 0x9e, 0x6e, 0x47, 0xdf, 0x34, 0x35, 0x6a, 0xcf, 0xdc, 0x22, 0xc9, 0xc0, 0x9b, 0x89, 0xd4, 0xed, 0xab, 0x12, 0xa2, 0x0d, 0x52, 0xbb, 0x02, 0x2f, 0xa9, 0xd7, 0x61, 0x1e, 0xb4, 0x50, 0x04, 0xf6, 0xc2, 0x16, 0x25, 0x86, 0x56, 0x55, 0x09, 0xbe, 0x91, }, } // gfMult returns a·b in GF(2^8)/p func gfMult(a, b byte, p uint32) byte { B := [2]uint32{0, uint32(b)} P := [2]uint32{0, p} var result uint32 // branchless GF multiplier for i := 0; i < 7; i++ { result ^= B[a&1] a >>= 1 B[1] = P[B[1]>>7] ^ (B[1] << 1) } result ^= B[a&1] return byte(result) } // mdsColumnMult calculates y{col} where [y0 y1 y2 y3] = MDS · [x0] func mdsColumnMult(in byte, col int) uint32 { mul01 := in mul5B := gfMult(in, 0x5B, mdsPolynomial) mulEF := gfMult(in, 0xEF, mdsPolynomial) switch col { case 0: return uint32(mul01) | uint32(mul5B)<<8 | uint32(mulEF)<<16 | uint32(mulEF)<<24 case 1: return uint32(mulEF) | uint32(mulEF)<<8 | uint32(mul5B)<<16 | uint32(mul01)<<24 case 2: return uint32(mul5B) | uint32(mulEF)<<8 | uint32(mul01)<<16 | uint32(mulEF)<<24 case 3: return uint32(mul5B) | uint32(mul01)<<8 | uint32(mulEF)<<16 | uint32(mul5B)<<24 } panic("unreachable") } // h implements the S-box generation function. See [TWOFISH] 4.3.5 func h(in, key []byte, offset int) uint32 { var y [4]byte for x := range y { y[x] = in[x] } switch len(key) / 8 { case 4: y[0] = sbox[1][y[0]] ^ key[4*(6+offset)+0] y[1] = sbox[0][y[1]] ^ key[4*(6+offset)+1] y[2] = sbox[0][y[2]] ^ key[4*(6+offset)+2] y[3] = sbox[1][y[3]] ^ key[4*(6+offset)+3] fallthrough case 3: y[0] = sbox[1][y[0]] ^ key[4*(4+offset)+0] y[1] = sbox[1][y[1]] ^ key[4*(4+offset)+1] y[2] = sbox[0][y[2]] ^ key[4*(4+offset)+2] y[3] = sbox[0][y[3]] ^ key[4*(4+offset)+3] fallthrough case 2: y[0] = sbox[1][sbox[0][sbox[0][y[0]]^key[4*(2+offset)+0]]^key[4*(0+offset)+0]] y[1] = sbox[0][sbox[0][sbox[1][y[1]]^key[4*(2+offset)+1]]^key[4*(0+offset)+1]] y[2] = sbox[1][sbox[1][sbox[0][y[2]]^key[4*(2+offset)+2]]^key[4*(0+offset)+2]] y[3] = sbox[0][sbox[1][sbox[1][y[3]]^key[4*(2+offset)+3]]^key[4*(0+offset)+3]] } // [y0 y1 y2 y3] = MDS . [x0 x1 x2 x3] var mdsMult uint32 for i := range y { mdsMult ^= mdsColumnMult(y[i], i) } return mdsMult } // Encrypt encrypts a 16-byte block from src to dst, which may overlap. // Note that for amounts of data larger than a block, // it is not safe to just call Encrypt on successive blocks; // instead, use an encryption mode like CBC (see crypto/cipher/cbc.go). func (c *Cipher) Encrypt(dst, src []byte) { S1 := c.s[0] S2 := c.s[1] S3 := c.s[2] S4 := c.s[3] // Load input ia := load32l(src[0:4]) ib := load32l(src[4:8]) ic := load32l(src[8:12]) id := load32l(src[12:16]) // Pre-whitening ia ^= c.k[0] ib ^= c.k[1] ic ^= c.k[2] id ^= c.k[3] for i := 0; i < 8; i++ { k := c.k[8+i*4 : 12+i*4] t2 := S2[byte(ib)] ^ S3[byte(ib>>8)] ^ S4[byte(ib>>16)] ^ S1[byte(ib>>24)] t1 := S1[byte(ia)] ^ S2[byte(ia>>8)] ^ S3[byte(ia>>16)] ^ S4[byte(ia>>24)] + t2 ic = ror(ic^(t1+k[0]), 1) id = rol(id, 1) ^ (t2 + t1 + k[1]) t2 = S2[byte(id)] ^ S3[byte(id>>8)] ^ S4[byte(id>>16)] ^ S1[byte(id>>24)] t1 = S1[byte(ic)] ^ S2[byte(ic>>8)] ^ S3[byte(ic>>16)] ^ S4[byte(ic>>24)] + t2 ia = ror(ia^(t1+k[2]), 1) ib = rol(ib, 1) ^ (t2 + t1 + k[3]) } // Output with "undo last swap" ta := ic ^ c.k[4] tb := id ^ c.k[5] tc := ia ^ c.k[6] td := ib ^ c.k[7] store32l(dst[0:4], ta) store32l(dst[4:8], tb) store32l(dst[8:12], tc) store32l(dst[12:16], td) } // Decrypt decrypts a 16-byte block from src to dst, which may overlap. func (c *Cipher) Decrypt(dst, src []byte) { S1 := c.s[0] S2 := c.s[1] S3 := c.s[2] S4 := c.s[3] // Load input ta := load32l(src[0:4]) tb := load32l(src[4:8]) tc := load32l(src[8:12]) td := load32l(src[12:16]) // Undo undo final swap ia := tc ^ c.k[6] ib := td ^ c.k[7] ic := ta ^ c.k[4] id := tb ^ c.k[5] for i := 8; i > 0; i-- { k := c.k[4+i*4 : 8+i*4] t2 := S2[byte(id)] ^ S3[byte(id>>8)] ^ S4[byte(id>>16)] ^ S1[byte(id>>24)] t1 := S1[byte(ic)] ^ S2[byte(ic>>8)] ^ S3[byte(ic>>16)] ^ S4[byte(ic>>24)] + t2 ia = rol(ia, 1) ^ (t1 + k[2]) ib = ror(ib^(t2+t1+k[3]), 1) t2 = S2[byte(ib)] ^ S3[byte(ib>>8)] ^ S4[byte(ib>>16)] ^ S1[byte(ib>>24)] t1 = S1[byte(ia)] ^ S2[byte(ia>>8)] ^ S3[byte(ia>>16)] ^ S4[byte(ia>>24)] + t2 ic = rol(ic, 1) ^ (t1 + k[0]) id = ror(id^(t2+t1+k[1]), 1) } // Undo pre-whitening ia ^= c.k[0] ib ^= c.k[1] ic ^= c.k[2] id ^= c.k[3] store32l(dst[0:4], ia) store32l(dst[4:8], ib) store32l(dst[8:12], ic) store32l(dst[12:16], id) } lxd-2.0.0/dist/src/golang.org/x/crypto/cast5/0000755061062106075000000000000012702772344023313 5ustar00stgraberdomain admins00000000000000lxd-2.0.0/dist/src/golang.org/x/crypto/cast5/cast5.go0000644061062106075000000007743512702772344024701 0ustar00stgraberdomain admins00000000000000// Copyright 2010 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Package cast5 implements CAST5, as defined in RFC 2144. CAST5 is a common // OpenPGP cipher. package cast5 // import "golang.org/x/crypto/cast5" import "errors" const BlockSize = 8 const KeySize = 16 type Cipher struct { masking [16]uint32 rotate [16]uint8 } func NewCipher(key []byte) (c *Cipher, err error) { if len(key) != KeySize { return nil, errors.New("CAST5: keys must be 16 bytes") } c = new(Cipher) c.keySchedule(key) return } func (c *Cipher) BlockSize() int { return BlockSize } func (c *Cipher) Encrypt(dst, src []byte) { l := uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3]) r := uint32(src[4])<<24 | uint32(src[5])<<16 | uint32(src[6])<<8 | uint32(src[7]) l, r = r, l^f1(r, c.masking[0], c.rotate[0]) l, r = r, l^f2(r, c.masking[1], c.rotate[1]) l, r = r, l^f3(r, c.masking[2], c.rotate[2]) l, r = r, l^f1(r, c.masking[3], c.rotate[3]) l, r = r, l^f2(r, c.masking[4], c.rotate[4]) l, r = r, l^f3(r, c.masking[5], c.rotate[5]) l, r = r, l^f1(r, c.masking[6], c.rotate[6]) l, r = r, l^f2(r, c.masking[7], c.rotate[7]) l, r = r, l^f3(r, c.masking[8], c.rotate[8]) l, r = r, l^f1(r, c.masking[9], c.rotate[9]) l, r = r, l^f2(r, c.masking[10], c.rotate[10]) l, r = r, l^f3(r, c.masking[11], c.rotate[11]) l, r = r, l^f1(r, c.masking[12], c.rotate[12]) l, r = r, l^f2(r, c.masking[13], c.rotate[13]) l, r = r, l^f3(r, c.masking[14], c.rotate[14]) l, r = r, l^f1(r, c.masking[15], c.rotate[15]) dst[0] = uint8(r >> 24) dst[1] = uint8(r >> 16) dst[2] = uint8(r >> 8) dst[3] = uint8(r) dst[4] = uint8(l >> 24) dst[5] = uint8(l >> 16) dst[6] = uint8(l >> 8) dst[7] = uint8(l) } func (c *Cipher) Decrypt(dst, src []byte) { l := uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3]) r := uint32(src[4])<<24 | uint32(src[5])<<16 | uint32(src[6])<<8 | uint32(src[7]) l, r = r, l^f1(r, c.masking[15], c.rotate[15]) l, r = r, l^f3(r, c.masking[14], c.rotate[14]) l, r = r, l^f2(r, c.masking[13], c.rotate[13]) l, r = r, l^f1(r, c.masking[12], c.rotate[12]) l, r = r, l^f3(r, c.masking[11], c.rotate[11]) l, r = r, l^f2(r, c.masking[10], c.rotate[10]) l, r = r, l^f1(r, c.masking[9], c.rotate[9]) l, r = r, l^f3(r, c.masking[8], c.rotate[8]) l, r = r, l^f2(r, c.masking[7], c.rotate[7]) l, r = r, l^f1(r, c.masking[6], c.rotate[6]) l, r = r, l^f3(r, c.masking[5], c.rotate[5]) l, r = r, l^f2(r, c.masking[4], c.rotate[4]) l, r = r, l^f1(r, c.masking[3], c.rotate[3]) l, r = r, l^f3(r, c.masking[2], c.rotate[2]) l, r = r, l^f2(r, c.masking[1], c.rotate[1]) l, r = r, l^f1(r, c.masking[0], c.rotate[0]) dst[0] = uint8(r >> 24) dst[1] = uint8(r >> 16) dst[2] = uint8(r >> 8) dst[3] = uint8(r) dst[4] = uint8(l >> 24) dst[5] = uint8(l >> 16) dst[6] = uint8(l >> 8) dst[7] = uint8(l) } type keyScheduleA [4][7]uint8 type keyScheduleB [4][5]uint8 // keyScheduleRound contains the magic values for a round of the key schedule. // The keyScheduleA deals with the lines like: // z0z1z2z3 = x0x1x2x3 ^ S5[xD] ^ S6[xF] ^ S7[xC] ^ S8[xE] ^ S7[x8] // Conceptually, both x and z are in the same array, x first. The first // element describes which word of this array gets written to and the // second, which word gets read. So, for the line above, it's "4, 0", because // it's writing to the first word of z, which, being after x, is word 4, and // reading from the first word of x: word 0. // // Next are the indexes into the S-boxes. Now the array is treated as bytes. So // "xD" is 0xd. The first byte of z is written as "16 + 0", just to be clear // that it's z that we're indexing. // // keyScheduleB deals with lines like: // K1 = S5[z8] ^ S6[z9] ^ S7[z7] ^ S8[z6] ^ S5[z2] // "K1" is ignored because key words are always written in order. So the five // elements are the S-box indexes. They use the same form as in keyScheduleA, // above. type keyScheduleRound struct{} type keySchedule []keyScheduleRound var schedule = []struct { a keyScheduleA b keyScheduleB }{ { keyScheduleA{ {4, 0, 0xd, 0xf, 0xc, 0xe, 0x8}, {5, 2, 16 + 0, 16 + 2, 16 + 1, 16 + 3, 0xa}, {6, 3, 16 + 7, 16 + 6, 16 + 5, 16 + 4, 9}, {7, 1, 16 + 0xa, 16 + 9, 16 + 0xb, 16 + 8, 0xb}, }, keyScheduleB{ {16 + 8, 16 + 9, 16 + 7, 16 + 6, 16 + 2}, {16 + 0xa, 16 + 0xb, 16 + 5, 16 + 4, 16 + 6}, {16 + 0xc, 16 + 0xd, 16 + 3, 16 + 2, 16 + 9}, {16 + 0xe, 16 + 0xf, 16 + 1, 16 + 0, 16 + 0xc}, }, }, { keyScheduleA{ {0, 6, 16 + 5, 16 + 7, 16 + 4, 16 + 6, 16 + 0}, {1, 4, 0, 2, 1, 3, 16 + 2}, {2, 5, 7, 6, 5, 4, 16 + 1}, {3, 7, 0xa, 9, 0xb, 8, 16 + 3}, }, keyScheduleB{ {3, 2, 0xc, 0xd, 8}, {1, 0, 0xe, 0xf, 0xd}, {7, 6, 8, 9, 3}, {5, 4, 0xa, 0xb, 7}, }, }, { keyScheduleA{ {4, 0, 0xd, 0xf, 0xc, 0xe, 8}, {5, 2, 16 + 0, 16 + 2, 16 + 1, 16 + 3, 0xa}, {6, 3, 16 + 7, 16 + 6, 16 + 5, 16 + 4, 9}, {7, 1, 16 + 0xa, 16 + 9, 16 + 0xb, 16 + 8, 0xb}, }, keyScheduleB{ {16 + 3, 16 + 2, 16 + 0xc, 16 + 0xd, 16 + 9}, {16 + 1, 16 + 0, 16 + 0xe, 16 + 0xf, 16 + 0xc}, {16 + 7, 16 + 6, 16 + 8, 16 + 9, 16 + 2}, {16 + 5, 16 + 4, 16 + 0xa, 16 + 0xb, 16 + 6}, }, }, { keyScheduleA{ {0, 6, 16 + 5, 16 + 7, 16 + 4, 16 + 6, 16 + 0}, {1, 4, 0, 2, 1, 3, 16 + 2}, {2, 5, 7, 6, 5, 4, 16 + 1}, {3, 7, 0xa, 9, 0xb, 8, 16 + 3}, }, keyScheduleB{ {8, 9, 7, 6, 3}, {0xa, 0xb, 5, 4, 7}, {0xc, 0xd, 3, 2, 8}, {0xe, 0xf, 1, 0, 0xd}, }, }, } func (c *Cipher) keySchedule(in []byte) { var t [8]uint32 var k [32]uint32 for i := 0; i < 4; i++ { j := i * 4 t[i] = uint32(in[j])<<24 | uint32(in[j+1])<<16 | uint32(in[j+2])<<8 | uint32(in[j+3]) } x := []byte{6, 7, 4, 5} ki := 0 for half := 0; half < 2; half++ { for _, round := range schedule { for j := 0; j < 4; j++ { var a [7]uint8 copy(a[:], round.a[j][:]) w := t[a[1]] w ^= sBox[4][(t[a[2]>>2]>>(24-8*(a[2]&3)))&0xff] w ^= sBox[5][(t[a[3]>>2]>>(24-8*(a[3]&3)))&0xff] w ^= sBox[6][(t[a[4]>>2]>>(24-8*(a[4]&3)))&0xff] w ^= sBox[7][(t[a[5]>>2]>>(24-8*(a[5]&3)))&0xff] w ^= sBox[x[j]][(t[a[6]>>2]>>(24-8*(a[6]&3)))&0xff] t[a[0]] = w } for j := 0; j < 4; j++ { var b [5]uint8 copy(b[:], round.b[j][:]) w := sBox[4][(t[b[0]>>2]>>(24-8*(b[0]&3)))&0xff] w ^= sBox[5][(t[b[1]>>2]>>(24-8*(b[1]&3)))&0xff] w ^= sBox[6][(t[b[2]>>2]>>(24-8*(b[2]&3)))&0xff] w ^= sBox[7][(t[b[3]>>2]>>(24-8*(b[3]&3)))&0xff] w ^= sBox[4+j][(t[b[4]>>2]>>(24-8*(b[4]&3)))&0xff] k[ki] = w ki++ } } } for i := 0; i < 16; i++ { c.masking[i] = k[i] c.rotate[i] = uint8(k[16+i] & 0x1f) } } // These are the three 'f' functions. See RFC 2144, section 2.2. func f1(d, m uint32, r uint8) uint32 { t := m + d I := (t << r) | (t >> (32 - r)) return ((sBox[0][I>>24] ^ sBox[1][(I>>16)&0xff]) - sBox[2][(I>>8)&0xff]) + sBox[3][I&0xff] } func f2(d, m uint32, r uint8) uint32 { t := m ^ d I := (t << r) | (t >> (32 - r)) return ((sBox[0][I>>24] - sBox[1][(I>>16)&0xff]) + sBox[2][(I>>8)&0xff]) ^ sBox[3][I&0xff] } func f3(d, m uint32, r uint8) uint32 { t := m - d I := (t << r) | (t >> (32 - r)) return ((sBox[0][I>>24] + sBox[1][(I>>16)&0xff]) ^ sBox[2][(I>>8)&0xff]) - sBox[3][I&0xff] } var sBox = [8][256]uint32{ { 0x30fb40d4, 0x9fa0ff0b, 0x6beccd2f, 0x3f258c7a, 0x1e213f2f, 0x9c004dd3, 0x6003e540, 0xcf9fc949, 0xbfd4af27, 0x88bbbdb5, 0xe2034090, 0x98d09675, 0x6e63a0e0, 0x15c361d2, 0xc2e7661d, 0x22d4ff8e, 0x28683b6f, 0xc07fd059, 0xff2379c8, 0x775f50e2, 0x43c340d3, 0xdf2f8656, 0x887ca41a, 0xa2d2bd2d, 0xa1c9e0d6, 0x346c4819, 0x61b76d87, 0x22540f2f, 0x2abe32e1, 0xaa54166b, 0x22568e3a, 0xa2d341d0, 0x66db40c8, 0xa784392f, 0x004dff2f, 0x2db9d2de, 0x97943fac, 0x4a97c1d8, 0x527644b7, 0xb5f437a7, 0xb82cbaef, 0xd751d159, 0x6ff7f0ed, 0x5a097a1f, 0x827b68d0, 0x90ecf52e, 0x22b0c054, 0xbc8e5935, 0x4b6d2f7f, 0x50bb64a2, 0xd2664910, 0xbee5812d, 0xb7332290, 0xe93b159f, 0xb48ee411, 0x4bff345d, 0xfd45c240, 0xad31973f, 0xc4f6d02e, 0x55fc8165, 0xd5b1caad, 0xa1ac2dae, 0xa2d4b76d, 0xc19b0c50, 0x882240f2, 0x0c6e4f38, 0xa4e4bfd7, 0x4f5ba272, 0x564c1d2f, 0xc59c5319, 0xb949e354, 0xb04669fe, 0xb1b6ab8a, 0xc71358dd, 0x6385c545, 0x110f935d, 0x57538ad5, 0x6a390493, 0xe63d37e0, 0x2a54f6b3, 0x3a787d5f, 0x6276a0b5, 0x19a6fcdf, 0x7a42206a, 0x29f9d4d5, 0xf61b1891, 0xbb72275e, 0xaa508167, 0x38901091, 0xc6b505eb, 0x84c7cb8c, 0x2ad75a0f, 0x874a1427, 0xa2d1936b, 0x2ad286af, 0xaa56d291, 0xd7894360, 0x425c750d, 0x93b39e26, 0x187184c9, 0x6c00b32d, 0x73e2bb14, 0xa0bebc3c, 0x54623779, 0x64459eab, 0x3f328b82, 0x7718cf82, 0x59a2cea6, 0x04ee002e, 0x89fe78e6, 0x3fab0950, 0x325ff6c2, 0x81383f05, 0x6963c5c8, 0x76cb5ad6, 0xd49974c9, 0xca180dcf, 0x380782d5, 0xc7fa5cf6, 0x8ac31511, 0x35e79e13, 0x47da91d0, 0xf40f9086, 0xa7e2419e, 0x31366241, 0x051ef495, 0xaa573b04, 0x4a805d8d, 0x548300d0, 0x00322a3c, 0xbf64cddf, 0xba57a68e, 0x75c6372b, 0x50afd341, 0xa7c13275, 0x915a0bf5, 0x6b54bfab, 0x2b0b1426, 0xab4cc9d7, 0x449ccd82, 0xf7fbf265, 0xab85c5f3, 0x1b55db94, 0xaad4e324, 0xcfa4bd3f, 0x2deaa3e2, 0x9e204d02, 0xc8bd25ac, 0xeadf55b3, 0xd5bd9e98, 0xe31231b2, 0x2ad5ad6c, 0x954329de, 0xadbe4528, 0xd8710f69, 0xaa51c90f, 0xaa786bf6, 0x22513f1e, 0xaa51a79b, 0x2ad344cc, 0x7b5a41f0, 0xd37cfbad, 0x1b069505, 0x41ece491, 0xb4c332e6, 0x032268d4, 0xc9600acc, 0xce387e6d, 0xbf6bb16c, 0x6a70fb78, 0x0d03d9c9, 0xd4df39de, 0xe01063da, 0x4736f464, 0x5ad328d8, 0xb347cc96, 0x75bb0fc3, 0x98511bfb, 0x4ffbcc35, 0xb58bcf6a, 0xe11f0abc, 0xbfc5fe4a, 0xa70aec10, 0xac39570a, 0x3f04442f, 0x6188b153, 0xe0397a2e, 0x5727cb79, 0x9ceb418f, 0x1cacd68d, 0x2ad37c96, 0x0175cb9d, 0xc69dff09, 0xc75b65f0, 0xd9db40d8, 0xec0e7779, 0x4744ead4, 0xb11c3274, 0xdd24cb9e, 0x7e1c54bd, 0xf01144f9, 0xd2240eb1, 0x9675b3fd, 0xa3ac3755, 0xd47c27af, 0x51c85f4d, 0x56907596, 0xa5bb15e6, 0x580304f0, 0xca042cf1, 0x011a37ea, 0x8dbfaadb, 0x35ba3e4a, 0x3526ffa0, 0xc37b4d09, 0xbc306ed9, 0x98a52666, 0x5648f725, 0xff5e569d, 0x0ced63d0, 0x7c63b2cf, 0x700b45e1, 0xd5ea50f1, 0x85a92872, 0xaf1fbda7, 0xd4234870, 0xa7870bf3, 0x2d3b4d79, 0x42e04198, 0x0cd0ede7, 0x26470db8, 0xf881814c, 0x474d6ad7, 0x7c0c5e5c, 0xd1231959, 0x381b7298, 0xf5d2f4db, 0xab838653, 0x6e2f1e23, 0x83719c9e, 0xbd91e046, 0x9a56456e, 0xdc39200c, 0x20c8c571, 0x962bda1c, 0xe1e696ff, 0xb141ab08, 0x7cca89b9, 0x1a69e783, 0x02cc4843, 0xa2f7c579, 0x429ef47d, 0x427b169c, 0x5ac9f049, 0xdd8f0f00, 0x5c8165bf, }, { 0x1f201094, 0xef0ba75b, 0x69e3cf7e, 0x393f4380, 0xfe61cf7a, 0xeec5207a, 0x55889c94, 0x72fc0651, 0xada7ef79, 0x4e1d7235, 0xd55a63ce, 0xde0436ba, 0x99c430ef, 0x5f0c0794, 0x18dcdb7d, 0xa1d6eff3, 0xa0b52f7b, 0x59e83605, 0xee15b094, 0xe9ffd909, 0xdc440086, 0xef944459, 0xba83ccb3, 0xe0c3cdfb, 0xd1da4181, 0x3b092ab1, 0xf997f1c1, 0xa5e6cf7b, 0x01420ddb, 0xe4e7ef5b, 0x25a1ff41, 0xe180f806, 0x1fc41080, 0x179bee7a, 0xd37ac6a9, 0xfe5830a4, 0x98de8b7f, 0x77e83f4e, 0x79929269, 0x24fa9f7b, 0xe113c85b, 0xacc40083, 0xd7503525, 0xf7ea615f, 0x62143154, 0x0d554b63, 0x5d681121, 0xc866c359, 0x3d63cf73, 0xcee234c0, 0xd4d87e87, 0x5c672b21, 0x071f6181, 0x39f7627f, 0x361e3084, 0xe4eb573b, 0x602f64a4, 0xd63acd9c, 0x1bbc4635, 0x9e81032d, 0x2701f50c, 0x99847ab4, 0xa0e3df79, 0xba6cf38c, 0x10843094, 0x2537a95e, 0xf46f6ffe, 0xa1ff3b1f, 0x208cfb6a, 0x8f458c74, 0xd9e0a227, 0x4ec73a34, 0xfc884f69, 0x3e4de8df, 0xef0e0088, 0x3559648d, 0x8a45388c, 0x1d804366, 0x721d9bfd, 0xa58684bb, 0xe8256333, 0x844e8212, 0x128d8098, 0xfed33fb4, 0xce280ae1, 0x27e19ba5, 0xd5a6c252, 0xe49754bd, 0xc5d655dd, 0xeb667064, 0x77840b4d, 0xa1b6a801, 0x84db26a9, 0xe0b56714, 0x21f043b7, 0xe5d05860, 0x54f03084, 0x066ff472, 0xa31aa153, 0xdadc4755, 0xb5625dbf, 0x68561be6, 0x83ca6b94, 0x2d6ed23b, 0xeccf01db, 0xa6d3d0ba, 0xb6803d5c, 0xaf77a709, 0x33b4a34c, 0x397bc8d6, 0x5ee22b95, 0x5f0e5304, 0x81ed6f61, 0x20e74364, 0xb45e1378, 0xde18639b, 0x881ca122, 0xb96726d1, 0x8049a7e8, 0x22b7da7b, 0x5e552d25, 0x5272d237, 0x79d2951c, 0xc60d894c, 0x488cb402, 0x1ba4fe5b, 0xa4b09f6b, 0x1ca815cf, 0xa20c3005, 0x8871df63, 0xb9de2fcb, 0x0cc6c9e9, 0x0beeff53, 0xe3214517, 0xb4542835, 0x9f63293c, 0xee41e729, 0x6e1d2d7c, 0x50045286, 0x1e6685f3, 0xf33401c6, 0x30a22c95, 0x31a70850, 0x60930f13, 0x73f98417, 0xa1269859, 0xec645c44, 0x52c877a9, 0xcdff33a6, 0xa02b1741, 0x7cbad9a2, 0x2180036f, 0x50d99c08, 0xcb3f4861, 0xc26bd765, 0x64a3f6ab, 0x80342676, 0x25a75e7b, 0xe4e6d1fc, 0x20c710e6, 0xcdf0b680, 0x17844d3b, 0x31eef84d, 0x7e0824e4, 0x2ccb49eb, 0x846a3bae, 0x8ff77888, 0xee5d60f6, 0x7af75673, 0x2fdd5cdb, 0xa11631c1, 0x30f66f43, 0xb3faec54, 0x157fd7fa, 0xef8579cc, 0xd152de58, 0xdb2ffd5e, 0x8f32ce19, 0x306af97a, 0x02f03ef8, 0x99319ad5, 0xc242fa0f, 0xa7e3ebb0, 0xc68e4906, 0xb8da230c, 0x80823028, 0xdcdef3c8, 0xd35fb171, 0x088a1bc8, 0xbec0c560, 0x61a3c9e8, 0xbca8f54d, 0xc72feffa, 0x22822e99, 0x82c570b4, 0xd8d94e89, 0x8b1c34bc, 0x301e16e6, 0x273be979, 0xb0ffeaa6, 0x61d9b8c6, 0x00b24869, 0xb7ffce3f, 0x08dc283b, 0x43daf65a, 0xf7e19798, 0x7619b72f, 0x8f1c9ba4, 0xdc8637a0, 0x16a7d3b1, 0x9fc393b7, 0xa7136eeb, 0xc6bcc63e, 0x1a513742, 0xef6828bc, 0x520365d6, 0x2d6a77ab, 0x3527ed4b, 0x821fd216, 0x095c6e2e, 0xdb92f2fb, 0x5eea29cb, 0x145892f5, 0x91584f7f, 0x5483697b, 0x2667a8cc, 0x85196048, 0x8c4bacea, 0x833860d4, 0x0d23e0f9, 0x6c387e8a, 0x0ae6d249, 0xb284600c, 0xd835731d, 0xdcb1c647, 0xac4c56ea, 0x3ebd81b3, 0x230eabb0, 0x6438bc87, 0xf0b5b1fa, 0x8f5ea2b3, 0xfc184642, 0x0a036b7a, 0x4fb089bd, 0x649da589, 0xa345415e, 0x5c038323, 0x3e5d3bb9, 0x43d79572, 0x7e6dd07c, 0x06dfdf1e, 0x6c6cc4ef, 0x7160a539, 0x73bfbe70, 0x83877605, 0x4523ecf1, }, { 0x8defc240, 0x25fa5d9f, 0xeb903dbf, 0xe810c907, 0x47607fff, 0x369fe44b, 0x8c1fc644, 0xaececa90, 0xbeb1f9bf, 0xeefbcaea, 0xe8cf1950, 0x51df07ae, 0x920e8806, 0xf0ad0548, 0xe13c8d83, 0x927010d5, 0x11107d9f, 0x07647db9, 0xb2e3e4d4, 0x3d4f285e, 0xb9afa820, 0xfade82e0, 0xa067268b, 0x8272792e, 0x553fb2c0, 0x489ae22b, 0xd4ef9794, 0x125e3fbc, 0x21fffcee, 0x825b1bfd, 0x9255c5ed, 0x1257a240, 0x4e1a8302, 0xbae07fff, 0x528246e7, 0x8e57140e, 0x3373f7bf, 0x8c9f8188, 0xa6fc4ee8, 0xc982b5a5, 0xa8c01db7, 0x579fc264, 0x67094f31, 0xf2bd3f5f, 0x40fff7c1, 0x1fb78dfc, 0x8e6bd2c1, 0x437be59b, 0x99b03dbf, 0xb5dbc64b, 0x638dc0e6, 0x55819d99, 0xa197c81c, 0x4a012d6e, 0xc5884a28, 0xccc36f71, 0xb843c213, 0x6c0743f1, 0x8309893c, 0x0feddd5f, 0x2f7fe850, 0xd7c07f7e, 0x02507fbf, 0x5afb9a04, 0xa747d2d0, 0x1651192e, 0xaf70bf3e, 0x58c31380, 0x5f98302e, 0x727cc3c4, 0x0a0fb402, 0x0f7fef82, 0x8c96fdad, 0x5d2c2aae, 0x8ee99a49, 0x50da88b8, 0x8427f4a0, 0x1eac5790, 0x796fb449, 0x8252dc15, 0xefbd7d9b, 0xa672597d, 0xada840d8, 0x45f54504, 0xfa5d7403, 0xe83ec305, 0x4f91751a, 0x925669c2, 0x23efe941, 0xa903f12e, 0x60270df2, 0x0276e4b6, 0x94fd6574, 0x927985b2, 0x8276dbcb, 0x02778176, 0xf8af918d, 0x4e48f79e, 0x8f616ddf, 0xe29d840e, 0x842f7d83, 0x340ce5c8, 0x96bbb682, 0x93b4b148, 0xef303cab, 0x984faf28, 0x779faf9b, 0x92dc560d, 0x224d1e20, 0x8437aa88, 0x7d29dc96, 0x2756d3dc, 0x8b907cee, 0xb51fd240, 0xe7c07ce3, 0xe566b4a1, 0xc3e9615e, 0x3cf8209d, 0x6094d1e3, 0xcd9ca341, 0x5c76460e, 0x00ea983b, 0xd4d67881, 0xfd47572c, 0xf76cedd9, 0xbda8229c, 0x127dadaa, 0x438a074e, 0x1f97c090, 0x081bdb8a, 0x93a07ebe, 0xb938ca15, 0x97b03cff, 0x3dc2c0f8, 0x8d1ab2ec, 0x64380e51, 0x68cc7bfb, 0xd90f2788, 0x12490181, 0x5de5ffd4, 0xdd7ef86a, 0x76a2e214, 0xb9a40368, 0x925d958f, 0x4b39fffa, 0xba39aee9, 0xa4ffd30b, 0xfaf7933b, 0x6d498623, 0x193cbcfa, 0x27627545, 0x825cf47a, 0x61bd8ba0, 0xd11e42d1, 0xcead04f4, 0x127ea392, 0x10428db7, 0x8272a972, 0x9270c4a8, 0x127de50b, 0x285ba1c8, 0x3c62f44f, 0x35c0eaa5, 0xe805d231, 0x428929fb, 0xb4fcdf82, 0x4fb66a53, 0x0e7dc15b, 0x1f081fab, 0x108618ae, 0xfcfd086d, 0xf9ff2889, 0x694bcc11, 0x236a5cae, 0x12deca4d, 0x2c3f8cc5, 0xd2d02dfe, 0xf8ef5896, 0xe4cf52da, 0x95155b67, 0x494a488c, 0xb9b6a80c, 0x5c8f82bc, 0x89d36b45, 0x3a609437, 0xec00c9a9, 0x44715253, 0x0a874b49, 0xd773bc40, 0x7c34671c, 0x02717ef6, 0x4feb5536, 0xa2d02fff, 0xd2bf60c4, 0xd43f03c0, 0x50b4ef6d, 0x07478cd1, 0x006e1888, 0xa2e53f55, 0xb9e6d4bc, 0xa2048016, 0x97573833, 0xd7207d67, 0xde0f8f3d, 0x72f87b33, 0xabcc4f33, 0x7688c55d, 0x7b00a6b0, 0x947b0001, 0x570075d2, 0xf9bb88f8, 0x8942019e, 0x4264a5ff, 0x856302e0, 0x72dbd92b, 0xee971b69, 0x6ea22fde, 0x5f08ae2b, 0xaf7a616d, 0xe5c98767, 0xcf1febd2, 0x61efc8c2, 0xf1ac2571, 0xcc8239c2, 0x67214cb8, 0xb1e583d1, 0xb7dc3e62, 0x7f10bdce, 0xf90a5c38, 0x0ff0443d, 0x606e6dc6, 0x60543a49, 0x5727c148, 0x2be98a1d, 0x8ab41738, 0x20e1be24, 0xaf96da0f, 0x68458425, 0x99833be5, 0x600d457d, 0x282f9350, 0x8334b362, 0xd91d1120, 0x2b6d8da0, 0x642b1e31, 0x9c305a00, 0x52bce688, 0x1b03588a, 0xf7baefd5, 0x4142ed9c, 0xa4315c11, 0x83323ec5, 0xdfef4636, 0xa133c501, 0xe9d3531c, 0xee353783, }, { 0x9db30420, 0x1fb6e9de, 0xa7be7bef, 0xd273a298, 0x4a4f7bdb, 0x64ad8c57, 0x85510443, 0xfa020ed1, 0x7e287aff, 0xe60fb663, 0x095f35a1, 0x79ebf120, 0xfd059d43, 0x6497b7b1, 0xf3641f63, 0x241e4adf, 0x28147f5f, 0x4fa2b8cd, 0xc9430040, 0x0cc32220, 0xfdd30b30, 0xc0a5374f, 0x1d2d00d9, 0x24147b15, 0xee4d111a, 0x0fca5167, 0x71ff904c, 0x2d195ffe, 0x1a05645f, 0x0c13fefe, 0x081b08ca, 0x05170121, 0x80530100, 0xe83e5efe, 0xac9af4f8, 0x7fe72701, 0xd2b8ee5f, 0x06df4261, 0xbb9e9b8a, 0x7293ea25, 0xce84ffdf, 0xf5718801, 0x3dd64b04, 0xa26f263b, 0x7ed48400, 0x547eebe6, 0x446d4ca0, 0x6cf3d6f5, 0x2649abdf, 0xaea0c7f5, 0x36338cc1, 0x503f7e93, 0xd3772061, 0x11b638e1, 0x72500e03, 0xf80eb2bb, 0xabe0502e, 0xec8d77de, 0x57971e81, 0xe14f6746, 0xc9335400, 0x6920318f, 0x081dbb99, 0xffc304a5, 0x4d351805, 0x7f3d5ce3, 0xa6c866c6, 0x5d5bcca9, 0xdaec6fea, 0x9f926f91, 0x9f46222f, 0x3991467d, 0xa5bf6d8e, 0x1143c44f, 0x43958302, 0xd0214eeb, 0x022083b8, 0x3fb6180c, 0x18f8931e, 0x281658e6, 0x26486e3e, 0x8bd78a70, 0x7477e4c1, 0xb506e07c, 0xf32d0a25, 0x79098b02, 0xe4eabb81, 0x28123b23, 0x69dead38, 0x1574ca16, 0xdf871b62, 0x211c40b7, 0xa51a9ef9, 0x0014377b, 0x041e8ac8, 0x09114003, 0xbd59e4d2, 0xe3d156d5, 0x4fe876d5, 0x2f91a340, 0x557be8de, 0x00eae4a7, 0x0ce5c2ec, 0x4db4bba6, 0xe756bdff, 0xdd3369ac, 0xec17b035, 0x06572327, 0x99afc8b0, 0x56c8c391, 0x6b65811c, 0x5e146119, 0x6e85cb75, 0xbe07c002, 0xc2325577, 0x893ff4ec, 0x5bbfc92d, 0xd0ec3b25, 0xb7801ab7, 0x8d6d3b24, 0x20c763ef, 0xc366a5fc, 0x9c382880, 0x0ace3205, 0xaac9548a, 0xeca1d7c7, 0x041afa32, 0x1d16625a, 0x6701902c, 0x9b757a54, 0x31d477f7, 0x9126b031, 0x36cc6fdb, 0xc70b8b46, 0xd9e66a48, 0x56e55a79, 0x026a4ceb, 0x52437eff, 0x2f8f76b4, 0x0df980a5, 0x8674cde3, 0xedda04eb, 0x17a9be04, 0x2c18f4df, 0xb7747f9d, 0xab2af7b4, 0xefc34d20, 0x2e096b7c, 0x1741a254, 0xe5b6a035, 0x213d42f6, 0x2c1c7c26, 0x61c2f50f, 0x6552daf9, 0xd2c231f8, 0x25130f69, 0xd8167fa2, 0x0418f2c8, 0x001a96a6, 0x0d1526ab, 0x63315c21, 0x5e0a72ec, 0x49bafefd, 0x187908d9, 0x8d0dbd86, 0x311170a7, 0x3e9b640c, 0xcc3e10d7, 0xd5cad3b6, 0x0caec388, 0xf73001e1, 0x6c728aff, 0x71eae2a1, 0x1f9af36e, 0xcfcbd12f, 0xc1de8417, 0xac07be6b, 0xcb44a1d8, 0x8b9b0f56, 0x013988c3, 0xb1c52fca, 0xb4be31cd, 0xd8782806, 0x12a3a4e2, 0x6f7de532, 0x58fd7eb6, 0xd01ee900, 0x24adffc2, 0xf4990fc5, 0x9711aac5, 0x001d7b95, 0x82e5e7d2, 0x109873f6, 0x00613096, 0xc32d9521, 0xada121ff, 0x29908415, 0x7fbb977f, 0xaf9eb3db, 0x29c9ed2a, 0x5ce2a465, 0xa730f32c, 0xd0aa3fe8, 0x8a5cc091, 0xd49e2ce7, 0x0ce454a9, 0xd60acd86, 0x015f1919, 0x77079103, 0xdea03af6, 0x78a8565e, 0xdee356df, 0x21f05cbe, 0x8b75e387, 0xb3c50651, 0xb8a5c3ef, 0xd8eeb6d2, 0xe523be77, 0xc2154529, 0x2f69efdf, 0xafe67afb, 0xf470c4b2, 0xf3e0eb5b, 0xd6cc9876, 0x39e4460c, 0x1fda8538, 0x1987832f, 0xca007367, 0xa99144f8, 0x296b299e, 0x492fc295, 0x9266beab, 0xb5676e69, 0x9bd3ddda, 0xdf7e052f, 0xdb25701c, 0x1b5e51ee, 0xf65324e6, 0x6afce36c, 0x0316cc04, 0x8644213e, 0xb7dc59d0, 0x7965291f, 0xccd6fd43, 0x41823979, 0x932bcdf6, 0xb657c34d, 0x4edfd282, 0x7ae5290c, 0x3cb9536b, 0x851e20fe, 0x9833557e, 0x13ecf0b0, 0xd3ffb372, 0x3f85c5c1, 0x0aef7ed2, }, { 0x7ec90c04, 0x2c6e74b9, 0x9b0e66df, 0xa6337911, 0xb86a7fff, 0x1dd358f5, 0x44dd9d44, 0x1731167f, 0x08fbf1fa, 0xe7f511cc, 0xd2051b00, 0x735aba00, 0x2ab722d8, 0x386381cb, 0xacf6243a, 0x69befd7a, 0xe6a2e77f, 0xf0c720cd, 0xc4494816, 0xccf5c180, 0x38851640, 0x15b0a848, 0xe68b18cb, 0x4caadeff, 0x5f480a01, 0x0412b2aa, 0x259814fc, 0x41d0efe2, 0x4e40b48d, 0x248eb6fb, 0x8dba1cfe, 0x41a99b02, 0x1a550a04, 0xba8f65cb, 0x7251f4e7, 0x95a51725, 0xc106ecd7, 0x97a5980a, 0xc539b9aa, 0x4d79fe6a, 0xf2f3f763, 0x68af8040, 0xed0c9e56, 0x11b4958b, 0xe1eb5a88, 0x8709e6b0, 0xd7e07156, 0x4e29fea7, 0x6366e52d, 0x02d1c000, 0xc4ac8e05, 0x9377f571, 0x0c05372a, 0x578535f2, 0x2261be02, 0xd642a0c9, 0xdf13a280, 0x74b55bd2, 0x682199c0, 0xd421e5ec, 0x53fb3ce8, 0xc8adedb3, 0x28a87fc9, 0x3d959981, 0x5c1ff900, 0xfe38d399, 0x0c4eff0b, 0x062407ea, 0xaa2f4fb1, 0x4fb96976, 0x90c79505, 0xb0a8a774, 0xef55a1ff, 0xe59ca2c2, 0xa6b62d27, 0xe66a4263, 0xdf65001f, 0x0ec50966, 0xdfdd55bc, 0x29de0655, 0x911e739a, 0x17af8975, 0x32c7911c, 0x89f89468, 0x0d01e980, 0x524755f4, 0x03b63cc9, 0x0cc844b2, 0xbcf3f0aa, 0x87ac36e9, 0xe53a7426, 0x01b3d82b, 0x1a9e7449, 0x64ee2d7e, 0xcddbb1da, 0x01c94910, 0xb868bf80, 0x0d26f3fd, 0x9342ede7, 0x04a5c284, 0x636737b6, 0x50f5b616, 0xf24766e3, 0x8eca36c1, 0x136e05db, 0xfef18391, 0xfb887a37, 0xd6e7f7d4, 0xc7fb7dc9, 0x3063fcdf, 0xb6f589de, 0xec2941da, 0x26e46695, 0xb7566419, 0xf654efc5, 0xd08d58b7, 0x48925401, 0xc1bacb7f, 0xe5ff550f, 0xb6083049, 0x5bb5d0e8, 0x87d72e5a, 0xab6a6ee1, 0x223a66ce, 0xc62bf3cd, 0x9e0885f9, 0x68cb3e47, 0x086c010f, 0xa21de820, 0xd18b69de, 0xf3f65777, 0xfa02c3f6, 0x407edac3, 0xcbb3d550, 0x1793084d, 0xb0d70eba, 0x0ab378d5, 0xd951fb0c, 0xded7da56, 0x4124bbe4, 0x94ca0b56, 0x0f5755d1, 0xe0e1e56e, 0x6184b5be, 0x580a249f, 0x94f74bc0, 0xe327888e, 0x9f7b5561, 0xc3dc0280, 0x05687715, 0x646c6bd7, 0x44904db3, 0x66b4f0a3, 0xc0f1648a, 0x697ed5af, 0x49e92ff6, 0x309e374f, 0x2cb6356a, 0x85808573, 0x4991f840, 0x76f0ae02, 0x083be84d, 0x28421c9a, 0x44489406, 0x736e4cb8, 0xc1092910, 0x8bc95fc6, 0x7d869cf4, 0x134f616f, 0x2e77118d, 0xb31b2be1, 0xaa90b472, 0x3ca5d717, 0x7d161bba, 0x9cad9010, 0xaf462ba2, 0x9fe459d2, 0x45d34559, 0xd9f2da13, 0xdbc65487, 0xf3e4f94e, 0x176d486f, 0x097c13ea, 0x631da5c7, 0x445f7382, 0x175683f4, 0xcdc66a97, 0x70be0288, 0xb3cdcf72, 0x6e5dd2f3, 0x20936079, 0x459b80a5, 0xbe60e2db, 0xa9c23101, 0xeba5315c, 0x224e42f2, 0x1c5c1572, 0xf6721b2c, 0x1ad2fff3, 0x8c25404e, 0x324ed72f, 0x4067b7fd, 0x0523138e, 0x5ca3bc78, 0xdc0fd66e, 0x75922283, 0x784d6b17, 0x58ebb16e, 0x44094f85, 0x3f481d87, 0xfcfeae7b, 0x77b5ff76, 0x8c2302bf, 0xaaf47556, 0x5f46b02a, 0x2b092801, 0x3d38f5f7, 0x0ca81f36, 0x52af4a8a, 0x66d5e7c0, 0xdf3b0874, 0x95055110, 0x1b5ad7a8, 0xf61ed5ad, 0x6cf6e479, 0x20758184, 0xd0cefa65, 0x88f7be58, 0x4a046826, 0x0ff6f8f3, 0xa09c7f70, 0x5346aba0, 0x5ce96c28, 0xe176eda3, 0x6bac307f, 0x376829d2, 0x85360fa9, 0x17e3fe2a, 0x24b79767, 0xf5a96b20, 0xd6cd2595, 0x68ff1ebf, 0x7555442c, 0xf19f06be, 0xf9e0659a, 0xeeb9491d, 0x34010718, 0xbb30cab8, 0xe822fe15, 0x88570983, 0x750e6249, 0xda627e55, 0x5e76ffa8, 0xb1534546, 0x6d47de08, 0xefe9e7d4, }, { 0xf6fa8f9d, 0x2cac6ce1, 0x4ca34867, 0xe2337f7c, 0x95db08e7, 0x016843b4, 0xeced5cbc, 0x325553ac, 0xbf9f0960, 0xdfa1e2ed, 0x83f0579d, 0x63ed86b9, 0x1ab6a6b8, 0xde5ebe39, 0xf38ff732, 0x8989b138, 0x33f14961, 0xc01937bd, 0xf506c6da, 0xe4625e7e, 0xa308ea99, 0x4e23e33c, 0x79cbd7cc, 0x48a14367, 0xa3149619, 0xfec94bd5, 0xa114174a, 0xeaa01866, 0xa084db2d, 0x09a8486f, 0xa888614a, 0x2900af98, 0x01665991, 0xe1992863, 0xc8f30c60, 0x2e78ef3c, 0xd0d51932, 0xcf0fec14, 0xf7ca07d2, 0xd0a82072, 0xfd41197e, 0x9305a6b0, 0xe86be3da, 0x74bed3cd, 0x372da53c, 0x4c7f4448, 0xdab5d440, 0x6dba0ec3, 0x083919a7, 0x9fbaeed9, 0x49dbcfb0, 0x4e670c53, 0x5c3d9c01, 0x64bdb941, 0x2c0e636a, 0xba7dd9cd, 0xea6f7388, 0xe70bc762, 0x35f29adb, 0x5c4cdd8d, 0xf0d48d8c, 0xb88153e2, 0x08a19866, 0x1ae2eac8, 0x284caf89, 0xaa928223, 0x9334be53, 0x3b3a21bf, 0x16434be3, 0x9aea3906, 0xefe8c36e, 0xf890cdd9, 0x80226dae, 0xc340a4a3, 0xdf7e9c09, 0xa694a807, 0x5b7c5ecc, 0x221db3a6, 0x9a69a02f, 0x68818a54, 0xceb2296f, 0x53c0843a, 0xfe893655, 0x25bfe68a, 0xb4628abc, 0xcf222ebf, 0x25ac6f48, 0xa9a99387, 0x53bddb65, 0xe76ffbe7, 0xe967fd78, 0x0ba93563, 0x8e342bc1, 0xe8a11be9, 0x4980740d, 0xc8087dfc, 0x8de4bf99, 0xa11101a0, 0x7fd37975, 0xda5a26c0, 0xe81f994f, 0x9528cd89, 0xfd339fed, 0xb87834bf, 0x5f04456d, 0x22258698, 0xc9c4c83b, 0x2dc156be, 0x4f628daa, 0x57f55ec5, 0xe2220abe, 0xd2916ebf, 0x4ec75b95, 0x24f2c3c0, 0x42d15d99, 0xcd0d7fa0, 0x7b6e27ff, 0xa8dc8af0, 0x7345c106, 0xf41e232f, 0x35162386, 0xe6ea8926, 0x3333b094, 0x157ec6f2, 0x372b74af, 0x692573e4, 0xe9a9d848, 0xf3160289, 0x3a62ef1d, 0xa787e238, 0xf3a5f676, 0x74364853, 0x20951063, 0x4576698d, 0xb6fad407, 0x592af950, 0x36f73523, 0x4cfb6e87, 0x7da4cec0, 0x6c152daa, 0xcb0396a8, 0xc50dfe5d, 0xfcd707ab, 0x0921c42f, 0x89dff0bb, 0x5fe2be78, 0x448f4f33, 0x754613c9, 0x2b05d08d, 0x48b9d585, 0xdc049441, 0xc8098f9b, 0x7dede786, 0xc39a3373, 0x42410005, 0x6a091751, 0x0ef3c8a6, 0x890072d6, 0x28207682, 0xa9a9f7be, 0xbf32679d, 0xd45b5b75, 0xb353fd00, 0xcbb0e358, 0x830f220a, 0x1f8fb214, 0xd372cf08, 0xcc3c4a13, 0x8cf63166, 0x061c87be, 0x88c98f88, 0x6062e397, 0x47cf8e7a, 0xb6c85283, 0x3cc2acfb, 0x3fc06976, 0x4e8f0252, 0x64d8314d, 0xda3870e3, 0x1e665459, 0xc10908f0, 0x513021a5, 0x6c5b68b7, 0x822f8aa0, 0x3007cd3e, 0x74719eef, 0xdc872681, 0x073340d4, 0x7e432fd9, 0x0c5ec241, 0x8809286c, 0xf592d891, 0x08a930f6, 0x957ef305, 0xb7fbffbd, 0xc266e96f, 0x6fe4ac98, 0xb173ecc0, 0xbc60b42a, 0x953498da, 0xfba1ae12, 0x2d4bd736, 0x0f25faab, 0xa4f3fceb, 0xe2969123, 0x257f0c3d, 0x9348af49, 0x361400bc, 0xe8816f4a, 0x3814f200, 0xa3f94043, 0x9c7a54c2, 0xbc704f57, 0xda41e7f9, 0xc25ad33a, 0x54f4a084, 0xb17f5505, 0x59357cbe, 0xedbd15c8, 0x7f97c5ab, 0xba5ac7b5, 0xb6f6deaf, 0x3a479c3a, 0x5302da25, 0x653d7e6a, 0x54268d49, 0x51a477ea, 0x5017d55b, 0xd7d25d88, 0x44136c76, 0x0404a8c8, 0xb8e5a121, 0xb81a928a, 0x60ed5869, 0x97c55b96, 0xeaec991b, 0x29935913, 0x01fdb7f1, 0x088e8dfa, 0x9ab6f6f5, 0x3b4cbf9f, 0x4a5de3ab, 0xe6051d35, 0xa0e1d855, 0xd36b4cf1, 0xf544edeb, 0xb0e93524, 0xbebb8fbd, 0xa2d762cf, 0x49c92f54, 0x38b5f331, 0x7128a454, 0x48392905, 0xa65b1db8, 0x851c97bd, 0xd675cf2f, }, { 0x85e04019, 0x332bf567, 0x662dbfff, 0xcfc65693, 0x2a8d7f6f, 0xab9bc912, 0xde6008a1, 0x2028da1f, 0x0227bce7, 0x4d642916, 0x18fac300, 0x50f18b82, 0x2cb2cb11, 0xb232e75c, 0x4b3695f2, 0xb28707de, 0xa05fbcf6, 0xcd4181e9, 0xe150210c, 0xe24ef1bd, 0xb168c381, 0xfde4e789, 0x5c79b0d8, 0x1e8bfd43, 0x4d495001, 0x38be4341, 0x913cee1d, 0x92a79c3f, 0x089766be, 0xbaeeadf4, 0x1286becf, 0xb6eacb19, 0x2660c200, 0x7565bde4, 0x64241f7a, 0x8248dca9, 0xc3b3ad66, 0x28136086, 0x0bd8dfa8, 0x356d1cf2, 0x107789be, 0xb3b2e9ce, 0x0502aa8f, 0x0bc0351e, 0x166bf52a, 0xeb12ff82, 0xe3486911, 0xd34d7516, 0x4e7b3aff, 0x5f43671b, 0x9cf6e037, 0x4981ac83, 0x334266ce, 0x8c9341b7, 0xd0d854c0, 0xcb3a6c88, 0x47bc2829, 0x4725ba37, 0xa66ad22b, 0x7ad61f1e, 0x0c5cbafa, 0x4437f107, 0xb6e79962, 0x42d2d816, 0x0a961288, 0xe1a5c06e, 0x13749e67, 0x72fc081a, 0xb1d139f7, 0xf9583745, 0xcf19df58, 0xbec3f756, 0xc06eba30, 0x07211b24, 0x45c28829, 0xc95e317f, 0xbc8ec511, 0x38bc46e9, 0xc6e6fa14, 0xbae8584a, 0xad4ebc46, 0x468f508b, 0x7829435f, 0xf124183b, 0x821dba9f, 0xaff60ff4, 0xea2c4e6d, 0x16e39264, 0x92544a8b, 0x009b4fc3, 0xaba68ced, 0x9ac96f78, 0x06a5b79a, 0xb2856e6e, 0x1aec3ca9, 0xbe838688, 0x0e0804e9, 0x55f1be56, 0xe7e5363b, 0xb3a1f25d, 0xf7debb85, 0x61fe033c, 0x16746233, 0x3c034c28, 0xda6d0c74, 0x79aac56c, 0x3ce4e1ad, 0x51f0c802, 0x98f8f35a, 0x1626a49f, 0xeed82b29, 0x1d382fe3, 0x0c4fb99a, 0xbb325778, 0x3ec6d97b, 0x6e77a6a9, 0xcb658b5c, 0xd45230c7, 0x2bd1408b, 0x60c03eb7, 0xb9068d78, 0xa33754f4, 0xf430c87d, 0xc8a71302, 0xb96d8c32, 0xebd4e7be, 0xbe8b9d2d, 0x7979fb06, 0xe7225308, 0x8b75cf77, 0x11ef8da4, 0xe083c858, 0x8d6b786f, 0x5a6317a6, 0xfa5cf7a0, 0x5dda0033, 0xf28ebfb0, 0xf5b9c310, 0xa0eac280, 0x08b9767a, 0xa3d9d2b0, 0x79d34217, 0x021a718d, 0x9ac6336a, 0x2711fd60, 0x438050e3, 0x069908a8, 0x3d7fedc4, 0x826d2bef, 0x4eeb8476, 0x488dcf25, 0x36c9d566, 0x28e74e41, 0xc2610aca, 0x3d49a9cf, 0xbae3b9df, 0xb65f8de6, 0x92aeaf64, 0x3ac7d5e6, 0x9ea80509, 0xf22b017d, 0xa4173f70, 0xdd1e16c3, 0x15e0d7f9, 0x50b1b887, 0x2b9f4fd5, 0x625aba82, 0x6a017962, 0x2ec01b9c, 0x15488aa9, 0xd716e740, 0x40055a2c, 0x93d29a22, 0xe32dbf9a, 0x058745b9, 0x3453dc1e, 0xd699296e, 0x496cff6f, 0x1c9f4986, 0xdfe2ed07, 0xb87242d1, 0x19de7eae, 0x053e561a, 0x15ad6f8c, 0x66626c1c, 0x7154c24c, 0xea082b2a, 0x93eb2939, 0x17dcb0f0, 0x58d4f2ae, 0x9ea294fb, 0x52cf564c, 0x9883fe66, 0x2ec40581, 0x763953c3, 0x01d6692e, 0xd3a0c108, 0xa1e7160e, 0xe4f2dfa6, 0x693ed285, 0x74904698, 0x4c2b0edd, 0x4f757656, 0x5d393378, 0xa132234f, 0x3d321c5d, 0xc3f5e194, 0x4b269301, 0xc79f022f, 0x3c997e7e, 0x5e4f9504, 0x3ffafbbd, 0x76f7ad0e, 0x296693f4, 0x3d1fce6f, 0xc61e45be, 0xd3b5ab34, 0xf72bf9b7, 0x1b0434c0, 0x4e72b567, 0x5592a33d, 0xb5229301, 0xcfd2a87f, 0x60aeb767, 0x1814386b, 0x30bcc33d, 0x38a0c07d, 0xfd1606f2, 0xc363519b, 0x589dd390, 0x5479f8e6, 0x1cb8d647, 0x97fd61a9, 0xea7759f4, 0x2d57539d, 0x569a58cf, 0xe84e63ad, 0x462e1b78, 0x6580f87e, 0xf3817914, 0x91da55f4, 0x40a230f3, 0xd1988f35, 0xb6e318d2, 0x3ffa50bc, 0x3d40f021, 0xc3c0bdae, 0x4958c24c, 0x518f36b2, 0x84b1d370, 0x0fedce83, 0x878ddada, 0xf2a279c7, 0x94e01be8, 0x90716f4b, 0x954b8aa3, }, { 0xe216300d, 0xbbddfffc, 0xa7ebdabd, 0x35648095, 0x7789f8b7, 0xe6c1121b, 0x0e241600, 0x052ce8b5, 0x11a9cfb0, 0xe5952f11, 0xece7990a, 0x9386d174, 0x2a42931c, 0x76e38111, 0xb12def3a, 0x37ddddfc, 0xde9adeb1, 0x0a0cc32c, 0xbe197029, 0x84a00940, 0xbb243a0f, 0xb4d137cf, 0xb44e79f0, 0x049eedfd, 0x0b15a15d, 0x480d3168, 0x8bbbde5a, 0x669ded42, 0xc7ece831, 0x3f8f95e7, 0x72df191b, 0x7580330d, 0x94074251, 0x5c7dcdfa, 0xabbe6d63, 0xaa402164, 0xb301d40a, 0x02e7d1ca, 0x53571dae, 0x7a3182a2, 0x12a8ddec, 0xfdaa335d, 0x176f43e8, 0x71fb46d4, 0x38129022, 0xce949ad4, 0xb84769ad, 0x965bd862, 0x82f3d055, 0x66fb9767, 0x15b80b4e, 0x1d5b47a0, 0x4cfde06f, 0xc28ec4b8, 0x57e8726e, 0x647a78fc, 0x99865d44, 0x608bd593, 0x6c200e03, 0x39dc5ff6, 0x5d0b00a3, 0xae63aff2, 0x7e8bd632, 0x70108c0c, 0xbbd35049, 0x2998df04, 0x980cf42a, 0x9b6df491, 0x9e7edd53, 0x06918548, 0x58cb7e07, 0x3b74ef2e, 0x522fffb1, 0xd24708cc, 0x1c7e27cd, 0xa4eb215b, 0x3cf1d2e2, 0x19b47a38, 0x424f7618, 0x35856039, 0x9d17dee7, 0x27eb35e6, 0xc9aff67b, 0x36baf5b8, 0x09c467cd, 0xc18910b1, 0xe11dbf7b, 0x06cd1af8, 0x7170c608, 0x2d5e3354, 0xd4de495a, 0x64c6d006, 0xbcc0c62c, 0x3dd00db3, 0x708f8f34, 0x77d51b42, 0x264f620f, 0x24b8d2bf, 0x15c1b79e, 0x46a52564, 0xf8d7e54e, 0x3e378160, 0x7895cda5, 0x859c15a5, 0xe6459788, 0xc37bc75f, 0xdb07ba0c, 0x0676a3ab, 0x7f229b1e, 0x31842e7b, 0x24259fd7, 0xf8bef472, 0x835ffcb8, 0x6df4c1f2, 0x96f5b195, 0xfd0af0fc, 0xb0fe134c, 0xe2506d3d, 0x4f9b12ea, 0xf215f225, 0xa223736f, 0x9fb4c428, 0x25d04979, 0x34c713f8, 0xc4618187, 0xea7a6e98, 0x7cd16efc, 0x1436876c, 0xf1544107, 0xbedeee14, 0x56e9af27, 0xa04aa441, 0x3cf7c899, 0x92ecbae6, 0xdd67016d, 0x151682eb, 0xa842eedf, 0xfdba60b4, 0xf1907b75, 0x20e3030f, 0x24d8c29e, 0xe139673b, 0xefa63fb8, 0x71873054, 0xb6f2cf3b, 0x9f326442, 0xcb15a4cc, 0xb01a4504, 0xf1e47d8d, 0x844a1be5, 0xbae7dfdc, 0x42cbda70, 0xcd7dae0a, 0x57e85b7a, 0xd53f5af6, 0x20cf4d8c, 0xcea4d428, 0x79d130a4, 0x3486ebfb, 0x33d3cddc, 0x77853b53, 0x37effcb5, 0xc5068778, 0xe580b3e6, 0x4e68b8f4, 0xc5c8b37e, 0x0d809ea2, 0x398feb7c, 0x132a4f94, 0x43b7950e, 0x2fee7d1c, 0x223613bd, 0xdd06caa2, 0x37df932b, 0xc4248289, 0xacf3ebc3, 0x5715f6b7, 0xef3478dd, 0xf267616f, 0xc148cbe4, 0x9052815e, 0x5e410fab, 0xb48a2465, 0x2eda7fa4, 0xe87b40e4, 0xe98ea084, 0x5889e9e1, 0xefd390fc, 0xdd07d35b, 0xdb485694, 0x38d7e5b2, 0x57720101, 0x730edebc, 0x5b643113, 0x94917e4f, 0x503c2fba, 0x646f1282, 0x7523d24a, 0xe0779695, 0xf9c17a8f, 0x7a5b2121, 0xd187b896, 0x29263a4d, 0xba510cdf, 0x81f47c9f, 0xad1163ed, 0xea7b5965, 0x1a00726e, 0x11403092, 0x00da6d77, 0x4a0cdd61, 0xad1f4603, 0x605bdfb0, 0x9eedc364, 0x22ebe6a8, 0xcee7d28a, 0xa0e736a0, 0x5564a6b9, 0x10853209, 0xc7eb8f37, 0x2de705ca, 0x8951570f, 0xdf09822b, 0xbd691a6c, 0xaa12e4f2, 0x87451c0f, 0xe0f6a27a, 0x3ada4819, 0x4cf1764f, 0x0d771c2b, 0x67cdb156, 0x350d8384, 0x5938fa0f, 0x42399ef3, 0x36997b07, 0x0e84093d, 0x4aa93e61, 0x8360d87b, 0x1fa98b0c, 0x1149382c, 0xe97625a5, 0x0614d1b7, 0x0e25244b, 0x0c768347, 0x589e8d82, 0x0d2059d1, 0xa466bb1e, 0xf8da0a82, 0x04f19130, 0xba6e4ec0, 0x99265164, 0x1ee7230d, 0x50b2ad80, 0xeaee6801, 0x8db2a283, 0xea8bf59e, }, } lxd-2.0.0/dist/src/golang.org/x/crypto/cast5/cast5_test.go0000644061062106075000000000510012702772344025714 0ustar00stgraberdomain admins00000000000000// Copyright 2010 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package cast5 import ( "bytes" "encoding/hex" "testing" ) // This test vector is taken from RFC 2144, App B.1. // Since the other two test vectors are for reduced-round variants, we can't // use them. var basicTests = []struct { key, plainText, cipherText string }{ { "0123456712345678234567893456789a", "0123456789abcdef", "238b4fe5847e44b2", }, } func TestBasic(t *testing.T) { for i, test := range basicTests { key, _ := hex.DecodeString(test.key) plainText, _ := hex.DecodeString(test.plainText) expected, _ := hex.DecodeString(test.cipherText) c, err := NewCipher(key) if err != nil { t.Errorf("#%d: failed to create Cipher: %s", i, err) continue } var cipherText [BlockSize]byte c.Encrypt(cipherText[:], plainText) if !bytes.Equal(cipherText[:], expected) { t.Errorf("#%d: got:%x want:%x", i, cipherText, expected) } var plainTextAgain [BlockSize]byte c.Decrypt(plainTextAgain[:], cipherText[:]) if !bytes.Equal(plainTextAgain[:], plainText) { t.Errorf("#%d: got:%x want:%x", i, plainTextAgain, plainText) } } } // TestFull performs the test specified in RFC 2144, App B.2. // However, due to the length of time taken, it's disabled here and a more // limited version is included, below. func TestFull(t *testing.T) { if testing.Short() { // This is too slow for normal testing return } a, b := iterate(1000000) const expectedA = "eea9d0a249fd3ba6b3436fb89d6dca92" const expectedB = "b2c95eb00c31ad7180ac05b8e83d696e" if hex.EncodeToString(a) != expectedA { t.Errorf("a: got:%x want:%s", a, expectedA) } if hex.EncodeToString(b) != expectedB { t.Errorf("b: got:%x want:%s", b, expectedB) } } func iterate(iterations int) ([]byte, []byte) { const initValueHex = "0123456712345678234567893456789a" initValue, _ := hex.DecodeString(initValueHex) var a, b [16]byte copy(a[:], initValue) copy(b[:], initValue) for i := 0; i < iterations; i++ { c, _ := NewCipher(b[:]) c.Encrypt(a[:8], a[:8]) c.Encrypt(a[8:], a[8:]) c, _ = NewCipher(a[:]) c.Encrypt(b[:8], b[:8]) c.Encrypt(b[8:], b[8:]) } return a[:], b[:] } func TestLimited(t *testing.T) { a, b := iterate(1000) const expectedA = "23f73b14b02a2ad7dfb9f2c35644798d" const expectedB = "e5bf37eff14c456a40b21ce369370a9f" if hex.EncodeToString(a) != expectedA { t.Errorf("a: got:%x want:%s", a, expectedA) } if hex.EncodeToString(b) != expectedB { t.Errorf("b: got:%x want:%s", b, expectedB) } } lxd-2.0.0/dist/src/golang.org/x/crypto/ssh/0000755061062106075000000000000012702772344023071 5ustar00stgraberdomain admins00000000000000lxd-2.0.0/dist/src/golang.org/x/crypto/ssh/kex.go0000644061062106075000000003276412702772344024223 0ustar00stgraberdomain admins00000000000000// Copyright 2013 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 ssh import ( "crypto" "crypto/ecdsa" "crypto/elliptic" "crypto/rand" "crypto/subtle" "errors" "io" "math/big" "golang.org/x/crypto/curve25519" ) const ( kexAlgoDH1SHA1 = "diffie-hellman-group1-sha1" kexAlgoDH14SHA1 = "diffie-hellman-group14-sha1" kexAlgoECDH256 = "ecdh-sha2-nistp256" kexAlgoECDH384 = "ecdh-sha2-nistp384" kexAlgoECDH521 = "ecdh-sha2-nistp521" kexAlgoCurve25519SHA256 = "curve25519-sha256@libssh.org" ) // kexResult captures the outcome of a key exchange. type kexResult struct { // Session hash. See also RFC 4253, section 8. H []byte // Shared secret. See also RFC 4253, section 8. K []byte // Host key as hashed into H. HostKey []byte // Signature of H. Signature []byte // A cryptographic hash function that matches the security // level of the key exchange algorithm. It is used for // calculating H, and for deriving keys from H and K. Hash crypto.Hash // The session ID, which is the first H computed. This is used // to signal data inside transport. SessionID []byte } // handshakeMagics contains data that is always included in the // session hash. type handshakeMagics struct { clientVersion, serverVersion []byte clientKexInit, serverKexInit []byte } func (m *handshakeMagics) write(w io.Writer) { writeString(w, m.clientVersion) writeString(w, m.serverVersion) writeString(w, m.clientKexInit) writeString(w, m.serverKexInit) } // kexAlgorithm abstracts different key exchange algorithms. type kexAlgorithm interface { // Server runs server-side key agreement, signing the result // with a hostkey. Server(p packetConn, rand io.Reader, magics *handshakeMagics, s Signer) (*kexResult, error) // Client runs the client-side key agreement. Caller is // responsible for verifying the host key signature. Client(p packetConn, rand io.Reader, magics *handshakeMagics) (*kexResult, error) } // dhGroup is a multiplicative group suitable for implementing Diffie-Hellman key agreement. type dhGroup struct { g, p *big.Int } func (group *dhGroup) diffieHellman(theirPublic, myPrivate *big.Int) (*big.Int, error) { if theirPublic.Sign() <= 0 || theirPublic.Cmp(group.p) >= 0 { return nil, errors.New("ssh: DH parameter out of bounds") } return new(big.Int).Exp(theirPublic, myPrivate, group.p), nil } func (group *dhGroup) Client(c packetConn, randSource io.Reader, magics *handshakeMagics) (*kexResult, error) { hashFunc := crypto.SHA1 x, err := rand.Int(randSource, group.p) if err != nil { return nil, err } X := new(big.Int).Exp(group.g, x, group.p) kexDHInit := kexDHInitMsg{ X: X, } if err := c.writePacket(Marshal(&kexDHInit)); err != nil { return nil, err } packet, err := c.readPacket() if err != nil { return nil, err } var kexDHReply kexDHReplyMsg if err = Unmarshal(packet, &kexDHReply); err != nil { return nil, err } kInt, err := group.diffieHellman(kexDHReply.Y, x) if err != nil { return nil, err } h := hashFunc.New() magics.write(h) writeString(h, kexDHReply.HostKey) writeInt(h, X) writeInt(h, kexDHReply.Y) K := make([]byte, intLength(kInt)) marshalInt(K, kInt) h.Write(K) return &kexResult{ H: h.Sum(nil), K: K, HostKey: kexDHReply.HostKey, Signature: kexDHReply.Signature, Hash: crypto.SHA1, }, nil } func (group *dhGroup) Server(c packetConn, randSource io.Reader, magics *handshakeMagics, priv Signer) (result *kexResult, err error) { hashFunc := crypto.SHA1 packet, err := c.readPacket() if err != nil { return } var kexDHInit kexDHInitMsg if err = Unmarshal(packet, &kexDHInit); err != nil { return } y, err := rand.Int(randSource, group.p) if err != nil { return } Y := new(big.Int).Exp(group.g, y, group.p) kInt, err := group.diffieHellman(kexDHInit.X, y) if err != nil { return nil, err } hostKeyBytes := priv.PublicKey().Marshal() h := hashFunc.New() magics.write(h) writeString(h, hostKeyBytes) writeInt(h, kexDHInit.X) writeInt(h, Y) K := make([]byte, intLength(kInt)) marshalInt(K, kInt) h.Write(K) H := h.Sum(nil) // H is already a hash, but the hostkey signing will apply its // own key-specific hash algorithm. sig, err := signAndMarshal(priv, randSource, H) if err != nil { return nil, err } kexDHReply := kexDHReplyMsg{ HostKey: hostKeyBytes, Y: Y, Signature: sig, } packet = Marshal(&kexDHReply) err = c.writePacket(packet) return &kexResult{ H: H, K: K, HostKey: hostKeyBytes, Signature: sig, Hash: crypto.SHA1, }, nil } // ecdh performs Elliptic Curve Diffie-Hellman key exchange as // described in RFC 5656, section 4. type ecdh struct { curve elliptic.Curve } func (kex *ecdh) Client(c packetConn, rand io.Reader, magics *handshakeMagics) (*kexResult, error) { ephKey, err := ecdsa.GenerateKey(kex.curve, rand) if err != nil { return nil, err } kexInit := kexECDHInitMsg{ ClientPubKey: elliptic.Marshal(kex.curve, ephKey.PublicKey.X, ephKey.PublicKey.Y), } serialized := Marshal(&kexInit) if err := c.writePacket(serialized); err != nil { return nil, err } packet, err := c.readPacket() if err != nil { return nil, err } var reply kexECDHReplyMsg if err = Unmarshal(packet, &reply); err != nil { return nil, err } x, y, err := unmarshalECKey(kex.curve, reply.EphemeralPubKey) if err != nil { return nil, err } // generate shared secret secret, _ := kex.curve.ScalarMult(x, y, ephKey.D.Bytes()) h := ecHash(kex.curve).New() magics.write(h) writeString(h, reply.HostKey) writeString(h, kexInit.ClientPubKey) writeString(h, reply.EphemeralPubKey) K := make([]byte, intLength(secret)) marshalInt(K, secret) h.Write(K) return &kexResult{ H: h.Sum(nil), K: K, HostKey: reply.HostKey, Signature: reply.Signature, Hash: ecHash(kex.curve), }, nil } // unmarshalECKey parses and checks an EC key. func unmarshalECKey(curve elliptic.Curve, pubkey []byte) (x, y *big.Int, err error) { x, y = elliptic.Unmarshal(curve, pubkey) if x == nil { return nil, nil, errors.New("ssh: elliptic.Unmarshal failure") } if !validateECPublicKey(curve, x, y) { return nil, nil, errors.New("ssh: public key not on curve") } return x, y, nil } // validateECPublicKey checks that the point is a valid public key for // the given curve. See [SEC1], 3.2.2 func validateECPublicKey(curve elliptic.Curve, x, y *big.Int) bool { if x.Sign() == 0 && y.Sign() == 0 { return false } if x.Cmp(curve.Params().P) >= 0 { return false } if y.Cmp(curve.Params().P) >= 0 { return false } if !curve.IsOnCurve(x, y) { return false } // We don't check if N * PubKey == 0, since // // - the NIST curves have cofactor = 1, so this is implicit. // (We don't foresee an implementation that supports non NIST // curves) // // - for ephemeral keys, we don't need to worry about small // subgroup attacks. return true } func (kex *ecdh) Server(c packetConn, rand io.Reader, magics *handshakeMagics, priv Signer) (result *kexResult, err error) { packet, err := c.readPacket() if err != nil { return nil, err } var kexECDHInit kexECDHInitMsg if err = Unmarshal(packet, &kexECDHInit); err != nil { return nil, err } clientX, clientY, err := unmarshalECKey(kex.curve, kexECDHInit.ClientPubKey) if err != nil { return nil, err } // We could cache this key across multiple users/multiple // connection attempts, but the benefit is small. OpenSSH // generates a new key for each incoming connection. ephKey, err := ecdsa.GenerateKey(kex.curve, rand) if err != nil { return nil, err } hostKeyBytes := priv.PublicKey().Marshal() serializedEphKey := elliptic.Marshal(kex.curve, ephKey.PublicKey.X, ephKey.PublicKey.Y) // generate shared secret secret, _ := kex.curve.ScalarMult(clientX, clientY, ephKey.D.Bytes()) h := ecHash(kex.curve).New() magics.write(h) writeString(h, hostKeyBytes) writeString(h, kexECDHInit.ClientPubKey) writeString(h, serializedEphKey) K := make([]byte, intLength(secret)) marshalInt(K, secret) h.Write(K) H := h.Sum(nil) // H is already a hash, but the hostkey signing will apply its // own key-specific hash algorithm. sig, err := signAndMarshal(priv, rand, H) if err != nil { return nil, err } reply := kexECDHReplyMsg{ EphemeralPubKey: serializedEphKey, HostKey: hostKeyBytes, Signature: sig, } serialized := Marshal(&reply) if err := c.writePacket(serialized); err != nil { return nil, err } return &kexResult{ H: H, K: K, HostKey: reply.HostKey, Signature: sig, Hash: ecHash(kex.curve), }, nil } var kexAlgoMap = map[string]kexAlgorithm{} func init() { // This is the group called diffie-hellman-group1-sha1 in RFC // 4253 and Oakley Group 2 in RFC 2409. p, _ := new(big.Int).SetString("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF", 16) kexAlgoMap[kexAlgoDH1SHA1] = &dhGroup{ g: new(big.Int).SetInt64(2), p: p, } // This is the group called diffie-hellman-group14-sha1 in RFC // 4253 and Oakley Group 14 in RFC 3526. p, _ = new(big.Int).SetString("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF", 16) kexAlgoMap[kexAlgoDH14SHA1] = &dhGroup{ g: new(big.Int).SetInt64(2), p: p, } kexAlgoMap[kexAlgoECDH521] = &ecdh{elliptic.P521()} kexAlgoMap[kexAlgoECDH384] = &ecdh{elliptic.P384()} kexAlgoMap[kexAlgoECDH256] = &ecdh{elliptic.P256()} kexAlgoMap[kexAlgoCurve25519SHA256] = &curve25519sha256{} } // curve25519sha256 implements the curve25519-sha256@libssh.org key // agreement protocol, as described in // https://git.libssh.org/projects/libssh.git/tree/doc/curve25519-sha256@libssh.org.txt type curve25519sha256 struct{} type curve25519KeyPair struct { priv [32]byte pub [32]byte } func (kp *curve25519KeyPair) generate(rand io.Reader) error { if _, err := io.ReadFull(rand, kp.priv[:]); err != nil { return err } curve25519.ScalarBaseMult(&kp.pub, &kp.priv) return nil } // curve25519Zeros is just an array of 32 zero bytes so that we have something // convenient to compare against in order to reject curve25519 points with the // wrong order. var curve25519Zeros [32]byte func (kex *curve25519sha256) Client(c packetConn, rand io.Reader, magics *handshakeMagics) (*kexResult, error) { var kp curve25519KeyPair if err := kp.generate(rand); err != nil { return nil, err } if err := c.writePacket(Marshal(&kexECDHInitMsg{kp.pub[:]})); err != nil { return nil, err } packet, err := c.readPacket() if err != nil { return nil, err } var reply kexECDHReplyMsg if err = Unmarshal(packet, &reply); err != nil { return nil, err } if len(reply.EphemeralPubKey) != 32 { return nil, errors.New("ssh: peer's curve25519 public value has wrong length") } var servPub, secret [32]byte copy(servPub[:], reply.EphemeralPubKey) curve25519.ScalarMult(&secret, &kp.priv, &servPub) if subtle.ConstantTimeCompare(secret[:], curve25519Zeros[:]) == 1 { return nil, errors.New("ssh: peer's curve25519 public value has wrong order") } h := crypto.SHA256.New() magics.write(h) writeString(h, reply.HostKey) writeString(h, kp.pub[:]) writeString(h, reply.EphemeralPubKey) kInt := new(big.Int).SetBytes(secret[:]) K := make([]byte, intLength(kInt)) marshalInt(K, kInt) h.Write(K) return &kexResult{ H: h.Sum(nil), K: K, HostKey: reply.HostKey, Signature: reply.Signature, Hash: crypto.SHA256, }, nil } func (kex *curve25519sha256) Server(c packetConn, rand io.Reader, magics *handshakeMagics, priv Signer) (result *kexResult, err error) { packet, err := c.readPacket() if err != nil { return } var kexInit kexECDHInitMsg if err = Unmarshal(packet, &kexInit); err != nil { return } if len(kexInit.ClientPubKey) != 32 { return nil, errors.New("ssh: peer's curve25519 public value has wrong length") } var kp curve25519KeyPair if err := kp.generate(rand); err != nil { return nil, err } var clientPub, secret [32]byte copy(clientPub[:], kexInit.ClientPubKey) curve25519.ScalarMult(&secret, &kp.priv, &clientPub) if subtle.ConstantTimeCompare(secret[:], curve25519Zeros[:]) == 1 { return nil, errors.New("ssh: peer's curve25519 public value has wrong order") } hostKeyBytes := priv.PublicKey().Marshal() h := crypto.SHA256.New() magics.write(h) writeString(h, hostKeyBytes) writeString(h, kexInit.ClientPubKey) writeString(h, kp.pub[:]) kInt := new(big.Int).SetBytes(secret[:]) K := make([]byte, intLength(kInt)) marshalInt(K, kInt) h.Write(K) H := h.Sum(nil) sig, err := signAndMarshal(priv, rand, H) if err != nil { return nil, err } reply := kexECDHReplyMsg{ EphemeralPubKey: kp.pub[:], HostKey: hostKeyBytes, Signature: sig, } if err := c.writePacket(Marshal(&reply)); err != nil { return nil, err } return &kexResult{ H: H, K: K, HostKey: hostKeyBytes, Signature: sig, Hash: crypto.SHA256, }, nil } lxd-2.0.0/dist/src/golang.org/x/crypto/ssh/transport.go0000644061062106075000000002174312702772344025463 0ustar00stgraberdomain admins00000000000000// 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 ssh import ( "bufio" "errors" "io" ) const ( gcmCipherID = "aes128-gcm@openssh.com" aes128cbcID = "aes128-cbc" ) // packetConn represents a transport that implements packet based // operations. type packetConn interface { // Encrypt and send a packet of data to the remote peer. writePacket(packet []byte) error // Read a packet from the connection readPacket() ([]byte, error) // Close closes the write-side of the connection. Close() error } // transport is the keyingTransport that implements the SSH packet // protocol. type transport struct { reader connectionState writer connectionState bufReader *bufio.Reader bufWriter *bufio.Writer rand io.Reader io.Closer // Initial H used for the session ID. Once assigned this does // not change, even during subsequent key exchanges. sessionID []byte } // getSessionID returns the ID of the SSH connection. The return value // should not be modified. func (t *transport) getSessionID() []byte { if t.sessionID == nil { panic("session ID not set yet") } return t.sessionID } // packetCipher represents a combination of SSH encryption/MAC // protocol. A single instance should be used for one direction only. type packetCipher interface { // writePacket encrypts the packet and writes it to w. The // contents of the packet are generally scrambled. writePacket(seqnum uint32, w io.Writer, rand io.Reader, packet []byte) error // readPacket reads and decrypts a packet of data. The // returned packet may be overwritten by future calls of // readPacket. readPacket(seqnum uint32, r io.Reader) ([]byte, error) } // connectionState represents one side (read or write) of the // connection. This is necessary because each direction has its own // keys, and can even have its own algorithms type connectionState struct { packetCipher seqNum uint32 dir direction pendingKeyChange chan packetCipher } // prepareKeyChange sets up key material for a keychange. The key changes in // both directions are triggered by reading and writing a msgNewKey packet // respectively. func (t *transport) prepareKeyChange(algs *algorithms, kexResult *kexResult) error { if t.sessionID == nil { t.sessionID = kexResult.H } kexResult.SessionID = t.sessionID if ciph, err := newPacketCipher(t.reader.dir, algs.r, kexResult); err != nil { return err } else { t.reader.pendingKeyChange <- ciph } if ciph, err := newPacketCipher(t.writer.dir, algs.w, kexResult); err != nil { return err } else { t.writer.pendingKeyChange <- ciph } return nil } // Read and decrypt next packet. func (t *transport) readPacket() ([]byte, error) { return t.reader.readPacket(t.bufReader) } func (s *connectionState) readPacket(r *bufio.Reader) ([]byte, error) { packet, err := s.packetCipher.readPacket(s.seqNum, r) s.seqNum++ if err == nil && len(packet) == 0 { err = errors.New("ssh: zero length packet") } if len(packet) > 0 { switch packet[0] { case msgNewKeys: select { case cipher := <-s.pendingKeyChange: s.packetCipher = cipher default: return nil, errors.New("ssh: got bogus newkeys message.") } case msgDisconnect: // Transform a disconnect message into an // error. Since this is lowest level at which // we interpret message types, doing it here // ensures that we don't have to handle it // elsewhere. var msg disconnectMsg if err := Unmarshal(packet, &msg); err != nil { return nil, err } return nil, &msg } } // The packet may point to an internal buffer, so copy the // packet out here. fresh := make([]byte, len(packet)) copy(fresh, packet) return fresh, err } func (t *transport) writePacket(packet []byte) error { return t.writer.writePacket(t.bufWriter, t.rand, packet) } func (s *connectionState) writePacket(w *bufio.Writer, rand io.Reader, packet []byte) error { changeKeys := len(packet) > 0 && packet[0] == msgNewKeys err := s.packetCipher.writePacket(s.seqNum, w, rand, packet) if err != nil { return err } if err = w.Flush(); err != nil { return err } s.seqNum++ if changeKeys { select { case cipher := <-s.pendingKeyChange: s.packetCipher = cipher default: panic("ssh: no key material for msgNewKeys") } } return err } func newTransport(rwc io.ReadWriteCloser, rand io.Reader, isClient bool) *transport { t := &transport{ bufReader: bufio.NewReader(rwc), bufWriter: bufio.NewWriter(rwc), rand: rand, reader: connectionState{ packetCipher: &streamPacketCipher{cipher: noneCipher{}}, pendingKeyChange: make(chan packetCipher, 1), }, writer: connectionState{ packetCipher: &streamPacketCipher{cipher: noneCipher{}}, pendingKeyChange: make(chan packetCipher, 1), }, Closer: rwc, } if isClient { t.reader.dir = serverKeys t.writer.dir = clientKeys } else { t.reader.dir = clientKeys t.writer.dir = serverKeys } return t } type direction struct { ivTag []byte keyTag []byte macKeyTag []byte } var ( serverKeys = direction{[]byte{'B'}, []byte{'D'}, []byte{'F'}} clientKeys = direction{[]byte{'A'}, []byte{'C'}, []byte{'E'}} ) // generateKeys generates key material for IV, MAC and encryption. func generateKeys(d direction, algs directionAlgorithms, kex *kexResult) (iv, key, macKey []byte) { cipherMode := cipherModes[algs.Cipher] macMode := macModes[algs.MAC] iv = make([]byte, cipherMode.ivSize) key = make([]byte, cipherMode.keySize) macKey = make([]byte, macMode.keySize) generateKeyMaterial(iv, d.ivTag, kex) generateKeyMaterial(key, d.keyTag, kex) generateKeyMaterial(macKey, d.macKeyTag, kex) return } // setupKeys sets the cipher and MAC keys from kex.K, kex.H and sessionId, as // described in RFC 4253, section 6.4. direction should either be serverKeys // (to setup server->client keys) or clientKeys (for client->server keys). func newPacketCipher(d direction, algs directionAlgorithms, kex *kexResult) (packetCipher, error) { iv, key, macKey := generateKeys(d, algs, kex) if algs.Cipher == gcmCipherID { return newGCMCipher(iv, key, macKey) } if algs.Cipher == aes128cbcID { return newAESCBCCipher(iv, key, macKey, algs) } c := &streamPacketCipher{ mac: macModes[algs.MAC].new(macKey), } c.macResult = make([]byte, c.mac.Size()) var err error c.cipher, err = cipherModes[algs.Cipher].createStream(key, iv) if err != nil { return nil, err } return c, nil } // generateKeyMaterial fills out with key material generated from tag, K, H // and sessionId, as specified in RFC 4253, section 7.2. func generateKeyMaterial(out, tag []byte, r *kexResult) { var digestsSoFar []byte h := r.Hash.New() for len(out) > 0 { h.Reset() h.Write(r.K) h.Write(r.H) if len(digestsSoFar) == 0 { h.Write(tag) h.Write(r.SessionID) } else { h.Write(digestsSoFar) } digest := h.Sum(nil) n := copy(out, digest) out = out[n:] if len(out) > 0 { digestsSoFar = append(digestsSoFar, digest...) } } } const packageVersion = "SSH-2.0-Go" // Sends and receives a version line. The versionLine string should // be US ASCII, start with "SSH-2.0-", and should not include a // newline. exchangeVersions returns the other side's version line. func exchangeVersions(rw io.ReadWriter, versionLine []byte) (them []byte, err error) { // Contrary to the RFC, we do not ignore lines that don't // start with "SSH-2.0-" to make the library usable with // nonconforming servers. for _, c := range versionLine { // The spec disallows non US-ASCII chars, and // specifically forbids null chars. if c < 32 { return nil, errors.New("ssh: junk character in version line") } } if _, err = rw.Write(append(versionLine, '\r', '\n')); err != nil { return } them, err = readVersion(rw) return them, err } // maxVersionStringBytes is the maximum number of bytes that we'll // accept as a version string. RFC 4253 section 4.2 limits this at 255 // chars const maxVersionStringBytes = 255 // Read version string as specified by RFC 4253, section 4.2. func readVersion(r io.Reader) ([]byte, error) { versionString := make([]byte, 0, 64) var ok bool var buf [1]byte for len(versionString) < maxVersionStringBytes { _, err := io.ReadFull(r, buf[:]) if err != nil { return nil, err } // The RFC says that the version should be terminated with \r\n // but several SSH servers actually only send a \n. if buf[0] == '\n' { ok = true break } // non ASCII chars are disallowed, but we are lenient, // since Go doesn't use null-terminated strings. // The RFC allows a comment after a space, however, // all of it (version and comments) goes into the // session hash. versionString = append(versionString, buf[0]) } if !ok { return nil, errors.New("ssh: overflow reading version string") } // There might be a '\r' on the end which we should remove. if len(versionString) > 0 && versionString[len(versionString)-1] == '\r' { versionString = versionString[:len(versionString)-1] } return versionString, nil } lxd-2.0.0/dist/src/golang.org/x/crypto/ssh/certs_test.go0000644061062106075000000002037212702772344025603 0ustar00stgraberdomain admins00000000000000// Copyright 2013 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 ssh import ( "bytes" "crypto/rand" "reflect" "testing" "time" ) // Cert generated by ssh-keygen 6.0p1 Debian-4. // % ssh-keygen -s ca-key -I test user-key const exampleSSHCert = `ssh-rsa-cert-v01@openssh.com AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgb1srW/W3ZDjYAO45xLYAwzHBDLsJ4Ux6ICFIkTjb1LEAAAADAQABAAAAYQCkoR51poH0wE8w72cqSB8Sszx+vAhzcMdCO0wqHTj7UNENHWEXGrU0E0UQekD7U+yhkhtoyjbPOVIP7hNa6aRk/ezdh/iUnCIt4Jt1v3Z1h1P+hA4QuYFMHNB+rmjPwAcAAAAAAAAAAAAAAAEAAAAEdGVzdAAAAAAAAAAAAAAAAP//////////AAAAAAAAAIIAAAAVcGVybWl0LVgxMS1mb3J3YXJkaW5nAAAAAAAAABdwZXJtaXQtYWdlbnQtZm9yd2FyZGluZwAAAAAAAAAWcGVybWl0LXBvcnQtZm9yd2FyZGluZwAAAAAAAAAKcGVybWl0LXB0eQAAAAAAAAAOcGVybWl0LXVzZXItcmMAAAAAAAAAAAAAAHcAAAAHc3NoLXJzYQAAAAMBAAEAAABhANFS2kaktpSGc+CcmEKPyw9mJC4nZKxHKTgLVZeaGbFZOvJTNzBspQHdy7Q1uKSfktxpgjZnksiu/tFF9ngyY2KFoc+U88ya95IZUycBGCUbBQ8+bhDtw/icdDGQD5WnUwAAAG8AAAAHc3NoLXJzYQAAAGC8Y9Z2LQKhIhxf52773XaWrXdxP0t3GBVo4A10vUWiYoAGepr6rQIoGGXFxT4B9Gp+nEBJjOwKDXPrAevow0T9ca8gZN+0ykbhSrXLE5Ao48rqr3zP4O1/9P7e6gp0gw8=` func TestParseCert(t *testing.T) { authKeyBytes := []byte(exampleSSHCert) key, _, _, rest, err := ParseAuthorizedKey(authKeyBytes) if err != nil { t.Fatalf("ParseAuthorizedKey: %v", err) } if len(rest) > 0 { t.Errorf("rest: got %q, want empty", rest) } if _, ok := key.(*Certificate); !ok { t.Fatalf("got %v (%T), want *Certificate", key, key) } marshaled := MarshalAuthorizedKey(key) // Before comparison, remove the trailing newline that // MarshalAuthorizedKey adds. marshaled = marshaled[:len(marshaled)-1] if !bytes.Equal(authKeyBytes, marshaled) { t.Errorf("marshaled certificate does not match original: got %q, want %q", marshaled, authKeyBytes) } } // Cert generated by ssh-keygen OpenSSH_6.8p1 OS X 10.10.3 // % ssh-keygen -s ca -I testcert -O source-address=192.168.1.0/24 -O force-command=/bin/sleep user.pub // user.pub key: ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDACh1rt2DXfV3hk6fszSQcQ/rueMId0kVD9U7nl8cfEnFxqOCrNT92g4laQIGl2mn8lsGZfTLg8ksHq3gkvgO3oo/0wHy4v32JeBOHTsN5AL4gfHNEhWeWb50ev47hnTsRIt9P4dxogeUo/hTu7j9+s9lLpEQXCvq6xocXQt0j8MV9qZBBXFLXVT3cWIkSqOdwt/5ZBg+1GSrc7WfCXVWgTk4a20uPMuJPxU4RQwZW6X3+O8Pqo8C3cW0OzZRFP6gUYUKUsTI5WntlS+LAxgw1mZNsozFGdbiOPRnEryE3SRldh9vjDR3tin1fGpA5P7+CEB/bqaXtG3V+F2OkqaMN // Critical Options: // force-command /bin/sleep // source-address 192.168.1.0/24 // Extensions: // permit-X11-forwarding // permit-agent-forwarding // permit-port-forwarding // permit-pty // permit-user-rc const exampleSSHCertWithOptions = `ssh-rsa-cert-v01@openssh.com AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgDyysCJY0XrO1n03EeRRoITnTPdjENFmWDs9X58PP3VUAAAADAQABAAABAQDACh1rt2DXfV3hk6fszSQcQ/rueMId0kVD9U7nl8cfEnFxqOCrNT92g4laQIGl2mn8lsGZfTLg8ksHq3gkvgO3oo/0wHy4v32JeBOHTsN5AL4gfHNEhWeWb50ev47hnTsRIt9P4dxogeUo/hTu7j9+s9lLpEQXCvq6xocXQt0j8MV9qZBBXFLXVT3cWIkSqOdwt/5ZBg+1GSrc7WfCXVWgTk4a20uPMuJPxU4RQwZW6X3+O8Pqo8C3cW0OzZRFP6gUYUKUsTI5WntlS+LAxgw1mZNsozFGdbiOPRnEryE3SRldh9vjDR3tin1fGpA5P7+CEB/bqaXtG3V+F2OkqaMNAAAAAAAAAAAAAAABAAAACHRlc3RjZXJ0AAAAAAAAAAAAAAAA//////////8AAABLAAAADWZvcmNlLWNvbW1hbmQAAAAOAAAACi9iaW4vc2xlZXAAAAAOc291cmNlLWFkZHJlc3MAAAASAAAADjE5Mi4xNjguMS4wLzI0AAAAggAAABVwZXJtaXQtWDExLWZvcndhcmRpbmcAAAAAAAAAF3Blcm1pdC1hZ2VudC1mb3J3YXJkaW5nAAAAAAAAABZwZXJtaXQtcG9ydC1mb3J3YXJkaW5nAAAAAAAAAApwZXJtaXQtcHR5AAAAAAAAAA5wZXJtaXQtdXNlci1yYwAAAAAAAAAAAAABFwAAAAdzc2gtcnNhAAAAAwEAAQAAAQEAwU+c5ui5A8+J/CFpjW8wCa52bEODA808WWQDCSuTG/eMXNf59v9Y8Pk0F1E9dGCosSNyVcB/hacUrc6He+i97+HJCyKavBsE6GDxrjRyxYqAlfcOXi/IVmaUGiO8OQ39d4GHrjToInKvExSUeleQyH4Y4/e27T/pILAqPFL3fyrvMLT5qU9QyIt6zIpa7GBP5+urouNavMprV3zsfIqNBbWypinOQAw823a5wN+zwXnhZrgQiHZ/USG09Y6k98y1dTVz8YHlQVR4D3lpTAsKDKJ5hCH9WU4fdf+lU8OyNGaJ/vz0XNqxcToe1l4numLTnaoSuH89pHryjqurB7lJKwAAAQ8AAAAHc3NoLXJzYQAAAQCaHvUIoPL1zWUHIXLvu96/HU1s/i4CAW2IIEuGgxCUCiFj6vyTyYtgxQxcmbfZf6eaITlS6XJZa7Qq4iaFZh75C1DXTX8labXhRSD4E2t//AIP9MC1rtQC5xo6FmbQ+BoKcDskr+mNACcbRSxs3IL3bwCfWDnIw2WbVox9ZdcthJKk4UoCW4ix4QwdHw7zlddlz++fGEEVhmTbll1SUkycGApPFBsAYRTMupUJcYPIeReBI/m8XfkoMk99bV8ZJQTAd7OekHY2/48Ff53jLmyDjP7kNw1F8OaPtkFs6dGJXta4krmaekPy87j+35In5hFj7yoOqvSbmYUkeX70/GGQ` func TestParseCertWithOptions(t *testing.T) { opts := map[string]string{ "source-address": "192.168.1.0/24", "force-command": "/bin/sleep", } exts := map[string]string{ "permit-X11-forwarding": "", "permit-agent-forwarding": "", "permit-port-forwarding": "", "permit-pty": "", "permit-user-rc": "", } authKeyBytes := []byte(exampleSSHCertWithOptions) key, _, _, rest, err := ParseAuthorizedKey(authKeyBytes) if err != nil { t.Fatalf("ParseAuthorizedKey: %v", err) } if len(rest) > 0 { t.Errorf("rest: got %q, want empty", rest) } cert, ok := key.(*Certificate) if !ok { t.Fatalf("got %v (%T), want *Certificate", key, key) } if !reflect.DeepEqual(cert.CriticalOptions, opts) { t.Errorf("unexpected critical options - got %v, want %v", cert.CriticalOptions, opts) } if !reflect.DeepEqual(cert.Extensions, exts) { t.Errorf("unexpected Extensions - got %v, want %v", cert.Extensions, exts) } marshaled := MarshalAuthorizedKey(key) // Before comparison, remove the trailing newline that // MarshalAuthorizedKey adds. marshaled = marshaled[:len(marshaled)-1] if !bytes.Equal(authKeyBytes, marshaled) { t.Errorf("marshaled certificate does not match original: got %q, want %q", marshaled, authKeyBytes) } } func TestValidateCert(t *testing.T) { key, _, _, _, err := ParseAuthorizedKey([]byte(exampleSSHCert)) if err != nil { t.Fatalf("ParseAuthorizedKey: %v", err) } validCert, ok := key.(*Certificate) if !ok { t.Fatalf("got %v (%T), want *Certificate", key, key) } checker := CertChecker{} checker.IsAuthority = func(k PublicKey) bool { return bytes.Equal(k.Marshal(), validCert.SignatureKey.Marshal()) } if err := checker.CheckCert("user", validCert); err != nil { t.Errorf("Unable to validate certificate: %v", err) } invalidCert := &Certificate{ Key: testPublicKeys["rsa"], SignatureKey: testPublicKeys["ecdsa"], ValidBefore: CertTimeInfinity, Signature: &Signature{}, } if err := checker.CheckCert("user", invalidCert); err == nil { t.Error("Invalid cert signature passed validation") } } func TestValidateCertTime(t *testing.T) { cert := Certificate{ ValidPrincipals: []string{"user"}, Key: testPublicKeys["rsa"], ValidAfter: 50, ValidBefore: 100, } cert.SignCert(rand.Reader, testSigners["ecdsa"]) for ts, ok := range map[int64]bool{ 25: false, 50: true, 99: true, 100: false, 125: false, } { checker := CertChecker{ Clock: func() time.Time { return time.Unix(ts, 0) }, } checker.IsAuthority = func(k PublicKey) bool { return bytes.Equal(k.Marshal(), testPublicKeys["ecdsa"].Marshal()) } if v := checker.CheckCert("user", &cert); (v == nil) != ok { t.Errorf("Authenticate(%d): %v", ts, v) } } } // TODO(hanwen): tests for // // host keys: // * fallbacks func TestHostKeyCert(t *testing.T) { cert := &Certificate{ ValidPrincipals: []string{"hostname", "hostname.domain"}, Key: testPublicKeys["rsa"], ValidBefore: CertTimeInfinity, CertType: HostCert, } cert.SignCert(rand.Reader, testSigners["ecdsa"]) checker := &CertChecker{ IsAuthority: func(p PublicKey) bool { return bytes.Equal(testPublicKeys["ecdsa"].Marshal(), p.Marshal()) }, } certSigner, err := NewCertSigner(cert, testSigners["rsa"]) if err != nil { t.Errorf("NewCertSigner: %v", err) } for _, name := range []string{"hostname", "otherhost"} { c1, c2, err := netPipe() if err != nil { t.Fatalf("netPipe: %v", err) } defer c1.Close() defer c2.Close() errc := make(chan error) go func() { conf := ServerConfig{ NoClientAuth: true, } conf.AddHostKey(certSigner) _, _, _, err := NewServerConn(c1, &conf) errc <- err }() config := &ClientConfig{ User: "user", HostKeyCallback: checker.CheckHostKey, } _, _, _, err = NewClientConn(c2, name, config) succeed := name == "hostname" if (err == nil) != succeed { t.Fatalf("NewClientConn(%q): %v", name, err) } err = <-errc if (err == nil) != succeed { t.Fatalf("NewServerConn(%q): %v", name, err) } } } lxd-2.0.0/dist/src/golang.org/x/crypto/ssh/channel.go0000644061062106075000000003720312702772344025035 0ustar00stgraberdomain admins00000000000000// 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 ssh import ( "encoding/binary" "errors" "fmt" "io" "log" "sync" ) const ( minPacketLength = 9 // channelMaxPacket contains the maximum number of bytes that will be // sent in a single packet. As per RFC 4253, section 6.1, 32k is also // the minimum. channelMaxPacket = 1 << 15 // We follow OpenSSH here. channelWindowSize = 64 * channelMaxPacket ) // NewChannel represents an incoming request to a channel. It must either be // accepted for use by calling Accept, or rejected by calling Reject. type NewChannel interface { // Accept accepts the channel creation request. It returns the Channel // and a Go channel containing SSH requests. The Go channel must be // serviced otherwise the Channel will hang. Accept() (Channel, <-chan *Request, error) // Reject rejects the channel creation request. After calling // this, no other methods on the Channel may be called. Reject(reason RejectionReason, message string) error // ChannelType returns the type of the channel, as supplied by the // client. ChannelType() string // ExtraData returns the arbitrary payload for this channel, as supplied // by the client. This data is specific to the channel type. ExtraData() []byte } // A Channel is an ordered, reliable, flow-controlled, duplex stream // that is multiplexed over an SSH connection. type Channel interface { // Read reads up to len(data) bytes from the channel. Read(data []byte) (int, error) // Write writes len(data) bytes to the channel. Write(data []byte) (int, error) // Close signals end of channel use. No data may be sent after this // call. Close() error // CloseWrite signals the end of sending in-band // data. Requests may still be sent, and the other side may // still send data CloseWrite() error // SendRequest sends a channel request. If wantReply is true, // it will wait for a reply and return the result as a // boolean, otherwise the return value will be false. Channel // requests are out-of-band messages so they may be sent even // if the data stream is closed or blocked by flow control. SendRequest(name string, wantReply bool, payload []byte) (bool, error) // Stderr returns an io.ReadWriter that writes to this channel // with the extended data type set to stderr. Stderr may // safely be read and written from a different goroutine than // Read and Write respectively. Stderr() io.ReadWriter } // Request is a request sent outside of the normal stream of // data. Requests can either be specific to an SSH channel, or they // can be global. type Request struct { Type string WantReply bool Payload []byte ch *channel mux *mux } // Reply sends a response to a request. It must be called for all requests // where WantReply is true and is a no-op otherwise. The payload argument is // ignored for replies to channel-specific requests. func (r *Request) Reply(ok bool, payload []byte) error { if !r.WantReply { return nil } if r.ch == nil { return r.mux.ackRequest(ok, payload) } return r.ch.ackRequest(ok) } // RejectionReason is an enumeration used when rejecting channel creation // requests. See RFC 4254, section 5.1. type RejectionReason uint32 const ( Prohibited RejectionReason = iota + 1 ConnectionFailed UnknownChannelType ResourceShortage ) // String converts the rejection reason to human readable form. func (r RejectionReason) String() string { switch r { case Prohibited: return "administratively prohibited" case ConnectionFailed: return "connect failed" case UnknownChannelType: return "unknown channel type" case ResourceShortage: return "resource shortage" } return fmt.Sprintf("unknown reason %d", int(r)) } func min(a uint32, b int) uint32 { if a < uint32(b) { return a } return uint32(b) } type channelDirection uint8 const ( channelInbound channelDirection = iota channelOutbound ) // channel is an implementation of the Channel interface that works // with the mux class. type channel struct { // R/O after creation chanType string extraData []byte localId, remoteId uint32 // maxIncomingPayload and maxRemotePayload are the maximum // payload sizes of normal and extended data packets for // receiving and sending, respectively. The wire packet will // be 9 or 13 bytes larger (excluding encryption overhead). maxIncomingPayload uint32 maxRemotePayload uint32 mux *mux // decided is set to true if an accept or reject message has been sent // (for outbound channels) or received (for inbound channels). decided bool // direction contains either channelOutbound, for channels created // locally, or channelInbound, for channels created by the peer. direction channelDirection // Pending internal channel messages. msg chan interface{} // Since requests have no ID, there can be only one request // with WantReply=true outstanding. This lock is held by a // goroutine that has such an outgoing request pending. sentRequestMu sync.Mutex incomingRequests chan *Request sentEOF bool // thread-safe data remoteWin window pending *buffer extPending *buffer // windowMu protects myWindow, the flow-control window. windowMu sync.Mutex myWindow uint32 // writeMu serializes calls to mux.conn.writePacket() and // protects sentClose and packetPool. This mutex must be // different from windowMu, as writePacket can block if there // is a key exchange pending. writeMu sync.Mutex sentClose bool // packetPool has a buffer for each extended channel ID to // save allocations during writes. packetPool map[uint32][]byte } // writePacket sends a packet. If the packet is a channel close, it updates // sentClose. This method takes the lock c.writeMu. func (c *channel) writePacket(packet []byte) error { c.writeMu.Lock() if c.sentClose { c.writeMu.Unlock() return io.EOF } c.sentClose = (packet[0] == msgChannelClose) err := c.mux.conn.writePacket(packet) c.writeMu.Unlock() return err } func (c *channel) sendMessage(msg interface{}) error { if debugMux { log.Printf("send %d: %#v", c.mux.chanList.offset, msg) } p := Marshal(msg) binary.BigEndian.PutUint32(p[1:], c.remoteId) return c.writePacket(p) } // WriteExtended writes data to a specific extended stream. These streams are // used, for example, for stderr. func (c *channel) WriteExtended(data []byte, extendedCode uint32) (n int, err error) { if c.sentEOF { return 0, io.EOF } // 1 byte message type, 4 bytes remoteId, 4 bytes data length opCode := byte(msgChannelData) headerLength := uint32(9) if extendedCode > 0 { headerLength += 4 opCode = msgChannelExtendedData } c.writeMu.Lock() packet := c.packetPool[extendedCode] // We don't remove the buffer from packetPool, so // WriteExtended calls from different goroutines will be // flagged as errors by the race detector. c.writeMu.Unlock() for len(data) > 0 { space := min(c.maxRemotePayload, len(data)) if space, err = c.remoteWin.reserve(space); err != nil { return n, err } if want := headerLength + space; uint32(cap(packet)) < want { packet = make([]byte, want) } else { packet = packet[:want] } todo := data[:space] packet[0] = opCode binary.BigEndian.PutUint32(packet[1:], c.remoteId) if extendedCode > 0 { binary.BigEndian.PutUint32(packet[5:], uint32(extendedCode)) } binary.BigEndian.PutUint32(packet[headerLength-4:], uint32(len(todo))) copy(packet[headerLength:], todo) if err = c.writePacket(packet); err != nil { return n, err } n += len(todo) data = data[len(todo):] } c.writeMu.Lock() c.packetPool[extendedCode] = packet c.writeMu.Unlock() return n, err } func (c *channel) handleData(packet []byte) error { headerLen := 9 isExtendedData := packet[0] == msgChannelExtendedData if isExtendedData { headerLen = 13 } if len(packet) < headerLen { // malformed data packet return parseError(packet[0]) } var extended uint32 if isExtendedData { extended = binary.BigEndian.Uint32(packet[5:]) } length := binary.BigEndian.Uint32(packet[headerLen-4 : headerLen]) if length == 0 { return nil } if length > c.maxIncomingPayload { // TODO(hanwen): should send Disconnect? return errors.New("ssh: incoming packet exceeds maximum payload size") } data := packet[headerLen:] if length != uint32(len(data)) { return errors.New("ssh: wrong packet length") } c.windowMu.Lock() if c.myWindow < length { c.windowMu.Unlock() // TODO(hanwen): should send Disconnect with reason? return errors.New("ssh: remote side wrote too much") } c.myWindow -= length c.windowMu.Unlock() if extended == 1 { c.extPending.write(data) } else if extended > 0 { // discard other extended data. } else { c.pending.write(data) } return nil } func (c *channel) adjustWindow(n uint32) error { c.windowMu.Lock() // Since myWindow is managed on our side, and can never exceed // the initial window setting, we don't worry about overflow. c.myWindow += uint32(n) c.windowMu.Unlock() return c.sendMessage(windowAdjustMsg{ AdditionalBytes: uint32(n), }) } func (c *channel) ReadExtended(data []byte, extended uint32) (n int, err error) { switch extended { case 1: n, err = c.extPending.Read(data) case 0: n, err = c.pending.Read(data) default: return 0, fmt.Errorf("ssh: extended code %d unimplemented", extended) } if n > 0 { err = c.adjustWindow(uint32(n)) // sendWindowAdjust can return io.EOF if the remote // peer has closed the connection, however we want to // defer forwarding io.EOF to the caller of Read until // the buffer has been drained. if n > 0 && err == io.EOF { err = nil } } return n, err } func (c *channel) close() { c.pending.eof() c.extPending.eof() close(c.msg) close(c.incomingRequests) c.writeMu.Lock() // This is not necesary for a normal channel teardown, but if // there was another error, it is. c.sentClose = true c.writeMu.Unlock() // Unblock writers. c.remoteWin.close() } // responseMessageReceived is called when a success or failure message is // received on a channel to check that such a message is reasonable for the // given channel. func (c *channel) responseMessageReceived() error { if c.direction == channelInbound { return errors.New("ssh: channel response message received on inbound channel") } if c.decided { return errors.New("ssh: duplicate response received for channel") } c.decided = true return nil } func (c *channel) handlePacket(packet []byte) error { switch packet[0] { case msgChannelData, msgChannelExtendedData: return c.handleData(packet) case msgChannelClose: c.sendMessage(channelCloseMsg{PeersId: c.remoteId}) c.mux.chanList.remove(c.localId) c.close() return nil case msgChannelEOF: // RFC 4254 is mute on how EOF affects dataExt messages but // it is logical to signal EOF at the same time. c.extPending.eof() c.pending.eof() return nil } decoded, err := decode(packet) if err != nil { return err } switch msg := decoded.(type) { case *channelOpenFailureMsg: if err := c.responseMessageReceived(); err != nil { return err } c.mux.chanList.remove(msg.PeersId) c.msg <- msg case *channelOpenConfirmMsg: if err := c.responseMessageReceived(); err != nil { return err } if msg.MaxPacketSize < minPacketLength || msg.MaxPacketSize > 1<<31 { return fmt.Errorf("ssh: invalid MaxPacketSize %d from peer", msg.MaxPacketSize) } c.remoteId = msg.MyId c.maxRemotePayload = msg.MaxPacketSize c.remoteWin.add(msg.MyWindow) c.msg <- msg case *windowAdjustMsg: if !c.remoteWin.add(msg.AdditionalBytes) { return fmt.Errorf("ssh: invalid window update for %d bytes", msg.AdditionalBytes) } case *channelRequestMsg: req := Request{ Type: msg.Request, WantReply: msg.WantReply, Payload: msg.RequestSpecificData, ch: c, } c.incomingRequests <- &req default: c.msg <- msg } return nil } func (m *mux) newChannel(chanType string, direction channelDirection, extraData []byte) *channel { ch := &channel{ remoteWin: window{Cond: newCond()}, myWindow: channelWindowSize, pending: newBuffer(), extPending: newBuffer(), direction: direction, incomingRequests: make(chan *Request, 16), msg: make(chan interface{}, 16), chanType: chanType, extraData: extraData, mux: m, packetPool: make(map[uint32][]byte), } ch.localId = m.chanList.add(ch) return ch } var errUndecided = errors.New("ssh: must Accept or Reject channel") var errDecidedAlready = errors.New("ssh: can call Accept or Reject only once") type extChannel struct { code uint32 ch *channel } func (e *extChannel) Write(data []byte) (n int, err error) { return e.ch.WriteExtended(data, e.code) } func (e *extChannel) Read(data []byte) (n int, err error) { return e.ch.ReadExtended(data, e.code) } func (c *channel) Accept() (Channel, <-chan *Request, error) { if c.decided { return nil, nil, errDecidedAlready } c.maxIncomingPayload = channelMaxPacket confirm := channelOpenConfirmMsg{ PeersId: c.remoteId, MyId: c.localId, MyWindow: c.myWindow, MaxPacketSize: c.maxIncomingPayload, } c.decided = true if err := c.sendMessage(confirm); err != nil { return nil, nil, err } return c, c.incomingRequests, nil } func (ch *channel) Reject(reason RejectionReason, message string) error { if ch.decided { return errDecidedAlready } reject := channelOpenFailureMsg{ PeersId: ch.remoteId, Reason: reason, Message: message, Language: "en", } ch.decided = true return ch.sendMessage(reject) } func (ch *channel) Read(data []byte) (int, error) { if !ch.decided { return 0, errUndecided } return ch.ReadExtended(data, 0) } func (ch *channel) Write(data []byte) (int, error) { if !ch.decided { return 0, errUndecided } return ch.WriteExtended(data, 0) } func (ch *channel) CloseWrite() error { if !ch.decided { return errUndecided } ch.sentEOF = true return ch.sendMessage(channelEOFMsg{ PeersId: ch.remoteId}) } func (ch *channel) Close() error { if !ch.decided { return errUndecided } return ch.sendMessage(channelCloseMsg{ PeersId: ch.remoteId}) } // Extended returns an io.ReadWriter that sends and receives data on the given, // SSH extended stream. Such streams are used, for example, for stderr. func (ch *channel) Extended(code uint32) io.ReadWriter { if !ch.decided { return nil } return &extChannel{code, ch} } func (ch *channel) Stderr() io.ReadWriter { return ch.Extended(1) } func (ch *channel) SendRequest(name string, wantReply bool, payload []byte) (bool, error) { if !ch.decided { return false, errUndecided } if wantReply { ch.sentRequestMu.Lock() defer ch.sentRequestMu.Unlock() } msg := channelRequestMsg{ PeersId: ch.remoteId, Request: name, WantReply: wantReply, RequestSpecificData: payload, } if err := ch.sendMessage(msg); err != nil { return false, err } if wantReply { m, ok := (<-ch.msg) if !ok { return false, io.EOF } switch m.(type) { case *channelRequestFailureMsg: return false, nil case *channelRequestSuccessMsg: return true, nil default: return false, fmt.Errorf("ssh: unexpected response to channel request: %#v", m) } } return false, nil } // ackRequest either sends an ack or nack to the channel request. func (ch *channel) ackRequest(ok bool) error { if !ch.decided { return errUndecided } var msg interface{} if !ok { msg = channelRequestFailureMsg{ PeersId: ch.remoteId, } } else { msg = channelRequestSuccessMsg{ PeersId: ch.remoteId, } } return ch.sendMessage(msg) } func (ch *channel) ChannelType() string { return ch.chanType } func (ch *channel) ExtraData() []byte { return ch.extraData } lxd-2.0.0/dist/src/golang.org/x/crypto/ssh/connection.go0000644061062106075000000000660112702772344025562 0ustar00stgraberdomain admins00000000000000// Copyright 2013 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 ssh import ( "fmt" "net" ) // OpenChannelError is returned if the other side rejects an // OpenChannel request. type OpenChannelError struct { Reason RejectionReason Message string } func (e *OpenChannelError) Error() string { return fmt.Sprintf("ssh: rejected: %s (%s)", e.Reason, e.Message) } // ConnMetadata holds metadata for the connection. type ConnMetadata interface { // User returns the user ID for this connection. // It is empty if no authentication is used. User() string // SessionID returns the sesson hash, also denoted by H. SessionID() []byte // ClientVersion returns the client's version string as hashed // into the session ID. ClientVersion() []byte // ServerVersion returns the server's version string as hashed // into the session ID. ServerVersion() []byte // RemoteAddr returns the remote address for this connection. RemoteAddr() net.Addr // LocalAddr returns the local address for this connection. LocalAddr() net.Addr } // Conn represents an SSH connection for both server and client roles. // Conn is the basis for implementing an application layer, such // as ClientConn, which implements the traditional shell access for // clients. type Conn interface { ConnMetadata // SendRequest sends a global request, and returns the // reply. If wantReply is true, it returns the response status // and payload. See also RFC4254, section 4. SendRequest(name string, wantReply bool, payload []byte) (bool, []byte, error) // OpenChannel tries to open an channel. If the request is // rejected, it returns *OpenChannelError. On success it returns // the SSH Channel and a Go channel for incoming, out-of-band // requests. The Go channel must be serviced, or the // connection will hang. OpenChannel(name string, data []byte) (Channel, <-chan *Request, error) // Close closes the underlying network connection Close() error // Wait blocks until the connection has shut down, and returns the // error causing the shutdown. Wait() error // TODO(hanwen): consider exposing: // RequestKeyChange // Disconnect } // DiscardRequests consumes and rejects all requests from the // passed-in channel. func DiscardRequests(in <-chan *Request) { for req := range in { if req.WantReply { req.Reply(false, nil) } } } // A connection represents an incoming connection. type connection struct { transport *handshakeTransport sshConn // The connection protocol. *mux } func (c *connection) Close() error { return c.sshConn.conn.Close() } // sshconn provides net.Conn metadata, but disallows direct reads and // writes. type sshConn struct { conn net.Conn user string sessionID []byte clientVersion []byte serverVersion []byte } func dup(src []byte) []byte { dst := make([]byte, len(src)) copy(dst, src) return dst } func (c *sshConn) User() string { return c.user } func (c *sshConn) RemoteAddr() net.Addr { return c.conn.RemoteAddr() } func (c *sshConn) Close() error { return c.conn.Close() } func (c *sshConn) LocalAddr() net.Addr { return c.conn.LocalAddr() } func (c *sshConn) SessionID() []byte { return dup(c.sessionID) } func (c *sshConn) ClientVersion() []byte { return dup(c.clientVersion) } func (c *sshConn) ServerVersion() []byte { return dup(c.serverVersion) } lxd-2.0.0/dist/src/golang.org/x/crypto/ssh/keys.go0000644061062106075000000004277212702772344024407 0ustar00stgraberdomain admins00000000000000// Copyright 2012 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 ssh import ( "bytes" "crypto" "crypto/dsa" "crypto/ecdsa" "crypto/elliptic" "crypto/rsa" "crypto/x509" "encoding/asn1" "encoding/base64" "encoding/pem" "errors" "fmt" "io" "math/big" "strings" ) // These constants represent the algorithm names for key types supported by this // package. const ( KeyAlgoRSA = "ssh-rsa" KeyAlgoDSA = "ssh-dss" KeyAlgoECDSA256 = "ecdsa-sha2-nistp256" KeyAlgoECDSA384 = "ecdsa-sha2-nistp384" KeyAlgoECDSA521 = "ecdsa-sha2-nistp521" ) // parsePubKey parses a public key of the given algorithm. // Use ParsePublicKey for keys with prepended algorithm. func parsePubKey(in []byte, algo string) (pubKey PublicKey, rest []byte, err error) { switch algo { case KeyAlgoRSA: return parseRSA(in) case KeyAlgoDSA: return parseDSA(in) case KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521: return parseECDSA(in) case CertAlgoRSAv01, CertAlgoDSAv01, CertAlgoECDSA256v01, CertAlgoECDSA384v01, CertAlgoECDSA521v01: cert, err := parseCert(in, certToPrivAlgo(algo)) if err != nil { return nil, nil, err } return cert, nil, nil } return nil, nil, fmt.Errorf("ssh: unknown key algorithm: %v", err) } // parseAuthorizedKey parses a public key in OpenSSH authorized_keys format // (see sshd(8) manual page) once the options and key type fields have been // removed. func parseAuthorizedKey(in []byte) (out PublicKey, comment string, err error) { in = bytes.TrimSpace(in) i := bytes.IndexAny(in, " \t") if i == -1 { i = len(in) } base64Key := in[:i] key := make([]byte, base64.StdEncoding.DecodedLen(len(base64Key))) n, err := base64.StdEncoding.Decode(key, base64Key) if err != nil { return nil, "", err } key = key[:n] out, err = ParsePublicKey(key) if err != nil { return nil, "", err } comment = string(bytes.TrimSpace(in[i:])) return out, comment, nil } // ParseKnownHosts parses an entry in the format of the known_hosts file. // // The known_hosts format is documented in the sshd(8) manual page. This // function will parse a single entry from in. On successful return, marker // will contain the optional marker value (i.e. "cert-authority" or "revoked") // or else be empty, hosts will contain the hosts that this entry matches, // pubKey will contain the public key and comment will contain any trailing // comment at the end of the line. See the sshd(8) manual page for the various // forms that a host string can take. // // The unparsed remainder of the input will be returned in rest. This function // can be called repeatedly to parse multiple entries. // // If no entries were found in the input then err will be io.EOF. Otherwise a // non-nil err value indicates a parse error. func ParseKnownHosts(in []byte) (marker string, hosts []string, pubKey PublicKey, comment string, rest []byte, err error) { for len(in) > 0 { end := bytes.IndexByte(in, '\n') if end != -1 { rest = in[end+1:] in = in[:end] } else { rest = nil } end = bytes.IndexByte(in, '\r') if end != -1 { in = in[:end] } in = bytes.TrimSpace(in) if len(in) == 0 || in[0] == '#' { in = rest continue } i := bytes.IndexAny(in, " \t") if i == -1 { in = rest continue } // Strip out the begining of the known_host key. // This is either an optional marker or a (set of) hostname(s). keyFields := bytes.Fields(in) if len(keyFields) < 3 || len(keyFields) > 5 { return "", nil, nil, "", nil, errors.New("ssh: invalid entry in known_hosts data") } // keyFields[0] is either "@cert-authority", "@revoked" or a comma separated // list of hosts marker := "" if keyFields[0][0] == '@' { marker = string(keyFields[0][1:]) keyFields = keyFields[1:] } hosts := string(keyFields[0]) // keyFields[1] contains the key type (e.g. “ssh-rsaâ€). // However, that information is duplicated inside the // base64-encoded key and so is ignored here. key := bytes.Join(keyFields[2:], []byte(" ")) if pubKey, comment, err = parseAuthorizedKey(key); err != nil { return "", nil, nil, "", nil, err } return marker, strings.Split(hosts, ","), pubKey, comment, rest, nil } return "", nil, nil, "", nil, io.EOF } // ParseAuthorizedKeys parses a public key from an authorized_keys // file used in OpenSSH according to the sshd(8) manual page. func ParseAuthorizedKey(in []byte) (out PublicKey, comment string, options []string, rest []byte, err error) { for len(in) > 0 { end := bytes.IndexByte(in, '\n') if end != -1 { rest = in[end+1:] in = in[:end] } else { rest = nil } end = bytes.IndexByte(in, '\r') if end != -1 { in = in[:end] } in = bytes.TrimSpace(in) if len(in) == 0 || in[0] == '#' { in = rest continue } i := bytes.IndexAny(in, " \t") if i == -1 { in = rest continue } if out, comment, err = parseAuthorizedKey(in[i:]); err == nil { return out, comment, options, rest, nil } // No key type recognised. Maybe there's an options field at // the beginning. var b byte inQuote := false var candidateOptions []string optionStart := 0 for i, b = range in { isEnd := !inQuote && (b == ' ' || b == '\t') if (b == ',' && !inQuote) || isEnd { if i-optionStart > 0 { candidateOptions = append(candidateOptions, string(in[optionStart:i])) } optionStart = i + 1 } if isEnd { break } if b == '"' && (i == 0 || (i > 0 && in[i-1] != '\\')) { inQuote = !inQuote } } for i < len(in) && (in[i] == ' ' || in[i] == '\t') { i++ } if i == len(in) { // Invalid line: unmatched quote in = rest continue } in = in[i:] i = bytes.IndexAny(in, " \t") if i == -1 { in = rest continue } if out, comment, err = parseAuthorizedKey(in[i:]); err == nil { options = candidateOptions return out, comment, options, rest, nil } in = rest continue } return nil, "", nil, nil, errors.New("ssh: no key found") } // ParsePublicKey parses an SSH public key formatted for use in // the SSH wire protocol according to RFC 4253, section 6.6. func ParsePublicKey(in []byte) (out PublicKey, err error) { algo, in, ok := parseString(in) if !ok { return nil, errShortRead } var rest []byte out, rest, err = parsePubKey(in, string(algo)) if len(rest) > 0 { return nil, errors.New("ssh: trailing junk in public key") } return out, err } // MarshalAuthorizedKey serializes key for inclusion in an OpenSSH // authorized_keys file. The return value ends with newline. func MarshalAuthorizedKey(key PublicKey) []byte { b := &bytes.Buffer{} b.WriteString(key.Type()) b.WriteByte(' ') e := base64.NewEncoder(base64.StdEncoding, b) e.Write(key.Marshal()) e.Close() b.WriteByte('\n') return b.Bytes() } // PublicKey is an abstraction of different types of public keys. type PublicKey interface { // Type returns the key's type, e.g. "ssh-rsa". Type() string // Marshal returns the serialized key data in SSH wire format, // with the name prefix. Marshal() []byte // Verify that sig is a signature on the given data using this // key. This function will hash the data appropriately first. Verify(data []byte, sig *Signature) error } // A Signer can create signatures that verify against a public key. type Signer interface { // PublicKey returns an associated PublicKey instance. PublicKey() PublicKey // Sign returns raw signature for the given data. This method // will apply the hash specified for the keytype to the data. Sign(rand io.Reader, data []byte) (*Signature, error) } type rsaPublicKey rsa.PublicKey func (r *rsaPublicKey) Type() string { return "ssh-rsa" } // parseRSA parses an RSA key according to RFC 4253, section 6.6. func parseRSA(in []byte) (out PublicKey, rest []byte, err error) { var w struct { E *big.Int N *big.Int Rest []byte `ssh:"rest"` } if err := Unmarshal(in, &w); err != nil { return nil, nil, err } if w.E.BitLen() > 24 { return nil, nil, errors.New("ssh: exponent too large") } e := w.E.Int64() if e < 3 || e&1 == 0 { return nil, nil, errors.New("ssh: incorrect exponent") } var key rsa.PublicKey key.E = int(e) key.N = w.N return (*rsaPublicKey)(&key), w.Rest, nil } func (r *rsaPublicKey) Marshal() []byte { e := new(big.Int).SetInt64(int64(r.E)) wirekey := struct { Name string E *big.Int N *big.Int }{ KeyAlgoRSA, e, r.N, } return Marshal(&wirekey) } func (r *rsaPublicKey) Verify(data []byte, sig *Signature) error { if sig.Format != r.Type() { return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, r.Type()) } h := crypto.SHA1.New() h.Write(data) digest := h.Sum(nil) return rsa.VerifyPKCS1v15((*rsa.PublicKey)(r), crypto.SHA1, digest, sig.Blob) } type dsaPublicKey dsa.PublicKey func (r *dsaPublicKey) Type() string { return "ssh-dss" } // parseDSA parses an DSA key according to RFC 4253, section 6.6. func parseDSA(in []byte) (out PublicKey, rest []byte, err error) { var w struct { P, Q, G, Y *big.Int Rest []byte `ssh:"rest"` } if err := Unmarshal(in, &w); err != nil { return nil, nil, err } key := &dsaPublicKey{ Parameters: dsa.Parameters{ P: w.P, Q: w.Q, G: w.G, }, Y: w.Y, } return key, w.Rest, nil } func (k *dsaPublicKey) Marshal() []byte { w := struct { Name string P, Q, G, Y *big.Int }{ k.Type(), k.P, k.Q, k.G, k.Y, } return Marshal(&w) } func (k *dsaPublicKey) Verify(data []byte, sig *Signature) error { if sig.Format != k.Type() { return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, k.Type()) } h := crypto.SHA1.New() h.Write(data) digest := h.Sum(nil) // Per RFC 4253, section 6.6, // The value for 'dss_signature_blob' is encoded as a string containing // r, followed by s (which are 160-bit integers, without lengths or // padding, unsigned, and in network byte order). // For DSS purposes, sig.Blob should be exactly 40 bytes in length. if len(sig.Blob) != 40 { return errors.New("ssh: DSA signature parse error") } r := new(big.Int).SetBytes(sig.Blob[:20]) s := new(big.Int).SetBytes(sig.Blob[20:]) if dsa.Verify((*dsa.PublicKey)(k), digest, r, s) { return nil } return errors.New("ssh: signature did not verify") } type dsaPrivateKey struct { *dsa.PrivateKey } func (k *dsaPrivateKey) PublicKey() PublicKey { return (*dsaPublicKey)(&k.PrivateKey.PublicKey) } func (k *dsaPrivateKey) Sign(rand io.Reader, data []byte) (*Signature, error) { h := crypto.SHA1.New() h.Write(data) digest := h.Sum(nil) r, s, err := dsa.Sign(rand, k.PrivateKey, digest) if err != nil { return nil, err } sig := make([]byte, 40) rb := r.Bytes() sb := s.Bytes() copy(sig[20-len(rb):20], rb) copy(sig[40-len(sb):], sb) return &Signature{ Format: k.PublicKey().Type(), Blob: sig, }, nil } type ecdsaPublicKey ecdsa.PublicKey func (key *ecdsaPublicKey) Type() string { return "ecdsa-sha2-" + key.nistID() } func (key *ecdsaPublicKey) nistID() string { switch key.Params().BitSize { case 256: return "nistp256" case 384: return "nistp384" case 521: return "nistp521" } panic("ssh: unsupported ecdsa key size") } func supportedEllipticCurve(curve elliptic.Curve) bool { return curve == elliptic.P256() || curve == elliptic.P384() || curve == elliptic.P521() } // ecHash returns the hash to match the given elliptic curve, see RFC // 5656, section 6.2.1 func ecHash(curve elliptic.Curve) crypto.Hash { bitSize := curve.Params().BitSize switch { case bitSize <= 256: return crypto.SHA256 case bitSize <= 384: return crypto.SHA384 } return crypto.SHA512 } // parseECDSA parses an ECDSA key according to RFC 5656, section 3.1. func parseECDSA(in []byte) (out PublicKey, rest []byte, err error) { var w struct { Curve string KeyBytes []byte Rest []byte `ssh:"rest"` } if err := Unmarshal(in, &w); err != nil { return nil, nil, err } key := new(ecdsa.PublicKey) switch w.Curve { case "nistp256": key.Curve = elliptic.P256() case "nistp384": key.Curve = elliptic.P384() case "nistp521": key.Curve = elliptic.P521() default: return nil, nil, errors.New("ssh: unsupported curve") } key.X, key.Y = elliptic.Unmarshal(key.Curve, w.KeyBytes) if key.X == nil || key.Y == nil { return nil, nil, errors.New("ssh: invalid curve point") } return (*ecdsaPublicKey)(key), w.Rest, nil } func (key *ecdsaPublicKey) Marshal() []byte { // See RFC 5656, section 3.1. keyBytes := elliptic.Marshal(key.Curve, key.X, key.Y) w := struct { Name string ID string Key []byte }{ key.Type(), key.nistID(), keyBytes, } return Marshal(&w) } func (key *ecdsaPublicKey) Verify(data []byte, sig *Signature) error { if sig.Format != key.Type() { return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, key.Type()) } h := ecHash(key.Curve).New() h.Write(data) digest := h.Sum(nil) // Per RFC 5656, section 3.1.2, // The ecdsa_signature_blob value has the following specific encoding: // mpint r // mpint s var ecSig struct { R *big.Int S *big.Int } if err := Unmarshal(sig.Blob, &ecSig); err != nil { return err } if ecdsa.Verify((*ecdsa.PublicKey)(key), digest, ecSig.R, ecSig.S) { return nil } return errors.New("ssh: signature did not verify") } // NewSignerFromKey takes an *rsa.PrivateKey, *dsa.PrivateKey, // *ecdsa.PrivateKey or any other crypto.Signer and returns a corresponding // Signer instance. ECDSA keys must use P-256, P-384 or P-521. func NewSignerFromKey(key interface{}) (Signer, error) { switch key := key.(type) { case crypto.Signer: return NewSignerFromSigner(key) case *dsa.PrivateKey: return &dsaPrivateKey{key}, nil default: return nil, fmt.Errorf("ssh: unsupported key type %T", key) } } type wrappedSigner struct { signer crypto.Signer pubKey PublicKey } // NewSignerFromSigner takes any crypto.Signer implementation and // returns a corresponding Signer interface. This can be used, for // example, with keys kept in hardware modules. func NewSignerFromSigner(signer crypto.Signer) (Signer, error) { pubKey, err := NewPublicKey(signer.Public()) if err != nil { return nil, err } return &wrappedSigner{signer, pubKey}, nil } func (s *wrappedSigner) PublicKey() PublicKey { return s.pubKey } func (s *wrappedSigner) Sign(rand io.Reader, data []byte) (*Signature, error) { var hashFunc crypto.Hash switch key := s.pubKey.(type) { case *rsaPublicKey, *dsaPublicKey: hashFunc = crypto.SHA1 case *ecdsaPublicKey: hashFunc = ecHash(key.Curve) default: return nil, fmt.Errorf("ssh: unsupported key type %T", key) } h := hashFunc.New() h.Write(data) digest := h.Sum(nil) signature, err := s.signer.Sign(rand, digest, hashFunc) if err != nil { return nil, err } // crypto.Signer.Sign is expected to return an ASN.1-encoded signature // for ECDSA and DSA, but that's not the encoding expected by SSH, so // re-encode. switch s.pubKey.(type) { case *ecdsaPublicKey, *dsaPublicKey: type asn1Signature struct { R, S *big.Int } asn1Sig := new(asn1Signature) _, err := asn1.Unmarshal(signature, asn1Sig) if err != nil { return nil, err } switch s.pubKey.(type) { case *ecdsaPublicKey: signature = Marshal(asn1Sig) case *dsaPublicKey: signature = make([]byte, 40) r := asn1Sig.R.Bytes() s := asn1Sig.S.Bytes() copy(signature[20-len(r):20], r) copy(signature[40-len(s):40], s) } } return &Signature{ Format: s.pubKey.Type(), Blob: signature, }, nil } // NewPublicKey takes an *rsa.PublicKey, *dsa.PublicKey, *ecdsa.PublicKey or // any other crypto.Signer and returns a corresponding Signer instance. ECDSA // keys must use P-256, P-384 or P-521. func NewPublicKey(key interface{}) (PublicKey, error) { switch key := key.(type) { case *rsa.PublicKey: return (*rsaPublicKey)(key), nil case *ecdsa.PublicKey: if !supportedEllipticCurve(key.Curve) { return nil, errors.New("ssh: only P-256, P-384 and P-521 EC keys are supported.") } return (*ecdsaPublicKey)(key), nil case *dsa.PublicKey: return (*dsaPublicKey)(key), nil default: return nil, fmt.Errorf("ssh: unsupported key type %T", key) } } // ParsePrivateKey returns a Signer from a PEM encoded private key. It supports // the same keys as ParseRawPrivateKey. func ParsePrivateKey(pemBytes []byte) (Signer, error) { key, err := ParseRawPrivateKey(pemBytes) if err != nil { return nil, err } return NewSignerFromKey(key) } // ParseRawPrivateKey returns a private key from a PEM encoded private key. It // supports RSA (PKCS#1), DSA (OpenSSL), and ECDSA private keys. func ParseRawPrivateKey(pemBytes []byte) (interface{}, error) { block, _ := pem.Decode(pemBytes) if block == nil { return nil, errors.New("ssh: no key found") } switch block.Type { case "RSA PRIVATE KEY": return x509.ParsePKCS1PrivateKey(block.Bytes) case "EC PRIVATE KEY": return x509.ParseECPrivateKey(block.Bytes) case "DSA PRIVATE KEY": return ParseDSAPrivateKey(block.Bytes) default: return nil, fmt.Errorf("ssh: unsupported key type %q", block.Type) } } // ParseDSAPrivateKey returns a DSA private key from its ASN.1 DER encoding, as // specified by the OpenSSL DSA man page. func ParseDSAPrivateKey(der []byte) (*dsa.PrivateKey, error) { var k struct { Version int P *big.Int Q *big.Int G *big.Int Priv *big.Int Pub *big.Int } rest, err := asn1.Unmarshal(der, &k) if err != nil { return nil, errors.New("ssh: failed to parse DSA key: " + err.Error()) } if len(rest) > 0 { return nil, errors.New("ssh: garbage after DSA key") } return &dsa.PrivateKey{ PublicKey: dsa.PublicKey{ Parameters: dsa.Parameters{ P: k.P, Q: k.Q, G: k.G, }, Y: k.Priv, }, X: k.Pub, }, nil } lxd-2.0.0/dist/src/golang.org/x/crypto/ssh/buffer.go0000644061062106075000000000422612702772344024675 0ustar00stgraberdomain admins00000000000000// Copyright 2012 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 ssh import ( "io" "sync" ) // buffer provides a linked list buffer for data exchange // between producer and consumer. Theoretically the buffer is // of unlimited capacity as it does no allocation of its own. type buffer struct { // protects concurrent access to head, tail and closed *sync.Cond head *element // the buffer that will be read first tail *element // the buffer that will be read last closed bool } // An element represents a single link in a linked list. type element struct { buf []byte next *element } // newBuffer returns an empty buffer that is not closed. func newBuffer() *buffer { e := new(element) b := &buffer{ Cond: newCond(), head: e, tail: e, } return b } // write makes buf available for Read to receive. // buf must not be modified after the call to write. func (b *buffer) write(buf []byte) { b.Cond.L.Lock() e := &element{buf: buf} b.tail.next = e b.tail = e b.Cond.Signal() b.Cond.L.Unlock() } // eof closes the buffer. Reads from the buffer once all // the data has been consumed will receive os.EOF. func (b *buffer) eof() error { b.Cond.L.Lock() b.closed = true b.Cond.Signal() b.Cond.L.Unlock() return nil } // Read reads data from the internal buffer in buf. Reads will block // if no data is available, or until the buffer is closed. func (b *buffer) Read(buf []byte) (n int, err error) { b.Cond.L.Lock() defer b.Cond.L.Unlock() for len(buf) > 0 { // if there is data in b.head, copy it if len(b.head.buf) > 0 { r := copy(buf, b.head.buf) buf, b.head.buf = buf[r:], b.head.buf[r:] n += r continue } // if there is a next buffer, make it the head if len(b.head.buf) == 0 && b.head != b.tail { b.head = b.head.next continue } // if at least one byte has been copied, return if n > 0 { break } // if nothing was read, and there is nothing outstanding // check to see if the buffer is closed. if b.closed { err = io.EOF break } // out of buffers, wait for producer b.Cond.Wait() } return } lxd-2.0.0/dist/src/golang.org/x/crypto/ssh/mux.go0000644061062106075000000001631612702772344024240 0ustar00stgraberdomain admins00000000000000// Copyright 2013 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 ssh import ( "encoding/binary" "fmt" "io" "log" "sync" "sync/atomic" ) // debugMux, if set, causes messages in the connection protocol to be // logged. const debugMux = false // chanList is a thread safe channel list. type chanList struct { // protects concurrent access to chans sync.Mutex // chans are indexed by the local id of the channel, which the // other side should send in the PeersId field. chans []*channel // This is a debugging aid: it offsets all IDs by this // amount. This helps distinguish otherwise identical // server/client muxes offset uint32 } // Assigns a channel ID to the given channel. func (c *chanList) add(ch *channel) uint32 { c.Lock() defer c.Unlock() for i := range c.chans { if c.chans[i] == nil { c.chans[i] = ch return uint32(i) + c.offset } } c.chans = append(c.chans, ch) return uint32(len(c.chans)-1) + c.offset } // getChan returns the channel for the given ID. func (c *chanList) getChan(id uint32) *channel { id -= c.offset c.Lock() defer c.Unlock() if id < uint32(len(c.chans)) { return c.chans[id] } return nil } func (c *chanList) remove(id uint32) { id -= c.offset c.Lock() if id < uint32(len(c.chans)) { c.chans[id] = nil } c.Unlock() } // dropAll forgets all channels it knows, returning them in a slice. func (c *chanList) dropAll() []*channel { c.Lock() defer c.Unlock() var r []*channel for _, ch := range c.chans { if ch == nil { continue } r = append(r, ch) } c.chans = nil return r } // mux represents the state for the SSH connection protocol, which // multiplexes many channels onto a single packet transport. type mux struct { conn packetConn chanList chanList incomingChannels chan NewChannel globalSentMu sync.Mutex globalResponses chan interface{} incomingRequests chan *Request errCond *sync.Cond err error } // When debugging, each new chanList instantiation has a different // offset. var globalOff uint32 func (m *mux) Wait() error { m.errCond.L.Lock() defer m.errCond.L.Unlock() for m.err == nil { m.errCond.Wait() } return m.err } // newMux returns a mux that runs over the given connection. func newMux(p packetConn) *mux { m := &mux{ conn: p, incomingChannels: make(chan NewChannel, 16), globalResponses: make(chan interface{}, 1), incomingRequests: make(chan *Request, 16), errCond: newCond(), } if debugMux { m.chanList.offset = atomic.AddUint32(&globalOff, 1) } go m.loop() return m } func (m *mux) sendMessage(msg interface{}) error { p := Marshal(msg) return m.conn.writePacket(p) } func (m *mux) SendRequest(name string, wantReply bool, payload []byte) (bool, []byte, error) { if wantReply { m.globalSentMu.Lock() defer m.globalSentMu.Unlock() } if err := m.sendMessage(globalRequestMsg{ Type: name, WantReply: wantReply, Data: payload, }); err != nil { return false, nil, err } if !wantReply { return false, nil, nil } msg, ok := <-m.globalResponses if !ok { return false, nil, io.EOF } switch msg := msg.(type) { case *globalRequestFailureMsg: return false, msg.Data, nil case *globalRequestSuccessMsg: return true, msg.Data, nil default: return false, nil, fmt.Errorf("ssh: unexpected response to request: %#v", msg) } } // ackRequest must be called after processing a global request that // has WantReply set. func (m *mux) ackRequest(ok bool, data []byte) error { if ok { return m.sendMessage(globalRequestSuccessMsg{Data: data}) } return m.sendMessage(globalRequestFailureMsg{Data: data}) } func (m *mux) Close() error { return m.conn.Close() } // loop runs the connection machine. It will process packets until an // error is encountered. To synchronize on loop exit, use mux.Wait. func (m *mux) loop() { var err error for err == nil { err = m.onePacket() } for _, ch := range m.chanList.dropAll() { ch.close() } close(m.incomingChannels) close(m.incomingRequests) close(m.globalResponses) m.conn.Close() m.errCond.L.Lock() m.err = err m.errCond.Broadcast() m.errCond.L.Unlock() if debugMux { log.Println("loop exit", err) } } // onePacket reads and processes one packet. func (m *mux) onePacket() error { packet, err := m.conn.readPacket() if err != nil { return err } if debugMux { if packet[0] == msgChannelData || packet[0] == msgChannelExtendedData { log.Printf("decoding(%d): data packet - %d bytes", m.chanList.offset, len(packet)) } else { p, _ := decode(packet) log.Printf("decoding(%d): %d %#v - %d bytes", m.chanList.offset, packet[0], p, len(packet)) } } switch packet[0] { case msgNewKeys: // Ignore notification of key change. return nil case msgChannelOpen: return m.handleChannelOpen(packet) case msgGlobalRequest, msgRequestSuccess, msgRequestFailure: return m.handleGlobalPacket(packet) } // assume a channel packet. if len(packet) < 5 { return parseError(packet[0]) } id := binary.BigEndian.Uint32(packet[1:]) ch := m.chanList.getChan(id) if ch == nil { return fmt.Errorf("ssh: invalid channel %d", id) } return ch.handlePacket(packet) } func (m *mux) handleGlobalPacket(packet []byte) error { msg, err := decode(packet) if err != nil { return err } switch msg := msg.(type) { case *globalRequestMsg: m.incomingRequests <- &Request{ Type: msg.Type, WantReply: msg.WantReply, Payload: msg.Data, mux: m, } case *globalRequestSuccessMsg, *globalRequestFailureMsg: m.globalResponses <- msg default: panic(fmt.Sprintf("not a global message %#v", msg)) } return nil } // handleChannelOpen schedules a channel to be Accept()ed. func (m *mux) handleChannelOpen(packet []byte) error { var msg channelOpenMsg if err := Unmarshal(packet, &msg); err != nil { return err } if msg.MaxPacketSize < minPacketLength || msg.MaxPacketSize > 1<<31 { failMsg := channelOpenFailureMsg{ PeersId: msg.PeersId, Reason: ConnectionFailed, Message: "invalid request", Language: "en_US.UTF-8", } return m.sendMessage(failMsg) } c := m.newChannel(msg.ChanType, channelInbound, msg.TypeSpecificData) c.remoteId = msg.PeersId c.maxRemotePayload = msg.MaxPacketSize c.remoteWin.add(msg.PeersWindow) m.incomingChannels <- c return nil } func (m *mux) OpenChannel(chanType string, extra []byte) (Channel, <-chan *Request, error) { ch, err := m.openChannel(chanType, extra) if err != nil { return nil, nil, err } return ch, ch.incomingRequests, nil } func (m *mux) openChannel(chanType string, extra []byte) (*channel, error) { ch := m.newChannel(chanType, channelOutbound, extra) ch.maxIncomingPayload = channelMaxPacket open := channelOpenMsg{ ChanType: chanType, PeersWindow: ch.myWindow, MaxPacketSize: ch.maxIncomingPayload, TypeSpecificData: extra, PeersId: ch.localId, } if err := m.sendMessage(open); err != nil { return nil, err } switch msg := (<-ch.msg).(type) { case *channelOpenConfirmMsg: return ch, nil case *channelOpenFailureMsg: return nil, &OpenChannelError{msg.Reason, msg.Message} default: return nil, fmt.Errorf("ssh: unexpected packet in response to channel open: %T", msg) } } lxd-2.0.0/dist/src/golang.org/x/crypto/ssh/session.go0000644061062106075000000003363412702772344025114 0ustar00stgraberdomain admins00000000000000// 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 ssh // Session implements an interactive session described in // "RFC 4254, section 6". import ( "bytes" "errors" "fmt" "io" "io/ioutil" "sync" ) type Signal string // POSIX signals as listed in RFC 4254 Section 6.10. const ( SIGABRT Signal = "ABRT" SIGALRM Signal = "ALRM" SIGFPE Signal = "FPE" SIGHUP Signal = "HUP" SIGILL Signal = "ILL" SIGINT Signal = "INT" SIGKILL Signal = "KILL" SIGPIPE Signal = "PIPE" SIGQUIT Signal = "QUIT" SIGSEGV Signal = "SEGV" SIGTERM Signal = "TERM" SIGUSR1 Signal = "USR1" SIGUSR2 Signal = "USR2" ) var signals = map[Signal]int{ SIGABRT: 6, SIGALRM: 14, SIGFPE: 8, SIGHUP: 1, SIGILL: 4, SIGINT: 2, SIGKILL: 9, SIGPIPE: 13, SIGQUIT: 3, SIGSEGV: 11, SIGTERM: 15, } type TerminalModes map[uint8]uint32 // POSIX terminal mode flags as listed in RFC 4254 Section 8. const ( tty_OP_END = 0 VINTR = 1 VQUIT = 2 VERASE = 3 VKILL = 4 VEOF = 5 VEOL = 6 VEOL2 = 7 VSTART = 8 VSTOP = 9 VSUSP = 10 VDSUSP = 11 VREPRINT = 12 VWERASE = 13 VLNEXT = 14 VFLUSH = 15 VSWTCH = 16 VSTATUS = 17 VDISCARD = 18 IGNPAR = 30 PARMRK = 31 INPCK = 32 ISTRIP = 33 INLCR = 34 IGNCR = 35 ICRNL = 36 IUCLC = 37 IXON = 38 IXANY = 39 IXOFF = 40 IMAXBEL = 41 ISIG = 50 ICANON = 51 XCASE = 52 ECHO = 53 ECHOE = 54 ECHOK = 55 ECHONL = 56 NOFLSH = 57 TOSTOP = 58 IEXTEN = 59 ECHOCTL = 60 ECHOKE = 61 PENDIN = 62 OPOST = 70 OLCUC = 71 ONLCR = 72 OCRNL = 73 ONOCR = 74 ONLRET = 75 CS7 = 90 CS8 = 91 PARENB = 92 PARODD = 93 TTY_OP_ISPEED = 128 TTY_OP_OSPEED = 129 ) // A Session represents a connection to a remote command or shell. type Session struct { // Stdin specifies the remote process's standard input. // If Stdin is nil, the remote process reads from an empty // bytes.Buffer. Stdin io.Reader // Stdout and Stderr specify the remote process's standard // output and error. // // If either is nil, Run connects the corresponding file // descriptor to an instance of ioutil.Discard. There is a // fixed amount of buffering that is shared for the two streams. // If either blocks it may eventually cause the remote // command to block. Stdout io.Writer Stderr io.Writer ch Channel // the channel backing this session started bool // true once Start, Run or Shell is invoked. copyFuncs []func() error errors chan error // one send per copyFunc // true if pipe method is active stdinpipe, stdoutpipe, stderrpipe bool // stdinPipeWriter is non-nil if StdinPipe has not been called // and Stdin was specified by the user; it is the write end of // a pipe connecting Session.Stdin to the stdin channel. stdinPipeWriter io.WriteCloser exitStatus chan error } // SendRequest sends an out-of-band channel request on the SSH channel // underlying the session. func (s *Session) SendRequest(name string, wantReply bool, payload []byte) (bool, error) { return s.ch.SendRequest(name, wantReply, payload) } func (s *Session) Close() error { return s.ch.Close() } // RFC 4254 Section 6.4. type setenvRequest struct { Name string Value string } // Setenv sets an environment variable that will be applied to any // command executed by Shell or Run. func (s *Session) Setenv(name, value string) error { msg := setenvRequest{ Name: name, Value: value, } ok, err := s.ch.SendRequest("env", true, Marshal(&msg)) if err == nil && !ok { err = errors.New("ssh: setenv failed") } return err } // RFC 4254 Section 6.2. type ptyRequestMsg struct { Term string Columns uint32 Rows uint32 Width uint32 Height uint32 Modelist string } // RequestPty requests the association of a pty with the session on the remote host. func (s *Session) RequestPty(term string, h, w int, termmodes TerminalModes) error { var tm []byte for k, v := range termmodes { kv := struct { Key byte Val uint32 }{k, v} tm = append(tm, Marshal(&kv)...) } tm = append(tm, tty_OP_END) req := ptyRequestMsg{ Term: term, Columns: uint32(w), Rows: uint32(h), Width: uint32(w * 8), Height: uint32(h * 8), Modelist: string(tm), } ok, err := s.ch.SendRequest("pty-req", true, Marshal(&req)) if err == nil && !ok { err = errors.New("ssh: pty-req failed") } return err } // RFC 4254 Section 6.5. type subsystemRequestMsg struct { Subsystem string } // RequestSubsystem requests the association of a subsystem with the session on the remote host. // A subsystem is a predefined command that runs in the background when the ssh session is initiated func (s *Session) RequestSubsystem(subsystem string) error { msg := subsystemRequestMsg{ Subsystem: subsystem, } ok, err := s.ch.SendRequest("subsystem", true, Marshal(&msg)) if err == nil && !ok { err = errors.New("ssh: subsystem request failed") } return err } // RFC 4254 Section 6.9. type signalMsg struct { Signal string } // Signal sends the given signal to the remote process. // sig is one of the SIG* constants. func (s *Session) Signal(sig Signal) error { msg := signalMsg{ Signal: string(sig), } _, err := s.ch.SendRequest("signal", false, Marshal(&msg)) return err } // RFC 4254 Section 6.5. type execMsg struct { Command string } // Start runs cmd on the remote host. Typically, the remote // server passes cmd to the shell for interpretation. // A Session only accepts one call to Run, Start or Shell. func (s *Session) Start(cmd string) error { if s.started { return errors.New("ssh: session already started") } req := execMsg{ Command: cmd, } ok, err := s.ch.SendRequest("exec", true, Marshal(&req)) if err == nil && !ok { err = fmt.Errorf("ssh: command %v failed", cmd) } if err != nil { return err } return s.start() } // Run runs cmd on the remote host. Typically, the remote // server passes cmd to the shell for interpretation. // A Session only accepts one call to Run, Start, Shell, Output, // or CombinedOutput. // // The returned error is nil if the command runs, has no problems // copying stdin, stdout, and stderr, and exits with a zero exit // status. // // If the command fails to run or doesn't complete successfully, the // error is of type *ExitError. Other error types may be // returned for I/O problems. func (s *Session) Run(cmd string) error { err := s.Start(cmd) if err != nil { return err } return s.Wait() } // Output runs cmd on the remote host and returns its standard output. func (s *Session) Output(cmd string) ([]byte, error) { if s.Stdout != nil { return nil, errors.New("ssh: Stdout already set") } var b bytes.Buffer s.Stdout = &b err := s.Run(cmd) return b.Bytes(), err } type singleWriter struct { b bytes.Buffer mu sync.Mutex } func (w *singleWriter) Write(p []byte) (int, error) { w.mu.Lock() defer w.mu.Unlock() return w.b.Write(p) } // CombinedOutput runs cmd on the remote host and returns its combined // standard output and standard error. func (s *Session) CombinedOutput(cmd string) ([]byte, error) { if s.Stdout != nil { return nil, errors.New("ssh: Stdout already set") } if s.Stderr != nil { return nil, errors.New("ssh: Stderr already set") } var b singleWriter s.Stdout = &b s.Stderr = &b err := s.Run(cmd) return b.b.Bytes(), err } // Shell starts a login shell on the remote host. A Session only // accepts one call to Run, Start, Shell, Output, or CombinedOutput. func (s *Session) Shell() error { if s.started { return errors.New("ssh: session already started") } ok, err := s.ch.SendRequest("shell", true, nil) if err == nil && !ok { return errors.New("ssh: could not start shell") } if err != nil { return err } return s.start() } func (s *Session) start() error { s.started = true type F func(*Session) for _, setupFd := range []F{(*Session).stdin, (*Session).stdout, (*Session).stderr} { setupFd(s) } s.errors = make(chan error, len(s.copyFuncs)) for _, fn := range s.copyFuncs { go func(fn func() error) { s.errors <- fn() }(fn) } return nil } // Wait waits for the remote command to exit. // // The returned error is nil if the command runs, has no problems // copying stdin, stdout, and stderr, and exits with a zero exit // status. // // If the command fails to run or doesn't complete successfully, the // error is of type *ExitError. Other error types may be // returned for I/O problems. func (s *Session) Wait() error { if !s.started { return errors.New("ssh: session not started") } waitErr := <-s.exitStatus if s.stdinPipeWriter != nil { s.stdinPipeWriter.Close() } var copyError error for _ = range s.copyFuncs { if err := <-s.errors; err != nil && copyError == nil { copyError = err } } if waitErr != nil { return waitErr } return copyError } func (s *Session) wait(reqs <-chan *Request) error { wm := Waitmsg{status: -1} // Wait for msg channel to be closed before returning. for msg := range reqs { switch msg.Type { case "exit-status": d := msg.Payload wm.status = int(d[0])<<24 | int(d[1])<<16 | int(d[2])<<8 | int(d[3]) case "exit-signal": var sigval struct { Signal string CoreDumped bool Error string Lang string } if err := Unmarshal(msg.Payload, &sigval); err != nil { return err } // Must sanitize strings? wm.signal = sigval.Signal wm.msg = sigval.Error wm.lang = sigval.Lang default: // This handles keepalives and matches // OpenSSH's behaviour. if msg.WantReply { msg.Reply(false, nil) } } } if wm.status == 0 { return nil } if wm.status == -1 { // exit-status was never sent from server if wm.signal == "" { return errors.New("wait: remote command exited without exit status or exit signal") } wm.status = 128 if _, ok := signals[Signal(wm.signal)]; ok { wm.status += signals[Signal(wm.signal)] } } return &ExitError{wm} } func (s *Session) stdin() { if s.stdinpipe { return } var stdin io.Reader if s.Stdin == nil { stdin = new(bytes.Buffer) } else { r, w := io.Pipe() go func() { _, err := io.Copy(w, s.Stdin) w.CloseWithError(err) }() stdin, s.stdinPipeWriter = r, w } s.copyFuncs = append(s.copyFuncs, func() error { _, err := io.Copy(s.ch, stdin) if err1 := s.ch.CloseWrite(); err == nil && err1 != io.EOF { err = err1 } return err }) } func (s *Session) stdout() { if s.stdoutpipe { return } if s.Stdout == nil { s.Stdout = ioutil.Discard } s.copyFuncs = append(s.copyFuncs, func() error { _, err := io.Copy(s.Stdout, s.ch) return err }) } func (s *Session) stderr() { if s.stderrpipe { return } if s.Stderr == nil { s.Stderr = ioutil.Discard } s.copyFuncs = append(s.copyFuncs, func() error { _, err := io.Copy(s.Stderr, s.ch.Stderr()) return err }) } // sessionStdin reroutes Close to CloseWrite. type sessionStdin struct { io.Writer ch Channel } func (s *sessionStdin) Close() error { return s.ch.CloseWrite() } // StdinPipe returns a pipe that will be connected to the // remote command's standard input when the command starts. func (s *Session) StdinPipe() (io.WriteCloser, error) { if s.Stdin != nil { return nil, errors.New("ssh: Stdin already set") } if s.started { return nil, errors.New("ssh: StdinPipe after process started") } s.stdinpipe = true return &sessionStdin{s.ch, s.ch}, nil } // StdoutPipe returns a pipe that will be connected to the // remote command's standard output when the command starts. // There is a fixed amount of buffering that is shared between // stdout and stderr streams. If the StdoutPipe reader is // not serviced fast enough it may eventually cause the // remote command to block. func (s *Session) StdoutPipe() (io.Reader, error) { if s.Stdout != nil { return nil, errors.New("ssh: Stdout already set") } if s.started { return nil, errors.New("ssh: StdoutPipe after process started") } s.stdoutpipe = true return s.ch, nil } // StderrPipe returns a pipe that will be connected to the // remote command's standard error when the command starts. // There is a fixed amount of buffering that is shared between // stdout and stderr streams. If the StderrPipe reader is // not serviced fast enough it may eventually cause the // remote command to block. func (s *Session) StderrPipe() (io.Reader, error) { if s.Stderr != nil { return nil, errors.New("ssh: Stderr already set") } if s.started { return nil, errors.New("ssh: StderrPipe after process started") } s.stderrpipe = true return s.ch.Stderr(), nil } // newSession returns a new interactive session on the remote host. func newSession(ch Channel, reqs <-chan *Request) (*Session, error) { s := &Session{ ch: ch, } s.exitStatus = make(chan error, 1) go func() { s.exitStatus <- s.wait(reqs) }() return s, nil } // An ExitError reports unsuccessful completion of a remote command. type ExitError struct { Waitmsg } func (e *ExitError) Error() string { return e.Waitmsg.String() } // Waitmsg stores the information about an exited remote command // as reported by Wait. type Waitmsg struct { status int signal string msg string lang string } // ExitStatus returns the exit status of the remote command. func (w Waitmsg) ExitStatus() int { return w.status } // Signal returns the exit signal of the remote command if // it was terminated violently. func (w Waitmsg) Signal() string { return w.signal } // Msg returns the exit message given by the remote command func (w Waitmsg) Msg() string { return w.msg } // Lang returns the language tag. See RFC 3066 func (w Waitmsg) Lang() string { return w.lang } func (w Waitmsg) String() string { return fmt.Sprintf("Process exited with: %v. Reason was: %v (%v)", w.status, w.msg, w.signal) } lxd-2.0.0/dist/src/golang.org/x/crypto/ssh/messages.go0000644061062106075000000004064312702772344025236 0ustar00stgraberdomain admins00000000000000// 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 ssh import ( "bytes" "encoding/binary" "errors" "fmt" "io" "math/big" "reflect" "strconv" ) // These are SSH message type numbers. They are scattered around several // documents but many were taken from [SSH-PARAMETERS]. const ( msgIgnore = 2 msgUnimplemented = 3 msgDebug = 4 msgNewKeys = 21 // Standard authentication messages msgUserAuthSuccess = 52 msgUserAuthBanner = 53 ) // SSH messages: // // These structures mirror the wire format of the corresponding SSH messages. // They are marshaled using reflection with the marshal and unmarshal functions // in this file. The only wrinkle is that a final member of type []byte with a // ssh tag of "rest" receives the remainder of a packet when unmarshaling. // See RFC 4253, section 11.1. const msgDisconnect = 1 // disconnectMsg is the message that signals a disconnect. It is also // the error type returned from mux.Wait() type disconnectMsg struct { Reason uint32 `sshtype:"1"` Message string Language string } func (d *disconnectMsg) Error() string { return fmt.Sprintf("ssh: disconnect, reason %d: %s", d.Reason, d.Message) } // See RFC 4253, section 7.1. const msgKexInit = 20 type kexInitMsg struct { Cookie [16]byte `sshtype:"20"` KexAlgos []string ServerHostKeyAlgos []string CiphersClientServer []string CiphersServerClient []string MACsClientServer []string MACsServerClient []string CompressionClientServer []string CompressionServerClient []string LanguagesClientServer []string LanguagesServerClient []string FirstKexFollows bool Reserved uint32 } // See RFC 4253, section 8. // Diffie-Helman const msgKexDHInit = 30 type kexDHInitMsg struct { X *big.Int `sshtype:"30"` } const msgKexECDHInit = 30 type kexECDHInitMsg struct { ClientPubKey []byte `sshtype:"30"` } const msgKexECDHReply = 31 type kexECDHReplyMsg struct { HostKey []byte `sshtype:"31"` EphemeralPubKey []byte Signature []byte } const msgKexDHReply = 31 type kexDHReplyMsg struct { HostKey []byte `sshtype:"31"` Y *big.Int Signature []byte } // See RFC 4253, section 10. const msgServiceRequest = 5 type serviceRequestMsg struct { Service string `sshtype:"5"` } // See RFC 4253, section 10. const msgServiceAccept = 6 type serviceAcceptMsg struct { Service string `sshtype:"6"` } // See RFC 4252, section 5. const msgUserAuthRequest = 50 type userAuthRequestMsg struct { User string `sshtype:"50"` Service string Method string Payload []byte `ssh:"rest"` } // See RFC 4252, section 5.1 const msgUserAuthFailure = 51 type userAuthFailureMsg struct { Methods []string `sshtype:"51"` PartialSuccess bool } // See RFC 4256, section 3.2 const msgUserAuthInfoRequest = 60 const msgUserAuthInfoResponse = 61 type userAuthInfoRequestMsg struct { User string `sshtype:"60"` Instruction string DeprecatedLanguage string NumPrompts uint32 Prompts []byte `ssh:"rest"` } // See RFC 4254, section 5.1. const msgChannelOpen = 90 type channelOpenMsg struct { ChanType string `sshtype:"90"` PeersId uint32 PeersWindow uint32 MaxPacketSize uint32 TypeSpecificData []byte `ssh:"rest"` } const msgChannelExtendedData = 95 const msgChannelData = 94 // See RFC 4254, section 5.1. const msgChannelOpenConfirm = 91 type channelOpenConfirmMsg struct { PeersId uint32 `sshtype:"91"` MyId uint32 MyWindow uint32 MaxPacketSize uint32 TypeSpecificData []byte `ssh:"rest"` } // See RFC 4254, section 5.1. const msgChannelOpenFailure = 92 type channelOpenFailureMsg struct { PeersId uint32 `sshtype:"92"` Reason RejectionReason Message string Language string } const msgChannelRequest = 98 type channelRequestMsg struct { PeersId uint32 `sshtype:"98"` Request string WantReply bool RequestSpecificData []byte `ssh:"rest"` } // See RFC 4254, section 5.4. const msgChannelSuccess = 99 type channelRequestSuccessMsg struct { PeersId uint32 `sshtype:"99"` } // See RFC 4254, section 5.4. const msgChannelFailure = 100 type channelRequestFailureMsg struct { PeersId uint32 `sshtype:"100"` } // See RFC 4254, section 5.3 const msgChannelClose = 97 type channelCloseMsg struct { PeersId uint32 `sshtype:"97"` } // See RFC 4254, section 5.3 const msgChannelEOF = 96 type channelEOFMsg struct { PeersId uint32 `sshtype:"96"` } // See RFC 4254, section 4 const msgGlobalRequest = 80 type globalRequestMsg struct { Type string `sshtype:"80"` WantReply bool Data []byte `ssh:"rest"` } // See RFC 4254, section 4 const msgRequestSuccess = 81 type globalRequestSuccessMsg struct { Data []byte `ssh:"rest" sshtype:"81"` } // See RFC 4254, section 4 const msgRequestFailure = 82 type globalRequestFailureMsg struct { Data []byte `ssh:"rest" sshtype:"82"` } // See RFC 4254, section 5.2 const msgChannelWindowAdjust = 93 type windowAdjustMsg struct { PeersId uint32 `sshtype:"93"` AdditionalBytes uint32 } // See RFC 4252, section 7 const msgUserAuthPubKeyOk = 60 type userAuthPubKeyOkMsg struct { Algo string `sshtype:"60"` PubKey []byte } // typeTag returns the type byte for the given type. The type should // be struct. func typeTag(structType reflect.Type) byte { var tag byte var tagStr string tagStr = structType.Field(0).Tag.Get("sshtype") i, err := strconv.Atoi(tagStr) if err == nil { tag = byte(i) } return tag } func fieldError(t reflect.Type, field int, problem string) error { if problem != "" { problem = ": " + problem } return fmt.Errorf("ssh: unmarshal error for field %s of type %s%s", t.Field(field).Name, t.Name(), problem) } var errShortRead = errors.New("ssh: short read") // Unmarshal parses data in SSH wire format into a structure. The out // argument should be a pointer to struct. If the first member of the // struct has the "sshtype" tag set to a number in decimal, the packet // must start that number. In case of error, Unmarshal returns a // ParseError or UnexpectedMessageError. func Unmarshal(data []byte, out interface{}) error { v := reflect.ValueOf(out).Elem() structType := v.Type() expectedType := typeTag(structType) if len(data) == 0 { return parseError(expectedType) } if expectedType > 0 { if data[0] != expectedType { return unexpectedMessageError(expectedType, data[0]) } data = data[1:] } var ok bool for i := 0; i < v.NumField(); i++ { field := v.Field(i) t := field.Type() switch t.Kind() { case reflect.Bool: if len(data) < 1 { return errShortRead } field.SetBool(data[0] != 0) data = data[1:] case reflect.Array: if t.Elem().Kind() != reflect.Uint8 { return fieldError(structType, i, "array of unsupported type") } if len(data) < t.Len() { return errShortRead } for j, n := 0, t.Len(); j < n; j++ { field.Index(j).Set(reflect.ValueOf(data[j])) } data = data[t.Len():] case reflect.Uint64: var u64 uint64 if u64, data, ok = parseUint64(data); !ok { return errShortRead } field.SetUint(u64) case reflect.Uint32: var u32 uint32 if u32, data, ok = parseUint32(data); !ok { return errShortRead } field.SetUint(uint64(u32)) case reflect.Uint8: if len(data) < 1 { return errShortRead } field.SetUint(uint64(data[0])) data = data[1:] case reflect.String: var s []byte if s, data, ok = parseString(data); !ok { return fieldError(structType, i, "") } field.SetString(string(s)) case reflect.Slice: switch t.Elem().Kind() { case reflect.Uint8: if structType.Field(i).Tag.Get("ssh") == "rest" { field.Set(reflect.ValueOf(data)) data = nil } else { var s []byte if s, data, ok = parseString(data); !ok { return errShortRead } field.Set(reflect.ValueOf(s)) } case reflect.String: var nl []string if nl, data, ok = parseNameList(data); !ok { return errShortRead } field.Set(reflect.ValueOf(nl)) default: return fieldError(structType, i, "slice of unsupported type") } case reflect.Ptr: if t == bigIntType { var n *big.Int if n, data, ok = parseInt(data); !ok { return errShortRead } field.Set(reflect.ValueOf(n)) } else { return fieldError(structType, i, "pointer to unsupported type") } default: return fieldError(structType, i, "unsupported type") } } if len(data) != 0 { return parseError(expectedType) } return nil } // Marshal serializes the message in msg to SSH wire format. The msg // argument should be a struct or pointer to struct. If the first // member has the "sshtype" tag set to a number in decimal, that // number is prepended to the result. If the last of member has the // "ssh" tag set to "rest", its contents are appended to the output. func Marshal(msg interface{}) []byte { out := make([]byte, 0, 64) return marshalStruct(out, msg) } func marshalStruct(out []byte, msg interface{}) []byte { v := reflect.Indirect(reflect.ValueOf(msg)) msgType := typeTag(v.Type()) if msgType > 0 { out = append(out, msgType) } for i, n := 0, v.NumField(); i < n; i++ { field := v.Field(i) switch t := field.Type(); t.Kind() { case reflect.Bool: var v uint8 if field.Bool() { v = 1 } out = append(out, v) case reflect.Array: if t.Elem().Kind() != reflect.Uint8 { panic(fmt.Sprintf("array of non-uint8 in field %d: %T", i, field.Interface())) } for j, l := 0, t.Len(); j < l; j++ { out = append(out, uint8(field.Index(j).Uint())) } case reflect.Uint32: out = appendU32(out, uint32(field.Uint())) case reflect.Uint64: out = appendU64(out, uint64(field.Uint())) case reflect.Uint8: out = append(out, uint8(field.Uint())) case reflect.String: s := field.String() out = appendInt(out, len(s)) out = append(out, s...) case reflect.Slice: switch t.Elem().Kind() { case reflect.Uint8: if v.Type().Field(i).Tag.Get("ssh") != "rest" { out = appendInt(out, field.Len()) } out = append(out, field.Bytes()...) case reflect.String: offset := len(out) out = appendU32(out, 0) if n := field.Len(); n > 0 { for j := 0; j < n; j++ { f := field.Index(j) if j != 0 { out = append(out, ',') } out = append(out, f.String()...) } // overwrite length value binary.BigEndian.PutUint32(out[offset:], uint32(len(out)-offset-4)) } default: panic(fmt.Sprintf("slice of unknown type in field %d: %T", i, field.Interface())) } case reflect.Ptr: if t == bigIntType { var n *big.Int nValue := reflect.ValueOf(&n) nValue.Elem().Set(field) needed := intLength(n) oldLength := len(out) if cap(out)-len(out) < needed { newOut := make([]byte, len(out), 2*(len(out)+needed)) copy(newOut, out) out = newOut } out = out[:oldLength+needed] marshalInt(out[oldLength:], n) } else { panic(fmt.Sprintf("pointer to unknown type in field %d: %T", i, field.Interface())) } } } return out } var bigOne = big.NewInt(1) func parseString(in []byte) (out, rest []byte, ok bool) { if len(in) < 4 { return } length := binary.BigEndian.Uint32(in) in = in[4:] if uint32(len(in)) < length { return } out = in[:length] rest = in[length:] ok = true return } var ( comma = []byte{','} emptyNameList = []string{} ) func parseNameList(in []byte) (out []string, rest []byte, ok bool) { contents, rest, ok := parseString(in) if !ok { return } if len(contents) == 0 { out = emptyNameList return } parts := bytes.Split(contents, comma) out = make([]string, len(parts)) for i, part := range parts { out[i] = string(part) } return } func parseInt(in []byte) (out *big.Int, rest []byte, ok bool) { contents, rest, ok := parseString(in) if !ok { return } out = new(big.Int) if len(contents) > 0 && contents[0]&0x80 == 0x80 { // This is a negative number notBytes := make([]byte, len(contents)) for i := range notBytes { notBytes[i] = ^contents[i] } out.SetBytes(notBytes) out.Add(out, bigOne) out.Neg(out) } else { // Positive number out.SetBytes(contents) } ok = true return } func parseUint32(in []byte) (uint32, []byte, bool) { if len(in) < 4 { return 0, nil, false } return binary.BigEndian.Uint32(in), in[4:], true } func parseUint64(in []byte) (uint64, []byte, bool) { if len(in) < 8 { return 0, nil, false } return binary.BigEndian.Uint64(in), in[8:], true } func intLength(n *big.Int) int { length := 4 /* length bytes */ if n.Sign() < 0 { nMinus1 := new(big.Int).Neg(n) nMinus1.Sub(nMinus1, bigOne) bitLen := nMinus1.BitLen() if bitLen%8 == 0 { // The number will need 0xff padding length++ } length += (bitLen + 7) / 8 } else if n.Sign() == 0 { // A zero is the zero length string } else { bitLen := n.BitLen() if bitLen%8 == 0 { // The number will need 0x00 padding length++ } length += (bitLen + 7) / 8 } return length } func marshalUint32(to []byte, n uint32) []byte { binary.BigEndian.PutUint32(to, n) return to[4:] } func marshalUint64(to []byte, n uint64) []byte { binary.BigEndian.PutUint64(to, n) return to[8:] } func marshalInt(to []byte, n *big.Int) []byte { lengthBytes := to to = to[4:] length := 0 if n.Sign() < 0 { // A negative number has to be converted to two's-complement // form. So we'll subtract 1 and invert. If the // most-significant-bit isn't set then we'll need to pad the // beginning with 0xff in order to keep the number negative. nMinus1 := new(big.Int).Neg(n) nMinus1.Sub(nMinus1, bigOne) bytes := nMinus1.Bytes() for i := range bytes { bytes[i] ^= 0xff } if len(bytes) == 0 || bytes[0]&0x80 == 0 { to[0] = 0xff to = to[1:] length++ } nBytes := copy(to, bytes) to = to[nBytes:] length += nBytes } else if n.Sign() == 0 { // A zero is the zero length string } else { bytes := n.Bytes() if len(bytes) > 0 && bytes[0]&0x80 != 0 { // We'll have to pad this with a 0x00 in order to // stop it looking like a negative number. to[0] = 0 to = to[1:] length++ } nBytes := copy(to, bytes) to = to[nBytes:] length += nBytes } lengthBytes[0] = byte(length >> 24) lengthBytes[1] = byte(length >> 16) lengthBytes[2] = byte(length >> 8) lengthBytes[3] = byte(length) return to } func writeInt(w io.Writer, n *big.Int) { length := intLength(n) buf := make([]byte, length) marshalInt(buf, n) w.Write(buf) } func writeString(w io.Writer, s []byte) { var lengthBytes [4]byte lengthBytes[0] = byte(len(s) >> 24) lengthBytes[1] = byte(len(s) >> 16) lengthBytes[2] = byte(len(s) >> 8) lengthBytes[3] = byte(len(s)) w.Write(lengthBytes[:]) w.Write(s) } func stringLength(n int) int { return 4 + n } func marshalString(to []byte, s []byte) []byte { to[0] = byte(len(s) >> 24) to[1] = byte(len(s) >> 16) to[2] = byte(len(s) >> 8) to[3] = byte(len(s)) to = to[4:] copy(to, s) return to[len(s):] } var bigIntType = reflect.TypeOf((*big.Int)(nil)) // Decode a packet into its corresponding message. func decode(packet []byte) (interface{}, error) { var msg interface{} switch packet[0] { case msgDisconnect: msg = new(disconnectMsg) case msgServiceRequest: msg = new(serviceRequestMsg) case msgServiceAccept: msg = new(serviceAcceptMsg) case msgKexInit: msg = new(kexInitMsg) case msgKexDHInit: msg = new(kexDHInitMsg) case msgKexDHReply: msg = new(kexDHReplyMsg) case msgUserAuthRequest: msg = new(userAuthRequestMsg) case msgUserAuthFailure: msg = new(userAuthFailureMsg) case msgUserAuthPubKeyOk: msg = new(userAuthPubKeyOkMsg) case msgGlobalRequest: msg = new(globalRequestMsg) case msgRequestSuccess: msg = new(globalRequestSuccessMsg) case msgRequestFailure: msg = new(globalRequestFailureMsg) case msgChannelOpen: msg = new(channelOpenMsg) case msgChannelOpenConfirm: msg = new(channelOpenConfirmMsg) case msgChannelOpenFailure: msg = new(channelOpenFailureMsg) case msgChannelWindowAdjust: msg = new(windowAdjustMsg) case msgChannelEOF: msg = new(channelEOFMsg) case msgChannelClose: msg = new(channelCloseMsg) case msgChannelRequest: msg = new(channelRequestMsg) case msgChannelSuccess: msg = new(channelRequestSuccessMsg) case msgChannelFailure: msg = new(channelRequestFailureMsg) default: return nil, unexpectedMessageError(0, packet[0]) } if err := Unmarshal(packet, msg); err != nil { return nil, err } return msg, nil } lxd-2.0.0/dist/src/golang.org/x/crypto/ssh/client_auth_test.go0000644061062106075000000002353512702772344026766 0ustar00stgraberdomain admins00000000000000// 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 ssh import ( "bytes" "crypto/rand" "errors" "fmt" "strings" "testing" ) type keyboardInteractive map[string]string func (cr keyboardInteractive) Challenge(user string, instruction string, questions []string, echos []bool) ([]string, error) { var answers []string for _, q := range questions { answers = append(answers, cr[q]) } return answers, nil } // reused internally by tests var clientPassword = "tiger" // tryAuth runs a handshake with a given config against an SSH server // with config serverConfig func tryAuth(t *testing.T, config *ClientConfig) error { c1, c2, err := netPipe() if err != nil { t.Fatalf("netPipe: %v", err) } defer c1.Close() defer c2.Close() certChecker := CertChecker{ IsAuthority: func(k PublicKey) bool { return bytes.Equal(k.Marshal(), testPublicKeys["ecdsa"].Marshal()) }, UserKeyFallback: func(conn ConnMetadata, key PublicKey) (*Permissions, error) { if conn.User() == "testuser" && bytes.Equal(key.Marshal(), testPublicKeys["rsa"].Marshal()) { return nil, nil } return nil, fmt.Errorf("pubkey for %q not acceptable", conn.User()) }, IsRevoked: func(c *Certificate) bool { return c.Serial == 666 }, } serverConfig := &ServerConfig{ PasswordCallback: func(conn ConnMetadata, pass []byte) (*Permissions, error) { if conn.User() == "testuser" && string(pass) == clientPassword { return nil, nil } return nil, errors.New("password auth failed") }, PublicKeyCallback: certChecker.Authenticate, KeyboardInteractiveCallback: func(conn ConnMetadata, challenge KeyboardInteractiveChallenge) (*Permissions, error) { ans, err := challenge("user", "instruction", []string{"question1", "question2"}, []bool{true, true}) if err != nil { return nil, err } ok := conn.User() == "testuser" && ans[0] == "answer1" && ans[1] == "answer2" if ok { challenge("user", "motd", nil, nil) return nil, nil } return nil, errors.New("keyboard-interactive failed") }, AuthLogCallback: func(conn ConnMetadata, method string, err error) { t.Logf("user %q, method %q: %v", conn.User(), method, err) }, } serverConfig.AddHostKey(testSigners["rsa"]) go newServer(c1, serverConfig) _, _, _, err = NewClientConn(c2, "", config) return err } func TestClientAuthPublicKey(t *testing.T) { config := &ClientConfig{ User: "testuser", Auth: []AuthMethod{ PublicKeys(testSigners["rsa"]), }, } if err := tryAuth(t, config); err != nil { t.Fatalf("unable to dial remote side: %s", err) } } func TestAuthMethodPassword(t *testing.T) { config := &ClientConfig{ User: "testuser", Auth: []AuthMethod{ Password(clientPassword), }, } if err := tryAuth(t, config); err != nil { t.Fatalf("unable to dial remote side: %s", err) } } func TestAuthMethodFallback(t *testing.T) { var passwordCalled bool config := &ClientConfig{ User: "testuser", Auth: []AuthMethod{ PublicKeys(testSigners["rsa"]), PasswordCallback( func() (string, error) { passwordCalled = true return "WRONG", nil }), }, } if err := tryAuth(t, config); err != nil { t.Fatalf("unable to dial remote side: %s", err) } if passwordCalled { t.Errorf("password auth tried before public-key auth.") } } func TestAuthMethodWrongPassword(t *testing.T) { config := &ClientConfig{ User: "testuser", Auth: []AuthMethod{ Password("wrong"), PublicKeys(testSigners["rsa"]), }, } if err := tryAuth(t, config); err != nil { t.Fatalf("unable to dial remote side: %s", err) } } func TestAuthMethodKeyboardInteractive(t *testing.T) { answers := keyboardInteractive(map[string]string{ "question1": "answer1", "question2": "answer2", }) config := &ClientConfig{ User: "testuser", Auth: []AuthMethod{ KeyboardInteractive(answers.Challenge), }, } if err := tryAuth(t, config); err != nil { t.Fatalf("unable to dial remote side: %s", err) } } func TestAuthMethodWrongKeyboardInteractive(t *testing.T) { answers := keyboardInteractive(map[string]string{ "question1": "answer1", "question2": "WRONG", }) config := &ClientConfig{ User: "testuser", Auth: []AuthMethod{ KeyboardInteractive(answers.Challenge), }, } if err := tryAuth(t, config); err == nil { t.Fatalf("wrong answers should not have authenticated with KeyboardInteractive") } } // the mock server will only authenticate ssh-rsa keys func TestAuthMethodInvalidPublicKey(t *testing.T) { config := &ClientConfig{ User: "testuser", Auth: []AuthMethod{ PublicKeys(testSigners["dsa"]), }, } if err := tryAuth(t, config); err == nil { t.Fatalf("dsa private key should not have authenticated with rsa public key") } } // the client should authenticate with the second key func TestAuthMethodRSAandDSA(t *testing.T) { config := &ClientConfig{ User: "testuser", Auth: []AuthMethod{ PublicKeys(testSigners["dsa"], testSigners["rsa"]), }, } if err := tryAuth(t, config); err != nil { t.Fatalf("client could not authenticate with rsa key: %v", err) } } func TestClientHMAC(t *testing.T) { for _, mac := range supportedMACs { config := &ClientConfig{ User: "testuser", Auth: []AuthMethod{ PublicKeys(testSigners["rsa"]), }, Config: Config{ MACs: []string{mac}, }, } if err := tryAuth(t, config); err != nil { t.Fatalf("client could not authenticate with mac algo %s: %v", mac, err) } } } // issue 4285. func TestClientUnsupportedCipher(t *testing.T) { config := &ClientConfig{ User: "testuser", Auth: []AuthMethod{ PublicKeys(), }, Config: Config{ Ciphers: []string{"aes128-cbc"}, // not currently supported }, } if err := tryAuth(t, config); err == nil { t.Errorf("expected no ciphers in common") } } func TestClientUnsupportedKex(t *testing.T) { config := &ClientConfig{ User: "testuser", Auth: []AuthMethod{ PublicKeys(), }, Config: Config{ KeyExchanges: []string{"diffie-hellman-group-exchange-sha256"}, // not currently supported }, } if err := tryAuth(t, config); err == nil || !strings.Contains(err.Error(), "common algorithm") { t.Errorf("got %v, expected 'common algorithm'", err) } } func TestClientLoginCert(t *testing.T) { cert := &Certificate{ Key: testPublicKeys["rsa"], ValidBefore: CertTimeInfinity, CertType: UserCert, } cert.SignCert(rand.Reader, testSigners["ecdsa"]) certSigner, err := NewCertSigner(cert, testSigners["rsa"]) if err != nil { t.Fatalf("NewCertSigner: %v", err) } clientConfig := &ClientConfig{ User: "user", } clientConfig.Auth = append(clientConfig.Auth, PublicKeys(certSigner)) t.Log("should succeed") if err := tryAuth(t, clientConfig); err != nil { t.Errorf("cert login failed: %v", err) } t.Log("corrupted signature") cert.Signature.Blob[0]++ if err := tryAuth(t, clientConfig); err == nil { t.Errorf("cert login passed with corrupted sig") } t.Log("revoked") cert.Serial = 666 cert.SignCert(rand.Reader, testSigners["ecdsa"]) if err := tryAuth(t, clientConfig); err == nil { t.Errorf("revoked cert login succeeded") } cert.Serial = 1 t.Log("sign with wrong key") cert.SignCert(rand.Reader, testSigners["dsa"]) if err := tryAuth(t, clientConfig); err == nil { t.Errorf("cert login passed with non-authoritive key") } t.Log("host cert") cert.CertType = HostCert cert.SignCert(rand.Reader, testSigners["ecdsa"]) if err := tryAuth(t, clientConfig); err == nil { t.Errorf("cert login passed with wrong type") } cert.CertType = UserCert t.Log("principal specified") cert.ValidPrincipals = []string{"user"} cert.SignCert(rand.Reader, testSigners["ecdsa"]) if err := tryAuth(t, clientConfig); err != nil { t.Errorf("cert login failed: %v", err) } t.Log("wrong principal specified") cert.ValidPrincipals = []string{"fred"} cert.SignCert(rand.Reader, testSigners["ecdsa"]) if err := tryAuth(t, clientConfig); err == nil { t.Errorf("cert login passed with wrong principal") } cert.ValidPrincipals = nil t.Log("added critical option") cert.CriticalOptions = map[string]string{"root-access": "yes"} cert.SignCert(rand.Reader, testSigners["ecdsa"]) if err := tryAuth(t, clientConfig); err == nil { t.Errorf("cert login passed with unrecognized critical option") } t.Log("allowed source address") cert.CriticalOptions = map[string]string{"source-address": "127.0.0.42/24"} cert.SignCert(rand.Reader, testSigners["ecdsa"]) if err := tryAuth(t, clientConfig); err != nil { t.Errorf("cert login with source-address failed: %v", err) } t.Log("disallowed source address") cert.CriticalOptions = map[string]string{"source-address": "127.0.0.42"} cert.SignCert(rand.Reader, testSigners["ecdsa"]) if err := tryAuth(t, clientConfig); err == nil { t.Errorf("cert login with source-address succeeded") } } func testPermissionsPassing(withPermissions bool, t *testing.T) { serverConfig := &ServerConfig{ PublicKeyCallback: func(conn ConnMetadata, key PublicKey) (*Permissions, error) { if conn.User() == "nopermissions" { return nil, nil } else { return &Permissions{}, nil } }, } serverConfig.AddHostKey(testSigners["rsa"]) clientConfig := &ClientConfig{ Auth: []AuthMethod{ PublicKeys(testSigners["rsa"]), }, } if withPermissions { clientConfig.User = "permissions" } else { clientConfig.User = "nopermissions" } c1, c2, err := netPipe() if err != nil { t.Fatalf("netPipe: %v", err) } defer c1.Close() defer c2.Close() go NewClientConn(c2, "", clientConfig) serverConn, err := newServer(c1, serverConfig) if err != nil { t.Fatal(err) } if p := serverConn.Permissions; (p != nil) != withPermissions { t.Fatalf("withPermissions is %t, but Permissions object is %#v", withPermissions, p) } } func TestPermissionsPassing(t *testing.T) { testPermissionsPassing(true, t) } func TestNoPermissionsPassing(t *testing.T) { testPermissionsPassing(false, t) } lxd-2.0.0/dist/src/golang.org/x/crypto/ssh/client_auth.go0000644061062106075000000002716312702772344025730 0ustar00stgraberdomain admins00000000000000// 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 ssh import ( "bytes" "errors" "fmt" "io" ) // clientAuthenticate authenticates with the remote server. See RFC 4252. func (c *connection) clientAuthenticate(config *ClientConfig) error { // initiate user auth session if err := c.transport.writePacket(Marshal(&serviceRequestMsg{serviceUserAuth})); err != nil { return err } packet, err := c.transport.readPacket() if err != nil { return err } var serviceAccept serviceAcceptMsg if err := Unmarshal(packet, &serviceAccept); err != nil { return err } // during the authentication phase the client first attempts the "none" method // then any untried methods suggested by the server. tried := make(map[string]bool) var lastMethods []string for auth := AuthMethod(new(noneAuth)); auth != nil; { ok, methods, err := auth.auth(c.transport.getSessionID(), config.User, c.transport, config.Rand) if err != nil { return err } if ok { // success return nil } tried[auth.method()] = true if methods == nil { methods = lastMethods } lastMethods = methods auth = nil findNext: for _, a := range config.Auth { candidateMethod := a.method() if tried[candidateMethod] { continue } for _, meth := range methods { if meth == candidateMethod { auth = a break findNext } } } } return fmt.Errorf("ssh: unable to authenticate, attempted methods %v, no supported methods remain", keys(tried)) } func keys(m map[string]bool) []string { s := make([]string, 0, len(m)) for key := range m { s = append(s, key) } return s } // An AuthMethod represents an instance of an RFC 4252 authentication method. type AuthMethod interface { // auth authenticates user over transport t. // Returns true if authentication is successful. // If authentication is not successful, a []string of alternative // method names is returned. If the slice is nil, it will be ignored // and the previous set of possible methods will be reused. auth(session []byte, user string, p packetConn, rand io.Reader) (bool, []string, error) // method returns the RFC 4252 method name. method() string } // "none" authentication, RFC 4252 section 5.2. type noneAuth int func (n *noneAuth) auth(session []byte, user string, c packetConn, rand io.Reader) (bool, []string, error) { if err := c.writePacket(Marshal(&userAuthRequestMsg{ User: user, Service: serviceSSH, Method: "none", })); err != nil { return false, nil, err } return handleAuthResponse(c) } func (n *noneAuth) method() string { return "none" } // passwordCallback is an AuthMethod that fetches the password through // a function call, e.g. by prompting the user. type passwordCallback func() (password string, err error) func (cb passwordCallback) auth(session []byte, user string, c packetConn, rand io.Reader) (bool, []string, error) { type passwordAuthMsg struct { User string `sshtype:"50"` Service string Method string Reply bool Password string } pw, err := cb() // REVIEW NOTE: is there a need to support skipping a password attempt? // The program may only find out that the user doesn't have a password // when prompting. if err != nil { return false, nil, err } if err := c.writePacket(Marshal(&passwordAuthMsg{ User: user, Service: serviceSSH, Method: cb.method(), Reply: false, Password: pw, })); err != nil { return false, nil, err } return handleAuthResponse(c) } func (cb passwordCallback) method() string { return "password" } // Password returns an AuthMethod using the given password. func Password(secret string) AuthMethod { return passwordCallback(func() (string, error) { return secret, nil }) } // PasswordCallback returns an AuthMethod that uses a callback for // fetching a password. func PasswordCallback(prompt func() (secret string, err error)) AuthMethod { return passwordCallback(prompt) } type publickeyAuthMsg struct { User string `sshtype:"50"` Service string Method string // HasSig indicates to the receiver packet that the auth request is signed and // should be used for authentication of the request. HasSig bool Algoname string PubKey []byte // Sig is tagged with "rest" so Marshal will exclude it during // validateKey Sig []byte `ssh:"rest"` } // publicKeyCallback is an AuthMethod that uses a set of key // pairs for authentication. type publicKeyCallback func() ([]Signer, error) func (cb publicKeyCallback) method() string { return "publickey" } func (cb publicKeyCallback) auth(session []byte, user string, c packetConn, rand io.Reader) (bool, []string, error) { // Authentication is performed in two stages. The first stage sends an // enquiry to test if each key is acceptable to the remote. The second // stage attempts to authenticate with the valid keys obtained in the // first stage. signers, err := cb() if err != nil { return false, nil, err } var validKeys []Signer for _, signer := range signers { if ok, err := validateKey(signer.PublicKey(), user, c); ok { validKeys = append(validKeys, signer) } else { if err != nil { return false, nil, err } } } // methods that may continue if this auth is not successful. var methods []string for _, signer := range validKeys { pub := signer.PublicKey() pubKey := pub.Marshal() sign, err := signer.Sign(rand, buildDataSignedForAuth(session, userAuthRequestMsg{ User: user, Service: serviceSSH, Method: cb.method(), }, []byte(pub.Type()), pubKey)) if err != nil { return false, nil, err } // manually wrap the serialized signature in a string s := Marshal(sign) sig := make([]byte, stringLength(len(s))) marshalString(sig, s) msg := publickeyAuthMsg{ User: user, Service: serviceSSH, Method: cb.method(), HasSig: true, Algoname: pub.Type(), PubKey: pubKey, Sig: sig, } p := Marshal(&msg) if err := c.writePacket(p); err != nil { return false, nil, err } var success bool success, methods, err = handleAuthResponse(c) if err != nil { return false, nil, err } if success { return success, methods, err } } return false, methods, nil } // validateKey validates the key provided is acceptable to the server. func validateKey(key PublicKey, user string, c packetConn) (bool, error) { pubKey := key.Marshal() msg := publickeyAuthMsg{ User: user, Service: serviceSSH, Method: "publickey", HasSig: false, Algoname: key.Type(), PubKey: pubKey, } if err := c.writePacket(Marshal(&msg)); err != nil { return false, err } return confirmKeyAck(key, c) } func confirmKeyAck(key PublicKey, c packetConn) (bool, error) { pubKey := key.Marshal() algoname := key.Type() for { packet, err := c.readPacket() if err != nil { return false, err } switch packet[0] { case msgUserAuthBanner: // TODO(gpaul): add callback to present the banner to the user case msgUserAuthPubKeyOk: var msg userAuthPubKeyOkMsg if err := Unmarshal(packet, &msg); err != nil { return false, err } if msg.Algo != algoname || !bytes.Equal(msg.PubKey, pubKey) { return false, nil } return true, nil case msgUserAuthFailure: return false, nil default: return false, unexpectedMessageError(msgUserAuthSuccess, packet[0]) } } } // PublicKeys returns an AuthMethod that uses the given key // pairs. func PublicKeys(signers ...Signer) AuthMethod { return publicKeyCallback(func() ([]Signer, error) { return signers, nil }) } // PublicKeysCallback returns an AuthMethod that runs the given // function to obtain a list of key pairs. func PublicKeysCallback(getSigners func() (signers []Signer, err error)) AuthMethod { return publicKeyCallback(getSigners) } // handleAuthResponse returns whether the preceding authentication request succeeded // along with a list of remaining authentication methods to try next and // an error if an unexpected response was received. func handleAuthResponse(c packetConn) (bool, []string, error) { for { packet, err := c.readPacket() if err != nil { return false, nil, err } switch packet[0] { case msgUserAuthBanner: // TODO: add callback to present the banner to the user case msgUserAuthFailure: var msg userAuthFailureMsg if err := Unmarshal(packet, &msg); err != nil { return false, nil, err } return false, msg.Methods, nil case msgUserAuthSuccess: return true, nil, nil default: return false, nil, unexpectedMessageError(msgUserAuthSuccess, packet[0]) } } } // KeyboardInteractiveChallenge should print questions, optionally // disabling echoing (e.g. for passwords), and return all the answers. // Challenge may be called multiple times in a single session. After // successful authentication, the server may send a challenge with no // questions, for which the user and instruction messages should be // printed. RFC 4256 section 3.3 details how the UI should behave for // both CLI and GUI environments. type KeyboardInteractiveChallenge func(user, instruction string, questions []string, echos []bool) (answers []string, err error) // KeyboardInteractive returns a AuthMethod using a prompt/response // sequence controlled by the server. func KeyboardInteractive(challenge KeyboardInteractiveChallenge) AuthMethod { return challenge } func (cb KeyboardInteractiveChallenge) method() string { return "keyboard-interactive" } func (cb KeyboardInteractiveChallenge) auth(session []byte, user string, c packetConn, rand io.Reader) (bool, []string, error) { type initiateMsg struct { User string `sshtype:"50"` Service string Method string Language string Submethods string } if err := c.writePacket(Marshal(&initiateMsg{ User: user, Service: serviceSSH, Method: "keyboard-interactive", })); err != nil { return false, nil, err } for { packet, err := c.readPacket() if err != nil { return false, nil, err } // like handleAuthResponse, but with less options. switch packet[0] { case msgUserAuthBanner: // TODO: Print banners during userauth. continue case msgUserAuthInfoRequest: // OK case msgUserAuthFailure: var msg userAuthFailureMsg if err := Unmarshal(packet, &msg); err != nil { return false, nil, err } return false, msg.Methods, nil case msgUserAuthSuccess: return true, nil, nil default: return false, nil, unexpectedMessageError(msgUserAuthInfoRequest, packet[0]) } var msg userAuthInfoRequestMsg if err := Unmarshal(packet, &msg); err != nil { return false, nil, err } // Manually unpack the prompt/echo pairs. rest := msg.Prompts var prompts []string var echos []bool for i := 0; i < int(msg.NumPrompts); i++ { prompt, r, ok := parseString(rest) if !ok || len(r) == 0 { return false, nil, errors.New("ssh: prompt format error") } prompts = append(prompts, string(prompt)) echos = append(echos, r[0] != 0) rest = r[1:] } if len(rest) != 0 { return false, nil, errors.New("ssh: extra data following keyboard-interactive pairs") } answers, err := cb(msg.User, msg.Instruction, prompts, echos) if err != nil { return false, nil, err } if len(answers) != len(prompts) { return false, nil, errors.New("ssh: not enough answers from keyboard-interactive callback") } responseLength := 1 + 4 for _, a := range answers { responseLength += stringLength(len(a)) } serialized := make([]byte, responseLength) p := serialized p[0] = msgUserAuthInfoResponse p = p[1:] p = marshalUint32(p, uint32(len(answers))) for _, a := range answers { p = marshalString(p, []byte(a)) } if err := c.writePacket(serialized); err != nil { return false, nil, err } } } lxd-2.0.0/dist/src/golang.org/x/crypto/ssh/transport_test.go0000644061062106075000000000502512702772344026515 0ustar00stgraberdomain admins00000000000000// 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 ssh import ( "bytes" "crypto/rand" "encoding/binary" "strings" "testing" ) func TestReadVersion(t *testing.T) { longversion := strings.Repeat("SSH-2.0-bla", 50)[:253] cases := map[string]string{ "SSH-2.0-bla\r\n": "SSH-2.0-bla", "SSH-2.0-bla\n": "SSH-2.0-bla", longversion + "\r\n": longversion, } for in, want := range cases { result, err := readVersion(bytes.NewBufferString(in)) if err != nil { t.Errorf("readVersion(%q): %s", in, err) } got := string(result) if got != want { t.Errorf("got %q, want %q", got, want) } } } func TestReadVersionError(t *testing.T) { longversion := strings.Repeat("SSH-2.0-bla", 50)[:253] cases := []string{ longversion + "too-long\r\n", } for _, in := range cases { if _, err := readVersion(bytes.NewBufferString(in)); err == nil { t.Errorf("readVersion(%q) should have failed", in) } } } func TestExchangeVersionsBasic(t *testing.T) { v := "SSH-2.0-bla" buf := bytes.NewBufferString(v + "\r\n") them, err := exchangeVersions(buf, []byte("xyz")) if err != nil { t.Errorf("exchangeVersions: %v", err) } if want := "SSH-2.0-bla"; string(them) != want { t.Errorf("got %q want %q for our version", them, want) } } func TestExchangeVersions(t *testing.T) { cases := []string{ "not\x000allowed", "not allowed\n", } for _, c := range cases { buf := bytes.NewBufferString("SSH-2.0-bla\r\n") if _, err := exchangeVersions(buf, []byte(c)); err == nil { t.Errorf("exchangeVersions(%q): should have failed", c) } } } type closerBuffer struct { bytes.Buffer } func (b *closerBuffer) Close() error { return nil } func TestTransportMaxPacketWrite(t *testing.T) { buf := &closerBuffer{} tr := newTransport(buf, rand.Reader, true) huge := make([]byte, maxPacket+1) err := tr.writePacket(huge) if err == nil { t.Errorf("transport accepted write for a huge packet.") } } func TestTransportMaxPacketReader(t *testing.T) { var header [5]byte huge := make([]byte, maxPacket+128) binary.BigEndian.PutUint32(header[0:], uint32(len(huge))) // padding. header[4] = 0 buf := &closerBuffer{} buf.Write(header[:]) buf.Write(huge) tr := newTransport(buf, rand.Reader, true) _, err := tr.readPacket() if err == nil { t.Errorf("transport succeeded reading huge packet.") } else if !strings.Contains(err.Error(), "large") { t.Errorf("got %q, should mention %q", err.Error(), "large") } } lxd-2.0.0/dist/src/golang.org/x/crypto/ssh/common.go0000644061062106075000000002210012702772344024703 0ustar00stgraberdomain admins00000000000000// 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 ssh import ( "crypto" "crypto/rand" "fmt" "io" "sync" _ "crypto/sha1" _ "crypto/sha256" _ "crypto/sha512" ) // These are string constants in the SSH protocol. const ( compressionNone = "none" serviceUserAuth = "ssh-userauth" serviceSSH = "ssh-connection" ) // supportedCiphers specifies the supported ciphers in preference order. var supportedCiphers = []string{ "aes128-ctr", "aes192-ctr", "aes256-ctr", "aes128-gcm@openssh.com", "arcfour256", "arcfour128", } // supportedKexAlgos specifies the supported key-exchange algorithms in // preference order. var supportedKexAlgos = []string{ kexAlgoCurve25519SHA256, // P384 and P521 are not constant-time yet, but since we don't // reuse ephemeral keys, using them for ECDH should be OK. kexAlgoECDH256, kexAlgoECDH384, kexAlgoECDH521, kexAlgoDH14SHA1, kexAlgoDH1SHA1, } // supportedKexAlgos specifies the supported host-key algorithms (i.e. methods // of authenticating servers) in preference order. var supportedHostKeyAlgos = []string{ CertAlgoRSAv01, CertAlgoDSAv01, CertAlgoECDSA256v01, CertAlgoECDSA384v01, CertAlgoECDSA521v01, KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521, KeyAlgoRSA, KeyAlgoDSA, } // supportedMACs specifies a default set of MAC algorithms in preference order. // This is based on RFC 4253, section 6.4, but with hmac-md5 variants removed // because they have reached the end of their useful life. var supportedMACs = []string{ "hmac-sha2-256", "hmac-sha1", "hmac-sha1-96", } var supportedCompressions = []string{compressionNone} // hashFuncs keeps the mapping of supported algorithms to their respective // hashes needed for signature verification. var hashFuncs = map[string]crypto.Hash{ KeyAlgoRSA: crypto.SHA1, KeyAlgoDSA: crypto.SHA1, KeyAlgoECDSA256: crypto.SHA256, KeyAlgoECDSA384: crypto.SHA384, KeyAlgoECDSA521: crypto.SHA512, CertAlgoRSAv01: crypto.SHA1, CertAlgoDSAv01: crypto.SHA1, CertAlgoECDSA256v01: crypto.SHA256, CertAlgoECDSA384v01: crypto.SHA384, CertAlgoECDSA521v01: crypto.SHA512, } // unexpectedMessageError results when the SSH message that we received didn't // match what we wanted. func unexpectedMessageError(expected, got uint8) error { return fmt.Errorf("ssh: unexpected message type %d (expected %d)", got, expected) } // parseError results from a malformed SSH message. func parseError(tag uint8) error { return fmt.Errorf("ssh: parse error in message type %d", tag) } func findCommon(what string, client []string, server []string) (common string, err error) { for _, c := range client { for _, s := range server { if c == s { return c, nil } } } return "", fmt.Errorf("ssh: no common algorithm for %s; client offered: %v, server offered: %v", what, client, server) } type directionAlgorithms struct { Cipher string MAC string Compression string } type algorithms struct { kex string hostKey string w directionAlgorithms r directionAlgorithms } func findAgreedAlgorithms(clientKexInit, serverKexInit *kexInitMsg) (algs *algorithms, err error) { result := &algorithms{} result.kex, err = findCommon("key exchange", clientKexInit.KexAlgos, serverKexInit.KexAlgos) if err != nil { return } result.hostKey, err = findCommon("host key", clientKexInit.ServerHostKeyAlgos, serverKexInit.ServerHostKeyAlgos) if err != nil { return } result.w.Cipher, err = findCommon("client to server cipher", clientKexInit.CiphersClientServer, serverKexInit.CiphersClientServer) if err != nil { return } result.r.Cipher, err = findCommon("server to client cipher", clientKexInit.CiphersServerClient, serverKexInit.CiphersServerClient) if err != nil { return } result.w.MAC, err = findCommon("client to server MAC", clientKexInit.MACsClientServer, serverKexInit.MACsClientServer) if err != nil { return } result.r.MAC, err = findCommon("server to client MAC", clientKexInit.MACsServerClient, serverKexInit.MACsServerClient) if err != nil { return } result.w.Compression, err = findCommon("client to server compression", clientKexInit.CompressionClientServer, serverKexInit.CompressionClientServer) if err != nil { return } result.r.Compression, err = findCommon("server to client compression", clientKexInit.CompressionServerClient, serverKexInit.CompressionServerClient) if err != nil { return } return result, nil } // If rekeythreshold is too small, we can't make any progress sending // stuff. const minRekeyThreshold uint64 = 256 // Config contains configuration data common to both ServerConfig and // ClientConfig. type Config struct { // Rand provides the source of entropy for cryptographic // primitives. If Rand is nil, the cryptographic random reader // in package crypto/rand will be used. Rand io.Reader // The maximum number of bytes sent or received after which a // new key is negotiated. It must be at least 256. If // unspecified, 1 gigabyte is used. RekeyThreshold uint64 // The allowed key exchanges algorithms. If unspecified then a // default set of algorithms is used. KeyExchanges []string // The allowed cipher algorithms. If unspecified then a sensible // default is used. Ciphers []string // The allowed MAC algorithms. If unspecified then a sensible default // is used. MACs []string } // SetDefaults sets sensible values for unset fields in config. This is // exported for testing: Configs passed to SSH functions are copied and have // default values set automatically. func (c *Config) SetDefaults() { if c.Rand == nil { c.Rand = rand.Reader } if c.Ciphers == nil { c.Ciphers = supportedCiphers } var ciphers []string for _, c := range c.Ciphers { if cipherModes[c] != nil { // reject the cipher if we have no cipherModes definition ciphers = append(ciphers, c) } } c.Ciphers = ciphers if c.KeyExchanges == nil { c.KeyExchanges = supportedKexAlgos } if c.MACs == nil { c.MACs = supportedMACs } if c.RekeyThreshold == 0 { // RFC 4253, section 9 suggests rekeying after 1G. c.RekeyThreshold = 1 << 30 } if c.RekeyThreshold < minRekeyThreshold { c.RekeyThreshold = minRekeyThreshold } } // buildDataSignedForAuth returns the data that is signed in order to prove // possession of a private key. See RFC 4252, section 7. func buildDataSignedForAuth(sessionId []byte, req userAuthRequestMsg, algo, pubKey []byte) []byte { data := struct { Session []byte Type byte User string Service string Method string Sign bool Algo []byte PubKey []byte }{ sessionId, msgUserAuthRequest, req.User, req.Service, req.Method, true, algo, pubKey, } return Marshal(data) } func appendU16(buf []byte, n uint16) []byte { return append(buf, byte(n>>8), byte(n)) } func appendU32(buf []byte, n uint32) []byte { return append(buf, byte(n>>24), byte(n>>16), byte(n>>8), byte(n)) } func appendU64(buf []byte, n uint64) []byte { return append(buf, byte(n>>56), byte(n>>48), byte(n>>40), byte(n>>32), byte(n>>24), byte(n>>16), byte(n>>8), byte(n)) } func appendInt(buf []byte, n int) []byte { return appendU32(buf, uint32(n)) } func appendString(buf []byte, s string) []byte { buf = appendU32(buf, uint32(len(s))) buf = append(buf, s...) return buf } func appendBool(buf []byte, b bool) []byte { if b { return append(buf, 1) } return append(buf, 0) } // newCond is a helper to hide the fact that there is no usable zero // value for sync.Cond. func newCond() *sync.Cond { return sync.NewCond(new(sync.Mutex)) } // window represents the buffer available to clients // wishing to write to a channel. type window struct { *sync.Cond win uint32 // RFC 4254 5.2 says the window size can grow to 2^32-1 writeWaiters int closed bool } // add adds win to the amount of window available // for consumers. func (w *window) add(win uint32) bool { // a zero sized window adjust is a noop. if win == 0 { return true } w.L.Lock() if w.win+win < win { w.L.Unlock() return false } w.win += win // It is unusual that multiple goroutines would be attempting to reserve // window space, but not guaranteed. Use broadcast to notify all waiters // that additional window is available. w.Broadcast() w.L.Unlock() return true } // close sets the window to closed, so all reservations fail // immediately. func (w *window) close() { w.L.Lock() w.closed = true w.Broadcast() w.L.Unlock() } // reserve reserves win from the available window capacity. // If no capacity remains, reserve will block. reserve may // return less than requested. func (w *window) reserve(win uint32) (uint32, error) { var err error w.L.Lock() w.writeWaiters++ w.Broadcast() for w.win == 0 && !w.closed { w.Wait() } w.writeWaiters-- if w.win < win { win = w.win } w.win -= win if w.closed { err = io.EOF } w.L.Unlock() return win, err } // waitWriterBlocked waits until some goroutine is blocked for further // writes. It is used in tests only. func (w *window) waitWriterBlocked() { w.Cond.L.Lock() for w.writeWaiters == 0 { w.Cond.Wait() } w.Cond.L.Unlock() } lxd-2.0.0/dist/src/golang.org/x/crypto/ssh/cipher_test.go0000644061062106075000000000627112702772344025737 0ustar00stgraberdomain admins00000000000000// 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 ssh import ( "bytes" "crypto" "crypto/aes" "crypto/rand" "testing" ) func TestDefaultCiphersExist(t *testing.T) { for _, cipherAlgo := range supportedCiphers { if _, ok := cipherModes[cipherAlgo]; !ok { t.Errorf("default cipher %q is unknown", cipherAlgo) } } } func TestPacketCiphers(t *testing.T) { // Still test aes128cbc cipher althought it's commented out. cipherModes[aes128cbcID] = &streamCipherMode{16, aes.BlockSize, 0, nil} defer delete(cipherModes, aes128cbcID) for cipher := range cipherModes { kr := &kexResult{Hash: crypto.SHA1} algs := directionAlgorithms{ Cipher: cipher, MAC: "hmac-sha1", Compression: "none", } client, err := newPacketCipher(clientKeys, algs, kr) if err != nil { t.Errorf("newPacketCipher(client, %q): %v", cipher, err) continue } server, err := newPacketCipher(clientKeys, algs, kr) if err != nil { t.Errorf("newPacketCipher(client, %q): %v", cipher, err) continue } want := "bla bla" input := []byte(want) buf := &bytes.Buffer{} if err := client.writePacket(0, buf, rand.Reader, input); err != nil { t.Errorf("writePacket(%q): %v", cipher, err) continue } packet, err := server.readPacket(0, buf) if err != nil { t.Errorf("readPacket(%q): %v", cipher, err) continue } if string(packet) != want { t.Errorf("roundtrip(%q): got %q, want %q", cipher, packet, want) } } } func TestCBCOracleCounterMeasure(t *testing.T) { cipherModes[aes128cbcID] = &streamCipherMode{16, aes.BlockSize, 0, nil} defer delete(cipherModes, aes128cbcID) kr := &kexResult{Hash: crypto.SHA1} algs := directionAlgorithms{ Cipher: aes128cbcID, MAC: "hmac-sha1", Compression: "none", } client, err := newPacketCipher(clientKeys, algs, kr) if err != nil { t.Fatalf("newPacketCipher(client): %v", err) } want := "bla bla" input := []byte(want) buf := &bytes.Buffer{} if err := client.writePacket(0, buf, rand.Reader, input); err != nil { t.Errorf("writePacket: %v", err) } packetSize := buf.Len() buf.Write(make([]byte, 2*maxPacket)) // We corrupt each byte, but this usually will only test the // 'packet too large' or 'MAC failure' cases. lastRead := -1 for i := 0; i < packetSize; i++ { server, err := newPacketCipher(clientKeys, algs, kr) if err != nil { t.Fatalf("newPacketCipher(client): %v", err) } fresh := &bytes.Buffer{} fresh.Write(buf.Bytes()) fresh.Bytes()[i] ^= 0x01 before := fresh.Len() _, err = server.readPacket(0, fresh) if err == nil { t.Errorf("corrupt byte %d: readPacket succeeded ", i) continue } if _, ok := err.(cbcError); !ok { t.Errorf("corrupt byte %d: got %v (%T), want cbcError", i, err, err) continue } after := fresh.Len() bytesRead := before - after if bytesRead < maxPacket { t.Errorf("corrupt byte %d: read %d bytes, want more than %d", i, bytesRead, maxPacket) continue } if i > 0 && bytesRead != lastRead { t.Errorf("corrupt byte %d: read %d bytes, want %d bytes read", i, bytesRead, lastRead) } lastRead = bytesRead } } lxd-2.0.0/dist/src/golang.org/x/crypto/ssh/kex_test.go0000644061062106075000000000206212702772344025246 0ustar00stgraberdomain admins00000000000000// Copyright 2013 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 ssh // Key exchange tests. import ( "crypto/rand" "reflect" "testing" ) func TestKexes(t *testing.T) { type kexResultErr struct { result *kexResult err error } for name, kex := range kexAlgoMap { a, b := memPipe() s := make(chan kexResultErr, 1) c := make(chan kexResultErr, 1) var magics handshakeMagics go func() { r, e := kex.Client(a, rand.Reader, &magics) a.Close() c <- kexResultErr{r, e} }() go func() { r, e := kex.Server(b, rand.Reader, &magics, testSigners["ecdsa"]) b.Close() s <- kexResultErr{r, e} }() clientRes := <-c serverRes := <-s if clientRes.err != nil { t.Errorf("client: %v", clientRes.err) } if serverRes.err != nil { t.Errorf("server: %v", serverRes.err) } if !reflect.DeepEqual(clientRes.result, serverRes.result) { t.Errorf("kex %q: mismatch %#v, %#v", name, clientRes.result, serverRes.result) } } } lxd-2.0.0/dist/src/golang.org/x/crypto/ssh/certs.go0000644061062106075000000003251112702772344024542 0ustar00stgraberdomain admins00000000000000// Copyright 2012 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 ssh import ( "bytes" "errors" "fmt" "io" "net" "sort" "time" ) // These constants from [PROTOCOL.certkeys] represent the algorithm names // for certificate types supported by this package. const ( CertAlgoRSAv01 = "ssh-rsa-cert-v01@openssh.com" CertAlgoDSAv01 = "ssh-dss-cert-v01@openssh.com" CertAlgoECDSA256v01 = "ecdsa-sha2-nistp256-cert-v01@openssh.com" CertAlgoECDSA384v01 = "ecdsa-sha2-nistp384-cert-v01@openssh.com" CertAlgoECDSA521v01 = "ecdsa-sha2-nistp521-cert-v01@openssh.com" ) // Certificate types distinguish between host and user // certificates. The values can be set in the CertType field of // Certificate. const ( UserCert = 1 HostCert = 2 ) // Signature represents a cryptographic signature. type Signature struct { Format string Blob []byte } // CertTimeInfinity can be used for OpenSSHCertV01.ValidBefore to indicate that // a certificate does not expire. const CertTimeInfinity = 1<<64 - 1 // An Certificate represents an OpenSSH certificate as defined in // [PROTOCOL.certkeys]?rev=1.8. type Certificate struct { Nonce []byte Key PublicKey Serial uint64 CertType uint32 KeyId string ValidPrincipals []string ValidAfter uint64 ValidBefore uint64 Permissions Reserved []byte SignatureKey PublicKey Signature *Signature } // genericCertData holds the key-independent part of the certificate data. // Overall, certificates contain an nonce, public key fields and // key-independent fields. type genericCertData struct { Serial uint64 CertType uint32 KeyId string ValidPrincipals []byte ValidAfter uint64 ValidBefore uint64 CriticalOptions []byte Extensions []byte Reserved []byte SignatureKey []byte Signature []byte } func marshalStringList(namelist []string) []byte { var to []byte for _, name := range namelist { s := struct{ N string }{name} to = append(to, Marshal(&s)...) } return to } type optionsTuple struct { Key string Value []byte } type optionsTupleValue struct { Value string } // serialize a map of critical options or extensions // issue #10569 - per [PROTOCOL.certkeys] and SSH implementation, // we need two length prefixes for a non-empty string value func marshalTuples(tups map[string]string) []byte { keys := make([]string, 0, len(tups)) for key := range tups { keys = append(keys, key) } sort.Strings(keys) var ret []byte for _, key := range keys { s := optionsTuple{Key: key} if value := tups[key]; len(value) > 0 { s.Value = Marshal(&optionsTupleValue{value}) } ret = append(ret, Marshal(&s)...) } return ret } // issue #10569 - per [PROTOCOL.certkeys] and SSH implementation, // we need two length prefixes for a non-empty option value func parseTuples(in []byte) (map[string]string, error) { tups := map[string]string{} var lastKey string var haveLastKey bool for len(in) > 0 { var key, val, extra []byte var ok bool if key, in, ok = parseString(in); !ok { return nil, errShortRead } keyStr := string(key) // according to [PROTOCOL.certkeys], the names must be in // lexical order. if haveLastKey && keyStr <= lastKey { return nil, fmt.Errorf("ssh: certificate options are not in lexical order") } lastKey, haveLastKey = keyStr, true // the next field is a data field, which if non-empty has a string embedded if val, in, ok = parseString(in); !ok { return nil, errShortRead } if len(val) > 0 { val, extra, ok = parseString(val) if !ok { return nil, errShortRead } if len(extra) > 0 { return nil, fmt.Errorf("ssh: unexpected trailing data after certificate option value") } tups[keyStr] = string(val) } else { tups[keyStr] = "" } } return tups, nil } func parseCert(in []byte, privAlgo string) (*Certificate, error) { nonce, rest, ok := parseString(in) if !ok { return nil, errShortRead } key, rest, err := parsePubKey(rest, privAlgo) if err != nil { return nil, err } var g genericCertData if err := Unmarshal(rest, &g); err != nil { return nil, err } c := &Certificate{ Nonce: nonce, Key: key, Serial: g.Serial, CertType: g.CertType, KeyId: g.KeyId, ValidAfter: g.ValidAfter, ValidBefore: g.ValidBefore, } for principals := g.ValidPrincipals; len(principals) > 0; { principal, rest, ok := parseString(principals) if !ok { return nil, errShortRead } c.ValidPrincipals = append(c.ValidPrincipals, string(principal)) principals = rest } c.CriticalOptions, err = parseTuples(g.CriticalOptions) if err != nil { return nil, err } c.Extensions, err = parseTuples(g.Extensions) if err != nil { return nil, err } c.Reserved = g.Reserved k, err := ParsePublicKey(g.SignatureKey) if err != nil { return nil, err } c.SignatureKey = k c.Signature, rest, ok = parseSignatureBody(g.Signature) if !ok || len(rest) > 0 { return nil, errors.New("ssh: signature parse error") } return c, nil } type openSSHCertSigner struct { pub *Certificate signer Signer } // NewCertSigner returns a Signer that signs with the given Certificate, whose // private key is held by signer. It returns an error if the public key in cert // doesn't match the key used by signer. func NewCertSigner(cert *Certificate, signer Signer) (Signer, error) { if bytes.Compare(cert.Key.Marshal(), signer.PublicKey().Marshal()) != 0 { return nil, errors.New("ssh: signer and cert have different public key") } return &openSSHCertSigner{cert, signer}, nil } func (s *openSSHCertSigner) Sign(rand io.Reader, data []byte) (*Signature, error) { return s.signer.Sign(rand, data) } func (s *openSSHCertSigner) PublicKey() PublicKey { return s.pub } const sourceAddressCriticalOption = "source-address" // CertChecker does the work of verifying a certificate. Its methods // can be plugged into ClientConfig.HostKeyCallback and // ServerConfig.PublicKeyCallback. For the CertChecker to work, // minimally, the IsAuthority callback should be set. type CertChecker struct { // SupportedCriticalOptions lists the CriticalOptions that the // server application layer understands. These are only used // for user certificates. SupportedCriticalOptions []string // IsAuthority should return true if the key is recognized as // an authority. This allows for certificates to be signed by other // certificates. IsAuthority func(auth PublicKey) bool // Clock is used for verifying time stamps. If nil, time.Now // is used. Clock func() time.Time // UserKeyFallback is called when CertChecker.Authenticate encounters a // public key that is not a certificate. It must implement validation // of user keys or else, if nil, all such keys are rejected. UserKeyFallback func(conn ConnMetadata, key PublicKey) (*Permissions, error) // HostKeyFallback is called when CertChecker.CheckHostKey encounters a // public key that is not a certificate. It must implement host key // validation or else, if nil, all such keys are rejected. HostKeyFallback func(addr string, remote net.Addr, key PublicKey) error // IsRevoked is called for each certificate so that revocation checking // can be implemented. It should return true if the given certificate // is revoked and false otherwise. If nil, no certificates are // considered to have been revoked. IsRevoked func(cert *Certificate) bool } // CheckHostKey checks a host key certificate. This method can be // plugged into ClientConfig.HostKeyCallback. func (c *CertChecker) CheckHostKey(addr string, remote net.Addr, key PublicKey) error { cert, ok := key.(*Certificate) if !ok { if c.HostKeyFallback != nil { return c.HostKeyFallback(addr, remote, key) } return errors.New("ssh: non-certificate host key") } if cert.CertType != HostCert { return fmt.Errorf("ssh: certificate presented as a host key has type %d", cert.CertType) } return c.CheckCert(addr, cert) } // Authenticate checks a user certificate. Authenticate can be used as // a value for ServerConfig.PublicKeyCallback. func (c *CertChecker) Authenticate(conn ConnMetadata, pubKey PublicKey) (*Permissions, error) { cert, ok := pubKey.(*Certificate) if !ok { if c.UserKeyFallback != nil { return c.UserKeyFallback(conn, pubKey) } return nil, errors.New("ssh: normal key pairs not accepted") } if cert.CertType != UserCert { return nil, fmt.Errorf("ssh: cert has type %d", cert.CertType) } if err := c.CheckCert(conn.User(), cert); err != nil { return nil, err } return &cert.Permissions, nil } // CheckCert checks CriticalOptions, ValidPrincipals, revocation, timestamp and // the signature of the certificate. func (c *CertChecker) CheckCert(principal string, cert *Certificate) error { if c.IsRevoked != nil && c.IsRevoked(cert) { return fmt.Errorf("ssh: certicate serial %d revoked", cert.Serial) } for opt, _ := range cert.CriticalOptions { // sourceAddressCriticalOption will be enforced by // serverAuthenticate if opt == sourceAddressCriticalOption { continue } found := false for _, supp := range c.SupportedCriticalOptions { if supp == opt { found = true break } } if !found { return fmt.Errorf("ssh: unsupported critical option %q in certificate", opt) } } if len(cert.ValidPrincipals) > 0 { // By default, certs are valid for all users/hosts. found := false for _, p := range cert.ValidPrincipals { if p == principal { found = true break } } if !found { return fmt.Errorf("ssh: principal %q not in the set of valid principals for given certificate: %q", principal, cert.ValidPrincipals) } } if !c.IsAuthority(cert.SignatureKey) { return fmt.Errorf("ssh: certificate signed by unrecognized authority") } clock := c.Clock if clock == nil { clock = time.Now } unixNow := clock().Unix() if after := int64(cert.ValidAfter); after < 0 || unixNow < int64(cert.ValidAfter) { return fmt.Errorf("ssh: cert is not yet valid") } if before := int64(cert.ValidBefore); cert.ValidBefore != uint64(CertTimeInfinity) && (unixNow >= before || before < 0) { return fmt.Errorf("ssh: cert has expired") } if err := cert.SignatureKey.Verify(cert.bytesForSigning(), cert.Signature); err != nil { return fmt.Errorf("ssh: certificate signature does not verify") } return nil } // SignCert sets c.SignatureKey to the authority's public key and stores a // Signature, by authority, in the certificate. func (c *Certificate) SignCert(rand io.Reader, authority Signer) error { c.Nonce = make([]byte, 32) if _, err := io.ReadFull(rand, c.Nonce); err != nil { return err } c.SignatureKey = authority.PublicKey() sig, err := authority.Sign(rand, c.bytesForSigning()) if err != nil { return err } c.Signature = sig return nil } var certAlgoNames = map[string]string{ KeyAlgoRSA: CertAlgoRSAv01, KeyAlgoDSA: CertAlgoDSAv01, KeyAlgoECDSA256: CertAlgoECDSA256v01, KeyAlgoECDSA384: CertAlgoECDSA384v01, KeyAlgoECDSA521: CertAlgoECDSA521v01, } // certToPrivAlgo returns the underlying algorithm for a certificate algorithm. // Panics if a non-certificate algorithm is passed. func certToPrivAlgo(algo string) string { for privAlgo, pubAlgo := range certAlgoNames { if pubAlgo == algo { return privAlgo } } panic("unknown cert algorithm") } func (cert *Certificate) bytesForSigning() []byte { c2 := *cert c2.Signature = nil out := c2.Marshal() // Drop trailing signature length. return out[:len(out)-4] } // Marshal serializes c into OpenSSH's wire format. It is part of the // PublicKey interface. func (c *Certificate) Marshal() []byte { generic := genericCertData{ Serial: c.Serial, CertType: c.CertType, KeyId: c.KeyId, ValidPrincipals: marshalStringList(c.ValidPrincipals), ValidAfter: uint64(c.ValidAfter), ValidBefore: uint64(c.ValidBefore), CriticalOptions: marshalTuples(c.CriticalOptions), Extensions: marshalTuples(c.Extensions), Reserved: c.Reserved, SignatureKey: c.SignatureKey.Marshal(), } if c.Signature != nil { generic.Signature = Marshal(c.Signature) } genericBytes := Marshal(&generic) keyBytes := c.Key.Marshal() _, keyBytes, _ = parseString(keyBytes) prefix := Marshal(&struct { Name string Nonce []byte Key []byte `ssh:"rest"` }{c.Type(), c.Nonce, keyBytes}) result := make([]byte, 0, len(prefix)+len(genericBytes)) result = append(result, prefix...) result = append(result, genericBytes...) return result } // Type returns the key name. It is part of the PublicKey interface. func (c *Certificate) Type() string { algo, ok := certAlgoNames[c.Key.Type()] if !ok { panic("unknown cert key type") } return algo } // Verify verifies a signature against the certificate's public // key. It is part of the PublicKey interface. func (c *Certificate) Verify(data []byte, sig *Signature) error { return c.Key.Verify(data, sig) } func parseSignatureBody(in []byte) (out *Signature, rest []byte, ok bool) { format, in, ok := parseString(in) if !ok { return } out = &Signature{ Format: string(format), } if out.Blob, in, ok = parseString(in); !ok { return } return out, in, ok } func parseSignature(in []byte) (out *Signature, rest []byte, ok bool) { sigBytes, rest, ok := parseString(in) if !ok { return } out, trailing, ok := parseSignatureBody(sigBytes) if !ok || len(trailing) > 0 { return nil, nil, false } return } lxd-2.0.0/dist/src/golang.org/x/crypto/ssh/mac.go0000644061062106075000000000225512702772344024164 0ustar00stgraberdomain admins00000000000000// Copyright 2012 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 ssh // Message authentication support import ( "crypto/hmac" "crypto/sha1" "crypto/sha256" "hash" ) type macMode struct { keySize int new func(key []byte) hash.Hash } // truncatingMAC wraps around a hash.Hash and truncates the output digest to // a given size. type truncatingMAC struct { length int hmac hash.Hash } func (t truncatingMAC) Write(data []byte) (int, error) { return t.hmac.Write(data) } func (t truncatingMAC) Sum(in []byte) []byte { out := t.hmac.Sum(in) return out[:len(in)+t.length] } func (t truncatingMAC) Reset() { t.hmac.Reset() } func (t truncatingMAC) Size() int { return t.length } func (t truncatingMAC) BlockSize() int { return t.hmac.BlockSize() } var macModes = map[string]*macMode{ "hmac-sha2-256": {32, func(key []byte) hash.Hash { return hmac.New(sha256.New, key) }}, "hmac-sha1": {20, func(key []byte) hash.Hash { return hmac.New(sha1.New, key) }}, "hmac-sha1-96": {20, func(key []byte) hash.Hash { return truncatingMAC{12, hmac.New(sha1.New, key)} }}, } lxd-2.0.0/dist/src/golang.org/x/crypto/ssh/example_test.go0000644061062106075000000001263212702772344026116 0ustar00stgraberdomain admins00000000000000// 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 ssh_test import ( "bytes" "fmt" "io/ioutil" "log" "net" "net/http" "golang.org/x/crypto/ssh" "golang.org/x/crypto/ssh/terminal" ) func ExampleNewServerConn() { // An SSH server is represented by a ServerConfig, which holds // certificate details and handles authentication of ServerConns. config := &ssh.ServerConfig{ PasswordCallback: func(c ssh.ConnMetadata, pass []byte) (*ssh.Permissions, error) { // Should use constant-time compare (or better, salt+hash) in // a production setting. if c.User() == "testuser" && string(pass) == "tiger" { return nil, nil } return nil, fmt.Errorf("password rejected for %q", c.User()) }, } privateBytes, err := ioutil.ReadFile("id_rsa") if err != nil { panic("Failed to load private key") } private, err := ssh.ParsePrivateKey(privateBytes) if err != nil { panic("Failed to parse private key") } config.AddHostKey(private) // Once a ServerConfig has been configured, connections can be // accepted. listener, err := net.Listen("tcp", "0.0.0.0:2022") if err != nil { panic("failed to listen for connection") } nConn, err := listener.Accept() if err != nil { panic("failed to accept incoming connection") } // Before use, a handshake must be performed on the incoming // net.Conn. _, chans, reqs, err := ssh.NewServerConn(nConn, config) if err != nil { panic("failed to handshake") } // The incoming Request channel must be serviced. go ssh.DiscardRequests(reqs) // Service the incoming Channel channel. for newChannel := range chans { // Channels have a type, depending on the application level // protocol intended. In the case of a shell, the type is // "session" and ServerShell may be used to present a simple // terminal interface. if newChannel.ChannelType() != "session" { newChannel.Reject(ssh.UnknownChannelType, "unknown channel type") continue } channel, requests, err := newChannel.Accept() if err != nil { panic("could not accept channel.") } // Sessions have out-of-band requests such as "shell", // "pty-req" and "env". Here we handle only the // "shell" request. go func(in <-chan *ssh.Request) { for req := range in { ok := false switch req.Type { case "shell": ok = true if len(req.Payload) > 0 { // We don't accept any // commands, only the // default shell. ok = false } } req.Reply(ok, nil) } }(requests) term := terminal.NewTerminal(channel, "> ") go func() { defer channel.Close() for { line, err := term.ReadLine() if err != nil { break } fmt.Println(line) } }() } } func ExampleDial() { // An SSH client is represented with a ClientConn. Currently only // the "password" authentication method is supported. // // To authenticate with the remote server you must pass at least one // implementation of AuthMethod via the Auth field in ClientConfig. config := &ssh.ClientConfig{ User: "username", Auth: []ssh.AuthMethod{ ssh.Password("yourpassword"), }, } client, err := ssh.Dial("tcp", "yourserver.com:22", config) if err != nil { panic("Failed to dial: " + err.Error()) } // Each ClientConn can support multiple interactive sessions, // represented by a Session. session, err := client.NewSession() if err != nil { panic("Failed to create session: " + err.Error()) } defer session.Close() // Once a Session is created, you can execute a single command on // the remote side using the Run method. var b bytes.Buffer session.Stdout = &b if err := session.Run("/usr/bin/whoami"); err != nil { panic("Failed to run: " + err.Error()) } fmt.Println(b.String()) } func ExampleClient_Listen() { config := &ssh.ClientConfig{ User: "username", Auth: []ssh.AuthMethod{ ssh.Password("password"), }, } // Dial your ssh server. conn, err := ssh.Dial("tcp", "localhost:22", config) if err != nil { log.Fatalf("unable to connect: %s", err) } defer conn.Close() // Request the remote side to open port 8080 on all interfaces. l, err := conn.Listen("tcp", "0.0.0.0:8080") if err != nil { log.Fatalf("unable to register tcp forward: %v", err) } defer l.Close() // Serve HTTP with your SSH server acting as a reverse proxy. http.Serve(l, http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) { fmt.Fprintf(resp, "Hello world!\n") })) } func ExampleSession_RequestPty() { // Create client config config := &ssh.ClientConfig{ User: "username", Auth: []ssh.AuthMethod{ ssh.Password("password"), }, } // Connect to ssh server conn, err := ssh.Dial("tcp", "localhost:22", config) if err != nil { log.Fatalf("unable to connect: %s", err) } defer conn.Close() // Create a session session, err := conn.NewSession() if err != nil { log.Fatalf("unable to create session: %s", err) } defer session.Close() // Set up terminal modes modes := ssh.TerminalModes{ ssh.ECHO: 0, // disable echoing ssh.TTY_OP_ISPEED: 14400, // input speed = 14.4kbaud ssh.TTY_OP_OSPEED: 14400, // output speed = 14.4kbaud } // Request pseudo terminal if err := session.RequestPty("xterm", 80, 40, modes); err != nil { log.Fatalf("request for pseudo terminal failed: %s", err) } // Start remote shell if err := session.Shell(); err != nil { log.Fatalf("failed to start shell: %s", err) } } lxd-2.0.0/dist/src/golang.org/x/crypto/ssh/agent/0000755061062106075000000000000012702772344024167 5ustar00stgraberdomain admins00000000000000lxd-2.0.0/dist/src/golang.org/x/crypto/ssh/agent/client_test.go0000644061062106075000000001621412702772344027037 0ustar00stgraberdomain admins00000000000000// Copyright 2012 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 agent import ( "bytes" "crypto/rand" "errors" "net" "os" "os/exec" "path/filepath" "strconv" "testing" "golang.org/x/crypto/ssh" ) // startAgent executes ssh-agent, and returns a Agent interface to it. func startAgent(t *testing.T) (client Agent, socket string, cleanup func()) { if testing.Short() { // ssh-agent is not always available, and the key // types supported vary by platform. t.Skip("skipping test due to -short") } bin, err := exec.LookPath("ssh-agent") if err != nil { t.Skip("could not find ssh-agent") } cmd := exec.Command(bin, "-s") out, err := cmd.Output() if err != nil { t.Fatalf("cmd.Output: %v", err) } /* Output looks like: SSH_AUTH_SOCK=/tmp/ssh-P65gpcqArqvH/agent.15541; export SSH_AUTH_SOCK; SSH_AGENT_PID=15542; export SSH_AGENT_PID; echo Agent pid 15542; */ fields := bytes.Split(out, []byte(";")) line := bytes.SplitN(fields[0], []byte("="), 2) line[0] = bytes.TrimLeft(line[0], "\n") if string(line[0]) != "SSH_AUTH_SOCK" { t.Fatalf("could not find key SSH_AUTH_SOCK in %q", fields[0]) } socket = string(line[1]) line = bytes.SplitN(fields[2], []byte("="), 2) line[0] = bytes.TrimLeft(line[0], "\n") if string(line[0]) != "SSH_AGENT_PID" { t.Fatalf("could not find key SSH_AGENT_PID in %q", fields[2]) } pidStr := line[1] pid, err := strconv.Atoi(string(pidStr)) if err != nil { t.Fatalf("Atoi(%q): %v", pidStr, err) } conn, err := net.Dial("unix", string(socket)) if err != nil { t.Fatalf("net.Dial: %v", err) } ac := NewClient(conn) return ac, socket, func() { proc, _ := os.FindProcess(pid) if proc != nil { proc.Kill() } conn.Close() os.RemoveAll(filepath.Dir(socket)) } } func testAgent(t *testing.T, key interface{}, cert *ssh.Certificate, lifetimeSecs uint32) { agent, _, cleanup := startAgent(t) defer cleanup() testAgentInterface(t, agent, key, cert, lifetimeSecs) } func testAgentInterface(t *testing.T, agent Agent, key interface{}, cert *ssh.Certificate, lifetimeSecs uint32) { signer, err := ssh.NewSignerFromKey(key) if err != nil { t.Fatalf("NewSignerFromKey(%T): %v", key, err) } // The agent should start up empty. if keys, err := agent.List(); err != nil { t.Fatalf("RequestIdentities: %v", err) } else if len(keys) > 0 { t.Fatalf("got %d keys, want 0: %v", len(keys), keys) } // Attempt to insert the key, with certificate if specified. var pubKey ssh.PublicKey if cert != nil { err = agent.Add(AddedKey{ PrivateKey: key, Certificate: cert, Comment: "comment", LifetimeSecs: lifetimeSecs, }) pubKey = cert } else { err = agent.Add(AddedKey{PrivateKey: key, Comment: "comment", LifetimeSecs: lifetimeSecs}) pubKey = signer.PublicKey() } if err != nil { t.Fatalf("insert(%T): %v", key, err) } // Did the key get inserted successfully? if keys, err := agent.List(); err != nil { t.Fatalf("List: %v", err) } else if len(keys) != 1 { t.Fatalf("got %v, want 1 key", keys) } else if keys[0].Comment != "comment" { t.Fatalf("key comment: got %v, want %v", keys[0].Comment, "comment") } else if !bytes.Equal(keys[0].Blob, pubKey.Marshal()) { t.Fatalf("key mismatch") } // Can the agent make a valid signature? data := []byte("hello") sig, err := agent.Sign(pubKey, data) if err != nil { t.Fatalf("Sign(%s): %v", pubKey.Type(), err) } if err := pubKey.Verify(data, sig); err != nil { t.Fatalf("Verify(%s): %v", pubKey.Type(), err) } } func TestAgent(t *testing.T) { for _, keyType := range []string{"rsa", "dsa", "ecdsa"} { testAgent(t, testPrivateKeys[keyType], nil, 0) } } func TestCert(t *testing.T) { cert := &ssh.Certificate{ Key: testPublicKeys["rsa"], ValidBefore: ssh.CertTimeInfinity, CertType: ssh.UserCert, } cert.SignCert(rand.Reader, testSigners["ecdsa"]) testAgent(t, testPrivateKeys["rsa"], cert, 0) } func TestConstraints(t *testing.T) { testAgent(t, testPrivateKeys["rsa"], nil, 3600 /* lifetime in seconds */) } // netPipe is analogous to net.Pipe, but it uses a real net.Conn, and // therefore is buffered (net.Pipe deadlocks if both sides start with // a write.) func netPipe() (net.Conn, net.Conn, error) { listener, err := net.Listen("tcp", "127.0.0.1:0") if err != nil { return nil, nil, err } defer listener.Close() c1, err := net.Dial("tcp", listener.Addr().String()) if err != nil { return nil, nil, err } c2, err := listener.Accept() if err != nil { c1.Close() return nil, nil, err } return c1, c2, nil } func TestAuth(t *testing.T) { a, b, err := netPipe() if err != nil { t.Fatalf("netPipe: %v", err) } defer a.Close() defer b.Close() agent, _, cleanup := startAgent(t) defer cleanup() if err := agent.Add(AddedKey{PrivateKey: testPrivateKeys["rsa"], Comment: "comment"}); err != nil { t.Errorf("Add: %v", err) } serverConf := ssh.ServerConfig{} serverConf.AddHostKey(testSigners["rsa"]) serverConf.PublicKeyCallback = func(c ssh.ConnMetadata, key ssh.PublicKey) (*ssh.Permissions, error) { if bytes.Equal(key.Marshal(), testPublicKeys["rsa"].Marshal()) { return nil, nil } return nil, errors.New("pubkey rejected") } go func() { conn, _, _, err := ssh.NewServerConn(a, &serverConf) if err != nil { t.Fatalf("Server: %v", err) } conn.Close() }() conf := ssh.ClientConfig{} conf.Auth = append(conf.Auth, ssh.PublicKeysCallback(agent.Signers)) conn, _, _, err := ssh.NewClientConn(b, "", &conf) if err != nil { t.Fatalf("NewClientConn: %v", err) } conn.Close() } func TestLockClient(t *testing.T) { agent, _, cleanup := startAgent(t) defer cleanup() testLockAgent(agent, t) } func testLockAgent(agent Agent, t *testing.T) { if err := agent.Add(AddedKey{PrivateKey: testPrivateKeys["rsa"], Comment: "comment 1"}); err != nil { t.Errorf("Add: %v", err) } if err := agent.Add(AddedKey{PrivateKey: testPrivateKeys["dsa"], Comment: "comment dsa"}); err != nil { t.Errorf("Add: %v", err) } if keys, err := agent.List(); err != nil { t.Errorf("List: %v", err) } else if len(keys) != 2 { t.Errorf("Want 2 keys, got %v", keys) } passphrase := []byte("secret") if err := agent.Lock(passphrase); err != nil { t.Errorf("Lock: %v", err) } if keys, err := agent.List(); err != nil { t.Errorf("List: %v", err) } else if len(keys) != 0 { t.Errorf("Want 0 keys, got %v", keys) } signer, _ := ssh.NewSignerFromKey(testPrivateKeys["rsa"]) if _, err := agent.Sign(signer.PublicKey(), []byte("hello")); err == nil { t.Fatalf("Sign did not fail") } if err := agent.Remove(signer.PublicKey()); err == nil { t.Fatalf("Remove did not fail") } if err := agent.RemoveAll(); err == nil { t.Fatalf("RemoveAll did not fail") } if err := agent.Unlock(nil); err == nil { t.Errorf("Unlock with wrong passphrase succeeded") } if err := agent.Unlock(passphrase); err != nil { t.Errorf("Unlock: %v", err) } if err := agent.Remove(signer.PublicKey()); err != nil { t.Fatalf("Remove: %v", err) } if keys, err := agent.List(); err != nil { t.Errorf("List: %v", err) } else if len(keys) != 1 { t.Errorf("Want 1 keys, got %v", keys) } } lxd-2.0.0/dist/src/golang.org/x/crypto/ssh/agent/example_test.go0000644061062106075000000000167712702772344027223 0ustar00stgraberdomain admins00000000000000// Copyright 2016 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 agent_test import ( "log" "os" "net" "golang.org/x/crypto/ssh" "golang.org/x/crypto/ssh/agent" ) func ExampleClientAgent() { // ssh-agent has a UNIX socket under $SSH_AUTH_SOCK socket := os.Getenv("SSH_AUTH_SOCK") conn, err := net.Dial("unix", socket) if err != nil { log.Fatalf("net.Dial: %v", err) } agentClient := agent.NewClient(conn) config := &ssh.ClientConfig{ User: "username", Auth: []ssh.AuthMethod{ // Use a callback rather than PublicKeys // so we only consult the agent once the remote server // wants it. ssh.PublicKeysCallback(agentClient.Signers), }, } sshc, err := ssh.Dial("tcp", "localhost:22", config) if err != nil { log.Fatalf("Dial: %v", err) } // .. use sshc sshc.Close() } lxd-2.0.0/dist/src/golang.org/x/crypto/ssh/agent/testdata_test.go0000644061062106075000000000425712702772344027376 0ustar00stgraberdomain admins00000000000000// Copyright 2014 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. // IMPLEMENTOR NOTE: To avoid a package loop, this file is in three places: // ssh/, ssh/agent, and ssh/test/. It should be kept in sync across all three // instances. package agent import ( "crypto/rand" "fmt" "golang.org/x/crypto/ssh" "golang.org/x/crypto/ssh/testdata" ) var ( testPrivateKeys map[string]interface{} testSigners map[string]ssh.Signer testPublicKeys map[string]ssh.PublicKey ) func init() { var err error n := len(testdata.PEMBytes) testPrivateKeys = make(map[string]interface{}, n) testSigners = make(map[string]ssh.Signer, n) testPublicKeys = make(map[string]ssh.PublicKey, n) for t, k := range testdata.PEMBytes { testPrivateKeys[t], err = ssh.ParseRawPrivateKey(k) if err != nil { panic(fmt.Sprintf("Unable to parse test key %s: %v", t, err)) } testSigners[t], err = ssh.NewSignerFromKey(testPrivateKeys[t]) if err != nil { panic(fmt.Sprintf("Unable to create signer for test key %s: %v", t, err)) } testPublicKeys[t] = testSigners[t].PublicKey() } // Create a cert and sign it for use in tests. testCert := &ssh.Certificate{ Nonce: []byte{}, // To pass reflect.DeepEqual after marshal & parse, this must be non-nil ValidPrincipals: []string{"gopher1", "gopher2"}, // increases test coverage ValidAfter: 0, // unix epoch ValidBefore: ssh.CertTimeInfinity, // The end of currently representable time. Reserved: []byte{}, // To pass reflect.DeepEqual after marshal & parse, this must be non-nil Key: testPublicKeys["ecdsa"], SignatureKey: testPublicKeys["rsa"], Permissions: ssh.Permissions{ CriticalOptions: map[string]string{}, Extensions: map[string]string{}, }, } testCert.SignCert(rand.Reader, testSigners["rsa"]) testPrivateKeys["cert"] = testPrivateKeys["ecdsa"] testSigners["cert"], err = ssh.NewCertSigner(testCert, testSigners["ecdsa"]) if err != nil { panic(fmt.Sprintf("Unable to create certificate signer: %v", err)) } } lxd-2.0.0/dist/src/golang.org/x/crypto/ssh/agent/keyring.go0000644061062106075000000000714012702772344026170 0ustar00stgraberdomain admins00000000000000// Copyright 2014 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 agent import ( "bytes" "crypto/rand" "crypto/subtle" "errors" "fmt" "sync" "golang.org/x/crypto/ssh" ) type privKey struct { signer ssh.Signer comment string } type keyring struct { mu sync.Mutex keys []privKey locked bool passphrase []byte } var errLocked = errors.New("agent: locked") // NewKeyring returns an Agent that holds keys in memory. It is safe // for concurrent use by multiple goroutines. func NewKeyring() Agent { return &keyring{} } // RemoveAll removes all identities. func (r *keyring) RemoveAll() error { r.mu.Lock() defer r.mu.Unlock() if r.locked { return errLocked } r.keys = nil return nil } // Remove removes all identities with the given public key. func (r *keyring) Remove(key ssh.PublicKey) error { r.mu.Lock() defer r.mu.Unlock() if r.locked { return errLocked } want := key.Marshal() found := false for i := 0; i < len(r.keys); { if bytes.Equal(r.keys[i].signer.PublicKey().Marshal(), want) { found = true r.keys[i] = r.keys[len(r.keys)-1] r.keys = r.keys[:len(r.keys)-1] continue } else { i++ } } if !found { return errors.New("agent: key not found") } return nil } // Lock locks the agent. Sign and Remove will fail, and List will empty an empty list. func (r *keyring) Lock(passphrase []byte) error { r.mu.Lock() defer r.mu.Unlock() if r.locked { return errLocked } r.locked = true r.passphrase = passphrase return nil } // Unlock undoes the effect of Lock func (r *keyring) Unlock(passphrase []byte) error { r.mu.Lock() defer r.mu.Unlock() if !r.locked { return errors.New("agent: not locked") } if len(passphrase) != len(r.passphrase) || 1 != subtle.ConstantTimeCompare(passphrase, r.passphrase) { return fmt.Errorf("agent: incorrect passphrase") } r.locked = false r.passphrase = nil return nil } // List returns the identities known to the agent. func (r *keyring) List() ([]*Key, error) { r.mu.Lock() defer r.mu.Unlock() if r.locked { // section 2.7: locked agents return empty. return nil, nil } var ids []*Key for _, k := range r.keys { pub := k.signer.PublicKey() ids = append(ids, &Key{ Format: pub.Type(), Blob: pub.Marshal(), Comment: k.comment}) } return ids, nil } // Insert adds a private key to the keyring. If a certificate // is given, that certificate is added as public key. Note that // any constraints given are ignored. func (r *keyring) Add(key AddedKey) error { r.mu.Lock() defer r.mu.Unlock() if r.locked { return errLocked } signer, err := ssh.NewSignerFromKey(key.PrivateKey) if err != nil { return err } if cert := key.Certificate; cert != nil { signer, err = ssh.NewCertSigner(cert, signer) if err != nil { return err } } r.keys = append(r.keys, privKey{signer, key.Comment}) return nil } // Sign returns a signature for the data. func (r *keyring) Sign(key ssh.PublicKey, data []byte) (*ssh.Signature, error) { r.mu.Lock() defer r.mu.Unlock() if r.locked { return nil, errLocked } wanted := key.Marshal() for _, k := range r.keys { if bytes.Equal(k.signer.PublicKey().Marshal(), wanted) { return k.signer.Sign(rand.Reader, data) } } return nil, errors.New("not found") } // Signers returns signers for all the known keys. func (r *keyring) Signers() ([]ssh.Signer, error) { r.mu.Lock() defer r.mu.Unlock() if r.locked { return nil, errLocked } s := make([]ssh.Signer, 0, len(r.keys)) for _, k := range r.keys { s = append(s, k.signer) } return s, nil } lxd-2.0.0/dist/src/golang.org/x/crypto/ssh/agent/server.go0000644061062106075000000001057512702772344026034 0ustar00stgraberdomain admins00000000000000// Copyright 2012 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 agent import ( "crypto/rsa" "encoding/binary" "fmt" "io" "log" "math/big" "golang.org/x/crypto/ssh" ) // Server wraps an Agent and uses it to implement the agent side of // the SSH-agent, wire protocol. type server struct { agent Agent } func (s *server) processRequestBytes(reqData []byte) []byte { rep, err := s.processRequest(reqData) if err != nil { if err != errLocked { // TODO(hanwen): provide better logging interface? log.Printf("agent %d: %v", reqData[0], err) } return []byte{agentFailure} } if err == nil && rep == nil { return []byte{agentSuccess} } return ssh.Marshal(rep) } func marshalKey(k *Key) []byte { var record struct { Blob []byte Comment string } record.Blob = k.Marshal() record.Comment = k.Comment return ssh.Marshal(&record) } type agentV1IdentityMsg struct { Numkeys uint32 `sshtype:"2"` } type agentRemoveIdentityMsg struct { KeyBlob []byte `sshtype:"18"` } type agentLockMsg struct { Passphrase []byte `sshtype:"22"` } type agentUnlockMsg struct { Passphrase []byte `sshtype:"23"` } func (s *server) processRequest(data []byte) (interface{}, error) { switch data[0] { case agentRequestV1Identities: return &agentV1IdentityMsg{0}, nil case agentRemoveIdentity: var req agentRemoveIdentityMsg if err := ssh.Unmarshal(data, &req); err != nil { return nil, err } var wk wireKey if err := ssh.Unmarshal(req.KeyBlob, &wk); err != nil { return nil, err } return nil, s.agent.Remove(&Key{Format: wk.Format, Blob: req.KeyBlob}) case agentRemoveAllIdentities: return nil, s.agent.RemoveAll() case agentLock: var req agentLockMsg if err := ssh.Unmarshal(data, &req); err != nil { return nil, err } return nil, s.agent.Lock(req.Passphrase) case agentUnlock: var req agentLockMsg if err := ssh.Unmarshal(data, &req); err != nil { return nil, err } return nil, s.agent.Unlock(req.Passphrase) case agentSignRequest: var req signRequestAgentMsg if err := ssh.Unmarshal(data, &req); err != nil { return nil, err } var wk wireKey if err := ssh.Unmarshal(req.KeyBlob, &wk); err != nil { return nil, err } k := &Key{ Format: wk.Format, Blob: req.KeyBlob, } sig, err := s.agent.Sign(k, req.Data) // TODO(hanwen): flags. if err != nil { return nil, err } return &signResponseAgentMsg{SigBlob: ssh.Marshal(sig)}, nil case agentRequestIdentities: keys, err := s.agent.List() if err != nil { return nil, err } rep := identitiesAnswerAgentMsg{ NumKeys: uint32(len(keys)), } for _, k := range keys { rep.Keys = append(rep.Keys, marshalKey(k)...) } return rep, nil case agentAddIdentity: return nil, s.insertIdentity(data) } return nil, fmt.Errorf("unknown opcode %d", data[0]) } func (s *server) insertIdentity(req []byte) error { var record struct { Type string `sshtype:"17"` Rest []byte `ssh:"rest"` } if err := ssh.Unmarshal(req, &record); err != nil { return err } switch record.Type { case ssh.KeyAlgoRSA: var k rsaKeyMsg if err := ssh.Unmarshal(req, &k); err != nil { return err } priv := rsa.PrivateKey{ PublicKey: rsa.PublicKey{ E: int(k.E.Int64()), N: k.N, }, D: k.D, Primes: []*big.Int{k.P, k.Q}, } priv.Precompute() return s.agent.Add(AddedKey{PrivateKey: &priv, Comment: k.Comments}) } return fmt.Errorf("not implemented: %s", record.Type) } // ServeAgent serves the agent protocol on the given connection. It // returns when an I/O error occurs. func ServeAgent(agent Agent, c io.ReadWriter) error { s := &server{agent} var length [4]byte for { if _, err := io.ReadFull(c, length[:]); err != nil { return err } l := binary.BigEndian.Uint32(length[:]) if l > maxAgentResponseBytes { // We also cap requests. return fmt.Errorf("agent: request too large: %d", l) } req := make([]byte, l) if _, err := io.ReadFull(c, req); err != nil { return err } repData := s.processRequestBytes(req) if len(repData) > maxAgentResponseBytes { return fmt.Errorf("agent: reply too large: %d bytes", len(repData)) } binary.BigEndian.PutUint32(length[:], uint32(len(repData))) if _, err := c.Write(length[:]); err != nil { return err } if _, err := c.Write(repData); err != nil { return err } } } lxd-2.0.0/dist/src/golang.org/x/crypto/ssh/agent/client.go0000644061062106075000000003574412702772344026011 0ustar00stgraberdomain admins00000000000000// Copyright 2012 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 agent implements the ssh-agent protocol, and provides both // a client and a server. The client can talk to a standard ssh-agent // that uses UNIX sockets, and one could implement an alternative // ssh-agent process using the sample server. // // References: // [PROTOCOL.agent]: http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/PROTOCOL.agent?rev=HEAD package agent // import "golang.org/x/crypto/ssh/agent" import ( "bytes" "crypto/dsa" "crypto/ecdsa" "crypto/elliptic" "crypto/rsa" "encoding/base64" "encoding/binary" "errors" "fmt" "io" "math/big" "sync" "golang.org/x/crypto/ssh" ) // Agent represents the capabilities of an ssh-agent. type Agent interface { // List returns the identities known to the agent. List() ([]*Key, error) // Sign has the agent sign the data using a protocol 2 key as defined // in [PROTOCOL.agent] section 2.6.2. Sign(key ssh.PublicKey, data []byte) (*ssh.Signature, error) // Add adds a private key to the agent. Add(key AddedKey) error // Remove removes all identities with the given public key. Remove(key ssh.PublicKey) error // RemoveAll removes all identities. RemoveAll() error // Lock locks the agent. Sign and Remove will fail, and List will empty an empty list. Lock(passphrase []byte) error // Unlock undoes the effect of Lock Unlock(passphrase []byte) error // Signers returns signers for all the known keys. Signers() ([]ssh.Signer, error) } // AddedKey describes an SSH key to be added to an Agent. type AddedKey struct { // PrivateKey must be a *rsa.PrivateKey, *dsa.PrivateKey or // *ecdsa.PrivateKey, which will be inserted into the agent. PrivateKey interface{} // Certificate, if not nil, is communicated to the agent and will be // stored with the key. Certificate *ssh.Certificate // Comment is an optional, free-form string. Comment string // LifetimeSecs, if not zero, is the number of seconds that the // agent will store the key for. LifetimeSecs uint32 // ConfirmBeforeUse, if true, requests that the agent confirm with the // user before each use of this key. ConfirmBeforeUse bool } // See [PROTOCOL.agent], section 3. const ( agentRequestV1Identities = 1 // 3.2 Requests from client to agent for protocol 2 key operations agentAddIdentity = 17 agentRemoveIdentity = 18 agentRemoveAllIdentities = 19 agentAddIdConstrained = 25 // 3.3 Key-type independent requests from client to agent agentAddSmartcardKey = 20 agentRemoveSmartcardKey = 21 agentLock = 22 agentUnlock = 23 agentAddSmartcardKeyConstrained = 26 // 3.7 Key constraint identifiers agentConstrainLifetime = 1 agentConstrainConfirm = 2 ) // maxAgentResponseBytes is the maximum agent reply size that is accepted. This // is a sanity check, not a limit in the spec. const maxAgentResponseBytes = 16 << 20 // Agent messages: // These structures mirror the wire format of the corresponding ssh agent // messages found in [PROTOCOL.agent]. // 3.4 Generic replies from agent to client const agentFailure = 5 type failureAgentMsg struct{} const agentSuccess = 6 type successAgentMsg struct{} // See [PROTOCOL.agent], section 2.5.2. const agentRequestIdentities = 11 type requestIdentitiesAgentMsg struct{} // See [PROTOCOL.agent], section 2.5.2. const agentIdentitiesAnswer = 12 type identitiesAnswerAgentMsg struct { NumKeys uint32 `sshtype:"12"` Keys []byte `ssh:"rest"` } // See [PROTOCOL.agent], section 2.6.2. const agentSignRequest = 13 type signRequestAgentMsg struct { KeyBlob []byte `sshtype:"13"` Data []byte Flags uint32 } // See [PROTOCOL.agent], section 2.6.2. // 3.6 Replies from agent to client for protocol 2 key operations const agentSignResponse = 14 type signResponseAgentMsg struct { SigBlob []byte `sshtype:"14"` } type publicKey struct { Format string Rest []byte `ssh:"rest"` } // Key represents a protocol 2 public key as defined in // [PROTOCOL.agent], section 2.5.2. type Key struct { Format string Blob []byte Comment string } func clientErr(err error) error { return fmt.Errorf("agent: client error: %v", err) } // String returns the storage form of an agent key with the format, base64 // encoded serialized key, and the comment if it is not empty. func (k *Key) String() string { s := string(k.Format) + " " + base64.StdEncoding.EncodeToString(k.Blob) if k.Comment != "" { s += " " + k.Comment } return s } // Type returns the public key type. func (k *Key) Type() string { return k.Format } // Marshal returns key blob to satisfy the ssh.PublicKey interface. func (k *Key) Marshal() []byte { return k.Blob } // Verify satisfies the ssh.PublicKey interface, but is not // implemented for agent keys. func (k *Key) Verify(data []byte, sig *ssh.Signature) error { return errors.New("agent: agent key does not know how to verify") } type wireKey struct { Format string Rest []byte `ssh:"rest"` } func parseKey(in []byte) (out *Key, rest []byte, err error) { var record struct { Blob []byte Comment string Rest []byte `ssh:"rest"` } if err := ssh.Unmarshal(in, &record); err != nil { return nil, nil, err } var wk wireKey if err := ssh.Unmarshal(record.Blob, &wk); err != nil { return nil, nil, err } return &Key{ Format: wk.Format, Blob: record.Blob, Comment: record.Comment, }, record.Rest, nil } // client is a client for an ssh-agent process. type client struct { // conn is typically a *net.UnixConn conn io.ReadWriter // mu is used to prevent concurrent access to the agent mu sync.Mutex } // NewClient returns an Agent that talks to an ssh-agent process over // the given connection. func NewClient(rw io.ReadWriter) Agent { return &client{conn: rw} } // call sends an RPC to the agent. On success, the reply is // unmarshaled into reply and replyType is set to the first byte of // the reply, which contains the type of the message. func (c *client) call(req []byte) (reply interface{}, err error) { c.mu.Lock() defer c.mu.Unlock() msg := make([]byte, 4+len(req)) binary.BigEndian.PutUint32(msg, uint32(len(req))) copy(msg[4:], req) if _, err = c.conn.Write(msg); err != nil { return nil, clientErr(err) } var respSizeBuf [4]byte if _, err = io.ReadFull(c.conn, respSizeBuf[:]); err != nil { return nil, clientErr(err) } respSize := binary.BigEndian.Uint32(respSizeBuf[:]) if respSize > maxAgentResponseBytes { return nil, clientErr(err) } buf := make([]byte, respSize) if _, err = io.ReadFull(c.conn, buf); err != nil { return nil, clientErr(err) } reply, err = unmarshal(buf) if err != nil { return nil, clientErr(err) } return reply, err } func (c *client) simpleCall(req []byte) error { resp, err := c.call(req) if err != nil { return err } if _, ok := resp.(*successAgentMsg); ok { return nil } return errors.New("agent: failure") } func (c *client) RemoveAll() error { return c.simpleCall([]byte{agentRemoveAllIdentities}) } func (c *client) Remove(key ssh.PublicKey) error { req := ssh.Marshal(&agentRemoveIdentityMsg{ KeyBlob: key.Marshal(), }) return c.simpleCall(req) } func (c *client) Lock(passphrase []byte) error { req := ssh.Marshal(&agentLockMsg{ Passphrase: passphrase, }) return c.simpleCall(req) } func (c *client) Unlock(passphrase []byte) error { req := ssh.Marshal(&agentUnlockMsg{ Passphrase: passphrase, }) return c.simpleCall(req) } // List returns the identities known to the agent. func (c *client) List() ([]*Key, error) { // see [PROTOCOL.agent] section 2.5.2. req := []byte{agentRequestIdentities} msg, err := c.call(req) if err != nil { return nil, err } switch msg := msg.(type) { case *identitiesAnswerAgentMsg: if msg.NumKeys > maxAgentResponseBytes/8 { return nil, errors.New("agent: too many keys in agent reply") } keys := make([]*Key, msg.NumKeys) data := msg.Keys for i := uint32(0); i < msg.NumKeys; i++ { var key *Key var err error if key, data, err = parseKey(data); err != nil { return nil, err } keys[i] = key } return keys, nil case *failureAgentMsg: return nil, errors.New("agent: failed to list keys") } panic("unreachable") } // Sign has the agent sign the data using a protocol 2 key as defined // in [PROTOCOL.agent] section 2.6.2. func (c *client) Sign(key ssh.PublicKey, data []byte) (*ssh.Signature, error) { req := ssh.Marshal(signRequestAgentMsg{ KeyBlob: key.Marshal(), Data: data, }) msg, err := c.call(req) if err != nil { return nil, err } switch msg := msg.(type) { case *signResponseAgentMsg: var sig ssh.Signature if err := ssh.Unmarshal(msg.SigBlob, &sig); err != nil { return nil, err } return &sig, nil case *failureAgentMsg: return nil, errors.New("agent: failed to sign challenge") } panic("unreachable") } // unmarshal parses an agent message in packet, returning the parsed // form and the message type of packet. func unmarshal(packet []byte) (interface{}, error) { if len(packet) < 1 { return nil, errors.New("agent: empty packet") } var msg interface{} switch packet[0] { case agentFailure: return new(failureAgentMsg), nil case agentSuccess: return new(successAgentMsg), nil case agentIdentitiesAnswer: msg = new(identitiesAnswerAgentMsg) case agentSignResponse: msg = new(signResponseAgentMsg) default: return nil, fmt.Errorf("agent: unknown type tag %d", packet[0]) } if err := ssh.Unmarshal(packet, msg); err != nil { return nil, err } return msg, nil } type rsaKeyMsg struct { Type string `sshtype:"17"` N *big.Int E *big.Int D *big.Int Iqmp *big.Int // IQMP = Inverse Q Mod P P *big.Int Q *big.Int Comments string Constraints []byte `ssh:"rest"` } type dsaKeyMsg struct { Type string `sshtype:"17"` P *big.Int Q *big.Int G *big.Int Y *big.Int X *big.Int Comments string Constraints []byte `ssh:"rest"` } type ecdsaKeyMsg struct { Type string `sshtype:"17"` Curve string KeyBytes []byte D *big.Int Comments string Constraints []byte `ssh:"rest"` } // Insert adds a private key to the agent. func (c *client) insertKey(s interface{}, comment string, constraints []byte) error { var req []byte switch k := s.(type) { case *rsa.PrivateKey: if len(k.Primes) != 2 { return fmt.Errorf("agent: unsupported RSA key with %d primes", len(k.Primes)) } k.Precompute() req = ssh.Marshal(rsaKeyMsg{ Type: ssh.KeyAlgoRSA, N: k.N, E: big.NewInt(int64(k.E)), D: k.D, Iqmp: k.Precomputed.Qinv, P: k.Primes[0], Q: k.Primes[1], Comments: comment, Constraints: constraints, }) case *dsa.PrivateKey: req = ssh.Marshal(dsaKeyMsg{ Type: ssh.KeyAlgoDSA, P: k.P, Q: k.Q, G: k.G, Y: k.Y, X: k.X, Comments: comment, Constraints: constraints, }) case *ecdsa.PrivateKey: nistID := fmt.Sprintf("nistp%d", k.Params().BitSize) req = ssh.Marshal(ecdsaKeyMsg{ Type: "ecdsa-sha2-" + nistID, Curve: nistID, KeyBytes: elliptic.Marshal(k.Curve, k.X, k.Y), D: k.D, Comments: comment, Constraints: constraints, }) default: return fmt.Errorf("agent: unsupported key type %T", s) } // if constraints are present then the message type needs to be changed. if len(constraints) != 0 { req[0] = agentAddIdConstrained } resp, err := c.call(req) if err != nil { return err } if _, ok := resp.(*successAgentMsg); ok { return nil } return errors.New("agent: failure") } type rsaCertMsg struct { Type string `sshtype:"17"` CertBytes []byte D *big.Int Iqmp *big.Int // IQMP = Inverse Q Mod P P *big.Int Q *big.Int Comments string Constraints []byte `ssh:"rest"` } type dsaCertMsg struct { Type string `sshtype:"17"` CertBytes []byte X *big.Int Comments string Constraints []byte `ssh:"rest"` } type ecdsaCertMsg struct { Type string `sshtype:"17"` CertBytes []byte D *big.Int Comments string Constraints []byte `ssh:"rest"` } // Insert adds a private key to the agent. If a certificate is given, // that certificate is added instead as public key. func (c *client) Add(key AddedKey) error { var constraints []byte if secs := key.LifetimeSecs; secs != 0 { constraints = append(constraints, agentConstrainLifetime) var secsBytes [4]byte binary.BigEndian.PutUint32(secsBytes[:], secs) constraints = append(constraints, secsBytes[:]...) } if key.ConfirmBeforeUse { constraints = append(constraints, agentConstrainConfirm) } if cert := key.Certificate; cert == nil { return c.insertKey(key.PrivateKey, key.Comment, constraints) } else { return c.insertCert(key.PrivateKey, cert, key.Comment, constraints) } } func (c *client) insertCert(s interface{}, cert *ssh.Certificate, comment string, constraints []byte) error { var req []byte switch k := s.(type) { case *rsa.PrivateKey: if len(k.Primes) != 2 { return fmt.Errorf("agent: unsupported RSA key with %d primes", len(k.Primes)) } k.Precompute() req = ssh.Marshal(rsaCertMsg{ Type: cert.Type(), CertBytes: cert.Marshal(), D: k.D, Iqmp: k.Precomputed.Qinv, P: k.Primes[0], Q: k.Primes[1], Comments: comment, Constraints: constraints, }) case *dsa.PrivateKey: req = ssh.Marshal(dsaCertMsg{ Type: cert.Type(), CertBytes: cert.Marshal(), X: k.X, Comments: comment, }) case *ecdsa.PrivateKey: req = ssh.Marshal(ecdsaCertMsg{ Type: cert.Type(), CertBytes: cert.Marshal(), D: k.D, Comments: comment, }) default: return fmt.Errorf("agent: unsupported key type %T", s) } // if constraints are present then the message type needs to be changed. if len(constraints) != 0 { req[0] = agentAddIdConstrained } signer, err := ssh.NewSignerFromKey(s) if err != nil { return err } if bytes.Compare(cert.Key.Marshal(), signer.PublicKey().Marshal()) != 0 { return errors.New("agent: signer and cert have different public key") } resp, err := c.call(req) if err != nil { return err } if _, ok := resp.(*successAgentMsg); ok { return nil } return errors.New("agent: failure") } // Signers provides a callback for client authentication. func (c *client) Signers() ([]ssh.Signer, error) { keys, err := c.List() if err != nil { return nil, err } var result []ssh.Signer for _, k := range keys { result = append(result, &agentKeyringSigner{c, k}) } return result, nil } type agentKeyringSigner struct { agent *client pub ssh.PublicKey } func (s *agentKeyringSigner) PublicKey() ssh.PublicKey { return s.pub } func (s *agentKeyringSigner) Sign(rand io.Reader, data []byte) (*ssh.Signature, error) { // The agent has its own entropy source, so the rand argument is ignored. return s.agent.Sign(s.pub, data) } lxd-2.0.0/dist/src/golang.org/x/crypto/ssh/agent/keyring_test.go0000644061062106075000000000346712702772344027237 0ustar00stgraberdomain admins00000000000000// Copyright 2015 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 agent import ( "testing" ) func addTestKey(t *testing.T, a Agent, keyName string) { err := a.Add(AddedKey{ PrivateKey: testPrivateKeys[keyName], Comment: keyName, }) if err != nil { t.Fatalf("failed to add key %q: %v", keyName, err) } } func removeTestKey(t *testing.T, a Agent, keyName string) { err := a.Remove(testPublicKeys[keyName]) if err != nil { t.Fatalf("failed to remove key %q: %v", keyName, err) } } func validateListedKeys(t *testing.T, a Agent, expectedKeys []string) { listedKeys, err := a.List() if err != nil { t.Fatalf("failed to list keys: %v", err) return } actualKeys := make(map[string]bool) for _, key := range listedKeys { actualKeys[key.Comment] = true } matchedKeys := make(map[string]bool) for _, expectedKey := range expectedKeys { if !actualKeys[expectedKey] { t.Fatalf("expected key %q, but was not found", expectedKey) } else { matchedKeys[expectedKey] = true } } for actualKey := range actualKeys { if !matchedKeys[actualKey] { t.Fatalf("key %q was found, but was not expected", actualKey) } } } func TestKeyringAddingAndRemoving(t *testing.T) { keyNames := []string{"dsa", "ecdsa", "rsa", "user"} // add all test private keys k := NewKeyring() for _, keyName := range keyNames { addTestKey(t, k, keyName) } validateListedKeys(t, k, keyNames) // remove a key in the middle keyToRemove := keyNames[1] keyNames = append(keyNames[:1], keyNames[2:]...) removeTestKey(t, k, keyToRemove) validateListedKeys(t, k, keyNames) // remove all keys err := k.RemoveAll() if err != nil { t.Fatalf("failed to remove all keys: %v", err) } validateListedKeys(t, k, []string{}) } lxd-2.0.0/dist/src/golang.org/x/crypto/ssh/agent/server_test.go0000644061062106075000000000316412702772344027067 0ustar00stgraberdomain admins00000000000000// Copyright 2012 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 agent import ( "testing" "golang.org/x/crypto/ssh" ) func TestServer(t *testing.T) { c1, c2, err := netPipe() if err != nil { t.Fatalf("netPipe: %v", err) } defer c1.Close() defer c2.Close() client := NewClient(c1) go ServeAgent(NewKeyring(), c2) testAgentInterface(t, client, testPrivateKeys["rsa"], nil, 0) } func TestLockServer(t *testing.T) { testLockAgent(NewKeyring(), t) } func TestSetupForwardAgent(t *testing.T) { a, b, err := netPipe() if err != nil { t.Fatalf("netPipe: %v", err) } defer a.Close() defer b.Close() _, socket, cleanup := startAgent(t) defer cleanup() serverConf := ssh.ServerConfig{ NoClientAuth: true, } serverConf.AddHostKey(testSigners["rsa"]) incoming := make(chan *ssh.ServerConn, 1) go func() { conn, _, _, err := ssh.NewServerConn(a, &serverConf) if err != nil { t.Fatalf("Server: %v", err) } incoming <- conn }() conf := ssh.ClientConfig{} conn, chans, reqs, err := ssh.NewClientConn(b, "", &conf) if err != nil { t.Fatalf("NewClientConn: %v", err) } client := ssh.NewClient(conn, chans, reqs) if err := ForwardToRemote(client, socket); err != nil { t.Fatalf("SetupForwardAgent: %v", err) } server := <-incoming ch, reqs, err := server.OpenChannel(channelType, nil) if err != nil { t.Fatalf("OpenChannel(%q): %v", channelType, err) } go ssh.DiscardRequests(reqs) agentClient := NewClient(ch) testAgentInterface(t, agentClient, testPrivateKeys["rsa"], nil, 0) conn.Close() } lxd-2.0.0/dist/src/golang.org/x/crypto/ssh/agent/forward.go0000644061062106075000000000424612702772344026170 0ustar00stgraberdomain admins00000000000000// Copyright 2014 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 agent import ( "errors" "io" "net" "sync" "golang.org/x/crypto/ssh" ) // RequestAgentForwarding sets up agent forwarding for the session. // ForwardToAgent or ForwardToRemote should be called to route // the authentication requests. func RequestAgentForwarding(session *ssh.Session) error { ok, err := session.SendRequest("auth-agent-req@openssh.com", true, nil) if err != nil { return err } if !ok { return errors.New("forwarding request denied") } return nil } // ForwardToAgent routes authentication requests to the given keyring. func ForwardToAgent(client *ssh.Client, keyring Agent) error { channels := client.HandleChannelOpen(channelType) if channels == nil { return errors.New("agent: already have handler for " + channelType) } go func() { for ch := range channels { channel, reqs, err := ch.Accept() if err != nil { continue } go ssh.DiscardRequests(reqs) go func() { ServeAgent(keyring, channel) channel.Close() }() } }() return nil } const channelType = "auth-agent@openssh.com" // ForwardToRemote routes authentication requests to the ssh-agent // process serving on the given unix socket. func ForwardToRemote(client *ssh.Client, addr string) error { channels := client.HandleChannelOpen(channelType) if channels == nil { return errors.New("agent: already have handler for " + channelType) } conn, err := net.Dial("unix", addr) if err != nil { return err } conn.Close() go func() { for ch := range channels { channel, reqs, err := ch.Accept() if err != nil { continue } go ssh.DiscardRequests(reqs) go forwardUnixSocket(channel, addr) } }() return nil } func forwardUnixSocket(channel ssh.Channel, addr string) { conn, err := net.Dial("unix", addr) if err != nil { return } var wg sync.WaitGroup wg.Add(2) go func() { io.Copy(conn, channel) conn.(*net.UnixConn).CloseWrite() wg.Done() }() go func() { io.Copy(channel, conn) channel.CloseWrite() wg.Done() }() wg.Wait() conn.Close() channel.Close() } lxd-2.0.0/dist/src/golang.org/x/crypto/ssh/handshake.go0000644061062106075000000002422712702772344025355 0ustar00stgraberdomain admins00000000000000// Copyright 2013 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 ssh import ( "crypto/rand" "errors" "fmt" "io" "log" "net" "sync" ) // debugHandshake, if set, prints messages sent and received. Key // exchange messages are printed as if DH were used, so the debug // messages are wrong when using ECDH. const debugHandshake = false // keyingTransport is a packet based transport that supports key // changes. It need not be thread-safe. It should pass through // msgNewKeys in both directions. type keyingTransport interface { packetConn // prepareKeyChange sets up a key change. The key change for a // direction will be effected if a msgNewKeys message is sent // or received. prepareKeyChange(*algorithms, *kexResult) error // getSessionID returns the session ID. prepareKeyChange must // have been called once. getSessionID() []byte } // rekeyingTransport is the interface of handshakeTransport that we // (internally) expose to ClientConn and ServerConn. type rekeyingTransport interface { packetConn // requestKeyChange asks the remote side to change keys. All // writes are blocked until the key change succeeds, which is // signaled by reading a msgNewKeys. requestKeyChange() error // getSessionID returns the session ID. This is only valid // after the first key change has completed. getSessionID() []byte } // handshakeTransport implements rekeying on top of a keyingTransport // and offers a thread-safe writePacket() interface. type handshakeTransport struct { conn keyingTransport config *Config serverVersion []byte clientVersion []byte // hostKeys is non-empty if we are the server. In that case, // it contains all host keys that can be used to sign the // connection. hostKeys []Signer // hostKeyAlgorithms is non-empty if we are the client. In that case, // we accept these key types from the server as host key. hostKeyAlgorithms []string // On read error, incoming is closed, and readError is set. incoming chan []byte readError error // data for host key checking hostKeyCallback func(hostname string, remote net.Addr, key PublicKey) error dialAddress string remoteAddr net.Addr readSinceKex uint64 // Protects the writing side of the connection mu sync.Mutex cond *sync.Cond sentInitPacket []byte sentInitMsg *kexInitMsg writtenSinceKex uint64 writeError error } func newHandshakeTransport(conn keyingTransport, config *Config, clientVersion, serverVersion []byte) *handshakeTransport { t := &handshakeTransport{ conn: conn, serverVersion: serverVersion, clientVersion: clientVersion, incoming: make(chan []byte, 16), config: config, } t.cond = sync.NewCond(&t.mu) return t } func newClientTransport(conn keyingTransport, clientVersion, serverVersion []byte, config *ClientConfig, dialAddr string, addr net.Addr) *handshakeTransport { t := newHandshakeTransport(conn, &config.Config, clientVersion, serverVersion) t.dialAddress = dialAddr t.remoteAddr = addr t.hostKeyCallback = config.HostKeyCallback if config.HostKeyAlgorithms != nil { t.hostKeyAlgorithms = config.HostKeyAlgorithms } else { t.hostKeyAlgorithms = supportedHostKeyAlgos } go t.readLoop() return t } func newServerTransport(conn keyingTransport, clientVersion, serverVersion []byte, config *ServerConfig) *handshakeTransport { t := newHandshakeTransport(conn, &config.Config, clientVersion, serverVersion) t.hostKeys = config.hostKeys go t.readLoop() return t } func (t *handshakeTransport) getSessionID() []byte { return t.conn.getSessionID() } func (t *handshakeTransport) id() string { if len(t.hostKeys) > 0 { return "server" } return "client" } func (t *handshakeTransport) readPacket() ([]byte, error) { p, ok := <-t.incoming if !ok { return nil, t.readError } return p, nil } func (t *handshakeTransport) readLoop() { for { p, err := t.readOnePacket() if err != nil { t.readError = err close(t.incoming) break } if p[0] == msgIgnore || p[0] == msgDebug { continue } t.incoming <- p } // If we can't read, declare the writing part dead too. t.mu.Lock() defer t.mu.Unlock() if t.writeError == nil { t.writeError = t.readError } t.cond.Broadcast() } func (t *handshakeTransport) readOnePacket() ([]byte, error) { if t.readSinceKex > t.config.RekeyThreshold { if err := t.requestKeyChange(); err != nil { return nil, err } } p, err := t.conn.readPacket() if err != nil { return nil, err } t.readSinceKex += uint64(len(p)) if debugHandshake { msg, err := decode(p) log.Printf("%s got %T %v (%v)", t.id(), msg, msg, err) } if p[0] != msgKexInit { return p, nil } err = t.enterKeyExchange(p) t.mu.Lock() if err != nil { // drop connection t.conn.Close() t.writeError = err } if debugHandshake { log.Printf("%s exited key exchange, err %v", t.id(), err) } // Unblock writers. t.sentInitMsg = nil t.sentInitPacket = nil t.cond.Broadcast() t.writtenSinceKex = 0 t.mu.Unlock() if err != nil { return nil, err } t.readSinceKex = 0 return []byte{msgNewKeys}, nil } // sendKexInit sends a key change message, and returns the message // that was sent. After initiating the key change, all writes will be // blocked until the change is done, and a failed key change will // close the underlying transport. This function is safe for // concurrent use by multiple goroutines. func (t *handshakeTransport) sendKexInit() (*kexInitMsg, []byte, error) { t.mu.Lock() defer t.mu.Unlock() return t.sendKexInitLocked() } func (t *handshakeTransport) requestKeyChange() error { _, _, err := t.sendKexInit() return err } // sendKexInitLocked sends a key change message. t.mu must be locked // while this happens. func (t *handshakeTransport) sendKexInitLocked() (*kexInitMsg, []byte, error) { // kexInits may be sent either in response to the other side, // or because our side wants to initiate a key change, so we // may have already sent a kexInit. In that case, don't send a // second kexInit. if t.sentInitMsg != nil { return t.sentInitMsg, t.sentInitPacket, nil } msg := &kexInitMsg{ KexAlgos: t.config.KeyExchanges, CiphersClientServer: t.config.Ciphers, CiphersServerClient: t.config.Ciphers, MACsClientServer: t.config.MACs, MACsServerClient: t.config.MACs, CompressionClientServer: supportedCompressions, CompressionServerClient: supportedCompressions, } io.ReadFull(rand.Reader, msg.Cookie[:]) if len(t.hostKeys) > 0 { for _, k := range t.hostKeys { msg.ServerHostKeyAlgos = append( msg.ServerHostKeyAlgos, k.PublicKey().Type()) } } else { msg.ServerHostKeyAlgos = t.hostKeyAlgorithms } packet := Marshal(msg) // writePacket destroys the contents, so save a copy. packetCopy := make([]byte, len(packet)) copy(packetCopy, packet) if err := t.conn.writePacket(packetCopy); err != nil { return nil, nil, err } t.sentInitMsg = msg t.sentInitPacket = packet return msg, packet, nil } func (t *handshakeTransport) writePacket(p []byte) error { t.mu.Lock() defer t.mu.Unlock() if t.writtenSinceKex > t.config.RekeyThreshold { t.sendKexInitLocked() } for t.sentInitMsg != nil && t.writeError == nil { t.cond.Wait() } if t.writeError != nil { return t.writeError } t.writtenSinceKex += uint64(len(p)) switch p[0] { case msgKexInit: return errors.New("ssh: only handshakeTransport can send kexInit") case msgNewKeys: return errors.New("ssh: only handshakeTransport can send newKeys") default: return t.conn.writePacket(p) } } func (t *handshakeTransport) Close() error { return t.conn.Close() } // enterKeyExchange runs the key exchange. func (t *handshakeTransport) enterKeyExchange(otherInitPacket []byte) error { if debugHandshake { log.Printf("%s entered key exchange", t.id()) } myInit, myInitPacket, err := t.sendKexInit() if err != nil { return err } otherInit := &kexInitMsg{} if err := Unmarshal(otherInitPacket, otherInit); err != nil { return err } magics := handshakeMagics{ clientVersion: t.clientVersion, serverVersion: t.serverVersion, clientKexInit: otherInitPacket, serverKexInit: myInitPacket, } clientInit := otherInit serverInit := myInit if len(t.hostKeys) == 0 { clientInit = myInit serverInit = otherInit magics.clientKexInit = myInitPacket magics.serverKexInit = otherInitPacket } algs, err := findAgreedAlgorithms(clientInit, serverInit) if err != nil { return err } // We don't send FirstKexFollows, but we handle receiving it. if otherInit.FirstKexFollows && algs.kex != otherInit.KexAlgos[0] { // other side sent a kex message for the wrong algorithm, // which we have to ignore. if _, err := t.conn.readPacket(); err != nil { return err } } kex, ok := kexAlgoMap[algs.kex] if !ok { return fmt.Errorf("ssh: unexpected key exchange algorithm %v", algs.kex) } var result *kexResult if len(t.hostKeys) > 0 { result, err = t.server(kex, algs, &magics) } else { result, err = t.client(kex, algs, &magics) } if err != nil { return err } t.conn.prepareKeyChange(algs, result) if err = t.conn.writePacket([]byte{msgNewKeys}); err != nil { return err } if packet, err := t.conn.readPacket(); err != nil { return err } else if packet[0] != msgNewKeys { return unexpectedMessageError(msgNewKeys, packet[0]) } return nil } func (t *handshakeTransport) server(kex kexAlgorithm, algs *algorithms, magics *handshakeMagics) (*kexResult, error) { var hostKey Signer for _, k := range t.hostKeys { if algs.hostKey == k.PublicKey().Type() { hostKey = k } } r, err := kex.Server(t.conn, t.config.Rand, magics, hostKey) return r, err } func (t *handshakeTransport) client(kex kexAlgorithm, algs *algorithms, magics *handshakeMagics) (*kexResult, error) { result, err := kex.Client(t.conn, t.config.Rand, magics) if err != nil { return nil, err } hostKey, err := ParsePublicKey(result.HostKey) if err != nil { return nil, err } if err := verifyHostKeySignature(hostKey, result); err != nil { return nil, err } if t.hostKeyCallback != nil { err = t.hostKeyCallback(t.dialAddress, t.remoteAddr, hostKey) if err != nil { return nil, err } } return result, nil } lxd-2.0.0/dist/src/golang.org/x/crypto/ssh/client_test.go0000644061062106075000000000171112702772344025735 0ustar00stgraberdomain admins00000000000000// Copyright 2014 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 ssh import ( "net" "testing" ) func testClientVersion(t *testing.T, config *ClientConfig, expected string) { clientConn, serverConn := net.Pipe() defer clientConn.Close() receivedVersion := make(chan string, 1) go func() { version, err := readVersion(serverConn) if err != nil { receivedVersion <- "" } else { receivedVersion <- string(version) } serverConn.Close() }() NewClientConn(clientConn, "", config) actual := <-receivedVersion if actual != expected { t.Fatalf("got %s; want %s", actual, expected) } } func TestCustomClientVersion(t *testing.T) { version := "Test-Client-Version-0.0" testClientVersion(t, &ClientConfig{ClientVersion: version}, version) } func TestDefaultClientVersion(t *testing.T) { testClientVersion(t, &ClientConfig{}, packageVersion) } lxd-2.0.0/dist/src/golang.org/x/crypto/ssh/tcpip_test.go0000644061062106075000000000076012702772344025601 0ustar00stgraberdomain admins00000000000000// Copyright 2014 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 ssh import ( "testing" ) func TestAutoPortListenBroken(t *testing.T) { broken := "SSH-2.0-OpenSSH_5.9hh11" works := "SSH-2.0-OpenSSH_6.1" if !isBrokenOpenSSHVersion(broken) { t.Errorf("version %q not marked as broken", broken) } if isBrokenOpenSSHVersion(works) { t.Errorf("version %q marked as broken", works) } } lxd-2.0.0/dist/src/golang.org/x/crypto/ssh/session_test.go0000644061062106075000000004623512702772344026154 0ustar00stgraberdomain admins00000000000000// 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 ssh // Session tests. import ( "bytes" crypto_rand "crypto/rand" "errors" "io" "io/ioutil" "math/rand" "net" "testing" "golang.org/x/crypto/ssh/terminal" ) type serverType func(Channel, <-chan *Request, *testing.T) // dial constructs a new test server and returns a *ClientConn. func dial(handler serverType, t *testing.T) *Client { c1, c2, err := netPipe() if err != nil { t.Fatalf("netPipe: %v", err) } go func() { defer c1.Close() conf := ServerConfig{ NoClientAuth: true, } conf.AddHostKey(testSigners["rsa"]) _, chans, reqs, err := NewServerConn(c1, &conf) if err != nil { t.Fatalf("Unable to handshake: %v", err) } go DiscardRequests(reqs) for newCh := range chans { if newCh.ChannelType() != "session" { newCh.Reject(UnknownChannelType, "unknown channel type") continue } ch, inReqs, err := newCh.Accept() if err != nil { t.Errorf("Accept: %v", err) continue } go func() { handler(ch, inReqs, t) }() } }() config := &ClientConfig{ User: "testuser", } conn, chans, reqs, err := NewClientConn(c2, "", config) if err != nil { t.Fatalf("unable to dial remote side: %v", err) } return NewClient(conn, chans, reqs) } // Test a simple string is returned to session.Stdout. func TestSessionShell(t *testing.T) { conn := dial(shellHandler, t) defer conn.Close() session, err := conn.NewSession() if err != nil { t.Fatalf("Unable to request new session: %v", err) } defer session.Close() stdout := new(bytes.Buffer) session.Stdout = stdout if err := session.Shell(); err != nil { t.Fatalf("Unable to execute command: %s", err) } if err := session.Wait(); err != nil { t.Fatalf("Remote command did not exit cleanly: %v", err) } actual := stdout.String() if actual != "golang" { t.Fatalf("Remote shell did not return expected string: expected=golang, actual=%s", actual) } } // TODO(dfc) add support for Std{in,err}Pipe when the Server supports it. // Test a simple string is returned via StdoutPipe. func TestSessionStdoutPipe(t *testing.T) { conn := dial(shellHandler, t) defer conn.Close() session, err := conn.NewSession() if err != nil { t.Fatalf("Unable to request new session: %v", err) } defer session.Close() stdout, err := session.StdoutPipe() if err != nil { t.Fatalf("Unable to request StdoutPipe(): %v", err) } var buf bytes.Buffer if err := session.Shell(); err != nil { t.Fatalf("Unable to execute command: %v", err) } done := make(chan bool, 1) go func() { if _, err := io.Copy(&buf, stdout); err != nil { t.Errorf("Copy of stdout failed: %v", err) } done <- true }() if err := session.Wait(); err != nil { t.Fatalf("Remote command did not exit cleanly: %v", err) } <-done actual := buf.String() if actual != "golang" { t.Fatalf("Remote shell did not return expected string: expected=golang, actual=%s", actual) } } // Test that a simple string is returned via the Output helper, // and that stderr is discarded. func TestSessionOutput(t *testing.T) { conn := dial(fixedOutputHandler, t) defer conn.Close() session, err := conn.NewSession() if err != nil { t.Fatalf("Unable to request new session: %v", err) } defer session.Close() buf, err := session.Output("") // cmd is ignored by fixedOutputHandler if err != nil { t.Error("Remote command did not exit cleanly:", err) } w := "this-is-stdout." g := string(buf) if g != w { t.Error("Remote command did not return expected string:") t.Logf("want %q", w) t.Logf("got %q", g) } } // Test that both stdout and stderr are returned // via the CombinedOutput helper. func TestSessionCombinedOutput(t *testing.T) { conn := dial(fixedOutputHandler, t) defer conn.Close() session, err := conn.NewSession() if err != nil { t.Fatalf("Unable to request new session: %v", err) } defer session.Close() buf, err := session.CombinedOutput("") // cmd is ignored by fixedOutputHandler if err != nil { t.Error("Remote command did not exit cleanly:", err) } const stdout = "this-is-stdout." const stderr = "this-is-stderr." g := string(buf) if g != stdout+stderr && g != stderr+stdout { t.Error("Remote command did not return expected string:") t.Logf("want %q, or %q", stdout+stderr, stderr+stdout) t.Logf("got %q", g) } } // Test non-0 exit status is returned correctly. func TestExitStatusNonZero(t *testing.T) { conn := dial(exitStatusNonZeroHandler, t) defer conn.Close() session, err := conn.NewSession() if err != nil { t.Fatalf("Unable to request new session: %v", err) } defer session.Close() if err := session.Shell(); err != nil { t.Fatalf("Unable to execute command: %v", err) } err = session.Wait() if err == nil { t.Fatalf("expected command to fail but it didn't") } e, ok := err.(*ExitError) if !ok { t.Fatalf("expected *ExitError but got %T", err) } if e.ExitStatus() != 15 { t.Fatalf("expected command to exit with 15 but got %v", e.ExitStatus()) } } // Test 0 exit status is returned correctly. func TestExitStatusZero(t *testing.T) { conn := dial(exitStatusZeroHandler, t) defer conn.Close() session, err := conn.NewSession() if err != nil { t.Fatalf("Unable to request new session: %v", err) } defer session.Close() if err := session.Shell(); err != nil { t.Fatalf("Unable to execute command: %v", err) } err = session.Wait() if err != nil { t.Fatalf("expected nil but got %v", err) } } // Test exit signal and status are both returned correctly. func TestExitSignalAndStatus(t *testing.T) { conn := dial(exitSignalAndStatusHandler, t) defer conn.Close() session, err := conn.NewSession() if err != nil { t.Fatalf("Unable to request new session: %v", err) } defer session.Close() if err := session.Shell(); err != nil { t.Fatalf("Unable to execute command: %v", err) } err = session.Wait() if err == nil { t.Fatalf("expected command to fail but it didn't") } e, ok := err.(*ExitError) if !ok { t.Fatalf("expected *ExitError but got %T", err) } if e.Signal() != "TERM" || e.ExitStatus() != 15 { t.Fatalf("expected command to exit with signal TERM and status 15 but got signal %s and status %v", e.Signal(), e.ExitStatus()) } } // Test exit signal and status are both returned correctly. func TestKnownExitSignalOnly(t *testing.T) { conn := dial(exitSignalHandler, t) defer conn.Close() session, err := conn.NewSession() if err != nil { t.Fatalf("Unable to request new session: %v", err) } defer session.Close() if err := session.Shell(); err != nil { t.Fatalf("Unable to execute command: %v", err) } err = session.Wait() if err == nil { t.Fatalf("expected command to fail but it didn't") } e, ok := err.(*ExitError) if !ok { t.Fatalf("expected *ExitError but got %T", err) } if e.Signal() != "TERM" || e.ExitStatus() != 143 { t.Fatalf("expected command to exit with signal TERM and status 143 but got signal %s and status %v", e.Signal(), e.ExitStatus()) } } // Test exit signal and status are both returned correctly. func TestUnknownExitSignal(t *testing.T) { conn := dial(exitSignalUnknownHandler, t) defer conn.Close() session, err := conn.NewSession() if err != nil { t.Fatalf("Unable to request new session: %v", err) } defer session.Close() if err := session.Shell(); err != nil { t.Fatalf("Unable to execute command: %v", err) } err = session.Wait() if err == nil { t.Fatalf("expected command to fail but it didn't") } e, ok := err.(*ExitError) if !ok { t.Fatalf("expected *ExitError but got %T", err) } if e.Signal() != "SYS" || e.ExitStatus() != 128 { t.Fatalf("expected command to exit with signal SYS and status 128 but got signal %s and status %v", e.Signal(), e.ExitStatus()) } } // Test WaitMsg is not returned if the channel closes abruptly. func TestExitWithoutStatusOrSignal(t *testing.T) { conn := dial(exitWithoutSignalOrStatus, t) defer conn.Close() session, err := conn.NewSession() if err != nil { t.Fatalf("Unable to request new session: %v", err) } defer session.Close() if err := session.Shell(); err != nil { t.Fatalf("Unable to execute command: %v", err) } err = session.Wait() if err == nil { t.Fatalf("expected command to fail but it didn't") } _, ok := err.(*ExitError) if ok { // you can't actually test for errors.errorString // because it's not exported. t.Fatalf("expected *errorString but got %T", err) } } // windowTestBytes is the number of bytes that we'll send to the SSH server. const windowTestBytes = 16000 * 200 // TestServerWindow writes random data to the server. The server is expected to echo // the same data back, which is compared against the original. func TestServerWindow(t *testing.T) { origBuf := bytes.NewBuffer(make([]byte, 0, windowTestBytes)) io.CopyN(origBuf, crypto_rand.Reader, windowTestBytes) origBytes := origBuf.Bytes() conn := dial(echoHandler, t) defer conn.Close() session, err := conn.NewSession() if err != nil { t.Fatal(err) } defer session.Close() result := make(chan []byte) go func() { defer close(result) echoedBuf := bytes.NewBuffer(make([]byte, 0, windowTestBytes)) serverStdout, err := session.StdoutPipe() if err != nil { t.Errorf("StdoutPipe failed: %v", err) return } n, err := copyNRandomly("stdout", echoedBuf, serverStdout, windowTestBytes) if err != nil && err != io.EOF { t.Errorf("Read only %d bytes from server, expected %d: %v", n, windowTestBytes, err) } result <- echoedBuf.Bytes() }() serverStdin, err := session.StdinPipe() if err != nil { t.Fatalf("StdinPipe failed: %v", err) } written, err := copyNRandomly("stdin", serverStdin, origBuf, windowTestBytes) if err != nil { t.Fatalf("failed to copy origBuf to serverStdin: %v", err) } if written != windowTestBytes { t.Fatalf("Wrote only %d of %d bytes to server", written, windowTestBytes) } echoedBytes := <-result if !bytes.Equal(origBytes, echoedBytes) { t.Fatalf("Echoed buffer differed from original, orig %d, echoed %d", len(origBytes), len(echoedBytes)) } } // Verify the client can handle a keepalive packet from the server. func TestClientHandlesKeepalives(t *testing.T) { conn := dial(channelKeepaliveSender, t) defer conn.Close() session, err := conn.NewSession() if err != nil { t.Fatal(err) } defer session.Close() if err := session.Shell(); err != nil { t.Fatalf("Unable to execute command: %v", err) } err = session.Wait() if err != nil { t.Fatalf("expected nil but got: %v", err) } } type exitStatusMsg struct { Status uint32 } type exitSignalMsg struct { Signal string CoreDumped bool Errmsg string Lang string } func handleTerminalRequests(in <-chan *Request) { for req := range in { ok := false switch req.Type { case "shell": ok = true if len(req.Payload) > 0 { // We don't accept any commands, only the default shell. ok = false } case "env": ok = true } req.Reply(ok, nil) } } func newServerShell(ch Channel, in <-chan *Request, prompt string) *terminal.Terminal { term := terminal.NewTerminal(ch, prompt) go handleTerminalRequests(in) return term } func exitStatusZeroHandler(ch Channel, in <-chan *Request, t *testing.T) { defer ch.Close() // this string is returned to stdout shell := newServerShell(ch, in, "> ") readLine(shell, t) sendStatus(0, ch, t) } func exitStatusNonZeroHandler(ch Channel, in <-chan *Request, t *testing.T) { defer ch.Close() shell := newServerShell(ch, in, "> ") readLine(shell, t) sendStatus(15, ch, t) } func exitSignalAndStatusHandler(ch Channel, in <-chan *Request, t *testing.T) { defer ch.Close() shell := newServerShell(ch, in, "> ") readLine(shell, t) sendStatus(15, ch, t) sendSignal("TERM", ch, t) } func exitSignalHandler(ch Channel, in <-chan *Request, t *testing.T) { defer ch.Close() shell := newServerShell(ch, in, "> ") readLine(shell, t) sendSignal("TERM", ch, t) } func exitSignalUnknownHandler(ch Channel, in <-chan *Request, t *testing.T) { defer ch.Close() shell := newServerShell(ch, in, "> ") readLine(shell, t) sendSignal("SYS", ch, t) } func exitWithoutSignalOrStatus(ch Channel, in <-chan *Request, t *testing.T) { defer ch.Close() shell := newServerShell(ch, in, "> ") readLine(shell, t) } func shellHandler(ch Channel, in <-chan *Request, t *testing.T) { defer ch.Close() // this string is returned to stdout shell := newServerShell(ch, in, "golang") readLine(shell, t) sendStatus(0, ch, t) } // Ignores the command, writes fixed strings to stderr and stdout. // Strings are "this-is-stdout." and "this-is-stderr.". func fixedOutputHandler(ch Channel, in <-chan *Request, t *testing.T) { defer ch.Close() _, err := ch.Read(nil) req, ok := <-in if !ok { t.Fatalf("error: expected channel request, got: %#v", err) return } // ignore request, always send some text req.Reply(true, nil) _, err = io.WriteString(ch, "this-is-stdout.") if err != nil { t.Fatalf("error writing on server: %v", err) } _, err = io.WriteString(ch.Stderr(), "this-is-stderr.") if err != nil { t.Fatalf("error writing on server: %v", err) } sendStatus(0, ch, t) } func readLine(shell *terminal.Terminal, t *testing.T) { if _, err := shell.ReadLine(); err != nil && err != io.EOF { t.Errorf("unable to read line: %v", err) } } func sendStatus(status uint32, ch Channel, t *testing.T) { msg := exitStatusMsg{ Status: status, } if _, err := ch.SendRequest("exit-status", false, Marshal(&msg)); err != nil { t.Errorf("unable to send status: %v", err) } } func sendSignal(signal string, ch Channel, t *testing.T) { sig := exitSignalMsg{ Signal: signal, CoreDumped: false, Errmsg: "Process terminated", Lang: "en-GB-oed", } if _, err := ch.SendRequest("exit-signal", false, Marshal(&sig)); err != nil { t.Errorf("unable to send signal: %v", err) } } func discardHandler(ch Channel, t *testing.T) { defer ch.Close() io.Copy(ioutil.Discard, ch) } func echoHandler(ch Channel, in <-chan *Request, t *testing.T) { defer ch.Close() if n, err := copyNRandomly("echohandler", ch, ch, windowTestBytes); err != nil { t.Errorf("short write, wrote %d, expected %d: %v ", n, windowTestBytes, err) } } // copyNRandomly copies n bytes from src to dst. It uses a variable, and random, // buffer size to exercise more code paths. func copyNRandomly(title string, dst io.Writer, src io.Reader, n int) (int, error) { var ( buf = make([]byte, 32*1024) written int remaining = n ) for remaining > 0 { l := rand.Intn(1 << 15) if remaining < l { l = remaining } nr, er := src.Read(buf[:l]) nw, ew := dst.Write(buf[:nr]) remaining -= nw written += nw if ew != nil { return written, ew } if nr != nw { return written, io.ErrShortWrite } if er != nil && er != io.EOF { return written, er } } return written, nil } func channelKeepaliveSender(ch Channel, in <-chan *Request, t *testing.T) { defer ch.Close() shell := newServerShell(ch, in, "> ") readLine(shell, t) if _, err := ch.SendRequest("keepalive@openssh.com", true, nil); err != nil { t.Errorf("unable to send channel keepalive request: %v", err) } sendStatus(0, ch, t) } func TestClientWriteEOF(t *testing.T) { conn := dial(simpleEchoHandler, t) defer conn.Close() session, err := conn.NewSession() if err != nil { t.Fatal(err) } defer session.Close() stdin, err := session.StdinPipe() if err != nil { t.Fatalf("StdinPipe failed: %v", err) } stdout, err := session.StdoutPipe() if err != nil { t.Fatalf("StdoutPipe failed: %v", err) } data := []byte(`0000`) _, err = stdin.Write(data) if err != nil { t.Fatalf("Write failed: %v", err) } stdin.Close() res, err := ioutil.ReadAll(stdout) if err != nil { t.Fatalf("Read failed: %v", err) } if !bytes.Equal(data, res) { t.Fatalf("Read differed from write, wrote: %v, read: %v", data, res) } } func simpleEchoHandler(ch Channel, in <-chan *Request, t *testing.T) { defer ch.Close() data, err := ioutil.ReadAll(ch) if err != nil { t.Errorf("handler read error: %v", err) } _, err = ch.Write(data) if err != nil { t.Errorf("handler write error: %v", err) } } func TestSessionID(t *testing.T) { c1, c2, err := netPipe() if err != nil { t.Fatalf("netPipe: %v", err) } defer c1.Close() defer c2.Close() serverID := make(chan []byte, 1) clientID := make(chan []byte, 1) serverConf := &ServerConfig{ NoClientAuth: true, } serverConf.AddHostKey(testSigners["ecdsa"]) clientConf := &ClientConfig{ User: "user", } go func() { conn, chans, reqs, err := NewServerConn(c1, serverConf) if err != nil { t.Fatalf("server handshake: %v", err) } serverID <- conn.SessionID() go DiscardRequests(reqs) for ch := range chans { ch.Reject(Prohibited, "") } }() go func() { conn, chans, reqs, err := NewClientConn(c2, "", clientConf) if err != nil { t.Fatalf("client handshake: %v", err) } clientID <- conn.SessionID() go DiscardRequests(reqs) for ch := range chans { ch.Reject(Prohibited, "") } }() s := <-serverID c := <-clientID if bytes.Compare(s, c) != 0 { t.Errorf("server session ID (%x) != client session ID (%x)", s, c) } else if len(s) == 0 { t.Errorf("client and server SessionID were empty.") } } type noReadConn struct { readSeen bool net.Conn } func (c *noReadConn) Close() error { return nil } func (c *noReadConn) Read(b []byte) (int, error) { c.readSeen = true return 0, errors.New("noReadConn error") } func TestInvalidServerConfiguration(t *testing.T) { c1, c2, err := netPipe() if err != nil { t.Fatalf("netPipe: %v", err) } defer c1.Close() defer c2.Close() serveConn := noReadConn{Conn: c1} serverConf := &ServerConfig{} NewServerConn(&serveConn, serverConf) if serveConn.readSeen { t.Fatalf("NewServerConn attempted to Read() from Conn while configuration is missing host key") } serverConf.AddHostKey(testSigners["ecdsa"]) NewServerConn(&serveConn, serverConf) if serveConn.readSeen { t.Fatalf("NewServerConn attempted to Read() from Conn while configuration is missing authentication method") } } func TestHostKeyAlgorithms(t *testing.T) { serverConf := &ServerConfig{ NoClientAuth: true, } serverConf.AddHostKey(testSigners["rsa"]) serverConf.AddHostKey(testSigners["ecdsa"]) connect := func(clientConf *ClientConfig, want string) { var alg string clientConf.HostKeyCallback = func(h string, a net.Addr, key PublicKey) error { alg = key.Type() return nil } c1, c2, err := netPipe() if err != nil { t.Fatalf("netPipe: %v", err) } defer c1.Close() defer c2.Close() go NewServerConn(c1, serverConf) _, _, _, err = NewClientConn(c2, "", clientConf) if err != nil { t.Fatalf("NewClientConn: %v", err) } if alg != want { t.Errorf("selected key algorithm %s, want %s", alg, want) } } // By default, we get the preferred algorithm, which is ECDSA 256. clientConf := &ClientConfig{} connect(clientConf, KeyAlgoECDSA256) // Client asks for RSA explicitly. clientConf.HostKeyAlgorithms = []string{KeyAlgoRSA} connect(clientConf, KeyAlgoRSA) c1, c2, err := netPipe() if err != nil { t.Fatalf("netPipe: %v", err) } defer c1.Close() defer c2.Close() go NewServerConn(c1, serverConf) clientConf.HostKeyAlgorithms = []string{"nonexistent-hostkey-algo"} _, _, _, err = NewClientConn(c2, "", clientConf) if err == nil { t.Fatal("succeeded connecting with unknown hostkey algorithm") } } lxd-2.0.0/dist/src/golang.org/x/crypto/ssh/test/0000755061062106075000000000000012702772344024050 5ustar00stgraberdomain admins00000000000000lxd-2.0.0/dist/src/golang.org/x/crypto/ssh/test/agent_unix_test.go0000644061062106075000000000304212702772344027576 0ustar00stgraberdomain admins00000000000000// Copyright 2014 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. // +build darwin dragonfly freebsd linux netbsd openbsd package test import ( "bytes" "testing" "golang.org/x/crypto/ssh" "golang.org/x/crypto/ssh/agent" ) func TestAgentForward(t *testing.T) { server := newServer(t) defer server.Shutdown() conn := server.Dial(clientConfig()) defer conn.Close() keyring := agent.NewKeyring() if err := keyring.Add(agent.AddedKey{PrivateKey: testPrivateKeys["dsa"]}); err != nil { t.Fatalf("Error adding key: %s", err) } if err := keyring.Add(agent.AddedKey{ PrivateKey: testPrivateKeys["dsa"], ConfirmBeforeUse: true, LifetimeSecs: 3600, }); err != nil { t.Fatalf("Error adding key with constraints: %s", err) } pub := testPublicKeys["dsa"] sess, err := conn.NewSession() if err != nil { t.Fatalf("NewSession: %v", err) } if err := agent.RequestAgentForwarding(sess); err != nil { t.Fatalf("RequestAgentForwarding: %v", err) } if err := agent.ForwardToAgent(conn, keyring); err != nil { t.Fatalf("SetupForwardKeyring: %v", err) } out, err := sess.CombinedOutput("ssh-add -L") if err != nil { t.Fatalf("running ssh-add: %v, out %s", err, out) } key, _, _, _, err := ssh.ParseAuthorizedKey(out) if err != nil { t.Fatalf("ParseAuthorizedKey(%q): %v", out, err) } if !bytes.Equal(key.Marshal(), pub.Marshal()) { t.Fatalf("got key %s, want %s", ssh.MarshalAuthorizedKey(key), ssh.MarshalAuthorizedKey(pub)) } } lxd-2.0.0/dist/src/golang.org/x/crypto/ssh/test/doc.go0000644061062106075000000000045512702772344025150 0ustar00stgraberdomain admins00000000000000// Copyright 2012 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 contains integration tests for the // golang.org/x/crypto/ssh package. package test // import "golang.org/x/crypto/ssh/test" lxd-2.0.0/dist/src/golang.org/x/crypto/ssh/test/session_test.go0000644061062106075000000001703212702772344027124 0ustar00stgraberdomain admins00000000000000// Copyright 2012 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. // +build !windows package test // Session functional tests. import ( "bytes" "errors" "io" "strings" "testing" "golang.org/x/crypto/ssh" ) func TestRunCommandSuccess(t *testing.T) { server := newServer(t) defer server.Shutdown() conn := server.Dial(clientConfig()) defer conn.Close() session, err := conn.NewSession() if err != nil { t.Fatalf("session failed: %v", err) } defer session.Close() err = session.Run("true") if err != nil { t.Fatalf("session failed: %v", err) } } func TestHostKeyCheck(t *testing.T) { server := newServer(t) defer server.Shutdown() conf := clientConfig() hostDB := hostKeyDB() conf.HostKeyCallback = hostDB.Check // change the keys. hostDB.keys[ssh.KeyAlgoRSA][25]++ hostDB.keys[ssh.KeyAlgoDSA][25]++ hostDB.keys[ssh.KeyAlgoECDSA256][25]++ conn, err := server.TryDial(conf) if err == nil { conn.Close() t.Fatalf("dial should have failed.") } else if !strings.Contains(err.Error(), "host key mismatch") { t.Fatalf("'host key mismatch' not found in %v", err) } } func TestRunCommandStdin(t *testing.T) { server := newServer(t) defer server.Shutdown() conn := server.Dial(clientConfig()) defer conn.Close() session, err := conn.NewSession() if err != nil { t.Fatalf("session failed: %v", err) } defer session.Close() r, w := io.Pipe() defer r.Close() defer w.Close() session.Stdin = r err = session.Run("true") if err != nil { t.Fatalf("session failed: %v", err) } } func TestRunCommandStdinError(t *testing.T) { server := newServer(t) defer server.Shutdown() conn := server.Dial(clientConfig()) defer conn.Close() session, err := conn.NewSession() if err != nil { t.Fatalf("session failed: %v", err) } defer session.Close() r, w := io.Pipe() defer r.Close() session.Stdin = r pipeErr := errors.New("closing write end of pipe") w.CloseWithError(pipeErr) err = session.Run("true") if err != pipeErr { t.Fatalf("expected %v, found %v", pipeErr, err) } } func TestRunCommandFailed(t *testing.T) { server := newServer(t) defer server.Shutdown() conn := server.Dial(clientConfig()) defer conn.Close() session, err := conn.NewSession() if err != nil { t.Fatalf("session failed: %v", err) } defer session.Close() err = session.Run(`bash -c "kill -9 $$"`) if err == nil { t.Fatalf("session succeeded: %v", err) } } func TestRunCommandWeClosed(t *testing.T) { server := newServer(t) defer server.Shutdown() conn := server.Dial(clientConfig()) defer conn.Close() session, err := conn.NewSession() if err != nil { t.Fatalf("session failed: %v", err) } err = session.Shell() if err != nil { t.Fatalf("shell failed: %v", err) } err = session.Close() if err != nil { t.Fatalf("shell failed: %v", err) } } func TestFuncLargeRead(t *testing.T) { server := newServer(t) defer server.Shutdown() conn := server.Dial(clientConfig()) defer conn.Close() session, err := conn.NewSession() if err != nil { t.Fatalf("unable to create new session: %s", err) } stdout, err := session.StdoutPipe() if err != nil { t.Fatalf("unable to acquire stdout pipe: %s", err) } err = session.Start("dd if=/dev/urandom bs=2048 count=1024") if err != nil { t.Fatalf("unable to execute remote command: %s", err) } buf := new(bytes.Buffer) n, err := io.Copy(buf, stdout) if err != nil { t.Fatalf("error reading from remote stdout: %s", err) } if n != 2048*1024 { t.Fatalf("Expected %d bytes but read only %d from remote command", 2048, n) } } func TestKeyChange(t *testing.T) { server := newServer(t) defer server.Shutdown() conf := clientConfig() hostDB := hostKeyDB() conf.HostKeyCallback = hostDB.Check conf.RekeyThreshold = 1024 conn := server.Dial(conf) defer conn.Close() for i := 0; i < 4; i++ { session, err := conn.NewSession() if err != nil { t.Fatalf("unable to create new session: %s", err) } stdout, err := session.StdoutPipe() if err != nil { t.Fatalf("unable to acquire stdout pipe: %s", err) } err = session.Start("dd if=/dev/urandom bs=1024 count=1") if err != nil { t.Fatalf("unable to execute remote command: %s", err) } buf := new(bytes.Buffer) n, err := io.Copy(buf, stdout) if err != nil { t.Fatalf("error reading from remote stdout: %s", err) } want := int64(1024) if n != want { t.Fatalf("Expected %d bytes but read only %d from remote command", want, n) } } if changes := hostDB.checkCount; changes < 4 { t.Errorf("got %d key changes, want 4", changes) } } func TestInvalidTerminalMode(t *testing.T) { server := newServer(t) defer server.Shutdown() conn := server.Dial(clientConfig()) defer conn.Close() session, err := conn.NewSession() if err != nil { t.Fatalf("session failed: %v", err) } defer session.Close() if err = session.RequestPty("vt100", 80, 40, ssh.TerminalModes{255: 1984}); err == nil { t.Fatalf("req-pty failed: successful request with invalid mode") } } func TestValidTerminalMode(t *testing.T) { server := newServer(t) defer server.Shutdown() conn := server.Dial(clientConfig()) defer conn.Close() session, err := conn.NewSession() if err != nil { t.Fatalf("session failed: %v", err) } defer session.Close() stdout, err := session.StdoutPipe() if err != nil { t.Fatalf("unable to acquire stdout pipe: %s", err) } stdin, err := session.StdinPipe() if err != nil { t.Fatalf("unable to acquire stdin pipe: %s", err) } tm := ssh.TerminalModes{ssh.ECHO: 0} if err = session.RequestPty("xterm", 80, 40, tm); err != nil { t.Fatalf("req-pty failed: %s", err) } err = session.Shell() if err != nil { t.Fatalf("session failed: %s", err) } stdin.Write([]byte("stty -a && exit\n")) var buf bytes.Buffer if _, err := io.Copy(&buf, stdout); err != nil { t.Fatalf("reading failed: %s", err) } if sttyOutput := buf.String(); !strings.Contains(sttyOutput, "-echo ") { t.Fatalf("terminal mode failure: expected -echo in stty output, got %s", sttyOutput) } } func TestCiphers(t *testing.T) { var config ssh.Config config.SetDefaults() cipherOrder := config.Ciphers // This cipher will not be tested when commented out in cipher.go it will // fallback to the next available as per line 292. cipherOrder = append(cipherOrder, "aes128-cbc") for _, ciph := range cipherOrder { server := newServer(t) defer server.Shutdown() conf := clientConfig() conf.Ciphers = []string{ciph} // Don't fail if sshd doesnt have the cipher. conf.Ciphers = append(conf.Ciphers, cipherOrder...) conn, err := server.TryDial(conf) if err == nil { conn.Close() } else { t.Fatalf("failed for cipher %q", ciph) } } } func TestMACs(t *testing.T) { var config ssh.Config config.SetDefaults() macOrder := config.MACs for _, mac := range macOrder { server := newServer(t) defer server.Shutdown() conf := clientConfig() conf.MACs = []string{mac} // Don't fail if sshd doesnt have the MAC. conf.MACs = append(conf.MACs, macOrder...) if conn, err := server.TryDial(conf); err == nil { conn.Close() } else { t.Fatalf("failed for MAC %q", mac) } } } func TestKeyExchanges(t *testing.T) { var config ssh.Config config.SetDefaults() kexOrder := config.KeyExchanges for _, kex := range kexOrder { server := newServer(t) defer server.Shutdown() conf := clientConfig() // Don't fail if sshd doesnt have the kex. conf.KeyExchanges = append([]string{kex}, kexOrder...) conn, err := server.TryDial(conf) if err == nil { conn.Close() } else { t.Errorf("failed for kex %q", kex) } } } lxd-2.0.0/dist/src/golang.org/x/crypto/ssh/test/tcpip_test.go0000644061062106075000000000142712702772344026561 0ustar00stgraberdomain admins00000000000000// Copyright 2012 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. // +build !windows package test // direct-tcpip functional tests import ( "io" "net" "testing" ) func TestDial(t *testing.T) { server := newServer(t) defer server.Shutdown() sshConn := server.Dial(clientConfig()) defer sshConn.Close() l, err := net.Listen("tcp", "127.0.0.1:0") if err != nil { t.Fatalf("Listen: %v", err) } defer l.Close() go func() { for { c, err := l.Accept() if err != nil { break } io.WriteString(c, c.RemoteAddr().String()) c.Close() } }() conn, err := sshConn.Dial("tcp", l.Addr().String()) if err != nil { t.Fatalf("Dial: %v", err) } defer conn.Close() } lxd-2.0.0/dist/src/golang.org/x/crypto/ssh/test/test_unix_test.go0000644061062106075000000001336512702772344027470 0ustar00stgraberdomain admins00000000000000// Copyright 2012 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. // +build darwin dragonfly freebsd linux netbsd openbsd plan9 package test // functional test harness for unix. import ( "bytes" "fmt" "io/ioutil" "log" "net" "os" "os/exec" "os/user" "path/filepath" "testing" "text/template" "golang.org/x/crypto/ssh" "golang.org/x/crypto/ssh/testdata" ) const sshd_config = ` Protocol 2 HostKey {{.Dir}}/id_rsa HostKey {{.Dir}}/id_dsa HostKey {{.Dir}}/id_ecdsa Pidfile {{.Dir}}/sshd.pid #UsePrivilegeSeparation no KeyRegenerationInterval 3600 ServerKeyBits 768 SyslogFacility AUTH LogLevel DEBUG2 LoginGraceTime 120 PermitRootLogin no StrictModes no RSAAuthentication yes PubkeyAuthentication yes AuthorizedKeysFile {{.Dir}}/id_user.pub TrustedUserCAKeys {{.Dir}}/id_ecdsa.pub IgnoreRhosts yes RhostsRSAAuthentication no HostbasedAuthentication no ` var configTmpl = template.Must(template.New("").Parse(sshd_config)) type server struct { t *testing.T cleanup func() // executed during Shutdown configfile string cmd *exec.Cmd output bytes.Buffer // holds stderr from sshd process // Client half of the network connection. clientConn net.Conn } func username() string { var username string if user, err := user.Current(); err == nil { username = user.Username } else { // user.Current() currently requires cgo. If an error is // returned attempt to get the username from the environment. log.Printf("user.Current: %v; falling back on $USER", err) username = os.Getenv("USER") } if username == "" { panic("Unable to get username") } return username } type storedHostKey struct { // keys map from an algorithm string to binary key data. keys map[string][]byte // checkCount counts the Check calls. Used for testing // rekeying. checkCount int } func (k *storedHostKey) Add(key ssh.PublicKey) { if k.keys == nil { k.keys = map[string][]byte{} } k.keys[key.Type()] = key.Marshal() } func (k *storedHostKey) Check(addr string, remote net.Addr, key ssh.PublicKey) error { k.checkCount++ algo := key.Type() if k.keys == nil || bytes.Compare(key.Marshal(), k.keys[algo]) != 0 { return fmt.Errorf("host key mismatch. Got %q, want %q", key, k.keys[algo]) } return nil } func hostKeyDB() *storedHostKey { keyChecker := &storedHostKey{} keyChecker.Add(testPublicKeys["ecdsa"]) keyChecker.Add(testPublicKeys["rsa"]) keyChecker.Add(testPublicKeys["dsa"]) return keyChecker } func clientConfig() *ssh.ClientConfig { config := &ssh.ClientConfig{ User: username(), Auth: []ssh.AuthMethod{ ssh.PublicKeys(testSigners["user"]), }, HostKeyCallback: hostKeyDB().Check, } return config } // unixConnection creates two halves of a connected net.UnixConn. It // is used for connecting the Go SSH client with sshd without opening // ports. func unixConnection() (*net.UnixConn, *net.UnixConn, error) { dir, err := ioutil.TempDir("", "unixConnection") if err != nil { return nil, nil, err } defer os.Remove(dir) addr := filepath.Join(dir, "ssh") listener, err := net.Listen("unix", addr) if err != nil { return nil, nil, err } defer listener.Close() c1, err := net.Dial("unix", addr) if err != nil { return nil, nil, err } c2, err := listener.Accept() if err != nil { c1.Close() return nil, nil, err } return c1.(*net.UnixConn), c2.(*net.UnixConn), nil } func (s *server) TryDial(config *ssh.ClientConfig) (*ssh.Client, error) { sshd, err := exec.LookPath("sshd") if err != nil { s.t.Skipf("skipping test: %v", err) } c1, c2, err := unixConnection() if err != nil { s.t.Fatalf("unixConnection: %v", err) } s.cmd = exec.Command(sshd, "-f", s.configfile, "-i", "-e") f, err := c2.File() if err != nil { s.t.Fatalf("UnixConn.File: %v", err) } defer f.Close() s.cmd.Stdin = f s.cmd.Stdout = f s.cmd.Stderr = &s.output if err := s.cmd.Start(); err != nil { s.t.Fail() s.Shutdown() s.t.Fatalf("s.cmd.Start: %v", err) } s.clientConn = c1 conn, chans, reqs, err := ssh.NewClientConn(c1, "", config) if err != nil { return nil, err } return ssh.NewClient(conn, chans, reqs), nil } func (s *server) Dial(config *ssh.ClientConfig) *ssh.Client { conn, err := s.TryDial(config) if err != nil { s.t.Fail() s.Shutdown() s.t.Fatalf("ssh.Client: %v", err) } return conn } func (s *server) Shutdown() { if s.cmd != nil && s.cmd.Process != nil { // Don't check for errors; if it fails it's most // likely "os: process already finished", and we don't // care about that. Use os.Interrupt, so child // processes are killed too. s.cmd.Process.Signal(os.Interrupt) s.cmd.Wait() } if s.t.Failed() { // log any output from sshd process s.t.Logf("sshd: %s", s.output.String()) } s.cleanup() } func writeFile(path string, contents []byte) { f, err := os.OpenFile(path, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0600) if err != nil { panic(err) } defer f.Close() if _, err := f.Write(contents); err != nil { panic(err) } } // newServer returns a new mock ssh server. func newServer(t *testing.T) *server { if testing.Short() { t.Skip("skipping test due to -short") } dir, err := ioutil.TempDir("", "sshtest") if err != nil { t.Fatal(err) } f, err := os.Create(filepath.Join(dir, "sshd_config")) if err != nil { t.Fatal(err) } err = configTmpl.Execute(f, map[string]string{ "Dir": dir, }) if err != nil { t.Fatal(err) } f.Close() for k, v := range testdata.PEMBytes { filename := "id_" + k writeFile(filepath.Join(dir, filename), v) writeFile(filepath.Join(dir, filename+".pub"), ssh.MarshalAuthorizedKey(testPublicKeys[k])) } return &server{ t: t, configfile: f.Name(), cleanup: func() { if err := os.RemoveAll(dir); err != nil { t.Error(err) } }, } } lxd-2.0.0/dist/src/golang.org/x/crypto/ssh/test/testdata_test.go0000644061062106075000000000425612702772344027256 0ustar00stgraberdomain admins00000000000000// Copyright 2014 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. // IMPLEMENTOR NOTE: To avoid a package loop, this file is in three places: // ssh/, ssh/agent, and ssh/test/. It should be kept in sync across all three // instances. package test import ( "crypto/rand" "fmt" "golang.org/x/crypto/ssh" "golang.org/x/crypto/ssh/testdata" ) var ( testPrivateKeys map[string]interface{} testSigners map[string]ssh.Signer testPublicKeys map[string]ssh.PublicKey ) func init() { var err error n := len(testdata.PEMBytes) testPrivateKeys = make(map[string]interface{}, n) testSigners = make(map[string]ssh.Signer, n) testPublicKeys = make(map[string]ssh.PublicKey, n) for t, k := range testdata.PEMBytes { testPrivateKeys[t], err = ssh.ParseRawPrivateKey(k) if err != nil { panic(fmt.Sprintf("Unable to parse test key %s: %v", t, err)) } testSigners[t], err = ssh.NewSignerFromKey(testPrivateKeys[t]) if err != nil { panic(fmt.Sprintf("Unable to create signer for test key %s: %v", t, err)) } testPublicKeys[t] = testSigners[t].PublicKey() } // Create a cert and sign it for use in tests. testCert := &ssh.Certificate{ Nonce: []byte{}, // To pass reflect.DeepEqual after marshal & parse, this must be non-nil ValidPrincipals: []string{"gopher1", "gopher2"}, // increases test coverage ValidAfter: 0, // unix epoch ValidBefore: ssh.CertTimeInfinity, // The end of currently representable time. Reserved: []byte{}, // To pass reflect.DeepEqual after marshal & parse, this must be non-nil Key: testPublicKeys["ecdsa"], SignatureKey: testPublicKeys["rsa"], Permissions: ssh.Permissions{ CriticalOptions: map[string]string{}, Extensions: map[string]string{}, }, } testCert.SignCert(rand.Reader, testSigners["rsa"]) testPrivateKeys["cert"] = testPrivateKeys["ecdsa"] testSigners["cert"], err = ssh.NewCertSigner(testCert, testSigners["ecdsa"]) if err != nil { panic(fmt.Sprintf("Unable to create certificate signer: %v", err)) } } lxd-2.0.0/dist/src/golang.org/x/crypto/ssh/test/forward_unix_test.go0000644061062106075000000000634112702772344030151 0ustar00stgraberdomain admins00000000000000// Copyright 2012 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. // +build darwin dragonfly freebsd linux netbsd openbsd package test import ( "bytes" "io" "io/ioutil" "math/rand" "net" "testing" "time" ) func TestPortForward(t *testing.T) { server := newServer(t) defer server.Shutdown() conn := server.Dial(clientConfig()) defer conn.Close() sshListener, err := conn.Listen("tcp", "localhost:0") if err != nil { t.Fatal(err) } go func() { sshConn, err := sshListener.Accept() if err != nil { t.Fatalf("listen.Accept failed: %v", err) } _, err = io.Copy(sshConn, sshConn) if err != nil && err != io.EOF { t.Fatalf("ssh client copy: %v", err) } sshConn.Close() }() forwardedAddr := sshListener.Addr().String() tcpConn, err := net.Dial("tcp", forwardedAddr) if err != nil { t.Fatalf("TCP dial failed: %v", err) } readChan := make(chan []byte) go func() { data, _ := ioutil.ReadAll(tcpConn) readChan <- data }() // Invent some data. data := make([]byte, 100*1000) for i := range data { data[i] = byte(i % 255) } var sent []byte for len(sent) < 1000*1000 { // Send random sized chunks m := rand.Intn(len(data)) n, err := tcpConn.Write(data[:m]) if err != nil { break } sent = append(sent, data[:n]...) } if err := tcpConn.(*net.TCPConn).CloseWrite(); err != nil { t.Errorf("tcpConn.CloseWrite: %v", err) } read := <-readChan if len(sent) != len(read) { t.Fatalf("got %d bytes, want %d", len(read), len(sent)) } if bytes.Compare(sent, read) != 0 { t.Fatalf("read back data does not match") } if err := sshListener.Close(); err != nil { t.Fatalf("sshListener.Close: %v", err) } // Check that the forward disappeared. tcpConn, err = net.Dial("tcp", forwardedAddr) if err == nil { tcpConn.Close() t.Errorf("still listening to %s after closing", forwardedAddr) } } func TestAcceptClose(t *testing.T) { server := newServer(t) defer server.Shutdown() conn := server.Dial(clientConfig()) sshListener, err := conn.Listen("tcp", "localhost:0") if err != nil { t.Fatal(err) } quit := make(chan error, 1) go func() { for { c, err := sshListener.Accept() if err != nil { quit <- err break } c.Close() } }() sshListener.Close() select { case <-time.After(1 * time.Second): t.Errorf("timeout: listener did not close.") case err := <-quit: t.Logf("quit as expected (error %v)", err) } } // Check that listeners exit if the underlying client transport dies. func TestPortForwardConnectionClose(t *testing.T) { server := newServer(t) defer server.Shutdown() conn := server.Dial(clientConfig()) sshListener, err := conn.Listen("tcp", "localhost:0") if err != nil { t.Fatal(err) } quit := make(chan error, 1) go func() { for { c, err := sshListener.Accept() if err != nil { quit <- err break } c.Close() } }() // It would be even nicer if we closed the server side, but it // is more involved as the fd for that side is dup()ed. server.clientConn.Close() select { case <-time.After(1 * time.Second): t.Errorf("timeout: listener did not close.") case err := <-quit: t.Logf("quit as expected (error %v)", err) } } lxd-2.0.0/dist/src/golang.org/x/crypto/ssh/test/cert_test.go0000644061062106075000000000211012702772344026365 0ustar00stgraberdomain admins00000000000000// Copyright 2014 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. // +build darwin dragonfly freebsd linux netbsd openbsd package test import ( "crypto/rand" "testing" "golang.org/x/crypto/ssh" ) func TestCertLogin(t *testing.T) { s := newServer(t) defer s.Shutdown() // Use a key different from the default. clientKey := testSigners["dsa"] caAuthKey := testSigners["ecdsa"] cert := &ssh.Certificate{ Key: clientKey.PublicKey(), ValidPrincipals: []string{username()}, CertType: ssh.UserCert, ValidBefore: ssh.CertTimeInfinity, } if err := cert.SignCert(rand.Reader, caAuthKey); err != nil { t.Fatalf("SetSignature: %v", err) } certSigner, err := ssh.NewCertSigner(cert, clientKey) if err != nil { t.Fatalf("NewCertSigner: %v", err) } conf := &ssh.ClientConfig{ User: username(), } conf.Auth = append(conf.Auth, ssh.PublicKeys(certSigner)) client, err := s.TryDial(conf) if err != nil { t.Fatalf("TryDial: %v", err) } client.Close() } lxd-2.0.0/dist/src/golang.org/x/crypto/ssh/testdata_test.go0000644061062106075000000000415612702772344026276 0ustar00stgraberdomain admins00000000000000// Copyright 2014 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. // IMPLEMENTOR NOTE: To avoid a package loop, this file is in three places: // ssh/, ssh/agent, and ssh/test/. It should be kept in sync across all three // instances. package ssh import ( "crypto/rand" "fmt" "golang.org/x/crypto/ssh/testdata" ) var ( testPrivateKeys map[string]interface{} testSigners map[string]Signer testPublicKeys map[string]PublicKey ) func init() { var err error n := len(testdata.PEMBytes) testPrivateKeys = make(map[string]interface{}, n) testSigners = make(map[string]Signer, n) testPublicKeys = make(map[string]PublicKey, n) for t, k := range testdata.PEMBytes { testPrivateKeys[t], err = ParseRawPrivateKey(k) if err != nil { panic(fmt.Sprintf("Unable to parse test key %s: %v", t, err)) } testSigners[t], err = NewSignerFromKey(testPrivateKeys[t]) if err != nil { panic(fmt.Sprintf("Unable to create signer for test key %s: %v", t, err)) } testPublicKeys[t] = testSigners[t].PublicKey() } // Create a cert and sign it for use in tests. testCert := &Certificate{ Nonce: []byte{}, // To pass reflect.DeepEqual after marshal & parse, this must be non-nil ValidPrincipals: []string{"gopher1", "gopher2"}, // increases test coverage ValidAfter: 0, // unix epoch ValidBefore: CertTimeInfinity, // The end of currently representable time. Reserved: []byte{}, // To pass reflect.DeepEqual after marshal & parse, this must be non-nil Key: testPublicKeys["ecdsa"], SignatureKey: testPublicKeys["rsa"], Permissions: Permissions{ CriticalOptions: map[string]string{}, Extensions: map[string]string{}, }, } testCert.SignCert(rand.Reader, testSigners["rsa"]) testPrivateKeys["cert"] = testPrivateKeys["ecdsa"] testSigners["cert"], err = NewCertSigner(testCert, testSigners["ecdsa"]) if err != nil { panic(fmt.Sprintf("Unable to create certificate signer: %v", err)) } } lxd-2.0.0/dist/src/golang.org/x/crypto/ssh/doc.go0000644061062106075000000000141712702772344024170 0ustar00stgraberdomain admins00000000000000// 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 ssh implements an SSH client and server. SSH is a transport security protocol, an authentication protocol and a family of application protocols. The most typical application level protocol is a remote shell and this is specifically implemented. However, the multiplexed nature of SSH is exposed to users that wish to support others. References: [PROTOCOL.certkeys]: http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/PROTOCOL.certkeys?rev=HEAD [SSH-PARAMETERS]: http://www.iana.org/assignments/ssh-parameters/ssh-parameters.xml#ssh-parameters-1 */ package ssh // import "golang.org/x/crypto/ssh" lxd-2.0.0/dist/src/golang.org/x/crypto/ssh/benchmark_test.go0000644061062106075000000000430012702772344026406 0ustar00stgraberdomain admins00000000000000// Copyright 2013 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 ssh import ( "errors" "io" "net" "testing" ) type server struct { *ServerConn chans <-chan NewChannel } func newServer(c net.Conn, conf *ServerConfig) (*server, error) { sconn, chans, reqs, err := NewServerConn(c, conf) if err != nil { return nil, err } go DiscardRequests(reqs) return &server{sconn, chans}, nil } func (s *server) Accept() (NewChannel, error) { n, ok := <-s.chans if !ok { return nil, io.EOF } return n, nil } func sshPipe() (Conn, *server, error) { c1, c2, err := netPipe() if err != nil { return nil, nil, err } clientConf := ClientConfig{ User: "user", } serverConf := ServerConfig{ NoClientAuth: true, } serverConf.AddHostKey(testSigners["ecdsa"]) done := make(chan *server, 1) go func() { server, err := newServer(c2, &serverConf) if err != nil { done <- nil } done <- server }() client, _, reqs, err := NewClientConn(c1, "", &clientConf) if err != nil { return nil, nil, err } server := <-done if server == nil { return nil, nil, errors.New("server handshake failed.") } go DiscardRequests(reqs) return client, server, nil } func BenchmarkEndToEnd(b *testing.B) { b.StopTimer() client, server, err := sshPipe() if err != nil { b.Fatalf("sshPipe: %v", err) } defer client.Close() defer server.Close() size := (1 << 20) input := make([]byte, size) output := make([]byte, size) b.SetBytes(int64(size)) done := make(chan int, 1) go func() { newCh, err := server.Accept() if err != nil { b.Fatalf("Client: %v", err) } ch, incoming, err := newCh.Accept() go DiscardRequests(incoming) for i := 0; i < b.N; i++ { if _, err := io.ReadFull(ch, output); err != nil { b.Fatalf("ReadFull: %v", err) } } ch.Close() done <- 1 }() ch, in, err := client.OpenChannel("speed", nil) if err != nil { b.Fatalf("OpenChannel: %v", err) } go DiscardRequests(in) b.ResetTimer() b.StartTimer() for i := 0; i < b.N; i++ { if _, err := ch.Write(input); err != nil { b.Fatalf("WriteFull: %v", err) } } ch.Close() b.StopTimer() <-done } lxd-2.0.0/dist/src/golang.org/x/crypto/ssh/keys_test.go0000644061062106075000000002634312702772344025442 0ustar00stgraberdomain admins00000000000000// Copyright 2014 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 ssh import ( "bytes" "crypto/dsa" "crypto/ecdsa" "crypto/elliptic" "crypto/rand" "crypto/rsa" "encoding/base64" "fmt" "reflect" "strings" "testing" "golang.org/x/crypto/ssh/testdata" ) func rawKey(pub PublicKey) interface{} { switch k := pub.(type) { case *rsaPublicKey: return (*rsa.PublicKey)(k) case *dsaPublicKey: return (*dsa.PublicKey)(k) case *ecdsaPublicKey: return (*ecdsa.PublicKey)(k) case *Certificate: return k } panic("unknown key type") } func TestKeyMarshalParse(t *testing.T) { for _, priv := range testSigners { pub := priv.PublicKey() roundtrip, err := ParsePublicKey(pub.Marshal()) if err != nil { t.Errorf("ParsePublicKey(%T): %v", pub, err) } k1 := rawKey(pub) k2 := rawKey(roundtrip) if !reflect.DeepEqual(k1, k2) { t.Errorf("got %#v in roundtrip, want %#v", k2, k1) } } } func TestUnsupportedCurves(t *testing.T) { raw, err := ecdsa.GenerateKey(elliptic.P224(), rand.Reader) if err != nil { t.Fatalf("GenerateKey: %v", err) } if _, err = NewSignerFromKey(raw); err == nil || !strings.Contains(err.Error(), "only P-256") { t.Fatalf("NewPrivateKey should not succeed with P-224, got: %v", err) } if _, err = NewPublicKey(&raw.PublicKey); err == nil || !strings.Contains(err.Error(), "only P-256") { t.Fatalf("NewPublicKey should not succeed with P-224, got: %v", err) } } func TestNewPublicKey(t *testing.T) { for _, k := range testSigners { raw := rawKey(k.PublicKey()) // Skip certificates, as NewPublicKey does not support them. if _, ok := raw.(*Certificate); ok { continue } pub, err := NewPublicKey(raw) if err != nil { t.Errorf("NewPublicKey(%#v): %v", raw, err) } if !reflect.DeepEqual(k.PublicKey(), pub) { t.Errorf("NewPublicKey(%#v) = %#v, want %#v", raw, pub, k.PublicKey()) } } } func TestKeySignVerify(t *testing.T) { for _, priv := range testSigners { pub := priv.PublicKey() data := []byte("sign me") sig, err := priv.Sign(rand.Reader, data) if err != nil { t.Fatalf("Sign(%T): %v", priv, err) } if err := pub.Verify(data, sig); err != nil { t.Errorf("publicKey.Verify(%T): %v", priv, err) } sig.Blob[5]++ if err := pub.Verify(data, sig); err == nil { t.Errorf("publicKey.Verify on broken sig did not fail") } } } func TestParseRSAPrivateKey(t *testing.T) { key := testPrivateKeys["rsa"] rsa, ok := key.(*rsa.PrivateKey) if !ok { t.Fatalf("got %T, want *rsa.PrivateKey", rsa) } if err := rsa.Validate(); err != nil { t.Errorf("Validate: %v", err) } } func TestParseECPrivateKey(t *testing.T) { key := testPrivateKeys["ecdsa"] ecKey, ok := key.(*ecdsa.PrivateKey) if !ok { t.Fatalf("got %T, want *ecdsa.PrivateKey", ecKey) } if !validateECPublicKey(ecKey.Curve, ecKey.X, ecKey.Y) { t.Fatalf("public key does not validate.") } } func TestParseDSA(t *testing.T) { // We actually exercise the ParsePrivateKey codepath here, as opposed to // using the ParseRawPrivateKey+NewSignerFromKey path that testdata_test.go // uses. s, err := ParsePrivateKey(testdata.PEMBytes["dsa"]) if err != nil { t.Fatalf("ParsePrivateKey returned error: %s", err) } data := []byte("sign me") sig, err := s.Sign(rand.Reader, data) if err != nil { t.Fatalf("dsa.Sign: %v", err) } if err := s.PublicKey().Verify(data, sig); err != nil { t.Errorf("Verify failed: %v", err) } } // Tests for authorized_keys parsing. // getTestKey returns a public key, and its base64 encoding. func getTestKey() (PublicKey, string) { k := testPublicKeys["rsa"] b := &bytes.Buffer{} e := base64.NewEncoder(base64.StdEncoding, b) e.Write(k.Marshal()) e.Close() return k, b.String() } func TestMarshalParsePublicKey(t *testing.T) { pub, pubSerialized := getTestKey() line := fmt.Sprintf("%s %s user@host", pub.Type(), pubSerialized) authKeys := MarshalAuthorizedKey(pub) actualFields := strings.Fields(string(authKeys)) if len(actualFields) == 0 { t.Fatalf("failed authKeys: %v", authKeys) } // drop the comment expectedFields := strings.Fields(line)[0:2] if !reflect.DeepEqual(actualFields, expectedFields) { t.Errorf("got %v, expected %v", actualFields, expectedFields) } actPub, _, _, _, err := ParseAuthorizedKey([]byte(line)) if err != nil { t.Fatalf("cannot parse %v: %v", line, err) } if !reflect.DeepEqual(actPub, pub) { t.Errorf("got %v, expected %v", actPub, pub) } } type authResult struct { pubKey PublicKey options []string comments string rest string ok bool } func testAuthorizedKeys(t *testing.T, authKeys []byte, expected []authResult) { rest := authKeys var values []authResult for len(rest) > 0 { var r authResult var err error r.pubKey, r.comments, r.options, rest, err = ParseAuthorizedKey(rest) r.ok = (err == nil) t.Log(err) r.rest = string(rest) values = append(values, r) } if !reflect.DeepEqual(values, expected) { t.Errorf("got %#v, expected %#v", values, expected) } } func TestAuthorizedKeyBasic(t *testing.T) { pub, pubSerialized := getTestKey() line := "ssh-rsa " + pubSerialized + " user@host" testAuthorizedKeys(t, []byte(line), []authResult{ {pub, nil, "user@host", "", true}, }) } func TestAuth(t *testing.T) { pub, pubSerialized := getTestKey() authWithOptions := []string{ `# comments to ignore before any keys...`, ``, `env="HOME=/home/root",no-port-forwarding ssh-rsa ` + pubSerialized + ` user@host`, `# comments to ignore, along with a blank line`, ``, `env="HOME=/home/root2" ssh-rsa ` + pubSerialized + ` user2@host2`, ``, `# more comments, plus a invalid entry`, `ssh-rsa data-that-will-not-parse user@host3`, } for _, eol := range []string{"\n", "\r\n"} { authOptions := strings.Join(authWithOptions, eol) rest2 := strings.Join(authWithOptions[3:], eol) rest3 := strings.Join(authWithOptions[6:], eol) testAuthorizedKeys(t, []byte(authOptions), []authResult{ {pub, []string{`env="HOME=/home/root"`, "no-port-forwarding"}, "user@host", rest2, true}, {pub, []string{`env="HOME=/home/root2"`}, "user2@host2", rest3, true}, {nil, nil, "", "", false}, }) } } func TestAuthWithQuotedSpaceInEnv(t *testing.T) { pub, pubSerialized := getTestKey() authWithQuotedSpaceInEnv := []byte(`env="HOME=/home/root dir",no-port-forwarding ssh-rsa ` + pubSerialized + ` user@host`) testAuthorizedKeys(t, []byte(authWithQuotedSpaceInEnv), []authResult{ {pub, []string{`env="HOME=/home/root dir"`, "no-port-forwarding"}, "user@host", "", true}, }) } func TestAuthWithQuotedCommaInEnv(t *testing.T) { pub, pubSerialized := getTestKey() authWithQuotedCommaInEnv := []byte(`env="HOME=/home/root,dir",no-port-forwarding ssh-rsa ` + pubSerialized + ` user@host`) testAuthorizedKeys(t, []byte(authWithQuotedCommaInEnv), []authResult{ {pub, []string{`env="HOME=/home/root,dir"`, "no-port-forwarding"}, "user@host", "", true}, }) } func TestAuthWithQuotedQuoteInEnv(t *testing.T) { pub, pubSerialized := getTestKey() authWithQuotedQuoteInEnv := []byte(`env="HOME=/home/\"root dir",no-port-forwarding` + "\t" + `ssh-rsa` + "\t" + pubSerialized + ` user@host`) authWithDoubleQuotedQuote := []byte(`no-port-forwarding,env="HOME=/home/ \"root dir\"" ssh-rsa ` + pubSerialized + "\t" + `user@host`) testAuthorizedKeys(t, []byte(authWithQuotedQuoteInEnv), []authResult{ {pub, []string{`env="HOME=/home/\"root dir"`, "no-port-forwarding"}, "user@host", "", true}, }) testAuthorizedKeys(t, []byte(authWithDoubleQuotedQuote), []authResult{ {pub, []string{"no-port-forwarding", `env="HOME=/home/ \"root dir\""`}, "user@host", "", true}, }) } func TestAuthWithInvalidSpace(t *testing.T) { _, pubSerialized := getTestKey() authWithInvalidSpace := []byte(`env="HOME=/home/root dir", no-port-forwarding ssh-rsa ` + pubSerialized + ` user@host #more to follow but still no valid keys`) testAuthorizedKeys(t, []byte(authWithInvalidSpace), []authResult{ {nil, nil, "", "", false}, }) } func TestAuthWithMissingQuote(t *testing.T) { pub, pubSerialized := getTestKey() authWithMissingQuote := []byte(`env="HOME=/home/root,no-port-forwarding ssh-rsa ` + pubSerialized + ` user@host env="HOME=/home/root",shared-control ssh-rsa ` + pubSerialized + ` user@host`) testAuthorizedKeys(t, []byte(authWithMissingQuote), []authResult{ {pub, []string{`env="HOME=/home/root"`, `shared-control`}, "user@host", "", true}, }) } func TestInvalidEntry(t *testing.T) { authInvalid := []byte(`ssh-rsa`) _, _, _, _, err := ParseAuthorizedKey(authInvalid) if err == nil { t.Errorf("got valid entry for %q", authInvalid) } } var knownHostsParseTests = []struct { input string err string marker string comment string hosts []string rest string } { { "", "EOF", "", "", nil, "", }, { "# Just a comment", "EOF", "", "", nil, "", }, { " \t ", "EOF", "", "", nil, "", }, { "localhost ssh-rsa {RSAPUB}", "", "", "", []string{"localhost"}, "", }, { "localhost\tssh-rsa {RSAPUB}", "", "", "", []string{"localhost"}, "", }, { "localhost\tssh-rsa {RSAPUB}\tcomment comment", "", "", "comment comment", []string{"localhost"}, "", }, { "localhost\tssh-rsa {RSAPUB}\tcomment comment\n", "", "", "comment comment", []string{"localhost"}, "", }, { "localhost\tssh-rsa {RSAPUB}\tcomment comment\r\n", "", "", "comment comment", []string{"localhost"}, "", }, { "localhost\tssh-rsa {RSAPUB}\tcomment comment\r\nnext line", "", "", "comment comment", []string{"localhost"}, "next line", }, { "localhost,[host2:123]\tssh-rsa {RSAPUB}\tcomment comment", "", "", "comment comment", []string{"localhost","[host2:123]"}, "", }, { "@marker \tlocalhost,[host2:123]\tssh-rsa {RSAPUB}", "", "marker", "", []string{"localhost","[host2:123]"}, "", }, { "@marker \tlocalhost,[host2:123]\tssh-rsa aabbccdd", "short read", "", "", nil, "", }, } func TestKnownHostsParsing(t *testing.T) { rsaPub, rsaPubSerialized := getTestKey() for i, test := range knownHostsParseTests { var expectedKey PublicKey const rsaKeyToken = "{RSAPUB}" input := test.input if strings.Contains(input, rsaKeyToken) { expectedKey = rsaPub input = strings.Replace(test.input, rsaKeyToken, rsaPubSerialized, -1) } marker, hosts, pubKey, comment, rest, err := ParseKnownHosts([]byte(input)) if err != nil { if len(test.err) == 0 { t.Errorf("#%d: unexpectedly failed with %q", i, err) } else if !strings.Contains(err.Error(), test.err) { t.Errorf("#%d: expected error containing %q, but got %q", i, test.err, err) } continue } else if len(test.err) != 0 { t.Errorf("#%d: succeeded but expected error including %q", i, test.err) continue } if !reflect.DeepEqual(expectedKey, pubKey) { t.Errorf("#%d: expected key %#v, but got %#v", i, expectedKey, pubKey) } if marker != test.marker { t.Errorf("#%d: expected marker %q, but got %q", i, test.marker, marker) } if comment != test.comment { t.Errorf("#%d: expected comment %q, but got %q", i, test.comment, comment) } if !reflect.DeepEqual(test.hosts, hosts) { t.Errorf("#%d: expected hosts %#v, but got %#v", i, test.hosts, hosts) } if rest := string(rest); rest != test.rest { t.Errorf("#%d: expected remaining input to be %q, but got %q", i, test.rest, rest) } } } lxd-2.0.0/dist/src/golang.org/x/crypto/ssh/server.go0000644061062106075000000003500112702772344024725 0ustar00stgraberdomain admins00000000000000// 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 ssh import ( "bytes" "errors" "fmt" "io" "net" ) // The Permissions type holds fine-grained permissions that are // specific to a user or a specific authentication method for a // user. Permissions, except for "source-address", must be enforced in // the server application layer, after successful authentication. The // Permissions are passed on in ServerConn so a server implementation // can honor them. type Permissions struct { // Critical options restrict default permissions. Common // restrictions are "source-address" and "force-command". If // the server cannot enforce the restriction, or does not // recognize it, the user should not authenticate. CriticalOptions map[string]string // Extensions are extra functionality that the server may // offer on authenticated connections. Common extensions are // "permit-agent-forwarding", "permit-X11-forwarding". Lack of // support for an extension does not preclude authenticating a // user. Extensions map[string]string } // ServerConfig holds server specific configuration data. type ServerConfig struct { // Config contains configuration shared between client and server. Config hostKeys []Signer // NoClientAuth is true if clients are allowed to connect without // authenticating. NoClientAuth bool // PasswordCallback, if non-nil, is called when a user // attempts to authenticate using a password. PasswordCallback func(conn ConnMetadata, password []byte) (*Permissions, error) // PublicKeyCallback, if non-nil, is called when a client attempts public // key authentication. It must return true if the given public key is // valid for the given user. For example, see CertChecker.Authenticate. PublicKeyCallback func(conn ConnMetadata, key PublicKey) (*Permissions, error) // KeyboardInteractiveCallback, if non-nil, is called when // keyboard-interactive authentication is selected (RFC // 4256). The client object's Challenge function should be // used to query the user. The callback may offer multiple // Challenge rounds. To avoid information leaks, the client // should be presented a challenge even if the user is // unknown. KeyboardInteractiveCallback func(conn ConnMetadata, client KeyboardInteractiveChallenge) (*Permissions, error) // AuthLogCallback, if non-nil, is called to log all authentication // attempts. AuthLogCallback func(conn ConnMetadata, method string, err error) // ServerVersion is the version identification string to announce in // the public handshake. // If empty, a reasonable default is used. // Note that RFC 4253 section 4.2 requires that this string start with // "SSH-2.0-". ServerVersion string } // AddHostKey adds a private key as a host key. If an existing host // key exists with the same algorithm, it is overwritten. Each server // config must have at least one host key. func (s *ServerConfig) AddHostKey(key Signer) { for i, k := range s.hostKeys { if k.PublicKey().Type() == key.PublicKey().Type() { s.hostKeys[i] = key return } } s.hostKeys = append(s.hostKeys, key) } // cachedPubKey contains the results of querying whether a public key is // acceptable for a user. type cachedPubKey struct { user string pubKeyData []byte result error perms *Permissions } const maxCachedPubKeys = 16 // pubKeyCache caches tests for public keys. Since SSH clients // will query whether a public key is acceptable before attempting to // authenticate with it, we end up with duplicate queries for public // key validity. The cache only applies to a single ServerConn. type pubKeyCache struct { keys []cachedPubKey } // get returns the result for a given user/algo/key tuple. func (c *pubKeyCache) get(user string, pubKeyData []byte) (cachedPubKey, bool) { for _, k := range c.keys { if k.user == user && bytes.Equal(k.pubKeyData, pubKeyData) { return k, true } } return cachedPubKey{}, false } // add adds the given tuple to the cache. func (c *pubKeyCache) add(candidate cachedPubKey) { if len(c.keys) < maxCachedPubKeys { c.keys = append(c.keys, candidate) } } // ServerConn is an authenticated SSH connection, as seen from the // server type ServerConn struct { Conn // If the succeeding authentication callback returned a // non-nil Permissions pointer, it is stored here. Permissions *Permissions } // NewServerConn starts a new SSH server with c as the underlying // transport. It starts with a handshake and, if the handshake is // unsuccessful, it closes the connection and returns an error. The // Request and NewChannel channels must be serviced, or the connection // will hang. func NewServerConn(c net.Conn, config *ServerConfig) (*ServerConn, <-chan NewChannel, <-chan *Request, error) { fullConf := *config fullConf.SetDefaults() s := &connection{ sshConn: sshConn{conn: c}, } perms, err := s.serverHandshake(&fullConf) if err != nil { c.Close() return nil, nil, nil, err } return &ServerConn{s, perms}, s.mux.incomingChannels, s.mux.incomingRequests, nil } // signAndMarshal signs the data with the appropriate algorithm, // and serializes the result in SSH wire format. func signAndMarshal(k Signer, rand io.Reader, data []byte) ([]byte, error) { sig, err := k.Sign(rand, data) if err != nil { return nil, err } return Marshal(sig), nil } // handshake performs key exchange and user authentication. func (s *connection) serverHandshake(config *ServerConfig) (*Permissions, error) { if len(config.hostKeys) == 0 { return nil, errors.New("ssh: server has no host keys") } if !config.NoClientAuth && config.PasswordCallback == nil && config.PublicKeyCallback == nil && config.KeyboardInteractiveCallback == nil { return nil, errors.New("ssh: no authentication methods configured but NoClientAuth is also false") } if config.ServerVersion != "" { s.serverVersion = []byte(config.ServerVersion) } else { s.serverVersion = []byte(packageVersion) } var err error s.clientVersion, err = exchangeVersions(s.sshConn.conn, s.serverVersion) if err != nil { return nil, err } tr := newTransport(s.sshConn.conn, config.Rand, false /* not client */) s.transport = newServerTransport(tr, s.clientVersion, s.serverVersion, config) if err := s.transport.requestKeyChange(); err != nil { return nil, err } if packet, err := s.transport.readPacket(); err != nil { return nil, err } else if packet[0] != msgNewKeys { return nil, unexpectedMessageError(msgNewKeys, packet[0]) } // We just did the key change, so the session ID is established. s.sessionID = s.transport.getSessionID() var packet []byte if packet, err = s.transport.readPacket(); err != nil { return nil, err } var serviceRequest serviceRequestMsg if err = Unmarshal(packet, &serviceRequest); err != nil { return nil, err } if serviceRequest.Service != serviceUserAuth { return nil, errors.New("ssh: requested service '" + serviceRequest.Service + "' before authenticating") } serviceAccept := serviceAcceptMsg{ Service: serviceUserAuth, } if err := s.transport.writePacket(Marshal(&serviceAccept)); err != nil { return nil, err } perms, err := s.serverAuthenticate(config) if err != nil { return nil, err } s.mux = newMux(s.transport) return perms, err } func isAcceptableAlgo(algo string) bool { switch algo { case KeyAlgoRSA, KeyAlgoDSA, KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521, CertAlgoRSAv01, CertAlgoDSAv01, CertAlgoECDSA256v01, CertAlgoECDSA384v01, CertAlgoECDSA521v01: return true } return false } func checkSourceAddress(addr net.Addr, sourceAddr string) error { if addr == nil { return errors.New("ssh: no address known for client, but source-address match required") } tcpAddr, ok := addr.(*net.TCPAddr) if !ok { return fmt.Errorf("ssh: remote address %v is not an TCP address when checking source-address match", addr) } if allowedIP := net.ParseIP(sourceAddr); allowedIP != nil { if bytes.Equal(allowedIP, tcpAddr.IP) { return nil } } else { _, ipNet, err := net.ParseCIDR(sourceAddr) if err != nil { return fmt.Errorf("ssh: error parsing source-address restriction %q: %v", sourceAddr, err) } if ipNet.Contains(tcpAddr.IP) { return nil } } return fmt.Errorf("ssh: remote address %v is not allowed because of source-address restriction", addr) } func (s *connection) serverAuthenticate(config *ServerConfig) (*Permissions, error) { var err error var cache pubKeyCache var perms *Permissions userAuthLoop: for { var userAuthReq userAuthRequestMsg if packet, err := s.transport.readPacket(); err != nil { return nil, err } else if err = Unmarshal(packet, &userAuthReq); err != nil { return nil, err } if userAuthReq.Service != serviceSSH { return nil, errors.New("ssh: client attempted to negotiate for unknown service: " + userAuthReq.Service) } s.user = userAuthReq.User perms = nil authErr := errors.New("no auth passed yet") switch userAuthReq.Method { case "none": if config.NoClientAuth { s.user = "" authErr = nil } case "password": if config.PasswordCallback == nil { authErr = errors.New("ssh: password auth not configured") break } payload := userAuthReq.Payload if len(payload) < 1 || payload[0] != 0 { return nil, parseError(msgUserAuthRequest) } payload = payload[1:] password, payload, ok := parseString(payload) if !ok || len(payload) > 0 { return nil, parseError(msgUserAuthRequest) } perms, authErr = config.PasswordCallback(s, password) case "keyboard-interactive": if config.KeyboardInteractiveCallback == nil { authErr = errors.New("ssh: keyboard-interactive auth not configubred") break } prompter := &sshClientKeyboardInteractive{s} perms, authErr = config.KeyboardInteractiveCallback(s, prompter.Challenge) case "publickey": if config.PublicKeyCallback == nil { authErr = errors.New("ssh: publickey auth not configured") break } payload := userAuthReq.Payload if len(payload) < 1 { return nil, parseError(msgUserAuthRequest) } isQuery := payload[0] == 0 payload = payload[1:] algoBytes, payload, ok := parseString(payload) if !ok { return nil, parseError(msgUserAuthRequest) } algo := string(algoBytes) if !isAcceptableAlgo(algo) { authErr = fmt.Errorf("ssh: algorithm %q not accepted", algo) break } pubKeyData, payload, ok := parseString(payload) if !ok { return nil, parseError(msgUserAuthRequest) } pubKey, err := ParsePublicKey(pubKeyData) if err != nil { return nil, err } candidate, ok := cache.get(s.user, pubKeyData) if !ok { candidate.user = s.user candidate.pubKeyData = pubKeyData candidate.perms, candidate.result = config.PublicKeyCallback(s, pubKey) if candidate.result == nil && candidate.perms != nil && candidate.perms.CriticalOptions != nil && candidate.perms.CriticalOptions[sourceAddressCriticalOption] != "" { candidate.result = checkSourceAddress( s.RemoteAddr(), candidate.perms.CriticalOptions[sourceAddressCriticalOption]) } cache.add(candidate) } if isQuery { // The client can query if the given public key // would be okay. if len(payload) > 0 { return nil, parseError(msgUserAuthRequest) } if candidate.result == nil { okMsg := userAuthPubKeyOkMsg{ Algo: algo, PubKey: pubKeyData, } if err = s.transport.writePacket(Marshal(&okMsg)); err != nil { return nil, err } continue userAuthLoop } authErr = candidate.result } else { sig, payload, ok := parseSignature(payload) if !ok || len(payload) > 0 { return nil, parseError(msgUserAuthRequest) } // Ensure the public key algo and signature algo // are supported. Compare the private key // algorithm name that corresponds to algo with // sig.Format. This is usually the same, but // for certs, the names differ. if !isAcceptableAlgo(sig.Format) { break } signedData := buildDataSignedForAuth(s.transport.getSessionID(), userAuthReq, algoBytes, pubKeyData) if err := pubKey.Verify(signedData, sig); err != nil { return nil, err } authErr = candidate.result perms = candidate.perms } default: authErr = fmt.Errorf("ssh: unknown method %q", userAuthReq.Method) } if config.AuthLogCallback != nil { config.AuthLogCallback(s, userAuthReq.Method, authErr) } if authErr == nil { break userAuthLoop } var failureMsg userAuthFailureMsg if config.PasswordCallback != nil { failureMsg.Methods = append(failureMsg.Methods, "password") } if config.PublicKeyCallback != nil { failureMsg.Methods = append(failureMsg.Methods, "publickey") } if config.KeyboardInteractiveCallback != nil { failureMsg.Methods = append(failureMsg.Methods, "keyboard-interactive") } if len(failureMsg.Methods) == 0 { return nil, errors.New("ssh: no authentication methods configured but NoClientAuth is also false") } if err = s.transport.writePacket(Marshal(&failureMsg)); err != nil { return nil, err } } if err = s.transport.writePacket([]byte{msgUserAuthSuccess}); err != nil { return nil, err } return perms, nil } // sshClientKeyboardInteractive implements a ClientKeyboardInteractive by // asking the client on the other side of a ServerConn. type sshClientKeyboardInteractive struct { *connection } func (c *sshClientKeyboardInteractive) Challenge(user, instruction string, questions []string, echos []bool) (answers []string, err error) { if len(questions) != len(echos) { return nil, errors.New("ssh: echos and questions must have equal length") } var prompts []byte for i := range questions { prompts = appendString(prompts, questions[i]) prompts = appendBool(prompts, echos[i]) } if err := c.transport.writePacket(Marshal(&userAuthInfoRequestMsg{ Instruction: instruction, NumPrompts: uint32(len(questions)), Prompts: prompts, })); err != nil { return nil, err } packet, err := c.transport.readPacket() if err != nil { return nil, err } if packet[0] != msgUserAuthInfoResponse { return nil, unexpectedMessageError(msgUserAuthInfoResponse, packet[0]) } packet = packet[1:] n, packet, ok := parseUint32(packet) if !ok || int(n) != len(questions) { return nil, parseError(msgUserAuthInfoResponse) } for i := uint32(0); i < n; i++ { ans, rest, ok := parseString(packet) if !ok { return nil, parseError(msgUserAuthInfoResponse) } answers = append(answers, string(ans)) packet = rest } if len(packet) != 0 { return nil, errors.New("ssh: junk at end of message") } return answers, nil } lxd-2.0.0/dist/src/golang.org/x/crypto/ssh/client.go0000644061062106075000000001463212702772344024704 0ustar00stgraberdomain admins00000000000000// 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 ssh import ( "errors" "fmt" "net" "sync" "time" ) // Client implements a traditional SSH client that supports shells, // subprocesses, port forwarding and tunneled dialing. type Client struct { Conn forwards forwardList // forwarded tcpip connections from the remote side mu sync.Mutex channelHandlers map[string]chan NewChannel } // HandleChannelOpen returns a channel on which NewChannel requests // for the given type are sent. If the type already is being handled, // nil is returned. The channel is closed when the connection is closed. func (c *Client) HandleChannelOpen(channelType string) <-chan NewChannel { c.mu.Lock() defer c.mu.Unlock() if c.channelHandlers == nil { // The SSH channel has been closed. c := make(chan NewChannel) close(c) return c } ch := c.channelHandlers[channelType] if ch != nil { return nil } ch = make(chan NewChannel, 16) c.channelHandlers[channelType] = ch return ch } // NewClient creates a Client on top of the given connection. func NewClient(c Conn, chans <-chan NewChannel, reqs <-chan *Request) *Client { conn := &Client{ Conn: c, channelHandlers: make(map[string]chan NewChannel, 1), } go conn.handleGlobalRequests(reqs) go conn.handleChannelOpens(chans) go func() { conn.Wait() conn.forwards.closeAll() }() go conn.forwards.handleChannels(conn.HandleChannelOpen("forwarded-tcpip")) return conn } // NewClientConn establishes an authenticated SSH connection using c // as the underlying transport. The Request and NewChannel channels // must be serviced or the connection will hang. func NewClientConn(c net.Conn, addr string, config *ClientConfig) (Conn, <-chan NewChannel, <-chan *Request, error) { fullConf := *config fullConf.SetDefaults() conn := &connection{ sshConn: sshConn{conn: c}, } if err := conn.clientHandshake(addr, &fullConf); err != nil { c.Close() return nil, nil, nil, fmt.Errorf("ssh: handshake failed: %v", err) } conn.mux = newMux(conn.transport) return conn, conn.mux.incomingChannels, conn.mux.incomingRequests, nil } // clientHandshake performs the client side key exchange. See RFC 4253 Section // 7. func (c *connection) clientHandshake(dialAddress string, config *ClientConfig) error { if config.ClientVersion != "" { c.clientVersion = []byte(config.ClientVersion) } else { c.clientVersion = []byte(packageVersion) } var err error c.serverVersion, err = exchangeVersions(c.sshConn.conn, c.clientVersion) if err != nil { return err } c.transport = newClientTransport( newTransport(c.sshConn.conn, config.Rand, true /* is client */), c.clientVersion, c.serverVersion, config, dialAddress, c.sshConn.RemoteAddr()) if err := c.transport.requestKeyChange(); err != nil { return err } if packet, err := c.transport.readPacket(); err != nil { return err } else if packet[0] != msgNewKeys { return unexpectedMessageError(msgNewKeys, packet[0]) } // We just did the key change, so the session ID is established. c.sessionID = c.transport.getSessionID() return c.clientAuthenticate(config) } // verifyHostKeySignature verifies the host key obtained in the key // exchange. func verifyHostKeySignature(hostKey PublicKey, result *kexResult) error { sig, rest, ok := parseSignatureBody(result.Signature) if len(rest) > 0 || !ok { return errors.New("ssh: signature parse error") } return hostKey.Verify(result.H, sig) } // NewSession opens a new Session for this client. (A session is a remote // execution of a program.) func (c *Client) NewSession() (*Session, error) { ch, in, err := c.OpenChannel("session", nil) if err != nil { return nil, err } return newSession(ch, in) } func (c *Client) handleGlobalRequests(incoming <-chan *Request) { for r := range incoming { // This handles keepalive messages and matches // the behaviour of OpenSSH. r.Reply(false, nil) } } // handleChannelOpens channel open messages from the remote side. func (c *Client) handleChannelOpens(in <-chan NewChannel) { for ch := range in { c.mu.Lock() handler := c.channelHandlers[ch.ChannelType()] c.mu.Unlock() if handler != nil { handler <- ch } else { ch.Reject(UnknownChannelType, fmt.Sprintf("unknown channel type: %v", ch.ChannelType())) } } c.mu.Lock() for _, ch := range c.channelHandlers { close(ch) } c.channelHandlers = nil c.mu.Unlock() } // Dial starts a client connection to the given SSH server. It is a // convenience function that connects to the given network address, // initiates the SSH handshake, and then sets up a Client. For access // to incoming channels and requests, use net.Dial with NewClientConn // instead. func Dial(network, addr string, config *ClientConfig) (*Client, error) { conn, err := net.DialTimeout(network, addr, config.Timeout) if err != nil { return nil, err } c, chans, reqs, err := NewClientConn(conn, addr, config) if err != nil { return nil, err } return NewClient(c, chans, reqs), nil } // A ClientConfig structure is used to configure a Client. It must not be // modified after having been passed to an SSH function. type ClientConfig struct { // Config contains configuration that is shared between clients and // servers. Config // User contains the username to authenticate as. User string // Auth contains possible authentication methods to use with the // server. Only the first instance of a particular RFC 4252 method will // be used during authentication. Auth []AuthMethod // HostKeyCallback, if not nil, is called during the cryptographic // handshake to validate the server's host key. A nil HostKeyCallback // implies that all host keys are accepted. HostKeyCallback func(hostname string, remote net.Addr, key PublicKey) error // ClientVersion contains the version identification string that will // be used for the connection. If empty, a reasonable default is used. ClientVersion string // HostKeyAlgorithms lists the key types that the client will // accept from the server as host key, in order of // preference. If empty, a reasonable default is used. Any // string returned from PublicKey.Type method may be used, or // any of the CertAlgoXxxx and KeyAlgoXxxx constants. HostKeyAlgorithms []string // Timeout is the maximum amount of time for the TCP connection to establish. // // A Timeout of zero means no timeout. Timeout time.Duration } lxd-2.0.0/dist/src/golang.org/x/crypto/ssh/handshake_test.go0000644061062106075000000002503712702772344026414 0ustar00stgraberdomain admins00000000000000// Copyright 2013 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 ssh import ( "bytes" "crypto/rand" "errors" "fmt" "net" "reflect" "runtime" "strings" "sync" "testing" ) type testChecker struct { calls []string } func (t *testChecker) Check(dialAddr string, addr net.Addr, key PublicKey) error { if dialAddr == "bad" { return fmt.Errorf("dialAddr is bad") } if tcpAddr, ok := addr.(*net.TCPAddr); !ok || tcpAddr == nil { return fmt.Errorf("testChecker: got %T want *net.TCPAddr", addr) } t.calls = append(t.calls, fmt.Sprintf("%s %v %s %x", dialAddr, addr, key.Type(), key.Marshal())) return nil } // netPipe is analogous to net.Pipe, but it uses a real net.Conn, and // therefore is buffered (net.Pipe deadlocks if both sides start with // a write.) func netPipe() (net.Conn, net.Conn, error) { listener, err := net.Listen("tcp", "127.0.0.1:0") if err != nil { return nil, nil, err } defer listener.Close() c1, err := net.Dial("tcp", listener.Addr().String()) if err != nil { return nil, nil, err } c2, err := listener.Accept() if err != nil { c1.Close() return nil, nil, err } return c1, c2, nil } func handshakePair(clientConf *ClientConfig, addr string) (client *handshakeTransport, server *handshakeTransport, err error) { a, b, err := netPipe() if err != nil { return nil, nil, err } trC := newTransport(a, rand.Reader, true) trS := newTransport(b, rand.Reader, false) clientConf.SetDefaults() v := []byte("version") client = newClientTransport(trC, v, v, clientConf, addr, a.RemoteAddr()) serverConf := &ServerConfig{} serverConf.AddHostKey(testSigners["ecdsa"]) serverConf.AddHostKey(testSigners["rsa"]) serverConf.SetDefaults() server = newServerTransport(trS, v, v, serverConf) return client, server, nil } func TestHandshakeBasic(t *testing.T) { if runtime.GOOS == "plan9" { t.Skip("see golang.org/issue/7237") } checker := &testChecker{} trC, trS, err := handshakePair(&ClientConfig{HostKeyCallback: checker.Check}, "addr") if err != nil { t.Fatalf("handshakePair: %v", err) } defer trC.Close() defer trS.Close() go func() { // Client writes a bunch of stuff, and does a key // change in the middle. This should not confuse the // handshake in progress for i := 0; i < 10; i++ { p := []byte{msgRequestSuccess, byte(i)} if err := trC.writePacket(p); err != nil { t.Fatalf("sendPacket: %v", err) } if i == 5 { // halfway through, we request a key change. _, _, err := trC.sendKexInit() if err != nil { t.Fatalf("sendKexInit: %v", err) } } } trC.Close() }() // Server checks that client messages come in cleanly i := 0 for { p, err := trS.readPacket() if err != nil { break } if p[0] == msgNewKeys { continue } want := []byte{msgRequestSuccess, byte(i)} if bytes.Compare(p, want) != 0 { t.Errorf("message %d: got %q, want %q", i, p, want) } i++ } if i != 10 { t.Errorf("received %d messages, want 10.", i) } // If all went well, we registered exactly 1 key change. if len(checker.calls) != 1 { t.Fatalf("got %d host key checks, want 1", len(checker.calls)) } pub := testSigners["ecdsa"].PublicKey() want := fmt.Sprintf("%s %v %s %x", "addr", trC.remoteAddr, pub.Type(), pub.Marshal()) if want != checker.calls[0] { t.Errorf("got %q want %q for host key check", checker.calls[0], want) } } func TestHandshakeError(t *testing.T) { checker := &testChecker{} trC, trS, err := handshakePair(&ClientConfig{HostKeyCallback: checker.Check}, "bad") if err != nil { t.Fatalf("handshakePair: %v", err) } defer trC.Close() defer trS.Close() // send a packet packet := []byte{msgRequestSuccess, 42} if err := trC.writePacket(packet); err != nil { t.Errorf("writePacket: %v", err) } // Now request a key change. _, _, err = trC.sendKexInit() if err != nil { t.Errorf("sendKexInit: %v", err) } // the key change will fail, and afterwards we can't write. if err := trC.writePacket([]byte{msgRequestSuccess, 43}); err == nil { t.Errorf("writePacket after botched rekey succeeded.") } readback, err := trS.readPacket() if err != nil { t.Fatalf("server closed too soon: %v", err) } if bytes.Compare(readback, packet) != 0 { t.Errorf("got %q want %q", readback, packet) } readback, err = trS.readPacket() if err == nil { t.Errorf("got a message %q after failed key change", readback) } } func TestHandshakeTwice(t *testing.T) { checker := &testChecker{} trC, trS, err := handshakePair(&ClientConfig{HostKeyCallback: checker.Check}, "addr") if err != nil { t.Fatalf("handshakePair: %v", err) } defer trC.Close() defer trS.Close() // send a packet packet := make([]byte, 5) packet[0] = msgRequestSuccess if err := trC.writePacket(packet); err != nil { t.Errorf("writePacket: %v", err) } // Now request a key change. _, _, err = trC.sendKexInit() if err != nil { t.Errorf("sendKexInit: %v", err) } // Send another packet. Use a fresh one, since writePacket destroys. packet = make([]byte, 5) packet[0] = msgRequestSuccess if err := trC.writePacket(packet); err != nil { t.Errorf("writePacket: %v", err) } // 2nd key change. _, _, err = trC.sendKexInit() if err != nil { t.Errorf("sendKexInit: %v", err) } packet = make([]byte, 5) packet[0] = msgRequestSuccess if err := trC.writePacket(packet); err != nil { t.Errorf("writePacket: %v", err) } packet = make([]byte, 5) packet[0] = msgRequestSuccess for i := 0; i < 5; i++ { msg, err := trS.readPacket() if err != nil { t.Fatalf("server closed too soon: %v", err) } if msg[0] == msgNewKeys { continue } if bytes.Compare(msg, packet) != 0 { t.Errorf("packet %d: got %q want %q", i, msg, packet) } } if len(checker.calls) != 2 { t.Errorf("got %d key changes, want 2", len(checker.calls)) } } func TestHandshakeAutoRekeyWrite(t *testing.T) { checker := &testChecker{} clientConf := &ClientConfig{HostKeyCallback: checker.Check} clientConf.RekeyThreshold = 500 trC, trS, err := handshakePair(clientConf, "addr") if err != nil { t.Fatalf("handshakePair: %v", err) } defer trC.Close() defer trS.Close() for i := 0; i < 5; i++ { packet := make([]byte, 251) packet[0] = msgRequestSuccess if err := trC.writePacket(packet); err != nil { t.Errorf("writePacket: %v", err) } } j := 0 for ; j < 5; j++ { _, err := trS.readPacket() if err != nil { break } } if j != 5 { t.Errorf("got %d, want 5 messages", j) } if len(checker.calls) != 2 { t.Errorf("got %d key changes, wanted 2", len(checker.calls)) } } type syncChecker struct { called chan int } func (t *syncChecker) Check(dialAddr string, addr net.Addr, key PublicKey) error { t.called <- 1 return nil } func TestHandshakeAutoRekeyRead(t *testing.T) { sync := &syncChecker{make(chan int, 2)} clientConf := &ClientConfig{ HostKeyCallback: sync.Check, } clientConf.RekeyThreshold = 500 trC, trS, err := handshakePair(clientConf, "addr") if err != nil { t.Fatalf("handshakePair: %v", err) } defer trC.Close() defer trS.Close() packet := make([]byte, 501) packet[0] = msgRequestSuccess if err := trS.writePacket(packet); err != nil { t.Fatalf("writePacket: %v", err) } // While we read out the packet, a key change will be // initiated. if _, err := trC.readPacket(); err != nil { t.Fatalf("readPacket(client): %v", err) } <-sync.called } // errorKeyingTransport generates errors after a given number of // read/write operations. type errorKeyingTransport struct { packetConn readLeft, writeLeft int } func (n *errorKeyingTransport) prepareKeyChange(*algorithms, *kexResult) error { return nil } func (n *errorKeyingTransport) getSessionID() []byte { return nil } func (n *errorKeyingTransport) writePacket(packet []byte) error { if n.writeLeft == 0 { n.Close() return errors.New("barf") } n.writeLeft-- return n.packetConn.writePacket(packet) } func (n *errorKeyingTransport) readPacket() ([]byte, error) { if n.readLeft == 0 { n.Close() return nil, errors.New("barf") } n.readLeft-- return n.packetConn.readPacket() } func TestHandshakeErrorHandlingRead(t *testing.T) { for i := 0; i < 20; i++ { testHandshakeErrorHandlingN(t, i, -1) } } func TestHandshakeErrorHandlingWrite(t *testing.T) { for i := 0; i < 20; i++ { testHandshakeErrorHandlingN(t, -1, i) } } // testHandshakeErrorHandlingN runs handshakes, injecting errors. If // handshakeTransport deadlocks, the go runtime will detect it and // panic. func testHandshakeErrorHandlingN(t *testing.T, readLimit, writeLimit int) { msg := Marshal(&serviceRequestMsg{strings.Repeat("x", int(minRekeyThreshold)/4)}) a, b := memPipe() defer a.Close() defer b.Close() key := testSigners["ecdsa"] serverConf := Config{RekeyThreshold: minRekeyThreshold} serverConf.SetDefaults() serverConn := newHandshakeTransport(&errorKeyingTransport{a, readLimit, writeLimit}, &serverConf, []byte{'a'}, []byte{'b'}) serverConn.hostKeys = []Signer{key} go serverConn.readLoop() clientConf := Config{RekeyThreshold: 10 * minRekeyThreshold} clientConf.SetDefaults() clientConn := newHandshakeTransport(&errorKeyingTransport{b, -1, -1}, &clientConf, []byte{'a'}, []byte{'b'}) clientConn.hostKeyAlgorithms = []string{key.PublicKey().Type()} go clientConn.readLoop() var wg sync.WaitGroup wg.Add(4) for _, hs := range []packetConn{serverConn, clientConn} { go func(c packetConn) { for { err := c.writePacket(msg) if err != nil { break } } wg.Done() }(hs) go func(c packetConn) { for { _, err := c.readPacket() if err != nil { break } } wg.Done() }(hs) } wg.Wait() } func TestDisconnect(t *testing.T) { if runtime.GOOS == "plan9" { t.Skip("see golang.org/issue/7237") } checker := &testChecker{} trC, trS, err := handshakePair(&ClientConfig{HostKeyCallback: checker.Check}, "addr") if err != nil { t.Fatalf("handshakePair: %v", err) } defer trC.Close() defer trS.Close() trC.writePacket([]byte{msgRequestSuccess, 0, 0}) errMsg := &disconnectMsg{ Reason: 42, Message: "such is life", } trC.writePacket(Marshal(errMsg)) trC.writePacket([]byte{msgRequestSuccess, 0, 0}) packet, err := trS.readPacket() if err != nil { t.Fatalf("readPacket 1: %v", err) } if packet[0] != msgRequestSuccess { t.Errorf("got packet %v, want packet type %d", packet, msgRequestSuccess) } _, err = trS.readPacket() if err == nil { t.Errorf("readPacket 2 succeeded") } else if !reflect.DeepEqual(err, errMsg) { t.Errorf("got error %#v, want %#v", err, errMsg) } _, err = trS.readPacket() if err == nil { t.Errorf("readPacket 3 succeeded") } } lxd-2.0.0/dist/src/golang.org/x/crypto/ssh/messages_test.go0000644061062106075000000001274512702772344026277 0ustar00stgraberdomain admins00000000000000// 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 ssh import ( "bytes" "math/big" "math/rand" "reflect" "testing" "testing/quick" ) var intLengthTests = []struct { val, length int }{ {0, 4 + 0}, {1, 4 + 1}, {127, 4 + 1}, {128, 4 + 2}, {-1, 4 + 1}, } func TestIntLength(t *testing.T) { for _, test := range intLengthTests { v := new(big.Int).SetInt64(int64(test.val)) length := intLength(v) if length != test.length { t.Errorf("For %d, got length %d but expected %d", test.val, length, test.length) } } } type msgAllTypes struct { Bool bool `sshtype:"21"` Array [16]byte Uint64 uint64 Uint32 uint32 Uint8 uint8 String string Strings []string Bytes []byte Int *big.Int Rest []byte `ssh:"rest"` } func (t *msgAllTypes) Generate(rand *rand.Rand, size int) reflect.Value { m := &msgAllTypes{} m.Bool = rand.Intn(2) == 1 randomBytes(m.Array[:], rand) m.Uint64 = uint64(rand.Int63n(1<<63 - 1)) m.Uint32 = uint32(rand.Intn((1 << 31) - 1)) m.Uint8 = uint8(rand.Intn(1 << 8)) m.String = string(m.Array[:]) m.Strings = randomNameList(rand) m.Bytes = m.Array[:] m.Int = randomInt(rand) m.Rest = m.Array[:] return reflect.ValueOf(m) } func TestMarshalUnmarshal(t *testing.T) { rand := rand.New(rand.NewSource(0)) iface := &msgAllTypes{} ty := reflect.ValueOf(iface).Type() n := 100 if testing.Short() { n = 5 } for j := 0; j < n; j++ { v, ok := quick.Value(ty, rand) if !ok { t.Errorf("failed to create value") break } m1 := v.Elem().Interface() m2 := iface marshaled := Marshal(m1) if err := Unmarshal(marshaled, m2); err != nil { t.Errorf("Unmarshal %#v: %s", m1, err) break } if !reflect.DeepEqual(v.Interface(), m2) { t.Errorf("got: %#v\nwant:%#v\n%x", m2, m1, marshaled) break } } } func TestUnmarshalEmptyPacket(t *testing.T) { var b []byte var m channelRequestSuccessMsg if err := Unmarshal(b, &m); err == nil { t.Fatalf("unmarshal of empty slice succeeded") } } func TestUnmarshalUnexpectedPacket(t *testing.T) { type S struct { I uint32 `sshtype:"43"` S string B bool } s := S{11, "hello", true} packet := Marshal(s) packet[0] = 42 roundtrip := S{} err := Unmarshal(packet, &roundtrip) if err == nil { t.Fatal("expected error, not nil") } } func TestMarshalPtr(t *testing.T) { s := struct { S string }{"hello"} m1 := Marshal(s) m2 := Marshal(&s) if !bytes.Equal(m1, m2) { t.Errorf("got %q, want %q for marshaled pointer", m2, m1) } } func TestBareMarshalUnmarshal(t *testing.T) { type S struct { I uint32 S string B bool } s := S{42, "hello", true} packet := Marshal(s) roundtrip := S{} Unmarshal(packet, &roundtrip) if !reflect.DeepEqual(s, roundtrip) { t.Errorf("got %#v, want %#v", roundtrip, s) } } func TestBareMarshal(t *testing.T) { type S2 struct { I uint32 } s := S2{42} packet := Marshal(s) i, rest, ok := parseUint32(packet) if len(rest) > 0 || !ok { t.Errorf("parseInt(%q): parse error", packet) } if i != s.I { t.Errorf("got %d, want %d", i, s.I) } } func TestUnmarshalShortKexInitPacket(t *testing.T) { // This used to panic. // Issue 11348 packet := []byte{0x14, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0xff, 0xff, 0xff, 0xff} kim := &kexInitMsg{} if err := Unmarshal(packet, kim); err == nil { t.Error("truncated packet unmarshaled without error") } } func randomBytes(out []byte, rand *rand.Rand) { for i := 0; i < len(out); i++ { out[i] = byte(rand.Int31()) } } func randomNameList(rand *rand.Rand) []string { ret := make([]string, rand.Int31()&15) for i := range ret { s := make([]byte, 1+(rand.Int31()&15)) for j := range s { s[j] = 'a' + uint8(rand.Int31()&15) } ret[i] = string(s) } return ret } func randomInt(rand *rand.Rand) *big.Int { return new(big.Int).SetInt64(int64(int32(rand.Uint32()))) } func (*kexInitMsg) Generate(rand *rand.Rand, size int) reflect.Value { ki := &kexInitMsg{} randomBytes(ki.Cookie[:], rand) ki.KexAlgos = randomNameList(rand) ki.ServerHostKeyAlgos = randomNameList(rand) ki.CiphersClientServer = randomNameList(rand) ki.CiphersServerClient = randomNameList(rand) ki.MACsClientServer = randomNameList(rand) ki.MACsServerClient = randomNameList(rand) ki.CompressionClientServer = randomNameList(rand) ki.CompressionServerClient = randomNameList(rand) ki.LanguagesClientServer = randomNameList(rand) ki.LanguagesServerClient = randomNameList(rand) if rand.Int31()&1 == 1 { ki.FirstKexFollows = true } return reflect.ValueOf(ki) } func (*kexDHInitMsg) Generate(rand *rand.Rand, size int) reflect.Value { dhi := &kexDHInitMsg{} dhi.X = randomInt(rand) return reflect.ValueOf(dhi) } var ( _kexInitMsg = new(kexInitMsg).Generate(rand.New(rand.NewSource(0)), 10).Elem().Interface() _kexDHInitMsg = new(kexDHInitMsg).Generate(rand.New(rand.NewSource(0)), 10).Elem().Interface() _kexInit = Marshal(_kexInitMsg) _kexDHInit = Marshal(_kexDHInitMsg) ) func BenchmarkMarshalKexInitMsg(b *testing.B) { for i := 0; i < b.N; i++ { Marshal(_kexInitMsg) } } func BenchmarkUnmarshalKexInitMsg(b *testing.B) { m := new(kexInitMsg) for i := 0; i < b.N; i++ { Unmarshal(_kexInit, m) } } func BenchmarkMarshalKexDHInitMsg(b *testing.B) { for i := 0; i < b.N; i++ { Marshal(_kexDHInitMsg) } } func BenchmarkUnmarshalKexDHInitMsg(b *testing.B) { m := new(kexDHInitMsg) for i := 0; i < b.N; i++ { Unmarshal(_kexDHInit, m) } } lxd-2.0.0/dist/src/golang.org/x/crypto/ssh/cipher.go0000644061062106075000000003564112702772344024703 0ustar00stgraberdomain admins00000000000000// 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 ssh import ( "crypto/aes" "crypto/cipher" "crypto/rc4" "crypto/subtle" "encoding/binary" "errors" "fmt" "hash" "io" "io/ioutil" ) const ( packetSizeMultiple = 16 // TODO(huin) this should be determined by the cipher. // RFC 4253 section 6.1 defines a minimum packet size of 32768 that implementations // MUST be able to process (plus a few more kilobytes for padding and mac). The RFC // indicates implementations SHOULD be able to handle larger packet sizes, but then // waffles on about reasonable limits. // // OpenSSH caps their maxPacket at 256kB so we choose to do // the same. maxPacket is also used to ensure that uint32 // length fields do not overflow, so it should remain well // below 4G. maxPacket = 256 * 1024 ) // noneCipher implements cipher.Stream and provides no encryption. It is used // by the transport before the first key-exchange. type noneCipher struct{} func (c noneCipher) XORKeyStream(dst, src []byte) { copy(dst, src) } func newAESCTR(key, iv []byte) (cipher.Stream, error) { c, err := aes.NewCipher(key) if err != nil { return nil, err } return cipher.NewCTR(c, iv), nil } func newRC4(key, iv []byte) (cipher.Stream, error) { return rc4.NewCipher(key) } type streamCipherMode struct { keySize int ivSize int skip int createFunc func(key, iv []byte) (cipher.Stream, error) } func (c *streamCipherMode) createStream(key, iv []byte) (cipher.Stream, error) { if len(key) < c.keySize { panic("ssh: key length too small for cipher") } if len(iv) < c.ivSize { panic("ssh: iv too small for cipher") } stream, err := c.createFunc(key[:c.keySize], iv[:c.ivSize]) if err != nil { return nil, err } var streamDump []byte if c.skip > 0 { streamDump = make([]byte, 512) } for remainingToDump := c.skip; remainingToDump > 0; { dumpThisTime := remainingToDump if dumpThisTime > len(streamDump) { dumpThisTime = len(streamDump) } stream.XORKeyStream(streamDump[:dumpThisTime], streamDump[:dumpThisTime]) remainingToDump -= dumpThisTime } return stream, nil } // cipherModes documents properties of supported ciphers. Ciphers not included // are not supported and will not be negotiated, even if explicitly requested in // ClientConfig.Crypto.Ciphers. var cipherModes = map[string]*streamCipherMode{ // Ciphers from RFC4344, which introduced many CTR-based ciphers. Algorithms // are defined in the order specified in the RFC. "aes128-ctr": {16, aes.BlockSize, 0, newAESCTR}, "aes192-ctr": {24, aes.BlockSize, 0, newAESCTR}, "aes256-ctr": {32, aes.BlockSize, 0, newAESCTR}, // Ciphers from RFC4345, which introduces security-improved arcfour ciphers. // They are defined in the order specified in the RFC. "arcfour128": {16, 0, 1536, newRC4}, "arcfour256": {32, 0, 1536, newRC4}, // Cipher defined in RFC 4253, which describes SSH Transport Layer Protocol. // Note that this cipher is not safe, as stated in RFC 4253: "Arcfour (and // RC4) has problems with weak keys, and should be used with caution." // RFC4345 introduces improved versions of Arcfour. "arcfour": {16, 0, 0, newRC4}, // AES-GCM is not a stream cipher, so it is constructed with a // special case. If we add any more non-stream ciphers, we // should invest a cleaner way to do this. gcmCipherID: {16, 12, 0, nil}, // CBC mode is insecure and so is not included in the default config. // (See http://www.isg.rhul.ac.uk/~kp/SandPfinal.pdf). If absolutely // needed, it's possible to specify a custom Config to enable it. // You should expect that an active attacker can recover plaintext if // you do. aes128cbcID: {16, aes.BlockSize, 0, nil}, } // prefixLen is the length of the packet prefix that contains the packet length // and number of padding bytes. const prefixLen = 5 // streamPacketCipher is a packetCipher using a stream cipher. type streamPacketCipher struct { mac hash.Hash cipher cipher.Stream // The following members are to avoid per-packet allocations. prefix [prefixLen]byte seqNumBytes [4]byte padding [2 * packetSizeMultiple]byte packetData []byte macResult []byte } // readPacket reads and decrypt a single packet from the reader argument. func (s *streamPacketCipher) readPacket(seqNum uint32, r io.Reader) ([]byte, error) { if _, err := io.ReadFull(r, s.prefix[:]); err != nil { return nil, err } s.cipher.XORKeyStream(s.prefix[:], s.prefix[:]) length := binary.BigEndian.Uint32(s.prefix[0:4]) paddingLength := uint32(s.prefix[4]) var macSize uint32 if s.mac != nil { s.mac.Reset() binary.BigEndian.PutUint32(s.seqNumBytes[:], seqNum) s.mac.Write(s.seqNumBytes[:]) s.mac.Write(s.prefix[:]) macSize = uint32(s.mac.Size()) } if length <= paddingLength+1 { return nil, errors.New("ssh: invalid packet length, packet too small") } if length > maxPacket { return nil, errors.New("ssh: invalid packet length, packet too large") } // the maxPacket check above ensures that length-1+macSize // does not overflow. if uint32(cap(s.packetData)) < length-1+macSize { s.packetData = make([]byte, length-1+macSize) } else { s.packetData = s.packetData[:length-1+macSize] } if _, err := io.ReadFull(r, s.packetData); err != nil { return nil, err } mac := s.packetData[length-1:] data := s.packetData[:length-1] s.cipher.XORKeyStream(data, data) if s.mac != nil { s.mac.Write(data) s.macResult = s.mac.Sum(s.macResult[:0]) if subtle.ConstantTimeCompare(s.macResult, mac) != 1 { return nil, errors.New("ssh: MAC failure") } } return s.packetData[:length-paddingLength-1], nil } // writePacket encrypts and sends a packet of data to the writer argument func (s *streamPacketCipher) writePacket(seqNum uint32, w io.Writer, rand io.Reader, packet []byte) error { if len(packet) > maxPacket { return errors.New("ssh: packet too large") } paddingLength := packetSizeMultiple - (prefixLen+len(packet))%packetSizeMultiple if paddingLength < 4 { paddingLength += packetSizeMultiple } length := len(packet) + 1 + paddingLength binary.BigEndian.PutUint32(s.prefix[:], uint32(length)) s.prefix[4] = byte(paddingLength) padding := s.padding[:paddingLength] if _, err := io.ReadFull(rand, padding); err != nil { return err } if s.mac != nil { s.mac.Reset() binary.BigEndian.PutUint32(s.seqNumBytes[:], seqNum) s.mac.Write(s.seqNumBytes[:]) s.mac.Write(s.prefix[:]) s.mac.Write(packet) s.mac.Write(padding) } s.cipher.XORKeyStream(s.prefix[:], s.prefix[:]) s.cipher.XORKeyStream(packet, packet) s.cipher.XORKeyStream(padding, padding) if _, err := w.Write(s.prefix[:]); err != nil { return err } if _, err := w.Write(packet); err != nil { return err } if _, err := w.Write(padding); err != nil { return err } if s.mac != nil { s.macResult = s.mac.Sum(s.macResult[:0]) if _, err := w.Write(s.macResult); err != nil { return err } } return nil } type gcmCipher struct { aead cipher.AEAD prefix [4]byte iv []byte buf []byte } func newGCMCipher(iv, key, macKey []byte) (packetCipher, error) { c, err := aes.NewCipher(key) if err != nil { return nil, err } aead, err := cipher.NewGCM(c) if err != nil { return nil, err } return &gcmCipher{ aead: aead, iv: iv, }, nil } const gcmTagSize = 16 func (c *gcmCipher) writePacket(seqNum uint32, w io.Writer, rand io.Reader, packet []byte) error { // Pad out to multiple of 16 bytes. This is different from the // stream cipher because that encrypts the length too. padding := byte(packetSizeMultiple - (1+len(packet))%packetSizeMultiple) if padding < 4 { padding += packetSizeMultiple } length := uint32(len(packet) + int(padding) + 1) binary.BigEndian.PutUint32(c.prefix[:], length) if _, err := w.Write(c.prefix[:]); err != nil { return err } if cap(c.buf) < int(length) { c.buf = make([]byte, length) } else { c.buf = c.buf[:length] } c.buf[0] = padding copy(c.buf[1:], packet) if _, err := io.ReadFull(rand, c.buf[1+len(packet):]); err != nil { return err } c.buf = c.aead.Seal(c.buf[:0], c.iv, c.buf, c.prefix[:]) if _, err := w.Write(c.buf); err != nil { return err } c.incIV() return nil } func (c *gcmCipher) incIV() { for i := 4 + 7; i >= 4; i-- { c.iv[i]++ if c.iv[i] != 0 { break } } } func (c *gcmCipher) readPacket(seqNum uint32, r io.Reader) ([]byte, error) { if _, err := io.ReadFull(r, c.prefix[:]); err != nil { return nil, err } length := binary.BigEndian.Uint32(c.prefix[:]) if length > maxPacket { return nil, errors.New("ssh: max packet length exceeded.") } if cap(c.buf) < int(length+gcmTagSize) { c.buf = make([]byte, length+gcmTagSize) } else { c.buf = c.buf[:length+gcmTagSize] } if _, err := io.ReadFull(r, c.buf); err != nil { return nil, err } plain, err := c.aead.Open(c.buf[:0], c.iv, c.buf, c.prefix[:]) if err != nil { return nil, err } c.incIV() padding := plain[0] if padding < 4 || padding >= 20 { return nil, fmt.Errorf("ssh: illegal padding %d", padding) } if int(padding+1) >= len(plain) { return nil, fmt.Errorf("ssh: padding %d too large", padding) } plain = plain[1 : length-uint32(padding)] return plain, nil } // cbcCipher implements aes128-cbc cipher defined in RFC 4253 section 6.1 type cbcCipher struct { mac hash.Hash macSize uint32 decrypter cipher.BlockMode encrypter cipher.BlockMode // The following members are to avoid per-packet allocations. seqNumBytes [4]byte packetData []byte macResult []byte // Amount of data we should still read to hide which // verification error triggered. oracleCamouflage uint32 } func newAESCBCCipher(iv, key, macKey []byte, algs directionAlgorithms) (packetCipher, error) { c, err := aes.NewCipher(key) if err != nil { return nil, err } cbc := &cbcCipher{ mac: macModes[algs.MAC].new(macKey), decrypter: cipher.NewCBCDecrypter(c, iv), encrypter: cipher.NewCBCEncrypter(c, iv), packetData: make([]byte, 1024), } if cbc.mac != nil { cbc.macSize = uint32(cbc.mac.Size()) } return cbc, nil } func maxUInt32(a, b int) uint32 { if a > b { return uint32(a) } return uint32(b) } const ( cbcMinPacketSizeMultiple = 8 cbcMinPacketSize = 16 cbcMinPaddingSize = 4 ) // cbcError represents a verification error that may leak information. type cbcError string func (e cbcError) Error() string { return string(e) } func (c *cbcCipher) readPacket(seqNum uint32, r io.Reader) ([]byte, error) { p, err := c.readPacketLeaky(seqNum, r) if err != nil { if _, ok := err.(cbcError); ok { // Verification error: read a fixed amount of // data, to make distinguishing between // failing MAC and failing length check more // difficult. io.CopyN(ioutil.Discard, r, int64(c.oracleCamouflage)) } } return p, err } func (c *cbcCipher) readPacketLeaky(seqNum uint32, r io.Reader) ([]byte, error) { blockSize := c.decrypter.BlockSize() // Read the header, which will include some of the subsequent data in the // case of block ciphers - this is copied back to the payload later. // How many bytes of payload/padding will be read with this first read. firstBlockLength := uint32((prefixLen + blockSize - 1) / blockSize * blockSize) firstBlock := c.packetData[:firstBlockLength] if _, err := io.ReadFull(r, firstBlock); err != nil { return nil, err } c.oracleCamouflage = maxPacket + 4 + c.macSize - firstBlockLength c.decrypter.CryptBlocks(firstBlock, firstBlock) length := binary.BigEndian.Uint32(firstBlock[:4]) if length > maxPacket { return nil, cbcError("ssh: packet too large") } if length+4 < maxUInt32(cbcMinPacketSize, blockSize) { // The minimum size of a packet is 16 (or the cipher block size, whichever // is larger) bytes. return nil, cbcError("ssh: packet too small") } // The length of the packet (including the length field but not the MAC) must // be a multiple of the block size or 8, whichever is larger. if (length+4)%maxUInt32(cbcMinPacketSizeMultiple, blockSize) != 0 { return nil, cbcError("ssh: invalid packet length multiple") } paddingLength := uint32(firstBlock[4]) if paddingLength < cbcMinPaddingSize || length <= paddingLength+1 { return nil, cbcError("ssh: invalid packet length") } // Positions within the c.packetData buffer: macStart := 4 + length paddingStart := macStart - paddingLength // Entire packet size, starting before length, ending at end of mac. entirePacketSize := macStart + c.macSize // Ensure c.packetData is large enough for the entire packet data. if uint32(cap(c.packetData)) < entirePacketSize { // Still need to upsize and copy, but this should be rare at runtime, only // on upsizing the packetData buffer. c.packetData = make([]byte, entirePacketSize) copy(c.packetData, firstBlock) } else { c.packetData = c.packetData[:entirePacketSize] } if n, err := io.ReadFull(r, c.packetData[firstBlockLength:]); err != nil { return nil, err } else { c.oracleCamouflage -= uint32(n) } remainingCrypted := c.packetData[firstBlockLength:macStart] c.decrypter.CryptBlocks(remainingCrypted, remainingCrypted) mac := c.packetData[macStart:] if c.mac != nil { c.mac.Reset() binary.BigEndian.PutUint32(c.seqNumBytes[:], seqNum) c.mac.Write(c.seqNumBytes[:]) c.mac.Write(c.packetData[:macStart]) c.macResult = c.mac.Sum(c.macResult[:0]) if subtle.ConstantTimeCompare(c.macResult, mac) != 1 { return nil, cbcError("ssh: MAC failure") } } return c.packetData[prefixLen:paddingStart], nil } func (c *cbcCipher) writePacket(seqNum uint32, w io.Writer, rand io.Reader, packet []byte) error { effectiveBlockSize := maxUInt32(cbcMinPacketSizeMultiple, c.encrypter.BlockSize()) // Length of encrypted portion of the packet (header, payload, padding). // Enforce minimum padding and packet size. encLength := maxUInt32(prefixLen+len(packet)+cbcMinPaddingSize, cbcMinPaddingSize) // Enforce block size. encLength = (encLength + effectiveBlockSize - 1) / effectiveBlockSize * effectiveBlockSize length := encLength - 4 paddingLength := int(length) - (1 + len(packet)) // Overall buffer contains: header, payload, padding, mac. // Space for the MAC is reserved in the capacity but not the slice length. bufferSize := encLength + c.macSize if uint32(cap(c.packetData)) < bufferSize { c.packetData = make([]byte, encLength, bufferSize) } else { c.packetData = c.packetData[:encLength] } p := c.packetData // Packet header. binary.BigEndian.PutUint32(p, length) p = p[4:] p[0] = byte(paddingLength) // Payload. p = p[1:] copy(p, packet) // Padding. p = p[len(packet):] if _, err := io.ReadFull(rand, p); err != nil { return err } if c.mac != nil { c.mac.Reset() binary.BigEndian.PutUint32(c.seqNumBytes[:], seqNum) c.mac.Write(c.seqNumBytes[:]) c.mac.Write(c.packetData) // The MAC is now appended into the capacity reserved for it earlier. c.packetData = c.mac.Sum(c.packetData) } c.encrypter.CryptBlocks(c.packetData[:encLength], c.packetData[:encLength]) if _, err := w.Write(c.packetData); err != nil { return err } return nil } lxd-2.0.0/dist/src/golang.org/x/crypto/ssh/buffer_test.go0000644061062106075000000000425412702772344025735 0ustar00stgraberdomain admins00000000000000// 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 ssh import ( "io" "testing" ) var alphabet = []byte("abcdefghijklmnopqrstuvwxyz") func TestBufferReadwrite(t *testing.T) { b := newBuffer() b.write(alphabet[:10]) r, _ := b.Read(make([]byte, 10)) if r != 10 { t.Fatalf("Expected written == read == 10, written: 10, read %d", r) } b = newBuffer() b.write(alphabet[:5]) r, _ = b.Read(make([]byte, 10)) if r != 5 { t.Fatalf("Expected written == read == 5, written: 5, read %d", r) } b = newBuffer() b.write(alphabet[:10]) r, _ = b.Read(make([]byte, 5)) if r != 5 { t.Fatalf("Expected written == 10, read == 5, written: 10, read %d", r) } b = newBuffer() b.write(alphabet[:5]) b.write(alphabet[5:15]) r, _ = b.Read(make([]byte, 10)) r2, _ := b.Read(make([]byte, 10)) if r != 10 || r2 != 5 || 15 != r+r2 { t.Fatal("Expected written == read == 15") } } func TestBufferClose(t *testing.T) { b := newBuffer() b.write(alphabet[:10]) b.eof() _, err := b.Read(make([]byte, 5)) if err != nil { t.Fatal("expected read of 5 to not return EOF") } b = newBuffer() b.write(alphabet[:10]) b.eof() r, err := b.Read(make([]byte, 5)) r2, err2 := b.Read(make([]byte, 10)) if r != 5 || r2 != 5 || err != nil || err2 != nil { t.Fatal("expected reads of 5 and 5") } b = newBuffer() b.write(alphabet[:10]) b.eof() r, err = b.Read(make([]byte, 5)) r2, err2 = b.Read(make([]byte, 10)) r3, err3 := b.Read(make([]byte, 10)) if r != 5 || r2 != 5 || r3 != 0 || err != nil || err2 != nil || err3 != io.EOF { t.Fatal("expected reads of 5 and 5 and 0, with EOF") } b = newBuffer() b.write(make([]byte, 5)) b.write(make([]byte, 10)) b.eof() r, err = b.Read(make([]byte, 9)) r2, err2 = b.Read(make([]byte, 3)) r3, err3 = b.Read(make([]byte, 3)) r4, err4 := b.Read(make([]byte, 10)) if err != nil || err2 != nil || err3 != nil || err4 != io.EOF { t.Fatalf("Expected EOF on forth read only, err=%v, err2=%v, err3=%v, err4=%v", err, err2, err3, err4) } if r != 9 || r2 != 3 || r3 != 3 || r4 != 0 { t.Fatal("Expected written == read == 15", r, r2, r3, r4) } } lxd-2.0.0/dist/src/golang.org/x/crypto/ssh/testdata/0000755061062106075000000000000012702772344024702 5ustar00stgraberdomain admins00000000000000lxd-2.0.0/dist/src/golang.org/x/crypto/ssh/testdata/keys.go0000644061062106075000000000357412702772344026215 0ustar00stgraberdomain admins00000000000000// Copyright 2014 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 testdata var PEMBytes = map[string][]byte{ "dsa": []byte(`-----BEGIN DSA PRIVATE KEY----- MIIBuwIBAAKBgQD6PDSEyXiI9jfNs97WuM46MSDCYlOqWw80ajN16AohtBncs1YB lHk//dQOvCYOsYaE+gNix2jtoRjwXhDsc25/IqQbU1ahb7mB8/rsaILRGIbA5WH3 EgFtJmXFovDz3if6F6TzvhFpHgJRmLYVR8cqsezL3hEZOvvs2iH7MorkxwIVAJHD nD82+lxh2fb4PMsIiaXudAsBAoGAQRf7Q/iaPRn43ZquUhd6WwvirqUj+tkIu6eV 2nZWYmXLlqFQKEy4Tejl7Wkyzr2OSYvbXLzo7TNxLKoWor6ips0phYPPMyXld14r juhT24CrhOzuLMhDduMDi032wDIZG4Y+K7ElU8Oufn8Sj5Wge8r6ANmmVgmFfynr FhdYCngCgYEA3ucGJ93/Mx4q4eKRDxcWD3QzWyqpbRVRRV1Vmih9Ha/qC994nJFz DQIdjxDIT2Rk2AGzMqFEB68Zc3O+Wcsmz5eWWzEwFxaTwOGWTyDqsDRLm3fD+QYj nOwuxb0Kce+gWI8voWcqC9cyRm09jGzu2Ab3Bhtpg8JJ8L7gS3MRZK4CFEx4UAfY Fmsr0W6fHB9nhS4/UXM8 -----END DSA PRIVATE KEY----- `), "ecdsa": []byte(`-----BEGIN EC PRIVATE KEY----- MHcCAQEEINGWx0zo6fhJ/0EAfrPzVFyFC9s18lBt3cRoEDhS3ARooAoGCCqGSM49 AwEHoUQDQgAEi9Hdw6KvZcWxfg2IDhA7UkpDtzzt6ZqJXSsFdLd+Kx4S3Sx4cVO+ 6/ZOXRnPmNAlLUqjShUsUBBngG0u2fqEqA== -----END EC PRIVATE KEY----- `), "rsa": []byte(`-----BEGIN RSA PRIVATE KEY----- MIIBOwIBAAJBALdGZxkXDAjsYk10ihwU6Id2KeILz1TAJuoq4tOgDWxEEGeTrcld r/ZwVaFzjWzxaf6zQIJbfaSEAhqD5yo72+sCAwEAAQJBAK8PEVU23Wj8mV0QjwcJ tZ4GcTUYQL7cF4+ezTCE9a1NrGnCP2RuQkHEKxuTVrxXt+6OF15/1/fuXnxKjmJC nxkCIQDaXvPPBi0c7vAxGwNY9726x01/dNbHCE0CBtcotobxpwIhANbbQbh3JHVW 2haQh4fAG5mhesZKAGcxTyv4mQ7uMSQdAiAj+4dzMpJWdSzQ+qGHlHMIBvVHLkqB y2VdEyF7DPCZewIhAI7GOI/6LDIFOvtPo6Bj2nNmyQ1HU6k/LRtNIXi4c9NJAiAr rrxx26itVhJmcvoUhOjwuzSlP2bE5VHAvkGB352YBg== -----END RSA PRIVATE KEY----- `), "user": []byte(`-----BEGIN EC PRIVATE KEY----- MHcCAQEEILYCAeq8f7V4vSSypRw7pxy8yz3V5W4qg8kSC3zJhqpQoAoGCCqGSM49 AwEHoUQDQgAEYcO2xNKiRUYOLEHM7VYAp57HNyKbOdYtHD83Z4hzNPVC4tM5mdGD PLL8IEwvYu2wq+lpXfGQnNMbzYf9gspG0w== -----END EC PRIVATE KEY----- `), } lxd-2.0.0/dist/src/golang.org/x/crypto/ssh/testdata/doc.go0000644061062106075000000000063212702772344025777 0ustar00stgraberdomain admins00000000000000// Copyright 2014 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 contains test data shared between the various subpackages of // the golang.org/x/crypto/ssh package. Under no circumstance should // this data be used for production code. package testdata // import "golang.org/x/crypto/ssh/testdata" lxd-2.0.0/dist/src/golang.org/x/crypto/ssh/mux_test.go0000644061062106075000000002511412702772344025273 0ustar00stgraberdomain admins00000000000000// Copyright 2013 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 ssh import ( "io" "io/ioutil" "sync" "testing" ) func muxPair() (*mux, *mux) { a, b := memPipe() s := newMux(a) c := newMux(b) return s, c } // Returns both ends of a channel, and the mux for the the 2nd // channel. func channelPair(t *testing.T) (*channel, *channel, *mux) { c, s := muxPair() res := make(chan *channel, 1) go func() { newCh, ok := <-s.incomingChannels if !ok { t.Fatalf("No incoming channel") } if newCh.ChannelType() != "chan" { t.Fatalf("got type %q want chan", newCh.ChannelType()) } ch, _, err := newCh.Accept() if err != nil { t.Fatalf("Accept %v", err) } res <- ch.(*channel) }() ch, err := c.openChannel("chan", nil) if err != nil { t.Fatalf("OpenChannel: %v", err) } return <-res, ch, c } // Test that stderr and stdout can be addressed from different // goroutines. This is intended for use with the race detector. func TestMuxChannelExtendedThreadSafety(t *testing.T) { writer, reader, mux := channelPair(t) defer writer.Close() defer reader.Close() defer mux.Close() var wr, rd sync.WaitGroup magic := "hello world" wr.Add(2) go func() { io.WriteString(writer, magic) wr.Done() }() go func() { io.WriteString(writer.Stderr(), magic) wr.Done() }() rd.Add(2) go func() { c, err := ioutil.ReadAll(reader) if string(c) != magic { t.Fatalf("stdout read got %q, want %q (error %s)", c, magic, err) } rd.Done() }() go func() { c, err := ioutil.ReadAll(reader.Stderr()) if string(c) != magic { t.Fatalf("stderr read got %q, want %q (error %s)", c, magic, err) } rd.Done() }() wr.Wait() writer.CloseWrite() rd.Wait() } func TestMuxReadWrite(t *testing.T) { s, c, mux := channelPair(t) defer s.Close() defer c.Close() defer mux.Close() magic := "hello world" magicExt := "hello stderr" go func() { _, err := s.Write([]byte(magic)) if err != nil { t.Fatalf("Write: %v", err) } _, err = s.Extended(1).Write([]byte(magicExt)) if err != nil { t.Fatalf("Write: %v", err) } err = s.Close() if err != nil { t.Fatalf("Close: %v", err) } }() var buf [1024]byte n, err := c.Read(buf[:]) if err != nil { t.Fatalf("server Read: %v", err) } got := string(buf[:n]) if got != magic { t.Fatalf("server: got %q want %q", got, magic) } n, err = c.Extended(1).Read(buf[:]) if err != nil { t.Fatalf("server Read: %v", err) } got = string(buf[:n]) if got != magicExt { t.Fatalf("server: got %q want %q", got, magic) } } func TestMuxChannelOverflow(t *testing.T) { reader, writer, mux := channelPair(t) defer reader.Close() defer writer.Close() defer mux.Close() wDone := make(chan int, 1) go func() { if _, err := writer.Write(make([]byte, channelWindowSize)); err != nil { t.Errorf("could not fill window: %v", err) } writer.Write(make([]byte, 1)) wDone <- 1 }() writer.remoteWin.waitWriterBlocked() // Send 1 byte. packet := make([]byte, 1+4+4+1) packet[0] = msgChannelData marshalUint32(packet[1:], writer.remoteId) marshalUint32(packet[5:], uint32(1)) packet[9] = 42 if err := writer.mux.conn.writePacket(packet); err != nil { t.Errorf("could not send packet") } if _, err := reader.SendRequest("hello", true, nil); err == nil { t.Errorf("SendRequest succeeded.") } <-wDone } func TestMuxChannelCloseWriteUnblock(t *testing.T) { reader, writer, mux := channelPair(t) defer reader.Close() defer writer.Close() defer mux.Close() wDone := make(chan int, 1) go func() { if _, err := writer.Write(make([]byte, channelWindowSize)); err != nil { t.Errorf("could not fill window: %v", err) } if _, err := writer.Write(make([]byte, 1)); err != io.EOF { t.Errorf("got %v, want EOF for unblock write", err) } wDone <- 1 }() writer.remoteWin.waitWriterBlocked() reader.Close() <-wDone } func TestMuxConnectionCloseWriteUnblock(t *testing.T) { reader, writer, mux := channelPair(t) defer reader.Close() defer writer.Close() defer mux.Close() wDone := make(chan int, 1) go func() { if _, err := writer.Write(make([]byte, channelWindowSize)); err != nil { t.Errorf("could not fill window: %v", err) } if _, err := writer.Write(make([]byte, 1)); err != io.EOF { t.Errorf("got %v, want EOF for unblock write", err) } wDone <- 1 }() writer.remoteWin.waitWriterBlocked() mux.Close() <-wDone } func TestMuxReject(t *testing.T) { client, server := muxPair() defer server.Close() defer client.Close() go func() { ch, ok := <-server.incomingChannels if !ok { t.Fatalf("Accept") } if ch.ChannelType() != "ch" || string(ch.ExtraData()) != "extra" { t.Fatalf("unexpected channel: %q, %q", ch.ChannelType(), ch.ExtraData()) } ch.Reject(RejectionReason(42), "message") }() ch, err := client.openChannel("ch", []byte("extra")) if ch != nil { t.Fatal("openChannel not rejected") } ocf, ok := err.(*OpenChannelError) if !ok { t.Errorf("got %#v want *OpenChannelError", err) } else if ocf.Reason != 42 || ocf.Message != "message" { t.Errorf("got %#v, want {Reason: 42, Message: %q}", ocf, "message") } want := "ssh: rejected: unknown reason 42 (message)" if err.Error() != want { t.Errorf("got %q, want %q", err.Error(), want) } } func TestMuxChannelRequest(t *testing.T) { client, server, mux := channelPair(t) defer server.Close() defer client.Close() defer mux.Close() var received int var wg sync.WaitGroup wg.Add(1) go func() { for r := range server.incomingRequests { received++ r.Reply(r.Type == "yes", nil) } wg.Done() }() _, err := client.SendRequest("yes", false, nil) if err != nil { t.Fatalf("SendRequest: %v", err) } ok, err := client.SendRequest("yes", true, nil) if err != nil { t.Fatalf("SendRequest: %v", err) } if !ok { t.Errorf("SendRequest(yes): %v", ok) } ok, err = client.SendRequest("no", true, nil) if err != nil { t.Fatalf("SendRequest: %v", err) } if ok { t.Errorf("SendRequest(no): %v", ok) } client.Close() wg.Wait() if received != 3 { t.Errorf("got %d requests, want %d", received, 3) } } func TestMuxGlobalRequest(t *testing.T) { clientMux, serverMux := muxPair() defer serverMux.Close() defer clientMux.Close() var seen bool go func() { for r := range serverMux.incomingRequests { seen = seen || r.Type == "peek" if r.WantReply { err := r.Reply(r.Type == "yes", append([]byte(r.Type), r.Payload...)) if err != nil { t.Errorf("AckRequest: %v", err) } } } }() _, _, err := clientMux.SendRequest("peek", false, nil) if err != nil { t.Errorf("SendRequest: %v", err) } ok, data, err := clientMux.SendRequest("yes", true, []byte("a")) if !ok || string(data) != "yesa" || err != nil { t.Errorf("SendRequest(\"yes\", true, \"a\"): %v %v %v", ok, data, err) } if ok, data, err := clientMux.SendRequest("yes", true, []byte("a")); !ok || string(data) != "yesa" || err != nil { t.Errorf("SendRequest(\"yes\", true, \"a\"): %v %v %v", ok, data, err) } if ok, data, err := clientMux.SendRequest("no", true, []byte("a")); ok || string(data) != "noa" || err != nil { t.Errorf("SendRequest(\"no\", true, \"a\"): %v %v %v", ok, data, err) } if !seen { t.Errorf("never saw 'peek' request") } } func TestMuxGlobalRequestUnblock(t *testing.T) { clientMux, serverMux := muxPair() defer serverMux.Close() defer clientMux.Close() result := make(chan error, 1) go func() { _, _, err := clientMux.SendRequest("hello", true, nil) result <- err }() <-serverMux.incomingRequests serverMux.conn.Close() err := <-result if err != io.EOF { t.Errorf("want EOF, got %v", io.EOF) } } func TestMuxChannelRequestUnblock(t *testing.T) { a, b, connB := channelPair(t) defer a.Close() defer b.Close() defer connB.Close() result := make(chan error, 1) go func() { _, err := a.SendRequest("hello", true, nil) result <- err }() <-b.incomingRequests connB.conn.Close() err := <-result if err != io.EOF { t.Errorf("want EOF, got %v", err) } } func TestMuxCloseChannel(t *testing.T) { r, w, mux := channelPair(t) defer mux.Close() defer r.Close() defer w.Close() result := make(chan error, 1) go func() { var b [1024]byte _, err := r.Read(b[:]) result <- err }() if err := w.Close(); err != nil { t.Errorf("w.Close: %v", err) } if _, err := w.Write([]byte("hello")); err != io.EOF { t.Errorf("got err %v, want io.EOF after Close", err) } if err := <-result; err != io.EOF { t.Errorf("got %v (%T), want io.EOF", err, err) } } func TestMuxCloseWriteChannel(t *testing.T) { r, w, mux := channelPair(t) defer mux.Close() result := make(chan error, 1) go func() { var b [1024]byte _, err := r.Read(b[:]) result <- err }() if err := w.CloseWrite(); err != nil { t.Errorf("w.CloseWrite: %v", err) } if _, err := w.Write([]byte("hello")); err != io.EOF { t.Errorf("got err %v, want io.EOF after CloseWrite", err) } if err := <-result; err != io.EOF { t.Errorf("got %v (%T), want io.EOF", err, err) } } func TestMuxInvalidRecord(t *testing.T) { a, b := muxPair() defer a.Close() defer b.Close() packet := make([]byte, 1+4+4+1) packet[0] = msgChannelData marshalUint32(packet[1:], 29348723 /* invalid channel id */) marshalUint32(packet[5:], 1) packet[9] = 42 a.conn.writePacket(packet) go a.SendRequest("hello", false, nil) // 'a' wrote an invalid packet, so 'b' has exited. req, ok := <-b.incomingRequests if ok { t.Errorf("got request %#v after receiving invalid packet", req) } } func TestZeroWindowAdjust(t *testing.T) { a, b, mux := channelPair(t) defer a.Close() defer b.Close() defer mux.Close() go func() { io.WriteString(a, "hello") // bogus adjust. a.sendMessage(windowAdjustMsg{}) io.WriteString(a, "world") a.Close() }() want := "helloworld" c, _ := ioutil.ReadAll(b) if string(c) != want { t.Errorf("got %q want %q", c, want) } } func TestMuxMaxPacketSize(t *testing.T) { a, b, mux := channelPair(t) defer a.Close() defer b.Close() defer mux.Close() large := make([]byte, a.maxRemotePayload+1) packet := make([]byte, 1+4+4+1+len(large)) packet[0] = msgChannelData marshalUint32(packet[1:], a.remoteId) marshalUint32(packet[5:], uint32(len(large))) packet[9] = 42 if err := a.mux.conn.writePacket(packet); err != nil { t.Errorf("could not send packet") } go a.SendRequest("hello", false, nil) _, ok := <-b.incomingRequests if ok { t.Errorf("connection still alive after receiving large packet.") } } // Don't ship code with debug=true. func TestDebug(t *testing.T) { if debugMux { t.Error("mux debug switched on") } if debugHandshake { t.Error("handshake debug switched on") } } lxd-2.0.0/dist/src/golang.org/x/crypto/ssh/mempipe_test.go0000644061062106075000000000374412702772344026123 0ustar00stgraberdomain admins00000000000000// Copyright 2013 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 ssh import ( "io" "sync" "testing" ) // An in-memory packetConn. It is safe to call Close and writePacket // from different goroutines. type memTransport struct { eof bool pending [][]byte write *memTransport sync.Mutex *sync.Cond } func (t *memTransport) readPacket() ([]byte, error) { t.Lock() defer t.Unlock() for { if len(t.pending) > 0 { r := t.pending[0] t.pending = t.pending[1:] return r, nil } if t.eof { return nil, io.EOF } t.Cond.Wait() } } func (t *memTransport) closeSelf() error { t.Lock() defer t.Unlock() if t.eof { return io.EOF } t.eof = true t.Cond.Broadcast() return nil } func (t *memTransport) Close() error { err := t.write.closeSelf() t.closeSelf() return err } func (t *memTransport) writePacket(p []byte) error { t.write.Lock() defer t.write.Unlock() if t.write.eof { return io.EOF } c := make([]byte, len(p)) copy(c, p) t.write.pending = append(t.write.pending, c) t.write.Cond.Signal() return nil } func memPipe() (a, b packetConn) { t1 := memTransport{} t2 := memTransport{} t1.write = &t2 t2.write = &t1 t1.Cond = sync.NewCond(&t1.Mutex) t2.Cond = sync.NewCond(&t2.Mutex) return &t1, &t2 } func TestMemPipe(t *testing.T) { a, b := memPipe() if err := a.writePacket([]byte{42}); err != nil { t.Fatalf("writePacket: %v", err) } if err := a.Close(); err != nil { t.Fatal("Close: ", err) } p, err := b.readPacket() if err != nil { t.Fatal("readPacket: ", err) } if len(p) != 1 || p[0] != 42 { t.Fatalf("got %v, want {42}", p) } p, err = b.readPacket() if err != io.EOF { t.Fatalf("got %v, %v, want EOF", p, err) } } func TestDoubleClose(t *testing.T) { a, _ := memPipe() err := a.Close() if err != nil { t.Errorf("Close: %v", err) } err = a.Close() if err != io.EOF { t.Errorf("expect EOF on double close.") } } lxd-2.0.0/dist/src/golang.org/x/crypto/ssh/terminal/0000755061062106075000000000000012702772344024704 5ustar00stgraberdomain admins00000000000000lxd-2.0.0/dist/src/golang.org/x/crypto/ssh/terminal/util_plan9.go0000644061062106075000000000375412702772344027324 0ustar00stgraberdomain admins00000000000000// Copyright 2016 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 terminal provides support functions for dealing with terminals, as // commonly found on UNIX systems. // // Putting a terminal into raw mode is the most common requirement: // // oldState, err := terminal.MakeRaw(0) // if err != nil { // panic(err) // } // defer terminal.Restore(0, oldState) package terminal import ( "fmt" "runtime" ) type State struct{} // IsTerminal returns true if the given file descriptor is a terminal. func IsTerminal(fd int) bool { return false } // MakeRaw put the terminal connected to the given file descriptor into raw // mode and returns the previous state of the terminal so that it can be // restored. func MakeRaw(fd int) (*State, error) { return nil, fmt.Errorf("terminal: MakeRaw not implemented on %s/%s", runtime.GOOS, runtime.GOARCH) } // GetState returns the current state of a terminal which may be useful to // restore the terminal after a signal. func GetState(fd int) (*State, error) { return nil, fmt.Errorf("terminal: GetState not implemented on %s/%s", runtime.GOOS, runtime.GOARCH) } // Restore restores the terminal connected to the given file descriptor to a // previous state. func Restore(fd int, state *State) error { return fmt.Errorf("terminal: Restore not implemented on %s/%s", runtime.GOOS, runtime.GOARCH) } // GetSize returns the dimensions of the given terminal. func GetSize(fd int) (width, height int, err error) { return 0, 0, fmt.Errorf("terminal: GetSize not implemented on %s/%s", runtime.GOOS, runtime.GOARCH) } // ReadPassword reads a line of input from a terminal without local echo. This // is commonly used for inputting passwords and other sensitive data. The slice // returned does not include the \n. func ReadPassword(fd int) ([]byte, error) { return nil, fmt.Errorf("terminal: ReadPassword not implemented on %s/%s", runtime.GOOS, runtime.GOARCH) } lxd-2.0.0/dist/src/golang.org/x/crypto/ssh/terminal/util.go0000644061062106075000000000767112702772344026223 0ustar00stgraberdomain admins00000000000000// 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. // +build darwin dragonfly freebsd linux,!appengine netbsd openbsd // Package terminal provides support functions for dealing with terminals, as // commonly found on UNIX systems. // // Putting a terminal into raw mode is the most common requirement: // // oldState, err := terminal.MakeRaw(0) // if err != nil { // panic(err) // } // defer terminal.Restore(0, oldState) package terminal // import "golang.org/x/crypto/ssh/terminal" import ( "io" "syscall" "unsafe" ) // State contains the state of a terminal. type State struct { termios syscall.Termios } // IsTerminal returns true if the given file descriptor is a terminal. func IsTerminal(fd int) bool { var termios syscall.Termios _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlReadTermios, uintptr(unsafe.Pointer(&termios)), 0, 0, 0) return err == 0 } // MakeRaw put the terminal connected to the given file descriptor into raw // mode and returns the previous state of the terminal so that it can be // restored. func MakeRaw(fd int) (*State, error) { var oldState State if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlReadTermios, uintptr(unsafe.Pointer(&oldState.termios)), 0, 0, 0); err != 0 { return nil, err } newState := oldState.termios newState.Iflag &^= syscall.ISTRIP | syscall.INLCR | syscall.ICRNL | syscall.IGNCR | syscall.IXON | syscall.IXOFF newState.Lflag &^= syscall.ECHO | syscall.ICANON | syscall.ISIG if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlWriteTermios, uintptr(unsafe.Pointer(&newState)), 0, 0, 0); err != 0 { return nil, err } return &oldState, nil } // GetState returns the current state of a terminal which may be useful to // restore the terminal after a signal. func GetState(fd int) (*State, error) { var oldState State if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlReadTermios, uintptr(unsafe.Pointer(&oldState.termios)), 0, 0, 0); err != 0 { return nil, err } return &oldState, nil } // Restore restores the terminal connected to the given file descriptor to a // previous state. func Restore(fd int, state *State) error { _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlWriteTermios, uintptr(unsafe.Pointer(&state.termios)), 0, 0, 0) return err } // GetSize returns the dimensions of the given terminal. func GetSize(fd int) (width, height int, err error) { var dimensions [4]uint16 if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), uintptr(syscall.TIOCGWINSZ), uintptr(unsafe.Pointer(&dimensions)), 0, 0, 0); err != 0 { return -1, -1, err } return int(dimensions[1]), int(dimensions[0]), nil } // ReadPassword reads a line of input from a terminal without local echo. This // is commonly used for inputting passwords and other sensitive data. The slice // returned does not include the \n. func ReadPassword(fd int) ([]byte, error) { var oldState syscall.Termios if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlReadTermios, uintptr(unsafe.Pointer(&oldState)), 0, 0, 0); err != 0 { return nil, err } newState := oldState newState.Lflag &^= syscall.ECHO newState.Lflag |= syscall.ICANON | syscall.ISIG newState.Iflag |= syscall.ICRNL if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlWriteTermios, uintptr(unsafe.Pointer(&newState)), 0, 0, 0); err != 0 { return nil, err } defer func() { syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlWriteTermios, uintptr(unsafe.Pointer(&oldState)), 0, 0, 0) }() var buf [16]byte var ret []byte for { n, err := syscall.Read(fd, buf[:]) if err != nil { return nil, err } if n == 0 { if len(ret) == 0 { return nil, io.EOF } break } if buf[n-1] == '\n' { n-- } ret = append(ret, buf[:n]...) if n < len(buf) { break } } return ret, nil } lxd-2.0.0/dist/src/golang.org/x/crypto/ssh/terminal/terminal_test.go0000644061062106075000000001327012702772344030110 0ustar00stgraberdomain admins00000000000000// 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 terminal import ( "io" "os" "testing" ) type MockTerminal struct { toSend []byte bytesPerRead int received []byte } func (c *MockTerminal) Read(data []byte) (n int, err error) { n = len(data) if n == 0 { return } if n > len(c.toSend) { n = len(c.toSend) } if n == 0 { return 0, io.EOF } if c.bytesPerRead > 0 && n > c.bytesPerRead { n = c.bytesPerRead } copy(data, c.toSend[:n]) c.toSend = c.toSend[n:] return } func (c *MockTerminal) Write(data []byte) (n int, err error) { c.received = append(c.received, data...) return len(data), nil } func TestClose(t *testing.T) { c := &MockTerminal{} ss := NewTerminal(c, "> ") line, err := ss.ReadLine() if line != "" { t.Errorf("Expected empty line but got: %s", line) } if err != io.EOF { t.Errorf("Error should have been EOF but got: %s", err) } } var keyPressTests = []struct { in string line string err error throwAwayLines int }{ { err: io.EOF, }, { in: "\r", line: "", }, { in: "foo\r", line: "foo", }, { in: "a\x1b[Cb\r", // right line: "ab", }, { in: "a\x1b[Db\r", // left line: "ba", }, { in: "a\177b\r", // backspace line: "b", }, { in: "\x1b[A\r", // up }, { in: "\x1b[B\r", // down }, { in: "line\x1b[A\x1b[B\r", // up then down line: "line", }, { in: "line1\rline2\x1b[A\r", // recall previous line. line: "line1", throwAwayLines: 1, }, { // recall two previous lines and append. in: "line1\rline2\rline3\x1b[A\x1b[Axxx\r", line: "line1xxx", throwAwayLines: 2, }, { // Ctrl-A to move to beginning of line followed by ^K to kill // line. in: "a b \001\013\r", line: "", }, { // Ctrl-A to move to beginning of line, Ctrl-E to move to end, // finally ^K to kill nothing. in: "a b \001\005\013\r", line: "a b ", }, { in: "\027\r", line: "", }, { in: "a\027\r", line: "", }, { in: "a \027\r", line: "", }, { in: "a b\027\r", line: "a ", }, { in: "a b \027\r", line: "a ", }, { in: "one two thr\x1b[D\027\r", line: "one two r", }, { in: "\013\r", line: "", }, { in: "a\013\r", line: "a", }, { in: "ab\x1b[D\013\r", line: "a", }, { in: "Ξεσκεπάζω\r", line: "Ξεσκεπάζω", }, { in: "£\r\x1b[A\177\r", // non-ASCII char, enter, up, backspace. line: "", throwAwayLines: 1, }, { in: "£\r££\x1b[A\x1b[B\177\r", // non-ASCII char, enter, 2x non-ASCII, up, down, backspace, enter. line: "£", throwAwayLines: 1, }, { // Ctrl-D at the end of the line should be ignored. in: "a\004\r", line: "a", }, { // a, b, left, Ctrl-D should erase the b. in: "ab\x1b[D\004\r", line: "a", }, { // a, b, c, d, left, left, ^U should erase to the beginning of // the line. in: "abcd\x1b[D\x1b[D\025\r", line: "cd", }, { // Bracketed paste mode: control sequences should be returned // verbatim in paste mode. in: "abc\x1b[200~de\177f\x1b[201~\177\r", line: "abcde\177", }, { // Enter in bracketed paste mode should still work. in: "abc\x1b[200~d\refg\x1b[201~h\r", line: "efgh", throwAwayLines: 1, }, { // Lines consisting entirely of pasted data should be indicated as such. in: "\x1b[200~a\r", line: "a", err: ErrPasteIndicator, }, } func TestKeyPresses(t *testing.T) { for i, test := range keyPressTests { for j := 1; j < len(test.in); j++ { c := &MockTerminal{ toSend: []byte(test.in), bytesPerRead: j, } ss := NewTerminal(c, "> ") for k := 0; k < test.throwAwayLines; k++ { _, err := ss.ReadLine() if err != nil { t.Errorf("Throwaway line %d from test %d resulted in error: %s", k, i, err) } } line, err := ss.ReadLine() if line != test.line { t.Errorf("Line resulting from test %d (%d bytes per read) was '%s', expected '%s'", i, j, line, test.line) break } if err != test.err { t.Errorf("Error resulting from test %d (%d bytes per read) was '%v', expected '%v'", i, j, err, test.err) break } } } } func TestPasswordNotSaved(t *testing.T) { c := &MockTerminal{ toSend: []byte("password\r\x1b[A\r"), bytesPerRead: 1, } ss := NewTerminal(c, "> ") pw, _ := ss.ReadPassword("> ") if pw != "password" { t.Fatalf("failed to read password, got %s", pw) } line, _ := ss.ReadLine() if len(line) > 0 { t.Fatalf("password was saved in history") } } var setSizeTests = []struct { width, height int }{ {40, 13}, {80, 24}, {132, 43}, } func TestTerminalSetSize(t *testing.T) { for _, setSize := range setSizeTests { c := &MockTerminal{ toSend: []byte("password\r\x1b[A\r"), bytesPerRead: 1, } ss := NewTerminal(c, "> ") ss.SetSize(setSize.width, setSize.height) pw, _ := ss.ReadPassword("Password: ") if pw != "password" { t.Fatalf("failed to read password, got %s", pw) } if string(c.received) != "Password: \r\n" { t.Errorf("failed to set the temporary prompt expected %q, got %q", "Password: ", c.received) } } } func TestMakeRawState(t *testing.T) { fd := int(os.Stdout.Fd()) if !IsTerminal(fd) { t.Skip("stdout is not a terminal; skipping test") } st, err := GetState(fd) if err != nil { t.Fatalf("failed to get terminal state from GetState: %s", err) } defer Restore(fd, st) raw, err := MakeRaw(fd) if err != nil { t.Fatalf("failed to get terminal state from MakeRaw: %s", err) } if *st != *raw { t.Errorf("states do not match; was %v, expected %v", raw, st) } } lxd-2.0.0/dist/src/golang.org/x/crypto/ssh/terminal/util_windows.go0000644061062106075000000001051612702772344027765 0ustar00stgraberdomain admins00000000000000// 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. // +build windows // Package terminal provides support functions for dealing with terminals, as // commonly found on UNIX systems. // // Putting a terminal into raw mode is the most common requirement: // // oldState, err := terminal.MakeRaw(0) // if err != nil { // panic(err) // } // defer terminal.Restore(0, oldState) package terminal import ( "io" "syscall" "unsafe" ) const ( enableLineInput = 2 enableEchoInput = 4 enableProcessedInput = 1 enableWindowInput = 8 enableMouseInput = 16 enableInsertMode = 32 enableQuickEditMode = 64 enableExtendedFlags = 128 enableAutoPosition = 256 enableProcessedOutput = 1 enableWrapAtEolOutput = 2 ) var kernel32 = syscall.NewLazyDLL("kernel32.dll") var ( procGetConsoleMode = kernel32.NewProc("GetConsoleMode") procSetConsoleMode = kernel32.NewProc("SetConsoleMode") procGetConsoleScreenBufferInfo = kernel32.NewProc("GetConsoleScreenBufferInfo") ) type ( short int16 word uint16 coord struct { x short y short } smallRect struct { left short top short right short bottom short } consoleScreenBufferInfo struct { size coord cursorPosition coord attributes word window smallRect maximumWindowSize coord } ) type State struct { mode uint32 } // IsTerminal returns true if the given file descriptor is a terminal. func IsTerminal(fd int) bool { var st uint32 r, _, e := syscall.Syscall(procGetConsoleMode.Addr(), 2, uintptr(fd), uintptr(unsafe.Pointer(&st)), 0) return r != 0 && e == 0 } // MakeRaw put the terminal connected to the given file descriptor into raw // mode and returns the previous state of the terminal so that it can be // restored. func MakeRaw(fd int) (*State, error) { var st uint32 _, _, e := syscall.Syscall(procGetConsoleMode.Addr(), 2, uintptr(fd), uintptr(unsafe.Pointer(&st)), 0) if e != 0 { return nil, error(e) } raw := st &^ (enableEchoInput | enableProcessedInput | enableLineInput | enableProcessedOutput) _, _, e = syscall.Syscall(procSetConsoleMode.Addr(), 2, uintptr(fd), uintptr(raw), 0) if e != 0 { return nil, error(e) } return &State{st}, nil } // GetState returns the current state of a terminal which may be useful to // restore the terminal after a signal. func GetState(fd int) (*State, error) { var st uint32 _, _, e := syscall.Syscall(procGetConsoleMode.Addr(), 2, uintptr(fd), uintptr(unsafe.Pointer(&st)), 0) if e != 0 { return nil, error(e) } return &State{st}, nil } // Restore restores the terminal connected to the given file descriptor to a // previous state. func Restore(fd int, state *State) error { _, _, err := syscall.Syscall(procSetConsoleMode.Addr(), 2, uintptr(fd), uintptr(state.mode), 0) return err } // GetSize returns the dimensions of the given terminal. func GetSize(fd int) (width, height int, err error) { var info consoleScreenBufferInfo _, _, e := syscall.Syscall(procGetConsoleScreenBufferInfo.Addr(), 2, uintptr(fd), uintptr(unsafe.Pointer(&info)), 0) if e != 0 { return 0, 0, error(e) } return int(info.size.x), int(info.size.y), nil } // ReadPassword reads a line of input from a terminal without local echo. This // is commonly used for inputting passwords and other sensitive data. The slice // returned does not include the \n. func ReadPassword(fd int) ([]byte, error) { var st uint32 _, _, e := syscall.Syscall(procGetConsoleMode.Addr(), 2, uintptr(fd), uintptr(unsafe.Pointer(&st)), 0) if e != 0 { return nil, error(e) } old := st st &^= (enableEchoInput) st |= (enableProcessedInput | enableLineInput | enableProcessedOutput) _, _, e = syscall.Syscall(procSetConsoleMode.Addr(), 2, uintptr(fd), uintptr(st), 0) if e != 0 { return nil, error(e) } defer func() { syscall.Syscall(procSetConsoleMode.Addr(), 2, uintptr(fd), uintptr(old), 0) }() var buf [16]byte var ret []byte for { n, err := syscall.Read(syscall.Handle(fd), buf[:]) if err != nil { return nil, err } if n == 0 { if len(ret) == 0 { return nil, io.EOF } break } if buf[n-1] == '\n' { n-- } if n > 0 && buf[n-1] == '\r' { n-- } ret = append(ret, buf[:n]...) if n < len(buf) { break } } return ret, nil } lxd-2.0.0/dist/src/golang.org/x/crypto/ssh/terminal/util_bsd.go0000644061062106075000000000051412702772344027040 0ustar00stgraberdomain admins00000000000000// Copyright 2013 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. // +build darwin dragonfly freebsd netbsd openbsd package terminal import "syscall" const ioctlReadTermios = syscall.TIOCGETA const ioctlWriteTermios = syscall.TIOCSETA lxd-2.0.0/dist/src/golang.org/x/crypto/ssh/terminal/terminal.go0000644061062106075000000005100012702772344027042 0ustar00stgraberdomain admins00000000000000// 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 terminal import ( "bytes" "io" "sync" "unicode/utf8" ) // EscapeCodes contains escape sequences that can be written to the terminal in // order to achieve different styles of text. type EscapeCodes struct { // Foreground colors Black, Red, Green, Yellow, Blue, Magenta, Cyan, White []byte // Reset all attributes Reset []byte } var vt100EscapeCodes = EscapeCodes{ Black: []byte{keyEscape, '[', '3', '0', 'm'}, Red: []byte{keyEscape, '[', '3', '1', 'm'}, Green: []byte{keyEscape, '[', '3', '2', 'm'}, Yellow: []byte{keyEscape, '[', '3', '3', 'm'}, Blue: []byte{keyEscape, '[', '3', '4', 'm'}, Magenta: []byte{keyEscape, '[', '3', '5', 'm'}, Cyan: []byte{keyEscape, '[', '3', '6', 'm'}, White: []byte{keyEscape, '[', '3', '7', 'm'}, Reset: []byte{keyEscape, '[', '0', 'm'}, } // Terminal contains the state for running a VT100 terminal that is capable of // reading lines of input. type Terminal struct { // AutoCompleteCallback, if non-null, is called for each keypress with // the full input line and the current position of the cursor (in // bytes, as an index into |line|). If it returns ok=false, the key // press is processed normally. Otherwise it returns a replacement line // and the new cursor position. AutoCompleteCallback func(line string, pos int, key rune) (newLine string, newPos int, ok bool) // Escape contains a pointer to the escape codes for this terminal. // It's always a valid pointer, although the escape codes themselves // may be empty if the terminal doesn't support them. Escape *EscapeCodes // lock protects the terminal and the state in this object from // concurrent processing of a key press and a Write() call. lock sync.Mutex c io.ReadWriter prompt []rune // line is the current line being entered. line []rune // pos is the logical position of the cursor in line pos int // echo is true if local echo is enabled echo bool // pasteActive is true iff there is a bracketed paste operation in // progress. pasteActive bool // cursorX contains the current X value of the cursor where the left // edge is 0. cursorY contains the row number where the first row of // the current line is 0. cursorX, cursorY int // maxLine is the greatest value of cursorY so far. maxLine int termWidth, termHeight int // outBuf contains the terminal data to be sent. outBuf []byte // remainder contains the remainder of any partial key sequences after // a read. It aliases into inBuf. remainder []byte inBuf [256]byte // history contains previously entered commands so that they can be // accessed with the up and down keys. history stRingBuffer // historyIndex stores the currently accessed history entry, where zero // means the immediately previous entry. historyIndex int // When navigating up and down the history it's possible to return to // the incomplete, initial line. That value is stored in // historyPending. historyPending string } // NewTerminal runs a VT100 terminal on the given ReadWriter. If the ReadWriter is // a local terminal, that terminal must first have been put into raw mode. // prompt is a string that is written at the start of each input line (i.e. // "> "). func NewTerminal(c io.ReadWriter, prompt string) *Terminal { return &Terminal{ Escape: &vt100EscapeCodes, c: c, prompt: []rune(prompt), termWidth: 80, termHeight: 24, echo: true, historyIndex: -1, } } const ( keyCtrlD = 4 keyCtrlU = 21 keyEnter = '\r' keyEscape = 27 keyBackspace = 127 keyUnknown = 0xd800 /* UTF-16 surrogate area */ + iota keyUp keyDown keyLeft keyRight keyAltLeft keyAltRight keyHome keyEnd keyDeleteWord keyDeleteLine keyClearScreen keyPasteStart keyPasteEnd ) var pasteStart = []byte{keyEscape, '[', '2', '0', '0', '~'} var pasteEnd = []byte{keyEscape, '[', '2', '0', '1', '~'} // bytesToKey tries to parse a key sequence from b. If successful, it returns // the key and the remainder of the input. Otherwise it returns utf8.RuneError. func bytesToKey(b []byte, pasteActive bool) (rune, []byte) { if len(b) == 0 { return utf8.RuneError, nil } if !pasteActive { switch b[0] { case 1: // ^A return keyHome, b[1:] case 5: // ^E return keyEnd, b[1:] case 8: // ^H return keyBackspace, b[1:] case 11: // ^K return keyDeleteLine, b[1:] case 12: // ^L return keyClearScreen, b[1:] case 23: // ^W return keyDeleteWord, b[1:] } } if b[0] != keyEscape { if !utf8.FullRune(b) { return utf8.RuneError, b } r, l := utf8.DecodeRune(b) return r, b[l:] } if !pasteActive && len(b) >= 3 && b[0] == keyEscape && b[1] == '[' { switch b[2] { case 'A': return keyUp, b[3:] case 'B': return keyDown, b[3:] case 'C': return keyRight, b[3:] case 'D': return keyLeft, b[3:] case 'H': return keyHome, b[3:] case 'F': return keyEnd, b[3:] } } if !pasteActive && len(b) >= 6 && b[0] == keyEscape && b[1] == '[' && b[2] == '1' && b[3] == ';' && b[4] == '3' { switch b[5] { case 'C': return keyAltRight, b[6:] case 'D': return keyAltLeft, b[6:] } } if !pasteActive && len(b) >= 6 && bytes.Equal(b[:6], pasteStart) { return keyPasteStart, b[6:] } if pasteActive && len(b) >= 6 && bytes.Equal(b[:6], pasteEnd) { return keyPasteEnd, b[6:] } // If we get here then we have a key that we don't recognise, or a // partial sequence. It's not clear how one should find the end of a // sequence without knowing them all, but it seems that [a-zA-Z~] only // appears at the end of a sequence. for i, c := range b[0:] { if c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c == '~' { return keyUnknown, b[i+1:] } } return utf8.RuneError, b } // queue appends data to the end of t.outBuf func (t *Terminal) queue(data []rune) { t.outBuf = append(t.outBuf, []byte(string(data))...) } var eraseUnderCursor = []rune{' ', keyEscape, '[', 'D'} var space = []rune{' '} func isPrintable(key rune) bool { isInSurrogateArea := key >= 0xd800 && key <= 0xdbff return key >= 32 && !isInSurrogateArea } // moveCursorToPos appends data to t.outBuf which will move the cursor to the // given, logical position in the text. func (t *Terminal) moveCursorToPos(pos int) { if !t.echo { return } x := visualLength(t.prompt) + pos y := x / t.termWidth x = x % t.termWidth up := 0 if y < t.cursorY { up = t.cursorY - y } down := 0 if y > t.cursorY { down = y - t.cursorY } left := 0 if x < t.cursorX { left = t.cursorX - x } right := 0 if x > t.cursorX { right = x - t.cursorX } t.cursorX = x t.cursorY = y t.move(up, down, left, right) } func (t *Terminal) move(up, down, left, right int) { movement := make([]rune, 3*(up+down+left+right)) m := movement for i := 0; i < up; i++ { m[0] = keyEscape m[1] = '[' m[2] = 'A' m = m[3:] } for i := 0; i < down; i++ { m[0] = keyEscape m[1] = '[' m[2] = 'B' m = m[3:] } for i := 0; i < left; i++ { m[0] = keyEscape m[1] = '[' m[2] = 'D' m = m[3:] } for i := 0; i < right; i++ { m[0] = keyEscape m[1] = '[' m[2] = 'C' m = m[3:] } t.queue(movement) } func (t *Terminal) clearLineToRight() { op := []rune{keyEscape, '[', 'K'} t.queue(op) } const maxLineLength = 4096 func (t *Terminal) setLine(newLine []rune, newPos int) { if t.echo { t.moveCursorToPos(0) t.writeLine(newLine) for i := len(newLine); i < len(t.line); i++ { t.writeLine(space) } t.moveCursorToPos(newPos) } t.line = newLine t.pos = newPos } func (t *Terminal) advanceCursor(places int) { t.cursorX += places t.cursorY += t.cursorX / t.termWidth if t.cursorY > t.maxLine { t.maxLine = t.cursorY } t.cursorX = t.cursorX % t.termWidth if places > 0 && t.cursorX == 0 { // Normally terminals will advance the current position // when writing a character. But that doesn't happen // for the last character in a line. However, when // writing a character (except a new line) that causes // a line wrap, the position will be advanced two // places. // // So, if we are stopping at the end of a line, we // need to write a newline so that our cursor can be // advanced to the next line. t.outBuf = append(t.outBuf, '\n') } } func (t *Terminal) eraseNPreviousChars(n int) { if n == 0 { return } if t.pos < n { n = t.pos } t.pos -= n t.moveCursorToPos(t.pos) copy(t.line[t.pos:], t.line[n+t.pos:]) t.line = t.line[:len(t.line)-n] if t.echo { t.writeLine(t.line[t.pos:]) for i := 0; i < n; i++ { t.queue(space) } t.advanceCursor(n) t.moveCursorToPos(t.pos) } } // countToLeftWord returns then number of characters from the cursor to the // start of the previous word. func (t *Terminal) countToLeftWord() int { if t.pos == 0 { return 0 } pos := t.pos - 1 for pos > 0 { if t.line[pos] != ' ' { break } pos-- } for pos > 0 { if t.line[pos] == ' ' { pos++ break } pos-- } return t.pos - pos } // countToRightWord returns then number of characters from the cursor to the // start of the next word. func (t *Terminal) countToRightWord() int { pos := t.pos for pos < len(t.line) { if t.line[pos] == ' ' { break } pos++ } for pos < len(t.line) { if t.line[pos] != ' ' { break } pos++ } return pos - t.pos } // visualLength returns the number of visible glyphs in s. func visualLength(runes []rune) int { inEscapeSeq := false length := 0 for _, r := range runes { switch { case inEscapeSeq: if (r >= 'a' && r <= 'z') || (r >= 'A' && r <= 'Z') { inEscapeSeq = false } case r == '\x1b': inEscapeSeq = true default: length++ } } return length } // handleKey processes the given key and, optionally, returns a line of text // that the user has entered. func (t *Terminal) handleKey(key rune) (line string, ok bool) { if t.pasteActive && key != keyEnter { t.addKeyToLine(key) return } switch key { case keyBackspace: if t.pos == 0 { return } t.eraseNPreviousChars(1) case keyAltLeft: // move left by a word. t.pos -= t.countToLeftWord() t.moveCursorToPos(t.pos) case keyAltRight: // move right by a word. t.pos += t.countToRightWord() t.moveCursorToPos(t.pos) case keyLeft: if t.pos == 0 { return } t.pos-- t.moveCursorToPos(t.pos) case keyRight: if t.pos == len(t.line) { return } t.pos++ t.moveCursorToPos(t.pos) case keyHome: if t.pos == 0 { return } t.pos = 0 t.moveCursorToPos(t.pos) case keyEnd: if t.pos == len(t.line) { return } t.pos = len(t.line) t.moveCursorToPos(t.pos) case keyUp: entry, ok := t.history.NthPreviousEntry(t.historyIndex + 1) if !ok { return "", false } if t.historyIndex == -1 { t.historyPending = string(t.line) } t.historyIndex++ runes := []rune(entry) t.setLine(runes, len(runes)) case keyDown: switch t.historyIndex { case -1: return case 0: runes := []rune(t.historyPending) t.setLine(runes, len(runes)) t.historyIndex-- default: entry, ok := t.history.NthPreviousEntry(t.historyIndex - 1) if ok { t.historyIndex-- runes := []rune(entry) t.setLine(runes, len(runes)) } } case keyEnter: t.moveCursorToPos(len(t.line)) t.queue([]rune("\r\n")) line = string(t.line) ok = true t.line = t.line[:0] t.pos = 0 t.cursorX = 0 t.cursorY = 0 t.maxLine = 0 case keyDeleteWord: // Delete zero or more spaces and then one or more characters. t.eraseNPreviousChars(t.countToLeftWord()) case keyDeleteLine: // Delete everything from the current cursor position to the // end of line. for i := t.pos; i < len(t.line); i++ { t.queue(space) t.advanceCursor(1) } t.line = t.line[:t.pos] t.moveCursorToPos(t.pos) case keyCtrlD: // Erase the character under the current position. // The EOF case when the line is empty is handled in // readLine(). if t.pos < len(t.line) { t.pos++ t.eraseNPreviousChars(1) } case keyCtrlU: t.eraseNPreviousChars(t.pos) case keyClearScreen: // Erases the screen and moves the cursor to the home position. t.queue([]rune("\x1b[2J\x1b[H")) t.queue(t.prompt) t.cursorX, t.cursorY = 0, 0 t.advanceCursor(visualLength(t.prompt)) t.setLine(t.line, t.pos) default: if t.AutoCompleteCallback != nil { prefix := string(t.line[:t.pos]) suffix := string(t.line[t.pos:]) t.lock.Unlock() newLine, newPos, completeOk := t.AutoCompleteCallback(prefix+suffix, len(prefix), key) t.lock.Lock() if completeOk { t.setLine([]rune(newLine), utf8.RuneCount([]byte(newLine)[:newPos])) return } } if !isPrintable(key) { return } if len(t.line) == maxLineLength { return } t.addKeyToLine(key) } return } // addKeyToLine inserts the given key at the current position in the current // line. func (t *Terminal) addKeyToLine(key rune) { if len(t.line) == cap(t.line) { newLine := make([]rune, len(t.line), 2*(1+len(t.line))) copy(newLine, t.line) t.line = newLine } t.line = t.line[:len(t.line)+1] copy(t.line[t.pos+1:], t.line[t.pos:]) t.line[t.pos] = key if t.echo { t.writeLine(t.line[t.pos:]) } t.pos++ t.moveCursorToPos(t.pos) } func (t *Terminal) writeLine(line []rune) { for len(line) != 0 { remainingOnLine := t.termWidth - t.cursorX todo := len(line) if todo > remainingOnLine { todo = remainingOnLine } t.queue(line[:todo]) t.advanceCursor(visualLength(line[:todo])) line = line[todo:] } } func (t *Terminal) Write(buf []byte) (n int, err error) { t.lock.Lock() defer t.lock.Unlock() if t.cursorX == 0 && t.cursorY == 0 { // This is the easy case: there's nothing on the screen that we // have to move out of the way. return t.c.Write(buf) } // We have a prompt and possibly user input on the screen. We // have to clear it first. t.move(0 /* up */, 0 /* down */, t.cursorX /* left */, 0 /* right */) t.cursorX = 0 t.clearLineToRight() for t.cursorY > 0 { t.move(1 /* up */, 0, 0, 0) t.cursorY-- t.clearLineToRight() } if _, err = t.c.Write(t.outBuf); err != nil { return } t.outBuf = t.outBuf[:0] if n, err = t.c.Write(buf); err != nil { return } t.writeLine(t.prompt) if t.echo { t.writeLine(t.line) } t.moveCursorToPos(t.pos) if _, err = t.c.Write(t.outBuf); err != nil { return } t.outBuf = t.outBuf[:0] return } // ReadPassword temporarily changes the prompt and reads a password, without // echo, from the terminal. func (t *Terminal) ReadPassword(prompt string) (line string, err error) { t.lock.Lock() defer t.lock.Unlock() oldPrompt := t.prompt t.prompt = []rune(prompt) t.echo = false line, err = t.readLine() t.prompt = oldPrompt t.echo = true return } // ReadLine returns a line of input from the terminal. func (t *Terminal) ReadLine() (line string, err error) { t.lock.Lock() defer t.lock.Unlock() return t.readLine() } func (t *Terminal) readLine() (line string, err error) { // t.lock must be held at this point if t.cursorX == 0 && t.cursorY == 0 { t.writeLine(t.prompt) t.c.Write(t.outBuf) t.outBuf = t.outBuf[:0] } lineIsPasted := t.pasteActive for { rest := t.remainder lineOk := false for !lineOk { var key rune key, rest = bytesToKey(rest, t.pasteActive) if key == utf8.RuneError { break } if !t.pasteActive { if key == keyCtrlD { if len(t.line) == 0 { return "", io.EOF } } if key == keyPasteStart { t.pasteActive = true if len(t.line) == 0 { lineIsPasted = true } continue } } else if key == keyPasteEnd { t.pasteActive = false continue } if !t.pasteActive { lineIsPasted = false } line, lineOk = t.handleKey(key) } if len(rest) > 0 { n := copy(t.inBuf[:], rest) t.remainder = t.inBuf[:n] } else { t.remainder = nil } t.c.Write(t.outBuf) t.outBuf = t.outBuf[:0] if lineOk { if t.echo { t.historyIndex = -1 t.history.Add(line) } if lineIsPasted { err = ErrPasteIndicator } return } // t.remainder is a slice at the beginning of t.inBuf // containing a partial key sequence readBuf := t.inBuf[len(t.remainder):] var n int t.lock.Unlock() n, err = t.c.Read(readBuf) t.lock.Lock() if err != nil { return } t.remainder = t.inBuf[:n+len(t.remainder)] } panic("unreachable") // for Go 1.0. } // SetPrompt sets the prompt to be used when reading subsequent lines. func (t *Terminal) SetPrompt(prompt string) { t.lock.Lock() defer t.lock.Unlock() t.prompt = []rune(prompt) } func (t *Terminal) clearAndRepaintLinePlusNPrevious(numPrevLines int) { // Move cursor to column zero at the start of the line. t.move(t.cursorY, 0, t.cursorX, 0) t.cursorX, t.cursorY = 0, 0 t.clearLineToRight() for t.cursorY < numPrevLines { // Move down a line t.move(0, 1, 0, 0) t.cursorY++ t.clearLineToRight() } // Move back to beginning. t.move(t.cursorY, 0, 0, 0) t.cursorX, t.cursorY = 0, 0 t.queue(t.prompt) t.advanceCursor(visualLength(t.prompt)) t.writeLine(t.line) t.moveCursorToPos(t.pos) } func (t *Terminal) SetSize(width, height int) error { t.lock.Lock() defer t.lock.Unlock() if width == 0 { width = 1 } oldWidth := t.termWidth t.termWidth, t.termHeight = width, height switch { case width == oldWidth: // If the width didn't change then nothing else needs to be // done. return nil case len(t.line) == 0 && t.cursorX == 0 && t.cursorY == 0: // If there is nothing on current line and no prompt printed, // just do nothing return nil case width < oldWidth: // Some terminals (e.g. xterm) will truncate lines that were // too long when shinking. Others, (e.g. gnome-terminal) will // attempt to wrap them. For the former, repainting t.maxLine // works great, but that behaviour goes badly wrong in the case // of the latter because they have doubled every full line. // We assume that we are working on a terminal that wraps lines // and adjust the cursor position based on every previous line // wrapping and turning into two. This causes the prompt on // xterms to move upwards, which isn't great, but it avoids a // huge mess with gnome-terminal. if t.cursorX >= t.termWidth { t.cursorX = t.termWidth - 1 } t.cursorY *= 2 t.clearAndRepaintLinePlusNPrevious(t.maxLine * 2) case width > oldWidth: // If the terminal expands then our position calculations will // be wrong in the future because we think the cursor is // |t.pos| chars into the string, but there will be a gap at // the end of any wrapped line. // // But the position will actually be correct until we move, so // we can move back to the beginning and repaint everything. t.clearAndRepaintLinePlusNPrevious(t.maxLine) } _, err := t.c.Write(t.outBuf) t.outBuf = t.outBuf[:0] return err } type pasteIndicatorError struct{} func (pasteIndicatorError) Error() string { return "terminal: ErrPasteIndicator not correctly handled" } // ErrPasteIndicator may be returned from ReadLine as the error, in addition // to valid line data. It indicates that bracketed paste mode is enabled and // that the returned line consists only of pasted data. Programs may wish to // interpret pasted data more literally than typed data. var ErrPasteIndicator = pasteIndicatorError{} // SetBracketedPasteMode requests that the terminal bracket paste operations // with markers. Not all terminals support this but, if it is supported, then // enabling this mode will stop any autocomplete callback from running due to // pastes. Additionally, any lines that are completely pasted will be returned // from ReadLine with the error set to ErrPasteIndicator. func (t *Terminal) SetBracketedPasteMode(on bool) { if on { io.WriteString(t.c, "\x1b[?2004h") } else { io.WriteString(t.c, "\x1b[?2004l") } } // stRingBuffer is a ring buffer of strings. type stRingBuffer struct { // entries contains max elements. entries []string max int // head contains the index of the element most recently added to the ring. head int // size contains the number of elements in the ring. size int } func (s *stRingBuffer) Add(a string) { if s.entries == nil { const defaultNumEntries = 100 s.entries = make([]string, defaultNumEntries) s.max = defaultNumEntries } s.head = (s.head + 1) % s.max s.entries[s.head] = a if s.size < s.max { s.size++ } } // NthPreviousEntry returns the value passed to the nth previous call to Add. // If n is zero then the immediately prior value is returned, if one, then the // next most recent, and so on. If such an element doesn't exist then ok is // false. func (s *stRingBuffer) NthPreviousEntry(n int) (value string, ok bool) { if n >= s.size { return "", false } index := s.head - n if index < 0 { index += s.max } return s.entries[index], true } lxd-2.0.0/dist/src/golang.org/x/crypto/ssh/terminal/util_linux.go0000644061062106075000000000071112702772344027426 0ustar00stgraberdomain admins00000000000000// Copyright 2013 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 terminal // These constants are declared here, rather than importing // them from the syscall package as some syscall packages, even // on linux, for example gccgo, do not declare them. const ioctlReadTermios = 0x5401 // syscall.TCGETS const ioctlWriteTermios = 0x5402 // syscall.TCSETS lxd-2.0.0/dist/src/golang.org/x/crypto/ssh/tcpip.go0000644061062106075000000002441312702772344024543 0ustar00stgraberdomain admins00000000000000// 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 ssh import ( "errors" "fmt" "io" "math/rand" "net" "strconv" "strings" "sync" "time" ) // Listen requests the remote peer open a listening socket on // addr. Incoming connections will be available by calling Accept on // the returned net.Listener. The listener must be serviced, or the // SSH connection may hang. func (c *Client) Listen(n, addr string) (net.Listener, error) { laddr, err := net.ResolveTCPAddr(n, addr) if err != nil { return nil, err } return c.ListenTCP(laddr) } // Automatic port allocation is broken with OpenSSH before 6.0. See // also https://bugzilla.mindrot.org/show_bug.cgi?id=2017. In // particular, OpenSSH 5.9 sends a channelOpenMsg with port number 0, // rather than the actual port number. This means you can never open // two different listeners with auto allocated ports. We work around // this by trying explicit ports until we succeed. const openSSHPrefix = "OpenSSH_" var portRandomizer = rand.New(rand.NewSource(time.Now().UnixNano())) // isBrokenOpenSSHVersion returns true if the given version string // specifies a version of OpenSSH that is known to have a bug in port // forwarding. func isBrokenOpenSSHVersion(versionStr string) bool { i := strings.Index(versionStr, openSSHPrefix) if i < 0 { return false } i += len(openSSHPrefix) j := i for ; j < len(versionStr); j++ { if versionStr[j] < '0' || versionStr[j] > '9' { break } } version, _ := strconv.Atoi(versionStr[i:j]) return version < 6 } // autoPortListenWorkaround simulates automatic port allocation by // trying random ports repeatedly. func (c *Client) autoPortListenWorkaround(laddr *net.TCPAddr) (net.Listener, error) { var sshListener net.Listener var err error const tries = 10 for i := 0; i < tries; i++ { addr := *laddr addr.Port = 1024 + portRandomizer.Intn(60000) sshListener, err = c.ListenTCP(&addr) if err == nil { laddr.Port = addr.Port return sshListener, err } } return nil, fmt.Errorf("ssh: listen on random port failed after %d tries: %v", tries, err) } // RFC 4254 7.1 type channelForwardMsg struct { addr string rport uint32 } // ListenTCP requests the remote peer open a listening socket // on laddr. Incoming connections will be available by calling // Accept on the returned net.Listener. func (c *Client) ListenTCP(laddr *net.TCPAddr) (net.Listener, error) { if laddr.Port == 0 && isBrokenOpenSSHVersion(string(c.ServerVersion())) { return c.autoPortListenWorkaround(laddr) } m := channelForwardMsg{ laddr.IP.String(), uint32(laddr.Port), } // send message ok, resp, err := c.SendRequest("tcpip-forward", true, Marshal(&m)) if err != nil { return nil, err } if !ok { return nil, errors.New("ssh: tcpip-forward request denied by peer") } // If the original port was 0, then the remote side will // supply a real port number in the response. if laddr.Port == 0 { var p struct { Port uint32 } if err := Unmarshal(resp, &p); err != nil { return nil, err } laddr.Port = int(p.Port) } // Register this forward, using the port number we obtained. ch := c.forwards.add(*laddr) return &tcpListener{laddr, c, ch}, nil } // forwardList stores a mapping between remote // forward requests and the tcpListeners. type forwardList struct { sync.Mutex entries []forwardEntry } // forwardEntry represents an established mapping of a laddr on a // remote ssh server to a channel connected to a tcpListener. type forwardEntry struct { laddr net.TCPAddr c chan forward } // forward represents an incoming forwarded tcpip connection. The // arguments to add/remove/lookup should be address as specified in // the original forward-request. type forward struct { newCh NewChannel // the ssh client channel underlying this forward raddr *net.TCPAddr // the raddr of the incoming connection } func (l *forwardList) add(addr net.TCPAddr) chan forward { l.Lock() defer l.Unlock() f := forwardEntry{ addr, make(chan forward, 1), } l.entries = append(l.entries, f) return f.c } // See RFC 4254, section 7.2 type forwardedTCPPayload struct { Addr string Port uint32 OriginAddr string OriginPort uint32 } // parseTCPAddr parses the originating address from the remote into a *net.TCPAddr. func parseTCPAddr(addr string, port uint32) (*net.TCPAddr, error) { if port == 0 || port > 65535 { return nil, fmt.Errorf("ssh: port number out of range: %d", port) } ip := net.ParseIP(string(addr)) if ip == nil { return nil, fmt.Errorf("ssh: cannot parse IP address %q", addr) } return &net.TCPAddr{IP: ip, Port: int(port)}, nil } func (l *forwardList) handleChannels(in <-chan NewChannel) { for ch := range in { var payload forwardedTCPPayload if err := Unmarshal(ch.ExtraData(), &payload); err != nil { ch.Reject(ConnectionFailed, "could not parse forwarded-tcpip payload: "+err.Error()) continue } // RFC 4254 section 7.2 specifies that incoming // addresses should list the address, in string // format. It is implied that this should be an IP // address, as it would be impossible to connect to it // otherwise. laddr, err := parseTCPAddr(payload.Addr, payload.Port) if err != nil { ch.Reject(ConnectionFailed, err.Error()) continue } raddr, err := parseTCPAddr(payload.OriginAddr, payload.OriginPort) if err != nil { ch.Reject(ConnectionFailed, err.Error()) continue } if ok := l.forward(*laddr, *raddr, ch); !ok { // Section 7.2, implementations MUST reject spurious incoming // connections. ch.Reject(Prohibited, "no forward for address") continue } } } // remove removes the forward entry, and the channel feeding its // listener. func (l *forwardList) remove(addr net.TCPAddr) { l.Lock() defer l.Unlock() for i, f := range l.entries { if addr.IP.Equal(f.laddr.IP) && addr.Port == f.laddr.Port { l.entries = append(l.entries[:i], l.entries[i+1:]...) close(f.c) return } } } // closeAll closes and clears all forwards. func (l *forwardList) closeAll() { l.Lock() defer l.Unlock() for _, f := range l.entries { close(f.c) } l.entries = nil } func (l *forwardList) forward(laddr, raddr net.TCPAddr, ch NewChannel) bool { l.Lock() defer l.Unlock() for _, f := range l.entries { if laddr.IP.Equal(f.laddr.IP) && laddr.Port == f.laddr.Port { f.c <- forward{ch, &raddr} return true } } return false } type tcpListener struct { laddr *net.TCPAddr conn *Client in <-chan forward } // Accept waits for and returns the next connection to the listener. func (l *tcpListener) Accept() (net.Conn, error) { s, ok := <-l.in if !ok { return nil, io.EOF } ch, incoming, err := s.newCh.Accept() if err != nil { return nil, err } go DiscardRequests(incoming) return &tcpChanConn{ Channel: ch, laddr: l.laddr, raddr: s.raddr, }, nil } // Close closes the listener. func (l *tcpListener) Close() error { m := channelForwardMsg{ l.laddr.IP.String(), uint32(l.laddr.Port), } // this also closes the listener. l.conn.forwards.remove(*l.laddr) ok, _, err := l.conn.SendRequest("cancel-tcpip-forward", true, Marshal(&m)) if err == nil && !ok { err = errors.New("ssh: cancel-tcpip-forward failed") } return err } // Addr returns the listener's network address. func (l *tcpListener) Addr() net.Addr { return l.laddr } // Dial initiates a connection to the addr from the remote host. // The resulting connection has a zero LocalAddr() and RemoteAddr(). func (c *Client) Dial(n, addr string) (net.Conn, error) { // Parse the address into host and numeric port. host, portString, err := net.SplitHostPort(addr) if err != nil { return nil, err } port, err := strconv.ParseUint(portString, 10, 16) if err != nil { return nil, err } // Use a zero address for local and remote address. zeroAddr := &net.TCPAddr{ IP: net.IPv4zero, Port: 0, } ch, err := c.dial(net.IPv4zero.String(), 0, host, int(port)) if err != nil { return nil, err } return &tcpChanConn{ Channel: ch, laddr: zeroAddr, raddr: zeroAddr, }, nil } // DialTCP connects to the remote address raddr on the network net, // which must be "tcp", "tcp4", or "tcp6". If laddr is not nil, it is used // as the local address for the connection. func (c *Client) DialTCP(n string, laddr, raddr *net.TCPAddr) (net.Conn, error) { if laddr == nil { laddr = &net.TCPAddr{ IP: net.IPv4zero, Port: 0, } } ch, err := c.dial(laddr.IP.String(), laddr.Port, raddr.IP.String(), raddr.Port) if err != nil { return nil, err } return &tcpChanConn{ Channel: ch, laddr: laddr, raddr: raddr, }, nil } // RFC 4254 7.2 type channelOpenDirectMsg struct { raddr string rport uint32 laddr string lport uint32 } func (c *Client) dial(laddr string, lport int, raddr string, rport int) (Channel, error) { msg := channelOpenDirectMsg{ raddr: raddr, rport: uint32(rport), laddr: laddr, lport: uint32(lport), } ch, in, err := c.OpenChannel("direct-tcpip", Marshal(&msg)) if err != nil { return nil, err } go DiscardRequests(in) return ch, err } type tcpChan struct { Channel // the backing channel } // tcpChanConn fulfills the net.Conn interface without // the tcpChan having to hold laddr or raddr directly. type tcpChanConn struct { Channel laddr, raddr net.Addr } // LocalAddr returns the local network address. func (t *tcpChanConn) LocalAddr() net.Addr { return t.laddr } // RemoteAddr returns the remote network address. func (t *tcpChanConn) RemoteAddr() net.Addr { return t.raddr } // SetDeadline sets the read and write deadlines associated // with the connection. func (t *tcpChanConn) SetDeadline(deadline time.Time) error { if err := t.SetReadDeadline(deadline); err != nil { return err } return t.SetWriteDeadline(deadline) } // SetReadDeadline sets the read deadline. // A zero value for t means Read will not time out. // After the deadline, the error from Read will implement net.Error // with Timeout() == true. func (t *tcpChanConn) SetReadDeadline(deadline time.Time) error { return errors.New("ssh: tcpChan: deadline not supported") } // SetWriteDeadline exists to satisfy the net.Conn interface // but is not implemented by this type. It always returns an error. func (t *tcpChanConn) SetWriteDeadline(deadline time.Time) error { return errors.New("ssh: tcpChan: deadline not supported") } lxd-2.0.0/dist/src/golang.org/x/crypto/otr/0000755061062106075000000000000012702772344023100 5ustar00stgraberdomain admins00000000000000lxd-2.0.0/dist/src/golang.org/x/crypto/otr/otr_test.go0000644061062106075000000003516212702772344025301 0ustar00stgraberdomain admins00000000000000// Copyright 2012 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 otr import ( "bufio" "bytes" "crypto/rand" "encoding/hex" "math/big" "os" "os/exec" "testing" ) var isQueryTests = []struct { msg string expectedVersion int }{ {"foo", 0}, {"?OtR", 0}, {"?OtR?", 0}, {"?OTR?", 0}, {"?OTRv?", 0}, {"?OTRv1?", 0}, {"?OTR?v1?", 0}, {"?OTR?v?", 0}, {"?OTR?v2?", 2}, {"?OTRv2?", 2}, {"?OTRv23?", 2}, {"?OTRv23 ?", 0}, } func TestIsQuery(t *testing.T) { for i, test := range isQueryTests { version := isQuery([]byte(test.msg)) if version != test.expectedVersion { t.Errorf("#%d: got %d, want %d", i, version, test.expectedVersion) } } } var alicePrivateKeyHex = "000000000080c81c2cb2eb729b7e6fd48e975a932c638b3a9055478583afa46755683e30102447f6da2d8bec9f386bbb5da6403b0040fee8650b6ab2d7f32c55ab017ae9b6aec8c324ab5844784e9a80e194830d548fb7f09a0410df2c4d5c8bc2b3e9ad484e65412be689cf0834694e0839fb2954021521ffdffb8f5c32c14dbf2020b3ce7500000014da4591d58def96de61aea7b04a8405fe1609308d000000808ddd5cb0b9d66956e3dea5a915d9aba9d8a6e7053b74dadb2fc52f9fe4e5bcc487d2305485ed95fed026ad93f06ebb8c9e8baf693b7887132c7ffdd3b0f72f4002ff4ed56583ca7c54458f8c068ca3e8a4dfa309d1dd5d34e2a4b68e6f4338835e5e0fb4317c9e4c7e4806dafda3ef459cd563775a586dd91b1319f72621bf3f00000080b8147e74d8c45e6318c37731b8b33b984a795b3653c2cd1d65cc99efe097cb7eb2fa49569bab5aab6e8a1c261a27d0f7840a5e80b317e6683042b59b6dceca2879c6ffc877a465be690c15e4a42f9a7588e79b10faac11b1ce3741fcef7aba8ce05327a2c16d279ee1b3d77eb783fb10e3356caa25635331e26dd42b8396c4d00000001420bec691fea37ecea58a5c717142f0b804452f57" var aliceFingerprintHex = "0bb01c360424522e94ee9c346ce877a1a4288b2f" var bobPrivateKeyHex = "000000000080a5138eb3d3eb9c1d85716faecadb718f87d31aaed1157671d7fee7e488f95e8e0ba60ad449ec732710a7dec5190f7182af2e2f98312d98497221dff160fd68033dd4f3a33b7c078d0d9f66e26847e76ca7447d4bab35486045090572863d9e4454777f24d6706f63e02548dfec2d0a620af37bbc1d24f884708a212c343b480d00000014e9c58f0ea21a5e4dfd9f44b6a9f7f6a9961a8fa9000000803c4d111aebd62d3c50c2889d420a32cdf1e98b70affcc1fcf44d59cca2eb019f6b774ef88153fb9b9615441a5fe25ea2d11b74ce922ca0232bd81b3c0fcac2a95b20cb6e6c0c5c1ace2e26f65dc43c751af0edbb10d669890e8ab6beea91410b8b2187af1a8347627a06ecea7e0f772c28aae9461301e83884860c9b656c722f0000008065af8625a555ea0e008cd04743671a3cda21162e83af045725db2eb2bb52712708dc0cc1a84c08b3649b88a966974bde27d8612c2861792ec9f08786a246fcadd6d8d3a81a32287745f309238f47618c2bd7612cb8b02d940571e0f30b96420bcd462ff542901b46109b1e5ad6423744448d20a57818a8cbb1647d0fea3b664e0000001440f9f2eb554cb00d45a5826b54bfa419b6980e48" func TestKeySerialization(t *testing.T) { var priv PrivateKey alicePrivateKey, _ := hex.DecodeString(alicePrivateKeyHex) rest, ok := priv.Parse(alicePrivateKey) if !ok { t.Error("failed to parse private key") } if len(rest) > 0 { t.Error("data remaining after parsing private key") } out := priv.Serialize(nil) if !bytes.Equal(alicePrivateKey, out) { t.Errorf("serialization (%x) is not equal to original (%x)", out, alicePrivateKey) } aliceFingerprint, _ := hex.DecodeString(aliceFingerprintHex) fingerprint := priv.PublicKey.Fingerprint() if !bytes.Equal(aliceFingerprint, fingerprint) { t.Errorf("fingerprint (%x) is not equal to expected value (%x)", fingerprint, aliceFingerprint) } } const libOTRPrivateKey = `(privkeys (account (name "foo@example.com") (protocol prpl-jabber) (private-key (dsa (p #00FC07ABCF0DC916AFF6E9AE47BEF60C7AB9B4D6B2469E436630E36F8A489BE812486A09F30B71224508654940A835301ACC525A4FF133FC152CC53DCC59D65C30A54F1993FE13FE63E5823D4C746DB21B90F9B9C00B49EC7404AB1D929BA7FBA12F2E45C6E0A651689750E8528AB8C031D3561FECEE72EBB4A090D450A9B7A857#) (q #00997BD266EF7B1F60A5C23F3A741F2AEFD07A2081#) (g #535E360E8A95EBA46A4F7DE50AD6E9B2A6DB785A66B64EB9F20338D2A3E8FB0E94725848F1AA6CC567CB83A1CC517EC806F2E92EAE71457E80B2210A189B91250779434B41FC8A8873F6DB94BEA7D177F5D59E7E114EE10A49CFD9CEF88AE43387023B672927BA74B04EB6BBB5E57597766A2F9CE3857D7ACE3E1E3BC1FC6F26#) (y #0AC8670AD767D7A8D9D14CC1AC6744CD7D76F993B77FFD9E39DF01E5A6536EF65E775FCEF2A983E2A19BD6415500F6979715D9FD1257E1FE2B6F5E1E74B333079E7C880D39868462A93454B41877BE62E5EF0A041C2EE9C9E76BD1E12AE25D9628DECB097025DD625EF49C3258A1A3C0FF501E3DC673B76D7BABF349009B6ECF#) (x #14D0345A3562C480A039E3C72764F72D79043216#) ) ) ) )` func TestParseLibOTRPrivateKey(t *testing.T) { var priv PrivateKey if !priv.Import([]byte(libOTRPrivateKey)) { t.Fatalf("Failed to import sample private key") } } func TestSignVerify(t *testing.T) { var priv PrivateKey alicePrivateKey, _ := hex.DecodeString(alicePrivateKeyHex) _, ok := priv.Parse(alicePrivateKey) if !ok { t.Error("failed to parse private key") } var msg [32]byte rand.Reader.Read(msg[:]) sig := priv.Sign(rand.Reader, msg[:]) rest, ok := priv.PublicKey.Verify(msg[:], sig) if !ok { t.Errorf("signature (%x) of %x failed to verify", sig, msg[:]) } else if len(rest) > 0 { t.Error("signature data remains after verification") } sig[10] ^= 80 _, ok = priv.PublicKey.Verify(msg[:], sig) if ok { t.Errorf("corrupted signature (%x) of %x verified", sig, msg[:]) } } func setupConversation(t *testing.T) (alice, bob *Conversation) { alicePrivateKey, _ := hex.DecodeString(alicePrivateKeyHex) bobPrivateKey, _ := hex.DecodeString(bobPrivateKeyHex) alice, bob = new(Conversation), new(Conversation) alice.PrivateKey = new(PrivateKey) bob.PrivateKey = new(PrivateKey) alice.PrivateKey.Parse(alicePrivateKey) bob.PrivateKey.Parse(bobPrivateKey) alice.FragmentSize = 100 bob.FragmentSize = 100 if alice.IsEncrypted() { t.Error("Alice believes that the conversation is secure before we've started") } if bob.IsEncrypted() { t.Error("Bob believes that the conversation is secure before we've started") } performHandshake(t, alice, bob) return alice, bob } func performHandshake(t *testing.T, alice, bob *Conversation) { var alicesMessage, bobsMessage [][]byte var out []byte var aliceChange, bobChange SecurityChange var err error alicesMessage = append(alicesMessage, []byte(QueryMessage)) for round := 0; len(alicesMessage) > 0 || len(bobsMessage) > 0; round++ { bobsMessage = nil for i, msg := range alicesMessage { out, _, bobChange, bobsMessage, err = bob.Receive(msg) if len(out) > 0 { t.Errorf("Bob generated output during key exchange, round %d, message %d", round, i) } if err != nil { t.Fatalf("Bob returned an error, round %d, message %d (%x): %s", round, i, msg, err) } if len(bobsMessage) > 0 && i != len(alicesMessage)-1 { t.Errorf("Bob produced output while processing a fragment, round %d, message %d", round, i) } } alicesMessage = nil for i, msg := range bobsMessage { out, _, aliceChange, alicesMessage, err = alice.Receive(msg) if len(out) > 0 { t.Errorf("Alice generated output during key exchange, round %d, message %d", round, i) } if err != nil { t.Fatalf("Alice returned an error, round %d, message %d (%x): %s", round, i, msg, err) } if len(alicesMessage) > 0 && i != len(bobsMessage)-1 { t.Errorf("Alice produced output while processing a fragment, round %d, message %d", round, i) } } } if aliceChange != NewKeys { t.Errorf("Alice terminated without signaling new keys") } if bobChange != NewKeys { t.Errorf("Bob terminated without signaling new keys") } if !bytes.Equal(alice.SSID[:], bob.SSID[:]) { t.Errorf("Session identifiers don't match. Alice has %x, Bob has %x", alice.SSID[:], bob.SSID[:]) } if !alice.IsEncrypted() { t.Error("Alice doesn't believe that the conversation is secure") } if !bob.IsEncrypted() { t.Error("Bob doesn't believe that the conversation is secure") } } const ( firstRoundTrip = iota subsequentRoundTrip noMACKeyCheck ) func roundTrip(t *testing.T, alice, bob *Conversation, message []byte, macKeyCheck int) { alicesMessage, err := alice.Send(message) if err != nil { t.Errorf("Error from Alice sending message: %s", err) } if len(alice.oldMACs) != 0 { t.Errorf("Alice has not revealed all MAC keys") } for i, msg := range alicesMessage { out, encrypted, _, _, err := bob.Receive(msg) if err != nil { t.Errorf("Error generated while processing test message: %s", err.Error()) } if len(out) > 0 { if i != len(alicesMessage)-1 { t.Fatal("Bob produced a message while processing a fragment of Alice's") } if !encrypted { t.Errorf("Message was not marked as encrypted") } if !bytes.Equal(out, message) { t.Errorf("Message corrupted: got %x, want %x", out, message) } } } switch macKeyCheck { case firstRoundTrip: if len(bob.oldMACs) != 0 { t.Errorf("Bob should not have MAC keys to reveal") } case subsequentRoundTrip: if len(bob.oldMACs) != 40 { t.Errorf("Bob has %d bytes of MAC keys to reveal, but should have 40", len(bob.oldMACs)) } } bobsMessage, err := bob.Send(message) if err != nil { t.Errorf("Error from Bob sending message: %s", err) } if len(bob.oldMACs) != 0 { t.Errorf("Bob has not revealed all MAC keys") } for i, msg := range bobsMessage { out, encrypted, _, _, err := alice.Receive(msg) if err != nil { t.Errorf("Error generated while processing test message: %s", err.Error()) } if len(out) > 0 { if i != len(bobsMessage)-1 { t.Fatal("Alice produced a message while processing a fragment of Bob's") } if !encrypted { t.Errorf("Message was not marked as encrypted") } if !bytes.Equal(out, message) { t.Errorf("Message corrupted: got %x, want %x", out, message) } } } switch macKeyCheck { case firstRoundTrip: if len(alice.oldMACs) != 20 { t.Errorf("Alice has %d bytes of MAC keys to reveal, but should have 20", len(alice.oldMACs)) } case subsequentRoundTrip: if len(alice.oldMACs) != 40 { t.Errorf("Alice has %d bytes of MAC keys to reveal, but should have 40", len(alice.oldMACs)) } } } func TestConversation(t *testing.T) { alice, bob := setupConversation(t) var testMessages = [][]byte{ []byte("hello"), []byte("bye"), } roundTripType := firstRoundTrip for _, testMessage := range testMessages { roundTrip(t, alice, bob, testMessage, roundTripType) roundTripType = subsequentRoundTrip } } func TestGoodSMP(t *testing.T) { var alice, bob Conversation alice.smp.secret = new(big.Int).SetInt64(42) bob.smp.secret = alice.smp.secret var alicesMessages, bobsMessages []tlv var aliceComplete, bobComplete bool var err error var out tlv alicesMessages = alice.startSMP("") for round := 0; len(alicesMessages) > 0 || len(bobsMessages) > 0; round++ { bobsMessages = bobsMessages[:0] for i, msg := range alicesMessages { out, bobComplete, err = bob.processSMP(msg) if err != nil { t.Errorf("Error from Bob in round %d: %s", round, err) } if bobComplete && i != len(alicesMessages)-1 { t.Errorf("Bob returned a completed signal before processing all of Alice's messages in round %d", round) } if out.typ != 0 { bobsMessages = append(bobsMessages, out) } } alicesMessages = alicesMessages[:0] for i, msg := range bobsMessages { out, aliceComplete, err = alice.processSMP(msg) if err != nil { t.Errorf("Error from Alice in round %d: %s", round, err) } if aliceComplete && i != len(bobsMessages)-1 { t.Errorf("Alice returned a completed signal before processing all of Bob's messages in round %d", round) } if out.typ != 0 { alicesMessages = append(alicesMessages, out) } } } if !aliceComplete || !bobComplete { t.Errorf("SMP completed without both sides reporting success: alice: %v, bob: %v\n", aliceComplete, bobComplete) } } func TestBadSMP(t *testing.T) { var alice, bob Conversation alice.smp.secret = new(big.Int).SetInt64(42) bob.smp.secret = new(big.Int).SetInt64(43) var alicesMessages, bobsMessages []tlv alicesMessages = alice.startSMP("") for round := 0; len(alicesMessages) > 0 || len(bobsMessages) > 0; round++ { bobsMessages = bobsMessages[:0] for _, msg := range alicesMessages { out, complete, _ := bob.processSMP(msg) if complete { t.Errorf("Bob signaled completion in round %d", round) } if out.typ != 0 { bobsMessages = append(bobsMessages, out) } } alicesMessages = alicesMessages[:0] for _, msg := range bobsMessages { out, complete, _ := alice.processSMP(msg) if complete { t.Errorf("Alice signaled completion in round %d", round) } if out.typ != 0 { alicesMessages = append(alicesMessages, out) } } } } func TestRehandshaking(t *testing.T) { alice, bob := setupConversation(t) roundTrip(t, alice, bob, []byte("test"), firstRoundTrip) roundTrip(t, alice, bob, []byte("test 2"), subsequentRoundTrip) roundTrip(t, alice, bob, []byte("test 3"), subsequentRoundTrip) roundTrip(t, alice, bob, []byte("test 4"), subsequentRoundTrip) roundTrip(t, alice, bob, []byte("test 5"), subsequentRoundTrip) roundTrip(t, alice, bob, []byte("test 6"), subsequentRoundTrip) roundTrip(t, alice, bob, []byte("test 7"), subsequentRoundTrip) roundTrip(t, alice, bob, []byte("test 8"), subsequentRoundTrip) performHandshake(t, alice, bob) roundTrip(t, alice, bob, []byte("test"), noMACKeyCheck) roundTrip(t, alice, bob, []byte("test 2"), noMACKeyCheck) } func TestAgainstLibOTR(t *testing.T) { // This test requires otr.c.test to be built as /tmp/a.out. // If enabled, this tests runs forever performing OTR handshakes in a // loop. return alicePrivateKey, _ := hex.DecodeString(alicePrivateKeyHex) var alice Conversation alice.PrivateKey = new(PrivateKey) alice.PrivateKey.Parse(alicePrivateKey) cmd := exec.Command("/tmp/a.out") cmd.Stderr = os.Stderr out, err := cmd.StdinPipe() if err != nil { t.Fatal(err) } defer out.Close() stdout, err := cmd.StdoutPipe() if err != nil { t.Fatal(err) } in := bufio.NewReader(stdout) if err := cmd.Start(); err != nil { t.Fatal(err) } out.Write([]byte(QueryMessage)) out.Write([]byte("\n")) var expectedText = []byte("test message") for { line, isPrefix, err := in.ReadLine() if isPrefix { t.Fatal("line from subprocess too long") } if err != nil { t.Fatal(err) } text, encrypted, change, alicesMessage, err := alice.Receive(line) if err != nil { t.Fatal(err) } for _, msg := range alicesMessage { out.Write(msg) out.Write([]byte("\n")) } if change == NewKeys { alicesMessage, err := alice.Send([]byte("Go -> libotr test message")) if err != nil { t.Fatalf("error sending message: %s", err.Error()) } else { for _, msg := range alicesMessage { out.Write(msg) out.Write([]byte("\n")) } } } if len(text) > 0 { if !bytes.Equal(text, expectedText) { t.Fatalf("expected %x, but got %x", expectedText, text) } if !encrypted { t.Fatal("message wasn't encrypted") } } } } lxd-2.0.0/dist/src/golang.org/x/crypto/otr/otr.go0000644061062106075000000010611712702772344024241 0ustar00stgraberdomain admins00000000000000// Copyright 2012 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 otr implements the Off The Record protocol as specified in // http://www.cypherpunks.ca/otr/Protocol-v2-3.1.0.html package otr // import "golang.org/x/crypto/otr" import ( "bytes" "crypto/aes" "crypto/cipher" "crypto/dsa" "crypto/hmac" "crypto/rand" "crypto/sha1" "crypto/sha256" "crypto/subtle" "encoding/base64" "encoding/hex" "errors" "hash" "io" "math/big" "strconv" ) // SecurityChange describes a change in the security state of a Conversation. type SecurityChange int const ( NoChange SecurityChange = iota // NewKeys indicates that a key exchange has completed. This occurs // when a conversation first becomes encrypted, and when the keys are // renegotiated within an encrypted conversation. NewKeys // SMPSecretNeeded indicates that the peer has started an // authentication and that we need to supply a secret. Call SMPQuestion // to get the optional, human readable challenge and then Authenticate // to supply the matching secret. SMPSecretNeeded // SMPComplete indicates that an authentication completed. The identity // of the peer has now been confirmed. SMPComplete // SMPFailed indicates that an authentication failed. SMPFailed // ConversationEnded indicates that the peer ended the secure // conversation. ConversationEnded ) // QueryMessage can be sent to a peer to start an OTR conversation. var QueryMessage = "?OTRv2?" // ErrorPrefix can be used to make an OTR error by appending an error message // to it. var ErrorPrefix = "?OTR Error:" var ( fragmentPartSeparator = []byte(",") fragmentPrefix = []byte("?OTR,") msgPrefix = []byte("?OTR:") queryMarker = []byte("?OTR") ) // isQuery attempts to parse an OTR query from msg and returns the greatest // common version, or 0 if msg is not an OTR query. func isQuery(msg []byte) (greatestCommonVersion int) { pos := bytes.Index(msg, queryMarker) if pos == -1 { return 0 } for i, c := range msg[pos+len(queryMarker):] { if i == 0 { if c == '?' { // Indicates support for version 1, but we don't // implement that. continue } if c != 'v' { // Invalid message return 0 } continue } if c == '?' { // End of message return } if c == ' ' || c == '\t' { // Probably an invalid message return 0 } if c == '2' { greatestCommonVersion = 2 } } return 0 } const ( statePlaintext = iota stateEncrypted stateFinished ) const ( authStateNone = iota authStateAwaitingDHKey authStateAwaitingRevealSig authStateAwaitingSig ) const ( msgTypeDHCommit = 2 msgTypeData = 3 msgTypeDHKey = 10 msgTypeRevealSig = 17 msgTypeSig = 18 ) const ( // If the requested fragment size is less than this, it will be ignored. minFragmentSize = 18 // Messages are padded to a multiple of this number of bytes. paddingGranularity = 256 // The number of bytes in a Diffie-Hellman private value (320-bits). dhPrivateBytes = 40 // The number of bytes needed to represent an element of the DSA // subgroup (160-bits). dsaSubgroupBytes = 20 // The number of bytes of the MAC that are sent on the wire (160-bits). macPrefixBytes = 20 ) // These are the global, common group parameters for OTR. var ( p *big.Int // group prime g *big.Int // group generator q *big.Int // group order pMinus2 *big.Int ) func init() { p, _ = new(big.Int).SetString("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA237327FFFFFFFFFFFFFFFF", 16) q, _ = new(big.Int).SetString("7FFFFFFFFFFFFFFFE487ED5110B4611A62633145C06E0E68948127044533E63A0105DF531D89CD9128A5043CC71A026EF7CA8CD9E69D218D98158536F92F8A1BA7F09AB6B6A8E122F242DABB312F3F637A262174D31BF6B585FFAE5B7A035BF6F71C35FDAD44CFD2D74F9208BE258FF324943328F6722D9EE1003E5C50B1DF82CC6D241B0E2AE9CD348B1FD47E9267AFC1B2AE91EE51D6CB0E3179AB1042A95DCF6A9483B84B4B36B3861AA7255E4C0278BA36046511B993FFFFFFFFFFFFFFFF", 16) g = new(big.Int).SetInt64(2) pMinus2 = new(big.Int).Sub(p, g) } // Conversation represents a relation with a peer. The zero value is a valid // Conversation, although PrivateKey must be set. // // When communicating with a peer, all inbound messages should be passed to // Conversation.Receive and all outbound messages to Conversation.Send. The // Conversation will take care of maintaining the encryption state and // negotiating encryption as needed. type Conversation struct { // PrivateKey contains the private key to use to sign key exchanges. PrivateKey *PrivateKey // Rand can be set to override the entropy source. Otherwise, // crypto/rand will be used. Rand io.Reader // If FragmentSize is set, all messages produced by Receive and Send // will be fragmented into messages of, at most, this number of bytes. FragmentSize int // Once Receive has returned NewKeys once, the following fields are // valid. SSID [8]byte TheirPublicKey PublicKey state, authState int r [16]byte x, y *big.Int gx, gy *big.Int gxBytes []byte digest [sha256.Size]byte revealKeys, sigKeys akeKeys myKeyId uint32 myCurrentDHPub *big.Int myCurrentDHPriv *big.Int myLastDHPub *big.Int myLastDHPriv *big.Int theirKeyId uint32 theirCurrentDHPub *big.Int theirLastDHPub *big.Int keySlots [4]keySlot myCounter [8]byte theirLastCtr [8]byte oldMACs []byte k, n int // fragment state frag []byte smp smpState } // A keySlot contains key material for a specific (their keyid, my keyid) pair. type keySlot struct { // used is true if this slot is valid. If false, it's free for reuse. used bool theirKeyId uint32 myKeyId uint32 sendAESKey, recvAESKey []byte sendMACKey, recvMACKey []byte theirLastCtr [8]byte } // akeKeys are generated during key exchange. There's one set for the reveal // signature message and another for the signature message. In the protocol // spec the latter are indicated with a prime mark. type akeKeys struct { c [16]byte m1, m2 [32]byte } func (c *Conversation) rand() io.Reader { if c.Rand != nil { return c.Rand } return rand.Reader } func (c *Conversation) randMPI(buf []byte) *big.Int { _, err := io.ReadFull(c.rand(), buf) if err != nil { panic("otr: short read from random source") } return new(big.Int).SetBytes(buf) } // tlv represents the type-length value from the protocol. type tlv struct { typ, length uint16 data []byte } const ( tlvTypePadding = 0 tlvTypeDisconnected = 1 tlvTypeSMP1 = 2 tlvTypeSMP2 = 3 tlvTypeSMP3 = 4 tlvTypeSMP4 = 5 tlvTypeSMPAbort = 6 tlvTypeSMP1WithQuestion = 7 ) // Receive handles a message from a peer. It returns a human readable message, // an indicator of whether that message was encrypted, a hint about the // encryption state and zero or more messages to send back to the peer. // These messages do not need to be passed to Send before transmission. func (c *Conversation) Receive(in []byte) (out []byte, encrypted bool, change SecurityChange, toSend [][]byte, err error) { if bytes.HasPrefix(in, fragmentPrefix) { in, err = c.processFragment(in) if in == nil || err != nil { return } } if bytes.HasPrefix(in, msgPrefix) && in[len(in)-1] == '.' { in = in[len(msgPrefix) : len(in)-1] } else if version := isQuery(in); version > 0 { c.authState = authStateAwaitingDHKey c.reset() toSend = c.encode(c.generateDHCommit()) return } else { // plaintext message out = in return } msg := make([]byte, base64.StdEncoding.DecodedLen(len(in))) msgLen, err := base64.StdEncoding.Decode(msg, in) if err != nil { err = errors.New("otr: invalid base64 encoding in message") return } msg = msg[:msgLen] // The first two bytes are the protocol version (2) if len(msg) < 3 || msg[0] != 0 || msg[1] != 2 { err = errors.New("otr: invalid OTR message") return } msgType := int(msg[2]) msg = msg[3:] switch msgType { case msgTypeDHCommit: switch c.authState { case authStateNone: c.authState = authStateAwaitingRevealSig if err = c.processDHCommit(msg); err != nil { return } c.reset() toSend = c.encode(c.generateDHKey()) return case authStateAwaitingDHKey: // This is a 'SYN-crossing'. The greater digest wins. var cmp int if cmp, err = c.compareToDHCommit(msg); err != nil { return } if cmp > 0 { // We win. Retransmit DH commit. toSend = c.encode(c.serializeDHCommit()) return } else { // They win. We forget about our DH commit. c.authState = authStateAwaitingRevealSig if err = c.processDHCommit(msg); err != nil { return } c.reset() toSend = c.encode(c.generateDHKey()) return } case authStateAwaitingRevealSig: if err = c.processDHCommit(msg); err != nil { return } toSend = c.encode(c.serializeDHKey()) case authStateAwaitingSig: if err = c.processDHCommit(msg); err != nil { return } c.reset() toSend = c.encode(c.generateDHKey()) c.authState = authStateAwaitingRevealSig default: panic("bad state") } case msgTypeDHKey: switch c.authState { case authStateAwaitingDHKey: var isSame bool if isSame, err = c.processDHKey(msg); err != nil { return } if isSame { err = errors.New("otr: unexpected duplicate DH key") return } toSend = c.encode(c.generateRevealSig()) c.authState = authStateAwaitingSig case authStateAwaitingSig: var isSame bool if isSame, err = c.processDHKey(msg); err != nil { return } if isSame { toSend = c.encode(c.serializeDHKey()) } } case msgTypeRevealSig: if c.authState != authStateAwaitingRevealSig { return } if err = c.processRevealSig(msg); err != nil { return } toSend = c.encode(c.generateSig()) c.authState = authStateNone c.state = stateEncrypted change = NewKeys case msgTypeSig: if c.authState != authStateAwaitingSig { return } if err = c.processSig(msg); err != nil { return } c.authState = authStateNone c.state = stateEncrypted change = NewKeys case msgTypeData: if c.state != stateEncrypted { err = errors.New("otr: encrypted message received without encrypted session established") return } var tlvs []tlv out, tlvs, err = c.processData(msg) encrypted = true EachTLV: for _, inTLV := range tlvs { switch inTLV.typ { case tlvTypeDisconnected: change = ConversationEnded c.state = stateFinished break EachTLV case tlvTypeSMP1, tlvTypeSMP2, tlvTypeSMP3, tlvTypeSMP4, tlvTypeSMPAbort, tlvTypeSMP1WithQuestion: var reply tlv var complete bool reply, complete, err = c.processSMP(inTLV) if err == smpSecretMissingError { err = nil change = SMPSecretNeeded c.smp.saved = &inTLV return } if err == smpFailureError { err = nil change = SMPFailed } else if complete { change = SMPComplete } if reply.typ != 0 { toSend = c.encode(c.generateData(nil, &reply)) } break EachTLV default: // skip unknown TLVs } } default: err = errors.New("otr: unknown message type " + strconv.Itoa(msgType)) } return } // Send takes a human readable message from the local user, possibly encrypts // it and returns zero one or more messages to send to the peer. func (c *Conversation) Send(msg []byte) ([][]byte, error) { switch c.state { case statePlaintext: return [][]byte{msg}, nil case stateEncrypted: return c.encode(c.generateData(msg, nil)), nil case stateFinished: return nil, errors.New("otr: cannot send message because secure conversation has finished") } return nil, errors.New("otr: cannot send message in current state") } // SMPQuestion returns the human readable challenge question from the peer. // It's only valid after Receive has returned SMPSecretNeeded. func (c *Conversation) SMPQuestion() string { return c.smp.question } // Authenticate begins an authentication with the peer. Authentication involves // an optional challenge message and a shared secret. The authentication // proceeds until either Receive returns SMPComplete, SMPSecretNeeded (which // indicates that a new authentication is happening and thus this one was // aborted) or SMPFailed. func (c *Conversation) Authenticate(question string, mutualSecret []byte) (toSend [][]byte, err error) { if c.state != stateEncrypted { err = errors.New("otr: can't authenticate a peer without a secure conversation established") return } if c.smp.saved != nil { c.calcSMPSecret(mutualSecret, false /* they started it */) var out tlv var complete bool out, complete, err = c.processSMP(*c.smp.saved) if complete { panic("SMP completed on the first message") } c.smp.saved = nil if out.typ != 0 { toSend = c.encode(c.generateData(nil, &out)) } return } c.calcSMPSecret(mutualSecret, true /* we started it */) outs := c.startSMP(question) for _, out := range outs { toSend = append(toSend, c.encode(c.generateData(nil, &out))...) } return } // End ends a secure conversation by generating a termination message for // the peer and switches to unencrypted communication. func (c *Conversation) End() (toSend [][]byte) { switch c.state { case statePlaintext: return nil case stateEncrypted: c.state = statePlaintext return c.encode(c.generateData(nil, &tlv{typ: tlvTypeDisconnected})) case stateFinished: c.state = statePlaintext return nil } panic("unreachable") } // IsEncrypted returns true if a message passed to Send would be encrypted // before transmission. This result remains valid until the next call to // Receive or End, which may change the state of the Conversation. func (c *Conversation) IsEncrypted() bool { return c.state == stateEncrypted } var fragmentError = errors.New("otr: invalid OTR fragment") // processFragment processes a fragmented OTR message and possibly returns a // complete message. Fragmented messages look like "?OTR,k,n,msg," where k is // the fragment number (starting from 1), n is the number of fragments in this // message and msg is a substring of the base64 encoded message. func (c *Conversation) processFragment(in []byte) (out []byte, err error) { in = in[len(fragmentPrefix):] // remove "?OTR," parts := bytes.Split(in, fragmentPartSeparator) if len(parts) != 4 || len(parts[3]) != 0 { return nil, fragmentError } k, err := strconv.Atoi(string(parts[0])) if err != nil { return nil, fragmentError } n, err := strconv.Atoi(string(parts[1])) if err != nil { return nil, fragmentError } if k < 1 || n < 1 || k > n { return nil, fragmentError } if k == 1 { c.frag = append(c.frag[:0], parts[2]...) c.k, c.n = k, n } else if n == c.n && k == c.k+1 { c.frag = append(c.frag, parts[2]...) c.k++ } else { c.frag = c.frag[:0] c.n, c.k = 0, 0 } if c.n > 0 && c.k == c.n { c.n, c.k = 0, 0 return c.frag, nil } return nil, nil } func (c *Conversation) generateDHCommit() []byte { _, err := io.ReadFull(c.rand(), c.r[:]) if err != nil { panic("otr: short read from random source") } var xBytes [dhPrivateBytes]byte c.x = c.randMPI(xBytes[:]) c.gx = new(big.Int).Exp(g, c.x, p) c.gy = nil c.gxBytes = appendMPI(nil, c.gx) h := sha256.New() h.Write(c.gxBytes) h.Sum(c.digest[:0]) aesCipher, err := aes.NewCipher(c.r[:]) if err != nil { panic(err.Error()) } var iv [aes.BlockSize]byte ctr := cipher.NewCTR(aesCipher, iv[:]) ctr.XORKeyStream(c.gxBytes, c.gxBytes) return c.serializeDHCommit() } func (c *Conversation) serializeDHCommit() []byte { var ret []byte ret = appendU16(ret, 2) // protocol version ret = append(ret, msgTypeDHCommit) ret = appendData(ret, c.gxBytes) ret = appendData(ret, c.digest[:]) return ret } func (c *Conversation) processDHCommit(in []byte) error { var ok1, ok2 bool c.gxBytes, in, ok1 = getData(in) digest, in, ok2 := getData(in) if !ok1 || !ok2 || len(in) > 0 { return errors.New("otr: corrupt DH commit message") } copy(c.digest[:], digest) return nil } func (c *Conversation) compareToDHCommit(in []byte) (int, error) { _, in, ok1 := getData(in) digest, in, ok2 := getData(in) if !ok1 || !ok2 || len(in) > 0 { return 0, errors.New("otr: corrupt DH commit message") } return bytes.Compare(c.digest[:], digest), nil } func (c *Conversation) generateDHKey() []byte { var yBytes [dhPrivateBytes]byte c.y = c.randMPI(yBytes[:]) c.gy = new(big.Int).Exp(g, c.y, p) return c.serializeDHKey() } func (c *Conversation) serializeDHKey() []byte { var ret []byte ret = appendU16(ret, 2) // protocol version ret = append(ret, msgTypeDHKey) ret = appendMPI(ret, c.gy) return ret } func (c *Conversation) processDHKey(in []byte) (isSame bool, err error) { gy, in, ok := getMPI(in) if !ok { err = errors.New("otr: corrupt DH key message") return } if gy.Cmp(g) < 0 || gy.Cmp(pMinus2) > 0 { err = errors.New("otr: DH value out of range") return } if c.gy != nil { isSame = c.gy.Cmp(gy) == 0 return } c.gy = gy return } func (c *Conversation) generateEncryptedSignature(keys *akeKeys, xFirst bool) ([]byte, []byte) { var xb []byte xb = c.PrivateKey.PublicKey.Serialize(xb) var verifyData []byte if xFirst { verifyData = appendMPI(verifyData, c.gx) verifyData = appendMPI(verifyData, c.gy) } else { verifyData = appendMPI(verifyData, c.gy) verifyData = appendMPI(verifyData, c.gx) } verifyData = append(verifyData, xb...) verifyData = appendU32(verifyData, c.myKeyId) mac := hmac.New(sha256.New, keys.m1[:]) mac.Write(verifyData) mb := mac.Sum(nil) xb = appendU32(xb, c.myKeyId) xb = append(xb, c.PrivateKey.Sign(c.rand(), mb)...) aesCipher, err := aes.NewCipher(keys.c[:]) if err != nil { panic(err.Error()) } var iv [aes.BlockSize]byte ctr := cipher.NewCTR(aesCipher, iv[:]) ctr.XORKeyStream(xb, xb) mac = hmac.New(sha256.New, keys.m2[:]) encryptedSig := appendData(nil, xb) mac.Write(encryptedSig) return encryptedSig, mac.Sum(nil) } func (c *Conversation) generateRevealSig() []byte { s := new(big.Int).Exp(c.gy, c.x, p) c.calcAKEKeys(s) c.myKeyId++ encryptedSig, mac := c.generateEncryptedSignature(&c.revealKeys, true /* gx comes first */) c.myCurrentDHPub = c.gx c.myCurrentDHPriv = c.x c.rotateDHKeys() incCounter(&c.myCounter) var ret []byte ret = appendU16(ret, 2) ret = append(ret, msgTypeRevealSig) ret = appendData(ret, c.r[:]) ret = append(ret, encryptedSig...) ret = append(ret, mac[:20]...) return ret } func (c *Conversation) processEncryptedSig(encryptedSig, theirMAC []byte, keys *akeKeys, xFirst bool) error { mac := hmac.New(sha256.New, keys.m2[:]) mac.Write(appendData(nil, encryptedSig)) myMAC := mac.Sum(nil)[:20] if len(myMAC) != len(theirMAC) || subtle.ConstantTimeCompare(myMAC, theirMAC) == 0 { return errors.New("bad signature MAC in encrypted signature") } aesCipher, err := aes.NewCipher(keys.c[:]) if err != nil { panic(err.Error()) } var iv [aes.BlockSize]byte ctr := cipher.NewCTR(aesCipher, iv[:]) ctr.XORKeyStream(encryptedSig, encryptedSig) sig := encryptedSig sig, ok1 := c.TheirPublicKey.Parse(sig) keyId, sig, ok2 := getU32(sig) if !ok1 || !ok2 { return errors.New("otr: corrupt encrypted signature") } var verifyData []byte if xFirst { verifyData = appendMPI(verifyData, c.gx) verifyData = appendMPI(verifyData, c.gy) } else { verifyData = appendMPI(verifyData, c.gy) verifyData = appendMPI(verifyData, c.gx) } verifyData = c.TheirPublicKey.Serialize(verifyData) verifyData = appendU32(verifyData, keyId) mac = hmac.New(sha256.New, keys.m1[:]) mac.Write(verifyData) mb := mac.Sum(nil) sig, ok1 = c.TheirPublicKey.Verify(mb, sig) if !ok1 { return errors.New("bad signature in encrypted signature") } if len(sig) > 0 { return errors.New("corrupt encrypted signature") } c.theirKeyId = keyId zero(c.theirLastCtr[:]) return nil } func (c *Conversation) processRevealSig(in []byte) error { r, in, ok1 := getData(in) encryptedSig, in, ok2 := getData(in) theirMAC := in if !ok1 || !ok2 || len(theirMAC) != 20 { return errors.New("otr: corrupt reveal signature message") } aesCipher, err := aes.NewCipher(r) if err != nil { return errors.New("otr: cannot create AES cipher from reveal signature message: " + err.Error()) } var iv [aes.BlockSize]byte ctr := cipher.NewCTR(aesCipher, iv[:]) ctr.XORKeyStream(c.gxBytes, c.gxBytes) h := sha256.New() h.Write(c.gxBytes) digest := h.Sum(nil) if len(digest) != len(c.digest) || subtle.ConstantTimeCompare(digest, c.digest[:]) == 0 { return errors.New("otr: bad commit MAC in reveal signature message") } var rest []byte c.gx, rest, ok1 = getMPI(c.gxBytes) if !ok1 || len(rest) > 0 { return errors.New("otr: gx corrupt after decryption") } if c.gx.Cmp(g) < 0 || c.gx.Cmp(pMinus2) > 0 { return errors.New("otr: DH value out of range") } s := new(big.Int).Exp(c.gx, c.y, p) c.calcAKEKeys(s) if err := c.processEncryptedSig(encryptedSig, theirMAC, &c.revealKeys, true /* gx comes first */); err != nil { return errors.New("otr: in reveal signature message: " + err.Error()) } c.theirCurrentDHPub = c.gx c.theirLastDHPub = nil return nil } func (c *Conversation) generateSig() []byte { c.myKeyId++ encryptedSig, mac := c.generateEncryptedSignature(&c.sigKeys, false /* gy comes first */) c.myCurrentDHPub = c.gy c.myCurrentDHPriv = c.y c.rotateDHKeys() incCounter(&c.myCounter) var ret []byte ret = appendU16(ret, 2) ret = append(ret, msgTypeSig) ret = append(ret, encryptedSig...) ret = append(ret, mac[:macPrefixBytes]...) return ret } func (c *Conversation) processSig(in []byte) error { encryptedSig, in, ok1 := getData(in) theirMAC := in if !ok1 || len(theirMAC) != macPrefixBytes { return errors.New("otr: corrupt signature message") } if err := c.processEncryptedSig(encryptedSig, theirMAC, &c.sigKeys, false /* gy comes first */); err != nil { return errors.New("otr: in signature message: " + err.Error()) } c.theirCurrentDHPub = c.gy c.theirLastDHPub = nil return nil } func (c *Conversation) rotateDHKeys() { // evict slots using our retired key id for i := range c.keySlots { slot := &c.keySlots[i] if slot.used && slot.myKeyId == c.myKeyId-1 { slot.used = false c.oldMACs = append(c.oldMACs, slot.recvMACKey...) } } c.myLastDHPriv = c.myCurrentDHPriv c.myLastDHPub = c.myCurrentDHPub var xBytes [dhPrivateBytes]byte c.myCurrentDHPriv = c.randMPI(xBytes[:]) c.myCurrentDHPub = new(big.Int).Exp(g, c.myCurrentDHPriv, p) c.myKeyId++ } func (c *Conversation) processData(in []byte) (out []byte, tlvs []tlv, err error) { origIn := in flags, in, ok1 := getU8(in) theirKeyId, in, ok2 := getU32(in) myKeyId, in, ok3 := getU32(in) y, in, ok4 := getMPI(in) counter, in, ok5 := getNBytes(in, 8) encrypted, in, ok6 := getData(in) macedData := origIn[:len(origIn)-len(in)] theirMAC, in, ok7 := getNBytes(in, macPrefixBytes) _, in, ok8 := getData(in) if !ok1 || !ok2 || !ok3 || !ok4 || !ok5 || !ok6 || !ok7 || !ok8 || len(in) > 0 { err = errors.New("otr: corrupt data message") return } ignoreErrors := flags&1 != 0 slot, err := c.calcDataKeys(myKeyId, theirKeyId) if err != nil { if ignoreErrors { err = nil } return } mac := hmac.New(sha1.New, slot.recvMACKey) mac.Write([]byte{0, 2, 3}) mac.Write(macedData) myMAC := mac.Sum(nil) if len(myMAC) != len(theirMAC) || subtle.ConstantTimeCompare(myMAC, theirMAC) == 0 { if !ignoreErrors { err = errors.New("otr: bad MAC on data message") } return } if bytes.Compare(counter, slot.theirLastCtr[:]) <= 0 { err = errors.New("otr: counter regressed") return } copy(slot.theirLastCtr[:], counter) var iv [aes.BlockSize]byte copy(iv[:], counter) aesCipher, err := aes.NewCipher(slot.recvAESKey) if err != nil { panic(err.Error()) } ctr := cipher.NewCTR(aesCipher, iv[:]) ctr.XORKeyStream(encrypted, encrypted) decrypted := encrypted if myKeyId == c.myKeyId { c.rotateDHKeys() } if theirKeyId == c.theirKeyId { // evict slots using their retired key id for i := range c.keySlots { slot := &c.keySlots[i] if slot.used && slot.theirKeyId == theirKeyId-1 { slot.used = false c.oldMACs = append(c.oldMACs, slot.recvMACKey...) } } c.theirLastDHPub = c.theirCurrentDHPub c.theirKeyId++ c.theirCurrentDHPub = y } if nulPos := bytes.IndexByte(decrypted, 0); nulPos >= 0 { out = decrypted[:nulPos] tlvData := decrypted[nulPos+1:] for len(tlvData) > 0 { var t tlv var ok1, ok2, ok3 bool t.typ, tlvData, ok1 = getU16(tlvData) t.length, tlvData, ok2 = getU16(tlvData) t.data, tlvData, ok3 = getNBytes(tlvData, int(t.length)) if !ok1 || !ok2 || !ok3 { err = errors.New("otr: corrupt tlv data") } tlvs = append(tlvs, t) } } else { out = decrypted } return } func (c *Conversation) generateData(msg []byte, extra *tlv) []byte { slot, err := c.calcDataKeys(c.myKeyId-1, c.theirKeyId) if err != nil { panic("otr: failed to generate sending keys: " + err.Error()) } var plaintext []byte plaintext = append(plaintext, msg...) plaintext = append(plaintext, 0) padding := paddingGranularity - ((len(plaintext) + 4) % paddingGranularity) plaintext = appendU16(plaintext, tlvTypePadding) plaintext = appendU16(plaintext, uint16(padding)) for i := 0; i < padding; i++ { plaintext = append(plaintext, 0) } if extra != nil { plaintext = appendU16(plaintext, extra.typ) plaintext = appendU16(plaintext, uint16(len(extra.data))) plaintext = append(plaintext, extra.data...) } encrypted := make([]byte, len(plaintext)) var iv [aes.BlockSize]byte copy(iv[:], c.myCounter[:]) aesCipher, err := aes.NewCipher(slot.sendAESKey) if err != nil { panic(err.Error()) } ctr := cipher.NewCTR(aesCipher, iv[:]) ctr.XORKeyStream(encrypted, plaintext) var ret []byte ret = appendU16(ret, 2) ret = append(ret, msgTypeData) ret = append(ret, 0 /* flags */) ret = appendU32(ret, c.myKeyId-1) ret = appendU32(ret, c.theirKeyId) ret = appendMPI(ret, c.myCurrentDHPub) ret = append(ret, c.myCounter[:]...) ret = appendData(ret, encrypted) mac := hmac.New(sha1.New, slot.sendMACKey) mac.Write(ret) ret = append(ret, mac.Sum(nil)[:macPrefixBytes]...) ret = appendData(ret, c.oldMACs) c.oldMACs = nil incCounter(&c.myCounter) return ret } func incCounter(counter *[8]byte) { for i := 7; i >= 0; i-- { counter[i]++ if counter[i] > 0 { break } } } // calcDataKeys computes the keys used to encrypt a data message given the key // IDs. func (c *Conversation) calcDataKeys(myKeyId, theirKeyId uint32) (slot *keySlot, err error) { // Check for a cache hit. for i := range c.keySlots { slot = &c.keySlots[i] if slot.used && slot.theirKeyId == theirKeyId && slot.myKeyId == myKeyId { return } } // Find an empty slot to write into. slot = nil for i := range c.keySlots { if !c.keySlots[i].used { slot = &c.keySlots[i] break } } if slot == nil { return nil, errors.New("otr: internal error: no more key slots") } var myPriv, myPub, theirPub *big.Int if myKeyId == c.myKeyId { myPriv = c.myCurrentDHPriv myPub = c.myCurrentDHPub } else if myKeyId == c.myKeyId-1 { myPriv = c.myLastDHPriv myPub = c.myLastDHPub } else { err = errors.New("otr: peer requested keyid " + strconv.FormatUint(uint64(myKeyId), 10) + " when I'm on " + strconv.FormatUint(uint64(c.myKeyId), 10)) return } if theirKeyId == c.theirKeyId { theirPub = c.theirCurrentDHPub } else if theirKeyId == c.theirKeyId-1 && c.theirLastDHPub != nil { theirPub = c.theirLastDHPub } else { err = errors.New("otr: peer requested keyid " + strconv.FormatUint(uint64(myKeyId), 10) + " when they're on " + strconv.FormatUint(uint64(c.myKeyId), 10)) return } var sendPrefixByte, recvPrefixByte [1]byte if myPub.Cmp(theirPub) > 0 { // we're the high end sendPrefixByte[0], recvPrefixByte[0] = 1, 2 } else { // we're the low end sendPrefixByte[0], recvPrefixByte[0] = 2, 1 } s := new(big.Int).Exp(theirPub, myPriv, p) sBytes := appendMPI(nil, s) h := sha1.New() h.Write(sendPrefixByte[:]) h.Write(sBytes) slot.sendAESKey = h.Sum(slot.sendAESKey[:0])[:16] h.Reset() h.Write(slot.sendAESKey) slot.sendMACKey = h.Sum(slot.sendMACKey[:0]) h.Reset() h.Write(recvPrefixByte[:]) h.Write(sBytes) slot.recvAESKey = h.Sum(slot.recvAESKey[:0])[:16] h.Reset() h.Write(slot.recvAESKey) slot.recvMACKey = h.Sum(slot.recvMACKey[:0]) slot.theirKeyId = theirKeyId slot.myKeyId = myKeyId slot.used = true zero(slot.theirLastCtr[:]) return } func (c *Conversation) calcAKEKeys(s *big.Int) { mpi := appendMPI(nil, s) h := sha256.New() var cBytes [32]byte hashWithPrefix(c.SSID[:], 0, mpi, h) hashWithPrefix(cBytes[:], 1, mpi, h) copy(c.revealKeys.c[:], cBytes[:16]) copy(c.sigKeys.c[:], cBytes[16:]) hashWithPrefix(c.revealKeys.m1[:], 2, mpi, h) hashWithPrefix(c.revealKeys.m2[:], 3, mpi, h) hashWithPrefix(c.sigKeys.m1[:], 4, mpi, h) hashWithPrefix(c.sigKeys.m2[:], 5, mpi, h) } func hashWithPrefix(out []byte, prefix byte, in []byte, h hash.Hash) { h.Reset() var p [1]byte p[0] = prefix h.Write(p[:]) h.Write(in) if len(out) == h.Size() { h.Sum(out[:0]) } else { digest := h.Sum(nil) copy(out, digest) } } func (c *Conversation) encode(msg []byte) [][]byte { b64 := make([]byte, base64.StdEncoding.EncodedLen(len(msg))+len(msgPrefix)+1) base64.StdEncoding.Encode(b64[len(msgPrefix):], msg) copy(b64, msgPrefix) b64[len(b64)-1] = '.' if c.FragmentSize < minFragmentSize || len(b64) <= c.FragmentSize { // We can encode this in a single fragment. return [][]byte{b64} } // We have to fragment this message. var ret [][]byte bytesPerFragment := c.FragmentSize - minFragmentSize numFragments := (len(b64) + bytesPerFragment) / bytesPerFragment for i := 0; i < numFragments; i++ { frag := []byte("?OTR," + strconv.Itoa(i+1) + "," + strconv.Itoa(numFragments) + ",") todo := bytesPerFragment if todo > len(b64) { todo = len(b64) } frag = append(frag, b64[:todo]...) b64 = b64[todo:] frag = append(frag, ',') ret = append(ret, frag) } return ret } func (c *Conversation) reset() { c.myKeyId = 0 for i := range c.keySlots { c.keySlots[i].used = false } } type PublicKey struct { dsa.PublicKey } func (pk *PublicKey) Parse(in []byte) ([]byte, bool) { var ok bool var pubKeyType uint16 if pubKeyType, in, ok = getU16(in); !ok || pubKeyType != 0 { return nil, false } if pk.P, in, ok = getMPI(in); !ok { return nil, false } if pk.Q, in, ok = getMPI(in); !ok { return nil, false } if pk.G, in, ok = getMPI(in); !ok { return nil, false } if pk.Y, in, ok = getMPI(in); !ok { return nil, false } return in, true } func (pk *PublicKey) Serialize(in []byte) []byte { in = appendU16(in, 0) in = appendMPI(in, pk.P) in = appendMPI(in, pk.Q) in = appendMPI(in, pk.G) in = appendMPI(in, pk.Y) return in } // Fingerprint returns the 20-byte, binary fingerprint of the PublicKey. func (pk *PublicKey) Fingerprint() []byte { b := pk.Serialize(nil) h := sha1.New() h.Write(b[2:]) return h.Sum(nil) } func (pk *PublicKey) Verify(hashed, sig []byte) ([]byte, bool) { if len(sig) != 2*dsaSubgroupBytes { return nil, false } r := new(big.Int).SetBytes(sig[:dsaSubgroupBytes]) s := new(big.Int).SetBytes(sig[dsaSubgroupBytes:]) ok := dsa.Verify(&pk.PublicKey, hashed, r, s) return sig[dsaSubgroupBytes*2:], ok } type PrivateKey struct { PublicKey dsa.PrivateKey } func (priv *PrivateKey) Sign(rand io.Reader, hashed []byte) []byte { r, s, err := dsa.Sign(rand, &priv.PrivateKey, hashed) if err != nil { panic(err.Error()) } rBytes := r.Bytes() sBytes := s.Bytes() if len(rBytes) > dsaSubgroupBytes || len(sBytes) > dsaSubgroupBytes { panic("DSA signature too large") } out := make([]byte, 2*dsaSubgroupBytes) copy(out[dsaSubgroupBytes-len(rBytes):], rBytes) copy(out[len(out)-len(sBytes):], sBytes) return out } func (priv *PrivateKey) Serialize(in []byte) []byte { in = priv.PublicKey.Serialize(in) in = appendMPI(in, priv.PrivateKey.X) return in } func (priv *PrivateKey) Parse(in []byte) ([]byte, bool) { in, ok := priv.PublicKey.Parse(in) if !ok { return in, ok } priv.PrivateKey.PublicKey = priv.PublicKey.PublicKey priv.PrivateKey.X, in, ok = getMPI(in) return in, ok } func (priv *PrivateKey) Generate(rand io.Reader) { if err := dsa.GenerateParameters(&priv.PrivateKey.PublicKey.Parameters, rand, dsa.L1024N160); err != nil { panic(err.Error()) } if err := dsa.GenerateKey(&priv.PrivateKey, rand); err != nil { panic(err.Error()) } priv.PublicKey.PublicKey = priv.PrivateKey.PublicKey } func notHex(r rune) bool { if r >= '0' && r <= '9' || r >= 'a' && r <= 'f' || r >= 'A' && r <= 'F' { return false } return true } // Import parses the contents of a libotr private key file. func (priv *PrivateKey) Import(in []byte) bool { mpiStart := []byte(" #") mpis := make([]*big.Int, 5) for i := 0; i < len(mpis); i++ { start := bytes.Index(in, mpiStart) if start == -1 { return false } in = in[start+len(mpiStart):] end := bytes.IndexFunc(in, notHex) if end == -1 { return false } hexBytes := in[:end] in = in[end:] if len(hexBytes)&1 != 0 { return false } mpiBytes := make([]byte, len(hexBytes)/2) if _, err := hex.Decode(mpiBytes, hexBytes); err != nil { return false } mpis[i] = new(big.Int).SetBytes(mpiBytes) } priv.PrivateKey.P = mpis[0] priv.PrivateKey.Q = mpis[1] priv.PrivateKey.G = mpis[2] priv.PrivateKey.Y = mpis[3] priv.PrivateKey.X = mpis[4] priv.PublicKey.PublicKey = priv.PrivateKey.PublicKey a := new(big.Int).Exp(priv.PrivateKey.G, priv.PrivateKey.X, priv.PrivateKey.P) return a.Cmp(priv.PrivateKey.Y) == 0 } func getU8(in []byte) (uint8, []byte, bool) { if len(in) < 1 { return 0, in, false } return in[0], in[1:], true } func getU16(in []byte) (uint16, []byte, bool) { if len(in) < 2 { return 0, in, false } r := uint16(in[0])<<8 | uint16(in[1]) return r, in[2:], true } func getU32(in []byte) (uint32, []byte, bool) { if len(in) < 4 { return 0, in, false } r := uint32(in[0])<<24 | uint32(in[1])<<16 | uint32(in[2])<<8 | uint32(in[3]) return r, in[4:], true } func getMPI(in []byte) (*big.Int, []byte, bool) { l, in, ok := getU32(in) if !ok || uint32(len(in)) < l { return nil, in, false } r := new(big.Int).SetBytes(in[:l]) return r, in[l:], true } func getData(in []byte) ([]byte, []byte, bool) { l, in, ok := getU32(in) if !ok || uint32(len(in)) < l { return nil, in, false } return in[:l], in[l:], true } func getNBytes(in []byte, n int) ([]byte, []byte, bool) { if len(in) < n { return nil, in, false } return in[:n], in[n:], true } func appendU16(out []byte, v uint16) []byte { out = append(out, byte(v>>8), byte(v)) return out } func appendU32(out []byte, v uint32) []byte { out = append(out, byte(v>>24), byte(v>>16), byte(v>>8), byte(v)) return out } func appendData(out, v []byte) []byte { out = appendU32(out, uint32(len(v))) out = append(out, v...) return out } func appendMPI(out []byte, v *big.Int) []byte { vBytes := v.Bytes() out = appendU32(out, uint32(len(vBytes))) out = append(out, vBytes...) return out } func appendMPIs(out []byte, mpis ...*big.Int) []byte { for _, mpi := range mpis { out = appendMPI(out, mpi) } return out } func zero(b []byte) { for i := range b { b[i] = 0 } } lxd-2.0.0/dist/src/golang.org/x/crypto/otr/libotr_test_helper.c0000644061062106075000000001401212702772344027133 0ustar00stgraberdomain admins00000000000000// Copyright 2012 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 code can be compiled and used to test the otr package against libotr. // See otr_test.go. // +build ignore #include #include #include #include #include #include static int g_session_established = 0; OtrlPolicy policy(void *opdata, ConnContext *context) { return OTRL_POLICY_ALWAYS; } int is_logged_in(void *opdata, const char *accountname, const char *protocol, const char *recipient) { return 1; } void inject_message(void *opdata, const char *accountname, const char *protocol, const char *recipient, const char *message) { printf("%s\n", message); fflush(stdout); fprintf(stderr, "libotr helper sent: %s\n", message); } void update_context_list(void *opdata) {} void new_fingerprint(void *opdata, OtrlUserState us, const char *accountname, const char *protocol, const char *username, unsigned char fingerprint[20]) { fprintf(stderr, "NEW FINGERPRINT\n"); g_session_established = 1; } void write_fingerprints(void *opdata) {} void gone_secure(void *opdata, ConnContext *context) {} void gone_insecure(void *opdata, ConnContext *context) {} void still_secure(void *opdata, ConnContext *context, int is_reply) {} int max_message_size(void *opdata, ConnContext *context) { return 99999; } const char *account_name(void *opdata, const char *account, const char *protocol) { return "ACCOUNT"; } void account_name_free(void *opdata, const char *account_name) {} const char *error_message(void *opdata, ConnContext *context, OtrlErrorCode err_code) { return "ERR"; } void error_message_free(void *opdata, const char *msg) {} void resent_msg_prefix_free(void *opdata, const char *prefix) {} void handle_smp_event(void *opdata, OtrlSMPEvent smp_event, ConnContext *context, unsigned short progress_event, char *question) {} void handle_msg_event(void *opdata, OtrlMessageEvent msg_event, ConnContext *context, const char *message, gcry_error_t err) { fprintf(stderr, "msg event: %d %s\n", msg_event, message); } OtrlMessageAppOps uiops = { policy, NULL, is_logged_in, inject_message, update_context_list, new_fingerprint, write_fingerprints, gone_secure, gone_insecure, still_secure, max_message_size, account_name, account_name_free, NULL, /* received_symkey */ error_message, error_message_free, NULL, /* resent_msg_prefix */ resent_msg_prefix_free, handle_smp_event, handle_msg_event, NULL /* create_instag */, NULL /* convert_msg */, NULL /* convert_free */, NULL /* timer_control */, }; static const char kPrivateKeyData[] = "(privkeys (account (name \"account\") (protocol proto) (private-key (dsa " "(p " "#00FC07ABCF0DC916AFF6E9AE47BEF60C7AB9B4D6B2469E436630E36F8A489BE812486A09F" "30B71224508654940A835301ACC525A4FF133FC152CC53DCC59D65C30A54F1993FE13FE63E" "5823D4C746DB21B90F9B9C00B49EC7404AB1D929BA7FBA12F2E45C6E0A651689750E8528AB" "8C031D3561FECEE72EBB4A090D450A9B7A857#) (q " "#00997BD266EF7B1F60A5C23F3A741F2AEFD07A2081#) (g " "#535E360E8A95EBA46A4F7DE50AD6E9B2A6DB785A66B64EB9F20338D2A3E8FB0E94725848F" "1AA6CC567CB83A1CC517EC806F2E92EAE71457E80B2210A189B91250779434B41FC8A8873F" "6DB94BEA7D177F5D59E7E114EE10A49CFD9CEF88AE43387023B672927BA74B04EB6BBB5E57" "597766A2F9CE3857D7ACE3E1E3BC1FC6F26#) (y " "#0AC8670AD767D7A8D9D14CC1AC6744CD7D76F993B77FFD9E39DF01E5A6536EF65E775FCEF" "2A983E2A19BD6415500F6979715D9FD1257E1FE2B6F5E1E74B333079E7C880D39868462A93" "454B41877BE62E5EF0A041C2EE9C9E76BD1E12AE25D9628DECB097025DD625EF49C3258A1A" "3C0FF501E3DC673B76D7BABF349009B6ECF#) (x " "#14D0345A3562C480A039E3C72764F72D79043216#)))))\n"; int main() { OTRL_INIT; // We have to write the private key information to a file because the libotr // API demands a filename to read from. const char *tmpdir = "/tmp"; if (getenv("TMP")) { tmpdir = getenv("TMP"); } char private_key_file[256]; snprintf(private_key_file, sizeof(private_key_file), "%s/libotr_test_helper_privatekeys-XXXXXX", tmpdir); int fd = mkstemp(private_key_file); if (fd == -1) { perror("creating temp file"); } write(fd, kPrivateKeyData, sizeof(kPrivateKeyData) - 1); close(fd); OtrlUserState userstate = otrl_userstate_create(); otrl_privkey_read(userstate, private_key_file); unlink(private_key_file); fprintf(stderr, "libotr helper started\n"); char buf[4096]; for (;;) { char *message = fgets(buf, sizeof(buf), stdin); if (strlen(message) == 0) { break; } message[strlen(message) - 1] = 0; fprintf(stderr, "libotr helper got: %s\n", message); char *newmessage = NULL; OtrlTLV *tlvs; int ignore_message = otrl_message_receiving( userstate, &uiops, NULL, "account", "proto", "peer", message, &newmessage, &tlvs, NULL, NULL, NULL); if (tlvs) { otrl_tlv_free(tlvs); } if (newmessage != NULL) { fprintf(stderr, "libotr got: %s\n", newmessage); otrl_message_free(newmessage); gcry_error_t err; char *newmessage = NULL; err = otrl_message_sending(userstate, &uiops, NULL, "account", "proto", "peer", 0, "test message", NULL, &newmessage, OTRL_FRAGMENT_SEND_SKIP, NULL, NULL, NULL); if (newmessage == NULL) { fprintf(stderr, "libotr didn't encrypt message\n"); return 1; } write(1, newmessage, strlen(newmessage)); write(1, "\n", 1); fprintf(stderr, "libotr sent: %s\n", newmessage); otrl_message_free(newmessage); g_session_established = 0; write(1, "?OTRv2?\n", 8); fprintf(stderr, "libotr sent: ?OTRv2\n"); } } return 0; } lxd-2.0.0/dist/src/golang.org/x/crypto/otr/smp.go0000644061062106075000000002731612702772344024237 0ustar00stgraberdomain admins00000000000000// Copyright 2012 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 file implements the Socialist Millionaires Protocol as described in // http://www.cypherpunks.ca/otr/Protocol-v2-3.1.0.html. The protocol // specification is required in order to understand this code and, where // possible, the variable names in the code match up with the spec. package otr import ( "bytes" "crypto/sha256" "errors" "hash" "math/big" ) type smpFailure string func (s smpFailure) Error() string { return string(s) } var smpFailureError = smpFailure("otr: SMP protocol failed") var smpSecretMissingError = smpFailure("otr: mutual secret needed") const smpVersion = 1 const ( smpState1 = iota smpState2 smpState3 smpState4 ) type smpState struct { state int a2, a3, b2, b3, pb, qb *big.Int g2a, g3a *big.Int g2, g3 *big.Int g3b, papb, qaqb, ra *big.Int saved *tlv secret *big.Int question string } func (c *Conversation) startSMP(question string) (tlvs []tlv) { if c.smp.state != smpState1 { tlvs = append(tlvs, c.generateSMPAbort()) } tlvs = append(tlvs, c.generateSMP1(question)) c.smp.question = "" c.smp.state = smpState2 return } func (c *Conversation) resetSMP() { c.smp.state = smpState1 c.smp.secret = nil c.smp.question = "" } func (c *Conversation) processSMP(in tlv) (out tlv, complete bool, err error) { data := in.data switch in.typ { case tlvTypeSMPAbort: if c.smp.state != smpState1 { err = smpFailureError } c.resetSMP() return case tlvTypeSMP1WithQuestion: // We preprocess this into a SMP1 message. nulPos := bytes.IndexByte(data, 0) if nulPos == -1 { err = errors.New("otr: SMP message with question didn't contain a NUL byte") return } c.smp.question = string(data[:nulPos]) data = data[nulPos+1:] } numMPIs, data, ok := getU32(data) if !ok || numMPIs > 20 { err = errors.New("otr: corrupt SMP message") return } mpis := make([]*big.Int, numMPIs) for i := range mpis { var ok bool mpis[i], data, ok = getMPI(data) if !ok { err = errors.New("otr: corrupt SMP message") return } } switch in.typ { case tlvTypeSMP1, tlvTypeSMP1WithQuestion: if c.smp.state != smpState1 { c.resetSMP() out = c.generateSMPAbort() return } if c.smp.secret == nil { err = smpSecretMissingError return } if err = c.processSMP1(mpis); err != nil { return } c.smp.state = smpState3 out = c.generateSMP2() case tlvTypeSMP2: if c.smp.state != smpState2 { c.resetSMP() out = c.generateSMPAbort() return } if out, err = c.processSMP2(mpis); err != nil { out = c.generateSMPAbort() return } c.smp.state = smpState4 case tlvTypeSMP3: if c.smp.state != smpState3 { c.resetSMP() out = c.generateSMPAbort() return } if out, err = c.processSMP3(mpis); err != nil { return } c.smp.state = smpState1 c.smp.secret = nil complete = true case tlvTypeSMP4: if c.smp.state != smpState4 { c.resetSMP() out = c.generateSMPAbort() return } if err = c.processSMP4(mpis); err != nil { out = c.generateSMPAbort() return } c.smp.state = smpState1 c.smp.secret = nil complete = true default: panic("unknown SMP message") } return } func (c *Conversation) calcSMPSecret(mutualSecret []byte, weStarted bool) { h := sha256.New() h.Write([]byte{smpVersion}) if weStarted { h.Write(c.PrivateKey.PublicKey.Fingerprint()) h.Write(c.TheirPublicKey.Fingerprint()) } else { h.Write(c.TheirPublicKey.Fingerprint()) h.Write(c.PrivateKey.PublicKey.Fingerprint()) } h.Write(c.SSID[:]) h.Write(mutualSecret) c.smp.secret = new(big.Int).SetBytes(h.Sum(nil)) } func (c *Conversation) generateSMP1(question string) tlv { var randBuf [16]byte c.smp.a2 = c.randMPI(randBuf[:]) c.smp.a3 = c.randMPI(randBuf[:]) g2a := new(big.Int).Exp(g, c.smp.a2, p) g3a := new(big.Int).Exp(g, c.smp.a3, p) h := sha256.New() r2 := c.randMPI(randBuf[:]) r := new(big.Int).Exp(g, r2, p) c2 := new(big.Int).SetBytes(hashMPIs(h, 1, r)) d2 := new(big.Int).Mul(c.smp.a2, c2) d2.Sub(r2, d2) d2.Mod(d2, q) if d2.Sign() < 0 { d2.Add(d2, q) } r3 := c.randMPI(randBuf[:]) r.Exp(g, r3, p) c3 := new(big.Int).SetBytes(hashMPIs(h, 2, r)) d3 := new(big.Int).Mul(c.smp.a3, c3) d3.Sub(r3, d3) d3.Mod(d3, q) if d3.Sign() < 0 { d3.Add(d3, q) } var ret tlv if len(question) > 0 { ret.typ = tlvTypeSMP1WithQuestion ret.data = append(ret.data, question...) ret.data = append(ret.data, 0) } else { ret.typ = tlvTypeSMP1 } ret.data = appendU32(ret.data, 6) ret.data = appendMPIs(ret.data, g2a, c2, d2, g3a, c3, d3) return ret } func (c *Conversation) processSMP1(mpis []*big.Int) error { if len(mpis) != 6 { return errors.New("otr: incorrect number of arguments in SMP1 message") } g2a := mpis[0] c2 := mpis[1] d2 := mpis[2] g3a := mpis[3] c3 := mpis[4] d3 := mpis[5] h := sha256.New() r := new(big.Int).Exp(g, d2, p) s := new(big.Int).Exp(g2a, c2, p) r.Mul(r, s) r.Mod(r, p) t := new(big.Int).SetBytes(hashMPIs(h, 1, r)) if c2.Cmp(t) != 0 { return errors.New("otr: ZKP c2 incorrect in SMP1 message") } r.Exp(g, d3, p) s.Exp(g3a, c3, p) r.Mul(r, s) r.Mod(r, p) t.SetBytes(hashMPIs(h, 2, r)) if c3.Cmp(t) != 0 { return errors.New("otr: ZKP c3 incorrect in SMP1 message") } c.smp.g2a = g2a c.smp.g3a = g3a return nil } func (c *Conversation) generateSMP2() tlv { var randBuf [16]byte b2 := c.randMPI(randBuf[:]) c.smp.b3 = c.randMPI(randBuf[:]) r2 := c.randMPI(randBuf[:]) r3 := c.randMPI(randBuf[:]) r4 := c.randMPI(randBuf[:]) r5 := c.randMPI(randBuf[:]) r6 := c.randMPI(randBuf[:]) g2b := new(big.Int).Exp(g, b2, p) g3b := new(big.Int).Exp(g, c.smp.b3, p) r := new(big.Int).Exp(g, r2, p) h := sha256.New() c2 := new(big.Int).SetBytes(hashMPIs(h, 3, r)) d2 := new(big.Int).Mul(b2, c2) d2.Sub(r2, d2) d2.Mod(d2, q) if d2.Sign() < 0 { d2.Add(d2, q) } r.Exp(g, r3, p) c3 := new(big.Int).SetBytes(hashMPIs(h, 4, r)) d3 := new(big.Int).Mul(c.smp.b3, c3) d3.Sub(r3, d3) d3.Mod(d3, q) if d3.Sign() < 0 { d3.Add(d3, q) } c.smp.g2 = new(big.Int).Exp(c.smp.g2a, b2, p) c.smp.g3 = new(big.Int).Exp(c.smp.g3a, c.smp.b3, p) c.smp.pb = new(big.Int).Exp(c.smp.g3, r4, p) c.smp.qb = new(big.Int).Exp(g, r4, p) r.Exp(c.smp.g2, c.smp.secret, p) c.smp.qb.Mul(c.smp.qb, r) c.smp.qb.Mod(c.smp.qb, p) s := new(big.Int) s.Exp(c.smp.g2, r6, p) r.Exp(g, r5, p) s.Mul(r, s) s.Mod(s, p) r.Exp(c.smp.g3, r5, p) cp := new(big.Int).SetBytes(hashMPIs(h, 5, r, s)) // D5 = r5 - r4 cP mod q and D6 = r6 - y cP mod q s.Mul(r4, cp) r.Sub(r5, s) d5 := new(big.Int).Mod(r, q) if d5.Sign() < 0 { d5.Add(d5, q) } s.Mul(c.smp.secret, cp) r.Sub(r6, s) d6 := new(big.Int).Mod(r, q) if d6.Sign() < 0 { d6.Add(d6, q) } var ret tlv ret.typ = tlvTypeSMP2 ret.data = appendU32(ret.data, 11) ret.data = appendMPIs(ret.data, g2b, c2, d2, g3b, c3, d3, c.smp.pb, c.smp.qb, cp, d5, d6) return ret } func (c *Conversation) processSMP2(mpis []*big.Int) (out tlv, err error) { if len(mpis) != 11 { err = errors.New("otr: incorrect number of arguments in SMP2 message") return } g2b := mpis[0] c2 := mpis[1] d2 := mpis[2] g3b := mpis[3] c3 := mpis[4] d3 := mpis[5] pb := mpis[6] qb := mpis[7] cp := mpis[8] d5 := mpis[9] d6 := mpis[10] h := sha256.New() r := new(big.Int).Exp(g, d2, p) s := new(big.Int).Exp(g2b, c2, p) r.Mul(r, s) r.Mod(r, p) s.SetBytes(hashMPIs(h, 3, r)) if c2.Cmp(s) != 0 { err = errors.New("otr: ZKP c2 failed in SMP2 message") return } r.Exp(g, d3, p) s.Exp(g3b, c3, p) r.Mul(r, s) r.Mod(r, p) s.SetBytes(hashMPIs(h, 4, r)) if c3.Cmp(s) != 0 { err = errors.New("otr: ZKP c3 failed in SMP2 message") return } c.smp.g2 = new(big.Int).Exp(g2b, c.smp.a2, p) c.smp.g3 = new(big.Int).Exp(g3b, c.smp.a3, p) r.Exp(g, d5, p) s.Exp(c.smp.g2, d6, p) r.Mul(r, s) s.Exp(qb, cp, p) r.Mul(r, s) r.Mod(r, p) s.Exp(c.smp.g3, d5, p) t := new(big.Int).Exp(pb, cp, p) s.Mul(s, t) s.Mod(s, p) t.SetBytes(hashMPIs(h, 5, s, r)) if cp.Cmp(t) != 0 { err = errors.New("otr: ZKP cP failed in SMP2 message") return } var randBuf [16]byte r4 := c.randMPI(randBuf[:]) r5 := c.randMPI(randBuf[:]) r6 := c.randMPI(randBuf[:]) r7 := c.randMPI(randBuf[:]) pa := new(big.Int).Exp(c.smp.g3, r4, p) r.Exp(c.smp.g2, c.smp.secret, p) qa := new(big.Int).Exp(g, r4, p) qa.Mul(qa, r) qa.Mod(qa, p) r.Exp(g, r5, p) s.Exp(c.smp.g2, r6, p) r.Mul(r, s) r.Mod(r, p) s.Exp(c.smp.g3, r5, p) cp.SetBytes(hashMPIs(h, 6, s, r)) r.Mul(r4, cp) d5 = new(big.Int).Sub(r5, r) d5.Mod(d5, q) if d5.Sign() < 0 { d5.Add(d5, q) } r.Mul(c.smp.secret, cp) d6 = new(big.Int).Sub(r6, r) d6.Mod(d6, q) if d6.Sign() < 0 { d6.Add(d6, q) } r.ModInverse(qb, p) qaqb := new(big.Int).Mul(qa, r) qaqb.Mod(qaqb, p) ra := new(big.Int).Exp(qaqb, c.smp.a3, p) r.Exp(qaqb, r7, p) s.Exp(g, r7, p) cr := new(big.Int).SetBytes(hashMPIs(h, 7, s, r)) r.Mul(c.smp.a3, cr) d7 := new(big.Int).Sub(r7, r) d7.Mod(d7, q) if d7.Sign() < 0 { d7.Add(d7, q) } c.smp.g3b = g3b c.smp.qaqb = qaqb r.ModInverse(pb, p) c.smp.papb = new(big.Int).Mul(pa, r) c.smp.papb.Mod(c.smp.papb, p) c.smp.ra = ra out.typ = tlvTypeSMP3 out.data = appendU32(out.data, 8) out.data = appendMPIs(out.data, pa, qa, cp, d5, d6, ra, cr, d7) return } func (c *Conversation) processSMP3(mpis []*big.Int) (out tlv, err error) { if len(mpis) != 8 { err = errors.New("otr: incorrect number of arguments in SMP3 message") return } pa := mpis[0] qa := mpis[1] cp := mpis[2] d5 := mpis[3] d6 := mpis[4] ra := mpis[5] cr := mpis[6] d7 := mpis[7] h := sha256.New() r := new(big.Int).Exp(g, d5, p) s := new(big.Int).Exp(c.smp.g2, d6, p) r.Mul(r, s) s.Exp(qa, cp, p) r.Mul(r, s) r.Mod(r, p) s.Exp(c.smp.g3, d5, p) t := new(big.Int).Exp(pa, cp, p) s.Mul(s, t) s.Mod(s, p) t.SetBytes(hashMPIs(h, 6, s, r)) if t.Cmp(cp) != 0 { err = errors.New("otr: ZKP cP failed in SMP3 message") return } r.ModInverse(c.smp.qb, p) qaqb := new(big.Int).Mul(qa, r) qaqb.Mod(qaqb, p) r.Exp(qaqb, d7, p) s.Exp(ra, cr, p) r.Mul(r, s) r.Mod(r, p) s.Exp(g, d7, p) t.Exp(c.smp.g3a, cr, p) s.Mul(s, t) s.Mod(s, p) t.SetBytes(hashMPIs(h, 7, s, r)) if t.Cmp(cr) != 0 { err = errors.New("otr: ZKP cR failed in SMP3 message") return } var randBuf [16]byte r7 := c.randMPI(randBuf[:]) rb := new(big.Int).Exp(qaqb, c.smp.b3, p) r.Exp(qaqb, r7, p) s.Exp(g, r7, p) cr = new(big.Int).SetBytes(hashMPIs(h, 8, s, r)) r.Mul(c.smp.b3, cr) d7 = new(big.Int).Sub(r7, r) d7.Mod(d7, q) if d7.Sign() < 0 { d7.Add(d7, q) } out.typ = tlvTypeSMP4 out.data = appendU32(out.data, 3) out.data = appendMPIs(out.data, rb, cr, d7) r.ModInverse(c.smp.pb, p) r.Mul(pa, r) r.Mod(r, p) s.Exp(ra, c.smp.b3, p) if r.Cmp(s) != 0 { err = smpFailureError } return } func (c *Conversation) processSMP4(mpis []*big.Int) error { if len(mpis) != 3 { return errors.New("otr: incorrect number of arguments in SMP4 message") } rb := mpis[0] cr := mpis[1] d7 := mpis[2] h := sha256.New() r := new(big.Int).Exp(c.smp.qaqb, d7, p) s := new(big.Int).Exp(rb, cr, p) r.Mul(r, s) r.Mod(r, p) s.Exp(g, d7, p) t := new(big.Int).Exp(c.smp.g3b, cr, p) s.Mul(s, t) s.Mod(s, p) t.SetBytes(hashMPIs(h, 8, s, r)) if t.Cmp(cr) != 0 { return errors.New("otr: ZKP cR failed in SMP4 message") } r.Exp(rb, c.smp.a3, p) if r.Cmp(c.smp.papb) != 0 { return smpFailureError } return nil } func (c *Conversation) generateSMPAbort() tlv { return tlv{typ: tlvTypeSMPAbort} } func hashMPIs(h hash.Hash, magic byte, mpis ...*big.Int) []byte { if h != nil { h.Reset() } else { h = sha256.New() } h.Write([]byte{magic}) for _, mpi := range mpis { h.Write(appendMPI(nil, mpi)) } return h.Sum(nil) } lxd-2.0.0/dist/src/golang.org/x/crypto/salsa20/0000755061062106075000000000000012702772344023541 5ustar00stgraberdomain admins00000000000000lxd-2.0.0/dist/src/golang.org/x/crypto/salsa20/salsa/0000755061062106075000000000000012702772344024644 5ustar00stgraberdomain admins00000000000000lxd-2.0.0/dist/src/golang.org/x/crypto/salsa20/salsa/salsa20_ref.go0000644061062106075000000001317012702772344027276 0ustar00stgraberdomain admins00000000000000// Copyright 2012 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. // +build !amd64 appengine gccgo package salsa const rounds = 20 // core applies the Salsa20 core function to 16-byte input in, 32-byte key k, // and 16-byte constant c, and puts the result into 64-byte array out. func core(out *[64]byte, in *[16]byte, k *[32]byte, c *[16]byte) { j0 := uint32(c[0]) | uint32(c[1])<<8 | uint32(c[2])<<16 | uint32(c[3])<<24 j1 := uint32(k[0]) | uint32(k[1])<<8 | uint32(k[2])<<16 | uint32(k[3])<<24 j2 := uint32(k[4]) | uint32(k[5])<<8 | uint32(k[6])<<16 | uint32(k[7])<<24 j3 := uint32(k[8]) | uint32(k[9])<<8 | uint32(k[10])<<16 | uint32(k[11])<<24 j4 := uint32(k[12]) | uint32(k[13])<<8 | uint32(k[14])<<16 | uint32(k[15])<<24 j5 := uint32(c[4]) | uint32(c[5])<<8 | uint32(c[6])<<16 | uint32(c[7])<<24 j6 := uint32(in[0]) | uint32(in[1])<<8 | uint32(in[2])<<16 | uint32(in[3])<<24 j7 := uint32(in[4]) | uint32(in[5])<<8 | uint32(in[6])<<16 | uint32(in[7])<<24 j8 := uint32(in[8]) | uint32(in[9])<<8 | uint32(in[10])<<16 | uint32(in[11])<<24 j9 := uint32(in[12]) | uint32(in[13])<<8 | uint32(in[14])<<16 | uint32(in[15])<<24 j10 := uint32(c[8]) | uint32(c[9])<<8 | uint32(c[10])<<16 | uint32(c[11])<<24 j11 := uint32(k[16]) | uint32(k[17])<<8 | uint32(k[18])<<16 | uint32(k[19])<<24 j12 := uint32(k[20]) | uint32(k[21])<<8 | uint32(k[22])<<16 | uint32(k[23])<<24 j13 := uint32(k[24]) | uint32(k[25])<<8 | uint32(k[26])<<16 | uint32(k[27])<<24 j14 := uint32(k[28]) | uint32(k[29])<<8 | uint32(k[30])<<16 | uint32(k[31])<<24 j15 := uint32(c[12]) | uint32(c[13])<<8 | uint32(c[14])<<16 | uint32(c[15])<<24 x0, x1, x2, x3, x4, x5, x6, x7, x8 := j0, j1, j2, j3, j4, j5, j6, j7, j8 x9, x10, x11, x12, x13, x14, x15 := j9, j10, j11, j12, j13, j14, j15 for i := 0; i < rounds; i += 2 { u := x0 + x12 x4 ^= u<<7 | u>>(32-7) u = x4 + x0 x8 ^= u<<9 | u>>(32-9) u = x8 + x4 x12 ^= u<<13 | u>>(32-13) u = x12 + x8 x0 ^= u<<18 | u>>(32-18) u = x5 + x1 x9 ^= u<<7 | u>>(32-7) u = x9 + x5 x13 ^= u<<9 | u>>(32-9) u = x13 + x9 x1 ^= u<<13 | u>>(32-13) u = x1 + x13 x5 ^= u<<18 | u>>(32-18) u = x10 + x6 x14 ^= u<<7 | u>>(32-7) u = x14 + x10 x2 ^= u<<9 | u>>(32-9) u = x2 + x14 x6 ^= u<<13 | u>>(32-13) u = x6 + x2 x10 ^= u<<18 | u>>(32-18) u = x15 + x11 x3 ^= u<<7 | u>>(32-7) u = x3 + x15 x7 ^= u<<9 | u>>(32-9) u = x7 + x3 x11 ^= u<<13 | u>>(32-13) u = x11 + x7 x15 ^= u<<18 | u>>(32-18) u = x0 + x3 x1 ^= u<<7 | u>>(32-7) u = x1 + x0 x2 ^= u<<9 | u>>(32-9) u = x2 + x1 x3 ^= u<<13 | u>>(32-13) u = x3 + x2 x0 ^= u<<18 | u>>(32-18) u = x5 + x4 x6 ^= u<<7 | u>>(32-7) u = x6 + x5 x7 ^= u<<9 | u>>(32-9) u = x7 + x6 x4 ^= u<<13 | u>>(32-13) u = x4 + x7 x5 ^= u<<18 | u>>(32-18) u = x10 + x9 x11 ^= u<<7 | u>>(32-7) u = x11 + x10 x8 ^= u<<9 | u>>(32-9) u = x8 + x11 x9 ^= u<<13 | u>>(32-13) u = x9 + x8 x10 ^= u<<18 | u>>(32-18) u = x15 + x14 x12 ^= u<<7 | u>>(32-7) u = x12 + x15 x13 ^= u<<9 | u>>(32-9) u = x13 + x12 x14 ^= u<<13 | u>>(32-13) u = x14 + x13 x15 ^= u<<18 | u>>(32-18) } x0 += j0 x1 += j1 x2 += j2 x3 += j3 x4 += j4 x5 += j5 x6 += j6 x7 += j7 x8 += j8 x9 += j9 x10 += j10 x11 += j11 x12 += j12 x13 += j13 x14 += j14 x15 += j15 out[0] = byte(x0) out[1] = byte(x0 >> 8) out[2] = byte(x0 >> 16) out[3] = byte(x0 >> 24) out[4] = byte(x1) out[5] = byte(x1 >> 8) out[6] = byte(x1 >> 16) out[7] = byte(x1 >> 24) out[8] = byte(x2) out[9] = byte(x2 >> 8) out[10] = byte(x2 >> 16) out[11] = byte(x2 >> 24) out[12] = byte(x3) out[13] = byte(x3 >> 8) out[14] = byte(x3 >> 16) out[15] = byte(x3 >> 24) out[16] = byte(x4) out[17] = byte(x4 >> 8) out[18] = byte(x4 >> 16) out[19] = byte(x4 >> 24) out[20] = byte(x5) out[21] = byte(x5 >> 8) out[22] = byte(x5 >> 16) out[23] = byte(x5 >> 24) out[24] = byte(x6) out[25] = byte(x6 >> 8) out[26] = byte(x6 >> 16) out[27] = byte(x6 >> 24) out[28] = byte(x7) out[29] = byte(x7 >> 8) out[30] = byte(x7 >> 16) out[31] = byte(x7 >> 24) out[32] = byte(x8) out[33] = byte(x8 >> 8) out[34] = byte(x8 >> 16) out[35] = byte(x8 >> 24) out[36] = byte(x9) out[37] = byte(x9 >> 8) out[38] = byte(x9 >> 16) out[39] = byte(x9 >> 24) out[40] = byte(x10) out[41] = byte(x10 >> 8) out[42] = byte(x10 >> 16) out[43] = byte(x10 >> 24) out[44] = byte(x11) out[45] = byte(x11 >> 8) out[46] = byte(x11 >> 16) out[47] = byte(x11 >> 24) out[48] = byte(x12) out[49] = byte(x12 >> 8) out[50] = byte(x12 >> 16) out[51] = byte(x12 >> 24) out[52] = byte(x13) out[53] = byte(x13 >> 8) out[54] = byte(x13 >> 16) out[55] = byte(x13 >> 24) out[56] = byte(x14) out[57] = byte(x14 >> 8) out[58] = byte(x14 >> 16) out[59] = byte(x14 >> 24) out[60] = byte(x15) out[61] = byte(x15 >> 8) out[62] = byte(x15 >> 16) out[63] = byte(x15 >> 24) } // XORKeyStream crypts bytes from in to out using the given key and counters. // In and out may be the same slice but otherwise should not overlap. Counter // contains the raw salsa20 counter bytes (both nonce and block counter). func XORKeyStream(out, in []byte, counter *[16]byte, key *[32]byte) { var block [64]byte var counterCopy [16]byte copy(counterCopy[:], counter[:]) for len(in) >= 64 { core(&block, &counterCopy, key, &Sigma) for i, x := range block { out[i] = in[i] ^ x } u := uint32(1) for i := 8; i < 16; i++ { u += uint32(counterCopy[i]) counterCopy[i] = byte(u) u >>= 8 } in = in[64:] out = out[64:] } if len(in) > 0 { core(&block, &counterCopy, key, &Sigma) for i, v := range in { out[i] = v ^ block[i] } } } lxd-2.0.0/dist/src/golang.org/x/crypto/salsa20/salsa/salsa_test.go0000644061062106075000000000217512702772344027342 0ustar00stgraberdomain admins00000000000000// Copyright 2012 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 salsa import "testing" func TestCore208(t *testing.T) { in := [64]byte{ 0x7e, 0x87, 0x9a, 0x21, 0x4f, 0x3e, 0xc9, 0x86, 0x7c, 0xa9, 0x40, 0xe6, 0x41, 0x71, 0x8f, 0x26, 0xba, 0xee, 0x55, 0x5b, 0x8c, 0x61, 0xc1, 0xb5, 0x0d, 0xf8, 0x46, 0x11, 0x6d, 0xcd, 0x3b, 0x1d, 0xee, 0x24, 0xf3, 0x19, 0xdf, 0x9b, 0x3d, 0x85, 0x14, 0x12, 0x1e, 0x4b, 0x5a, 0xc5, 0xaa, 0x32, 0x76, 0x02, 0x1d, 0x29, 0x09, 0xc7, 0x48, 0x29, 0xed, 0xeb, 0xc6, 0x8d, 0xb8, 0xb8, 0xc2, 0x5e} out := [64]byte{ 0xa4, 0x1f, 0x85, 0x9c, 0x66, 0x08, 0xcc, 0x99, 0x3b, 0x81, 0xca, 0xcb, 0x02, 0x0c, 0xef, 0x05, 0x04, 0x4b, 0x21, 0x81, 0xa2, 0xfd, 0x33, 0x7d, 0xfd, 0x7b, 0x1c, 0x63, 0x96, 0x68, 0x2f, 0x29, 0xb4, 0x39, 0x31, 0x68, 0xe3, 0xc9, 0xe6, 0xbc, 0xfe, 0x6b, 0xc5, 0xb7, 0xa0, 0x6d, 0x96, 0xba, 0xe4, 0x24, 0xcc, 0x10, 0x2c, 0x91, 0x74, 0x5c, 0x24, 0xad, 0x67, 0x3d, 0xc7, 0x61, 0x8f, 0x81, } Core208(&in, &in) if in != out { t.Errorf("expected %x, got %x", out, in) } } lxd-2.0.0/dist/src/golang.org/x/crypto/salsa20/salsa/salsa20_amd64.go0000644061062106075000000000137312702772344027437 0ustar00stgraberdomain admins00000000000000// Copyright 2012 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. // +build amd64,!appengine,!gccgo package salsa // This function is implemented in salsa2020_amd64.s. //go:noescape func salsa2020XORKeyStream(out, in *byte, n uint64, nonce, key *byte) // XORKeyStream crypts bytes from in to out using the given key and counters. // In and out may be the same slice but otherwise should not overlap. Counter // contains the raw salsa20 counter bytes (both nonce and block counter). func XORKeyStream(out, in []byte, counter *[16]byte, key *[32]byte) { if len(in) == 0 { return } salsa2020XORKeyStream(&out[0], &in[0], uint64(len(in)), &counter[0], &key[0]) } lxd-2.0.0/dist/src/golang.org/x/crypto/salsa20/salsa/salsa2020_amd64.s0000644061062106075000000003315112702772344027435 0ustar00stgraberdomain admins00000000000000// Copyright 2012 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. // +build amd64,!appengine,!gccgo // This code was translated into a form compatible with 6a from the public // domain sources in SUPERCOP: http://bench.cr.yp.to/supercop.html // func salsa2020XORKeyStream(out, in *byte, n uint64, nonce, key *byte) TEXT ·salsa2020XORKeyStream(SB),0,$512-40 MOVQ out+0(FP),DI MOVQ in+8(FP),SI MOVQ n+16(FP),DX MOVQ nonce+24(FP),CX MOVQ key+32(FP),R8 MOVQ SP,R11 MOVQ $31,R9 NOTQ R9 ANDQ R9,SP ADDQ $32,SP MOVQ R11,352(SP) MOVQ R12,360(SP) MOVQ R13,368(SP) MOVQ R14,376(SP) MOVQ R15,384(SP) MOVQ BX,392(SP) MOVQ BP,400(SP) MOVQ DX,R9 MOVQ CX,DX MOVQ R8,R10 CMPQ R9,$0 JBE DONE START: MOVL 20(R10),CX MOVL 0(R10),R8 MOVL 0(DX),AX MOVL 16(R10),R11 MOVL CX,0(SP) MOVL R8, 4 (SP) MOVL AX, 8 (SP) MOVL R11, 12 (SP) MOVL 8(DX),CX MOVL 24(R10),R8 MOVL 4(R10),AX MOVL 4(DX),R11 MOVL CX,16(SP) MOVL R8, 20 (SP) MOVL AX, 24 (SP) MOVL R11, 28 (SP) MOVL 12(DX),CX MOVL 12(R10),DX MOVL 28(R10),R8 MOVL 8(R10),AX MOVL DX,32(SP) MOVL CX, 36 (SP) MOVL R8, 40 (SP) MOVL AX, 44 (SP) MOVQ $1634760805,DX MOVQ $857760878,CX MOVQ $2036477234,R8 MOVQ $1797285236,AX MOVL DX,48(SP) MOVL CX, 52 (SP) MOVL R8, 56 (SP) MOVL AX, 60 (SP) CMPQ R9,$256 JB BYTESBETWEEN1AND255 MOVOA 48(SP),X0 PSHUFL $0X55,X0,X1 PSHUFL $0XAA,X0,X2 PSHUFL $0XFF,X0,X3 PSHUFL $0X00,X0,X0 MOVOA X1,64(SP) MOVOA X2,80(SP) MOVOA X3,96(SP) MOVOA X0,112(SP) MOVOA 0(SP),X0 PSHUFL $0XAA,X0,X1 PSHUFL $0XFF,X0,X2 PSHUFL $0X00,X0,X3 PSHUFL $0X55,X0,X0 MOVOA X1,128(SP) MOVOA X2,144(SP) MOVOA X3,160(SP) MOVOA X0,176(SP) MOVOA 16(SP),X0 PSHUFL $0XFF,X0,X1 PSHUFL $0X55,X0,X2 PSHUFL $0XAA,X0,X0 MOVOA X1,192(SP) MOVOA X2,208(SP) MOVOA X0,224(SP) MOVOA 32(SP),X0 PSHUFL $0X00,X0,X1 PSHUFL $0XAA,X0,X2 PSHUFL $0XFF,X0,X0 MOVOA X1,240(SP) MOVOA X2,256(SP) MOVOA X0,272(SP) BYTESATLEAST256: MOVL 16(SP),DX MOVL 36 (SP),CX MOVL DX,288(SP) MOVL CX,304(SP) ADDQ $1,DX SHLQ $32,CX ADDQ CX,DX MOVQ DX,CX SHRQ $32,CX MOVL DX, 292 (SP) MOVL CX, 308 (SP) ADDQ $1,DX SHLQ $32,CX ADDQ CX,DX MOVQ DX,CX SHRQ $32,CX MOVL DX, 296 (SP) MOVL CX, 312 (SP) ADDQ $1,DX SHLQ $32,CX ADDQ CX,DX MOVQ DX,CX SHRQ $32,CX MOVL DX, 300 (SP) MOVL CX, 316 (SP) ADDQ $1,DX SHLQ $32,CX ADDQ CX,DX MOVQ DX,CX SHRQ $32,CX MOVL DX,16(SP) MOVL CX, 36 (SP) MOVQ R9,408(SP) MOVQ $20,DX MOVOA 64(SP),X0 MOVOA 80(SP),X1 MOVOA 96(SP),X2 MOVOA 256(SP),X3 MOVOA 272(SP),X4 MOVOA 128(SP),X5 MOVOA 144(SP),X6 MOVOA 176(SP),X7 MOVOA 192(SP),X8 MOVOA 208(SP),X9 MOVOA 224(SP),X10 MOVOA 304(SP),X11 MOVOA 112(SP),X12 MOVOA 160(SP),X13 MOVOA 240(SP),X14 MOVOA 288(SP),X15 MAINLOOP1: MOVOA X1,320(SP) MOVOA X2,336(SP) MOVOA X13,X1 PADDL X12,X1 MOVOA X1,X2 PSLLL $7,X1 PXOR X1,X14 PSRLL $25,X2 PXOR X2,X14 MOVOA X7,X1 PADDL X0,X1 MOVOA X1,X2 PSLLL $7,X1 PXOR X1,X11 PSRLL $25,X2 PXOR X2,X11 MOVOA X12,X1 PADDL X14,X1 MOVOA X1,X2 PSLLL $9,X1 PXOR X1,X15 PSRLL $23,X2 PXOR X2,X15 MOVOA X0,X1 PADDL X11,X1 MOVOA X1,X2 PSLLL $9,X1 PXOR X1,X9 PSRLL $23,X2 PXOR X2,X9 MOVOA X14,X1 PADDL X15,X1 MOVOA X1,X2 PSLLL $13,X1 PXOR X1,X13 PSRLL $19,X2 PXOR X2,X13 MOVOA X11,X1 PADDL X9,X1 MOVOA X1,X2 PSLLL $13,X1 PXOR X1,X7 PSRLL $19,X2 PXOR X2,X7 MOVOA X15,X1 PADDL X13,X1 MOVOA X1,X2 PSLLL $18,X1 PXOR X1,X12 PSRLL $14,X2 PXOR X2,X12 MOVOA 320(SP),X1 MOVOA X12,320(SP) MOVOA X9,X2 PADDL X7,X2 MOVOA X2,X12 PSLLL $18,X2 PXOR X2,X0 PSRLL $14,X12 PXOR X12,X0 MOVOA X5,X2 PADDL X1,X2 MOVOA X2,X12 PSLLL $7,X2 PXOR X2,X3 PSRLL $25,X12 PXOR X12,X3 MOVOA 336(SP),X2 MOVOA X0,336(SP) MOVOA X6,X0 PADDL X2,X0 MOVOA X0,X12 PSLLL $7,X0 PXOR X0,X4 PSRLL $25,X12 PXOR X12,X4 MOVOA X1,X0 PADDL X3,X0 MOVOA X0,X12 PSLLL $9,X0 PXOR X0,X10 PSRLL $23,X12 PXOR X12,X10 MOVOA X2,X0 PADDL X4,X0 MOVOA X0,X12 PSLLL $9,X0 PXOR X0,X8 PSRLL $23,X12 PXOR X12,X8 MOVOA X3,X0 PADDL X10,X0 MOVOA X0,X12 PSLLL $13,X0 PXOR X0,X5 PSRLL $19,X12 PXOR X12,X5 MOVOA X4,X0 PADDL X8,X0 MOVOA X0,X12 PSLLL $13,X0 PXOR X0,X6 PSRLL $19,X12 PXOR X12,X6 MOVOA X10,X0 PADDL X5,X0 MOVOA X0,X12 PSLLL $18,X0 PXOR X0,X1 PSRLL $14,X12 PXOR X12,X1 MOVOA 320(SP),X0 MOVOA X1,320(SP) MOVOA X4,X1 PADDL X0,X1 MOVOA X1,X12 PSLLL $7,X1 PXOR X1,X7 PSRLL $25,X12 PXOR X12,X7 MOVOA X8,X1 PADDL X6,X1 MOVOA X1,X12 PSLLL $18,X1 PXOR X1,X2 PSRLL $14,X12 PXOR X12,X2 MOVOA 336(SP),X12 MOVOA X2,336(SP) MOVOA X14,X1 PADDL X12,X1 MOVOA X1,X2 PSLLL $7,X1 PXOR X1,X5 PSRLL $25,X2 PXOR X2,X5 MOVOA X0,X1 PADDL X7,X1 MOVOA X1,X2 PSLLL $9,X1 PXOR X1,X10 PSRLL $23,X2 PXOR X2,X10 MOVOA X12,X1 PADDL X5,X1 MOVOA X1,X2 PSLLL $9,X1 PXOR X1,X8 PSRLL $23,X2 PXOR X2,X8 MOVOA X7,X1 PADDL X10,X1 MOVOA X1,X2 PSLLL $13,X1 PXOR X1,X4 PSRLL $19,X2 PXOR X2,X4 MOVOA X5,X1 PADDL X8,X1 MOVOA X1,X2 PSLLL $13,X1 PXOR X1,X14 PSRLL $19,X2 PXOR X2,X14 MOVOA X10,X1 PADDL X4,X1 MOVOA X1,X2 PSLLL $18,X1 PXOR X1,X0 PSRLL $14,X2 PXOR X2,X0 MOVOA 320(SP),X1 MOVOA X0,320(SP) MOVOA X8,X0 PADDL X14,X0 MOVOA X0,X2 PSLLL $18,X0 PXOR X0,X12 PSRLL $14,X2 PXOR X2,X12 MOVOA X11,X0 PADDL X1,X0 MOVOA X0,X2 PSLLL $7,X0 PXOR X0,X6 PSRLL $25,X2 PXOR X2,X6 MOVOA 336(SP),X2 MOVOA X12,336(SP) MOVOA X3,X0 PADDL X2,X0 MOVOA X0,X12 PSLLL $7,X0 PXOR X0,X13 PSRLL $25,X12 PXOR X12,X13 MOVOA X1,X0 PADDL X6,X0 MOVOA X0,X12 PSLLL $9,X0 PXOR X0,X15 PSRLL $23,X12 PXOR X12,X15 MOVOA X2,X0 PADDL X13,X0 MOVOA X0,X12 PSLLL $9,X0 PXOR X0,X9 PSRLL $23,X12 PXOR X12,X9 MOVOA X6,X0 PADDL X15,X0 MOVOA X0,X12 PSLLL $13,X0 PXOR X0,X11 PSRLL $19,X12 PXOR X12,X11 MOVOA X13,X0 PADDL X9,X0 MOVOA X0,X12 PSLLL $13,X0 PXOR X0,X3 PSRLL $19,X12 PXOR X12,X3 MOVOA X15,X0 PADDL X11,X0 MOVOA X0,X12 PSLLL $18,X0 PXOR X0,X1 PSRLL $14,X12 PXOR X12,X1 MOVOA X9,X0 PADDL X3,X0 MOVOA X0,X12 PSLLL $18,X0 PXOR X0,X2 PSRLL $14,X12 PXOR X12,X2 MOVOA 320(SP),X12 MOVOA 336(SP),X0 SUBQ $2,DX JA MAINLOOP1 PADDL 112(SP),X12 PADDL 176(SP),X7 PADDL 224(SP),X10 PADDL 272(SP),X4 MOVD X12,DX MOVD X7,CX MOVD X10,R8 MOVD X4,R9 PSHUFL $0X39,X12,X12 PSHUFL $0X39,X7,X7 PSHUFL $0X39,X10,X10 PSHUFL $0X39,X4,X4 XORL 0(SI),DX XORL 4(SI),CX XORL 8(SI),R8 XORL 12(SI),R9 MOVL DX,0(DI) MOVL CX,4(DI) MOVL R8,8(DI) MOVL R9,12(DI) MOVD X12,DX MOVD X7,CX MOVD X10,R8 MOVD X4,R9 PSHUFL $0X39,X12,X12 PSHUFL $0X39,X7,X7 PSHUFL $0X39,X10,X10 PSHUFL $0X39,X4,X4 XORL 64(SI),DX XORL 68(SI),CX XORL 72(SI),R8 XORL 76(SI),R9 MOVL DX,64(DI) MOVL CX,68(DI) MOVL R8,72(DI) MOVL R9,76(DI) MOVD X12,DX MOVD X7,CX MOVD X10,R8 MOVD X4,R9 PSHUFL $0X39,X12,X12 PSHUFL $0X39,X7,X7 PSHUFL $0X39,X10,X10 PSHUFL $0X39,X4,X4 XORL 128(SI),DX XORL 132(SI),CX XORL 136(SI),R8 XORL 140(SI),R9 MOVL DX,128(DI) MOVL CX,132(DI) MOVL R8,136(DI) MOVL R9,140(DI) MOVD X12,DX MOVD X7,CX MOVD X10,R8 MOVD X4,R9 XORL 192(SI),DX XORL 196(SI),CX XORL 200(SI),R8 XORL 204(SI),R9 MOVL DX,192(DI) MOVL CX,196(DI) MOVL R8,200(DI) MOVL R9,204(DI) PADDL 240(SP),X14 PADDL 64(SP),X0 PADDL 128(SP),X5 PADDL 192(SP),X8 MOVD X14,DX MOVD X0,CX MOVD X5,R8 MOVD X8,R9 PSHUFL $0X39,X14,X14 PSHUFL $0X39,X0,X0 PSHUFL $0X39,X5,X5 PSHUFL $0X39,X8,X8 XORL 16(SI),DX XORL 20(SI),CX XORL 24(SI),R8 XORL 28(SI),R9 MOVL DX,16(DI) MOVL CX,20(DI) MOVL R8,24(DI) MOVL R9,28(DI) MOVD X14,DX MOVD X0,CX MOVD X5,R8 MOVD X8,R9 PSHUFL $0X39,X14,X14 PSHUFL $0X39,X0,X0 PSHUFL $0X39,X5,X5 PSHUFL $0X39,X8,X8 XORL 80(SI),DX XORL 84(SI),CX XORL 88(SI),R8 XORL 92(SI),R9 MOVL DX,80(DI) MOVL CX,84(DI) MOVL R8,88(DI) MOVL R9,92(DI) MOVD X14,DX MOVD X0,CX MOVD X5,R8 MOVD X8,R9 PSHUFL $0X39,X14,X14 PSHUFL $0X39,X0,X0 PSHUFL $0X39,X5,X5 PSHUFL $0X39,X8,X8 XORL 144(SI),DX XORL 148(SI),CX XORL 152(SI),R8 XORL 156(SI),R9 MOVL DX,144(DI) MOVL CX,148(DI) MOVL R8,152(DI) MOVL R9,156(DI) MOVD X14,DX MOVD X0,CX MOVD X5,R8 MOVD X8,R9 XORL 208(SI),DX XORL 212(SI),CX XORL 216(SI),R8 XORL 220(SI),R9 MOVL DX,208(DI) MOVL CX,212(DI) MOVL R8,216(DI) MOVL R9,220(DI) PADDL 288(SP),X15 PADDL 304(SP),X11 PADDL 80(SP),X1 PADDL 144(SP),X6 MOVD X15,DX MOVD X11,CX MOVD X1,R8 MOVD X6,R9 PSHUFL $0X39,X15,X15 PSHUFL $0X39,X11,X11 PSHUFL $0X39,X1,X1 PSHUFL $0X39,X6,X6 XORL 32(SI),DX XORL 36(SI),CX XORL 40(SI),R8 XORL 44(SI),R9 MOVL DX,32(DI) MOVL CX,36(DI) MOVL R8,40(DI) MOVL R9,44(DI) MOVD X15,DX MOVD X11,CX MOVD X1,R8 MOVD X6,R9 PSHUFL $0X39,X15,X15 PSHUFL $0X39,X11,X11 PSHUFL $0X39,X1,X1 PSHUFL $0X39,X6,X6 XORL 96(SI),DX XORL 100(SI),CX XORL 104(SI),R8 XORL 108(SI),R9 MOVL DX,96(DI) MOVL CX,100(DI) MOVL R8,104(DI) MOVL R9,108(DI) MOVD X15,DX MOVD X11,CX MOVD X1,R8 MOVD X6,R9 PSHUFL $0X39,X15,X15 PSHUFL $0X39,X11,X11 PSHUFL $0X39,X1,X1 PSHUFL $0X39,X6,X6 XORL 160(SI),DX XORL 164(SI),CX XORL 168(SI),R8 XORL 172(SI),R9 MOVL DX,160(DI) MOVL CX,164(DI) MOVL R8,168(DI) MOVL R9,172(DI) MOVD X15,DX MOVD X11,CX MOVD X1,R8 MOVD X6,R9 XORL 224(SI),DX XORL 228(SI),CX XORL 232(SI),R8 XORL 236(SI),R9 MOVL DX,224(DI) MOVL CX,228(DI) MOVL R8,232(DI) MOVL R9,236(DI) PADDL 160(SP),X13 PADDL 208(SP),X9 PADDL 256(SP),X3 PADDL 96(SP),X2 MOVD X13,DX MOVD X9,CX MOVD X3,R8 MOVD X2,R9 PSHUFL $0X39,X13,X13 PSHUFL $0X39,X9,X9 PSHUFL $0X39,X3,X3 PSHUFL $0X39,X2,X2 XORL 48(SI),DX XORL 52(SI),CX XORL 56(SI),R8 XORL 60(SI),R9 MOVL DX,48(DI) MOVL CX,52(DI) MOVL R8,56(DI) MOVL R9,60(DI) MOVD X13,DX MOVD X9,CX MOVD X3,R8 MOVD X2,R9 PSHUFL $0X39,X13,X13 PSHUFL $0X39,X9,X9 PSHUFL $0X39,X3,X3 PSHUFL $0X39,X2,X2 XORL 112(SI),DX XORL 116(SI),CX XORL 120(SI),R8 XORL 124(SI),R9 MOVL DX,112(DI) MOVL CX,116(DI) MOVL R8,120(DI) MOVL R9,124(DI) MOVD X13,DX MOVD X9,CX MOVD X3,R8 MOVD X2,R9 PSHUFL $0X39,X13,X13 PSHUFL $0X39,X9,X9 PSHUFL $0X39,X3,X3 PSHUFL $0X39,X2,X2 XORL 176(SI),DX XORL 180(SI),CX XORL 184(SI),R8 XORL 188(SI),R9 MOVL DX,176(DI) MOVL CX,180(DI) MOVL R8,184(DI) MOVL R9,188(DI) MOVD X13,DX MOVD X9,CX MOVD X3,R8 MOVD X2,R9 XORL 240(SI),DX XORL 244(SI),CX XORL 248(SI),R8 XORL 252(SI),R9 MOVL DX,240(DI) MOVL CX,244(DI) MOVL R8,248(DI) MOVL R9,252(DI) MOVQ 408(SP),R9 SUBQ $256,R9 ADDQ $256,SI ADDQ $256,DI CMPQ R9,$256 JAE BYTESATLEAST256 CMPQ R9,$0 JBE DONE BYTESBETWEEN1AND255: CMPQ R9,$64 JAE NOCOPY MOVQ DI,DX LEAQ 416(SP),DI MOVQ R9,CX REP; MOVSB LEAQ 416(SP),DI LEAQ 416(SP),SI NOCOPY: MOVQ R9,408(SP) MOVOA 48(SP),X0 MOVOA 0(SP),X1 MOVOA 16(SP),X2 MOVOA 32(SP),X3 MOVOA X1,X4 MOVQ $20,CX MAINLOOP2: PADDL X0,X4 MOVOA X0,X5 MOVOA X4,X6 PSLLL $7,X4 PSRLL $25,X6 PXOR X4,X3 PXOR X6,X3 PADDL X3,X5 MOVOA X3,X4 MOVOA X5,X6 PSLLL $9,X5 PSRLL $23,X6 PXOR X5,X2 PSHUFL $0X93,X3,X3 PXOR X6,X2 PADDL X2,X4 MOVOA X2,X5 MOVOA X4,X6 PSLLL $13,X4 PSRLL $19,X6 PXOR X4,X1 PSHUFL $0X4E,X2,X2 PXOR X6,X1 PADDL X1,X5 MOVOA X3,X4 MOVOA X5,X6 PSLLL $18,X5 PSRLL $14,X6 PXOR X5,X0 PSHUFL $0X39,X1,X1 PXOR X6,X0 PADDL X0,X4 MOVOA X0,X5 MOVOA X4,X6 PSLLL $7,X4 PSRLL $25,X6 PXOR X4,X1 PXOR X6,X1 PADDL X1,X5 MOVOA X1,X4 MOVOA X5,X6 PSLLL $9,X5 PSRLL $23,X6 PXOR X5,X2 PSHUFL $0X93,X1,X1 PXOR X6,X2 PADDL X2,X4 MOVOA X2,X5 MOVOA X4,X6 PSLLL $13,X4 PSRLL $19,X6 PXOR X4,X3 PSHUFL $0X4E,X2,X2 PXOR X6,X3 PADDL X3,X5 MOVOA X1,X4 MOVOA X5,X6 PSLLL $18,X5 PSRLL $14,X6 PXOR X5,X0 PSHUFL $0X39,X3,X3 PXOR X6,X0 PADDL X0,X4 MOVOA X0,X5 MOVOA X4,X6 PSLLL $7,X4 PSRLL $25,X6 PXOR X4,X3 PXOR X6,X3 PADDL X3,X5 MOVOA X3,X4 MOVOA X5,X6 PSLLL $9,X5 PSRLL $23,X6 PXOR X5,X2 PSHUFL $0X93,X3,X3 PXOR X6,X2 PADDL X2,X4 MOVOA X2,X5 MOVOA X4,X6 PSLLL $13,X4 PSRLL $19,X6 PXOR X4,X1 PSHUFL $0X4E,X2,X2 PXOR X6,X1 PADDL X1,X5 MOVOA X3,X4 MOVOA X5,X6 PSLLL $18,X5 PSRLL $14,X6 PXOR X5,X0 PSHUFL $0X39,X1,X1 PXOR X6,X0 PADDL X0,X4 MOVOA X0,X5 MOVOA X4,X6 PSLLL $7,X4 PSRLL $25,X6 PXOR X4,X1 PXOR X6,X1 PADDL X1,X5 MOVOA X1,X4 MOVOA X5,X6 PSLLL $9,X5 PSRLL $23,X6 PXOR X5,X2 PSHUFL $0X93,X1,X1 PXOR X6,X2 PADDL X2,X4 MOVOA X2,X5 MOVOA X4,X6 PSLLL $13,X4 PSRLL $19,X6 PXOR X4,X3 PSHUFL $0X4E,X2,X2 PXOR X6,X3 SUBQ $4,CX PADDL X3,X5 MOVOA X1,X4 MOVOA X5,X6 PSLLL $18,X5 PXOR X7,X7 PSRLL $14,X6 PXOR X5,X0 PSHUFL $0X39,X3,X3 PXOR X6,X0 JA MAINLOOP2 PADDL 48(SP),X0 PADDL 0(SP),X1 PADDL 16(SP),X2 PADDL 32(SP),X3 MOVD X0,CX MOVD X1,R8 MOVD X2,R9 MOVD X3,AX PSHUFL $0X39,X0,X0 PSHUFL $0X39,X1,X1 PSHUFL $0X39,X2,X2 PSHUFL $0X39,X3,X3 XORL 0(SI),CX XORL 48(SI),R8 XORL 32(SI),R9 XORL 16(SI),AX MOVL CX,0(DI) MOVL R8,48(DI) MOVL R9,32(DI) MOVL AX,16(DI) MOVD X0,CX MOVD X1,R8 MOVD X2,R9 MOVD X3,AX PSHUFL $0X39,X0,X0 PSHUFL $0X39,X1,X1 PSHUFL $0X39,X2,X2 PSHUFL $0X39,X3,X3 XORL 20(SI),CX XORL 4(SI),R8 XORL 52(SI),R9 XORL 36(SI),AX MOVL CX,20(DI) MOVL R8,4(DI) MOVL R9,52(DI) MOVL AX,36(DI) MOVD X0,CX MOVD X1,R8 MOVD X2,R9 MOVD X3,AX PSHUFL $0X39,X0,X0 PSHUFL $0X39,X1,X1 PSHUFL $0X39,X2,X2 PSHUFL $0X39,X3,X3 XORL 40(SI),CX XORL 24(SI),R8 XORL 8(SI),R9 XORL 56(SI),AX MOVL CX,40(DI) MOVL R8,24(DI) MOVL R9,8(DI) MOVL AX,56(DI) MOVD X0,CX MOVD X1,R8 MOVD X2,R9 MOVD X3,AX XORL 60(SI),CX XORL 44(SI),R8 XORL 28(SI),R9 XORL 12(SI),AX MOVL CX,60(DI) MOVL R8,44(DI) MOVL R9,28(DI) MOVL AX,12(DI) MOVQ 408(SP),R9 MOVL 16(SP),CX MOVL 36 (SP),R8 ADDQ $1,CX SHLQ $32,R8 ADDQ R8,CX MOVQ CX,R8 SHRQ $32,R8 MOVL CX,16(SP) MOVL R8, 36 (SP) CMPQ R9,$64 JA BYTESATLEAST65 JAE BYTESATLEAST64 MOVQ DI,SI MOVQ DX,DI MOVQ R9,CX REP; MOVSB BYTESATLEAST64: DONE: MOVQ 352(SP),R11 MOVQ 360(SP),R12 MOVQ 368(SP),R13 MOVQ 376(SP),R14 MOVQ 384(SP),R15 MOVQ 392(SP),BX MOVQ 400(SP),BP MOVQ R11,SP RET BYTESATLEAST65: SUBQ $64,R9 ADDQ $64,DI ADDQ $64,SI JMP BYTESBETWEEN1AND255 lxd-2.0.0/dist/src/golang.org/x/crypto/salsa20/salsa/hsalsa20.go0000644061062106075000000001000212702772344026601 0ustar00stgraberdomain admins00000000000000// Copyright 2012 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 salsa provides low-level access to functions in the Salsa family. package salsa // import "golang.org/x/crypto/salsa20/salsa" // Sigma is the Salsa20 constant for 256-bit keys. var Sigma = [16]byte{'e', 'x', 'p', 'a', 'n', 'd', ' ', '3', '2', '-', 'b', 'y', 't', 'e', ' ', 'k'} // HSalsa20 applies the HSalsa20 core function to a 16-byte input in, 32-byte // key k, and 16-byte constant c, and puts the result into the 32-byte array // out. func HSalsa20(out *[32]byte, in *[16]byte, k *[32]byte, c *[16]byte) { x0 := uint32(c[0]) | uint32(c[1])<<8 | uint32(c[2])<<16 | uint32(c[3])<<24 x1 := uint32(k[0]) | uint32(k[1])<<8 | uint32(k[2])<<16 | uint32(k[3])<<24 x2 := uint32(k[4]) | uint32(k[5])<<8 | uint32(k[6])<<16 | uint32(k[7])<<24 x3 := uint32(k[8]) | uint32(k[9])<<8 | uint32(k[10])<<16 | uint32(k[11])<<24 x4 := uint32(k[12]) | uint32(k[13])<<8 | uint32(k[14])<<16 | uint32(k[15])<<24 x5 := uint32(c[4]) | uint32(c[5])<<8 | uint32(c[6])<<16 | uint32(c[7])<<24 x6 := uint32(in[0]) | uint32(in[1])<<8 | uint32(in[2])<<16 | uint32(in[3])<<24 x7 := uint32(in[4]) | uint32(in[5])<<8 | uint32(in[6])<<16 | uint32(in[7])<<24 x8 := uint32(in[8]) | uint32(in[9])<<8 | uint32(in[10])<<16 | uint32(in[11])<<24 x9 := uint32(in[12]) | uint32(in[13])<<8 | uint32(in[14])<<16 | uint32(in[15])<<24 x10 := uint32(c[8]) | uint32(c[9])<<8 | uint32(c[10])<<16 | uint32(c[11])<<24 x11 := uint32(k[16]) | uint32(k[17])<<8 | uint32(k[18])<<16 | uint32(k[19])<<24 x12 := uint32(k[20]) | uint32(k[21])<<8 | uint32(k[22])<<16 | uint32(k[23])<<24 x13 := uint32(k[24]) | uint32(k[25])<<8 | uint32(k[26])<<16 | uint32(k[27])<<24 x14 := uint32(k[28]) | uint32(k[29])<<8 | uint32(k[30])<<16 | uint32(k[31])<<24 x15 := uint32(c[12]) | uint32(c[13])<<8 | uint32(c[14])<<16 | uint32(c[15])<<24 for i := 0; i < 20; i += 2 { u := x0 + x12 x4 ^= u<<7 | u>>(32-7) u = x4 + x0 x8 ^= u<<9 | u>>(32-9) u = x8 + x4 x12 ^= u<<13 | u>>(32-13) u = x12 + x8 x0 ^= u<<18 | u>>(32-18) u = x5 + x1 x9 ^= u<<7 | u>>(32-7) u = x9 + x5 x13 ^= u<<9 | u>>(32-9) u = x13 + x9 x1 ^= u<<13 | u>>(32-13) u = x1 + x13 x5 ^= u<<18 | u>>(32-18) u = x10 + x6 x14 ^= u<<7 | u>>(32-7) u = x14 + x10 x2 ^= u<<9 | u>>(32-9) u = x2 + x14 x6 ^= u<<13 | u>>(32-13) u = x6 + x2 x10 ^= u<<18 | u>>(32-18) u = x15 + x11 x3 ^= u<<7 | u>>(32-7) u = x3 + x15 x7 ^= u<<9 | u>>(32-9) u = x7 + x3 x11 ^= u<<13 | u>>(32-13) u = x11 + x7 x15 ^= u<<18 | u>>(32-18) u = x0 + x3 x1 ^= u<<7 | u>>(32-7) u = x1 + x0 x2 ^= u<<9 | u>>(32-9) u = x2 + x1 x3 ^= u<<13 | u>>(32-13) u = x3 + x2 x0 ^= u<<18 | u>>(32-18) u = x5 + x4 x6 ^= u<<7 | u>>(32-7) u = x6 + x5 x7 ^= u<<9 | u>>(32-9) u = x7 + x6 x4 ^= u<<13 | u>>(32-13) u = x4 + x7 x5 ^= u<<18 | u>>(32-18) u = x10 + x9 x11 ^= u<<7 | u>>(32-7) u = x11 + x10 x8 ^= u<<9 | u>>(32-9) u = x8 + x11 x9 ^= u<<13 | u>>(32-13) u = x9 + x8 x10 ^= u<<18 | u>>(32-18) u = x15 + x14 x12 ^= u<<7 | u>>(32-7) u = x12 + x15 x13 ^= u<<9 | u>>(32-9) u = x13 + x12 x14 ^= u<<13 | u>>(32-13) u = x14 + x13 x15 ^= u<<18 | u>>(32-18) } out[0] = byte(x0) out[1] = byte(x0 >> 8) out[2] = byte(x0 >> 16) out[3] = byte(x0 >> 24) out[4] = byte(x5) out[5] = byte(x5 >> 8) out[6] = byte(x5 >> 16) out[7] = byte(x5 >> 24) out[8] = byte(x10) out[9] = byte(x10 >> 8) out[10] = byte(x10 >> 16) out[11] = byte(x10 >> 24) out[12] = byte(x15) out[13] = byte(x15 >> 8) out[14] = byte(x15 >> 16) out[15] = byte(x15 >> 24) out[16] = byte(x6) out[17] = byte(x6 >> 8) out[18] = byte(x6 >> 16) out[19] = byte(x6 >> 24) out[20] = byte(x7) out[21] = byte(x7 >> 8) out[22] = byte(x7 >> 16) out[23] = byte(x7 >> 24) out[24] = byte(x8) out[25] = byte(x8 >> 8) out[26] = byte(x8 >> 16) out[27] = byte(x8 >> 24) out[28] = byte(x9) out[29] = byte(x9 >> 8) out[30] = byte(x9 >> 16) out[31] = byte(x9 >> 24) } lxd-2.0.0/dist/src/golang.org/x/crypto/salsa20/salsa/salsa208.go0000644061062106075000000001156712702772344026542 0ustar00stgraberdomain admins00000000000000// Copyright 2012 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 salsa // Core208 applies the Salsa20/8 core function to the 64-byte array in and puts // the result into the 64-byte array out. The input and output may be the same array. func Core208(out *[64]byte, in *[64]byte) { j0 := uint32(in[0]) | uint32(in[1])<<8 | uint32(in[2])<<16 | uint32(in[3])<<24 j1 := uint32(in[4]) | uint32(in[5])<<8 | uint32(in[6])<<16 | uint32(in[7])<<24 j2 := uint32(in[8]) | uint32(in[9])<<8 | uint32(in[10])<<16 | uint32(in[11])<<24 j3 := uint32(in[12]) | uint32(in[13])<<8 | uint32(in[14])<<16 | uint32(in[15])<<24 j4 := uint32(in[16]) | uint32(in[17])<<8 | uint32(in[18])<<16 | uint32(in[19])<<24 j5 := uint32(in[20]) | uint32(in[21])<<8 | uint32(in[22])<<16 | uint32(in[23])<<24 j6 := uint32(in[24]) | uint32(in[25])<<8 | uint32(in[26])<<16 | uint32(in[27])<<24 j7 := uint32(in[28]) | uint32(in[29])<<8 | uint32(in[30])<<16 | uint32(in[31])<<24 j8 := uint32(in[32]) | uint32(in[33])<<8 | uint32(in[34])<<16 | uint32(in[35])<<24 j9 := uint32(in[36]) | uint32(in[37])<<8 | uint32(in[38])<<16 | uint32(in[39])<<24 j10 := uint32(in[40]) | uint32(in[41])<<8 | uint32(in[42])<<16 | uint32(in[43])<<24 j11 := uint32(in[44]) | uint32(in[45])<<8 | uint32(in[46])<<16 | uint32(in[47])<<24 j12 := uint32(in[48]) | uint32(in[49])<<8 | uint32(in[50])<<16 | uint32(in[51])<<24 j13 := uint32(in[52]) | uint32(in[53])<<8 | uint32(in[54])<<16 | uint32(in[55])<<24 j14 := uint32(in[56]) | uint32(in[57])<<8 | uint32(in[58])<<16 | uint32(in[59])<<24 j15 := uint32(in[60]) | uint32(in[61])<<8 | uint32(in[62])<<16 | uint32(in[63])<<24 x0, x1, x2, x3, x4, x5, x6, x7, x8 := j0, j1, j2, j3, j4, j5, j6, j7, j8 x9, x10, x11, x12, x13, x14, x15 := j9, j10, j11, j12, j13, j14, j15 for i := 0; i < 8; i += 2 { u := x0 + x12 x4 ^= u<<7 | u>>(32-7) u = x4 + x0 x8 ^= u<<9 | u>>(32-9) u = x8 + x4 x12 ^= u<<13 | u>>(32-13) u = x12 + x8 x0 ^= u<<18 | u>>(32-18) u = x5 + x1 x9 ^= u<<7 | u>>(32-7) u = x9 + x5 x13 ^= u<<9 | u>>(32-9) u = x13 + x9 x1 ^= u<<13 | u>>(32-13) u = x1 + x13 x5 ^= u<<18 | u>>(32-18) u = x10 + x6 x14 ^= u<<7 | u>>(32-7) u = x14 + x10 x2 ^= u<<9 | u>>(32-9) u = x2 + x14 x6 ^= u<<13 | u>>(32-13) u = x6 + x2 x10 ^= u<<18 | u>>(32-18) u = x15 + x11 x3 ^= u<<7 | u>>(32-7) u = x3 + x15 x7 ^= u<<9 | u>>(32-9) u = x7 + x3 x11 ^= u<<13 | u>>(32-13) u = x11 + x7 x15 ^= u<<18 | u>>(32-18) u = x0 + x3 x1 ^= u<<7 | u>>(32-7) u = x1 + x0 x2 ^= u<<9 | u>>(32-9) u = x2 + x1 x3 ^= u<<13 | u>>(32-13) u = x3 + x2 x0 ^= u<<18 | u>>(32-18) u = x5 + x4 x6 ^= u<<7 | u>>(32-7) u = x6 + x5 x7 ^= u<<9 | u>>(32-9) u = x7 + x6 x4 ^= u<<13 | u>>(32-13) u = x4 + x7 x5 ^= u<<18 | u>>(32-18) u = x10 + x9 x11 ^= u<<7 | u>>(32-7) u = x11 + x10 x8 ^= u<<9 | u>>(32-9) u = x8 + x11 x9 ^= u<<13 | u>>(32-13) u = x9 + x8 x10 ^= u<<18 | u>>(32-18) u = x15 + x14 x12 ^= u<<7 | u>>(32-7) u = x12 + x15 x13 ^= u<<9 | u>>(32-9) u = x13 + x12 x14 ^= u<<13 | u>>(32-13) u = x14 + x13 x15 ^= u<<18 | u>>(32-18) } x0 += j0 x1 += j1 x2 += j2 x3 += j3 x4 += j4 x5 += j5 x6 += j6 x7 += j7 x8 += j8 x9 += j9 x10 += j10 x11 += j11 x12 += j12 x13 += j13 x14 += j14 x15 += j15 out[0] = byte(x0) out[1] = byte(x0 >> 8) out[2] = byte(x0 >> 16) out[3] = byte(x0 >> 24) out[4] = byte(x1) out[5] = byte(x1 >> 8) out[6] = byte(x1 >> 16) out[7] = byte(x1 >> 24) out[8] = byte(x2) out[9] = byte(x2 >> 8) out[10] = byte(x2 >> 16) out[11] = byte(x2 >> 24) out[12] = byte(x3) out[13] = byte(x3 >> 8) out[14] = byte(x3 >> 16) out[15] = byte(x3 >> 24) out[16] = byte(x4) out[17] = byte(x4 >> 8) out[18] = byte(x4 >> 16) out[19] = byte(x4 >> 24) out[20] = byte(x5) out[21] = byte(x5 >> 8) out[22] = byte(x5 >> 16) out[23] = byte(x5 >> 24) out[24] = byte(x6) out[25] = byte(x6 >> 8) out[26] = byte(x6 >> 16) out[27] = byte(x6 >> 24) out[28] = byte(x7) out[29] = byte(x7 >> 8) out[30] = byte(x7 >> 16) out[31] = byte(x7 >> 24) out[32] = byte(x8) out[33] = byte(x8 >> 8) out[34] = byte(x8 >> 16) out[35] = byte(x8 >> 24) out[36] = byte(x9) out[37] = byte(x9 >> 8) out[38] = byte(x9 >> 16) out[39] = byte(x9 >> 24) out[40] = byte(x10) out[41] = byte(x10 >> 8) out[42] = byte(x10 >> 16) out[43] = byte(x10 >> 24) out[44] = byte(x11) out[45] = byte(x11 >> 8) out[46] = byte(x11 >> 16) out[47] = byte(x11 >> 24) out[48] = byte(x12) out[49] = byte(x12 >> 8) out[50] = byte(x12 >> 16) out[51] = byte(x12 >> 24) out[52] = byte(x13) out[53] = byte(x13 >> 8) out[54] = byte(x13 >> 16) out[55] = byte(x13 >> 24) out[56] = byte(x14) out[57] = byte(x14 >> 8) out[58] = byte(x14 >> 16) out[59] = byte(x14 >> 24) out[60] = byte(x15) out[61] = byte(x15 >> 8) out[62] = byte(x15 >> 16) out[63] = byte(x15 >> 24) } lxd-2.0.0/dist/src/golang.org/x/crypto/salsa20/salsa20_test.go0000644061062106075000000000727312702772344026405 0ustar00stgraberdomain admins00000000000000// Copyright 2012 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 salsa20 import ( "bytes" "encoding/hex" "testing" ) func fromHex(s string) []byte { ret, err := hex.DecodeString(s) if err != nil { panic(err) } return ret } // testVectors was taken from set 6 of the ECRYPT test vectors: // http://www.ecrypt.eu.org/stream/svn/viewcvs.cgi/ecrypt/trunk/submissions/salsa20/full/verified.test-vectors?logsort=rev&rev=210&view=markup var testVectors = []struct { key []byte iv []byte numBytes int xor []byte }{ { fromHex("0053A6F94C9FF24598EB3E91E4378ADD3083D6297CCF2275C81B6EC11467BA0D"), fromHex("0D74DB42A91077DE"), 131072, fromHex("C349B6A51A3EC9B712EAED3F90D8BCEE69B7628645F251A996F55260C62EF31FD6C6B0AEA94E136C9D984AD2DF3578F78E457527B03A0450580DD874F63B1AB9"), }, { fromHex("0558ABFE51A4F74A9DF04396E93C8FE23588DB2E81D4277ACD2073C6196CBF12"), fromHex("167DE44BB21980E7"), 131072, fromHex("C3EAAF32836BACE32D04E1124231EF47E101367D6305413A0EEB07C60698A2876E4D031870A739D6FFDDD208597AFF0A47AC17EDB0167DD67EBA84F1883D4DFD"), }, { fromHex("0A5DB00356A9FC4FA2F5489BEE4194E73A8DE03386D92C7FD22578CB1E71C417"), fromHex("1F86ED54BB2289F0"), 131072, fromHex("3CD23C3DC90201ACC0CF49B440B6C417F0DC8D8410A716D5314C059E14B1A8D9A9FB8EA3D9C8DAE12B21402F674AA95C67B1FC514E994C9D3F3A6E41DFF5BBA6"), }, { fromHex("0F62B5085BAE0154A7FA4DA0F34699EC3F92E5388BDE3184D72A7DD02376C91C"), fromHex("288FF65DC42B92F9"), 131072, fromHex("E00EBCCD70D69152725F9987982178A2E2E139C7BCBE04CA8A0E99E318D9AB76F988C8549F75ADD790BA4F81C176DA653C1A043F11A958E169B6D2319F4EEC1A"), }, } func TestSalsa20(t *testing.T) { var inBuf, outBuf []byte var key [32]byte for i, test := range testVectors { if test.numBytes%64 != 0 { t.Errorf("#%d: numBytes is not a multiple of 64", i) continue } if test.numBytes > len(inBuf) { inBuf = make([]byte, test.numBytes) outBuf = make([]byte, test.numBytes) } in := inBuf[:test.numBytes] out := outBuf[:test.numBytes] copy(key[:], test.key) XORKeyStream(out, in, test.iv, &key) var xor [64]byte for len(out) > 0 { for i := 0; i < 64; i++ { xor[i] ^= out[i] } out = out[64:] } if !bytes.Equal(xor[:], test.xor) { t.Errorf("#%d: bad result", i) } } } var xSalsa20TestData = []struct { in, nonce, key, out []byte }{ { []byte("Hello world!"), []byte("24-byte nonce for xsalsa"), []byte("this is 32-byte key for xsalsa20"), []byte{0x00, 0x2d, 0x45, 0x13, 0x84, 0x3f, 0xc2, 0x40, 0xc4, 0x01, 0xe5, 0x41}, }, { make([]byte, 64), []byte("24-byte nonce for xsalsa"), []byte("this is 32-byte key for xsalsa20"), []byte{0x48, 0x48, 0x29, 0x7f, 0xeb, 0x1f, 0xb5, 0x2f, 0xb6, 0x6d, 0x81, 0x60, 0x9b, 0xd5, 0x47, 0xfa, 0xbc, 0xbe, 0x70, 0x26, 0xed, 0xc8, 0xb5, 0xe5, 0xe4, 0x49, 0xd0, 0x88, 0xbf, 0xa6, 0x9c, 0x08, 0x8f, 0x5d, 0x8d, 0xa1, 0xd7, 0x91, 0x26, 0x7c, 0x2c, 0x19, 0x5a, 0x7f, 0x8c, 0xae, 0x9c, 0x4b, 0x40, 0x50, 0xd0, 0x8c, 0xe6, 0xd3, 0xa1, 0x51, 0xec, 0x26, 0x5f, 0x3a, 0x58, 0xe4, 0x76, 0x48}, }, } func TestXSalsa20(t *testing.T) { var key [32]byte for i, test := range xSalsa20TestData { out := make([]byte, len(test.in)) copy(key[:], test.key) XORKeyStream(out, test.in, test.nonce, &key) if !bytes.Equal(out, test.out) { t.Errorf("%d: expected %x, got %x", i, test.out, out) } } } var ( keyArray [32]byte key = &keyArray nonce [8]byte msg = make([]byte, 1<<10) ) func BenchmarkXOR1K(b *testing.B) { b.StopTimer() out := make([]byte, 1024) b.StartTimer() for i := 0; i < b.N; i++ { XORKeyStream(out, msg[:1024], nonce[:], key) } b.SetBytes(1024) } lxd-2.0.0/dist/src/golang.org/x/crypto/salsa20/salsa20.go0000644061062106075000000000357712702772344025351 0ustar00stgraberdomain admins00000000000000// Copyright 2012 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 salsa20 implements the Salsa20 stream cipher as specified in http://cr.yp.to/snuffle/spec.pdf. Salsa20 differs from many other stream ciphers in that it is message orientated rather than byte orientated. Keystream blocks are not preserved between calls, therefore each side must encrypt/decrypt data with the same segmentation. Another aspect of this difference is that part of the counter is exposed as an nonce in each call. Encrypting two different messages with the same (key, nonce) pair leads to trivial plaintext recovery. This is analogous to encrypting two different messages with the same key with a traditional stream cipher. This package also implements XSalsa20: a version of Salsa20 with a 24-byte nonce as specified in http://cr.yp.to/snuffle/xsalsa-20081128.pdf. Simply passing a 24-byte slice as the nonce triggers XSalsa20. */ package salsa20 // import "golang.org/x/crypto/salsa20" // TODO(agl): implement XORKeyStream12 and XORKeyStream8 - the reduced round variants of Salsa20. import ( "golang.org/x/crypto/salsa20/salsa" ) // XORKeyStream crypts bytes from in to out using the given key and nonce. In // and out may be the same slice but otherwise should not overlap. Nonce must // be either 8 or 24 bytes long. func XORKeyStream(out, in []byte, nonce []byte, key *[32]byte) { if len(out) < len(in) { in = in[:len(out)] } var subNonce [16]byte if len(nonce) == 24 { var subKey [32]byte var hNonce [16]byte copy(hNonce[:], nonce[:16]) salsa.HSalsa20(&subKey, &hNonce, key, &salsa.Sigma) copy(subNonce[:], nonce[16:]) key = &subKey } else if len(nonce) == 8 { copy(subNonce[:], nonce[:]) } else { panic("salsa20: nonce must be 8 or 24 bytes") } salsa.XORKeyStream(out, in, &subNonce, key) } lxd-2.0.0/dist/src/golang.org/x/crypto/xtea/0000755061062106075000000000000012702772344023235 5ustar00stgraberdomain admins00000000000000lxd-2.0.0/dist/src/golang.org/x/crypto/xtea/block.go0000644061062106075000000000341712702772344024663 0ustar00stgraberdomain admins00000000000000// Copyright 2009 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. /* Implementation adapted from Needham and Wheeler's paper: http://www.cix.co.uk/~klockstone/xtea.pdf A precalculated look up table is used during encryption/decryption for values that are based purely on the key. */ package xtea // XTEA is based on 64 rounds. const numRounds = 64 // blockToUint32 reads an 8 byte slice into two uint32s. // The block is treated as big endian. func blockToUint32(src []byte) (uint32, uint32) { r0 := uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3]) r1 := uint32(src[4])<<24 | uint32(src[5])<<16 | uint32(src[6])<<8 | uint32(src[7]) return r0, r1 } // uint32ToBlock writes two uint32s into an 8 byte data block. // Values are written as big endian. func uint32ToBlock(v0, v1 uint32, dst []byte) { dst[0] = byte(v0 >> 24) dst[1] = byte(v0 >> 16) dst[2] = byte(v0 >> 8) dst[3] = byte(v0) dst[4] = byte(v1 >> 24) dst[5] = byte(v1 >> 16) dst[6] = byte(v1 >> 8) dst[7] = byte(v1 >> 0) } // encryptBlock encrypts a single 8 byte block using XTEA. func encryptBlock(c *Cipher, dst, src []byte) { v0, v1 := blockToUint32(src) // Two rounds of XTEA applied per loop for i := 0; i < numRounds; { v0 += ((v1<<4 ^ v1>>5) + v1) ^ c.table[i] i++ v1 += ((v0<<4 ^ v0>>5) + v0) ^ c.table[i] i++ } uint32ToBlock(v0, v1, dst) } // decryptBlock decrypt a single 8 byte block using XTEA. func decryptBlock(c *Cipher, dst, src []byte) { v0, v1 := blockToUint32(src) // Two rounds of XTEA applied per loop for i := numRounds; i > 0; { i-- v1 -= ((v0<<4 ^ v0>>5) + v0) ^ c.table[i] i-- v0 -= ((v1<<4 ^ v1>>5) + v1) ^ c.table[i] } uint32ToBlock(v0, v1, dst) } lxd-2.0.0/dist/src/golang.org/x/crypto/xtea/cipher.go0000644061062106075000000000460412702772344025042 0ustar00stgraberdomain admins00000000000000// Copyright 2009 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Package xtea implements XTEA encryption, as defined in Needham and Wheeler's // 1997 technical report, "Tea extensions." package xtea // import "golang.org/x/crypto/xtea" // For details, see http://www.cix.co.uk/~klockstone/xtea.pdf import "strconv" // The XTEA block size in bytes. const BlockSize = 8 // A Cipher is an instance of an XTEA cipher using a particular key. // table contains a series of precalculated values that are used each round. type Cipher struct { table [64]uint32 } type KeySizeError int func (k KeySizeError) Error() string { return "crypto/xtea: invalid key size " + strconv.Itoa(int(k)) } // NewCipher creates and returns a new Cipher. // The key argument should be the XTEA key. // XTEA only supports 128 bit (16 byte) keys. func NewCipher(key []byte) (*Cipher, error) { k := len(key) switch k { default: return nil, KeySizeError(k) case 16: break } c := new(Cipher) initCipher(c, key) return c, nil } // BlockSize returns the XTEA block size, 8 bytes. // It is necessary to satisfy the Block interface in the // package "crypto/cipher". func (c *Cipher) BlockSize() int { return BlockSize } // Encrypt encrypts the 8 byte buffer src using the key and stores the result in dst. // Note that for amounts of data larger than a block, // it is not safe to just call Encrypt on successive blocks; // instead, use an encryption mode like CBC (see crypto/cipher/cbc.go). func (c *Cipher) Encrypt(dst, src []byte) { encryptBlock(c, dst, src) } // Decrypt decrypts the 8 byte buffer src using the key k and stores the result in dst. func (c *Cipher) Decrypt(dst, src []byte) { decryptBlock(c, dst, src) } // initCipher initializes the cipher context by creating a look up table // of precalculated values that are based on the key. func initCipher(c *Cipher, key []byte) { // Load the key into four uint32s var k [4]uint32 for i := 0; i < len(k); i++ { j := i << 2 // Multiply by 4 k[i] = uint32(key[j+0])<<24 | uint32(key[j+1])<<16 | uint32(key[j+2])<<8 | uint32(key[j+3]) } // Precalculate the table const delta = 0x9E3779B9 var sum uint32 = 0 // Two rounds of XTEA applied per loop for i := 0; i < numRounds; { c.table[i] = sum + k[sum&3] i++ sum += delta c.table[i] = sum + k[(sum>>11)&3] i++ } } lxd-2.0.0/dist/src/golang.org/x/crypto/xtea/xtea_test.go0000644061062106075000000001637112702772344025574 0ustar00stgraberdomain admins00000000000000// Copyright 2009 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package xtea import ( "testing" ) // A sample test key for when we just want to initialize a cipher var testKey = []byte{0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF} // Test that the block size for XTEA is correct func TestBlocksize(t *testing.T) { if BlockSize != 8 { t.Errorf("BlockSize constant - expected 8, got %d", BlockSize) return } c, err := NewCipher(testKey) if err != nil { t.Errorf("NewCipher(%d bytes) = %s", len(testKey), err) return } result := c.BlockSize() if result != 8 { t.Errorf("BlockSize function - expected 8, got %d", result) return } } // A series of test values to confirm that the Cipher.table array was initialized correctly var testTable = []uint32{ 0x00112233, 0x6B1568B8, 0xE28CE030, 0xC5089E2D, 0xC5089E2D, 0x1EFBD3A2, 0xA7845C2A, 0x78EF0917, 0x78EF0917, 0x172682D0, 0x5B6AC714, 0x822AC955, 0x3DE68511, 0xDC1DFECA, 0x2062430E, 0x3611343F, 0xF1CCEFFB, 0x900469B4, 0xD448ADF8, 0x2E3BE36D, 0xB6C46BF5, 0x994029F2, 0x994029F2, 0xF3335F67, 0x6AAAD6DF, 0x4D2694DC, 0x4D2694DC, 0xEB5E0E95, 0x2FA252D9, 0x4551440A, 0x121E10D6, 0xB0558A8F, 0xE388BDC3, 0x0A48C004, 0xC6047BC0, 0x643BF579, 0xA88039BD, 0x02736F32, 0x8AFBF7BA, 0x5C66A4A7, 0x5C66A4A7, 0xC76AEB2C, 0x3EE262A4, 0x215E20A1, 0x215E20A1, 0x7B515616, 0x03D9DE9E, 0x1988CFCF, 0xD5448B8B, 0x737C0544, 0xB7C04988, 0xDE804BC9, 0x9A3C0785, 0x3873813E, 0x7CB7C582, 0xD6AAFAF7, 0x4E22726F, 0x309E306C, 0x309E306C, 0x8A9165E1, 0x1319EE69, 0xF595AC66, 0xF595AC66, 0x4F88E1DB, } // Test that the cipher context is initialized correctly func TestCipherInit(t *testing.T) { c, err := NewCipher(testKey) if err != nil { t.Errorf("NewCipher(%d bytes) = %s", len(testKey), err) return } for i := 0; i < len(c.table); i++ { if c.table[i] != testTable[i] { t.Errorf("NewCipher() failed to initialize Cipher.table[%d] correctly. Expected %08X, got %08X", i, testTable[i], c.table[i]) break } } } // Test that invalid key sizes return an error func TestInvalidKeySize(t *testing.T) { // Test a long key key := []byte{ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, } _, err := NewCipher(key) if err == nil { t.Errorf("Invalid key size %d didn't result in an error.", len(key)) } // Test a short key key = []byte{0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77} _, err = NewCipher(key) if err == nil { t.Errorf("Invalid key size %d didn't result in an error.", len(key)) } } // Test that we can correctly decode some bytes we have encoded func TestEncodeDecode(t *testing.T) { original := []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF} input := original output := make([]byte, BlockSize) c, err := NewCipher(testKey) if err != nil { t.Errorf("NewCipher(%d bytes) = %s", len(testKey), err) return } // Encrypt the input block c.Encrypt(output, input) // Check that the output does not match the input differs := false for i := 0; i < len(input); i++ { if output[i] != input[i] { differs = true break } } if differs == false { t.Error("Cipher.Encrypt: Failed to encrypt the input block.") return } // Decrypt the block we just encrypted input = output output = make([]byte, BlockSize) c.Decrypt(output, input) // Check that the output from decrypt matches our initial input for i := 0; i < len(input); i++ { if output[i] != original[i] { t.Errorf("Decrypted byte %d differed. Expected %02X, got %02X\n", i, original[i], output[i]) return } } } // Test Vectors type CryptTest struct { key []byte plainText []byte cipherText []byte } var CryptTests = []CryptTest{ // These were sourced from http://www.freemedialibrary.com/index.php/XTEA_test_vectors { []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f}, []byte{0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48}, []byte{0x49, 0x7d, 0xf3, 0xd0, 0x72, 0x61, 0x2c, 0xb5}, }, { []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f}, []byte{0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41}, []byte{0xe7, 0x8f, 0x2d, 0x13, 0x74, 0x43, 0x41, 0xd8}, }, { []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f}, []byte{0x5a, 0x5b, 0x6e, 0x27, 0x89, 0x48, 0xd7, 0x7f}, []byte{0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41}, }, { []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, []byte{0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48}, []byte{0xa0, 0x39, 0x05, 0x89, 0xf8, 0xb8, 0xef, 0xa5}, }, { []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, []byte{0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41}, []byte{0xed, 0x23, 0x37, 0x5a, 0x82, 0x1a, 0x8c, 0x2d}, }, { []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, []byte{0x70, 0xe1, 0x22, 0x5d, 0x6e, 0x4e, 0x76, 0x55}, []byte{0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41}, }, // These vectors are from http://wiki.secondlife.com/wiki/XTEA_Strong_Encryption_Implementation#Bouncy_Castle_C.23_API { []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, []byte{0xDE, 0xE9, 0xD4, 0xD8, 0xF7, 0x13, 0x1E, 0xD9}, }, { []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, []byte{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08}, []byte{0x06, 0x5C, 0x1B, 0x89, 0x75, 0xC6, 0xA8, 0x16}, }, { []byte{0x01, 0x23, 0x45, 0x67, 0x12, 0x34, 0x56, 0x78, 0x23, 0x45, 0x67, 0x89, 0x34, 0x56, 0x78, 0x9A}, []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, []byte{0x1F, 0xF9, 0xA0, 0x26, 0x1A, 0xC6, 0x42, 0x64}, }, { []byte{0x01, 0x23, 0x45, 0x67, 0x12, 0x34, 0x56, 0x78, 0x23, 0x45, 0x67, 0x89, 0x34, 0x56, 0x78, 0x9A}, []byte{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08}, []byte{0x8C, 0x67, 0x15, 0x5B, 0x2E, 0xF9, 0x1E, 0xAD}, }, } // Test encryption func TestCipherEncrypt(t *testing.T) { for i, tt := range CryptTests { c, err := NewCipher(tt.key) if err != nil { t.Errorf("NewCipher(%d bytes), vector %d = %s", len(tt.key), i, err) continue } out := make([]byte, len(tt.plainText)) c.Encrypt(out, tt.plainText) for j := 0; j < len(out); j++ { if out[j] != tt.cipherText[j] { t.Errorf("Cipher.Encrypt %d: out[%d] = %02X, expected %02X", i, j, out[j], tt.cipherText[j]) break } } } } // Test decryption func TestCipherDecrypt(t *testing.T) { for i, tt := range CryptTests { c, err := NewCipher(tt.key) if err != nil { t.Errorf("NewCipher(%d bytes), vector %d = %s", len(tt.key), i, err) continue } out := make([]byte, len(tt.cipherText)) c.Decrypt(out, tt.cipherText) for j := 0; j < len(out); j++ { if out[j] != tt.plainText[j] { t.Errorf("Cipher.Decrypt %d: out[%d] = %02X, expected %02X", i, j, out[j], tt.plainText[j]) break } } } } lxd-2.0.0/dist/src/golang.org/x/crypto/CONTRIBUTING.md0000644061062106075000000000200712702772344024524 0ustar00stgraberdomain admins00000000000000# Contributing to Go Go is an open source project. It is the work of hundreds of contributors. We appreciate your help! ## Filing issues When [filing an issue](https://golang.org/issue/new), make sure to answer these five questions: 1. What version of Go are you using (`go version`)? 2. What operating system and processor architecture are you using? 3. What did you do? 4. What did you expect to see? 5. What did you see instead? General questions should go to the [golang-nuts mailing list](https://groups.google.com/group/golang-nuts) instead of the issue tracker. The gophers there will answer or ask you to file an issue if you've tripped over a bug. ## Contributing code Please read the [Contribution Guidelines](https://golang.org/doc/contribute.html) before sending patches. **We do not accept GitHub pull requests** (we use [Gerrit](https://code.google.com/p/gerrit/) instead for code review). Unless otherwise noted, the Go source files are distributed under the BSD-style license found in the LICENSE file. lxd-2.0.0/dist/src/golang.org/x/crypto/bn256/0000755061062106075000000000000012702772344023130 5ustar00stgraberdomain admins00000000000000lxd-2.0.0/dist/src/golang.org/x/crypto/bn256/example_test.go0000644061062106075000000000221312702772344026147 0ustar00stgraberdomain admins00000000000000// Copyright 2012 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 bn256 import ( "crypto/rand" ) func ExamplePair() { // This implements the tripartite Diffie-Hellman algorithm from "A One // Round Protocol for Tripartite Diffie-Hellman", A. Joux. // http://www.springerlink.com/content/cddc57yyva0hburb/fulltext.pdf // Each of three parties, a, b and c, generate a private value. a, _ := rand.Int(rand.Reader, Order) b, _ := rand.Int(rand.Reader, Order) c, _ := rand.Int(rand.Reader, Order) // Then each party calculates gâ‚ and gâ‚‚ times their private value. pa := new(G1).ScalarBaseMult(a) qa := new(G2).ScalarBaseMult(a) pb := new(G1).ScalarBaseMult(b) qb := new(G2).ScalarBaseMult(b) pc := new(G1).ScalarBaseMult(c) qc := new(G2).ScalarBaseMult(c) // Now each party exchanges its public values with the other two and // all parties can calculate the shared key. k1 := Pair(pb, qc) k1.ScalarMult(k1, a) k2 := Pair(pc, qa) k2.ScalarMult(k2, b) k3 := Pair(pa, qb) k3.ScalarMult(k3, c) // k1, k2 and k3 will all be equal. } lxd-2.0.0/dist/src/golang.org/x/crypto/bn256/gfp12.go0000644061062106075000000000707512702772344024407 0ustar00stgraberdomain admins00000000000000// Copyright 2012 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 bn256 // For details of the algorithms used, see "Multiplication and Squaring on // Pairing-Friendly Fields, Devegili et al. // http://eprint.iacr.org/2006/471.pdf. import ( "math/big" ) // gfP12 implements the field of size p¹² as a quadratic extension of gfP6 // where ω²=Ï„. type gfP12 struct { x, y *gfP6 // value is xω + y } func newGFp12(pool *bnPool) *gfP12 { return &gfP12{newGFp6(pool), newGFp6(pool)} } func (e *gfP12) String() string { return "(" + e.x.String() + "," + e.y.String() + ")" } func (e *gfP12) Put(pool *bnPool) { e.x.Put(pool) e.y.Put(pool) } func (e *gfP12) Set(a *gfP12) *gfP12 { e.x.Set(a.x) e.y.Set(a.y) return e } func (e *gfP12) SetZero() *gfP12 { e.x.SetZero() e.y.SetZero() return e } func (e *gfP12) SetOne() *gfP12 { e.x.SetZero() e.y.SetOne() return e } func (e *gfP12) Minimal() { e.x.Minimal() e.y.Minimal() } func (e *gfP12) IsZero() bool { e.Minimal() return e.x.IsZero() && e.y.IsZero() } func (e *gfP12) IsOne() bool { e.Minimal() return e.x.IsZero() && e.y.IsOne() } func (e *gfP12) Conjugate(a *gfP12) *gfP12 { e.x.Negative(a.x) e.y.Set(a.y) return a } func (e *gfP12) Negative(a *gfP12) *gfP12 { e.x.Negative(a.x) e.y.Negative(a.y) return e } // Frobenius computes (xω+y)^p = x^p ω·ξ^((p-1)/6) + y^p func (e *gfP12) Frobenius(a *gfP12, pool *bnPool) *gfP12 { e.x.Frobenius(a.x, pool) e.y.Frobenius(a.y, pool) e.x.MulScalar(e.x, xiToPMinus1Over6, pool) return e } // FrobeniusP2 computes (xω+y)^p² = x^p² ω·ξ^((p²-1)/6) + y^p² func (e *gfP12) FrobeniusP2(a *gfP12, pool *bnPool) *gfP12 { e.x.FrobeniusP2(a.x) e.x.MulGFP(e.x, xiToPSquaredMinus1Over6) e.y.FrobeniusP2(a.y) return e } func (e *gfP12) Add(a, b *gfP12) *gfP12 { e.x.Add(a.x, b.x) e.y.Add(a.y, b.y) return e } func (e *gfP12) Sub(a, b *gfP12) *gfP12 { e.x.Sub(a.x, b.x) e.y.Sub(a.y, b.y) return e } func (e *gfP12) Mul(a, b *gfP12, pool *bnPool) *gfP12 { tx := newGFp6(pool) tx.Mul(a.x, b.y, pool) t := newGFp6(pool) t.Mul(b.x, a.y, pool) tx.Add(tx, t) ty := newGFp6(pool) ty.Mul(a.y, b.y, pool) t.Mul(a.x, b.x, pool) t.MulTau(t, pool) e.y.Add(ty, t) e.x.Set(tx) tx.Put(pool) ty.Put(pool) t.Put(pool) return e } func (e *gfP12) MulScalar(a *gfP12, b *gfP6, pool *bnPool) *gfP12 { e.x.Mul(e.x, b, pool) e.y.Mul(e.y, b, pool) return e } func (c *gfP12) Exp(a *gfP12, power *big.Int, pool *bnPool) *gfP12 { sum := newGFp12(pool) sum.SetOne() t := newGFp12(pool) for i := power.BitLen() - 1; i >= 0; i-- { t.Square(sum, pool) if power.Bit(i) != 0 { sum.Mul(t, a, pool) } else { sum.Set(t) } } c.Set(sum) sum.Put(pool) t.Put(pool) return c } func (e *gfP12) Square(a *gfP12, pool *bnPool) *gfP12 { // Complex squaring algorithm v0 := newGFp6(pool) v0.Mul(a.x, a.y, pool) t := newGFp6(pool) t.MulTau(a.x, pool) t.Add(a.y, t) ty := newGFp6(pool) ty.Add(a.x, a.y) ty.Mul(ty, t, pool) ty.Sub(ty, v0) t.MulTau(v0, pool) ty.Sub(ty, t) e.y.Set(ty) e.x.Double(v0) v0.Put(pool) t.Put(pool) ty.Put(pool) return e } func (e *gfP12) Invert(a *gfP12, pool *bnPool) *gfP12 { // See "Implementing cryptographic pairings", M. Scott, section 3.2. // ftp://136.206.11.249/pub/crypto/pairings.pdf t1 := newGFp6(pool) t2 := newGFp6(pool) t1.Square(a.x, pool) t2.Square(a.y, pool) t1.MulTau(t1, pool) t1.Sub(t2, t1) t2.Invert(t1, pool) e.x.Negative(a.x) e.y.Set(a.y) e.MulScalar(e, t2, pool) t1.Put(pool) t2.Put(pool) return e } lxd-2.0.0/dist/src/golang.org/x/crypto/bn256/optate.go0000644061062106075000000002073312702772344024760 0ustar00stgraberdomain admins00000000000000// Copyright 2012 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 bn256 func lineFunctionAdd(r, p *twistPoint, q *curvePoint, r2 *gfP2, pool *bnPool) (a, b, c *gfP2, rOut *twistPoint) { // See the mixed addition algorithm from "Faster Computation of the // Tate Pairing", http://arxiv.org/pdf/0904.0854v3.pdf B := newGFp2(pool).Mul(p.x, r.t, pool) D := newGFp2(pool).Add(p.y, r.z) D.Square(D, pool) D.Sub(D, r2) D.Sub(D, r.t) D.Mul(D, r.t, pool) H := newGFp2(pool).Sub(B, r.x) I := newGFp2(pool).Square(H, pool) E := newGFp2(pool).Add(I, I) E.Add(E, E) J := newGFp2(pool).Mul(H, E, pool) L1 := newGFp2(pool).Sub(D, r.y) L1.Sub(L1, r.y) V := newGFp2(pool).Mul(r.x, E, pool) rOut = newTwistPoint(pool) rOut.x.Square(L1, pool) rOut.x.Sub(rOut.x, J) rOut.x.Sub(rOut.x, V) rOut.x.Sub(rOut.x, V) rOut.z.Add(r.z, H) rOut.z.Square(rOut.z, pool) rOut.z.Sub(rOut.z, r.t) rOut.z.Sub(rOut.z, I) t := newGFp2(pool).Sub(V, rOut.x) t.Mul(t, L1, pool) t2 := newGFp2(pool).Mul(r.y, J, pool) t2.Add(t2, t2) rOut.y.Sub(t, t2) rOut.t.Square(rOut.z, pool) t.Add(p.y, rOut.z) t.Square(t, pool) t.Sub(t, r2) t.Sub(t, rOut.t) t2.Mul(L1, p.x, pool) t2.Add(t2, t2) a = newGFp2(pool) a.Sub(t2, t) c = newGFp2(pool) c.MulScalar(rOut.z, q.y) c.Add(c, c) b = newGFp2(pool) b.SetZero() b.Sub(b, L1) b.MulScalar(b, q.x) b.Add(b, b) B.Put(pool) D.Put(pool) H.Put(pool) I.Put(pool) E.Put(pool) J.Put(pool) L1.Put(pool) V.Put(pool) t.Put(pool) t2.Put(pool) return } func lineFunctionDouble(r *twistPoint, q *curvePoint, pool *bnPool) (a, b, c *gfP2, rOut *twistPoint) { // See the doubling algorithm for a=0 from "Faster Computation of the // Tate Pairing", http://arxiv.org/pdf/0904.0854v3.pdf A := newGFp2(pool).Square(r.x, pool) B := newGFp2(pool).Square(r.y, pool) C := newGFp2(pool).Square(B, pool) D := newGFp2(pool).Add(r.x, B) D.Square(D, pool) D.Sub(D, A) D.Sub(D, C) D.Add(D, D) E := newGFp2(pool).Add(A, A) E.Add(E, A) G := newGFp2(pool).Square(E, pool) rOut = newTwistPoint(pool) rOut.x.Sub(G, D) rOut.x.Sub(rOut.x, D) rOut.z.Add(r.y, r.z) rOut.z.Square(rOut.z, pool) rOut.z.Sub(rOut.z, B) rOut.z.Sub(rOut.z, r.t) rOut.y.Sub(D, rOut.x) rOut.y.Mul(rOut.y, E, pool) t := newGFp2(pool).Add(C, C) t.Add(t, t) t.Add(t, t) rOut.y.Sub(rOut.y, t) rOut.t.Square(rOut.z, pool) t.Mul(E, r.t, pool) t.Add(t, t) b = newGFp2(pool) b.SetZero() b.Sub(b, t) b.MulScalar(b, q.x) a = newGFp2(pool) a.Add(r.x, E) a.Square(a, pool) a.Sub(a, A) a.Sub(a, G) t.Add(B, B) t.Add(t, t) a.Sub(a, t) c = newGFp2(pool) c.Mul(rOut.z, r.t, pool) c.Add(c, c) c.MulScalar(c, q.y) A.Put(pool) B.Put(pool) C.Put(pool) D.Put(pool) E.Put(pool) G.Put(pool) t.Put(pool) return } func mulLine(ret *gfP12, a, b, c *gfP2, pool *bnPool) { a2 := newGFp6(pool) a2.x.SetZero() a2.y.Set(a) a2.z.Set(b) a2.Mul(a2, ret.x, pool) t3 := newGFp6(pool).MulScalar(ret.y, c, pool) t := newGFp2(pool) t.Add(b, c) t2 := newGFp6(pool) t2.x.SetZero() t2.y.Set(a) t2.z.Set(t) ret.x.Add(ret.x, ret.y) ret.y.Set(t3) ret.x.Mul(ret.x, t2, pool) ret.x.Sub(ret.x, a2) ret.x.Sub(ret.x, ret.y) a2.MulTau(a2, pool) ret.y.Add(ret.y, a2) a2.Put(pool) t3.Put(pool) t2.Put(pool) t.Put(pool) } // sixuPlus2NAF is 6u+2 in non-adjacent form. var sixuPlus2NAF = []int8{0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, -1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, -1, 0, 1, 0, 0, 0, 1, 0, -1, 0, 0, 0, -1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, -1, 0, -1, 0, 0, 0, 0, 1, 0, 0, 0, 1} // miller implements the Miller loop for calculating the Optimal Ate pairing. // See algorithm 1 from http://cryptojedi.org/papers/dclxvi-20100714.pdf func miller(q *twistPoint, p *curvePoint, pool *bnPool) *gfP12 { ret := newGFp12(pool) ret.SetOne() aAffine := newTwistPoint(pool) aAffine.Set(q) aAffine.MakeAffine(pool) bAffine := newCurvePoint(pool) bAffine.Set(p) bAffine.MakeAffine(pool) minusA := newTwistPoint(pool) minusA.Negative(aAffine, pool) r := newTwistPoint(pool) r.Set(aAffine) r2 := newGFp2(pool) r2.Square(aAffine.y, pool) for i := len(sixuPlus2NAF) - 1; i > 0; i-- { a, b, c, newR := lineFunctionDouble(r, bAffine, pool) if i != len(sixuPlus2NAF)-1 { ret.Square(ret, pool) } mulLine(ret, a, b, c, pool) a.Put(pool) b.Put(pool) c.Put(pool) r.Put(pool) r = newR switch sixuPlus2NAF[i-1] { case 1: a, b, c, newR = lineFunctionAdd(r, aAffine, bAffine, r2, pool) case -1: a, b, c, newR = lineFunctionAdd(r, minusA, bAffine, r2, pool) default: continue } mulLine(ret, a, b, c, pool) a.Put(pool) b.Put(pool) c.Put(pool) r.Put(pool) r = newR } // In order to calculate Q1 we have to convert q from the sextic twist // to the full GF(p^12) group, apply the Frobenius there, and convert // back. // // The twist isomorphism is (x', y') -> (xω², yω³). If we consider just // x for a moment, then after applying the Frobenius, we have x̄ω^(2p) // where xÌ„ is the conjugate of x. If we are going to apply the inverse // isomorphism we need a value with a single coefficient of ω² so we // rewrite this as x̄ω^(2p-2)ω². ξⶠ= ω and, due to the construction of // p, 2p-2 is a multiple of six. Therefore we can rewrite as // x̄ξ^((p-1)/3)ω² and applying the inverse isomorphism eliminates the // ω². // // A similar argument can be made for the y value. q1 := newTwistPoint(pool) q1.x.Conjugate(aAffine.x) q1.x.Mul(q1.x, xiToPMinus1Over3, pool) q1.y.Conjugate(aAffine.y) q1.y.Mul(q1.y, xiToPMinus1Over2, pool) q1.z.SetOne() q1.t.SetOne() // For Q2 we are applying the p² Frobenius. The two conjugations cancel // out and we are left only with the factors from the isomorphism. In // the case of x, we end up with a pure number which is why // xiToPSquaredMinus1Over3 is ∈ GF(p). With y we get a factor of -1. We // ignore this to end up with -Q2. minusQ2 := newTwistPoint(pool) minusQ2.x.MulScalar(aAffine.x, xiToPSquaredMinus1Over3) minusQ2.y.Set(aAffine.y) minusQ2.z.SetOne() minusQ2.t.SetOne() r2.Square(q1.y, pool) a, b, c, newR := lineFunctionAdd(r, q1, bAffine, r2, pool) mulLine(ret, a, b, c, pool) a.Put(pool) b.Put(pool) c.Put(pool) r.Put(pool) r = newR r2.Square(minusQ2.y, pool) a, b, c, newR = lineFunctionAdd(r, minusQ2, bAffine, r2, pool) mulLine(ret, a, b, c, pool) a.Put(pool) b.Put(pool) c.Put(pool) r.Put(pool) r = newR aAffine.Put(pool) bAffine.Put(pool) minusA.Put(pool) r.Put(pool) r2.Put(pool) return ret } // finalExponentiation computes the (p¹²-1)/Order-th power of an element of // GF(p¹²) to obtain an element of GT (steps 13-15 of algorithm 1 from // http://cryptojedi.org/papers/dclxvi-20100714.pdf) func finalExponentiation(in *gfP12, pool *bnPool) *gfP12 { t1 := newGFp12(pool) // This is the p^6-Frobenius t1.x.Negative(in.x) t1.y.Set(in.y) inv := newGFp12(pool) inv.Invert(in, pool) t1.Mul(t1, inv, pool) t2 := newGFp12(pool).FrobeniusP2(t1, pool) t1.Mul(t1, t2, pool) fp := newGFp12(pool).Frobenius(t1, pool) fp2 := newGFp12(pool).FrobeniusP2(t1, pool) fp3 := newGFp12(pool).Frobenius(fp2, pool) fu, fu2, fu3 := newGFp12(pool), newGFp12(pool), newGFp12(pool) fu.Exp(t1, u, pool) fu2.Exp(fu, u, pool) fu3.Exp(fu2, u, pool) y3 := newGFp12(pool).Frobenius(fu, pool) fu2p := newGFp12(pool).Frobenius(fu2, pool) fu3p := newGFp12(pool).Frobenius(fu3, pool) y2 := newGFp12(pool).FrobeniusP2(fu2, pool) y0 := newGFp12(pool) y0.Mul(fp, fp2, pool) y0.Mul(y0, fp3, pool) y1, y4, y5 := newGFp12(pool), newGFp12(pool), newGFp12(pool) y1.Conjugate(t1) y5.Conjugate(fu2) y3.Conjugate(y3) y4.Mul(fu, fu2p, pool) y4.Conjugate(y4) y6 := newGFp12(pool) y6.Mul(fu3, fu3p, pool) y6.Conjugate(y6) t0 := newGFp12(pool) t0.Square(y6, pool) t0.Mul(t0, y4, pool) t0.Mul(t0, y5, pool) t1.Mul(y3, y5, pool) t1.Mul(t1, t0, pool) t0.Mul(t0, y2, pool) t1.Square(t1, pool) t1.Mul(t1, t0, pool) t1.Square(t1, pool) t0.Mul(t1, y1, pool) t1.Mul(t1, y0, pool) t0.Square(t0, pool) t0.Mul(t0, t1, pool) inv.Put(pool) t1.Put(pool) t2.Put(pool) fp.Put(pool) fp2.Put(pool) fp3.Put(pool) fu.Put(pool) fu2.Put(pool) fu3.Put(pool) fu2p.Put(pool) fu3p.Put(pool) y0.Put(pool) y1.Put(pool) y2.Put(pool) y3.Put(pool) y4.Put(pool) y5.Put(pool) y6.Put(pool) return t0 } func optimalAte(a *twistPoint, b *curvePoint, pool *bnPool) *gfP12 { e := miller(a, b, pool) ret := finalExponentiation(e, pool) e.Put(pool) if a.IsInfinity() || b.IsInfinity() { ret.SetOne() } return ret } lxd-2.0.0/dist/src/golang.org/x/crypto/bn256/bn256_test.go0000644061062106075000000001505012702772344025353 0ustar00stgraberdomain admins00000000000000// Copyright 2012 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 bn256 import ( "bytes" "crypto/rand" "math/big" "testing" ) func TestGFp2Invert(t *testing.T) { pool := new(bnPool) a := newGFp2(pool) a.x.SetString("23423492374", 10) a.y.SetString("12934872398472394827398470", 10) inv := newGFp2(pool) inv.Invert(a, pool) b := newGFp2(pool).Mul(inv, a, pool) if b.x.Int64() != 0 || b.y.Int64() != 1 { t.Fatalf("bad result for a^-1*a: %s %s", b.x, b.y) } a.Put(pool) b.Put(pool) inv.Put(pool) if c := pool.Count(); c > 0 { t.Errorf("Pool count non-zero: %d\n", c) } } func isZero(n *big.Int) bool { return new(big.Int).Mod(n, p).Int64() == 0 } func isOne(n *big.Int) bool { return new(big.Int).Mod(n, p).Int64() == 1 } func TestGFp6Invert(t *testing.T) { pool := new(bnPool) a := newGFp6(pool) a.x.x.SetString("239487238491", 10) a.x.y.SetString("2356249827341", 10) a.y.x.SetString("082659782", 10) a.y.y.SetString("182703523765", 10) a.z.x.SetString("978236549263", 10) a.z.y.SetString("64893242", 10) inv := newGFp6(pool) inv.Invert(a, pool) b := newGFp6(pool).Mul(inv, a, pool) if !isZero(b.x.x) || !isZero(b.x.y) || !isZero(b.y.x) || !isZero(b.y.y) || !isZero(b.z.x) || !isOne(b.z.y) { t.Fatalf("bad result for a^-1*a: %s", b) } a.Put(pool) b.Put(pool) inv.Put(pool) if c := pool.Count(); c > 0 { t.Errorf("Pool count non-zero: %d\n", c) } } func TestGFp12Invert(t *testing.T) { pool := new(bnPool) a := newGFp12(pool) a.x.x.x.SetString("239846234862342323958623", 10) a.x.x.y.SetString("2359862352529835623", 10) a.x.y.x.SetString("928836523", 10) a.x.y.y.SetString("9856234", 10) a.x.z.x.SetString("235635286", 10) a.x.z.y.SetString("5628392833", 10) a.y.x.x.SetString("252936598265329856238956532167968", 10) a.y.x.y.SetString("23596239865236954178968", 10) a.y.y.x.SetString("95421692834", 10) a.y.y.y.SetString("236548", 10) a.y.z.x.SetString("924523", 10) a.y.z.y.SetString("12954623", 10) inv := newGFp12(pool) inv.Invert(a, pool) b := newGFp12(pool).Mul(inv, a, pool) if !isZero(b.x.x.x) || !isZero(b.x.x.y) || !isZero(b.x.y.x) || !isZero(b.x.y.y) || !isZero(b.x.z.x) || !isZero(b.x.z.y) || !isZero(b.y.x.x) || !isZero(b.y.x.y) || !isZero(b.y.y.x) || !isZero(b.y.y.y) || !isZero(b.y.z.x) || !isOne(b.y.z.y) { t.Fatalf("bad result for a^-1*a: %s", b) } a.Put(pool) b.Put(pool) inv.Put(pool) if c := pool.Count(); c > 0 { t.Errorf("Pool count non-zero: %d\n", c) } } func TestCurveImpl(t *testing.T) { pool := new(bnPool) g := &curvePoint{ pool.Get().SetInt64(1), pool.Get().SetInt64(-2), pool.Get().SetInt64(1), pool.Get().SetInt64(0), } x := pool.Get().SetInt64(32498273234) X := newCurvePoint(pool).Mul(g, x, pool) y := pool.Get().SetInt64(98732423523) Y := newCurvePoint(pool).Mul(g, y, pool) s1 := newCurvePoint(pool).Mul(X, y, pool).MakeAffine(pool) s2 := newCurvePoint(pool).Mul(Y, x, pool).MakeAffine(pool) if s1.x.Cmp(s2.x) != 0 || s2.x.Cmp(s1.x) != 0 { t.Errorf("DH points don't match: (%s, %s) (%s, %s)", s1.x, s1.y, s2.x, s2.y) } pool.Put(x) X.Put(pool) pool.Put(y) Y.Put(pool) s1.Put(pool) s2.Put(pool) g.Put(pool) if c := pool.Count(); c > 0 { t.Errorf("Pool count non-zero: %d\n", c) } } func TestOrderG1(t *testing.T) { g := new(G1).ScalarBaseMult(Order) if !g.p.IsInfinity() { t.Error("G1 has incorrect order") } one := new(G1).ScalarBaseMult(new(big.Int).SetInt64(1)) g.Add(g, one) g.p.MakeAffine(nil) if g.p.x.Cmp(one.p.x) != 0 || g.p.y.Cmp(one.p.y) != 0 { t.Errorf("1+0 != 1 in G1") } } func TestOrderG2(t *testing.T) { g := new(G2).ScalarBaseMult(Order) if !g.p.IsInfinity() { t.Error("G2 has incorrect order") } one := new(G2).ScalarBaseMult(new(big.Int).SetInt64(1)) g.Add(g, one) g.p.MakeAffine(nil) if g.p.x.x.Cmp(one.p.x.x) != 0 || g.p.x.y.Cmp(one.p.x.y) != 0 || g.p.y.x.Cmp(one.p.y.x) != 0 || g.p.y.y.Cmp(one.p.y.y) != 0 { t.Errorf("1+0 != 1 in G2") } } func TestOrderGT(t *testing.T) { gt := Pair(&G1{curveGen}, &G2{twistGen}) g := new(GT).ScalarMult(gt, Order) if !g.p.IsOne() { t.Error("GT has incorrect order") } } func TestBilinearity(t *testing.T) { for i := 0; i < 2; i++ { a, p1, _ := RandomG1(rand.Reader) b, p2, _ := RandomG2(rand.Reader) e1 := Pair(p1, p2) e2 := Pair(&G1{curveGen}, &G2{twistGen}) e2.ScalarMult(e2, a) e2.ScalarMult(e2, b) minusE2 := new(GT).Neg(e2) e1.Add(e1, minusE2) if !e1.p.IsOne() { t.Fatalf("bad pairing result: %s", e1) } } } func TestG1Marshal(t *testing.T) { g := new(G1).ScalarBaseMult(new(big.Int).SetInt64(1)) form := g.Marshal() _, ok := new(G1).Unmarshal(form) if !ok { t.Fatalf("failed to unmarshal") } g.ScalarBaseMult(Order) form = g.Marshal() g2, ok := new(G1).Unmarshal(form) if !ok { t.Fatalf("failed to unmarshal ∞") } if !g2.p.IsInfinity() { t.Fatalf("∞ unmarshaled incorrectly") } } func TestG2Marshal(t *testing.T) { g := new(G2).ScalarBaseMult(new(big.Int).SetInt64(1)) form := g.Marshal() _, ok := new(G2).Unmarshal(form) if !ok { t.Fatalf("failed to unmarshal") } g.ScalarBaseMult(Order) form = g.Marshal() g2, ok := new(G2).Unmarshal(form) if !ok { t.Fatalf("failed to unmarshal ∞") } if !g2.p.IsInfinity() { t.Fatalf("∞ unmarshaled incorrectly") } } func TestG1Identity(t *testing.T) { g := new(G1).ScalarBaseMult(new(big.Int).SetInt64(0)) if !g.p.IsInfinity() { t.Error("failure") } } func TestG2Identity(t *testing.T) { g := new(G2).ScalarBaseMult(new(big.Int).SetInt64(0)) if !g.p.IsInfinity() { t.Error("failure") } } func TestTripartiteDiffieHellman(t *testing.T) { a, _ := rand.Int(rand.Reader, Order) b, _ := rand.Int(rand.Reader, Order) c, _ := rand.Int(rand.Reader, Order) pa, _ := new(G1).Unmarshal(new(G1).ScalarBaseMult(a).Marshal()) qa, _ := new(G2).Unmarshal(new(G2).ScalarBaseMult(a).Marshal()) pb, _ := new(G1).Unmarshal(new(G1).ScalarBaseMult(b).Marshal()) qb, _ := new(G2).Unmarshal(new(G2).ScalarBaseMult(b).Marshal()) pc, _ := new(G1).Unmarshal(new(G1).ScalarBaseMult(c).Marshal()) qc, _ := new(G2).Unmarshal(new(G2).ScalarBaseMult(c).Marshal()) k1 := Pair(pb, qc) k1.ScalarMult(k1, a) k1Bytes := k1.Marshal() k2 := Pair(pc, qa) k2.ScalarMult(k2, b) k2Bytes := k2.Marshal() k3 := Pair(pa, qb) k3.ScalarMult(k3, c) k3Bytes := k3.Marshal() if !bytes.Equal(k1Bytes, k2Bytes) || !bytes.Equal(k2Bytes, k3Bytes) { t.Errorf("keys didn't agree") } } func BenchmarkPairing(b *testing.B) { for i := 0; i < b.N; i++ { Pair(&G1{curveGen}, &G2{twistGen}) } } lxd-2.0.0/dist/src/golang.org/x/crypto/bn256/gfp2.go0000644061062106075000000000732012702772344024317 0ustar00stgraberdomain admins00000000000000// Copyright 2012 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 bn256 // For details of the algorithms used, see "Multiplication and Squaring on // Pairing-Friendly Fields, Devegili et al. // http://eprint.iacr.org/2006/471.pdf. import ( "math/big" ) // gfP2 implements a field of size p² as a quadratic extension of the base // field where i²=-1. type gfP2 struct { x, y *big.Int // value is xi+y. } func newGFp2(pool *bnPool) *gfP2 { return &gfP2{pool.Get(), pool.Get()} } func (e *gfP2) String() string { x := new(big.Int).Mod(e.x, p) y := new(big.Int).Mod(e.y, p) return "(" + x.String() + "," + y.String() + ")" } func (e *gfP2) Put(pool *bnPool) { pool.Put(e.x) pool.Put(e.y) } func (e *gfP2) Set(a *gfP2) *gfP2 { e.x.Set(a.x) e.y.Set(a.y) return e } func (e *gfP2) SetZero() *gfP2 { e.x.SetInt64(0) e.y.SetInt64(0) return e } func (e *gfP2) SetOne() *gfP2 { e.x.SetInt64(0) e.y.SetInt64(1) return e } func (e *gfP2) Minimal() { if e.x.Sign() < 0 || e.x.Cmp(p) >= 0 { e.x.Mod(e.x, p) } if e.y.Sign() < 0 || e.y.Cmp(p) >= 0 { e.y.Mod(e.y, p) } } func (e *gfP2) IsZero() bool { return e.x.Sign() == 0 && e.y.Sign() == 0 } func (e *gfP2) IsOne() bool { if e.x.Sign() != 0 { return false } words := e.y.Bits() return len(words) == 1 && words[0] == 1 } func (e *gfP2) Conjugate(a *gfP2) *gfP2 { e.y.Set(a.y) e.x.Neg(a.x) return e } func (e *gfP2) Negative(a *gfP2) *gfP2 { e.x.Neg(a.x) e.y.Neg(a.y) return e } func (e *gfP2) Add(a, b *gfP2) *gfP2 { e.x.Add(a.x, b.x) e.y.Add(a.y, b.y) return e } func (e *gfP2) Sub(a, b *gfP2) *gfP2 { e.x.Sub(a.x, b.x) e.y.Sub(a.y, b.y) return e } func (e *gfP2) Double(a *gfP2) *gfP2 { e.x.Lsh(a.x, 1) e.y.Lsh(a.y, 1) return e } func (c *gfP2) Exp(a *gfP2, power *big.Int, pool *bnPool) *gfP2 { sum := newGFp2(pool) sum.SetOne() t := newGFp2(pool) for i := power.BitLen() - 1; i >= 0; i-- { t.Square(sum, pool) if power.Bit(i) != 0 { sum.Mul(t, a, pool) } else { sum.Set(t) } } c.Set(sum) sum.Put(pool) t.Put(pool) return c } // See "Multiplication and Squaring in Pairing-Friendly Fields", // http://eprint.iacr.org/2006/471.pdf func (e *gfP2) Mul(a, b *gfP2, pool *bnPool) *gfP2 { tx := pool.Get().Mul(a.x, b.y) t := pool.Get().Mul(b.x, a.y) tx.Add(tx, t) tx.Mod(tx, p) ty := pool.Get().Mul(a.y, b.y) t.Mul(a.x, b.x) ty.Sub(ty, t) e.y.Mod(ty, p) e.x.Set(tx) pool.Put(tx) pool.Put(ty) pool.Put(t) return e } func (e *gfP2) MulScalar(a *gfP2, b *big.Int) *gfP2 { e.x.Mul(a.x, b) e.y.Mul(a.y, b) return e } // MulXi sets e=ξa where ξ=i+3 and then returns e. func (e *gfP2) MulXi(a *gfP2, pool *bnPool) *gfP2 { // (xi+y)(i+3) = (3x+y)i+(3y-x) tx := pool.Get().Lsh(a.x, 1) tx.Add(tx, a.x) tx.Add(tx, a.y) ty := pool.Get().Lsh(a.y, 1) ty.Add(ty, a.y) ty.Sub(ty, a.x) e.x.Set(tx) e.y.Set(ty) pool.Put(tx) pool.Put(ty) return e } func (e *gfP2) Square(a *gfP2, pool *bnPool) *gfP2 { // Complex squaring algorithm: // (xi+b)² = (x+y)(y-x) + 2*i*x*y t1 := pool.Get().Sub(a.y, a.x) t2 := pool.Get().Add(a.x, a.y) ty := pool.Get().Mul(t1, t2) ty.Mod(ty, p) t1.Mul(a.x, a.y) t1.Lsh(t1, 1) e.x.Mod(t1, p) e.y.Set(ty) pool.Put(t1) pool.Put(t2) pool.Put(ty) return e } func (e *gfP2) Invert(a *gfP2, pool *bnPool) *gfP2 { // See "Implementing cryptographic pairings", M. Scott, section 3.2. // ftp://136.206.11.249/pub/crypto/pairings.pdf t := pool.Get() t.Mul(a.y, a.y) t2 := pool.Get() t2.Mul(a.x, a.x) t.Add(t, t2) inv := pool.Get() inv.ModInverse(t, p) e.x.Neg(a.x) e.x.Mul(e.x, inv) e.x.Mod(e.x, p) e.y.Mul(a.y, inv) e.y.Mod(e.y, p) pool.Put(t) pool.Put(t2) pool.Put(inv) return e } lxd-2.0.0/dist/src/golang.org/x/crypto/bn256/twist.go0000644061062106075000000001227212702772344024635 0ustar00stgraberdomain admins00000000000000// Copyright 2012 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 bn256 import ( "math/big" ) // twistPoint implements the elliptic curve y²=x³+3/ξ over GF(p²). Points are // kept in Jacobian form and t=z² when valid. The group Gâ‚‚ is the set of // n-torsion points of this curve over GF(p²) (where n = Order) type twistPoint struct { x, y, z, t *gfP2 } var twistB = &gfP2{ bigFromBase10("6500054969564660373279643874235990574282535810762300357187714502686418407178"), bigFromBase10("45500384786952622612957507119651934019977750675336102500314001518804928850249"), } // twistGen is the generator of group Gâ‚‚. var twistGen = &twistPoint{ &gfP2{ bigFromBase10("21167961636542580255011770066570541300993051739349375019639421053990175267184"), bigFromBase10("64746500191241794695844075326670126197795977525365406531717464316923369116492"), }, &gfP2{ bigFromBase10("20666913350058776956210519119118544732556678129809273996262322366050359951122"), bigFromBase10("17778617556404439934652658462602675281523610326338642107814333856843981424549"), }, &gfP2{ bigFromBase10("0"), bigFromBase10("1"), }, &gfP2{ bigFromBase10("0"), bigFromBase10("1"), }, } func newTwistPoint(pool *bnPool) *twistPoint { return &twistPoint{ newGFp2(pool), newGFp2(pool), newGFp2(pool), newGFp2(pool), } } func (c *twistPoint) String() string { return "(" + c.x.String() + ", " + c.y.String() + ", " + c.z.String() + ")" } func (c *twistPoint) Put(pool *bnPool) { c.x.Put(pool) c.y.Put(pool) c.z.Put(pool) c.t.Put(pool) } func (c *twistPoint) Set(a *twistPoint) { c.x.Set(a.x) c.y.Set(a.y) c.z.Set(a.z) c.t.Set(a.t) } // IsOnCurve returns true iff c is on the curve where c must be in affine form. func (c *twistPoint) IsOnCurve() bool { pool := new(bnPool) yy := newGFp2(pool).Square(c.y, pool) xxx := newGFp2(pool).Square(c.x, pool) xxx.Mul(xxx, c.x, pool) yy.Sub(yy, xxx) yy.Sub(yy, twistB) yy.Minimal() return yy.x.Sign() == 0 && yy.y.Sign() == 0 } func (c *twistPoint) SetInfinity() { c.z.SetZero() } func (c *twistPoint) IsInfinity() bool { return c.z.IsZero() } func (c *twistPoint) Add(a, b *twistPoint, pool *bnPool) { // For additional comments, see the same function in curve.go. if a.IsInfinity() { c.Set(b) return } if b.IsInfinity() { c.Set(a) return } // See http://hyperelliptic.org/EFD/g1p/auto-code/shortw/jacobian-0/addition/add-2007-bl.op3 z1z1 := newGFp2(pool).Square(a.z, pool) z2z2 := newGFp2(pool).Square(b.z, pool) u1 := newGFp2(pool).Mul(a.x, z2z2, pool) u2 := newGFp2(pool).Mul(b.x, z1z1, pool) t := newGFp2(pool).Mul(b.z, z2z2, pool) s1 := newGFp2(pool).Mul(a.y, t, pool) t.Mul(a.z, z1z1, pool) s2 := newGFp2(pool).Mul(b.y, t, pool) h := newGFp2(pool).Sub(u2, u1) xEqual := h.IsZero() t.Add(h, h) i := newGFp2(pool).Square(t, pool) j := newGFp2(pool).Mul(h, i, pool) t.Sub(s2, s1) yEqual := t.IsZero() if xEqual && yEqual { c.Double(a, pool) return } r := newGFp2(pool).Add(t, t) v := newGFp2(pool).Mul(u1, i, pool) t4 := newGFp2(pool).Square(r, pool) t.Add(v, v) t6 := newGFp2(pool).Sub(t4, j) c.x.Sub(t6, t) t.Sub(v, c.x) // t7 t4.Mul(s1, j, pool) // t8 t6.Add(t4, t4) // t9 t4.Mul(r, t, pool) // t10 c.y.Sub(t4, t6) t.Add(a.z, b.z) // t11 t4.Square(t, pool) // t12 t.Sub(t4, z1z1) // t13 t4.Sub(t, z2z2) // t14 c.z.Mul(t4, h, pool) z1z1.Put(pool) z2z2.Put(pool) u1.Put(pool) u2.Put(pool) t.Put(pool) s1.Put(pool) s2.Put(pool) h.Put(pool) i.Put(pool) j.Put(pool) r.Put(pool) v.Put(pool) t4.Put(pool) t6.Put(pool) } func (c *twistPoint) Double(a *twistPoint, pool *bnPool) { // See http://hyperelliptic.org/EFD/g1p/auto-code/shortw/jacobian-0/doubling/dbl-2009-l.op3 A := newGFp2(pool).Square(a.x, pool) B := newGFp2(pool).Square(a.y, pool) C := newGFp2(pool).Square(B, pool) t := newGFp2(pool).Add(a.x, B) t2 := newGFp2(pool).Square(t, pool) t.Sub(t2, A) t2.Sub(t, C) d := newGFp2(pool).Add(t2, t2) t.Add(A, A) e := newGFp2(pool).Add(t, A) f := newGFp2(pool).Square(e, pool) t.Add(d, d) c.x.Sub(f, t) t.Add(C, C) t2.Add(t, t) t.Add(t2, t2) c.y.Sub(d, c.x) t2.Mul(e, c.y, pool) c.y.Sub(t2, t) t.Mul(a.y, a.z, pool) c.z.Add(t, t) A.Put(pool) B.Put(pool) C.Put(pool) t.Put(pool) t2.Put(pool) d.Put(pool) e.Put(pool) f.Put(pool) } func (c *twistPoint) Mul(a *twistPoint, scalar *big.Int, pool *bnPool) *twistPoint { sum := newTwistPoint(pool) sum.SetInfinity() t := newTwistPoint(pool) for i := scalar.BitLen(); i >= 0; i-- { t.Double(sum, pool) if scalar.Bit(i) != 0 { sum.Add(t, a, pool) } else { sum.Set(t) } } c.Set(sum) sum.Put(pool) t.Put(pool) return c } func (c *twistPoint) MakeAffine(pool *bnPool) *twistPoint { if c.z.IsOne() { return c } zInv := newGFp2(pool).Invert(c.z, pool) t := newGFp2(pool).Mul(c.y, zInv, pool) zInv2 := newGFp2(pool).Square(zInv, pool) c.y.Mul(t, zInv2, pool) t.Mul(c.x, zInv2, pool) c.x.Set(t) c.z.SetOne() c.t.SetOne() zInv.Put(pool) t.Put(pool) zInv2.Put(pool) return c } func (c *twistPoint) Negative(a *twistPoint, pool *bnPool) { c.x.Set(a.x) c.y.SetZero() c.y.Sub(c.y, a.y) c.z.Set(a.z) c.t.SetZero() } lxd-2.0.0/dist/src/golang.org/x/crypto/bn256/bn256.go0000644061062106075000000002262512702772344024322 0ustar00stgraberdomain admins00000000000000// Copyright 2012 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 bn256 implements a particular bilinear group at the 128-bit security level. // // Bilinear groups are the basis of many of the new cryptographic protocols // that have been proposed over the past decade. They consist of a triplet of // groups (Gâ‚, Gâ‚‚ and GT) such that there exists a function e(gâ‚Ë£,g₂ʸ)=gTˣʸ // (where gâ‚“ is a generator of the respective group). That function is called // a pairing function. // // This package specifically implements the Optimal Ate pairing over a 256-bit // Barreto-Naehrig curve as described in // http://cryptojedi.org/papers/dclxvi-20100714.pdf. Its output is compatible // with the implementation described in that paper. package bn256 // import "golang.org/x/crypto/bn256" import ( "crypto/rand" "io" "math/big" ) // BUG(agl): this implementation is not constant time. // TODO(agl): keep GF(p²) elements in Mongomery form. // G1 is an abstract cyclic group. The zero value is suitable for use as the // output of an operation, but cannot be used as an input. type G1 struct { p *curvePoint } // RandomG1 returns x and gâ‚Ë£ where x is a random, non-zero number read from r. func RandomG1(r io.Reader) (*big.Int, *G1, error) { var k *big.Int var err error for { k, err = rand.Int(r, Order) if err != nil { return nil, nil, err } if k.Sign() > 0 { break } } return k, new(G1).ScalarBaseMult(k), nil } func (g *G1) String() string { return "bn256.G1" + g.p.String() } // ScalarBaseMult sets e to g*k where g is the generator of the group and // then returns e. func (e *G1) ScalarBaseMult(k *big.Int) *G1 { if e.p == nil { e.p = newCurvePoint(nil) } e.p.Mul(curveGen, k, new(bnPool)) return e } // ScalarMult sets e to a*k and then returns e. func (e *G1) ScalarMult(a *G1, k *big.Int) *G1 { if e.p == nil { e.p = newCurvePoint(nil) } e.p.Mul(a.p, k, new(bnPool)) return e } // Add sets e to a+b and then returns e. // BUG(agl): this function is not complete: a==b fails. func (e *G1) Add(a, b *G1) *G1 { if e.p == nil { e.p = newCurvePoint(nil) } e.p.Add(a.p, b.p, new(bnPool)) return e } // Neg sets e to -a and then returns e. func (e *G1) Neg(a *G1) *G1 { if e.p == nil { e.p = newCurvePoint(nil) } e.p.Negative(a.p) return e } // Marshal converts n to a byte slice. func (n *G1) Marshal() []byte { n.p.MakeAffine(nil) xBytes := new(big.Int).Mod(n.p.x, p).Bytes() yBytes := new(big.Int).Mod(n.p.y, p).Bytes() // Each value is a 256-bit number. const numBytes = 256 / 8 ret := make([]byte, numBytes*2) copy(ret[1*numBytes-len(xBytes):], xBytes) copy(ret[2*numBytes-len(yBytes):], yBytes) return ret } // Unmarshal sets e to the result of converting the output of Marshal back into // a group element and then returns e. func (e *G1) Unmarshal(m []byte) (*G1, bool) { // Each value is a 256-bit number. const numBytes = 256 / 8 if len(m) != 2*numBytes { return nil, false } if e.p == nil { e.p = newCurvePoint(nil) } e.p.x.SetBytes(m[0*numBytes : 1*numBytes]) e.p.y.SetBytes(m[1*numBytes : 2*numBytes]) if e.p.x.Sign() == 0 && e.p.y.Sign() == 0 { // This is the point at infinity. e.p.y.SetInt64(1) e.p.z.SetInt64(0) e.p.t.SetInt64(0) } else { e.p.z.SetInt64(1) e.p.t.SetInt64(1) if !e.p.IsOnCurve() { return nil, false } } return e, true } // G2 is an abstract cyclic group. The zero value is suitable for use as the // output of an operation, but cannot be used as an input. type G2 struct { p *twistPoint } // RandomG1 returns x and gâ‚‚Ë£ where x is a random, non-zero number read from r. func RandomG2(r io.Reader) (*big.Int, *G2, error) { var k *big.Int var err error for { k, err = rand.Int(r, Order) if err != nil { return nil, nil, err } if k.Sign() > 0 { break } } return k, new(G2).ScalarBaseMult(k), nil } func (g *G2) String() string { return "bn256.G2" + g.p.String() } // ScalarBaseMult sets e to g*k where g is the generator of the group and // then returns out. func (e *G2) ScalarBaseMult(k *big.Int) *G2 { if e.p == nil { e.p = newTwistPoint(nil) } e.p.Mul(twistGen, k, new(bnPool)) return e } // ScalarMult sets e to a*k and then returns e. func (e *G2) ScalarMult(a *G2, k *big.Int) *G2 { if e.p == nil { e.p = newTwistPoint(nil) } e.p.Mul(a.p, k, new(bnPool)) return e } // Add sets e to a+b and then returns e. // BUG(agl): this function is not complete: a==b fails. func (e *G2) Add(a, b *G2) *G2 { if e.p == nil { e.p = newTwistPoint(nil) } e.p.Add(a.p, b.p, new(bnPool)) return e } // Marshal converts n into a byte slice. func (n *G2) Marshal() []byte { n.p.MakeAffine(nil) xxBytes := new(big.Int).Mod(n.p.x.x, p).Bytes() xyBytes := new(big.Int).Mod(n.p.x.y, p).Bytes() yxBytes := new(big.Int).Mod(n.p.y.x, p).Bytes() yyBytes := new(big.Int).Mod(n.p.y.y, p).Bytes() // Each value is a 256-bit number. const numBytes = 256 / 8 ret := make([]byte, numBytes*4) copy(ret[1*numBytes-len(xxBytes):], xxBytes) copy(ret[2*numBytes-len(xyBytes):], xyBytes) copy(ret[3*numBytes-len(yxBytes):], yxBytes) copy(ret[4*numBytes-len(yyBytes):], yyBytes) return ret } // Unmarshal sets e to the result of converting the output of Marshal back into // a group element and then returns e. func (e *G2) Unmarshal(m []byte) (*G2, bool) { // Each value is a 256-bit number. const numBytes = 256 / 8 if len(m) != 4*numBytes { return nil, false } if e.p == nil { e.p = newTwistPoint(nil) } e.p.x.x.SetBytes(m[0*numBytes : 1*numBytes]) e.p.x.y.SetBytes(m[1*numBytes : 2*numBytes]) e.p.y.x.SetBytes(m[2*numBytes : 3*numBytes]) e.p.y.y.SetBytes(m[3*numBytes : 4*numBytes]) if e.p.x.x.Sign() == 0 && e.p.x.y.Sign() == 0 && e.p.y.x.Sign() == 0 && e.p.y.y.Sign() == 0 { // This is the point at infinity. e.p.y.SetOne() e.p.z.SetZero() e.p.t.SetZero() } else { e.p.z.SetOne() e.p.t.SetOne() if !e.p.IsOnCurve() { return nil, false } } return e, true } // GT is an abstract cyclic group. The zero value is suitable for use as the // output of an operation, but cannot be used as an input. type GT struct { p *gfP12 } func (g *GT) String() string { return "bn256.GT" + g.p.String() } // ScalarMult sets e to a*k and then returns e. func (e *GT) ScalarMult(a *GT, k *big.Int) *GT { if e.p == nil { e.p = newGFp12(nil) } e.p.Exp(a.p, k, new(bnPool)) return e } // Add sets e to a+b and then returns e. func (e *GT) Add(a, b *GT) *GT { if e.p == nil { e.p = newGFp12(nil) } e.p.Mul(a.p, b.p, new(bnPool)) return e } // Neg sets e to -a and then returns e. func (e *GT) Neg(a *GT) *GT { if e.p == nil { e.p = newGFp12(nil) } e.p.Invert(a.p, new(bnPool)) return e } // Marshal converts n into a byte slice. func (n *GT) Marshal() []byte { n.p.Minimal() xxxBytes := n.p.x.x.x.Bytes() xxyBytes := n.p.x.x.y.Bytes() xyxBytes := n.p.x.y.x.Bytes() xyyBytes := n.p.x.y.y.Bytes() xzxBytes := n.p.x.z.x.Bytes() xzyBytes := n.p.x.z.y.Bytes() yxxBytes := n.p.y.x.x.Bytes() yxyBytes := n.p.y.x.y.Bytes() yyxBytes := n.p.y.y.x.Bytes() yyyBytes := n.p.y.y.y.Bytes() yzxBytes := n.p.y.z.x.Bytes() yzyBytes := n.p.y.z.y.Bytes() // Each value is a 256-bit number. const numBytes = 256 / 8 ret := make([]byte, numBytes*12) copy(ret[1*numBytes-len(xxxBytes):], xxxBytes) copy(ret[2*numBytes-len(xxyBytes):], xxyBytes) copy(ret[3*numBytes-len(xyxBytes):], xyxBytes) copy(ret[4*numBytes-len(xyyBytes):], xyyBytes) copy(ret[5*numBytes-len(xzxBytes):], xzxBytes) copy(ret[6*numBytes-len(xzyBytes):], xzyBytes) copy(ret[7*numBytes-len(yxxBytes):], yxxBytes) copy(ret[8*numBytes-len(yxyBytes):], yxyBytes) copy(ret[9*numBytes-len(yyxBytes):], yyxBytes) copy(ret[10*numBytes-len(yyyBytes):], yyyBytes) copy(ret[11*numBytes-len(yzxBytes):], yzxBytes) copy(ret[12*numBytes-len(yzyBytes):], yzyBytes) return ret } // Unmarshal sets e to the result of converting the output of Marshal back into // a group element and then returns e. func (e *GT) Unmarshal(m []byte) (*GT, bool) { // Each value is a 256-bit number. const numBytes = 256 / 8 if len(m) != 12*numBytes { return nil, false } if e.p == nil { e.p = newGFp12(nil) } e.p.x.x.x.SetBytes(m[0*numBytes : 1*numBytes]) e.p.x.x.y.SetBytes(m[1*numBytes : 2*numBytes]) e.p.x.y.x.SetBytes(m[2*numBytes : 3*numBytes]) e.p.x.y.y.SetBytes(m[3*numBytes : 4*numBytes]) e.p.x.z.x.SetBytes(m[4*numBytes : 5*numBytes]) e.p.x.z.y.SetBytes(m[5*numBytes : 6*numBytes]) e.p.y.x.x.SetBytes(m[6*numBytes : 7*numBytes]) e.p.y.x.y.SetBytes(m[7*numBytes : 8*numBytes]) e.p.y.y.x.SetBytes(m[8*numBytes : 9*numBytes]) e.p.y.y.y.SetBytes(m[9*numBytes : 10*numBytes]) e.p.y.z.x.SetBytes(m[10*numBytes : 11*numBytes]) e.p.y.z.y.SetBytes(m[11*numBytes : 12*numBytes]) return e, true } // Pair calculates an Optimal Ate pairing. func Pair(g1 *G1, g2 *G2) *GT { return >{optimalAte(g2.p, g1.p, new(bnPool))} } // bnPool implements a tiny cache of *big.Int objects that's used to reduce the // number of allocations made during processing. type bnPool struct { bns []*big.Int count int } func (pool *bnPool) Get() *big.Int { if pool == nil { return new(big.Int) } pool.count++ l := len(pool.bns) if l == 0 { return new(big.Int) } bn := pool.bns[l-1] pool.bns = pool.bns[:l-1] return bn } func (pool *bnPool) Put(bn *big.Int) { if pool == nil { return } pool.bns = append(pool.bns, bn) pool.count-- } func (pool *bnPool) Count() int { return pool.count } lxd-2.0.0/dist/src/golang.org/x/crypto/bn256/constants.go0000644061062106075000000000465012702772344025500 0ustar00stgraberdomain admins00000000000000// Copyright 2012 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 bn256 import ( "math/big" ) func bigFromBase10(s string) *big.Int { n, _ := new(big.Int).SetString(s, 10) return n } // u is the BN parameter that determines the prime: 1868033³. var u = bigFromBase10("6518589491078791937") // p is a prime over which we form a basic field: 36uâ´+36u³+24u³+6u+1. var p = bigFromBase10("65000549695646603732796438742359905742825358107623003571877145026864184071783") // Order is the number of elements in both Gâ‚ and Gâ‚‚: 36uâ´+36u³+18u³+6u+1. var Order = bigFromBase10("65000549695646603732796438742359905742570406053903786389881062969044166799969") // xiToPMinus1Over6 is ξ^((p-1)/6) where ξ = i+3. var xiToPMinus1Over6 = &gfP2{bigFromBase10("8669379979083712429711189836753509758585994370025260553045152614783263110636"), bigFromBase10("19998038925833620163537568958541907098007303196759855091367510456613536016040")} // xiToPMinus1Over3 is ξ^((p-1)/3) where ξ = i+3. var xiToPMinus1Over3 = &gfP2{bigFromBase10("26098034838977895781559542626833399156321265654106457577426020397262786167059"), bigFromBase10("15931493369629630809226283458085260090334794394361662678240713231519278691715")} // xiToPMinus1Over2 is ξ^((p-1)/2) where ξ = i+3. var xiToPMinus1Over2 = &gfP2{bigFromBase10("50997318142241922852281555961173165965672272825141804376761836765206060036244"), bigFromBase10("38665955945962842195025998234511023902832543644254935982879660597356748036009")} // xiToPSquaredMinus1Over3 is ξ^((p²-1)/3) where ξ = i+3. var xiToPSquaredMinus1Over3 = bigFromBase10("65000549695646603727810655408050771481677621702948236658134783353303381437752") // xiTo2PSquaredMinus2Over3 is ξ^((2p²-2)/3) where ξ = i+3 (a cubic root of unity, mod p). var xiTo2PSquaredMinus2Over3 = bigFromBase10("4985783334309134261147736404674766913742361673560802634030") // xiToPSquaredMinus1Over6 is ξ^((1p²-1)/6) where ξ = i+3 (a cubic root of -1, mod p). var xiToPSquaredMinus1Over6 = bigFromBase10("65000549695646603727810655408050771481677621702948236658134783353303381437753") // xiTo2PMinus2Over3 is ξ^((2p-2)/3) where ξ = i+3. var xiTo2PMinus2Over3 = &gfP2{bigFromBase10("19885131339612776214803633203834694332692106372356013117629940868870585019582"), bigFromBase10("21645619881471562101905880913352894726728173167203616652430647841922248593627")} lxd-2.0.0/dist/src/golang.org/x/crypto/bn256/curve.go0000644061062106075000000001254512702772344024612 0ustar00stgraberdomain admins00000000000000// Copyright 2012 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 bn256 import ( "math/big" ) // curvePoint implements the elliptic curve y²=x³+3. Points are kept in // Jacobian form and t=z² when valid. Gâ‚ is the set of points of this curve on // GF(p). type curvePoint struct { x, y, z, t *big.Int } var curveB = new(big.Int).SetInt64(3) // curveGen is the generator of Gâ‚. var curveGen = &curvePoint{ new(big.Int).SetInt64(1), new(big.Int).SetInt64(-2), new(big.Int).SetInt64(1), new(big.Int).SetInt64(1), } func newCurvePoint(pool *bnPool) *curvePoint { return &curvePoint{ pool.Get(), pool.Get(), pool.Get(), pool.Get(), } } func (c *curvePoint) String() string { c.MakeAffine(new(bnPool)) return "(" + c.x.String() + ", " + c.y.String() + ")" } func (c *curvePoint) Put(pool *bnPool) { pool.Put(c.x) pool.Put(c.y) pool.Put(c.z) pool.Put(c.t) } func (c *curvePoint) Set(a *curvePoint) { c.x.Set(a.x) c.y.Set(a.y) c.z.Set(a.z) c.t.Set(a.t) } // IsOnCurve returns true iff c is on the curve where c must be in affine form. func (c *curvePoint) IsOnCurve() bool { yy := new(big.Int).Mul(c.y, c.y) xxx := new(big.Int).Mul(c.x, c.x) xxx.Mul(xxx, c.x) yy.Sub(yy, xxx) yy.Sub(yy, curveB) if yy.Sign() < 0 || yy.Cmp(p) >= 0 { yy.Mod(yy, p) } return yy.Sign() == 0 } func (c *curvePoint) SetInfinity() { c.z.SetInt64(0) } func (c *curvePoint) IsInfinity() bool { return c.z.Sign() == 0 } func (c *curvePoint) Add(a, b *curvePoint, pool *bnPool) { if a.IsInfinity() { c.Set(b) return } if b.IsInfinity() { c.Set(a) return } // See http://hyperelliptic.org/EFD/g1p/auto-code/shortw/jacobian-0/addition/add-2007-bl.op3 // Normalize the points by replacing a = [x1:y1:z1] and b = [x2:y2:z2] // by [u1:s1:z1·z2] and [u2:s2:z1·z2] // where u1 = x1·z2², s1 = y1·z2³ and u1 = x2·z1², s2 = y2·z1³ z1z1 := pool.Get().Mul(a.z, a.z) z1z1.Mod(z1z1, p) z2z2 := pool.Get().Mul(b.z, b.z) z2z2.Mod(z2z2, p) u1 := pool.Get().Mul(a.x, z2z2) u1.Mod(u1, p) u2 := pool.Get().Mul(b.x, z1z1) u2.Mod(u2, p) t := pool.Get().Mul(b.z, z2z2) t.Mod(t, p) s1 := pool.Get().Mul(a.y, t) s1.Mod(s1, p) t.Mul(a.z, z1z1) t.Mod(t, p) s2 := pool.Get().Mul(b.y, t) s2.Mod(s2, p) // Compute x = (2h)²(s²-u1-u2) // where s = (s2-s1)/(u2-u1) is the slope of the line through // (u1,s1) and (u2,s2). The extra factor 2h = 2(u2-u1) comes from the value of z below. // This is also: // 4(s2-s1)² - 4h²(u1+u2) = 4(s2-s1)² - 4h³ - 4h²(2u1) // = r² - j - 2v // with the notations below. h := pool.Get().Sub(u2, u1) xEqual := h.Sign() == 0 t.Add(h, h) // i = 4h² i := pool.Get().Mul(t, t) i.Mod(i, p) // j = 4h³ j := pool.Get().Mul(h, i) j.Mod(j, p) t.Sub(s2, s1) yEqual := t.Sign() == 0 if xEqual && yEqual { c.Double(a, pool) return } r := pool.Get().Add(t, t) v := pool.Get().Mul(u1, i) v.Mod(v, p) // t4 = 4(s2-s1)² t4 := pool.Get().Mul(r, r) t4.Mod(t4, p) t.Add(v, v) t6 := pool.Get().Sub(t4, j) c.x.Sub(t6, t) // Set y = -(2h)³(s1 + s*(x/4h²-u1)) // This is also // y = - 2·s1·j - (s2-s1)(2x - 2i·u1) = r(v-x) - 2·s1·j t.Sub(v, c.x) // t7 t4.Mul(s1, j) // t8 t4.Mod(t4, p) t6.Add(t4, t4) // t9 t4.Mul(r, t) // t10 t4.Mod(t4, p) c.y.Sub(t4, t6) // Set z = 2(u2-u1)·z1·z2 = 2h·z1·z2 t.Add(a.z, b.z) // t11 t4.Mul(t, t) // t12 t4.Mod(t4, p) t.Sub(t4, z1z1) // t13 t4.Sub(t, z2z2) // t14 c.z.Mul(t4, h) c.z.Mod(c.z, p) pool.Put(z1z1) pool.Put(z2z2) pool.Put(u1) pool.Put(u2) pool.Put(t) pool.Put(s1) pool.Put(s2) pool.Put(h) pool.Put(i) pool.Put(j) pool.Put(r) pool.Put(v) pool.Put(t4) pool.Put(t6) } func (c *curvePoint) Double(a *curvePoint, pool *bnPool) { // See http://hyperelliptic.org/EFD/g1p/auto-code/shortw/jacobian-0/doubling/dbl-2009-l.op3 A := pool.Get().Mul(a.x, a.x) A.Mod(A, p) B := pool.Get().Mul(a.y, a.y) B.Mod(B, p) C := pool.Get().Mul(B, B) C.Mod(C, p) t := pool.Get().Add(a.x, B) t2 := pool.Get().Mul(t, t) t2.Mod(t2, p) t.Sub(t2, A) t2.Sub(t, C) d := pool.Get().Add(t2, t2) t.Add(A, A) e := pool.Get().Add(t, A) f := pool.Get().Mul(e, e) f.Mod(f, p) t.Add(d, d) c.x.Sub(f, t) t.Add(C, C) t2.Add(t, t) t.Add(t2, t2) c.y.Sub(d, c.x) t2.Mul(e, c.y) t2.Mod(t2, p) c.y.Sub(t2, t) t.Mul(a.y, a.z) t.Mod(t, p) c.z.Add(t, t) pool.Put(A) pool.Put(B) pool.Put(C) pool.Put(t) pool.Put(t2) pool.Put(d) pool.Put(e) pool.Put(f) } func (c *curvePoint) Mul(a *curvePoint, scalar *big.Int, pool *bnPool) *curvePoint { sum := newCurvePoint(pool) sum.SetInfinity() t := newCurvePoint(pool) for i := scalar.BitLen(); i >= 0; i-- { t.Double(sum, pool) if scalar.Bit(i) != 0 { sum.Add(t, a, pool) } else { sum.Set(t) } } c.Set(sum) sum.Put(pool) t.Put(pool) return c } func (c *curvePoint) MakeAffine(pool *bnPool) *curvePoint { if words := c.z.Bits(); len(words) == 1 && words[0] == 1 { return c } zInv := pool.Get().ModInverse(c.z, p) t := pool.Get().Mul(c.y, zInv) t.Mod(t, p) zInv2 := pool.Get().Mul(zInv, zInv) zInv2.Mod(zInv2, p) c.y.Mul(t, zInv2) c.y.Mod(c.y, p) t.Mul(c.x, zInv2) t.Mod(t, p) c.x.Set(t) c.z.SetInt64(1) c.t.SetInt64(1) pool.Put(zInv) pool.Put(t) pool.Put(zInv2) return c } func (c *curvePoint) Negative(a *curvePoint) { c.x.Set(a.x) c.y.Neg(a.y) c.z.Set(a.z) c.t.SetInt64(0) } lxd-2.0.0/dist/src/golang.org/x/crypto/bn256/gfp6.go0000644061062106075000000001322112702772344024320 0ustar00stgraberdomain admins00000000000000// Copyright 2012 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 bn256 // For details of the algorithms used, see "Multiplication and Squaring on // Pairing-Friendly Fields, Devegili et al. // http://eprint.iacr.org/2006/471.pdf. import ( "math/big" ) // gfP6 implements the field of size pâ¶ as a cubic extension of gfP2 where τ³=ξ // and ξ=i+3. type gfP6 struct { x, y, z *gfP2 // value is xτ² + yÏ„ + z } func newGFp6(pool *bnPool) *gfP6 { return &gfP6{newGFp2(pool), newGFp2(pool), newGFp2(pool)} } func (e *gfP6) String() string { return "(" + e.x.String() + "," + e.y.String() + "," + e.z.String() + ")" } func (e *gfP6) Put(pool *bnPool) { e.x.Put(pool) e.y.Put(pool) e.z.Put(pool) } func (e *gfP6) Set(a *gfP6) *gfP6 { e.x.Set(a.x) e.y.Set(a.y) e.z.Set(a.z) return e } func (e *gfP6) SetZero() *gfP6 { e.x.SetZero() e.y.SetZero() e.z.SetZero() return e } func (e *gfP6) SetOne() *gfP6 { e.x.SetZero() e.y.SetZero() e.z.SetOne() return e } func (e *gfP6) Minimal() { e.x.Minimal() e.y.Minimal() e.z.Minimal() } func (e *gfP6) IsZero() bool { return e.x.IsZero() && e.y.IsZero() && e.z.IsZero() } func (e *gfP6) IsOne() bool { return e.x.IsZero() && e.y.IsZero() && e.z.IsOne() } func (e *gfP6) Negative(a *gfP6) *gfP6 { e.x.Negative(a.x) e.y.Negative(a.y) e.z.Negative(a.z) return e } func (e *gfP6) Frobenius(a *gfP6, pool *bnPool) *gfP6 { e.x.Conjugate(a.x) e.y.Conjugate(a.y) e.z.Conjugate(a.z) e.x.Mul(e.x, xiTo2PMinus2Over3, pool) e.y.Mul(e.y, xiToPMinus1Over3, pool) return e } // FrobeniusP2 computes (xτ²+yÏ„+z)^(p²) = xÏ„^(2p²) + yÏ„^(p²) + z func (e *gfP6) FrobeniusP2(a *gfP6) *gfP6 { // Ï„^(2p²) = τ²τ^(2p²-2) = τ²ξ^((2p²-2)/3) e.x.MulScalar(a.x, xiTo2PSquaredMinus2Over3) // Ï„^(p²) = ττ^(p²-1) = τξ^((p²-1)/3) e.y.MulScalar(a.y, xiToPSquaredMinus1Over3) e.z.Set(a.z) return e } func (e *gfP6) Add(a, b *gfP6) *gfP6 { e.x.Add(a.x, b.x) e.y.Add(a.y, b.y) e.z.Add(a.z, b.z) return e } func (e *gfP6) Sub(a, b *gfP6) *gfP6 { e.x.Sub(a.x, b.x) e.y.Sub(a.y, b.y) e.z.Sub(a.z, b.z) return e } func (e *gfP6) Double(a *gfP6) *gfP6 { e.x.Double(a.x) e.y.Double(a.y) e.z.Double(a.z) return e } func (e *gfP6) Mul(a, b *gfP6, pool *bnPool) *gfP6 { // "Multiplication and Squaring on Pairing-Friendly Fields" // Section 4, Karatsuba method. // http://eprint.iacr.org/2006/471.pdf v0 := newGFp2(pool) v0.Mul(a.z, b.z, pool) v1 := newGFp2(pool) v1.Mul(a.y, b.y, pool) v2 := newGFp2(pool) v2.Mul(a.x, b.x, pool) t0 := newGFp2(pool) t0.Add(a.x, a.y) t1 := newGFp2(pool) t1.Add(b.x, b.y) tz := newGFp2(pool) tz.Mul(t0, t1, pool) tz.Sub(tz, v1) tz.Sub(tz, v2) tz.MulXi(tz, pool) tz.Add(tz, v0) t0.Add(a.y, a.z) t1.Add(b.y, b.z) ty := newGFp2(pool) ty.Mul(t0, t1, pool) ty.Sub(ty, v0) ty.Sub(ty, v1) t0.MulXi(v2, pool) ty.Add(ty, t0) t0.Add(a.x, a.z) t1.Add(b.x, b.z) tx := newGFp2(pool) tx.Mul(t0, t1, pool) tx.Sub(tx, v0) tx.Add(tx, v1) tx.Sub(tx, v2) e.x.Set(tx) e.y.Set(ty) e.z.Set(tz) t0.Put(pool) t1.Put(pool) tx.Put(pool) ty.Put(pool) tz.Put(pool) v0.Put(pool) v1.Put(pool) v2.Put(pool) return e } func (e *gfP6) MulScalar(a *gfP6, b *gfP2, pool *bnPool) *gfP6 { e.x.Mul(a.x, b, pool) e.y.Mul(a.y, b, pool) e.z.Mul(a.z, b, pool) return e } func (e *gfP6) MulGFP(a *gfP6, b *big.Int) *gfP6 { e.x.MulScalar(a.x, b) e.y.MulScalar(a.y, b) e.z.MulScalar(a.z, b) return e } // MulTau computes τ·(aτ²+bÏ„+c) = bτ²+cÏ„+aξ func (e *gfP6) MulTau(a *gfP6, pool *bnPool) { tz := newGFp2(pool) tz.MulXi(a.x, pool) ty := newGFp2(pool) ty.Set(a.y) e.y.Set(a.z) e.x.Set(ty) e.z.Set(tz) tz.Put(pool) ty.Put(pool) } func (e *gfP6) Square(a *gfP6, pool *bnPool) *gfP6 { v0 := newGFp2(pool).Square(a.z, pool) v1 := newGFp2(pool).Square(a.y, pool) v2 := newGFp2(pool).Square(a.x, pool) c0 := newGFp2(pool).Add(a.x, a.y) c0.Square(c0, pool) c0.Sub(c0, v1) c0.Sub(c0, v2) c0.MulXi(c0, pool) c0.Add(c0, v0) c1 := newGFp2(pool).Add(a.y, a.z) c1.Square(c1, pool) c1.Sub(c1, v0) c1.Sub(c1, v1) xiV2 := newGFp2(pool).MulXi(v2, pool) c1.Add(c1, xiV2) c2 := newGFp2(pool).Add(a.x, a.z) c2.Square(c2, pool) c2.Sub(c2, v0) c2.Add(c2, v1) c2.Sub(c2, v2) e.x.Set(c2) e.y.Set(c1) e.z.Set(c0) v0.Put(pool) v1.Put(pool) v2.Put(pool) c0.Put(pool) c1.Put(pool) c2.Put(pool) xiV2.Put(pool) return e } func (e *gfP6) Invert(a *gfP6, pool *bnPool) *gfP6 { // See "Implementing cryptographic pairings", M. Scott, section 3.2. // ftp://136.206.11.249/pub/crypto/pairings.pdf // Here we can give a short explanation of how it works: let j be a cubic root of // unity in GF(p²) so that 1+j+j²=0. // Then (xτ² + yÏ„ + z)(xj²τ² + yjÏ„ + z)(xjτ² + yj²τ + z) // = (xτ² + yÏ„ + z)(Cτ²+BÏ„+A) // = (x³ξ²+y³ξ+z³-3ξxyz) = F is an element of the base field (the norm). // // On the other hand (xj²τ² + yjÏ„ + z)(xjτ² + yj²τ + z) // = τ²(y²-ξxz) + Ï„(ξx²-yz) + (z²-ξxy) // // So that's why A = (z²-ξxy), B = (ξx²-yz), C = (y²-ξxz) t1 := newGFp2(pool) A := newGFp2(pool) A.Square(a.z, pool) t1.Mul(a.x, a.y, pool) t1.MulXi(t1, pool) A.Sub(A, t1) B := newGFp2(pool) B.Square(a.x, pool) B.MulXi(B, pool) t1.Mul(a.y, a.z, pool) B.Sub(B, t1) C := newGFp2(pool) C.Square(a.y, pool) t1.Mul(a.x, a.z, pool) C.Sub(C, t1) F := newGFp2(pool) F.Mul(C, a.y, pool) F.MulXi(F, pool) t1.Mul(A, a.z, pool) F.Add(F, t1) t1.Mul(B, a.x, pool) t1.MulXi(t1, pool) F.Add(F, t1) F.Invert(F, pool) e.x.Mul(C, F, pool) e.y.Mul(B, F, pool) e.z.Mul(A, F, pool) t1.Put(pool) A.Put(pool) B.Put(pool) C.Put(pool) F.Put(pool) return e } lxd-2.0.0/dist/src/golang.org/x/crypto/hkdf/0000755061062106075000000000000012702772344023210 5ustar00stgraberdomain admins00000000000000lxd-2.0.0/dist/src/golang.org/x/crypto/hkdf/example_test.go0000644061062106075000000000273212702772344026235 0ustar00stgraberdomain admins00000000000000// Copyright 2014 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 hkdf_test import ( "bytes" "crypto/rand" "crypto/sha256" "fmt" "golang.org/x/crypto/hkdf" "io" ) // Usage example that expands one master key into three other cryptographically // secure keys. func Example_usage() { // Underlying hash function to use hash := sha256.New // Cryptographically secure master key. master := []byte{0x00, 0x01, 0x02, 0x03} // i.e. NOT this. // Non secret salt, optional (can be nil) // Recommended: hash-length sized random salt := make([]byte, hash().Size()) n, err := io.ReadFull(rand.Reader, salt) if n != len(salt) || err != nil { fmt.Println("error:", err) return } // Non secret context specific info, optional (can be nil). // Note, independent from the master key. info := []byte{0x03, 0x14, 0x15, 0x92, 0x65} // Create the key derivation function hkdf := hkdf.New(hash, master, salt, info) // Generate the required keys keys := make([][]byte, 3) for i := 0; i < len(keys); i++ { keys[i] = make([]byte, 24) n, err := io.ReadFull(hkdf, keys[i]) if n != len(keys[i]) || err != nil { fmt.Println("error:", err) return } } // Keys should contain 192 bit random keys for i := 1; i <= len(keys); i++ { fmt.Printf("Key #%d: %v\n", i, !bytes.Equal(keys[i-1], make([]byte, 24))) } // Output: // Key #1: true // Key #2: true // Key #3: true } lxd-2.0.0/dist/src/golang.org/x/crypto/hkdf/hkdf.go0000644061062106075000000000345512702772344024462 0ustar00stgraberdomain admins00000000000000// Copyright 2014 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 hkdf implements the HMAC-based Extract-and-Expand Key Derivation // Function (HKDF) as defined in RFC 5869. // // HKDF is a cryptographic key derivation function (KDF) with the goal of // expanding limited input keying material into one or more cryptographically // strong secret keys. // // RFC 5869: https://tools.ietf.org/html/rfc5869 package hkdf // import "golang.org/x/crypto/hkdf" import ( "crypto/hmac" "errors" "hash" "io" ) type hkdf struct { expander hash.Hash size int info []byte counter byte prev []byte cache []byte } func (f *hkdf) Read(p []byte) (int, error) { // Check whether enough data can be generated need := len(p) remains := len(f.cache) + int(255-f.counter+1)*f.size if remains < need { return 0, errors.New("hkdf: entropy limit reached") } // Read from the cache, if enough data is present n := copy(p, f.cache) p = p[n:] // Fill the buffer for len(p) > 0 { f.expander.Reset() f.expander.Write(f.prev) f.expander.Write(f.info) f.expander.Write([]byte{f.counter}) f.prev = f.expander.Sum(f.prev[:0]) f.counter++ // Copy the new batch into p f.cache = f.prev n = copy(p, f.cache) p = p[n:] } // Save leftovers for next run f.cache = f.cache[n:] return need, nil } // New returns a new HKDF using the given hash, the secret keying material to expand // and optional salt and info fields. func New(hash func() hash.Hash, secret, salt, info []byte) io.Reader { if salt == nil { salt = make([]byte, hash().Size()) } extractor := hmac.New(hash, salt) extractor.Write(secret) prk := extractor.Sum(nil) return &hkdf{hmac.New(hash, prk), extractor.Size(), info, 1, nil, nil} } lxd-2.0.0/dist/src/golang.org/x/crypto/hkdf/hkdf_test.go0000644061062106075000000002516712702772344025525 0ustar00stgraberdomain admins00000000000000// Copyright 2014 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 hkdf import ( "bytes" "crypto/md5" "crypto/sha1" "crypto/sha256" "crypto/sha512" "hash" "io" "testing" ) type hkdfTest struct { hash func() hash.Hash master []byte salt []byte info []byte out []byte } var hkdfTests = []hkdfTest{ // Tests from RFC 5869 { sha256.New, []byte{ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, }, []byte{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, }, []byte{ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, }, []byte{ 0x3c, 0xb2, 0x5f, 0x25, 0xfa, 0xac, 0xd5, 0x7a, 0x90, 0x43, 0x4f, 0x64, 0xd0, 0x36, 0x2f, 0x2a, 0x2d, 0x2d, 0x0a, 0x90, 0xcf, 0x1a, 0x5a, 0x4c, 0x5d, 0xb0, 0x2d, 0x56, 0xec, 0xc4, 0xc5, 0xbf, 0x34, 0x00, 0x72, 0x08, 0xd5, 0xb8, 0x87, 0x18, 0x58, 0x65, }, }, { sha256.New, []byte{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, }, []byte{ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, }, []byte{ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, }, []byte{ 0xb1, 0x1e, 0x39, 0x8d, 0xc8, 0x03, 0x27, 0xa1, 0xc8, 0xe7, 0xf7, 0x8c, 0x59, 0x6a, 0x49, 0x34, 0x4f, 0x01, 0x2e, 0xda, 0x2d, 0x4e, 0xfa, 0xd8, 0xa0, 0x50, 0xcc, 0x4c, 0x19, 0xaf, 0xa9, 0x7c, 0x59, 0x04, 0x5a, 0x99, 0xca, 0xc7, 0x82, 0x72, 0x71, 0xcb, 0x41, 0xc6, 0x5e, 0x59, 0x0e, 0x09, 0xda, 0x32, 0x75, 0x60, 0x0c, 0x2f, 0x09, 0xb8, 0x36, 0x77, 0x93, 0xa9, 0xac, 0xa3, 0xdb, 0x71, 0xcc, 0x30, 0xc5, 0x81, 0x79, 0xec, 0x3e, 0x87, 0xc1, 0x4c, 0x01, 0xd5, 0xc1, 0xf3, 0x43, 0x4f, 0x1d, 0x87, }, }, { sha256.New, []byte{ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, }, []byte{}, []byte{}, []byte{ 0x8d, 0xa4, 0xe7, 0x75, 0xa5, 0x63, 0xc1, 0x8f, 0x71, 0x5f, 0x80, 0x2a, 0x06, 0x3c, 0x5a, 0x31, 0xb8, 0xa1, 0x1f, 0x5c, 0x5e, 0xe1, 0x87, 0x9e, 0xc3, 0x45, 0x4e, 0x5f, 0x3c, 0x73, 0x8d, 0x2d, 0x9d, 0x20, 0x13, 0x95, 0xfa, 0xa4, 0xb6, 0x1a, 0x96, 0xc8, }, }, { sha1.New, []byte{ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, }, []byte{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, }, []byte{ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, }, []byte{ 0x08, 0x5a, 0x01, 0xea, 0x1b, 0x10, 0xf3, 0x69, 0x33, 0x06, 0x8b, 0x56, 0xef, 0xa5, 0xad, 0x81, 0xa4, 0xf1, 0x4b, 0x82, 0x2f, 0x5b, 0x09, 0x15, 0x68, 0xa9, 0xcd, 0xd4, 0xf1, 0x55, 0xfd, 0xa2, 0xc2, 0x2e, 0x42, 0x24, 0x78, 0xd3, 0x05, 0xf3, 0xf8, 0x96, }, }, { sha1.New, []byte{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, }, []byte{ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, }, []byte{ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, }, []byte{ 0x0b, 0xd7, 0x70, 0xa7, 0x4d, 0x11, 0x60, 0xf7, 0xc9, 0xf1, 0x2c, 0xd5, 0x91, 0x2a, 0x06, 0xeb, 0xff, 0x6a, 0xdc, 0xae, 0x89, 0x9d, 0x92, 0x19, 0x1f, 0xe4, 0x30, 0x56, 0x73, 0xba, 0x2f, 0xfe, 0x8f, 0xa3, 0xf1, 0xa4, 0xe5, 0xad, 0x79, 0xf3, 0xf3, 0x34, 0xb3, 0xb2, 0x02, 0xb2, 0x17, 0x3c, 0x48, 0x6e, 0xa3, 0x7c, 0xe3, 0xd3, 0x97, 0xed, 0x03, 0x4c, 0x7f, 0x9d, 0xfe, 0xb1, 0x5c, 0x5e, 0x92, 0x73, 0x36, 0xd0, 0x44, 0x1f, 0x4c, 0x43, 0x00, 0xe2, 0xcf, 0xf0, 0xd0, 0x90, 0x0b, 0x52, 0xd3, 0xb4, }, }, { sha1.New, []byte{ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, }, []byte{}, []byte{}, []byte{ 0x0a, 0xc1, 0xaf, 0x70, 0x02, 0xb3, 0xd7, 0x61, 0xd1, 0xe5, 0x52, 0x98, 0xda, 0x9d, 0x05, 0x06, 0xb9, 0xae, 0x52, 0x05, 0x72, 0x20, 0xa3, 0x06, 0xe0, 0x7b, 0x6b, 0x87, 0xe8, 0xdf, 0x21, 0xd0, 0xea, 0x00, 0x03, 0x3d, 0xe0, 0x39, 0x84, 0xd3, 0x49, 0x18, }, }, { sha1.New, []byte{ 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, }, nil, []byte{}, []byte{ 0x2c, 0x91, 0x11, 0x72, 0x04, 0xd7, 0x45, 0xf3, 0x50, 0x0d, 0x63, 0x6a, 0x62, 0xf6, 0x4f, 0x0a, 0xb3, 0xba, 0xe5, 0x48, 0xaa, 0x53, 0xd4, 0x23, 0xb0, 0xd1, 0xf2, 0x7e, 0xbb, 0xa6, 0xf5, 0xe5, 0x67, 0x3a, 0x08, 0x1d, 0x70, 0xcc, 0xe7, 0xac, 0xfc, 0x48, }, }, } func TestHKDF(t *testing.T) { for i, tt := range hkdfTests { hkdf := New(tt.hash, tt.master, tt.salt, tt.info) out := make([]byte, len(tt.out)) n, err := io.ReadFull(hkdf, out) if n != len(tt.out) || err != nil { t.Errorf("test %d: not enough output bytes: %d.", i, n) } if !bytes.Equal(out, tt.out) { t.Errorf("test %d: incorrect output: have %v, need %v.", i, out, tt.out) } } } func TestHKDFMultiRead(t *testing.T) { for i, tt := range hkdfTests { hkdf := New(tt.hash, tt.master, tt.salt, tt.info) out := make([]byte, len(tt.out)) for b := 0; b < len(tt.out); b++ { n, err := io.ReadFull(hkdf, out[b:b+1]) if n != 1 || err != nil { t.Errorf("test %d.%d: not enough output bytes: have %d, need %d .", i, b, n, len(tt.out)) } } if !bytes.Equal(out, tt.out) { t.Errorf("test %d: incorrect output: have %v, need %v.", i, out, tt.out) } } } func TestHKDFLimit(t *testing.T) { hash := sha1.New master := []byte{0x00, 0x01, 0x02, 0x03} info := []byte{} hkdf := New(hash, master, nil, info) limit := hash().Size() * 255 out := make([]byte, limit) // The maximum output bytes should be extractable n, err := io.ReadFull(hkdf, out) if n != limit || err != nil { t.Errorf("not enough output bytes: %d, %v.", n, err) } // Reading one more should fail n, err = io.ReadFull(hkdf, make([]byte, 1)) if n > 0 || err == nil { t.Errorf("key expansion overflowed: n = %d, err = %v", n, err) } } func Benchmark16ByteMD5Single(b *testing.B) { benchmarkHKDFSingle(md5.New, 16, b) } func Benchmark20ByteSHA1Single(b *testing.B) { benchmarkHKDFSingle(sha1.New, 20, b) } func Benchmark32ByteSHA256Single(b *testing.B) { benchmarkHKDFSingle(sha256.New, 32, b) } func Benchmark64ByteSHA512Single(b *testing.B) { benchmarkHKDFSingle(sha512.New, 64, b) } func Benchmark8ByteMD5Stream(b *testing.B) { benchmarkHKDFStream(md5.New, 8, b) } func Benchmark16ByteMD5Stream(b *testing.B) { benchmarkHKDFStream(md5.New, 16, b) } func Benchmark8ByteSHA1Stream(b *testing.B) { benchmarkHKDFStream(sha1.New, 8, b) } func Benchmark20ByteSHA1Stream(b *testing.B) { benchmarkHKDFStream(sha1.New, 20, b) } func Benchmark8ByteSHA256Stream(b *testing.B) { benchmarkHKDFStream(sha256.New, 8, b) } func Benchmark32ByteSHA256Stream(b *testing.B) { benchmarkHKDFStream(sha256.New, 32, b) } func Benchmark8ByteSHA512Stream(b *testing.B) { benchmarkHKDFStream(sha512.New, 8, b) } func Benchmark64ByteSHA512Stream(b *testing.B) { benchmarkHKDFStream(sha512.New, 64, b) } func benchmarkHKDFSingle(hasher func() hash.Hash, block int, b *testing.B) { master := []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07} salt := []byte{0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17} info := []byte{0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27} out := make([]byte, block) b.SetBytes(int64(block)) b.ResetTimer() for i := 0; i < b.N; i++ { hkdf := New(hasher, master, salt, info) io.ReadFull(hkdf, out) } } func benchmarkHKDFStream(hasher func() hash.Hash, block int, b *testing.B) { master := []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07} salt := []byte{0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17} info := []byte{0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27} out := make([]byte, block) b.SetBytes(int64(block)) b.ResetTimer() hkdf := New(hasher, master, salt, info) for i := 0; i < b.N; i++ { _, err := io.ReadFull(hkdf, out) if err != nil { hkdf = New(hasher, master, salt, info) i-- } } } lxd-2.0.0/dist/src/golang.org/x/crypto/.gitattributes0000644061062106075000000000053112702772344025166 0ustar00stgraberdomain admins00000000000000# Treat all files in this repo as binary, with no git magic updating # line endings. Windows users contributing to Go will need to use a # modern version of git and editors capable of LF line endings. # # We'll prevent accidental CRLF line endings from entering the repo # via the git-review gofmt checks. # # See golang.org/issue/9281 * -text lxd-2.0.0/dist/src/golang.org/x/crypto/PATENTS0000644061062106075000000000242712702772344023342 0ustar00stgraberdomain admins00000000000000Additional IP Rights Grant (Patents) "This implementation" means the copyrightable works distributed by Google as part of the Go project. Google hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, transfer and otherwise run, modify and propagate the contents of this implementation of Go, where such license applies only to those patent claims, both currently owned or controlled by Google and acquired in the future, licensable by Google that are necessarily infringed by this implementation of Go. This grant does not include claims that would be infringed only as a consequence of further modification of this implementation. If you or your agent or exclusive licensee institute or order or agree to the institution of patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that this implementation of Go or any code incorporated within this implementation of Go constitutes direct or contributory patent infringement, or inducement of patent infringement, then any patent rights granted to you under this License for this implementation of Go shall terminate as of the date such litigation is filed. lxd-2.0.0/dist/src/golang.org/x/crypto/scrypt/0000755061062106075000000000000012702772344023620 5ustar00stgraberdomain admins00000000000000lxd-2.0.0/dist/src/golang.org/x/crypto/scrypt/scrypt.go0000644061062106075000000001335212702772344025477 0ustar00stgraberdomain admins00000000000000// Copyright 2012 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 scrypt implements the scrypt key derivation function as defined in // Colin Percival's paper "Stronger Key Derivation via Sequential Memory-Hard // Functions" (http://www.tarsnap.com/scrypt/scrypt.pdf). package scrypt // import "golang.org/x/crypto/scrypt" import ( "crypto/sha256" "errors" "golang.org/x/crypto/pbkdf2" ) const maxInt = int(^uint(0) >> 1) // blockCopy copies n numbers from src into dst. func blockCopy(dst, src []uint32, n int) { copy(dst, src[:n]) } // blockXOR XORs numbers from dst with n numbers from src. func blockXOR(dst, src []uint32, n int) { for i, v := range src[:n] { dst[i] ^= v } } // salsaXOR applies Salsa20/8 to the XOR of 16 numbers from tmp and in, // and puts the result into both both tmp and out. func salsaXOR(tmp *[16]uint32, in, out []uint32) { w0 := tmp[0] ^ in[0] w1 := tmp[1] ^ in[1] w2 := tmp[2] ^ in[2] w3 := tmp[3] ^ in[3] w4 := tmp[4] ^ in[4] w5 := tmp[5] ^ in[5] w6 := tmp[6] ^ in[6] w7 := tmp[7] ^ in[7] w8 := tmp[8] ^ in[8] w9 := tmp[9] ^ in[9] w10 := tmp[10] ^ in[10] w11 := tmp[11] ^ in[11] w12 := tmp[12] ^ in[12] w13 := tmp[13] ^ in[13] w14 := tmp[14] ^ in[14] w15 := tmp[15] ^ in[15] x0, x1, x2, x3, x4, x5, x6, x7, x8 := w0, w1, w2, w3, w4, w5, w6, w7, w8 x9, x10, x11, x12, x13, x14, x15 := w9, w10, w11, w12, w13, w14, w15 for i := 0; i < 8; i += 2 { u := x0 + x12 x4 ^= u<<7 | u>>(32-7) u = x4 + x0 x8 ^= u<<9 | u>>(32-9) u = x8 + x4 x12 ^= u<<13 | u>>(32-13) u = x12 + x8 x0 ^= u<<18 | u>>(32-18) u = x5 + x1 x9 ^= u<<7 | u>>(32-7) u = x9 + x5 x13 ^= u<<9 | u>>(32-9) u = x13 + x9 x1 ^= u<<13 | u>>(32-13) u = x1 + x13 x5 ^= u<<18 | u>>(32-18) u = x10 + x6 x14 ^= u<<7 | u>>(32-7) u = x14 + x10 x2 ^= u<<9 | u>>(32-9) u = x2 + x14 x6 ^= u<<13 | u>>(32-13) u = x6 + x2 x10 ^= u<<18 | u>>(32-18) u = x15 + x11 x3 ^= u<<7 | u>>(32-7) u = x3 + x15 x7 ^= u<<9 | u>>(32-9) u = x7 + x3 x11 ^= u<<13 | u>>(32-13) u = x11 + x7 x15 ^= u<<18 | u>>(32-18) u = x0 + x3 x1 ^= u<<7 | u>>(32-7) u = x1 + x0 x2 ^= u<<9 | u>>(32-9) u = x2 + x1 x3 ^= u<<13 | u>>(32-13) u = x3 + x2 x0 ^= u<<18 | u>>(32-18) u = x5 + x4 x6 ^= u<<7 | u>>(32-7) u = x6 + x5 x7 ^= u<<9 | u>>(32-9) u = x7 + x6 x4 ^= u<<13 | u>>(32-13) u = x4 + x7 x5 ^= u<<18 | u>>(32-18) u = x10 + x9 x11 ^= u<<7 | u>>(32-7) u = x11 + x10 x8 ^= u<<9 | u>>(32-9) u = x8 + x11 x9 ^= u<<13 | u>>(32-13) u = x9 + x8 x10 ^= u<<18 | u>>(32-18) u = x15 + x14 x12 ^= u<<7 | u>>(32-7) u = x12 + x15 x13 ^= u<<9 | u>>(32-9) u = x13 + x12 x14 ^= u<<13 | u>>(32-13) u = x14 + x13 x15 ^= u<<18 | u>>(32-18) } x0 += w0 x1 += w1 x2 += w2 x3 += w3 x4 += w4 x5 += w5 x6 += w6 x7 += w7 x8 += w8 x9 += w9 x10 += w10 x11 += w11 x12 += w12 x13 += w13 x14 += w14 x15 += w15 out[0], tmp[0] = x0, x0 out[1], tmp[1] = x1, x1 out[2], tmp[2] = x2, x2 out[3], tmp[3] = x3, x3 out[4], tmp[4] = x4, x4 out[5], tmp[5] = x5, x5 out[6], tmp[6] = x6, x6 out[7], tmp[7] = x7, x7 out[8], tmp[8] = x8, x8 out[9], tmp[9] = x9, x9 out[10], tmp[10] = x10, x10 out[11], tmp[11] = x11, x11 out[12], tmp[12] = x12, x12 out[13], tmp[13] = x13, x13 out[14], tmp[14] = x14, x14 out[15], tmp[15] = x15, x15 } func blockMix(tmp *[16]uint32, in, out []uint32, r int) { blockCopy(tmp[:], in[(2*r-1)*16:], 16) for i := 0; i < 2*r; i += 2 { salsaXOR(tmp, in[i*16:], out[i*8:]) salsaXOR(tmp, in[i*16+16:], out[i*8+r*16:]) } } func integer(b []uint32, r int) uint64 { j := (2*r - 1) * 16 return uint64(b[j]) | uint64(b[j+1])<<32 } func smix(b []byte, r, N int, v, xy []uint32) { var tmp [16]uint32 x := xy y := xy[32*r:] j := 0 for i := 0; i < 32*r; i++ { x[i] = uint32(b[j]) | uint32(b[j+1])<<8 | uint32(b[j+2])<<16 | uint32(b[j+3])<<24 j += 4 } for i := 0; i < N; i += 2 { blockCopy(v[i*(32*r):], x, 32*r) blockMix(&tmp, x, y, r) blockCopy(v[(i+1)*(32*r):], y, 32*r) blockMix(&tmp, y, x, r) } for i := 0; i < N; i += 2 { j := int(integer(x, r) & uint64(N-1)) blockXOR(x, v[j*(32*r):], 32*r) blockMix(&tmp, x, y, r) j = int(integer(y, r) & uint64(N-1)) blockXOR(y, v[j*(32*r):], 32*r) blockMix(&tmp, y, x, r) } j = 0 for _, v := range x[:32*r] { b[j+0] = byte(v >> 0) b[j+1] = byte(v >> 8) b[j+2] = byte(v >> 16) b[j+3] = byte(v >> 24) j += 4 } } // Key derives a key from the password, salt, and cost parameters, returning // a byte slice of length keyLen that can be used as cryptographic key. // // N is a CPU/memory cost parameter, which must be a power of two greater than 1. // r and p must satisfy r * p < 2³â°. If the parameters do not satisfy the // limits, the function returns a nil byte slice and an error. // // For example, you can get a derived key for e.g. AES-256 (which needs a // 32-byte key) by doing: // // dk := scrypt.Key([]byte("some password"), salt, 16384, 8, 1, 32) // // The recommended parameters for interactive logins as of 2009 are N=16384, // r=8, p=1. They should be increased as memory latency and CPU parallelism // increases. Remember to get a good random salt. func Key(password, salt []byte, N, r, p, keyLen int) ([]byte, error) { if N <= 1 || N&(N-1) != 0 { return nil, errors.New("scrypt: N must be > 1 and a power of 2") } if uint64(r)*uint64(p) >= 1<<30 || r > maxInt/128/p || r > maxInt/256 || N > maxInt/128/r { return nil, errors.New("scrypt: parameters are too large") } xy := make([]uint32, 64*r) v := make([]uint32, 32*N*r) b := pbkdf2.Key(password, salt, 1, p*128*r, sha256.New) for i := 0; i < p; i++ { smix(b[i*128*r:], r, N, v, xy) } return pbkdf2.Key(password, b, 1, keyLen, sha256.New), nil } lxd-2.0.0/dist/src/golang.org/x/crypto/scrypt/scrypt_test.go0000644061062106075000000001054712702772344026541 0ustar00stgraberdomain admins00000000000000// Copyright 2012 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 scrypt import ( "bytes" "testing" ) type testVector struct { password string salt string N, r, p int output []byte } var good = []testVector{ { "password", "salt", 2, 10, 10, []byte{ 0x48, 0x2c, 0x85, 0x8e, 0x22, 0x90, 0x55, 0xe6, 0x2f, 0x41, 0xe0, 0xec, 0x81, 0x9a, 0x5e, 0xe1, 0x8b, 0xdb, 0x87, 0x25, 0x1a, 0x53, 0x4f, 0x75, 0xac, 0xd9, 0x5a, 0xc5, 0xe5, 0xa, 0xa1, 0x5f, }, }, { "password", "salt", 16, 100, 100, []byte{ 0x88, 0xbd, 0x5e, 0xdb, 0x52, 0xd1, 0xdd, 0x0, 0x18, 0x87, 0x72, 0xad, 0x36, 0x17, 0x12, 0x90, 0x22, 0x4e, 0x74, 0x82, 0x95, 0x25, 0xb1, 0x8d, 0x73, 0x23, 0xa5, 0x7f, 0x91, 0x96, 0x3c, 0x37, }, }, { "this is a long \000 password", "and this is a long \000 salt", 16384, 8, 1, []byte{ 0xc3, 0xf1, 0x82, 0xee, 0x2d, 0xec, 0x84, 0x6e, 0x70, 0xa6, 0x94, 0x2f, 0xb5, 0x29, 0x98, 0x5a, 0x3a, 0x09, 0x76, 0x5e, 0xf0, 0x4c, 0x61, 0x29, 0x23, 0xb1, 0x7f, 0x18, 0x55, 0x5a, 0x37, 0x07, 0x6d, 0xeb, 0x2b, 0x98, 0x30, 0xd6, 0x9d, 0xe5, 0x49, 0x26, 0x51, 0xe4, 0x50, 0x6a, 0xe5, 0x77, 0x6d, 0x96, 0xd4, 0x0f, 0x67, 0xaa, 0xee, 0x37, 0xe1, 0x77, 0x7b, 0x8a, 0xd5, 0xc3, 0x11, 0x14, 0x32, 0xbb, 0x3b, 0x6f, 0x7e, 0x12, 0x64, 0x40, 0x18, 0x79, 0xe6, 0x41, 0xae, }, }, { "p", "s", 2, 1, 1, []byte{ 0x48, 0xb0, 0xd2, 0xa8, 0xa3, 0x27, 0x26, 0x11, 0x98, 0x4c, 0x50, 0xeb, 0xd6, 0x30, 0xaf, 0x52, }, }, { "", "", 16, 1, 1, []byte{ 0x77, 0xd6, 0x57, 0x62, 0x38, 0x65, 0x7b, 0x20, 0x3b, 0x19, 0xca, 0x42, 0xc1, 0x8a, 0x04, 0x97, 0xf1, 0x6b, 0x48, 0x44, 0xe3, 0x07, 0x4a, 0xe8, 0xdf, 0xdf, 0xfa, 0x3f, 0xed, 0xe2, 0x14, 0x42, 0xfc, 0xd0, 0x06, 0x9d, 0xed, 0x09, 0x48, 0xf8, 0x32, 0x6a, 0x75, 0x3a, 0x0f, 0xc8, 0x1f, 0x17, 0xe8, 0xd3, 0xe0, 0xfb, 0x2e, 0x0d, 0x36, 0x28, 0xcf, 0x35, 0xe2, 0x0c, 0x38, 0xd1, 0x89, 0x06, }, }, { "password", "NaCl", 1024, 8, 16, []byte{ 0xfd, 0xba, 0xbe, 0x1c, 0x9d, 0x34, 0x72, 0x00, 0x78, 0x56, 0xe7, 0x19, 0x0d, 0x01, 0xe9, 0xfe, 0x7c, 0x6a, 0xd7, 0xcb, 0xc8, 0x23, 0x78, 0x30, 0xe7, 0x73, 0x76, 0x63, 0x4b, 0x37, 0x31, 0x62, 0x2e, 0xaf, 0x30, 0xd9, 0x2e, 0x22, 0xa3, 0x88, 0x6f, 0xf1, 0x09, 0x27, 0x9d, 0x98, 0x30, 0xda, 0xc7, 0x27, 0xaf, 0xb9, 0x4a, 0x83, 0xee, 0x6d, 0x83, 0x60, 0xcb, 0xdf, 0xa2, 0xcc, 0x06, 0x40, }, }, { "pleaseletmein", "SodiumChloride", 16384, 8, 1, []byte{ 0x70, 0x23, 0xbd, 0xcb, 0x3a, 0xfd, 0x73, 0x48, 0x46, 0x1c, 0x06, 0xcd, 0x81, 0xfd, 0x38, 0xeb, 0xfd, 0xa8, 0xfb, 0xba, 0x90, 0x4f, 0x8e, 0x3e, 0xa9, 0xb5, 0x43, 0xf6, 0x54, 0x5d, 0xa1, 0xf2, 0xd5, 0x43, 0x29, 0x55, 0x61, 0x3f, 0x0f, 0xcf, 0x62, 0xd4, 0x97, 0x05, 0x24, 0x2a, 0x9a, 0xf9, 0xe6, 0x1e, 0x85, 0xdc, 0x0d, 0x65, 0x1e, 0x40, 0xdf, 0xcf, 0x01, 0x7b, 0x45, 0x57, 0x58, 0x87, }, }, /* // Disabled: needs 1 GiB RAM and takes too long for a simple test. { "pleaseletmein", "SodiumChloride", 1048576, 8, 1, []byte{ 0x21, 0x01, 0xcb, 0x9b, 0x6a, 0x51, 0x1a, 0xae, 0xad, 0xdb, 0xbe, 0x09, 0xcf, 0x70, 0xf8, 0x81, 0xec, 0x56, 0x8d, 0x57, 0x4a, 0x2f, 0xfd, 0x4d, 0xab, 0xe5, 0xee, 0x98, 0x20, 0xad, 0xaa, 0x47, 0x8e, 0x56, 0xfd, 0x8f, 0x4b, 0xa5, 0xd0, 0x9f, 0xfa, 0x1c, 0x6d, 0x92, 0x7c, 0x40, 0xf4, 0xc3, 0x37, 0x30, 0x40, 0x49, 0xe8, 0xa9, 0x52, 0xfb, 0xcb, 0xf4, 0x5c, 0x6f, 0xa7, 0x7a, 0x41, 0xa4, }, }, */ } var bad = []testVector{ {"p", "s", 0, 1, 1, nil}, // N == 0 {"p", "s", 1, 1, 1, nil}, // N == 1 {"p", "s", 7, 8, 1, nil}, // N is not power of 2 {"p", "s", 16, maxInt / 2, maxInt / 2, nil}, // p * r too large } func TestKey(t *testing.T) { for i, v := range good { k, err := Key([]byte(v.password), []byte(v.salt), v.N, v.r, v.p, len(v.output)) if err != nil { t.Errorf("%d: got unexpected error: %s", i, err) } if !bytes.Equal(k, v.output) { t.Errorf("%d: expected %x, got %x", i, v.output, k) } } for i, v := range bad { _, err := Key([]byte(v.password), []byte(v.salt), v.N, v.r, v.p, 32) if err == nil { t.Errorf("%d: expected error, got nil", i) } } } func BenchmarkKey(b *testing.B) { for i := 0; i < b.N; i++ { Key([]byte("password"), []byte("salt"), 16384, 8, 1, 64) } } lxd-2.0.0/dist/src/golang.org/x/crypto/nacl/0000755061062106075000000000000012702772344023211 5ustar00stgraberdomain admins00000000000000lxd-2.0.0/dist/src/golang.org/x/crypto/nacl/secretbox/0000755061062106075000000000000012702772344025207 5ustar00stgraberdomain admins00000000000000lxd-2.0.0/dist/src/golang.org/x/crypto/nacl/secretbox/secretbox.go0000644061062106075000000001121312702772344027532 0ustar00stgraberdomain admins00000000000000// Copyright 2012 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 secretbox encrypts and authenticates small messages. Secretbox uses XSalsa20 and Poly1305 to encrypt and authenticate messages with secret-key cryptography. The length of messages is not hidden. It is the caller's responsibility to ensure the uniqueness of nonces—for example, by using nonce 1 for the first message, nonce 2 for the second message, etc. Nonces are long enough that randomly generated nonces have negligible risk of collision. This package is interoperable with NaCl: http://nacl.cr.yp.to/secretbox.html. */ package secretbox // import "golang.org/x/crypto/nacl/secretbox" import ( "golang.org/x/crypto/poly1305" "golang.org/x/crypto/salsa20/salsa" ) // Overhead is the number of bytes of overhead when boxing a message. const Overhead = poly1305.TagSize // setup produces a sub-key and Salsa20 counter given a nonce and key. func setup(subKey *[32]byte, counter *[16]byte, nonce *[24]byte, key *[32]byte) { // We use XSalsa20 for encryption so first we need to generate a // key and nonce with HSalsa20. var hNonce [16]byte copy(hNonce[:], nonce[:]) salsa.HSalsa20(subKey, &hNonce, key, &salsa.Sigma) // The final 8 bytes of the original nonce form the new nonce. copy(counter[:], nonce[16:]) } // sliceForAppend takes a slice and a requested number of bytes. It returns a // slice with the contents of the given slice followed by that many bytes and a // second slice that aliases into it and contains only the extra bytes. If the // original slice has sufficient capacity then no allocation is performed. func sliceForAppend(in []byte, n int) (head, tail []byte) { if total := len(in) + n; cap(in) >= total { head = in[:total] } else { head = make([]byte, total) copy(head, in) } tail = head[len(in):] return } // Seal appends an encrypted and authenticated copy of message to out, which // must not overlap message. The key and nonce pair must be unique for each // distinct message and the output will be Overhead bytes longer than message. func Seal(out, message []byte, nonce *[24]byte, key *[32]byte) []byte { var subKey [32]byte var counter [16]byte setup(&subKey, &counter, nonce, key) // The Poly1305 key is generated by encrypting 32 bytes of zeros. Since // Salsa20 works with 64-byte blocks, we also generate 32 bytes of // keystream as a side effect. var firstBlock [64]byte salsa.XORKeyStream(firstBlock[:], firstBlock[:], &counter, &subKey) var poly1305Key [32]byte copy(poly1305Key[:], firstBlock[:]) ret, out := sliceForAppend(out, len(message)+poly1305.TagSize) // We XOR up to 32 bytes of message with the keystream generated from // the first block. firstMessageBlock := message if len(firstMessageBlock) > 32 { firstMessageBlock = firstMessageBlock[:32] } tagOut := out out = out[poly1305.TagSize:] for i, x := range firstMessageBlock { out[i] = firstBlock[32+i] ^ x } message = message[len(firstMessageBlock):] ciphertext := out out = out[len(firstMessageBlock):] // Now encrypt the rest. counter[8] = 1 salsa.XORKeyStream(out, message, &counter, &subKey) var tag [poly1305.TagSize]byte poly1305.Sum(&tag, ciphertext, &poly1305Key) copy(tagOut, tag[:]) return ret } // Open authenticates and decrypts a box produced by Seal and appends the // message to out, which must not overlap box. The output will be Overhead // bytes smaller than box. func Open(out []byte, box []byte, nonce *[24]byte, key *[32]byte) ([]byte, bool) { if len(box) < Overhead { return nil, false } var subKey [32]byte var counter [16]byte setup(&subKey, &counter, nonce, key) // The Poly1305 key is generated by encrypting 32 bytes of zeros. Since // Salsa20 works with 64-byte blocks, we also generate 32 bytes of // keystream as a side effect. var firstBlock [64]byte salsa.XORKeyStream(firstBlock[:], firstBlock[:], &counter, &subKey) var poly1305Key [32]byte copy(poly1305Key[:], firstBlock[:]) var tag [poly1305.TagSize]byte copy(tag[:], box) if !poly1305.Verify(&tag, box[poly1305.TagSize:], &poly1305Key) { return nil, false } ret, out := sliceForAppend(out, len(box)-Overhead) // We XOR up to 32 bytes of box with the keystream generated from // the first block. box = box[Overhead:] firstMessageBlock := box if len(firstMessageBlock) > 32 { firstMessageBlock = firstMessageBlock[:32] } for i, x := range firstMessageBlock { out[i] = firstBlock[32+i] ^ x } box = box[len(firstMessageBlock):] out = out[len(firstMessageBlock):] // Now decrypt the rest. counter[8] = 1 salsa.XORKeyStream(out, box, &counter, &subKey) return ret, true } lxd-2.0.0/dist/src/golang.org/x/crypto/nacl/secretbox/secretbox_test.go0000644061062106075000000000402112702772344030570 0ustar00stgraberdomain admins00000000000000// Copyright 2012 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 secretbox import ( "bytes" "crypto/rand" "encoding/hex" "testing" ) func TestSealOpen(t *testing.T) { var key [32]byte var nonce [24]byte rand.Reader.Read(key[:]) rand.Reader.Read(nonce[:]) var box, opened []byte for msgLen := 0; msgLen < 128; msgLen += 17 { message := make([]byte, msgLen) rand.Reader.Read(message) box = Seal(box[:0], message, &nonce, &key) var ok bool opened, ok = Open(opened[:0], box, &nonce, &key) if !ok { t.Errorf("%d: failed to open box", msgLen) continue } if !bytes.Equal(opened, message) { t.Errorf("%d: got %x, expected %x", msgLen, opened, message) continue } } for i := range box { box[i] ^= 0x20 _, ok := Open(opened[:0], box, &nonce, &key) if ok { t.Errorf("box was opened after corrupting byte %d", i) } box[i] ^= 0x20 } } func TestSecretBox(t *testing.T) { var key [32]byte var nonce [24]byte var message [64]byte for i := range key[:] { key[i] = 1 } for i := range nonce[:] { nonce[i] = 2 } for i := range message[:] { message[i] = 3 } box := Seal(nil, message[:], &nonce, &key) // expected was generated using the C implementation of NaCl. expected, _ := hex.DecodeString("8442bc313f4626f1359e3b50122b6ce6fe66ddfe7d39d14e637eb4fd5b45beadab55198df6ab5368439792a23c87db70acb6156dc5ef957ac04f6276cf6093b84be77ff0849cc33e34b7254d5a8f65ad") if !bytes.Equal(box, expected) { t.Fatalf("box didn't match, got\n%x\n, expected\n%x", box, expected) } } func TestAppend(t *testing.T) { var key [32]byte var nonce [24]byte var message [8]byte out := make([]byte, 4) box := Seal(out, message[:], &nonce, &key) if !bytes.Equal(box[:4], out[:4]) { t.Fatalf("Seal didn't correctly append") } out = make([]byte, 4, 100) box = Seal(out, message[:], &nonce, &key) if !bytes.Equal(box[:4], out[:4]) { t.Fatalf("Seal didn't correctly append with sufficient capacity.") } } lxd-2.0.0/dist/src/golang.org/x/crypto/nacl/box/0000755061062106075000000000000012702772344024001 5ustar00stgraberdomain admins00000000000000lxd-2.0.0/dist/src/golang.org/x/crypto/nacl/box/box.go0000644061062106075000000000630012702772344025117 0ustar00stgraberdomain admins00000000000000// Copyright 2012 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 box authenticates and encrypts messages using public-key cryptography. Box uses Curve25519, XSalsa20 and Poly1305 to encrypt and authenticate messages. The length of messages is not hidden. It is the caller's responsibility to ensure the uniqueness of nonces—for example, by using nonce 1 for the first message, nonce 2 for the second message, etc. Nonces are long enough that randomly generated nonces have negligible risk of collision. This package is interoperable with NaCl: http://nacl.cr.yp.to/box.html. */ package box // import "golang.org/x/crypto/nacl/box" import ( "golang.org/x/crypto/curve25519" "golang.org/x/crypto/nacl/secretbox" "golang.org/x/crypto/salsa20/salsa" "io" ) // Overhead is the number of bytes of overhead when boxing a message. const Overhead = secretbox.Overhead // GenerateKey generates a new public/private key pair suitable for use with // Seal and Open. func GenerateKey(rand io.Reader) (publicKey, privateKey *[32]byte, err error) { publicKey = new([32]byte) privateKey = new([32]byte) _, err = io.ReadFull(rand, privateKey[:]) if err != nil { publicKey = nil privateKey = nil return } curve25519.ScalarBaseMult(publicKey, privateKey) return } var zeros [16]byte // Precompute calculates the shared key between peersPublicKey and privateKey // and writes it to sharedKey. The shared key can be used with // OpenAfterPrecomputation and SealAfterPrecomputation to speed up processing // when using the same pair of keys repeatedly. func Precompute(sharedKey, peersPublicKey, privateKey *[32]byte) { curve25519.ScalarMult(sharedKey, privateKey, peersPublicKey) salsa.HSalsa20(sharedKey, &zeros, sharedKey, &salsa.Sigma) } // Seal appends an encrypted and authenticated copy of message to out, which // will be Overhead bytes longer than the original and must not overlap. The // nonce must be unique for each distinct message for a given pair of keys. func Seal(out, message []byte, nonce *[24]byte, peersPublicKey, privateKey *[32]byte) []byte { var sharedKey [32]byte Precompute(&sharedKey, peersPublicKey, privateKey) return secretbox.Seal(out, message, nonce, &sharedKey) } // SealAfterPrecomputation performs the same actions as Seal, but takes a // shared key as generated by Precompute. func SealAfterPrecomputation(out, message []byte, nonce *[24]byte, sharedKey *[32]byte) []byte { return secretbox.Seal(out, message, nonce, sharedKey) } // Open authenticates and decrypts a box produced by Seal and appends the // message to out, which must not overlap box. The output will be Overhead // bytes smaller than box. func Open(out, box []byte, nonce *[24]byte, peersPublicKey, privateKey *[32]byte) ([]byte, bool) { var sharedKey [32]byte Precompute(&sharedKey, peersPublicKey, privateKey) return secretbox.Open(out, box, nonce, &sharedKey) } // OpenAfterPrecomputation performs the same actions as Open, but takes a // shared key as generated by Precompute. func OpenAfterPrecomputation(out, box []byte, nonce *[24]byte, sharedKey *[32]byte) ([]byte, bool) { return secretbox.Open(out, box, nonce, sharedKey) } lxd-2.0.0/dist/src/golang.org/x/crypto/nacl/box/box_test.go0000644061062106075000000000356012702772344026163 0ustar00stgraberdomain admins00000000000000// Copyright 2012 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 box import ( "bytes" "crypto/rand" "encoding/hex" "testing" "golang.org/x/crypto/curve25519" ) func TestSealOpen(t *testing.T) { publicKey1, privateKey1, _ := GenerateKey(rand.Reader) publicKey2, privateKey2, _ := GenerateKey(rand.Reader) if *privateKey1 == *privateKey2 { t.Fatalf("private keys are equal!") } if *publicKey1 == *publicKey2 { t.Fatalf("public keys are equal!") } message := []byte("test message") var nonce [24]byte box := Seal(nil, message, &nonce, publicKey1, privateKey2) opened, ok := Open(nil, box, &nonce, publicKey2, privateKey1) if !ok { t.Fatalf("failed to open box") } if !bytes.Equal(opened, message) { t.Fatalf("got %x, want %x", opened, message) } for i := range box { box[i] ^= 0x40 _, ok := Open(nil, box, &nonce, publicKey2, privateKey1) if ok { t.Fatalf("opened box with byte %d corrupted", i) } box[i] ^= 0x40 } } func TestBox(t *testing.T) { var privateKey1, privateKey2 [32]byte for i := range privateKey1[:] { privateKey1[i] = 1 } for i := range privateKey2[:] { privateKey2[i] = 2 } var publicKey1 [32]byte curve25519.ScalarBaseMult(&publicKey1, &privateKey1) var message [64]byte for i := range message[:] { message[i] = 3 } var nonce [24]byte for i := range nonce[:] { nonce[i] = 4 } box := Seal(nil, message[:], &nonce, &publicKey1, &privateKey2) // expected was generated using the C implementation of NaCl. expected, _ := hex.DecodeString("78ea30b19d2341ebbdba54180f821eec265cf86312549bea8a37652a8bb94f07b78a73ed1708085e6ddd0e943bbdeb8755079a37eb31d86163ce241164a47629c0539f330b4914cd135b3855bc2a2dfc") if !bytes.Equal(box, expected) { t.Fatalf("box didn't match, got\n%x\n, expected\n%x", box, expected) } } lxd-2.0.0/dist/src/golang.org/x/crypto/AUTHORS0000644061062106075000000000025512702772344023346 0ustar00stgraberdomain admins00000000000000# This source code refers to The Go Authors for copyright purposes. # The master list of authors is in the main Go distribution, # visible at http://tip.golang.org/AUTHORS. lxd-2.0.0/dist/src/golang.org/x/crypto/bcrypt/0000755061062106075000000000000012702772344023577 5ustar00stgraberdomain admins00000000000000lxd-2.0.0/dist/src/golang.org/x/crypto/bcrypt/bcrypt.go0000644061062106075000000001731012702772344025433 0ustar00stgraberdomain admins00000000000000// 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 bcrypt implements Provos and Mazières's bcrypt adaptive hashing // algorithm. See http://www.usenix.org/event/usenix99/provos/provos.pdf package bcrypt // import "golang.org/x/crypto/bcrypt" // The code is a port of Provos and Mazières's C implementation. import ( "crypto/rand" "crypto/subtle" "errors" "fmt" "golang.org/x/crypto/blowfish" "io" "strconv" ) const ( MinCost int = 4 // the minimum allowable cost as passed in to GenerateFromPassword MaxCost int = 31 // the maximum allowable cost as passed in to GenerateFromPassword DefaultCost int = 10 // the cost that will actually be set if a cost below MinCost is passed into GenerateFromPassword ) // The error returned from CompareHashAndPassword when a password and hash do // not match. var ErrMismatchedHashAndPassword = errors.New("crypto/bcrypt: hashedPassword is not the hash of the given password") // The error returned from CompareHashAndPassword when a hash is too short to // be a bcrypt hash. var ErrHashTooShort = errors.New("crypto/bcrypt: hashedSecret too short to be a bcrypted password") // The error returned from CompareHashAndPassword when a hash was created with // a bcrypt algorithm newer than this implementation. type HashVersionTooNewError byte func (hv HashVersionTooNewError) Error() string { return fmt.Sprintf("crypto/bcrypt: bcrypt algorithm version '%c' requested is newer than current version '%c'", byte(hv), majorVersion) } // The error returned from CompareHashAndPassword when a hash starts with something other than '$' type InvalidHashPrefixError byte func (ih InvalidHashPrefixError) Error() string { return fmt.Sprintf("crypto/bcrypt: bcrypt hashes must start with '$', but hashedSecret started with '%c'", byte(ih)) } type InvalidCostError int func (ic InvalidCostError) Error() string { return fmt.Sprintf("crypto/bcrypt: cost %d is outside allowed range (%d,%d)", int(ic), int(MinCost), int(MaxCost)) } const ( majorVersion = '2' minorVersion = 'a' maxSaltSize = 16 maxCryptedHashSize = 23 encodedSaltSize = 22 encodedHashSize = 31 minHashSize = 59 ) // magicCipherData is an IV for the 64 Blowfish encryption calls in // bcrypt(). It's the string "OrpheanBeholderScryDoubt" in big-endian bytes. var magicCipherData = []byte{ 0x4f, 0x72, 0x70, 0x68, 0x65, 0x61, 0x6e, 0x42, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x53, 0x63, 0x72, 0x79, 0x44, 0x6f, 0x75, 0x62, 0x74, } type hashed struct { hash []byte salt []byte cost int // allowed range is MinCost to MaxCost major byte minor byte } // GenerateFromPassword returns the bcrypt hash of the password at the given // cost. If the cost given is less than MinCost, the cost will be set to // DefaultCost, instead. Use CompareHashAndPassword, as defined in this package, // to compare the returned hashed password with its cleartext version. func GenerateFromPassword(password []byte, cost int) ([]byte, error) { p, err := newFromPassword(password, cost) if err != nil { return nil, err } return p.Hash(), nil } // CompareHashAndPassword compares a bcrypt hashed password with its possible // plaintext equivalent. Returns nil on success, or an error on failure. func CompareHashAndPassword(hashedPassword, password []byte) error { p, err := newFromHash(hashedPassword) if err != nil { return err } otherHash, err := bcrypt(password, p.cost, p.salt) if err != nil { return err } otherP := &hashed{otherHash, p.salt, p.cost, p.major, p.minor} if subtle.ConstantTimeCompare(p.Hash(), otherP.Hash()) == 1 { return nil } return ErrMismatchedHashAndPassword } // Cost returns the hashing cost used to create the given hashed // password. When, in the future, the hashing cost of a password system needs // to be increased in order to adjust for greater computational power, this // function allows one to establish which passwords need to be updated. func Cost(hashedPassword []byte) (int, error) { p, err := newFromHash(hashedPassword) if err != nil { return 0, err } return p.cost, nil } func newFromPassword(password []byte, cost int) (*hashed, error) { if cost < MinCost { cost = DefaultCost } p := new(hashed) p.major = majorVersion p.minor = minorVersion err := checkCost(cost) if err != nil { return nil, err } p.cost = cost unencodedSalt := make([]byte, maxSaltSize) _, err = io.ReadFull(rand.Reader, unencodedSalt) if err != nil { return nil, err } p.salt = base64Encode(unencodedSalt) hash, err := bcrypt(password, p.cost, p.salt) if err != nil { return nil, err } p.hash = hash return p, err } func newFromHash(hashedSecret []byte) (*hashed, error) { if len(hashedSecret) < minHashSize { return nil, ErrHashTooShort } p := new(hashed) n, err := p.decodeVersion(hashedSecret) if err != nil { return nil, err } hashedSecret = hashedSecret[n:] n, err = p.decodeCost(hashedSecret) if err != nil { return nil, err } hashedSecret = hashedSecret[n:] // The "+2" is here because we'll have to append at most 2 '=' to the salt // when base64 decoding it in expensiveBlowfishSetup(). p.salt = make([]byte, encodedSaltSize, encodedSaltSize+2) copy(p.salt, hashedSecret[:encodedSaltSize]) hashedSecret = hashedSecret[encodedSaltSize:] p.hash = make([]byte, len(hashedSecret)) copy(p.hash, hashedSecret) return p, nil } func bcrypt(password []byte, cost int, salt []byte) ([]byte, error) { cipherData := make([]byte, len(magicCipherData)) copy(cipherData, magicCipherData) c, err := expensiveBlowfishSetup(password, uint32(cost), salt) if err != nil { return nil, err } for i := 0; i < 24; i += 8 { for j := 0; j < 64; j++ { c.Encrypt(cipherData[i:i+8], cipherData[i:i+8]) } } // Bug compatibility with C bcrypt implementations. We only encode 23 of // the 24 bytes encrypted. hsh := base64Encode(cipherData[:maxCryptedHashSize]) return hsh, nil } func expensiveBlowfishSetup(key []byte, cost uint32, salt []byte) (*blowfish.Cipher, error) { csalt, err := base64Decode(salt) if err != nil { return nil, err } // Bug compatibility with C bcrypt implementations. They use the trailing // NULL in the key string during expansion. ckey := append(key, 0) c, err := blowfish.NewSaltedCipher(ckey, csalt) if err != nil { return nil, err } var i, rounds uint64 rounds = 1 << cost for i = 0; i < rounds; i++ { blowfish.ExpandKey(ckey, c) blowfish.ExpandKey(csalt, c) } return c, nil } func (p *hashed) Hash() []byte { arr := make([]byte, 60) arr[0] = '$' arr[1] = p.major n := 2 if p.minor != 0 { arr[2] = p.minor n = 3 } arr[n] = '$' n += 1 copy(arr[n:], []byte(fmt.Sprintf("%02d", p.cost))) n += 2 arr[n] = '$' n += 1 copy(arr[n:], p.salt) n += encodedSaltSize copy(arr[n:], p.hash) n += encodedHashSize return arr[:n] } func (p *hashed) decodeVersion(sbytes []byte) (int, error) { if sbytes[0] != '$' { return -1, InvalidHashPrefixError(sbytes[0]) } if sbytes[1] > majorVersion { return -1, HashVersionTooNewError(sbytes[1]) } p.major = sbytes[1] n := 3 if sbytes[2] != '$' { p.minor = sbytes[2] n++ } return n, nil } // sbytes should begin where decodeVersion left off. func (p *hashed) decodeCost(sbytes []byte) (int, error) { cost, err := strconv.Atoi(string(sbytes[0:2])) if err != nil { return -1, err } err = checkCost(cost) if err != nil { return -1, err } p.cost = cost return 3, nil } func (p *hashed) String() string { return fmt.Sprintf("&{hash: %#v, salt: %#v, cost: %d, major: %c, minor: %c}", string(p.hash), p.salt, p.cost, p.major, p.minor) } func checkCost(cost int) error { if cost < MinCost || cost > MaxCost { return InvalidCostError(cost) } return nil } lxd-2.0.0/dist/src/golang.org/x/crypto/bcrypt/bcrypt_test.go0000644061062106075000000001434412702772344026476 0ustar00stgraberdomain admins00000000000000// 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 bcrypt import ( "bytes" "fmt" "testing" ) func TestBcryptingIsEasy(t *testing.T) { pass := []byte("mypassword") hp, err := GenerateFromPassword(pass, 0) if err != nil { t.Fatalf("GenerateFromPassword error: %s", err) } if CompareHashAndPassword(hp, pass) != nil { t.Errorf("%v should hash %s correctly", hp, pass) } notPass := "notthepass" err = CompareHashAndPassword(hp, []byte(notPass)) if err != ErrMismatchedHashAndPassword { t.Errorf("%v and %s should be mismatched", hp, notPass) } } func TestBcryptingIsCorrect(t *testing.T) { pass := []byte("allmine") salt := []byte("XajjQvNhvvRt5GSeFk1xFe") expectedHash := []byte("$2a$10$XajjQvNhvvRt5GSeFk1xFeyqRrsxkhBkUiQeg0dt.wU1qD4aFDcga") hash, err := bcrypt(pass, 10, salt) if err != nil { t.Fatalf("bcrypt blew up: %v", err) } if !bytes.HasSuffix(expectedHash, hash) { t.Errorf("%v should be the suffix of %v", hash, expectedHash) } h, err := newFromHash(expectedHash) if err != nil { t.Errorf("Unable to parse %s: %v", string(expectedHash), err) } // This is not the safe way to compare these hashes. We do this only for // testing clarity. Use bcrypt.CompareHashAndPassword() if err == nil && !bytes.Equal(expectedHash, h.Hash()) { t.Errorf("Parsed hash %v should equal %v", h.Hash(), expectedHash) } } func TestVeryShortPasswords(t *testing.T) { key := []byte("k") salt := []byte("XajjQvNhvvRt5GSeFk1xFe") _, err := bcrypt(key, 10, salt) if err != nil { t.Errorf("One byte key resulted in error: %s", err) } } func TestTooLongPasswordsWork(t *testing.T) { salt := []byte("XajjQvNhvvRt5GSeFk1xFe") // One byte over the usual 56 byte limit that blowfish has tooLongPass := []byte("012345678901234567890123456789012345678901234567890123456") tooLongExpected := []byte("$2a$10$XajjQvNhvvRt5GSeFk1xFe5l47dONXg781AmZtd869sO8zfsHuw7C") hash, err := bcrypt(tooLongPass, 10, salt) if err != nil { t.Fatalf("bcrypt blew up on long password: %v", err) } if !bytes.HasSuffix(tooLongExpected, hash) { t.Errorf("%v should be the suffix of %v", hash, tooLongExpected) } } type InvalidHashTest struct { err error hash []byte } var invalidTests = []InvalidHashTest{ {ErrHashTooShort, []byte("$2a$10$fooo")}, {ErrHashTooShort, []byte("$2a")}, {HashVersionTooNewError('3'), []byte("$3a$10$sssssssssssssssssssssshhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh")}, {InvalidHashPrefixError('%'), []byte("%2a$10$sssssssssssssssssssssshhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh")}, {InvalidCostError(32), []byte("$2a$32$sssssssssssssssssssssshhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh")}, } func TestInvalidHashErrors(t *testing.T) { check := func(name string, expected, err error) { if err == nil { t.Errorf("%s: Should have returned an error", name) } if err != nil && err != expected { t.Errorf("%s gave err %v but should have given %v", name, err, expected) } } for _, iht := range invalidTests { _, err := newFromHash(iht.hash) check("newFromHash", iht.err, err) err = CompareHashAndPassword(iht.hash, []byte("anything")) check("CompareHashAndPassword", iht.err, err) } } func TestUnpaddedBase64Encoding(t *testing.T) { original := []byte{101, 201, 101, 75, 19, 227, 199, 20, 239, 236, 133, 32, 30, 109, 243, 30} encodedOriginal := []byte("XajjQvNhvvRt5GSeFk1xFe") encoded := base64Encode(original) if !bytes.Equal(encodedOriginal, encoded) { t.Errorf("Encoded %v should have equaled %v", encoded, encodedOriginal) } decoded, err := base64Decode(encodedOriginal) if err != nil { t.Fatalf("base64Decode blew up: %s", err) } if !bytes.Equal(decoded, original) { t.Errorf("Decoded %v should have equaled %v", decoded, original) } } func TestCost(t *testing.T) { suffix := "XajjQvNhvvRt5GSeFk1xFe5l47dONXg781AmZtd869sO8zfsHuw7C" for _, vers := range []string{"2a", "2"} { for _, cost := range []int{4, 10} { s := fmt.Sprintf("$%s$%02d$%s", vers, cost, suffix) h := []byte(s) actual, err := Cost(h) if err != nil { t.Errorf("Cost, error: %s", err) continue } if actual != cost { t.Errorf("Cost, expected: %d, actual: %d", cost, actual) } } } _, err := Cost([]byte("$a$a$" + suffix)) if err == nil { t.Errorf("Cost, malformed but no error returned") } } func TestCostValidationInHash(t *testing.T) { if testing.Short() { return } pass := []byte("mypassword") for c := 0; c < MinCost; c++ { p, _ := newFromPassword(pass, c) if p.cost != DefaultCost { t.Errorf("newFromPassword should default costs below %d to %d, but was %d", MinCost, DefaultCost, p.cost) } } p, _ := newFromPassword(pass, 14) if p.cost != 14 { t.Errorf("newFromPassword should default cost to 14, but was %d", p.cost) } hp, _ := newFromHash(p.Hash()) if p.cost != hp.cost { t.Errorf("newFromHash should maintain the cost at %d, but was %d", p.cost, hp.cost) } _, err := newFromPassword(pass, 32) if err == nil { t.Fatalf("newFromPassword: should return a cost error") } if err != InvalidCostError(32) { t.Errorf("newFromPassword: should return cost error, got %#v", err) } } func TestCostReturnsWithLeadingZeroes(t *testing.T) { hp, _ := newFromPassword([]byte("abcdefgh"), 7) cost := hp.Hash()[4:7] expected := []byte("07$") if !bytes.Equal(expected, cost) { t.Errorf("single digit costs in hash should have leading zeros: was %v instead of %v", cost, expected) } } func TestMinorNotRequired(t *testing.T) { noMinorHash := []byte("$2$10$XajjQvNhvvRt5GSeFk1xFeyqRrsxkhBkUiQeg0dt.wU1qD4aFDcga") h, err := newFromHash(noMinorHash) if err != nil { t.Fatalf("No minor hash blew up: %s", err) } if h.minor != 0 { t.Errorf("Should leave minor version at 0, but was %d", h.minor) } if !bytes.Equal(noMinorHash, h.Hash()) { t.Errorf("Should generate hash %v, but created %v", noMinorHash, h.Hash()) } } func BenchmarkEqual(b *testing.B) { b.StopTimer() passwd := []byte("somepasswordyoulike") hash, _ := GenerateFromPassword(passwd, 10) b.StartTimer() for i := 0; i < b.N; i++ { CompareHashAndPassword(hash, passwd) } } func BenchmarkGeneration(b *testing.B) { b.StopTimer() passwd := []byte("mylongpassword1234") b.StartTimer() for i := 0; i < b.N; i++ { GenerateFromPassword(passwd, 10) } } lxd-2.0.0/dist/src/golang.org/x/crypto/bcrypt/base64.go0000644061062106075000000000146112702772344025214 0ustar00stgraberdomain admins00000000000000// 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 bcrypt import "encoding/base64" const alphabet = "./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" var bcEncoding = base64.NewEncoding(alphabet) func base64Encode(src []byte) []byte { n := bcEncoding.EncodedLen(len(src)) dst := make([]byte, n) bcEncoding.Encode(dst, src) for dst[n-1] == '=' { n-- } return dst[:n] } func base64Decode(src []byte) ([]byte, error) { numOfEquals := 4 - (len(src) % 4) for i := 0; i < numOfEquals; i++ { src = append(src, '=') } dst := make([]byte, bcEncoding.DecodedLen(len(src))) n, err := bcEncoding.Decode(dst, src) if err != nil { return nil, err } return dst[:n], nil } lxd-2.0.0/dist/src/golang.org/x/crypto/README0000644061062106075000000000022112702772344023147 0ustar00stgraberdomain admins00000000000000This repository holds supplementary Go cryptography libraries. To submit changes to this repository, see http://golang.org/doc/contribute.html. lxd-2.0.0/dist/src/github.com/0000755061062106075000000000000012702772372020510 5ustar00stgraberdomain admins00000000000000lxd-2.0.0/dist/src/github.com/stretchr/0000755061062106075000000000000012702772370022344 5ustar00stgraberdomain admins00000000000000lxd-2.0.0/dist/src/github.com/stretchr/testify/0000755061062106075000000000000012702772371024034 5ustar00stgraberdomain admins00000000000000lxd-2.0.0/dist/src/github.com/stretchr/testify/package_test.go0000644061062106075000000000027112702772371027015 0ustar00stgraberdomain admins00000000000000package testify import ( "github.com/stretchr/testify/assert" "testing" ) func TestImports(t *testing.T) { if assert.Equal(t, 1, 1) != true { t.Error("Something is wrong.") } } lxd-2.0.0/dist/src/github.com/stretchr/testify/assert/0000755061062106075000000000000012702772371025335 5ustar00stgraberdomain admins00000000000000lxd-2.0.0/dist/src/github.com/stretchr/testify/assert/forward_assertions.go0000644061062106075000000000055612702772371031610 0ustar00stgraberdomain admins00000000000000package assert // Assertions provides assertion methods around the // TestingT interface. type Assertions struct { t TestingT } // New makes a new Assertions object for the specified TestingT. func New(t TestingT) *Assertions { return &Assertions{ t: t, } } //go:generate go run ../_codegen/main.go -output-package=assert -template=assertion_forward.go.tmpl lxd-2.0.0/dist/src/github.com/stretchr/testify/assert/errors.go0000644061062106075000000000050612702772371027201 0ustar00stgraberdomain admins00000000000000package assert import ( "errors" ) // AnError is an error instance useful for testing. If the code does not care // about error specifics, and only needs to return the error for example, this // error should be used to make the test code more readable. var AnError = errors.New("assert.AnError general error for testing") lxd-2.0.0/dist/src/github.com/stretchr/testify/assert/doc.go0000644061062106075000000000254312702772371026435 0ustar00stgraberdomain admins00000000000000// Package assert provides a set of comprehensive testing tools for use with the normal Go testing system. // // Example Usage // // The following is a complete example using assert in a standard test function: // import ( // "testing" // "github.com/stretchr/testify/assert" // ) // // func TestSomething(t *testing.T) { // // var a string = "Hello" // var b string = "Hello" // // assert.Equal(t, a, b, "The two words should be the same.") // // } // // if you assert many times, use the format below: // // import ( // "testing" // "github.com/stretchr/testify/assert" // ) // // func TestSomething(t *testing.T) { // assert := assert.New(t) // // var a string = "Hello" // var b string = "Hello" // // assert.Equal(a, b, "The two words should be the same.") // } // // Assertions // // Assertions allow you to easily write test code, and are global funcs in the `assert` package. // All assertion functions take, as the first argument, the `*testing.T` object provided by the // testing framework. This allows the assertion funcs to write the failings and other details to // the correct place. // // Every assertion function also takes an optional string message as the final argument, // allowing custom error messages to be appended to the message the assertion method outputs. package assert lxd-2.0.0/dist/src/github.com/stretchr/testify/assert/forward_assertions_test.go0000644061062106075000000004141112702772371032642 0ustar00stgraberdomain admins00000000000000package assert import ( "errors" "regexp" "testing" "time" ) func TestImplementsWrapper(t *testing.T) { assert := New(new(testing.T)) if !assert.Implements((*AssertionTesterInterface)(nil), new(AssertionTesterConformingObject)) { t.Error("Implements method should return true: AssertionTesterConformingObject implements AssertionTesterInterface") } if assert.Implements((*AssertionTesterInterface)(nil), new(AssertionTesterNonConformingObject)) { t.Error("Implements method should return false: AssertionTesterNonConformingObject does not implements AssertionTesterInterface") } } func TestIsTypeWrapper(t *testing.T) { assert := New(new(testing.T)) if !assert.IsType(new(AssertionTesterConformingObject), new(AssertionTesterConformingObject)) { t.Error("IsType should return true: AssertionTesterConformingObject is the same type as AssertionTesterConformingObject") } if assert.IsType(new(AssertionTesterConformingObject), new(AssertionTesterNonConformingObject)) { t.Error("IsType should return false: AssertionTesterConformingObject is not the same type as AssertionTesterNonConformingObject") } } func TestEqualWrapper(t *testing.T) { assert := New(new(testing.T)) if !assert.Equal("Hello World", "Hello World") { t.Error("Equal should return true") } if !assert.Equal(123, 123) { t.Error("Equal should return true") } if !assert.Equal(123.5, 123.5) { t.Error("Equal should return true") } if !assert.Equal([]byte("Hello World"), []byte("Hello World")) { t.Error("Equal should return true") } if !assert.Equal(nil, nil) { t.Error("Equal should return true") } } func TestEqualValuesWrapper(t *testing.T) { assert := New(new(testing.T)) if !assert.EqualValues(uint32(10), int32(10)) { t.Error("EqualValues should return true") } } func TestNotNilWrapper(t *testing.T) { assert := New(new(testing.T)) if !assert.NotNil(new(AssertionTesterConformingObject)) { t.Error("NotNil should return true: object is not nil") } if assert.NotNil(nil) { t.Error("NotNil should return false: object is nil") } } func TestNilWrapper(t *testing.T) { assert := New(new(testing.T)) if !assert.Nil(nil) { t.Error("Nil should return true: object is nil") } if assert.Nil(new(AssertionTesterConformingObject)) { t.Error("Nil should return false: object is not nil") } } func TestTrueWrapper(t *testing.T) { assert := New(new(testing.T)) if !assert.True(true) { t.Error("True should return true") } if assert.True(false) { t.Error("True should return false") } } func TestFalseWrapper(t *testing.T) { assert := New(new(testing.T)) if !assert.False(false) { t.Error("False should return true") } if assert.False(true) { t.Error("False should return false") } } func TestExactlyWrapper(t *testing.T) { assert := New(new(testing.T)) a := float32(1) b := float64(1) c := float32(1) d := float32(2) if assert.Exactly(a, b) { t.Error("Exactly should return false") } if assert.Exactly(a, d) { t.Error("Exactly should return false") } if !assert.Exactly(a, c) { t.Error("Exactly should return true") } if assert.Exactly(nil, a) { t.Error("Exactly should return false") } if assert.Exactly(a, nil) { t.Error("Exactly should return false") } } func TestNotEqualWrapper(t *testing.T) { assert := New(new(testing.T)) if !assert.NotEqual("Hello World", "Hello World!") { t.Error("NotEqual should return true") } if !assert.NotEqual(123, 1234) { t.Error("NotEqual should return true") } if !assert.NotEqual(123.5, 123.55) { t.Error("NotEqual should return true") } if !assert.NotEqual([]byte("Hello World"), []byte("Hello World!")) { t.Error("NotEqual should return true") } if !assert.NotEqual(nil, new(AssertionTesterConformingObject)) { t.Error("NotEqual should return true") } } func TestContainsWrapper(t *testing.T) { assert := New(new(testing.T)) list := []string{"Foo", "Bar"} if !assert.Contains("Hello World", "Hello") { t.Error("Contains should return true: \"Hello World\" contains \"Hello\"") } if assert.Contains("Hello World", "Salut") { t.Error("Contains should return false: \"Hello World\" does not contain \"Salut\"") } if !assert.Contains(list, "Foo") { t.Error("Contains should return true: \"[\"Foo\", \"Bar\"]\" contains \"Foo\"") } if assert.Contains(list, "Salut") { t.Error("Contains should return false: \"[\"Foo\", \"Bar\"]\" does not contain \"Salut\"") } } func TestNotContainsWrapper(t *testing.T) { assert := New(new(testing.T)) list := []string{"Foo", "Bar"} if !assert.NotContains("Hello World", "Hello!") { t.Error("NotContains should return true: \"Hello World\" does not contain \"Hello!\"") } if assert.NotContains("Hello World", "Hello") { t.Error("NotContains should return false: \"Hello World\" contains \"Hello\"") } if !assert.NotContains(list, "Foo!") { t.Error("NotContains should return true: \"[\"Foo\", \"Bar\"]\" does not contain \"Foo!\"") } if assert.NotContains(list, "Foo") { t.Error("NotContains should return false: \"[\"Foo\", \"Bar\"]\" contains \"Foo\"") } } func TestConditionWrapper(t *testing.T) { assert := New(new(testing.T)) if !assert.Condition(func() bool { return true }, "Truth") { t.Error("Condition should return true") } if assert.Condition(func() bool { return false }, "Lie") { t.Error("Condition should return false") } } func TestDidPanicWrapper(t *testing.T) { if funcDidPanic, _ := didPanic(func() { panic("Panic!") }); !funcDidPanic { t.Error("didPanic should return true") } if funcDidPanic, _ := didPanic(func() { }); funcDidPanic { t.Error("didPanic should return false") } } func TestPanicsWrapper(t *testing.T) { assert := New(new(testing.T)) if !assert.Panics(func() { panic("Panic!") }) { t.Error("Panics should return true") } if assert.Panics(func() { }) { t.Error("Panics should return false") } } func TestNotPanicsWrapper(t *testing.T) { assert := New(new(testing.T)) if !assert.NotPanics(func() { }) { t.Error("NotPanics should return true") } if assert.NotPanics(func() { panic("Panic!") }) { t.Error("NotPanics should return false") } } func TestNoErrorWrapper(t *testing.T) { assert := New(t) mockAssert := New(new(testing.T)) // start with a nil error var err error assert.True(mockAssert.NoError(err), "NoError should return True for nil arg") // now set an error err = errors.New("Some error") assert.False(mockAssert.NoError(err), "NoError with error should return False") } func TestErrorWrapper(t *testing.T) { assert := New(t) mockAssert := New(new(testing.T)) // start with a nil error var err error assert.False(mockAssert.Error(err), "Error should return False for nil arg") // now set an error err = errors.New("Some error") assert.True(mockAssert.Error(err), "Error with error should return True") } func TestEqualErrorWrapper(t *testing.T) { assert := New(t) mockAssert := New(new(testing.T)) // start with a nil error var err error assert.False(mockAssert.EqualError(err, ""), "EqualError should return false for nil arg") // now set an error err = errors.New("some error") assert.False(mockAssert.EqualError(err, "Not some error"), "EqualError should return false for different error string") assert.True(mockAssert.EqualError(err, "some error"), "EqualError should return true") } func TestEmptyWrapper(t *testing.T) { assert := New(t) mockAssert := New(new(testing.T)) assert.True(mockAssert.Empty(""), "Empty string is empty") assert.True(mockAssert.Empty(nil), "Nil is empty") assert.True(mockAssert.Empty([]string{}), "Empty string array is empty") assert.True(mockAssert.Empty(0), "Zero int value is empty") assert.True(mockAssert.Empty(false), "False value is empty") assert.False(mockAssert.Empty("something"), "Non Empty string is not empty") assert.False(mockAssert.Empty(errors.New("something")), "Non nil object is not empty") assert.False(mockAssert.Empty([]string{"something"}), "Non empty string array is not empty") assert.False(mockAssert.Empty(1), "Non-zero int value is not empty") assert.False(mockAssert.Empty(true), "True value is not empty") } func TestNotEmptyWrapper(t *testing.T) { assert := New(t) mockAssert := New(new(testing.T)) assert.False(mockAssert.NotEmpty(""), "Empty string is empty") assert.False(mockAssert.NotEmpty(nil), "Nil is empty") assert.False(mockAssert.NotEmpty([]string{}), "Empty string array is empty") assert.False(mockAssert.NotEmpty(0), "Zero int value is empty") assert.False(mockAssert.NotEmpty(false), "False value is empty") assert.True(mockAssert.NotEmpty("something"), "Non Empty string is not empty") assert.True(mockAssert.NotEmpty(errors.New("something")), "Non nil object is not empty") assert.True(mockAssert.NotEmpty([]string{"something"}), "Non empty string array is not empty") assert.True(mockAssert.NotEmpty(1), "Non-zero int value is not empty") assert.True(mockAssert.NotEmpty(true), "True value is not empty") } func TestLenWrapper(t *testing.T) { assert := New(t) mockAssert := New(new(testing.T)) assert.False(mockAssert.Len(nil, 0), "nil does not have length") assert.False(mockAssert.Len(0, 0), "int does not have length") assert.False(mockAssert.Len(true, 0), "true does not have length") assert.False(mockAssert.Len(false, 0), "false does not have length") assert.False(mockAssert.Len('A', 0), "Rune does not have length") assert.False(mockAssert.Len(struct{}{}, 0), "Struct does not have length") ch := make(chan int, 5) ch <- 1 ch <- 2 ch <- 3 cases := []struct { v interface{} l int }{ {[]int{1, 2, 3}, 3}, {[...]int{1, 2, 3}, 3}, {"ABC", 3}, {map[int]int{1: 2, 2: 4, 3: 6}, 3}, {ch, 3}, {[]int{}, 0}, {map[int]int{}, 0}, {make(chan int), 0}, {[]int(nil), 0}, {map[int]int(nil), 0}, {(chan int)(nil), 0}, } for _, c := range cases { assert.True(mockAssert.Len(c.v, c.l), "%#v have %d items", c.v, c.l) } } func TestWithinDurationWrapper(t *testing.T) { assert := New(t) mockAssert := New(new(testing.T)) a := time.Now() b := a.Add(10 * time.Second) assert.True(mockAssert.WithinDuration(a, b, 10*time.Second), "A 10s difference is within a 10s time difference") assert.True(mockAssert.WithinDuration(b, a, 10*time.Second), "A 10s difference is within a 10s time difference") assert.False(mockAssert.WithinDuration(a, b, 9*time.Second), "A 10s difference is not within a 9s time difference") assert.False(mockAssert.WithinDuration(b, a, 9*time.Second), "A 10s difference is not within a 9s time difference") assert.False(mockAssert.WithinDuration(a, b, -9*time.Second), "A 10s difference is not within a 9s time difference") assert.False(mockAssert.WithinDuration(b, a, -9*time.Second), "A 10s difference is not within a 9s time difference") assert.False(mockAssert.WithinDuration(a, b, -11*time.Second), "A 10s difference is not within a 9s time difference") assert.False(mockAssert.WithinDuration(b, a, -11*time.Second), "A 10s difference is not within a 9s time difference") } func TestInDeltaWrapper(t *testing.T) { assert := New(new(testing.T)) True(t, assert.InDelta(1.001, 1, 0.01), "|1.001 - 1| <= 0.01") True(t, assert.InDelta(1, 1.001, 0.01), "|1 - 1.001| <= 0.01") True(t, assert.InDelta(1, 2, 1), "|1 - 2| <= 1") False(t, assert.InDelta(1, 2, 0.5), "Expected |1 - 2| <= 0.5 to fail") False(t, assert.InDelta(2, 1, 0.5), "Expected |2 - 1| <= 0.5 to fail") False(t, assert.InDelta("", nil, 1), "Expected non numerals to fail") cases := []struct { a, b interface{} delta float64 }{ {uint8(2), uint8(1), 1}, {uint16(2), uint16(1), 1}, {uint32(2), uint32(1), 1}, {uint64(2), uint64(1), 1}, {int(2), int(1), 1}, {int8(2), int8(1), 1}, {int16(2), int16(1), 1}, {int32(2), int32(1), 1}, {int64(2), int64(1), 1}, {float32(2), float32(1), 1}, {float64(2), float64(1), 1}, } for _, tc := range cases { True(t, assert.InDelta(tc.a, tc.b, tc.delta), "Expected |%V - %V| <= %v", tc.a, tc.b, tc.delta) } } func TestInEpsilonWrapper(t *testing.T) { assert := New(new(testing.T)) cases := []struct { a, b interface{} epsilon float64 }{ {uint8(2), uint16(2), .001}, {2.1, 2.2, 0.1}, {2.2, 2.1, 0.1}, {-2.1, -2.2, 0.1}, {-2.2, -2.1, 0.1}, {uint64(100), uint8(101), 0.01}, {0.1, -0.1, 2}, } for _, tc := range cases { True(t, assert.InEpsilon(tc.a, tc.b, tc.epsilon, "Expected %V and %V to have a relative difference of %v", tc.a, tc.b, tc.epsilon)) } cases = []struct { a, b interface{} epsilon float64 }{ {uint8(2), int16(-2), .001}, {uint64(100), uint8(102), 0.01}, {2.1, 2.2, 0.001}, {2.2, 2.1, 0.001}, {2.1, -2.2, 1}, {2.1, "bla-bla", 0}, {0.1, -0.1, 1.99}, } for _, tc := range cases { False(t, assert.InEpsilon(tc.a, tc.b, tc.epsilon, "Expected %V and %V to have a relative difference of %v", tc.a, tc.b, tc.epsilon)) } } func TestRegexpWrapper(t *testing.T) { assert := New(new(testing.T)) cases := []struct { rx, str string }{ {"^start", "start of the line"}, {"end$", "in the end"}, {"[0-9]{3}[.-]?[0-9]{2}[.-]?[0-9]{2}", "My phone number is 650.12.34"}, } for _, tc := range cases { True(t, assert.Regexp(tc.rx, tc.str)) True(t, assert.Regexp(regexp.MustCompile(tc.rx), tc.str)) False(t, assert.NotRegexp(tc.rx, tc.str)) False(t, assert.NotRegexp(regexp.MustCompile(tc.rx), tc.str)) } cases = []struct { rx, str string }{ {"^asdfastart", "Not the start of the line"}, {"end$", "in the end."}, {"[0-9]{3}[.-]?[0-9]{2}[.-]?[0-9]{2}", "My phone number is 650.12a.34"}, } for _, tc := range cases { False(t, assert.Regexp(tc.rx, tc.str), "Expected \"%s\" to not match \"%s\"", tc.rx, tc.str) False(t, assert.Regexp(regexp.MustCompile(tc.rx), tc.str)) True(t, assert.NotRegexp(tc.rx, tc.str)) True(t, assert.NotRegexp(regexp.MustCompile(tc.rx), tc.str)) } } func TestZeroWrapper(t *testing.T) { assert := New(t) mockAssert := New(new(testing.T)) for _, test := range zeros { assert.True(mockAssert.Zero(test), "Zero should return true for %v", test) } for _, test := range nonZeros { assert.False(mockAssert.Zero(test), "Zero should return false for %v", test) } } func TestNotZeroWrapper(t *testing.T) { assert := New(t) mockAssert := New(new(testing.T)) for _, test := range zeros { assert.False(mockAssert.NotZero(test), "Zero should return true for %v", test) } for _, test := range nonZeros { assert.True(mockAssert.NotZero(test), "Zero should return false for %v", test) } } func TestJSONEqWrapper_EqualSONString(t *testing.T) { assert := New(new(testing.T)) if !assert.JSONEq(`{"hello": "world", "foo": "bar"}`, `{"hello": "world", "foo": "bar"}`) { t.Error("JSONEq should return true") } } func TestJSONEqWrapper_EquivalentButNotEqual(t *testing.T) { assert := New(new(testing.T)) if !assert.JSONEq(`{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`) { t.Error("JSONEq should return true") } } func TestJSONEqWrapper_HashOfArraysAndHashes(t *testing.T) { assert := New(new(testing.T)) if !assert.JSONEq("{\r\n\t\"numeric\": 1.5,\r\n\t\"array\": [{\"foo\": \"bar\"}, 1, \"string\", [\"nested\", \"array\", 5.5]],\r\n\t\"hash\": {\"nested\": \"hash\", \"nested_slice\": [\"this\", \"is\", \"nested\"]},\r\n\t\"string\": \"foo\"\r\n}", "{\r\n\t\"numeric\": 1.5,\r\n\t\"hash\": {\"nested\": \"hash\", \"nested_slice\": [\"this\", \"is\", \"nested\"]},\r\n\t\"string\": \"foo\",\r\n\t\"array\": [{\"foo\": \"bar\"}, 1, \"string\", [\"nested\", \"array\", 5.5]]\r\n}") { t.Error("JSONEq should return true") } } func TestJSONEqWrapper_Array(t *testing.T) { assert := New(new(testing.T)) if !assert.JSONEq(`["foo", {"hello": "world", "nested": "hash"}]`, `["foo", {"nested": "hash", "hello": "world"}]`) { t.Error("JSONEq should return true") } } func TestJSONEqWrapper_HashAndArrayNotEquivalent(t *testing.T) { assert := New(new(testing.T)) if assert.JSONEq(`["foo", {"hello": "world", "nested": "hash"}]`, `{"foo": "bar", {"nested": "hash", "hello": "world"}}`) { t.Error("JSONEq should return false") } } func TestJSONEqWrapper_HashesNotEquivalent(t *testing.T) { assert := New(new(testing.T)) if assert.JSONEq(`{"foo": "bar"}`, `{"foo": "bar", "hello": "world"}`) { t.Error("JSONEq should return false") } } func TestJSONEqWrapper_ActualIsNotJSON(t *testing.T) { assert := New(new(testing.T)) if assert.JSONEq(`{"foo": "bar"}`, "Not JSON") { t.Error("JSONEq should return false") } } func TestJSONEqWrapper_ExpectedIsNotJSON(t *testing.T) { assert := New(new(testing.T)) if assert.JSONEq("Not JSON", `{"foo": "bar", "hello": "world"}`) { t.Error("JSONEq should return false") } } func TestJSONEqWrapper_ExpectedAndActualNotJSON(t *testing.T) { assert := New(new(testing.T)) if assert.JSONEq("Not JSON", "Not JSON") { t.Error("JSONEq should return false") } } func TestJSONEqWrapper_ArraysOfDifferentOrder(t *testing.T) { assert := New(new(testing.T)) if assert.JSONEq(`["foo", {"hello": "world", "nested": "hash"}]`, `[{ "hello": "world", "nested": "hash"}, "foo"]`) { t.Error("JSONEq should return false") } } lxd-2.0.0/dist/src/github.com/stretchr/testify/assert/http_assertions_test.go0000644061062106075000000000700512702772371032156 0ustar00stgraberdomain admins00000000000000package assert import ( "fmt" "net/http" "net/url" "testing" ) func httpOK(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) } func httpRedirect(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusTemporaryRedirect) } func httpError(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusInternalServerError) } func TestHTTPStatuses(t *testing.T) { assert := New(t) mockT := new(testing.T) assert.Equal(HTTPSuccess(mockT, httpOK, "GET", "/", nil), true) assert.Equal(HTTPSuccess(mockT, httpRedirect, "GET", "/", nil), false) assert.Equal(HTTPSuccess(mockT, httpError, "GET", "/", nil), false) assert.Equal(HTTPRedirect(mockT, httpOK, "GET", "/", nil), false) assert.Equal(HTTPRedirect(mockT, httpRedirect, "GET", "/", nil), true) assert.Equal(HTTPRedirect(mockT, httpError, "GET", "/", nil), false) assert.Equal(HTTPError(mockT, httpOK, "GET", "/", nil), false) assert.Equal(HTTPError(mockT, httpRedirect, "GET", "/", nil), false) assert.Equal(HTTPError(mockT, httpError, "GET", "/", nil), true) } func TestHTTPStatusesWrapper(t *testing.T) { assert := New(t) mockAssert := New(new(testing.T)) assert.Equal(mockAssert.HTTPSuccess(httpOK, "GET", "/", nil), true) assert.Equal(mockAssert.HTTPSuccess(httpRedirect, "GET", "/", nil), false) assert.Equal(mockAssert.HTTPSuccess(httpError, "GET", "/", nil), false) assert.Equal(mockAssert.HTTPRedirect(httpOK, "GET", "/", nil), false) assert.Equal(mockAssert.HTTPRedirect(httpRedirect, "GET", "/", nil), true) assert.Equal(mockAssert.HTTPRedirect(httpError, "GET", "/", nil), false) assert.Equal(mockAssert.HTTPError(httpOK, "GET", "/", nil), false) assert.Equal(mockAssert.HTTPError(httpRedirect, "GET", "/", nil), false) assert.Equal(mockAssert.HTTPError(httpError, "GET", "/", nil), true) } func httpHelloName(w http.ResponseWriter, r *http.Request) { name := r.FormValue("name") w.Write([]byte(fmt.Sprintf("Hello, %s!", name))) } func TestHttpBody(t *testing.T) { assert := New(t) mockT := new(testing.T) assert.True(HTTPBodyContains(mockT, httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "Hello, World!")) assert.True(HTTPBodyContains(mockT, httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "World")) assert.False(HTTPBodyContains(mockT, httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "world")) assert.False(HTTPBodyNotContains(mockT, httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "Hello, World!")) assert.False(HTTPBodyNotContains(mockT, httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "World")) assert.True(HTTPBodyNotContains(mockT, httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "world")) } func TestHttpBodyWrappers(t *testing.T) { assert := New(t) mockAssert := New(new(testing.T)) assert.True(mockAssert.HTTPBodyContains(httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "Hello, World!")) assert.True(mockAssert.HTTPBodyContains(httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "World")) assert.False(mockAssert.HTTPBodyContains(httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "world")) assert.False(mockAssert.HTTPBodyNotContains(httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "Hello, World!")) assert.False(mockAssert.HTTPBodyNotContains(httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "World")) assert.True(mockAssert.HTTPBodyNotContains(httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "world")) } lxd-2.0.0/dist/src/github.com/stretchr/testify/assert/assertion_forward.go0000644061062106075000000003316312702772371031425 0ustar00stgraberdomain admins00000000000000/* * CODE GENERATED AUTOMATICALLY WITH github.com/stretchr/testify/_codegen * THIS FILE MUST NOT BE EDITED BY HAND */ package assert import ( http "net/http" url "net/url" time "time" ) // Condition uses a Comparison to assert a complex condition. func (a *Assertions) Condition(comp Comparison, msgAndArgs ...interface{}) bool { return Condition(a.t, comp, msgAndArgs...) } // Contains asserts that the specified string, list(array, slice...) or map contains the // specified substring or element. // // a.Contains("Hello World", "World", "But 'Hello World' does contain 'World'") // a.Contains(["Hello", "World"], "World", "But ["Hello", "World"] does contain 'World'") // a.Contains({"Hello": "World"}, "Hello", "But {'Hello': 'World'} does contain 'Hello'") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) Contains(s interface{}, contains interface{}, msgAndArgs ...interface{}) bool { return Contains(a.t, s, contains, msgAndArgs...) } // Empty asserts that the specified object is empty. I.e. nil, "", false, 0 or either // a slice or a channel with len == 0. // // a.Empty(obj) // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) Empty(object interface{}, msgAndArgs ...interface{}) bool { return Empty(a.t, object, msgAndArgs...) } // Equal asserts that two objects are equal. // // a.Equal(123, 123, "123 and 123 should be equal") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) Equal(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool { return Equal(a.t, expected, actual, msgAndArgs...) } // EqualError asserts that a function returned an error (i.e. not `nil`) // and that it is equal to the provided error. // // actualObj, err := SomeFunction() // if assert.Error(t, err, "An error was expected") { // assert.Equal(t, err, expectedError) // } // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) EqualError(theError error, errString string, msgAndArgs ...interface{}) bool { return EqualError(a.t, theError, errString, msgAndArgs...) } // EqualValues asserts that two objects are equal or convertable to the same types // and equal. // // a.EqualValues(uint32(123), int32(123), "123 and 123 should be equal") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) EqualValues(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool { return EqualValues(a.t, expected, actual, msgAndArgs...) } // Error asserts that a function returned an error (i.e. not `nil`). // // actualObj, err := SomeFunction() // if a.Error(err, "An error was expected") { // assert.Equal(t, err, expectedError) // } // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) Error(err error, msgAndArgs ...interface{}) bool { return Error(a.t, err, msgAndArgs...) } // Exactly asserts that two objects are equal is value and type. // // a.Exactly(int32(123), int64(123), "123 and 123 should NOT be equal") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) Exactly(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool { return Exactly(a.t, expected, actual, msgAndArgs...) } // Fail reports a failure through func (a *Assertions) Fail(failureMessage string, msgAndArgs ...interface{}) bool { return Fail(a.t, failureMessage, msgAndArgs...) } // FailNow fails test func (a *Assertions) FailNow(failureMessage string, msgAndArgs ...interface{}) bool { return FailNow(a.t, failureMessage, msgAndArgs...) } // False asserts that the specified value is false. // // a.False(myBool, "myBool should be false") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) False(value bool, msgAndArgs ...interface{}) bool { return False(a.t, value, msgAndArgs...) } // HTTPBodyContains asserts that a specified handler returns a // body that contains a string. // // a.HTTPBodyContains(myHandler, "www.google.com", nil, "I'm Feeling Lucky") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPBodyContains(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}) bool { return HTTPBodyContains(a.t, handler, method, url, values, str) } // HTTPBodyNotContains asserts that a specified handler returns a // body that does not contain a string. // // a.HTTPBodyNotContains(myHandler, "www.google.com", nil, "I'm Feeling Lucky") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPBodyNotContains(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}) bool { return HTTPBodyNotContains(a.t, handler, method, url, values, str) } // HTTPError asserts that a specified handler returns an error status code. // // a.HTTPError(myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}} // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPError(handler http.HandlerFunc, method string, url string, values url.Values) bool { return HTTPError(a.t, handler, method, url, values) } // HTTPRedirect asserts that a specified handler returns a redirect status code. // // a.HTTPRedirect(myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}} // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPRedirect(handler http.HandlerFunc, method string, url string, values url.Values) bool { return HTTPRedirect(a.t, handler, method, url, values) } // HTTPSuccess asserts that a specified handler returns a success status code. // // a.HTTPSuccess(myHandler, "POST", "http://www.google.com", nil) // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPSuccess(handler http.HandlerFunc, method string, url string, values url.Values) bool { return HTTPSuccess(a.t, handler, method, url, values) } // Implements asserts that an object is implemented by the specified interface. // // a.Implements((*MyInterface)(nil), new(MyObject), "MyObject") func (a *Assertions) Implements(interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) bool { return Implements(a.t, interfaceObject, object, msgAndArgs...) } // InDelta asserts that the two numerals are within delta of each other. // // a.InDelta(math.Pi, (22 / 7.0), 0.01) // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) InDelta(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) bool { return InDelta(a.t, expected, actual, delta, msgAndArgs...) } // InDeltaSlice is the same as InDelta, except it compares two slices. func (a *Assertions) InDeltaSlice(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) bool { return InDeltaSlice(a.t, expected, actual, delta, msgAndArgs...) } // InEpsilon asserts that expected and actual have a relative error less than epsilon // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) InEpsilon(expected interface{}, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool { return InEpsilon(a.t, expected, actual, epsilon, msgAndArgs...) } // InEpsilonSlice is the same as InEpsilon, except it compares two slices. func (a *Assertions) InEpsilonSlice(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) bool { return InEpsilonSlice(a.t, expected, actual, delta, msgAndArgs...) } // IsType asserts that the specified objects are of the same type. func (a *Assertions) IsType(expectedType interface{}, object interface{}, msgAndArgs ...interface{}) bool { return IsType(a.t, expectedType, object, msgAndArgs...) } // JSONEq asserts that two JSON strings are equivalent. // // a.JSONEq(`{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`) // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) JSONEq(expected string, actual string, msgAndArgs ...interface{}) bool { return JSONEq(a.t, expected, actual, msgAndArgs...) } // Len asserts that the specified object has specific length. // Len also fails if the object has a type that len() not accept. // // a.Len(mySlice, 3, "The size of slice is not 3") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) Len(object interface{}, length int, msgAndArgs ...interface{}) bool { return Len(a.t, object, length, msgAndArgs...) } // Nil asserts that the specified object is nil. // // a.Nil(err, "err should be nothing") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) Nil(object interface{}, msgAndArgs ...interface{}) bool { return Nil(a.t, object, msgAndArgs...) } // NoError asserts that a function returned no error (i.e. `nil`). // // actualObj, err := SomeFunction() // if a.NoError(err) { // assert.Equal(t, actualObj, expectedObj) // } // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) NoError(err error, msgAndArgs ...interface{}) bool { return NoError(a.t, err, msgAndArgs...) } // NotContains asserts that the specified string, list(array, slice...) or map does NOT contain the // specified substring or element. // // a.NotContains("Hello World", "Earth", "But 'Hello World' does NOT contain 'Earth'") // a.NotContains(["Hello", "World"], "Earth", "But ['Hello', 'World'] does NOT contain 'Earth'") // a.NotContains({"Hello": "World"}, "Earth", "But {'Hello': 'World'} does NOT contain 'Earth'") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) NotContains(s interface{}, contains interface{}, msgAndArgs ...interface{}) bool { return NotContains(a.t, s, contains, msgAndArgs...) } // NotEmpty asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either // a slice or a channel with len == 0. // // if a.NotEmpty(obj) { // assert.Equal(t, "two", obj[1]) // } // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) NotEmpty(object interface{}, msgAndArgs ...interface{}) bool { return NotEmpty(a.t, object, msgAndArgs...) } // NotEqual asserts that the specified values are NOT equal. // // a.NotEqual(obj1, obj2, "two objects shouldn't be equal") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) NotEqual(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool { return NotEqual(a.t, expected, actual, msgAndArgs...) } // NotNil asserts that the specified object is not nil. // // a.NotNil(err, "err should be something") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) NotNil(object interface{}, msgAndArgs ...interface{}) bool { return NotNil(a.t, object, msgAndArgs...) } // NotPanics asserts that the code inside the specified PanicTestFunc does NOT panic. // // a.NotPanics(func(){ // RemainCalm() // }, "Calling RemainCalm() should NOT panic") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) NotPanics(f PanicTestFunc, msgAndArgs ...interface{}) bool { return NotPanics(a.t, f, msgAndArgs...) } // NotRegexp asserts that a specified regexp does not match a string. // // a.NotRegexp(regexp.MustCompile("starts"), "it's starting") // a.NotRegexp("^start", "it's not starting") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) NotRegexp(rx interface{}, str interface{}, msgAndArgs ...interface{}) bool { return NotRegexp(a.t, rx, str, msgAndArgs...) } // NotZero asserts that i is not the zero value for its type and returns the truth. func (a *Assertions) NotZero(i interface{}, msgAndArgs ...interface{}) bool { return NotZero(a.t, i, msgAndArgs...) } // Panics asserts that the code inside the specified PanicTestFunc panics. // // a.Panics(func(){ // GoCrazy() // }, "Calling GoCrazy() should panic") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) Panics(f PanicTestFunc, msgAndArgs ...interface{}) bool { return Panics(a.t, f, msgAndArgs...) } // Regexp asserts that a specified regexp matches a string. // // a.Regexp(regexp.MustCompile("start"), "it's starting") // a.Regexp("start...$", "it's not starting") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) Regexp(rx interface{}, str interface{}, msgAndArgs ...interface{}) bool { return Regexp(a.t, rx, str, msgAndArgs...) } // True asserts that the specified value is true. // // a.True(myBool, "myBool should be true") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) True(value bool, msgAndArgs ...interface{}) bool { return True(a.t, value, msgAndArgs...) } // WithinDuration asserts that the two times are within duration delta of each other. // // a.WithinDuration(time.Now(), time.Now(), 10*time.Second, "The difference should not be more than 10s") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) WithinDuration(expected time.Time, actual time.Time, delta time.Duration, msgAndArgs ...interface{}) bool { return WithinDuration(a.t, expected, actual, delta, msgAndArgs...) } // Zero asserts that i is the zero value for its type and returns the truth. func (a *Assertions) Zero(i interface{}, msgAndArgs ...interface{}) bool { return Zero(a.t, i, msgAndArgs...) } lxd-2.0.0/dist/src/github.com/stretchr/testify/assert/http_assertions.go0000644061062106075000000000704112702772371031117 0ustar00stgraberdomain admins00000000000000package assert import ( "fmt" "net/http" "net/http/httptest" "net/url" "strings" ) // httpCode is a helper that returns HTTP code of the response. It returns -1 // if building a new request fails. func httpCode(handler http.HandlerFunc, method, url string, values url.Values) int { w := httptest.NewRecorder() req, err := http.NewRequest(method, url+"?"+values.Encode(), nil) if err != nil { return -1 } handler(w, req) return w.Code } // HTTPSuccess asserts that a specified handler returns a success status code. // // assert.HTTPSuccess(t, myHandler, "POST", "http://www.google.com", nil) // // Returns whether the assertion was successful (true) or not (false). func HTTPSuccess(t TestingT, handler http.HandlerFunc, method, url string, values url.Values) bool { code := httpCode(handler, method, url, values) if code == -1 { return false } return code >= http.StatusOK && code <= http.StatusPartialContent } // HTTPRedirect asserts that a specified handler returns a redirect status code. // // assert.HTTPRedirect(t, myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}} // // Returns whether the assertion was successful (true) or not (false). func HTTPRedirect(t TestingT, handler http.HandlerFunc, method, url string, values url.Values) bool { code := httpCode(handler, method, url, values) if code == -1 { return false } return code >= http.StatusMultipleChoices && code <= http.StatusTemporaryRedirect } // HTTPError asserts that a specified handler returns an error status code. // // assert.HTTPError(t, myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}} // // Returns whether the assertion was successful (true) or not (false). func HTTPError(t TestingT, handler http.HandlerFunc, method, url string, values url.Values) bool { code := httpCode(handler, method, url, values) if code == -1 { return false } return code >= http.StatusBadRequest } // HTTPBody is a helper that returns HTTP body of the response. It returns // empty string if building a new request fails. func HTTPBody(handler http.HandlerFunc, method, url string, values url.Values) string { w := httptest.NewRecorder() req, err := http.NewRequest(method, url+"?"+values.Encode(), nil) if err != nil { return "" } handler(w, req) return w.Body.String() } // HTTPBodyContains asserts that a specified handler returns a // body that contains a string. // // assert.HTTPBodyContains(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky") // // Returns whether the assertion was successful (true) or not (false). func HTTPBodyContains(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, str interface{}) bool { body := HTTPBody(handler, method, url, values) contains := strings.Contains(body, fmt.Sprint(str)) if !contains { Fail(t, fmt.Sprintf("Expected response body for \"%s\" to contain \"%s\" but found \"%s\"", url+"?"+values.Encode(), str, body)) } return contains } // HTTPBodyNotContains asserts that a specified handler returns a // body that does not contain a string. // // assert.HTTPBodyNotContains(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky") // // Returns whether the assertion was successful (true) or not (false). func HTTPBodyNotContains(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, str interface{}) bool { body := HTTPBody(handler, method, url, values) contains := strings.Contains(body, fmt.Sprint(str)) if contains { Fail(t, "Expected response body for %s to NOT contain \"%s\" but found \"%s\"", url+"?"+values.Encode(), str, body) } return !contains } lxd-2.0.0/dist/src/github.com/stretchr/testify/assert/assertions.go0000644061062106075000000006622712702772371030073 0ustar00stgraberdomain admins00000000000000package assert import ( "bufio" "bytes" "encoding/json" "fmt" "math" "reflect" "regexp" "runtime" "strings" "time" "unicode" "unicode/utf8" "github.com/davecgh/go-spew/spew" "github.com/pmezard/go-difflib/difflib" ) // TestingT is an interface wrapper around *testing.T type TestingT interface { Errorf(format string, args ...interface{}) } // Comparison a custom function that returns true on success and false on failure type Comparison func() (success bool) /* Helper functions */ // ObjectsAreEqual determines if two objects are considered equal. // // This function does no assertion of any kind. func ObjectsAreEqual(expected, actual interface{}) bool { if expected == nil || actual == nil { return expected == actual } return reflect.DeepEqual(expected, actual) } // ObjectsAreEqualValues gets whether two objects are equal, or if their // values are equal. func ObjectsAreEqualValues(expected, actual interface{}) bool { if ObjectsAreEqual(expected, actual) { return true } actualType := reflect.TypeOf(actual) if actualType == nil { return false } expectedValue := reflect.ValueOf(expected) if expectedValue.IsValid() && expectedValue.Type().ConvertibleTo(actualType) { // Attempt comparison after type conversion return reflect.DeepEqual(expectedValue.Convert(actualType).Interface(), actual) } return false } /* CallerInfo is necessary because the assert functions use the testing object internally, causing it to print the file:line of the assert method, rather than where the problem actually occured in calling code.*/ // CallerInfo returns an array of strings containing the file and line number // of each stack frame leading from the current test to the assert call that // failed. func CallerInfo() []string { pc := uintptr(0) file := "" line := 0 ok := false name := "" callers := []string{} for i := 0; ; i++ { pc, file, line, ok = runtime.Caller(i) if !ok { return nil } // This is a huge edge case, but it will panic if this is the case, see #180 if file == "" { break } parts := strings.Split(file, "/") dir := parts[len(parts)-2] file = parts[len(parts)-1] if (dir != "assert" && dir != "mock" && dir != "require") || file == "mock_test.go" { callers = append(callers, fmt.Sprintf("%s:%d", file, line)) } f := runtime.FuncForPC(pc) if f == nil { break } name = f.Name() // Drop the package segments := strings.Split(name, ".") name = segments[len(segments)-1] if isTest(name, "Test") || isTest(name, "Benchmark") || isTest(name, "Example") { break } } return callers } // Stolen from the `go test` tool. // isTest tells whether name looks like a test (or benchmark, according to prefix). // It is a Test (say) if there is a character after Test that is not a lower-case letter. // We don't want TesticularCancer. func isTest(name, prefix string) bool { if !strings.HasPrefix(name, prefix) { return false } if len(name) == len(prefix) { // "Test" is ok return true } rune, _ := utf8.DecodeRuneInString(name[len(prefix):]) return !unicode.IsLower(rune) } // getWhitespaceString returns a string that is long enough to overwrite the default // output from the go testing framework. func getWhitespaceString() string { _, file, line, ok := runtime.Caller(1) if !ok { return "" } parts := strings.Split(file, "/") file = parts[len(parts)-1] return strings.Repeat(" ", len(fmt.Sprintf("%s:%d: ", file, line))) } func messageFromMsgAndArgs(msgAndArgs ...interface{}) string { if len(msgAndArgs) == 0 || msgAndArgs == nil { return "" } if len(msgAndArgs) == 1 { return msgAndArgs[0].(string) } if len(msgAndArgs) > 1 { return fmt.Sprintf(msgAndArgs[0].(string), msgAndArgs[1:]...) } return "" } // Indents all lines of the message by appending a number of tabs to each line, in an output format compatible with Go's // test printing (see inner comment for specifics) func indentMessageLines(message string, tabs int) string { outBuf := new(bytes.Buffer) for i, scanner := 0, bufio.NewScanner(strings.NewReader(message)); scanner.Scan(); i++ { if i != 0 { outBuf.WriteRune('\n') } for ii := 0; ii < tabs; ii++ { outBuf.WriteRune('\t') // Bizarrely, all lines except the first need one fewer tabs prepended, so deliberately advance the counter // by 1 prematurely. if ii == 0 && i > 0 { ii++ } } outBuf.WriteString(scanner.Text()) } return outBuf.String() } type failNower interface { FailNow() } // FailNow fails test func FailNow(t TestingT, failureMessage string, msgAndArgs ...interface{}) bool { Fail(t, failureMessage, msgAndArgs...) // We cannot extend TestingT with FailNow() and // maintain backwards compatibility, so we fallback // to panicking when FailNow is not available in // TestingT. // See issue #263 if t, ok := t.(failNower); ok { t.FailNow() } else { panic("test failed and t is missing `FailNow()`") } return false } // Fail reports a failure through func Fail(t TestingT, failureMessage string, msgAndArgs ...interface{}) bool { message := messageFromMsgAndArgs(msgAndArgs...) errorTrace := strings.Join(CallerInfo(), "\n\r\t\t\t") if len(message) > 0 { t.Errorf("\r%s\r\tError Trace:\t%s\n"+ "\r\tError:%s\n"+ "\r\tMessages:\t%s\n\r", getWhitespaceString(), errorTrace, indentMessageLines(failureMessage, 2), message) } else { t.Errorf("\r%s\r\tError Trace:\t%s\n"+ "\r\tError:%s\n\r", getWhitespaceString(), errorTrace, indentMessageLines(failureMessage, 2)) } return false } // Implements asserts that an object is implemented by the specified interface. // // assert.Implements(t, (*MyInterface)(nil), new(MyObject), "MyObject") func Implements(t TestingT, interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) bool { interfaceType := reflect.TypeOf(interfaceObject).Elem() if !reflect.TypeOf(object).Implements(interfaceType) { return Fail(t, fmt.Sprintf("%T must implement %v", object, interfaceType), msgAndArgs...) } return true } // IsType asserts that the specified objects are of the same type. func IsType(t TestingT, expectedType interface{}, object interface{}, msgAndArgs ...interface{}) bool { if !ObjectsAreEqual(reflect.TypeOf(object), reflect.TypeOf(expectedType)) { return Fail(t, fmt.Sprintf("Object expected to be of type %v, but was %v", reflect.TypeOf(expectedType), reflect.TypeOf(object)), msgAndArgs...) } return true } // Equal asserts that two objects are equal. // // assert.Equal(t, 123, 123, "123 and 123 should be equal") // // Returns whether the assertion was successful (true) or not (false). func Equal(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { if !ObjectsAreEqual(expected, actual) { diff := diff(expected, actual) return Fail(t, fmt.Sprintf("Not equal: %#v (expected)\n"+ " != %#v (actual)%s", expected, actual, diff), msgAndArgs...) } return true } // EqualValues asserts that two objects are equal or convertable to the same types // and equal. // // assert.EqualValues(t, uint32(123), int32(123), "123 and 123 should be equal") // // Returns whether the assertion was successful (true) or not (false). func EqualValues(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { if !ObjectsAreEqualValues(expected, actual) { return Fail(t, fmt.Sprintf("Not equal: %#v (expected)\n"+ " != %#v (actual)", expected, actual), msgAndArgs...) } return true } // Exactly asserts that two objects are equal is value and type. // // assert.Exactly(t, int32(123), int64(123), "123 and 123 should NOT be equal") // // Returns whether the assertion was successful (true) or not (false). func Exactly(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { aType := reflect.TypeOf(expected) bType := reflect.TypeOf(actual) if aType != bType { return Fail(t, fmt.Sprintf("Types expected to match exactly\n\r\t%v != %v", aType, bType), msgAndArgs...) } return Equal(t, expected, actual, msgAndArgs...) } // NotNil asserts that the specified object is not nil. // // assert.NotNil(t, err, "err should be something") // // Returns whether the assertion was successful (true) or not (false). func NotNil(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { if !isNil(object) { return true } return Fail(t, "Expected value not to be nil.", msgAndArgs...) } // isNil checks if a specified object is nil or not, without Failing. func isNil(object interface{}) bool { if object == nil { return true } value := reflect.ValueOf(object) kind := value.Kind() if kind >= reflect.Chan && kind <= reflect.Slice && value.IsNil() { return true } return false } // Nil asserts that the specified object is nil. // // assert.Nil(t, err, "err should be nothing") // // Returns whether the assertion was successful (true) or not (false). func Nil(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { if isNil(object) { return true } return Fail(t, fmt.Sprintf("Expected nil, but got: %#v", object), msgAndArgs...) } var numericZeros = []interface{}{ int(0), int8(0), int16(0), int32(0), int64(0), uint(0), uint8(0), uint16(0), uint32(0), uint64(0), float32(0), float64(0), } // isEmpty gets whether the specified object is considered empty or not. func isEmpty(object interface{}) bool { if object == nil { return true } else if object == "" { return true } else if object == false { return true } for _, v := range numericZeros { if object == v { return true } } objValue := reflect.ValueOf(object) switch objValue.Kind() { case reflect.Map: fallthrough case reflect.Slice, reflect.Chan: { return (objValue.Len() == 0) } case reflect.Struct: switch object.(type) { case time.Time: return object.(time.Time).IsZero() } case reflect.Ptr: { if objValue.IsNil() { return true } switch object.(type) { case *time.Time: return object.(*time.Time).IsZero() default: return false } } } return false } // Empty asserts that the specified object is empty. I.e. nil, "", false, 0 or either // a slice or a channel with len == 0. // // assert.Empty(t, obj) // // Returns whether the assertion was successful (true) or not (false). func Empty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { pass := isEmpty(object) if !pass { Fail(t, fmt.Sprintf("Should be empty, but was %v", object), msgAndArgs...) } return pass } // NotEmpty asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either // a slice or a channel with len == 0. // // if assert.NotEmpty(t, obj) { // assert.Equal(t, "two", obj[1]) // } // // Returns whether the assertion was successful (true) or not (false). func NotEmpty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { pass := !isEmpty(object) if !pass { Fail(t, fmt.Sprintf("Should NOT be empty, but was %v", object), msgAndArgs...) } return pass } // getLen try to get length of object. // return (false, 0) if impossible. func getLen(x interface{}) (ok bool, length int) { v := reflect.ValueOf(x) defer func() { if e := recover(); e != nil { ok = false } }() return true, v.Len() } // Len asserts that the specified object has specific length. // Len also fails if the object has a type that len() not accept. // // assert.Len(t, mySlice, 3, "The size of slice is not 3") // // Returns whether the assertion was successful (true) or not (false). func Len(t TestingT, object interface{}, length int, msgAndArgs ...interface{}) bool { ok, l := getLen(object) if !ok { return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", object), msgAndArgs...) } if l != length { return Fail(t, fmt.Sprintf("\"%s\" should have %d item(s), but has %d", object, length, l), msgAndArgs...) } return true } // True asserts that the specified value is true. // // assert.True(t, myBool, "myBool should be true") // // Returns whether the assertion was successful (true) or not (false). func True(t TestingT, value bool, msgAndArgs ...interface{}) bool { if value != true { return Fail(t, "Should be true", msgAndArgs...) } return true } // False asserts that the specified value is false. // // assert.False(t, myBool, "myBool should be false") // // Returns whether the assertion was successful (true) or not (false). func False(t TestingT, value bool, msgAndArgs ...interface{}) bool { if value != false { return Fail(t, "Should be false", msgAndArgs...) } return true } // NotEqual asserts that the specified values are NOT equal. // // assert.NotEqual(t, obj1, obj2, "two objects shouldn't be equal") // // Returns whether the assertion was successful (true) or not (false). func NotEqual(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { if ObjectsAreEqual(expected, actual) { return Fail(t, fmt.Sprintf("Should not be: %#v\n", actual), msgAndArgs...) } return true } // containsElement try loop over the list check if the list includes the element. // return (false, false) if impossible. // return (true, false) if element was not found. // return (true, true) if element was found. func includeElement(list interface{}, element interface{}) (ok, found bool) { listValue := reflect.ValueOf(list) elementValue := reflect.ValueOf(element) defer func() { if e := recover(); e != nil { ok = false found = false } }() if reflect.TypeOf(list).Kind() == reflect.String { return true, strings.Contains(listValue.String(), elementValue.String()) } if reflect.TypeOf(list).Kind() == reflect.Map { mapKeys := listValue.MapKeys() for i := 0; i < len(mapKeys); i++ { if ObjectsAreEqual(mapKeys[i].Interface(), element) { return true, true } } return true, false } for i := 0; i < listValue.Len(); i++ { if ObjectsAreEqual(listValue.Index(i).Interface(), element) { return true, true } } return true, false } // Contains asserts that the specified string, list(array, slice...) or map contains the // specified substring or element. // // assert.Contains(t, "Hello World", "World", "But 'Hello World' does contain 'World'") // assert.Contains(t, ["Hello", "World"], "World", "But ["Hello", "World"] does contain 'World'") // assert.Contains(t, {"Hello": "World"}, "Hello", "But {'Hello': 'World'} does contain 'Hello'") // // Returns whether the assertion was successful (true) or not (false). func Contains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) bool { ok, found := includeElement(s, contains) if !ok { return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", s), msgAndArgs...) } if !found { return Fail(t, fmt.Sprintf("\"%s\" does not contain \"%s\"", s, contains), msgAndArgs...) } return true } // NotContains asserts that the specified string, list(array, slice...) or map does NOT contain the // specified substring or element. // // assert.NotContains(t, "Hello World", "Earth", "But 'Hello World' does NOT contain 'Earth'") // assert.NotContains(t, ["Hello", "World"], "Earth", "But ['Hello', 'World'] does NOT contain 'Earth'") // assert.NotContains(t, {"Hello": "World"}, "Earth", "But {'Hello': 'World'} does NOT contain 'Earth'") // // Returns whether the assertion was successful (true) or not (false). func NotContains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) bool { ok, found := includeElement(s, contains) if !ok { return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", s), msgAndArgs...) } if found { return Fail(t, fmt.Sprintf("\"%s\" should not contain \"%s\"", s, contains), msgAndArgs...) } return true } // Condition uses a Comparison to assert a complex condition. func Condition(t TestingT, comp Comparison, msgAndArgs ...interface{}) bool { result := comp() if !result { Fail(t, "Condition failed!", msgAndArgs...) } return result } // PanicTestFunc defines a func that should be passed to the assert.Panics and assert.NotPanics // methods, and represents a simple func that takes no arguments, and returns nothing. type PanicTestFunc func() // didPanic returns true if the function passed to it panics. Otherwise, it returns false. func didPanic(f PanicTestFunc) (bool, interface{}) { didPanic := false var message interface{} func() { defer func() { if message = recover(); message != nil { didPanic = true } }() // call the target function f() }() return didPanic, message } // Panics asserts that the code inside the specified PanicTestFunc panics. // // assert.Panics(t, func(){ // GoCrazy() // }, "Calling GoCrazy() should panic") // // Returns whether the assertion was successful (true) or not (false). func Panics(t TestingT, f PanicTestFunc, msgAndArgs ...interface{}) bool { if funcDidPanic, panicValue := didPanic(f); !funcDidPanic { return Fail(t, fmt.Sprintf("func %#v should panic\n\r\tPanic value:\t%v", f, panicValue), msgAndArgs...) } return true } // NotPanics asserts that the code inside the specified PanicTestFunc does NOT panic. // // assert.NotPanics(t, func(){ // RemainCalm() // }, "Calling RemainCalm() should NOT panic") // // Returns whether the assertion was successful (true) or not (false). func NotPanics(t TestingT, f PanicTestFunc, msgAndArgs ...interface{}) bool { if funcDidPanic, panicValue := didPanic(f); funcDidPanic { return Fail(t, fmt.Sprintf("func %#v should not panic\n\r\tPanic value:\t%v", f, panicValue), msgAndArgs...) } return true } // WithinDuration asserts that the two times are within duration delta of each other. // // assert.WithinDuration(t, time.Now(), time.Now(), 10*time.Second, "The difference should not be more than 10s") // // Returns whether the assertion was successful (true) or not (false). func WithinDuration(t TestingT, expected, actual time.Time, delta time.Duration, msgAndArgs ...interface{}) bool { dt := expected.Sub(actual) if dt < -delta || dt > delta { return Fail(t, fmt.Sprintf("Max difference between %v and %v allowed is %v, but difference was %v", expected, actual, delta, dt), msgAndArgs...) } return true } func toFloat(x interface{}) (float64, bool) { var xf float64 xok := true switch xn := x.(type) { case uint8: xf = float64(xn) case uint16: xf = float64(xn) case uint32: xf = float64(xn) case uint64: xf = float64(xn) case int: xf = float64(xn) case int8: xf = float64(xn) case int16: xf = float64(xn) case int32: xf = float64(xn) case int64: xf = float64(xn) case float32: xf = float64(xn) case float64: xf = float64(xn) default: xok = false } return xf, xok } // InDelta asserts that the two numerals are within delta of each other. // // assert.InDelta(t, math.Pi, (22 / 7.0), 0.01) // // Returns whether the assertion was successful (true) or not (false). func InDelta(t TestingT, expected, actual interface{}, delta float64, msgAndArgs ...interface{}) bool { af, aok := toFloat(expected) bf, bok := toFloat(actual) if !aok || !bok { return Fail(t, fmt.Sprintf("Parameters must be numerical"), msgAndArgs...) } if math.IsNaN(af) { return Fail(t, fmt.Sprintf("Actual must not be NaN"), msgAndArgs...) } if math.IsNaN(bf) { return Fail(t, fmt.Sprintf("Expected %v with delta %v, but was NaN", expected, delta), msgAndArgs...) } dt := af - bf if dt < -delta || dt > delta { return Fail(t, fmt.Sprintf("Max difference between %v and %v allowed is %v, but difference was %v", expected, actual, delta, dt), msgAndArgs...) } return true } // InDeltaSlice is the same as InDelta, except it compares two slices. func InDeltaSlice(t TestingT, expected, actual interface{}, delta float64, msgAndArgs ...interface{}) bool { if expected == nil || actual == nil || reflect.TypeOf(actual).Kind() != reflect.Slice || reflect.TypeOf(expected).Kind() != reflect.Slice { return Fail(t, fmt.Sprintf("Parameters must be slice"), msgAndArgs...) } actualSlice := reflect.ValueOf(actual) expectedSlice := reflect.ValueOf(expected) for i := 0; i < actualSlice.Len(); i++ { result := InDelta(t, actualSlice.Index(i).Interface(), expectedSlice.Index(i).Interface(), delta) if !result { return result } } return true } func calcRelativeError(expected, actual interface{}) (float64, error) { af, aok := toFloat(expected) if !aok { return 0, fmt.Errorf("expected value %q cannot be converted to float", expected) } if af == 0 { return 0, fmt.Errorf("expected value must have a value other than zero to calculate the relative error") } bf, bok := toFloat(actual) if !bok { return 0, fmt.Errorf("expected value %q cannot be converted to float", actual) } return math.Abs(af-bf) / math.Abs(af), nil } // InEpsilon asserts that expected and actual have a relative error less than epsilon // // Returns whether the assertion was successful (true) or not (false). func InEpsilon(t TestingT, expected, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool { actualEpsilon, err := calcRelativeError(expected, actual) if err != nil { return Fail(t, err.Error(), msgAndArgs...) } if actualEpsilon > epsilon { return Fail(t, fmt.Sprintf("Relative error is too high: %#v (expected)\n"+ " < %#v (actual)", actualEpsilon, epsilon), msgAndArgs...) } return true } // InEpsilonSlice is the same as InEpsilon, except it compares each value from two slices. func InEpsilonSlice(t TestingT, expected, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool { if expected == nil || actual == nil || reflect.TypeOf(actual).Kind() != reflect.Slice || reflect.TypeOf(expected).Kind() != reflect.Slice { return Fail(t, fmt.Sprintf("Parameters must be slice"), msgAndArgs...) } actualSlice := reflect.ValueOf(actual) expectedSlice := reflect.ValueOf(expected) for i := 0; i < actualSlice.Len(); i++ { result := InEpsilon(t, actualSlice.Index(i).Interface(), expectedSlice.Index(i).Interface(), epsilon) if !result { return result } } return true } /* Errors */ // NoError asserts that a function returned no error (i.e. `nil`). // // actualObj, err := SomeFunction() // if assert.NoError(t, err) { // assert.Equal(t, actualObj, expectedObj) // } // // Returns whether the assertion was successful (true) or not (false). func NoError(t TestingT, err error, msgAndArgs ...interface{}) bool { if isNil(err) { return true } return Fail(t, fmt.Sprintf("Received unexpected error %q", err), msgAndArgs...) } // Error asserts that a function returned an error (i.e. not `nil`). // // actualObj, err := SomeFunction() // if assert.Error(t, err, "An error was expected") { // assert.Equal(t, err, expectedError) // } // // Returns whether the assertion was successful (true) or not (false). func Error(t TestingT, err error, msgAndArgs ...interface{}) bool { message := messageFromMsgAndArgs(msgAndArgs...) return NotNil(t, err, "An error is expected but got nil. %s", message) } // EqualError asserts that a function returned an error (i.e. not `nil`) // and that it is equal to the provided error. // // actualObj, err := SomeFunction() // if assert.Error(t, err, "An error was expected") { // assert.Equal(t, err, expectedError) // } // // Returns whether the assertion was successful (true) or not (false). func EqualError(t TestingT, theError error, errString string, msgAndArgs ...interface{}) bool { message := messageFromMsgAndArgs(msgAndArgs...) if !NotNil(t, theError, "An error is expected but got nil. %s", message) { return false } s := "An error with value \"%s\" is expected but got \"%s\". %s" return Equal(t, errString, theError.Error(), s, errString, theError.Error(), message) } // matchRegexp return true if a specified regexp matches a string. func matchRegexp(rx interface{}, str interface{}) bool { var r *regexp.Regexp if rr, ok := rx.(*regexp.Regexp); ok { r = rr } else { r = regexp.MustCompile(fmt.Sprint(rx)) } return (r.FindStringIndex(fmt.Sprint(str)) != nil) } // Regexp asserts that a specified regexp matches a string. // // assert.Regexp(t, regexp.MustCompile("start"), "it's starting") // assert.Regexp(t, "start...$", "it's not starting") // // Returns whether the assertion was successful (true) or not (false). func Regexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interface{}) bool { match := matchRegexp(rx, str) if !match { Fail(t, fmt.Sprintf("Expect \"%v\" to match \"%v\"", str, rx), msgAndArgs...) } return match } // NotRegexp asserts that a specified regexp does not match a string. // // assert.NotRegexp(t, regexp.MustCompile("starts"), "it's starting") // assert.NotRegexp(t, "^start", "it's not starting") // // Returns whether the assertion was successful (true) or not (false). func NotRegexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interface{}) bool { match := matchRegexp(rx, str) if match { Fail(t, fmt.Sprintf("Expect \"%v\" to NOT match \"%v\"", str, rx), msgAndArgs...) } return !match } // Zero asserts that i is the zero value for its type and returns the truth. func Zero(t TestingT, i interface{}, msgAndArgs ...interface{}) bool { if i != nil && !reflect.DeepEqual(i, reflect.Zero(reflect.TypeOf(i)).Interface()) { return Fail(t, fmt.Sprintf("Should be zero, but was %v", i), msgAndArgs...) } return true } // NotZero asserts that i is not the zero value for its type and returns the truth. func NotZero(t TestingT, i interface{}, msgAndArgs ...interface{}) bool { if i == nil || reflect.DeepEqual(i, reflect.Zero(reflect.TypeOf(i)).Interface()) { return Fail(t, fmt.Sprintf("Should not be zero, but was %v", i), msgAndArgs...) } return true } // JSONEq asserts that two JSON strings are equivalent. // // assert.JSONEq(t, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`) // // Returns whether the assertion was successful (true) or not (false). func JSONEq(t TestingT, expected string, actual string, msgAndArgs ...interface{}) bool { var expectedJSONAsInterface, actualJSONAsInterface interface{} if err := json.Unmarshal([]byte(expected), &expectedJSONAsInterface); err != nil { return Fail(t, fmt.Sprintf("Expected value ('%s') is not valid json.\nJSON parsing error: '%s'", expected, err.Error()), msgAndArgs...) } if err := json.Unmarshal([]byte(actual), &actualJSONAsInterface); err != nil { return Fail(t, fmt.Sprintf("Input ('%s') needs to be valid json.\nJSON parsing error: '%s'", actual, err.Error()), msgAndArgs...) } return Equal(t, expectedJSONAsInterface, actualJSONAsInterface, msgAndArgs...) } func typeAndKind(v interface{}) (reflect.Type, reflect.Kind) { t := reflect.TypeOf(v) k := t.Kind() if k == reflect.Ptr { t = t.Elem() k = t.Kind() } return t, k } // diff returns a diff of both values as long as both are of the same type and // are a struct, map, slice or array. Otherwise it returns an empty string. func diff(expected interface{}, actual interface{}) string { if expected == nil || actual == nil { return "" } et, ek := typeAndKind(expected) at, _ := typeAndKind(actual) if et != at { return "" } if ek != reflect.Struct && ek != reflect.Map && ek != reflect.Slice && ek != reflect.Array { return "" } spew.Config.SortKeys = true e := spew.Sdump(expected) a := spew.Sdump(actual) diff, _ := difflib.GetUnifiedDiffString(difflib.UnifiedDiff{ A: difflib.SplitLines(e), B: difflib.SplitLines(a), FromFile: "Expected", FromDate: "", ToFile: "Actual", ToDate: "", Context: 1, }) return "\n\nDiff:\n" + diff } lxd-2.0.0/dist/src/github.com/stretchr/testify/assert/assertions_test.go0000644061062106075000000006667612702772371031142 0ustar00stgraberdomain admins00000000000000package assert import ( "errors" "io" "math" "os" "reflect" "regexp" "testing" "time" ) var ( i interface{} zeros = []interface{}{ false, byte(0), complex64(0), complex128(0), float32(0), float64(0), int(0), int8(0), int16(0), int32(0), int64(0), rune(0), uint(0), uint8(0), uint16(0), uint32(0), uint64(0), uintptr(0), "", [0]interface{}{}, []interface{}(nil), struct{ x int }{}, (*interface{})(nil), (func())(nil), nil, interface{}(nil), map[interface{}]interface{}(nil), (chan interface{})(nil), (<-chan interface{})(nil), (chan<- interface{})(nil), } nonZeros = []interface{}{ true, byte(1), complex64(1), complex128(1), float32(1), float64(1), int(1), int8(1), int16(1), int32(1), int64(1), rune(1), uint(1), uint8(1), uint16(1), uint32(1), uint64(1), uintptr(1), "s", [1]interface{}{1}, []interface{}{}, struct{ x int }{1}, (*interface{})(&i), (func())(func() {}), interface{}(1), map[interface{}]interface{}{}, (chan interface{})(make(chan interface{})), (<-chan interface{})(make(chan interface{})), (chan<- interface{})(make(chan interface{})), } ) // AssertionTesterInterface defines an interface to be used for testing assertion methods type AssertionTesterInterface interface { TestMethod() } // AssertionTesterConformingObject is an object that conforms to the AssertionTesterInterface interface type AssertionTesterConformingObject struct { } func (a *AssertionTesterConformingObject) TestMethod() { } // AssertionTesterNonConformingObject is an object that does not conform to the AssertionTesterInterface interface type AssertionTesterNonConformingObject struct { } func TestObjectsAreEqual(t *testing.T) { if !ObjectsAreEqual("Hello World", "Hello World") { t.Error("objectsAreEqual should return true") } if !ObjectsAreEqual(123, 123) { t.Error("objectsAreEqual should return true") } if !ObjectsAreEqual(123.5, 123.5) { t.Error("objectsAreEqual should return true") } if !ObjectsAreEqual([]byte("Hello World"), []byte("Hello World")) { t.Error("objectsAreEqual should return true") } if !ObjectsAreEqual(nil, nil) { t.Error("objectsAreEqual should return true") } if ObjectsAreEqual(map[int]int{5: 10}, map[int]int{10: 20}) { t.Error("objectsAreEqual should return false") } if ObjectsAreEqual('x', "x") { t.Error("objectsAreEqual should return false") } if ObjectsAreEqual("x", 'x') { t.Error("objectsAreEqual should return false") } if ObjectsAreEqual(0, 0.1) { t.Error("objectsAreEqual should return false") } if ObjectsAreEqual(0.1, 0) { t.Error("objectsAreEqual should return false") } if ObjectsAreEqual(uint32(10), int32(10)) { t.Error("objectsAreEqual should return false") } if !ObjectsAreEqualValues(uint32(10), int32(10)) { t.Error("ObjectsAreEqualValues should return true") } if ObjectsAreEqualValues(0, nil) { t.Fail() } if ObjectsAreEqualValues(nil, 0) { t.Fail() } } func TestImplements(t *testing.T) { mockT := new(testing.T) if !Implements(mockT, (*AssertionTesterInterface)(nil), new(AssertionTesterConformingObject)) { t.Error("Implements method should return true: AssertionTesterConformingObject implements AssertionTesterInterface") } if Implements(mockT, (*AssertionTesterInterface)(nil), new(AssertionTesterNonConformingObject)) { t.Error("Implements method should return false: AssertionTesterNonConformingObject does not implements AssertionTesterInterface") } } func TestIsType(t *testing.T) { mockT := new(testing.T) if !IsType(mockT, new(AssertionTesterConformingObject), new(AssertionTesterConformingObject)) { t.Error("IsType should return true: AssertionTesterConformingObject is the same type as AssertionTesterConformingObject") } if IsType(mockT, new(AssertionTesterConformingObject), new(AssertionTesterNonConformingObject)) { t.Error("IsType should return false: AssertionTesterConformingObject is not the same type as AssertionTesterNonConformingObject") } } func TestEqual(t *testing.T) { mockT := new(testing.T) if !Equal(mockT, "Hello World", "Hello World") { t.Error("Equal should return true") } if !Equal(mockT, 123, 123) { t.Error("Equal should return true") } if !Equal(mockT, 123.5, 123.5) { t.Error("Equal should return true") } if !Equal(mockT, []byte("Hello World"), []byte("Hello World")) { t.Error("Equal should return true") } if !Equal(mockT, nil, nil) { t.Error("Equal should return true") } if !Equal(mockT, int32(123), int32(123)) { t.Error("Equal should return true") } if !Equal(mockT, uint64(123), uint64(123)) { t.Error("Equal should return true") } } func TestNotNil(t *testing.T) { mockT := new(testing.T) if !NotNil(mockT, new(AssertionTesterConformingObject)) { t.Error("NotNil should return true: object is not nil") } if NotNil(mockT, nil) { t.Error("NotNil should return false: object is nil") } if NotNil(mockT, (*struct{})(nil)) { t.Error("NotNil should return false: object is (*struct{})(nil)") } } func TestNil(t *testing.T) { mockT := new(testing.T) if !Nil(mockT, nil) { t.Error("Nil should return true: object is nil") } if !Nil(mockT, (*struct{})(nil)) { t.Error("Nil should return true: object is (*struct{})(nil)") } if Nil(mockT, new(AssertionTesterConformingObject)) { t.Error("Nil should return false: object is not nil") } } func TestTrue(t *testing.T) { mockT := new(testing.T) if !True(mockT, true) { t.Error("True should return true") } if True(mockT, false) { t.Error("True should return false") } } func TestFalse(t *testing.T) { mockT := new(testing.T) if !False(mockT, false) { t.Error("False should return true") } if False(mockT, true) { t.Error("False should return false") } } func TestExactly(t *testing.T) { mockT := new(testing.T) a := float32(1) b := float64(1) c := float32(1) d := float32(2) if Exactly(mockT, a, b) { t.Error("Exactly should return false") } if Exactly(mockT, a, d) { t.Error("Exactly should return false") } if !Exactly(mockT, a, c) { t.Error("Exactly should return true") } if Exactly(mockT, nil, a) { t.Error("Exactly should return false") } if Exactly(mockT, a, nil) { t.Error("Exactly should return false") } } func TestNotEqual(t *testing.T) { mockT := new(testing.T) if !NotEqual(mockT, "Hello World", "Hello World!") { t.Error("NotEqual should return true") } if !NotEqual(mockT, 123, 1234) { t.Error("NotEqual should return true") } if !NotEqual(mockT, 123.5, 123.55) { t.Error("NotEqual should return true") } if !NotEqual(mockT, []byte("Hello World"), []byte("Hello World!")) { t.Error("NotEqual should return true") } if !NotEqual(mockT, nil, new(AssertionTesterConformingObject)) { t.Error("NotEqual should return true") } funcA := func() int { return 23 } funcB := func() int { return 42 } if !NotEqual(mockT, funcA, funcB) { t.Error("NotEqual should return true") } if NotEqual(mockT, "Hello World", "Hello World") { t.Error("NotEqual should return false") } if NotEqual(mockT, 123, 123) { t.Error("NotEqual should return false") } if NotEqual(mockT, 123.5, 123.5) { t.Error("NotEqual should return false") } if NotEqual(mockT, []byte("Hello World"), []byte("Hello World")) { t.Error("NotEqual should return false") } if NotEqual(mockT, new(AssertionTesterConformingObject), new(AssertionTesterConformingObject)) { t.Error("NotEqual should return false") } } type A struct { Name, Value string } func TestContains(t *testing.T) { mockT := new(testing.T) list := []string{"Foo", "Bar"} complexList := []*A{ {"b", "c"}, {"d", "e"}, {"g", "h"}, {"j", "k"}, } simpleMap := map[interface{}]interface{}{"Foo": "Bar"} if !Contains(mockT, "Hello World", "Hello") { t.Error("Contains should return true: \"Hello World\" contains \"Hello\"") } if Contains(mockT, "Hello World", "Salut") { t.Error("Contains should return false: \"Hello World\" does not contain \"Salut\"") } if !Contains(mockT, list, "Bar") { t.Error("Contains should return true: \"[\"Foo\", \"Bar\"]\" contains \"Bar\"") } if Contains(mockT, list, "Salut") { t.Error("Contains should return false: \"[\"Foo\", \"Bar\"]\" does not contain \"Salut\"") } if !Contains(mockT, complexList, &A{"g", "h"}) { t.Error("Contains should return true: complexList contains {\"g\", \"h\"}") } if Contains(mockT, complexList, &A{"g", "e"}) { t.Error("Contains should return false: complexList contains {\"g\", \"e\"}") } if Contains(mockT, complexList, &A{"g", "e"}) { t.Error("Contains should return false: complexList contains {\"g\", \"e\"}") } if !Contains(mockT, simpleMap, "Foo") { t.Error("Contains should return true: \"{\"Foo\": \"Bar\"}\" contains \"Foo\"") } if Contains(mockT, simpleMap, "Bar") { t.Error("Contains should return false: \"{\"Foo\": \"Bar\"}\" does not contains \"Bar\"") } } func TestNotContains(t *testing.T) { mockT := new(testing.T) list := []string{"Foo", "Bar"} simpleMap := map[interface{}]interface{}{"Foo": "Bar"} if !NotContains(mockT, "Hello World", "Hello!") { t.Error("NotContains should return true: \"Hello World\" does not contain \"Hello!\"") } if NotContains(mockT, "Hello World", "Hello") { t.Error("NotContains should return false: \"Hello World\" contains \"Hello\"") } if !NotContains(mockT, list, "Foo!") { t.Error("NotContains should return true: \"[\"Foo\", \"Bar\"]\" does not contain \"Foo!\"") } if NotContains(mockT, list, "Foo") { t.Error("NotContains should return false: \"[\"Foo\", \"Bar\"]\" contains \"Foo\"") } if NotContains(mockT, simpleMap, "Foo") { t.Error("Contains should return true: \"{\"Foo\": \"Bar\"}\" contains \"Foo\"") } if !NotContains(mockT, simpleMap, "Bar") { t.Error("Contains should return false: \"{\"Foo\": \"Bar\"}\" does not contains \"Bar\"") } } func Test_includeElement(t *testing.T) { list1 := []string{"Foo", "Bar"} list2 := []int{1, 2} simpleMap := map[interface{}]interface{}{"Foo": "Bar"} ok, found := includeElement("Hello World", "World") True(t, ok) True(t, found) ok, found = includeElement(list1, "Foo") True(t, ok) True(t, found) ok, found = includeElement(list1, "Bar") True(t, ok) True(t, found) ok, found = includeElement(list2, 1) True(t, ok) True(t, found) ok, found = includeElement(list2, 2) True(t, ok) True(t, found) ok, found = includeElement(list1, "Foo!") True(t, ok) False(t, found) ok, found = includeElement(list2, 3) True(t, ok) False(t, found) ok, found = includeElement(list2, "1") True(t, ok) False(t, found) ok, found = includeElement(simpleMap, "Foo") True(t, ok) True(t, found) ok, found = includeElement(simpleMap, "Bar") True(t, ok) False(t, found) ok, found = includeElement(1433, "1") False(t, ok) False(t, found) } func TestCondition(t *testing.T) { mockT := new(testing.T) if !Condition(mockT, func() bool { return true }, "Truth") { t.Error("Condition should return true") } if Condition(mockT, func() bool { return false }, "Lie") { t.Error("Condition should return false") } } func TestDidPanic(t *testing.T) { if funcDidPanic, _ := didPanic(func() { panic("Panic!") }); !funcDidPanic { t.Error("didPanic should return true") } if funcDidPanic, _ := didPanic(func() { }); funcDidPanic { t.Error("didPanic should return false") } } func TestPanics(t *testing.T) { mockT := new(testing.T) if !Panics(mockT, func() { panic("Panic!") }) { t.Error("Panics should return true") } if Panics(mockT, func() { }) { t.Error("Panics should return false") } } func TestNotPanics(t *testing.T) { mockT := new(testing.T) if !NotPanics(mockT, func() { }) { t.Error("NotPanics should return true") } if NotPanics(mockT, func() { panic("Panic!") }) { t.Error("NotPanics should return false") } } func TestNoError(t *testing.T) { mockT := new(testing.T) // start with a nil error var err error True(t, NoError(mockT, err), "NoError should return True for nil arg") // now set an error err = errors.New("some error") False(t, NoError(mockT, err), "NoError with error should return False") } func TestError(t *testing.T) { mockT := new(testing.T) // start with a nil error var err error False(t, Error(mockT, err), "Error should return False for nil arg") // now set an error err = errors.New("some error") True(t, Error(mockT, err), "Error with error should return True") } func TestEqualError(t *testing.T) { mockT := new(testing.T) // start with a nil error var err error False(t, EqualError(mockT, err, ""), "EqualError should return false for nil arg") // now set an error err = errors.New("some error") False(t, EqualError(mockT, err, "Not some error"), "EqualError should return false for different error string") True(t, EqualError(mockT, err, "some error"), "EqualError should return true") } func Test_isEmpty(t *testing.T) { chWithValue := make(chan struct{}, 1) chWithValue <- struct{}{} True(t, isEmpty("")) True(t, isEmpty(nil)) True(t, isEmpty([]string{})) True(t, isEmpty(0)) True(t, isEmpty(int32(0))) True(t, isEmpty(int64(0))) True(t, isEmpty(false)) True(t, isEmpty(map[string]string{})) True(t, isEmpty(new(time.Time))) True(t, isEmpty(time.Time{})) True(t, isEmpty(make(chan struct{}))) False(t, isEmpty("something")) False(t, isEmpty(errors.New("something"))) False(t, isEmpty([]string{"something"})) False(t, isEmpty(1)) False(t, isEmpty(true)) False(t, isEmpty(map[string]string{"Hello": "World"})) False(t, isEmpty(chWithValue)) } func TestEmpty(t *testing.T) { mockT := new(testing.T) chWithValue := make(chan struct{}, 1) chWithValue <- struct{}{} var tiP *time.Time var tiNP time.Time var s *string var f *os.File True(t, Empty(mockT, ""), "Empty string is empty") True(t, Empty(mockT, nil), "Nil is empty") True(t, Empty(mockT, []string{}), "Empty string array is empty") True(t, Empty(mockT, 0), "Zero int value is empty") True(t, Empty(mockT, false), "False value is empty") True(t, Empty(mockT, make(chan struct{})), "Channel without values is empty") True(t, Empty(mockT, s), "Nil string pointer is empty") True(t, Empty(mockT, f), "Nil os.File pointer is empty") True(t, Empty(mockT, tiP), "Nil time.Time pointer is empty") True(t, Empty(mockT, tiNP), "time.Time is empty") False(t, Empty(mockT, "something"), "Non Empty string is not empty") False(t, Empty(mockT, errors.New("something")), "Non nil object is not empty") False(t, Empty(mockT, []string{"something"}), "Non empty string array is not empty") False(t, Empty(mockT, 1), "Non-zero int value is not empty") False(t, Empty(mockT, true), "True value is not empty") False(t, Empty(mockT, chWithValue), "Channel with values is not empty") } func TestNotEmpty(t *testing.T) { mockT := new(testing.T) chWithValue := make(chan struct{}, 1) chWithValue <- struct{}{} False(t, NotEmpty(mockT, ""), "Empty string is empty") False(t, NotEmpty(mockT, nil), "Nil is empty") False(t, NotEmpty(mockT, []string{}), "Empty string array is empty") False(t, NotEmpty(mockT, 0), "Zero int value is empty") False(t, NotEmpty(mockT, false), "False value is empty") False(t, NotEmpty(mockT, make(chan struct{})), "Channel without values is empty") True(t, NotEmpty(mockT, "something"), "Non Empty string is not empty") True(t, NotEmpty(mockT, errors.New("something")), "Non nil object is not empty") True(t, NotEmpty(mockT, []string{"something"}), "Non empty string array is not empty") True(t, NotEmpty(mockT, 1), "Non-zero int value is not empty") True(t, NotEmpty(mockT, true), "True value is not empty") True(t, NotEmpty(mockT, chWithValue), "Channel with values is not empty") } func Test_getLen(t *testing.T) { falseCases := []interface{}{ nil, 0, true, false, 'A', struct{}{}, } for _, v := range falseCases { ok, l := getLen(v) False(t, ok, "Expected getLen fail to get length of %#v", v) Equal(t, 0, l, "getLen should return 0 for %#v", v) } ch := make(chan int, 5) ch <- 1 ch <- 2 ch <- 3 trueCases := []struct { v interface{} l int }{ {[]int{1, 2, 3}, 3}, {[...]int{1, 2, 3}, 3}, {"ABC", 3}, {map[int]int{1: 2, 2: 4, 3: 6}, 3}, {ch, 3}, {[]int{}, 0}, {map[int]int{}, 0}, {make(chan int), 0}, {[]int(nil), 0}, {map[int]int(nil), 0}, {(chan int)(nil), 0}, } for _, c := range trueCases { ok, l := getLen(c.v) True(t, ok, "Expected getLen success to get length of %#v", c.v) Equal(t, c.l, l) } } func TestLen(t *testing.T) { mockT := new(testing.T) False(t, Len(mockT, nil, 0), "nil does not have length") False(t, Len(mockT, 0, 0), "int does not have length") False(t, Len(mockT, true, 0), "true does not have length") False(t, Len(mockT, false, 0), "false does not have length") False(t, Len(mockT, 'A', 0), "Rune does not have length") False(t, Len(mockT, struct{}{}, 0), "Struct does not have length") ch := make(chan int, 5) ch <- 1 ch <- 2 ch <- 3 cases := []struct { v interface{} l int }{ {[]int{1, 2, 3}, 3}, {[...]int{1, 2, 3}, 3}, {"ABC", 3}, {map[int]int{1: 2, 2: 4, 3: 6}, 3}, {ch, 3}, {[]int{}, 0}, {map[int]int{}, 0}, {make(chan int), 0}, {[]int(nil), 0}, {map[int]int(nil), 0}, {(chan int)(nil), 0}, } for _, c := range cases { True(t, Len(mockT, c.v, c.l), "%#v have %d items", c.v, c.l) } cases = []struct { v interface{} l int }{ {[]int{1, 2, 3}, 4}, {[...]int{1, 2, 3}, 2}, {"ABC", 2}, {map[int]int{1: 2, 2: 4, 3: 6}, 4}, {ch, 2}, {[]int{}, 1}, {map[int]int{}, 1}, {make(chan int), 1}, {[]int(nil), 1}, {map[int]int(nil), 1}, {(chan int)(nil), 1}, } for _, c := range cases { False(t, Len(mockT, c.v, c.l), "%#v have %d items", c.v, c.l) } } func TestWithinDuration(t *testing.T) { mockT := new(testing.T) a := time.Now() b := a.Add(10 * time.Second) True(t, WithinDuration(mockT, a, b, 10*time.Second), "A 10s difference is within a 10s time difference") True(t, WithinDuration(mockT, b, a, 10*time.Second), "A 10s difference is within a 10s time difference") False(t, WithinDuration(mockT, a, b, 9*time.Second), "A 10s difference is not within a 9s time difference") False(t, WithinDuration(mockT, b, a, 9*time.Second), "A 10s difference is not within a 9s time difference") False(t, WithinDuration(mockT, a, b, -9*time.Second), "A 10s difference is not within a 9s time difference") False(t, WithinDuration(mockT, b, a, -9*time.Second), "A 10s difference is not within a 9s time difference") False(t, WithinDuration(mockT, a, b, -11*time.Second), "A 10s difference is not within a 9s time difference") False(t, WithinDuration(mockT, b, a, -11*time.Second), "A 10s difference is not within a 9s time difference") } func TestInDelta(t *testing.T) { mockT := new(testing.T) True(t, InDelta(mockT, 1.001, 1, 0.01), "|1.001 - 1| <= 0.01") True(t, InDelta(mockT, 1, 1.001, 0.01), "|1 - 1.001| <= 0.01") True(t, InDelta(mockT, 1, 2, 1), "|1 - 2| <= 1") False(t, InDelta(mockT, 1, 2, 0.5), "Expected |1 - 2| <= 0.5 to fail") False(t, InDelta(mockT, 2, 1, 0.5), "Expected |2 - 1| <= 0.5 to fail") False(t, InDelta(mockT, "", nil, 1), "Expected non numerals to fail") False(t, InDelta(mockT, 42, math.NaN(), 0.01), "Expected NaN for actual to fail") False(t, InDelta(mockT, math.NaN(), 42, 0.01), "Expected NaN for expected to fail") cases := []struct { a, b interface{} delta float64 }{ {uint8(2), uint8(1), 1}, {uint16(2), uint16(1), 1}, {uint32(2), uint32(1), 1}, {uint64(2), uint64(1), 1}, {int(2), int(1), 1}, {int8(2), int8(1), 1}, {int16(2), int16(1), 1}, {int32(2), int32(1), 1}, {int64(2), int64(1), 1}, {float32(2), float32(1), 1}, {float64(2), float64(1), 1}, } for _, tc := range cases { True(t, InDelta(mockT, tc.a, tc.b, tc.delta), "Expected |%V - %V| <= %v", tc.a, tc.b, tc.delta) } } func TestInDeltaSlice(t *testing.T) { mockT := new(testing.T) True(t, InDeltaSlice(mockT, []float64{1.001, 0.999}, []float64{1, 1}, 0.1), "{1.001, 0.009} is element-wise close to {1, 1} in delta=0.1") True(t, InDeltaSlice(mockT, []float64{1, 2}, []float64{0, 3}, 1), "{1, 2} is element-wise close to {0, 3} in delta=1") False(t, InDeltaSlice(mockT, []float64{1, 2}, []float64{0, 3}, 0.1), "{1, 2} is not element-wise close to {0, 3} in delta=0.1") False(t, InDeltaSlice(mockT, "", nil, 1), "Expected non numeral slices to fail") } func TestInEpsilon(t *testing.T) { mockT := new(testing.T) cases := []struct { a, b interface{} epsilon float64 }{ {uint8(2), uint16(2), .001}, {2.1, 2.2, 0.1}, {2.2, 2.1, 0.1}, {-2.1, -2.2, 0.1}, {-2.2, -2.1, 0.1}, {uint64(100), uint8(101), 0.01}, {0.1, -0.1, 2}, {0.1, 0, 2}, } for _, tc := range cases { True(t, InEpsilon(t, tc.a, tc.b, tc.epsilon, "Expected %V and %V to have a relative difference of %v", tc.a, tc.b, tc.epsilon), "test: %q", tc) } cases = []struct { a, b interface{} epsilon float64 }{ {uint8(2), int16(-2), .001}, {uint64(100), uint8(102), 0.01}, {2.1, 2.2, 0.001}, {2.2, 2.1, 0.001}, {2.1, -2.2, 1}, {2.1, "bla-bla", 0}, {0.1, -0.1, 1.99}, {0, 0.1, 2}, // expected must be different to zero } for _, tc := range cases { False(t, InEpsilon(mockT, tc.a, tc.b, tc.epsilon, "Expected %V and %V to have a relative difference of %v", tc.a, tc.b, tc.epsilon)) } } func TestInEpsilonSlice(t *testing.T) { mockT := new(testing.T) True(t, InEpsilonSlice(mockT, []float64{2.2, 2.0}, []float64{2.1, 2.1}, 0.06), "{2.2, 2.0} is element-wise close to {2.1, 2.1} in espilon=0.06") False(t, InEpsilonSlice(mockT, []float64{2.2, 2.0}, []float64{2.1, 2.1}, 0.04), "{2.2, 2.0} is not element-wise close to {2.1, 2.1} in espilon=0.04") False(t, InEpsilonSlice(mockT, "", nil, 1), "Expected non numeral slices to fail") } func TestRegexp(t *testing.T) { mockT := new(testing.T) cases := []struct { rx, str string }{ {"^start", "start of the line"}, {"end$", "in the end"}, {"[0-9]{3}[.-]?[0-9]{2}[.-]?[0-9]{2}", "My phone number is 650.12.34"}, } for _, tc := range cases { True(t, Regexp(mockT, tc.rx, tc.str)) True(t, Regexp(mockT, regexp.MustCompile(tc.rx), tc.str)) False(t, NotRegexp(mockT, tc.rx, tc.str)) False(t, NotRegexp(mockT, regexp.MustCompile(tc.rx), tc.str)) } cases = []struct { rx, str string }{ {"^asdfastart", "Not the start of the line"}, {"end$", "in the end."}, {"[0-9]{3}[.-]?[0-9]{2}[.-]?[0-9]{2}", "My phone number is 650.12a.34"}, } for _, tc := range cases { False(t, Regexp(mockT, tc.rx, tc.str), "Expected \"%s\" to not match \"%s\"", tc.rx, tc.str) False(t, Regexp(mockT, regexp.MustCompile(tc.rx), tc.str)) True(t, NotRegexp(mockT, tc.rx, tc.str)) True(t, NotRegexp(mockT, regexp.MustCompile(tc.rx), tc.str)) } } func testAutogeneratedFunction() { defer func() { if err := recover(); err == nil { panic("did not panic") } CallerInfo() }() t := struct { io.Closer }{} var c io.Closer c = t c.Close() } func TestCallerInfoWithAutogeneratedFunctions(t *testing.T) { NotPanics(t, func() { testAutogeneratedFunction() }) } func TestZero(t *testing.T) { mockT := new(testing.T) for _, test := range zeros { True(t, Zero(mockT, test, "%#v is not the %v zero value", test, reflect.TypeOf(test))) } for _, test := range nonZeros { False(t, Zero(mockT, test, "%#v is not the %v zero value", test, reflect.TypeOf(test))) } } func TestNotZero(t *testing.T) { mockT := new(testing.T) for _, test := range zeros { False(t, NotZero(mockT, test, "%#v is not the %v zero value", test, reflect.TypeOf(test))) } for _, test := range nonZeros { True(t, NotZero(mockT, test, "%#v is not the %v zero value", test, reflect.TypeOf(test))) } } func TestJSONEq_EqualSONString(t *testing.T) { mockT := new(testing.T) True(t, JSONEq(mockT, `{"hello": "world", "foo": "bar"}`, `{"hello": "world", "foo": "bar"}`)) } func TestJSONEq_EquivalentButNotEqual(t *testing.T) { mockT := new(testing.T) True(t, JSONEq(mockT, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`)) } func TestJSONEq_HashOfArraysAndHashes(t *testing.T) { mockT := new(testing.T) True(t, JSONEq(mockT, "{\r\n\t\"numeric\": 1.5,\r\n\t\"array\": [{\"foo\": \"bar\"}, 1, \"string\", [\"nested\", \"array\", 5.5]],\r\n\t\"hash\": {\"nested\": \"hash\", \"nested_slice\": [\"this\", \"is\", \"nested\"]},\r\n\t\"string\": \"foo\"\r\n}", "{\r\n\t\"numeric\": 1.5,\r\n\t\"hash\": {\"nested\": \"hash\", \"nested_slice\": [\"this\", \"is\", \"nested\"]},\r\n\t\"string\": \"foo\",\r\n\t\"array\": [{\"foo\": \"bar\"}, 1, \"string\", [\"nested\", \"array\", 5.5]]\r\n}")) } func TestJSONEq_Array(t *testing.T) { mockT := new(testing.T) True(t, JSONEq(mockT, `["foo", {"hello": "world", "nested": "hash"}]`, `["foo", {"nested": "hash", "hello": "world"}]`)) } func TestJSONEq_HashAndArrayNotEquivalent(t *testing.T) { mockT := new(testing.T) False(t, JSONEq(mockT, `["foo", {"hello": "world", "nested": "hash"}]`, `{"foo": "bar", {"nested": "hash", "hello": "world"}}`)) } func TestJSONEq_HashesNotEquivalent(t *testing.T) { mockT := new(testing.T) False(t, JSONEq(mockT, `{"foo": "bar"}`, `{"foo": "bar", "hello": "world"}`)) } func TestJSONEq_ActualIsNotJSON(t *testing.T) { mockT := new(testing.T) False(t, JSONEq(mockT, `{"foo": "bar"}`, "Not JSON")) } func TestJSONEq_ExpectedIsNotJSON(t *testing.T) { mockT := new(testing.T) False(t, JSONEq(mockT, "Not JSON", `{"foo": "bar", "hello": "world"}`)) } func TestJSONEq_ExpectedAndActualNotJSON(t *testing.T) { mockT := new(testing.T) False(t, JSONEq(mockT, "Not JSON", "Not JSON")) } func TestJSONEq_ArraysOfDifferentOrder(t *testing.T) { mockT := new(testing.T) False(t, JSONEq(mockT, `["foo", {"hello": "world", "nested": "hash"}]`, `[{ "hello": "world", "nested": "hash"}, "foo"]`)) } func TestDiff(t *testing.T) { expected := ` Diff: --- Expected +++ Actual @@ -1,3 +1,3 @@ (struct { foo string }) { - foo: (string) (len=5) "hello" + foo: (string) (len=3) "bar" } ` actual := diff( struct{ foo string }{"hello"}, struct{ foo string }{"bar"}, ) Equal(t, expected, actual) expected = ` Diff: --- Expected +++ Actual @@ -2,5 +2,5 @@ (int) 1, - (int) 2, (int) 3, - (int) 4 + (int) 5, + (int) 7 } ` actual = diff( []int{1, 2, 3, 4}, []int{1, 3, 5, 7}, ) Equal(t, expected, actual) expected = ` Diff: --- Expected +++ Actual @@ -2,4 +2,4 @@ (int) 1, - (int) 2, - (int) 3 + (int) 3, + (int) 5 } ` actual = diff( []int{1, 2, 3, 4}[0:3], []int{1, 3, 5, 7}[0:3], ) Equal(t, expected, actual) expected = ` Diff: --- Expected +++ Actual @@ -1,6 +1,6 @@ (map[string]int) (len=4) { - (string) (len=4) "four": (int) 4, + (string) (len=4) "five": (int) 5, (string) (len=3) "one": (int) 1, - (string) (len=5) "three": (int) 3, - (string) (len=3) "two": (int) 2 + (string) (len=5) "seven": (int) 7, + (string) (len=5) "three": (int) 3 } ` actual = diff( map[string]int{"one": 1, "two": 2, "three": 3, "four": 4}, map[string]int{"one": 1, "three": 3, "five": 5, "seven": 7}, ) Equal(t, expected, actual) } func TestDiffEmptyCases(t *testing.T) { Equal(t, "", diff(nil, nil)) Equal(t, "", diff(struct{ foo string }{}, nil)) Equal(t, "", diff(nil, struct{ foo string }{})) Equal(t, "", diff(1, 2)) Equal(t, "", diff(1, 2)) Equal(t, "", diff([]int{1}, []bool{true})) } type mockTestingT struct { } func (m *mockTestingT) Errorf(format string, args ...interface{}) {} func TestFailNowWithPlainTestingT(t *testing.T) { mockT := &mockTestingT{} Panics(t, func() { FailNow(mockT, "failed") }, "should panic since mockT is missing FailNow()") } type mockFailNowTestingT struct { } func (m *mockFailNowTestingT) Errorf(format string, args ...interface{}) {} func (m *mockFailNowTestingT) FailNow() {} func TestFailNowWithFullTestingT(t *testing.T) { mockT := &mockFailNowTestingT{} NotPanics(t, func() { FailNow(mockT, "failed") }, "should call mockT.FailNow() rather than panicking") } lxd-2.0.0/dist/src/github.com/stretchr/testify/assert/assertion_forward.go.tmpl0000644061062106075000000000021312702772371032366 0ustar00stgraberdomain admins00000000000000{{.CommentWithoutT "a"}} func (a *Assertions) {{.DocInfo.Name}}({{.Params}}) bool { return {{.DocInfo.Name}}(a.t, {{.ForwardedParams}}) } lxd-2.0.0/dist/src/github.com/stretchr/testify/doc.go0000644061062106075000000000165412702772371025136 0ustar00stgraberdomain admins00000000000000// Package testify is a set of packages that provide many tools for testifying that your code will behave as you intend. // // testify contains the following packages: // // The assert package provides a comprehensive set of assertion functions that tie in to the Go testing system. // // The http package contains tools to make it easier to test http activity using the Go testing system. // // The mock package provides a system by which it is possible to mock your objects and verify calls are happening as expected. // // The suite package provides a basic structure for using structs as testing suites, and methods on those structs as tests. It includes setup/teardown functionality in the way of interfaces. package testify // blank imports help docs. import ( // assert package _ "github.com/stretchr/testify/assert" // http package _ "github.com/stretchr/testify/http" // mock package _ "github.com/stretchr/testify/mock" ) lxd-2.0.0/dist/src/github.com/stretchr/testify/.travis.yml0000644061062106075000000000016512702772371026147 0ustar00stgraberdomain admins00000000000000language: go sudo: false go: - 1.1 - 1.2 - 1.3 - 1.4 - 1.5 - 1.6 - tip script: - go test -v ./... lxd-2.0.0/dist/src/github.com/stretchr/testify/mock/0000755061062106075000000000000012702772371024765 5ustar00stgraberdomain admins00000000000000lxd-2.0.0/dist/src/github.com/stretchr/testify/mock/mock_test.go0000644061062106075000000007127112702772371027314 0ustar00stgraberdomain admins00000000000000package mock import ( "errors" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "testing" "time" ) /* Test objects */ // ExampleInterface represents an example interface. type ExampleInterface interface { TheExampleMethod(a, b, c int) (int, error) } // TestExampleImplementation is a test implementation of ExampleInterface type TestExampleImplementation struct { Mock } func (i *TestExampleImplementation) TheExampleMethod(a, b, c int) (int, error) { args := i.Called(a, b, c) return args.Int(0), errors.New("Whoops") } func (i *TestExampleImplementation) TheExampleMethod2(yesorno bool) { i.Called(yesorno) } type ExampleType struct { ran bool } func (i *TestExampleImplementation) TheExampleMethod3(et *ExampleType) error { args := i.Called(et) return args.Error(0) } func (i *TestExampleImplementation) TheExampleMethodFunc(fn func(string) error) error { args := i.Called(fn) return args.Error(0) } func (i *TestExampleImplementation) TheExampleMethodVariadic(a ...int) error { args := i.Called(a) return args.Error(0) } func (i *TestExampleImplementation) TheExampleMethodVariadicInterface(a ...interface{}) error { args := i.Called(a) return args.Error(0) } type ExampleFuncType func(string) error func (i *TestExampleImplementation) TheExampleMethodFuncType(fn ExampleFuncType) error { args := i.Called(fn) return args.Error(0) } /* Mock */ func Test_Mock_TestData(t *testing.T) { var mockedService = new(TestExampleImplementation) if assert.NotNil(t, mockedService.TestData()) { mockedService.TestData().Set("something", 123) assert.Equal(t, 123, mockedService.TestData().Get("something").Data()) } } func Test_Mock_On(t *testing.T) { // make a test impl object var mockedService = new(TestExampleImplementation) c := mockedService.On("TheExampleMethod") assert.Equal(t, []*Call{c}, mockedService.ExpectedCalls) assert.Equal(t, "TheExampleMethod", c.Method) } func Test_Mock_Chained_On(t *testing.T) { // make a test impl object var mockedService = new(TestExampleImplementation) mockedService. On("TheExampleMethod", 1, 2, 3). Return(0). On("TheExampleMethod3", AnythingOfType("*mock.ExampleType")). Return(nil) expectedCalls := []*Call{ &Call{ Parent: &mockedService.Mock, Method: "TheExampleMethod", Arguments: []interface{}{1, 2, 3}, ReturnArguments: []interface{}{0}, }, &Call{ Parent: &mockedService.Mock, Method: "TheExampleMethod3", Arguments: []interface{}{AnythingOfType("*mock.ExampleType")}, ReturnArguments: []interface{}{nil}, }, } assert.Equal(t, expectedCalls, mockedService.ExpectedCalls) } func Test_Mock_On_WithArgs(t *testing.T) { // make a test impl object var mockedService = new(TestExampleImplementation) c := mockedService.On("TheExampleMethod", 1, 2, 3, 4) assert.Equal(t, []*Call{c}, mockedService.ExpectedCalls) assert.Equal(t, "TheExampleMethod", c.Method) assert.Equal(t, Arguments{1, 2, 3, 4}, c.Arguments) } func Test_Mock_On_WithFuncArg(t *testing.T) { // make a test impl object var mockedService = new(TestExampleImplementation) c := mockedService. On("TheExampleMethodFunc", AnythingOfType("func(string) error")). Return(nil) assert.Equal(t, []*Call{c}, mockedService.ExpectedCalls) assert.Equal(t, "TheExampleMethodFunc", c.Method) assert.Equal(t, 1, len(c.Arguments)) assert.Equal(t, AnythingOfType("func(string) error"), c.Arguments[0]) fn := func(string) error { return nil } assert.NotPanics(t, func() { mockedService.TheExampleMethodFunc(fn) }) } func Test_Mock_On_WithIntArgMatcher(t *testing.T) { var mockedService TestExampleImplementation mockedService.On("TheExampleMethod", MatchedBy(func(a int) bool { return a == 1 }), MatchedBy(func(b int) bool { return b == 2 }), MatchedBy(func(c int) bool { return c == 3 })).Return(0, nil) assert.Panics(t, func() { mockedService.TheExampleMethod(1, 2, 4) }) assert.Panics(t, func() { mockedService.TheExampleMethod(2, 2, 3) }) assert.NotPanics(t, func() { mockedService.TheExampleMethod(1, 2, 3) }) } func Test_Mock_On_WithPtrArgMatcher(t *testing.T) { var mockedService TestExampleImplementation mockedService.On("TheExampleMethod3", MatchedBy(func(a *ExampleType) bool { return a.ran == true }), ).Return(nil) mockedService.On("TheExampleMethod3", MatchedBy(func(a *ExampleType) bool { return a.ran == false }), ).Return(errors.New("error")) assert.Equal(t, mockedService.TheExampleMethod3(&ExampleType{true}), nil) assert.EqualError(t, mockedService.TheExampleMethod3(&ExampleType{false}), "error") } func Test_Mock_On_WithFuncArgMatcher(t *testing.T) { var mockedService TestExampleImplementation fixture1, fixture2 := errors.New("fixture1"), errors.New("fixture2") mockedService.On("TheExampleMethodFunc", MatchedBy(func(a func(string) error) bool { return a("string") == fixture1 }), ).Return(errors.New("fixture1")) mockedService.On("TheExampleMethodFunc", MatchedBy(func(a func(string) error) bool { return a("string") == fixture2 }), ).Return(errors.New("fixture2")) assert.EqualError(t, mockedService.TheExampleMethodFunc( func(string) error { return fixture1 }), "fixture1") assert.EqualError(t, mockedService.TheExampleMethodFunc( func(string) error { return fixture2 }), "fixture2") } func Test_Mock_On_WithVariadicFunc(t *testing.T) { // make a test impl object var mockedService = new(TestExampleImplementation) c := mockedService. On("TheExampleMethodVariadic", []int{1, 2, 3}). Return(nil) assert.Equal(t, []*Call{c}, mockedService.ExpectedCalls) assert.Equal(t, 1, len(c.Arguments)) assert.Equal(t, []int{1, 2, 3}, c.Arguments[0]) assert.NotPanics(t, func() { mockedService.TheExampleMethodVariadic(1, 2, 3) }) assert.Panics(t, func() { mockedService.TheExampleMethodVariadic(1, 2) }) } func Test_Mock_On_WithVariadicFuncWithInterface(t *testing.T) { // make a test impl object var mockedService = new(TestExampleImplementation) c := mockedService.On("TheExampleMethodVariadicInterface", []interface{}{1, 2, 3}). Return(nil) assert.Equal(t, []*Call{c}, mockedService.ExpectedCalls) assert.Equal(t, 1, len(c.Arguments)) assert.Equal(t, []interface{}{1, 2, 3}, c.Arguments[0]) assert.NotPanics(t, func() { mockedService.TheExampleMethodVariadicInterface(1, 2, 3) }) assert.Panics(t, func() { mockedService.TheExampleMethodVariadicInterface(1, 2) }) } func Test_Mock_On_WithVariadicFuncWithEmptyInterfaceArray(t *testing.T) { // make a test impl object var mockedService = new(TestExampleImplementation) var expected []interface{} c := mockedService. On("TheExampleMethodVariadicInterface", expected). Return(nil) assert.Equal(t, []*Call{c}, mockedService.ExpectedCalls) assert.Equal(t, 1, len(c.Arguments)) assert.Equal(t, expected, c.Arguments[0]) assert.NotPanics(t, func() { mockedService.TheExampleMethodVariadicInterface() }) assert.Panics(t, func() { mockedService.TheExampleMethodVariadicInterface(1, 2) }) } func Test_Mock_On_WithFuncPanics(t *testing.T) { // make a test impl object var mockedService = new(TestExampleImplementation) assert.Panics(t, func() { mockedService.On("TheExampleMethodFunc", func(string) error { return nil }) }) } func Test_Mock_On_WithFuncTypeArg(t *testing.T) { // make a test impl object var mockedService = new(TestExampleImplementation) c := mockedService. On("TheExampleMethodFuncType", AnythingOfType("mock.ExampleFuncType")). Return(nil) assert.Equal(t, []*Call{c}, mockedService.ExpectedCalls) assert.Equal(t, 1, len(c.Arguments)) assert.Equal(t, AnythingOfType("mock.ExampleFuncType"), c.Arguments[0]) fn := func(string) error { return nil } assert.NotPanics(t, func() { mockedService.TheExampleMethodFuncType(fn) }) } func Test_Mock_Return(t *testing.T) { // make a test impl object var mockedService = new(TestExampleImplementation) c := mockedService. On("TheExampleMethod", "A", "B", true). Return(1, "two", true) require.Equal(t, []*Call{c}, mockedService.ExpectedCalls) call := mockedService.ExpectedCalls[0] assert.Equal(t, "TheExampleMethod", call.Method) assert.Equal(t, "A", call.Arguments[0]) assert.Equal(t, "B", call.Arguments[1]) assert.Equal(t, true, call.Arguments[2]) assert.Equal(t, 1, call.ReturnArguments[0]) assert.Equal(t, "two", call.ReturnArguments[1]) assert.Equal(t, true, call.ReturnArguments[2]) assert.Equal(t, 0, call.Repeatability) assert.Nil(t, call.WaitFor) } func Test_Mock_Return_WaitUntil(t *testing.T) { // make a test impl object var mockedService = new(TestExampleImplementation) ch := time.After(time.Second) c := mockedService.Mock. On("TheExampleMethod", "A", "B", true). WaitUntil(ch). Return(1, "two", true) // assert that the call was created require.Equal(t, []*Call{c}, mockedService.ExpectedCalls) call := mockedService.ExpectedCalls[0] assert.Equal(t, "TheExampleMethod", call.Method) assert.Equal(t, "A", call.Arguments[0]) assert.Equal(t, "B", call.Arguments[1]) assert.Equal(t, true, call.Arguments[2]) assert.Equal(t, 1, call.ReturnArguments[0]) assert.Equal(t, "two", call.ReturnArguments[1]) assert.Equal(t, true, call.ReturnArguments[2]) assert.Equal(t, 0, call.Repeatability) assert.Equal(t, ch, call.WaitFor) } func Test_Mock_Return_After(t *testing.T) { // make a test impl object var mockedService = new(TestExampleImplementation) c := mockedService.Mock. On("TheExampleMethod", "A", "B", true). Return(1, "two", true). After(time.Second) require.Equal(t, []*Call{c}, mockedService.ExpectedCalls) call := mockedService.Mock.ExpectedCalls[0] assert.Equal(t, "TheExampleMethod", call.Method) assert.Equal(t, "A", call.Arguments[0]) assert.Equal(t, "B", call.Arguments[1]) assert.Equal(t, true, call.Arguments[2]) assert.Equal(t, 1, call.ReturnArguments[0]) assert.Equal(t, "two", call.ReturnArguments[1]) assert.Equal(t, true, call.ReturnArguments[2]) assert.Equal(t, 0, call.Repeatability) assert.NotEqual(t, nil, call.WaitFor) } func Test_Mock_Return_Run(t *testing.T) { // make a test impl object var mockedService = new(TestExampleImplementation) fn := func(args Arguments) { arg := args.Get(0).(*ExampleType) arg.ran = true } c := mockedService.Mock. On("TheExampleMethod3", AnythingOfType("*mock.ExampleType")). Return(nil). Run(fn) require.Equal(t, []*Call{c}, mockedService.ExpectedCalls) call := mockedService.Mock.ExpectedCalls[0] assert.Equal(t, "TheExampleMethod3", call.Method) assert.Equal(t, AnythingOfType("*mock.ExampleType"), call.Arguments[0]) assert.Equal(t, nil, call.ReturnArguments[0]) assert.Equal(t, 0, call.Repeatability) assert.NotEqual(t, nil, call.WaitFor) assert.NotNil(t, call.Run) et := ExampleType{} assert.Equal(t, false, et.ran) mockedService.TheExampleMethod3(&et) assert.Equal(t, true, et.ran) } func Test_Mock_Return_Run_Out_Of_Order(t *testing.T) { // make a test impl object var mockedService = new(TestExampleImplementation) f := func(args Arguments) { arg := args.Get(0).(*ExampleType) arg.ran = true } c := mockedService.Mock. On("TheExampleMethod3", AnythingOfType("*mock.ExampleType")). Run(f). Return(nil) require.Equal(t, []*Call{c}, mockedService.ExpectedCalls) call := mockedService.Mock.ExpectedCalls[0] assert.Equal(t, "TheExampleMethod3", call.Method) assert.Equal(t, AnythingOfType("*mock.ExampleType"), call.Arguments[0]) assert.Equal(t, nil, call.ReturnArguments[0]) assert.Equal(t, 0, call.Repeatability) assert.NotEqual(t, nil, call.WaitFor) assert.NotNil(t, call.Run) } func Test_Mock_Return_Once(t *testing.T) { // make a test impl object var mockedService = new(TestExampleImplementation) c := mockedService.On("TheExampleMethod", "A", "B", true). Return(1, "two", true). Once() require.Equal(t, []*Call{c}, mockedService.ExpectedCalls) call := mockedService.ExpectedCalls[0] assert.Equal(t, "TheExampleMethod", call.Method) assert.Equal(t, "A", call.Arguments[0]) assert.Equal(t, "B", call.Arguments[1]) assert.Equal(t, true, call.Arguments[2]) assert.Equal(t, 1, call.ReturnArguments[0]) assert.Equal(t, "two", call.ReturnArguments[1]) assert.Equal(t, true, call.ReturnArguments[2]) assert.Equal(t, 1, call.Repeatability) assert.Nil(t, call.WaitFor) } func Test_Mock_Return_Twice(t *testing.T) { // make a test impl object var mockedService = new(TestExampleImplementation) c := mockedService. On("TheExampleMethod", "A", "B", true). Return(1, "two", true). Twice() require.Equal(t, []*Call{c}, mockedService.ExpectedCalls) call := mockedService.ExpectedCalls[0] assert.Equal(t, "TheExampleMethod", call.Method) assert.Equal(t, "A", call.Arguments[0]) assert.Equal(t, "B", call.Arguments[1]) assert.Equal(t, true, call.Arguments[2]) assert.Equal(t, 1, call.ReturnArguments[0]) assert.Equal(t, "two", call.ReturnArguments[1]) assert.Equal(t, true, call.ReturnArguments[2]) assert.Equal(t, 2, call.Repeatability) assert.Nil(t, call.WaitFor) } func Test_Mock_Return_Times(t *testing.T) { // make a test impl object var mockedService = new(TestExampleImplementation) c := mockedService. On("TheExampleMethod", "A", "B", true). Return(1, "two", true). Times(5) require.Equal(t, []*Call{c}, mockedService.ExpectedCalls) call := mockedService.ExpectedCalls[0] assert.Equal(t, "TheExampleMethod", call.Method) assert.Equal(t, "A", call.Arguments[0]) assert.Equal(t, "B", call.Arguments[1]) assert.Equal(t, true, call.Arguments[2]) assert.Equal(t, 1, call.ReturnArguments[0]) assert.Equal(t, "two", call.ReturnArguments[1]) assert.Equal(t, true, call.ReturnArguments[2]) assert.Equal(t, 5, call.Repeatability) assert.Nil(t, call.WaitFor) } func Test_Mock_Return_Nothing(t *testing.T) { // make a test impl object var mockedService = new(TestExampleImplementation) c := mockedService. On("TheExampleMethod", "A", "B", true). Return() require.Equal(t, []*Call{c}, mockedService.ExpectedCalls) call := mockedService.ExpectedCalls[0] assert.Equal(t, "TheExampleMethod", call.Method) assert.Equal(t, "A", call.Arguments[0]) assert.Equal(t, "B", call.Arguments[1]) assert.Equal(t, true, call.Arguments[2]) assert.Equal(t, 0, len(call.ReturnArguments)) } func Test_Mock_findExpectedCall(t *testing.T) { m := new(Mock) m.On("One", 1).Return("one") m.On("Two", 2).Return("two") m.On("Two", 3).Return("three") f, c := m.findExpectedCall("Two", 3) if assert.Equal(t, 2, f) { if assert.NotNil(t, c) { assert.Equal(t, "Two", c.Method) assert.Equal(t, 3, c.Arguments[0]) assert.Equal(t, "three", c.ReturnArguments[0]) } } } func Test_Mock_findExpectedCall_For_Unknown_Method(t *testing.T) { m := new(Mock) m.On("One", 1).Return("one") m.On("Two", 2).Return("two") m.On("Two", 3).Return("three") f, _ := m.findExpectedCall("Two") assert.Equal(t, -1, f) } func Test_Mock_findExpectedCall_Respects_Repeatability(t *testing.T) { m := new(Mock) m.On("One", 1).Return("one") m.On("Two", 2).Return("two").Once() m.On("Two", 3).Return("three").Twice() m.On("Two", 3).Return("three").Times(8) f, c := m.findExpectedCall("Two", 3) if assert.Equal(t, 2, f) { if assert.NotNil(t, c) { assert.Equal(t, "Two", c.Method) assert.Equal(t, 3, c.Arguments[0]) assert.Equal(t, "three", c.ReturnArguments[0]) } } } func Test_callString(t *testing.T) { assert.Equal(t, `Method(int,bool,string)`, callString("Method", []interface{}{1, true, "something"}, false)) } func Test_Mock_Called(t *testing.T) { var mockedService = new(TestExampleImplementation) mockedService.On("Test_Mock_Called", 1, 2, 3).Return(5, "6", true) returnArguments := mockedService.Called(1, 2, 3) if assert.Equal(t, 1, len(mockedService.Calls)) { assert.Equal(t, "Test_Mock_Called", mockedService.Calls[0].Method) assert.Equal(t, 1, mockedService.Calls[0].Arguments[0]) assert.Equal(t, 2, mockedService.Calls[0].Arguments[1]) assert.Equal(t, 3, mockedService.Calls[0].Arguments[2]) } if assert.Equal(t, 3, len(returnArguments)) { assert.Equal(t, 5, returnArguments[0]) assert.Equal(t, "6", returnArguments[1]) assert.Equal(t, true, returnArguments[2]) } } func asyncCall(m *Mock, ch chan Arguments) { ch <- m.Called(1, 2, 3) } func Test_Mock_Called_blocks(t *testing.T) { var mockedService = new(TestExampleImplementation) mockedService.Mock.On("asyncCall", 1, 2, 3).Return(5, "6", true).After(2 * time.Millisecond) ch := make(chan Arguments) go asyncCall(&mockedService.Mock, ch) select { case <-ch: t.Fatal("should have waited") case <-time.After(1 * time.Millisecond): } returnArguments := <-ch if assert.Equal(t, 1, len(mockedService.Mock.Calls)) { assert.Equal(t, "asyncCall", mockedService.Mock.Calls[0].Method) assert.Equal(t, 1, mockedService.Mock.Calls[0].Arguments[0]) assert.Equal(t, 2, mockedService.Mock.Calls[0].Arguments[1]) assert.Equal(t, 3, mockedService.Mock.Calls[0].Arguments[2]) } if assert.Equal(t, 3, len(returnArguments)) { assert.Equal(t, 5, returnArguments[0]) assert.Equal(t, "6", returnArguments[1]) assert.Equal(t, true, returnArguments[2]) } } func Test_Mock_Called_For_Bounded_Repeatability(t *testing.T) { var mockedService = new(TestExampleImplementation) mockedService. On("Test_Mock_Called_For_Bounded_Repeatability", 1, 2, 3). Return(5, "6", true). Once() mockedService. On("Test_Mock_Called_For_Bounded_Repeatability", 1, 2, 3). Return(-1, "hi", false) returnArguments1 := mockedService.Called(1, 2, 3) returnArguments2 := mockedService.Called(1, 2, 3) if assert.Equal(t, 2, len(mockedService.Calls)) { assert.Equal(t, "Test_Mock_Called_For_Bounded_Repeatability", mockedService.Calls[0].Method) assert.Equal(t, 1, mockedService.Calls[0].Arguments[0]) assert.Equal(t, 2, mockedService.Calls[0].Arguments[1]) assert.Equal(t, 3, mockedService.Calls[0].Arguments[2]) assert.Equal(t, "Test_Mock_Called_For_Bounded_Repeatability", mockedService.Calls[1].Method) assert.Equal(t, 1, mockedService.Calls[1].Arguments[0]) assert.Equal(t, 2, mockedService.Calls[1].Arguments[1]) assert.Equal(t, 3, mockedService.Calls[1].Arguments[2]) } if assert.Equal(t, 3, len(returnArguments1)) { assert.Equal(t, 5, returnArguments1[0]) assert.Equal(t, "6", returnArguments1[1]) assert.Equal(t, true, returnArguments1[2]) } if assert.Equal(t, 3, len(returnArguments2)) { assert.Equal(t, -1, returnArguments2[0]) assert.Equal(t, "hi", returnArguments2[1]) assert.Equal(t, false, returnArguments2[2]) } } func Test_Mock_Called_For_SetTime_Expectation(t *testing.T) { var mockedService = new(TestExampleImplementation) mockedService.On("TheExampleMethod", 1, 2, 3).Return(5, "6", true).Times(4) mockedService.TheExampleMethod(1, 2, 3) mockedService.TheExampleMethod(1, 2, 3) mockedService.TheExampleMethod(1, 2, 3) mockedService.TheExampleMethod(1, 2, 3) assert.Panics(t, func() { mockedService.TheExampleMethod(1, 2, 3) }) } func Test_Mock_Called_Unexpected(t *testing.T) { var mockedService = new(TestExampleImplementation) // make sure it panics if no expectation was made assert.Panics(t, func() { mockedService.Called(1, 2, 3) }, "Calling unexpected method should panic") } func Test_AssertExpectationsForObjects_Helper(t *testing.T) { var mockedService1 = new(TestExampleImplementation) var mockedService2 = new(TestExampleImplementation) var mockedService3 = new(TestExampleImplementation) mockedService1.On("Test_AssertExpectationsForObjects_Helper", 1).Return() mockedService2.On("Test_AssertExpectationsForObjects_Helper", 2).Return() mockedService3.On("Test_AssertExpectationsForObjects_Helper", 3).Return() mockedService1.Called(1) mockedService2.Called(2) mockedService3.Called(3) assert.True(t, AssertExpectationsForObjects(t, mockedService1.Mock, mockedService2.Mock, mockedService3.Mock)) } func Test_AssertExpectationsForObjects_Helper_Failed(t *testing.T) { var mockedService1 = new(TestExampleImplementation) var mockedService2 = new(TestExampleImplementation) var mockedService3 = new(TestExampleImplementation) mockedService1.On("Test_AssertExpectationsForObjects_Helper_Failed", 1).Return() mockedService2.On("Test_AssertExpectationsForObjects_Helper_Failed", 2).Return() mockedService3.On("Test_AssertExpectationsForObjects_Helper_Failed", 3).Return() mockedService1.Called(1) mockedService3.Called(3) tt := new(testing.T) assert.False(t, AssertExpectationsForObjects(tt, mockedService1.Mock, mockedService2.Mock, mockedService3.Mock)) } func Test_Mock_AssertExpectations(t *testing.T) { var mockedService = new(TestExampleImplementation) mockedService.On("Test_Mock_AssertExpectations", 1, 2, 3).Return(5, 6, 7) tt := new(testing.T) assert.False(t, mockedService.AssertExpectations(tt)) // make the call now mockedService.Called(1, 2, 3) // now assert expectations assert.True(t, mockedService.AssertExpectations(tt)) } func Test_Mock_AssertExpectationsCustomType(t *testing.T) { var mockedService = new(TestExampleImplementation) mockedService.On("TheExampleMethod3", AnythingOfType("*mock.ExampleType")).Return(nil).Once() tt := new(testing.T) assert.False(t, mockedService.AssertExpectations(tt)) // make the call now mockedService.TheExampleMethod3(&ExampleType{}) // now assert expectations assert.True(t, mockedService.AssertExpectations(tt)) } func Test_Mock_AssertExpectations_With_Repeatability(t *testing.T) { var mockedService = new(TestExampleImplementation) mockedService.On("Test_Mock_AssertExpectations_With_Repeatability", 1, 2, 3).Return(5, 6, 7).Twice() tt := new(testing.T) assert.False(t, mockedService.AssertExpectations(tt)) // make the call now mockedService.Called(1, 2, 3) assert.False(t, mockedService.AssertExpectations(tt)) mockedService.Called(1, 2, 3) // now assert expectations assert.True(t, mockedService.AssertExpectations(tt)) } func Test_Mock_TwoCallsWithDifferentArguments(t *testing.T) { var mockedService = new(TestExampleImplementation) mockedService.On("Test_Mock_TwoCallsWithDifferentArguments", 1, 2, 3).Return(5, 6, 7) mockedService.On("Test_Mock_TwoCallsWithDifferentArguments", 4, 5, 6).Return(5, 6, 7) args1 := mockedService.Called(1, 2, 3) assert.Equal(t, 5, args1.Int(0)) assert.Equal(t, 6, args1.Int(1)) assert.Equal(t, 7, args1.Int(2)) args2 := mockedService.Called(4, 5, 6) assert.Equal(t, 5, args2.Int(0)) assert.Equal(t, 6, args2.Int(1)) assert.Equal(t, 7, args2.Int(2)) } func Test_Mock_AssertNumberOfCalls(t *testing.T) { var mockedService = new(TestExampleImplementation) mockedService.On("Test_Mock_AssertNumberOfCalls", 1, 2, 3).Return(5, 6, 7) mockedService.Called(1, 2, 3) assert.True(t, mockedService.AssertNumberOfCalls(t, "Test_Mock_AssertNumberOfCalls", 1)) mockedService.Called(1, 2, 3) assert.True(t, mockedService.AssertNumberOfCalls(t, "Test_Mock_AssertNumberOfCalls", 2)) } func Test_Mock_AssertCalled(t *testing.T) { var mockedService = new(TestExampleImplementation) mockedService.On("Test_Mock_AssertCalled", 1, 2, 3).Return(5, 6, 7) mockedService.Called(1, 2, 3) assert.True(t, mockedService.AssertCalled(t, "Test_Mock_AssertCalled", 1, 2, 3)) } func Test_Mock_AssertCalled_WithAnythingOfTypeArgument(t *testing.T) { var mockedService = new(TestExampleImplementation) mockedService. On("Test_Mock_AssertCalled_WithAnythingOfTypeArgument", Anything, Anything, Anything). Return() mockedService.Called(1, "two", []uint8("three")) assert.True(t, mockedService.AssertCalled(t, "Test_Mock_AssertCalled_WithAnythingOfTypeArgument", AnythingOfType("int"), AnythingOfType("string"), AnythingOfType("[]uint8"))) } func Test_Mock_AssertCalled_WithArguments(t *testing.T) { var mockedService = new(TestExampleImplementation) mockedService.On("Test_Mock_AssertCalled_WithArguments", 1, 2, 3).Return(5, 6, 7) mockedService.Called(1, 2, 3) tt := new(testing.T) assert.True(t, mockedService.AssertCalled(tt, "Test_Mock_AssertCalled_WithArguments", 1, 2, 3)) assert.False(t, mockedService.AssertCalled(tt, "Test_Mock_AssertCalled_WithArguments", 2, 3, 4)) } func Test_Mock_AssertCalled_WithArguments_With_Repeatability(t *testing.T) { var mockedService = new(TestExampleImplementation) mockedService.On("Test_Mock_AssertCalled_WithArguments_With_Repeatability", 1, 2, 3).Return(5, 6, 7).Once() mockedService.On("Test_Mock_AssertCalled_WithArguments_With_Repeatability", 2, 3, 4).Return(5, 6, 7).Once() mockedService.Called(1, 2, 3) mockedService.Called(2, 3, 4) tt := new(testing.T) assert.True(t, mockedService.AssertCalled(tt, "Test_Mock_AssertCalled_WithArguments_With_Repeatability", 1, 2, 3)) assert.True(t, mockedService.AssertCalled(tt, "Test_Mock_AssertCalled_WithArguments_With_Repeatability", 2, 3, 4)) assert.False(t, mockedService.AssertCalled(tt, "Test_Mock_AssertCalled_WithArguments_With_Repeatability", 3, 4, 5)) } func Test_Mock_AssertNotCalled(t *testing.T) { var mockedService = new(TestExampleImplementation) mockedService.On("Test_Mock_AssertNotCalled", 1, 2, 3).Return(5, 6, 7) mockedService.Called(1, 2, 3) assert.True(t, mockedService.AssertNotCalled(t, "Test_Mock_NotCalled")) } /* Arguments helper methods */ func Test_Arguments_Get(t *testing.T) { var args = Arguments([]interface{}{"string", 123, true}) assert.Equal(t, "string", args.Get(0).(string)) assert.Equal(t, 123, args.Get(1).(int)) assert.Equal(t, true, args.Get(2).(bool)) } func Test_Arguments_Is(t *testing.T) { var args = Arguments([]interface{}{"string", 123, true}) assert.True(t, args.Is("string", 123, true)) assert.False(t, args.Is("wrong", 456, false)) } func Test_Arguments_Diff(t *testing.T) { var args = Arguments([]interface{}{"Hello World", 123, true}) var diff string var count int diff, count = args.Diff([]interface{}{"Hello World", 456, "false"}) assert.Equal(t, 2, count) assert.Contains(t, diff, `%!s(int=456) != %!s(int=123)`) assert.Contains(t, diff, `false != %!s(bool=true)`) } func Test_Arguments_Diff_DifferentNumberOfArgs(t *testing.T) { var args = Arguments([]interface{}{"string", 123, true}) var diff string var count int diff, count = args.Diff([]interface{}{"string", 456, "false", "extra"}) assert.Equal(t, 3, count) assert.Contains(t, diff, `extra != (Missing)`) } func Test_Arguments_Diff_WithAnythingArgument(t *testing.T) { var args = Arguments([]interface{}{"string", 123, true}) var count int _, count = args.Diff([]interface{}{"string", Anything, true}) assert.Equal(t, 0, count) } func Test_Arguments_Diff_WithAnythingArgument_InActualToo(t *testing.T) { var args = Arguments([]interface{}{"string", Anything, true}) var count int _, count = args.Diff([]interface{}{"string", 123, true}) assert.Equal(t, 0, count) } func Test_Arguments_Diff_WithAnythingOfTypeArgument(t *testing.T) { var args = Arguments([]interface{}{"string", AnythingOfType("int"), true}) var count int _, count = args.Diff([]interface{}{"string", 123, true}) assert.Equal(t, 0, count) } func Test_Arguments_Diff_WithAnythingOfTypeArgument_Failing(t *testing.T) { var args = Arguments([]interface{}{"string", AnythingOfType("string"), true}) var count int var diff string diff, count = args.Diff([]interface{}{"string", 123, true}) assert.Equal(t, 1, count) assert.Contains(t, diff, `string != type int - %!s(int=123)`) } func Test_Arguments_Diff_WithArgMatcher(t *testing.T) { matchFn := func(a int) bool { return a == 123 } var args = Arguments([]interface{}{"string", MatchedBy(matchFn), true}) diff, count := args.Diff([]interface{}{"string", 124, true}) assert.Equal(t, 1, count) assert.Contains(t, diff, `%!s(int=124) not matched by func(int) bool`) diff, count = args.Diff([]interface{}{"string", false, true}) assert.Equal(t, 1, count) assert.Contains(t, diff, `%!s(bool=false) not matched by func(int) bool`) diff, count = args.Diff([]interface{}{"string", 123, false}) assert.Contains(t, diff, `%!s(int=123) matched by func(int) bool`) diff, count = args.Diff([]interface{}{"string", 123, true}) assert.Equal(t, 0, count) assert.Contains(t, diff, `No differences.`) } func Test_Arguments_Assert(t *testing.T) { var args = Arguments([]interface{}{"string", 123, true}) assert.True(t, args.Assert(t, "string", 123, true)) } func Test_Arguments_String_Representation(t *testing.T) { var args = Arguments([]interface{}{"string", 123, true}) assert.Equal(t, `string,int,bool`, args.String()) } func Test_Arguments_String(t *testing.T) { var args = Arguments([]interface{}{"string", 123, true}) assert.Equal(t, "string", args.String(0)) } func Test_Arguments_Error(t *testing.T) { var err = errors.New("An Error") var args = Arguments([]interface{}{"string", 123, true, err}) assert.Equal(t, err, args.Error(3)) } func Test_Arguments_Error_Nil(t *testing.T) { var args = Arguments([]interface{}{"string", 123, true, nil}) assert.Equal(t, nil, args.Error(3)) } func Test_Arguments_Int(t *testing.T) { var args = Arguments([]interface{}{"string", 123, true}) assert.Equal(t, 123, args.Int(1)) } func Test_Arguments_Bool(t *testing.T) { var args = Arguments([]interface{}{"string", 123, true}) assert.Equal(t, true, args.Bool(2)) } lxd-2.0.0/dist/src/github.com/stretchr/testify/mock/doc.go0000644061062106075000000000307512702772371026066 0ustar00stgraberdomain admins00000000000000// Package mock provides a system by which it is possible to mock your objects // and verify calls are happening as expected. // // Example Usage // // The mock package provides an object, Mock, that tracks activity on another object. It is usually // embedded into a test object as shown below: // // type MyTestObject struct { // // add a Mock object instance // mock.Mock // // // other fields go here as normal // } // // When implementing the methods of an interface, you wire your functions up // to call the Mock.Called(args...) method, and return the appropriate values. // // For example, to mock a method that saves the name and age of a person and returns // the year of their birth or an error, you might write this: // // func (o *MyTestObject) SavePersonDetails(firstname, lastname string, age int) (int, error) { // args := o.Called(firstname, lastname, age) // return args.Int(0), args.Error(1) // } // // The Int, Error and Bool methods are examples of strongly typed getters that take the argument // index position. Given this argument list: // // (12, true, "Something") // // You could read them out strongly typed like this: // // args.Int(0) // args.Bool(1) // args.String(2) // // For objects of your own type, use the generic Arguments.Get(index) method and make a type assertion: // // return args.Get(0).(*MyObject), args.Get(1).(*AnotherObjectOfMine) // // This may cause a panic if the object you are getting is nil (the type assertion will fail), in those // cases you should check for nil first. package mock lxd-2.0.0/dist/src/github.com/stretchr/testify/mock/mock.go0000644061062106075000000004701312702772371026252 0ustar00stgraberdomain admins00000000000000package mock import ( "fmt" "reflect" "regexp" "runtime" "strings" "sync" "time" "github.com/stretchr/objx" "github.com/stretchr/testify/assert" ) // TestingT is an interface wrapper around *testing.T type TestingT interface { Logf(format string, args ...interface{}) Errorf(format string, args ...interface{}) FailNow() } /* Call */ // Call represents a method call and is used for setting expectations, // as well as recording activity. type Call struct { Parent *Mock // The name of the method that was or will be called. Method string // Holds the arguments of the method. Arguments Arguments // Holds the arguments that should be returned when // this method is called. ReturnArguments Arguments // The number of times to return the return arguments when setting // expectations. 0 means to always return the value. Repeatability int // Holds a channel that will be used to block the Return until it either // recieves a message or is closed. nil means it returns immediately. WaitFor <-chan time.Time // Holds a handler used to manipulate arguments content that are passed by // reference. It's useful when mocking methods such as unmarshalers or // decoders. RunFn func(Arguments) } func newCall(parent *Mock, methodName string, methodArguments ...interface{}) *Call { return &Call{ Parent: parent, Method: methodName, Arguments: methodArguments, ReturnArguments: make([]interface{}, 0), Repeatability: 0, WaitFor: nil, RunFn: nil, } } func (c *Call) lock() { c.Parent.mutex.Lock() } func (c *Call) unlock() { c.Parent.mutex.Unlock() } // Return specifies the return arguments for the expectation. // // Mock.On("DoSomething").Return(errors.New("failed")) func (c *Call) Return(returnArguments ...interface{}) *Call { c.lock() defer c.unlock() c.ReturnArguments = returnArguments return c } // Once indicates that that the mock should only return the value once. // // Mock.On("MyMethod", arg1, arg2).Return(returnArg1, returnArg2).Once() func (c *Call) Once() *Call { return c.Times(1) } // Twice indicates that that the mock should only return the value twice. // // Mock.On("MyMethod", arg1, arg2).Return(returnArg1, returnArg2).Twice() func (c *Call) Twice() *Call { return c.Times(2) } // Times indicates that that the mock should only return the indicated number // of times. // // Mock.On("MyMethod", arg1, arg2).Return(returnArg1, returnArg2).Times(5) func (c *Call) Times(i int) *Call { c.lock() defer c.unlock() c.Repeatability = i return c } // WaitUntil sets the channel that will block the mock's return until its closed // or a message is received. // // Mock.On("MyMethod", arg1, arg2).WaitUntil(time.After(time.Second)) func (c *Call) WaitUntil(w <-chan time.Time) *Call { c.lock() defer c.unlock() c.WaitFor = w return c } // After sets how long to block until the call returns // // Mock.On("MyMethod", arg1, arg2).After(time.Second) func (c *Call) After(d time.Duration) *Call { return c.WaitUntil(time.After(d)) } // Run sets a handler to be called before returning. It can be used when // mocking a method such as unmarshalers that takes a pointer to a struct and // sets properties in such struct // // Mock.On("Unmarshal", AnythingOfType("*map[string]interface{}").Return().Run(func(args Arguments) { // arg := args.Get(0).(*map[string]interface{}) // arg["foo"] = "bar" // }) func (c *Call) Run(fn func(Arguments)) *Call { c.lock() defer c.unlock() c.RunFn = fn return c } // On chains a new expectation description onto the mocked interface. This // allows syntax like. // // Mock. // On("MyMethod", 1).Return(nil). // On("MyOtherMethod", 'a', 'b', 'c').Return(errors.New("Some Error")) func (c *Call) On(methodName string, arguments ...interface{}) *Call { return c.Parent.On(methodName, arguments...) } // Mock is the workhorse used to track activity on another object. // For an example of its usage, refer to the "Example Usage" section at the top // of this document. type Mock struct { // Represents the calls that are expected of // an object. ExpectedCalls []*Call // Holds the calls that were made to this mocked object. Calls []Call // TestData holds any data that might be useful for testing. Testify ignores // this data completely allowing you to do whatever you like with it. testData objx.Map mutex sync.Mutex } // TestData holds any data that might be useful for testing. Testify ignores // this data completely allowing you to do whatever you like with it. func (m *Mock) TestData() objx.Map { if m.testData == nil { m.testData = make(objx.Map) } return m.testData } /* Setting expectations */ // On starts a description of an expectation of the specified method // being called. // // Mock.On("MyMethod", arg1, arg2) func (m *Mock) On(methodName string, arguments ...interface{}) *Call { for _, arg := range arguments { if v := reflect.ValueOf(arg); v.Kind() == reflect.Func { panic(fmt.Sprintf("cannot use Func in expectations. Use mock.AnythingOfType(\"%T\")", arg)) } } m.mutex.Lock() defer m.mutex.Unlock() c := newCall(m, methodName, arguments...) m.ExpectedCalls = append(m.ExpectedCalls, c) return c } // /* // Recording and responding to activity // */ func (m *Mock) findExpectedCall(method string, arguments ...interface{}) (int, *Call) { m.mutex.Lock() defer m.mutex.Unlock() for i, call := range m.ExpectedCalls { if call.Method == method && call.Repeatability > -1 { _, diffCount := call.Arguments.Diff(arguments) if diffCount == 0 { return i, call } } } return -1, nil } func (m *Mock) findClosestCall(method string, arguments ...interface{}) (bool, *Call) { diffCount := 0 var closestCall *Call for _, call := range m.expectedCalls() { if call.Method == method { _, tempDiffCount := call.Arguments.Diff(arguments) if tempDiffCount < diffCount || diffCount == 0 { diffCount = tempDiffCount closestCall = call } } } if closestCall == nil { return false, nil } return true, closestCall } func callString(method string, arguments Arguments, includeArgumentValues bool) string { var argValsString string if includeArgumentValues { var argVals []string for argIndex, arg := range arguments { argVals = append(argVals, fmt.Sprintf("%d: %#v", argIndex, arg)) } argValsString = fmt.Sprintf("\n\t\t%s", strings.Join(argVals, "\n\t\t")) } return fmt.Sprintf("%s(%s)%s", method, arguments.String(), argValsString) } // Called tells the mock object that a method has been called, and gets an array // of arguments to return. Panics if the call is unexpected (i.e. not preceeded by // appropriate .On .Return() calls) // If Call.WaitFor is set, blocks until the channel is closed or receives a message. func (m *Mock) Called(arguments ...interface{}) Arguments { // get the calling function's name pc, _, _, ok := runtime.Caller(1) if !ok { panic("Couldn't get the caller information") } functionPath := runtime.FuncForPC(pc).Name() //Next four lines are required to use GCCGO function naming conventions. //For Ex: github_com_docker_libkv_store_mock.WatchTree.pN39_github_com_docker_libkv_store_mock.Mock //uses inteface information unlike golang github.com/docker/libkv/store/mock.(*Mock).WatchTree //With GCCGO we need to remove interface information starting from pN
. re := regexp.MustCompile("\\.pN\\d+_") if re.MatchString(functionPath) { functionPath = re.Split(functionPath, -1)[0] } parts := strings.Split(functionPath, ".") functionName := parts[len(parts)-1] found, call := m.findExpectedCall(functionName, arguments...) if found < 0 { // we have to fail here - because we don't know what to do // as the return arguments. This is because: // // a) this is a totally unexpected call to this method, // b) the arguments are not what was expected, or // c) the developer has forgotten to add an accompanying On...Return pair. closestFound, closestCall := m.findClosestCall(functionName, arguments...) if closestFound { panic(fmt.Sprintf("\n\nmock: Unexpected Method Call\n-----------------------------\n\n%s\n\nThe closest call I have is: \n\n%s\n", callString(functionName, arguments, true), callString(functionName, closestCall.Arguments, true))) } else { panic(fmt.Sprintf("\nassert: mock: I don't know what to return because the method call was unexpected.\n\tEither do Mock.On(\"%s\").Return(...) first, or remove the %s() call.\n\tThis method was unexpected:\n\t\t%s\n\tat: %s", functionName, functionName, callString(functionName, arguments, true), assert.CallerInfo())) } } else { m.mutex.Lock() switch { case call.Repeatability == 1: call.Repeatability = -1 case call.Repeatability > 1: call.Repeatability-- } m.mutex.Unlock() } // add the call m.mutex.Lock() m.Calls = append(m.Calls, *newCall(m, functionName, arguments...)) m.mutex.Unlock() // block if specified if call.WaitFor != nil { <-call.WaitFor } if call.RunFn != nil { call.RunFn(arguments) } return call.ReturnArguments } /* Assertions */ // AssertExpectationsForObjects asserts that everything specified with On and Return // of the specified objects was in fact called as expected. // // Calls may have occurred in any order. func AssertExpectationsForObjects(t TestingT, testObjects ...interface{}) bool { var success = true for _, obj := range testObjects { mockObj := obj.(Mock) success = success && mockObj.AssertExpectations(t) } return success } // AssertExpectations asserts that everything specified with On and Return was // in fact called as expected. Calls may have occurred in any order. func (m *Mock) AssertExpectations(t TestingT) bool { var somethingMissing bool var failedExpectations int // iterate through each expectation expectedCalls := m.expectedCalls() for _, expectedCall := range expectedCalls { if !m.methodWasCalled(expectedCall.Method, expectedCall.Arguments) { somethingMissing = true failedExpectations++ t.Logf("\u274C\t%s(%s)", expectedCall.Method, expectedCall.Arguments.String()) } else { m.mutex.Lock() if expectedCall.Repeatability > 0 { somethingMissing = true failedExpectations++ } else { t.Logf("\u2705\t%s(%s)", expectedCall.Method, expectedCall.Arguments.String()) } m.mutex.Unlock() } } if somethingMissing { t.Errorf("FAIL: %d out of %d expectation(s) were met.\n\tThe code you are testing needs to make %d more call(s).\n\tat: %s", len(expectedCalls)-failedExpectations, len(expectedCalls), failedExpectations, assert.CallerInfo()) } return !somethingMissing } // AssertNumberOfCalls asserts that the method was called expectedCalls times. func (m *Mock) AssertNumberOfCalls(t TestingT, methodName string, expectedCalls int) bool { var actualCalls int for _, call := range m.calls() { if call.Method == methodName { actualCalls++ } } return assert.Equal(t, expectedCalls, actualCalls, fmt.Sprintf("Expected number of calls (%d) does not match the actual number of calls (%d).", expectedCalls, actualCalls)) } // AssertCalled asserts that the method was called. func (m *Mock) AssertCalled(t TestingT, methodName string, arguments ...interface{}) bool { if !assert.True(t, m.methodWasCalled(methodName, arguments), fmt.Sprintf("The \"%s\" method should have been called with %d argument(s), but was not.", methodName, len(arguments))) { t.Logf("%v", m.expectedCalls()) return false } return true } // AssertNotCalled asserts that the method was not called. func (m *Mock) AssertNotCalled(t TestingT, methodName string, arguments ...interface{}) bool { if !assert.False(t, m.methodWasCalled(methodName, arguments), fmt.Sprintf("The \"%s\" method was called with %d argument(s), but should NOT have been.", methodName, len(arguments))) { t.Logf("%v", m.expectedCalls()) return false } return true } func (m *Mock) methodWasCalled(methodName string, expected []interface{}) bool { for _, call := range m.calls() { if call.Method == methodName { _, differences := Arguments(expected).Diff(call.Arguments) if differences == 0 { // found the expected call return true } } } // we didn't find the expected call return false } func (m *Mock) expectedCalls() []*Call { m.mutex.Lock() defer m.mutex.Unlock() return append([]*Call{}, m.ExpectedCalls...) } func (m *Mock) calls() []Call { m.mutex.Lock() defer m.mutex.Unlock() return append([]Call{}, m.Calls...) } /* Arguments */ // Arguments holds an array of method arguments or return values. type Arguments []interface{} const ( // Anything is used in Diff and Assert when the argument being tested // shouldn't be taken into consideration. Anything string = "mock.Anything" ) // AnythingOfTypeArgument is a string that contains the type of an argument // for use when type checking. Used in Diff and Assert. type AnythingOfTypeArgument string // AnythingOfType returns an AnythingOfTypeArgument object containing the // name of the type to check for. Used in Diff and Assert. // // For example: // Assert(t, AnythingOfType("string"), AnythingOfType("int")) func AnythingOfType(t string) AnythingOfTypeArgument { return AnythingOfTypeArgument(t) } // argumentMatcher performs custom argument matching, returning whether or // not the argument is matched by the expectation fixture function. type argumentMatcher struct { // fn is a function which accepts one argument, and returns a bool. fn reflect.Value } func (f argumentMatcher) Matches(argument interface{}) bool { expectType := f.fn.Type().In(0) if reflect.TypeOf(argument).AssignableTo(expectType) { result := f.fn.Call([]reflect.Value{reflect.ValueOf(argument)}) return result[0].Bool() } return false } func (f argumentMatcher) String() string { return fmt.Sprintf("func(%s) bool", f.fn.Type().In(0).Name()) } // MatchedBy can be used to match a mock call based on only certain properties // from a complex struct or some calculation. It takes a function that will be // evaluated with the called argument and will return true when there's a match // and false otherwise. // // Example: // m.On("Do", MatchedBy(func(req *http.Request) bool { return req.Host == "example.com" })) // // |fn|, must be a function accepting a single argument (of the expected type) // which returns a bool. If |fn| doesn't match the required signature, // MathedBy() panics. func MatchedBy(fn interface{}) argumentMatcher { fnType := reflect.TypeOf(fn) if fnType.Kind() != reflect.Func { panic(fmt.Sprintf("assert: arguments: %s is not a func", fn)) } if fnType.NumIn() != 1 { panic(fmt.Sprintf("assert: arguments: %s does not take exactly one argument", fn)) } if fnType.NumOut() != 1 || fnType.Out(0).Kind() != reflect.Bool { panic(fmt.Sprintf("assert: arguments: %s does not return a bool", fn)) } return argumentMatcher{fn: reflect.ValueOf(fn)} } // Get Returns the argument at the specified index. func (args Arguments) Get(index int) interface{} { if index+1 > len(args) { panic(fmt.Sprintf("assert: arguments: Cannot call Get(%d) because there are %d argument(s).", index, len(args))) } return args[index] } // Is gets whether the objects match the arguments specified. func (args Arguments) Is(objects ...interface{}) bool { for i, obj := range args { if obj != objects[i] { return false } } return true } // Diff gets a string describing the differences between the arguments // and the specified objects. // // Returns the diff string and number of differences found. func (args Arguments) Diff(objects []interface{}) (string, int) { var output = "\n" var differences int var maxArgCount = len(args) if len(objects) > maxArgCount { maxArgCount = len(objects) } for i := 0; i < maxArgCount; i++ { var actual, expected interface{} if len(objects) <= i { actual = "(Missing)" } else { actual = objects[i] } if len(args) <= i { expected = "(Missing)" } else { expected = args[i] } if matcher, ok := expected.(argumentMatcher); ok { if matcher.Matches(actual) { output = fmt.Sprintf("%s\t%d: \u2705 %s matched by %s\n", output, i, actual, matcher) } else { differences++ output = fmt.Sprintf("%s\t%d: \u2705 %s not matched by %s\n", output, i, actual, matcher) } } else if reflect.TypeOf(expected) == reflect.TypeOf((*AnythingOfTypeArgument)(nil)).Elem() { // type checking if reflect.TypeOf(actual).Name() != string(expected.(AnythingOfTypeArgument)) && reflect.TypeOf(actual).String() != string(expected.(AnythingOfTypeArgument)) { // not match differences++ output = fmt.Sprintf("%s\t%d: \u274C type %s != type %s - %s\n", output, i, expected, reflect.TypeOf(actual).Name(), actual) } } else { // normal checking if assert.ObjectsAreEqual(expected, Anything) || assert.ObjectsAreEqual(actual, Anything) || assert.ObjectsAreEqual(actual, expected) { // match output = fmt.Sprintf("%s\t%d: \u2705 %s == %s\n", output, i, actual, expected) } else { // not match differences++ output = fmt.Sprintf("%s\t%d: \u274C %s != %s\n", output, i, actual, expected) } } } if differences == 0 { return "No differences.", differences } return output, differences } // Assert compares the arguments with the specified objects and fails if // they do not exactly match. func (args Arguments) Assert(t TestingT, objects ...interface{}) bool { // get the differences diff, diffCount := args.Diff(objects) if diffCount == 0 { return true } // there are differences... report them... t.Logf(diff) t.Errorf("%sArguments do not match.", assert.CallerInfo()) return false } // String gets the argument at the specified index. Panics if there is no argument, or // if the argument is of the wrong type. // // If no index is provided, String() returns a complete string representation // of the arguments. func (args Arguments) String(indexOrNil ...int) string { if len(indexOrNil) == 0 { // normal String() method - return a string representation of the args var argsStr []string for _, arg := range args { argsStr = append(argsStr, fmt.Sprintf("%s", reflect.TypeOf(arg))) } return strings.Join(argsStr, ",") } else if len(indexOrNil) == 1 { // Index has been specified - get the argument at that index var index = indexOrNil[0] var s string var ok bool if s, ok = args.Get(index).(string); !ok { panic(fmt.Sprintf("assert: arguments: String(%d) failed because object wasn't correct type: %s", index, args.Get(index))) } return s } panic(fmt.Sprintf("assert: arguments: Wrong number of arguments passed to String. Must be 0 or 1, not %d", len(indexOrNil))) } // Int gets the argument at the specified index. Panics if there is no argument, or // if the argument is of the wrong type. func (args Arguments) Int(index int) int { var s int var ok bool if s, ok = args.Get(index).(int); !ok { panic(fmt.Sprintf("assert: arguments: Int(%d) failed because object wasn't correct type: %v", index, args.Get(index))) } return s } // Error gets the argument at the specified index. Panics if there is no argument, or // if the argument is of the wrong type. func (args Arguments) Error(index int) error { obj := args.Get(index) var s error var ok bool if obj == nil { return nil } if s, ok = obj.(error); !ok { panic(fmt.Sprintf("assert: arguments: Error(%d) failed because object wasn't correct type: %v", index, args.Get(index))) } return s } // Bool gets the argument at the specified index. Panics if there is no argument, or // if the argument is of the wrong type. func (args Arguments) Bool(index int) bool { var s bool var ok bool if s, ok = args.Get(index).(bool); !ok { panic(fmt.Sprintf("assert: arguments: Bool(%d) failed because object wasn't correct type: %v", index, args.Get(index))) } return s } lxd-2.0.0/dist/src/github.com/stretchr/testify/README.md0000644061062106075000000002543412702772371025323 0ustar00stgraberdomain admins00000000000000Testify - Thou Shalt Write Tests ================================ [![Build Status](https://travis-ci.org/stretchr/testify.svg)](https://travis-ci.org/stretchr/testify) Go code (golang) set of packages that provide many tools for testifying that your code will behave as you intend. Features include: * [Easy assertions](#assert-package) * [Mocking](#mock-package) * [HTTP response trapping](#http-package) * [Testing suite interfaces and functions](#suite-package) Get started: * Install testify with [one line of code](#installation), or [update it with another](#staying-up-to-date) * For an introduction to writing test code in Go, see http://golang.org/doc/code.html#Testing * Check out the API Documentation http://godoc.org/github.com/stretchr/testify * To make your testing life easier, check out our other project, [gorc](http://github.com/stretchr/gorc) * A little about [Test-Driven Development (TDD)](http://en.wikipedia.org/wiki/Test-driven_development) [`assert`](http://godoc.org/github.com/stretchr/testify/assert "API documentation") package ------------------------------------------------------------------------------------------- The `assert` package provides some helpful methods that allow you to write better test code in Go. * Prints friendly, easy to read failure descriptions * Allows for very readable code * Optionally annotate each assertion with a message See it in action: ```go package yours import ( "testing" "github.com/stretchr/testify/assert" ) func TestSomething(t *testing.T) { // assert equality assert.Equal(t, 123, 123, "they should be equal") // assert inequality assert.NotEqual(t, 123, 456, "they should not be equal") // assert for nil (good for errors) assert.Nil(t, object) // assert for not nil (good when you expect something) if assert.NotNil(t, object) { // now we know that object isn't nil, we are safe to make // further assertions without causing any errors assert.Equal(t, "Something", object.Value) } } ``` * Every assert func takes the `testing.T` object as the first argument. This is how it writes the errors out through the normal `go test` capabilities. * Every assert func returns a bool indicating whether the assertion was successful or not, this is useful for if you want to go on making further assertions under certain conditions. if you assert many times, use the below: ```go package yours import ( "testing" "github.com/stretchr/testify/assert" ) func TestSomething(t *testing.T) { assert := assert.New(t) // assert equality assert.Equal(123, 123, "they should be equal") // assert inequality assert.NotEqual(123, 456, "they should not be equal") // assert for nil (good for errors) assert.Nil(object) // assert for not nil (good when you expect something) if assert.NotNil(object) { // now we know that object isn't nil, we are safe to make // further assertions without causing any errors assert.Equal("Something", object.Value) } } ``` [`require`](http://godoc.org/github.com/stretchr/testify/require "API documentation") package --------------------------------------------------------------------------------------------- The `require` package provides same global functions as the `assert` package, but instead of returning a boolean result they terminate current test. See [t.FailNow](http://golang.org/pkg/testing/#T.FailNow) for details. [`http`](http://godoc.org/github.com/stretchr/testify/http "API documentation") package --------------------------------------------------------------------------------------- The `http` package contains test objects useful for testing code that relies on the `net/http` package. Check out the [(deprecated) API documentation for the `http` package](http://godoc.org/github.com/stretchr/testify/http). We recommend you use [httptest](http://golang.org/pkg/net/http/httptest) instead. [`mock`](http://godoc.org/github.com/stretchr/testify/mock "API documentation") package ---------------------------------------------------------------------------------------- The `mock` package provides a mechanism for easily writing mock objects that can be used in place of real objects when writing test code. An example test function that tests a piece of code that relies on an external object `testObj`, can setup expectations (testify) and assert that they indeed happened: ```go package yours import ( "testing" "github.com/stretchr/testify/mock" ) /* Test objects */ // MyMockedObject is a mocked object that implements an interface // that describes an object that the code I am testing relies on. type MyMockedObject struct{ mock.Mock } // DoSomething is a method on MyMockedObject that implements some interface // and just records the activity, and returns what the Mock object tells it to. // // In the real object, this method would do something useful, but since this // is a mocked object - we're just going to stub it out. // // NOTE: This method is not being tested here, code that uses this object is. func (m *MyMockedObject) DoSomething(number int) (bool, error) { args := m.Called(number) return args.Bool(0), args.Error(1) } /* Actual test functions */ // TestSomething is an example of how to use our test object to // make assertions about some target code we are testing. func TestSomething(t *testing.T) { // create an instance of our test object testObj := new(MyMockedObject) // setup expectations testObj.On("DoSomething", 123).Return(true, nil) // call the code we are testing targetFuncThatDoesSomethingWithObj(testObj) // assert that the expectations were met testObj.AssertExpectations(t) } ``` For more information on how to write mock code, check out the [API documentation for the `mock` package](http://godoc.org/github.com/stretchr/testify/mock). You can use the [mockery tool](http://github.com/vektra/mockery) to autogenerate the mock code against an interface as well, making using mocks much quicker. [`suite`](http://godoc.org/github.com/stretchr/testify/suite "API documentation") package ----------------------------------------------------------------------------------------- The `suite` package provides functionality that you might be used to from more common object oriented languages. With it, you can build a testing suite as a struct, build setup/teardown methods and testing methods on your struct, and run them with 'go test' as per normal. An example suite is shown below: ```go // Basic imports import ( "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/suite" ) // Define the suite, and absorb the built-in basic suite // functionality from testify - including a T() method which // returns the current testing context type ExampleTestSuite struct { suite.Suite VariableThatShouldStartAtFive int } // Make sure that VariableThatShouldStartAtFive is set to five // before each test func (suite *ExampleTestSuite) SetupTest() { suite.VariableThatShouldStartAtFive = 5 } // All methods that begin with "Test" are run as tests within a // suite. func (suite *ExampleTestSuite) TestExample() { assert.Equal(suite.T(), 5, suite.VariableThatShouldStartAtFive) } // In order for 'go test' to run this suite, we need to create // a normal test function and pass our suite to suite.Run func TestExampleTestSuite(t *testing.T) { suite.Run(t, new(ExampleTestSuite)) } ``` For a more complete example, using all of the functionality provided by the suite package, look at our [example testing suite](https://github.com/stretchr/testify/blob/master/suite/suite_test.go) For more information on writing suites, check out the [API documentation for the `suite` package](http://godoc.org/github.com/stretchr/testify/suite). `Suite` object has assertion methods: ```go // Basic imports import ( "testing" "github.com/stretchr/testify/suite" ) // Define the suite, and absorb the built-in basic suite // functionality from testify - including assertion methods. type ExampleTestSuite struct { suite.Suite VariableThatShouldStartAtFive int } // Make sure that VariableThatShouldStartAtFive is set to five // before each test func (suite *ExampleTestSuite) SetupTest() { suite.VariableThatShouldStartAtFive = 5 } // All methods that begin with "Test" are run as tests within a // suite. func (suite *ExampleTestSuite) TestExample() { suite.Equal(suite.VariableThatShouldStartAtFive, 5) } // In order for 'go test' to run this suite, we need to create // a normal test function and pass our suite to suite.Run func TestExampleTestSuite(t *testing.T) { suite.Run(t, new(ExampleTestSuite)) } ``` ------ Installation ============ To install Testify, use `go get`: * Latest version: go get github.com/stretchr/testify * Specific version: go get gopkg.in/stretchr/testify.v1 This will then make the following packages available to you: github.com/stretchr/testify/assert github.com/stretchr/testify/mock github.com/stretchr/testify/http Import the `testify/assert` package into your code using this template: ```go package yours import ( "testing" "github.com/stretchr/testify/assert" ) func TestSomething(t *testing.T) { assert.True(t, true, "True is true!") } ``` ------ Staying up to date ================== To update Testify to the latest version, use `go get -u github.com/stretchr/testify`. ------ Version History =============== * 1.0 - New package versioning strategy adopted. ------ Contributing ============ Please feel free to submit issues, fork the repository and send pull requests! When submitting an issue, we ask that you please include a complete test function that demonstrates the issue. Extra credit for those using Testify to write the test code that demonstrates it. ------ Licence ======= Copyright (c) 2012 - 2013 Mat Ryer and Tyler Bunnell Please consider promoting this project if you find it useful. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. lxd-2.0.0/dist/src/github.com/stretchr/testify/require/0000755061062106075000000000000012702772371025510 5ustar00stgraberdomain admins00000000000000lxd-2.0.0/dist/src/github.com/stretchr/testify/require/requirements.go0000644061062106075000000000036612702772371030567 0ustar00stgraberdomain admins00000000000000package require // TestingT is an interface wrapper around *testing.T type TestingT interface { Errorf(format string, args ...interface{}) FailNow() } //go:generate go run ../_codegen/main.go -output-package=require -template=require.go.tmpl lxd-2.0.0/dist/src/github.com/stretchr/testify/require/forward_requirements.go0000644061062106075000000000055612702772371032314 0ustar00stgraberdomain admins00000000000000package require // Assertions provides assertion methods around the // TestingT interface. type Assertions struct { t TestingT } // New makes a new Assertions object for the specified TestingT. func New(t TestingT) *Assertions { return &Assertions{ t: t, } } //go:generate go run ../_codegen/main.go -output-package=require -template=require_forward.go.tmpl lxd-2.0.0/dist/src/github.com/stretchr/testify/require/doc.go0000644061062106075000000000155412702772371026611 0ustar00stgraberdomain admins00000000000000// Package require implements the same assertions as the `assert` package but // stops test execution when a test fails. // // Example Usage // // The following is a complete example using require in a standard test function: // import ( // "testing" // "github.com/stretchr/testify/require" // ) // // func TestSomething(t *testing.T) { // // var a string = "Hello" // var b string = "Hello" // // require.Equal(t, a, b, "The two words should be the same.") // // } // // Assertions // // The `require` package have same global functions as in the `assert` package, // but instead of returning a boolean result they call `t.FailNow()`. // // Every assertion function also takes an optional string message as the final argument, // allowing custom error messages to be appended to the message the assertion method outputs. package require lxd-2.0.0/dist/src/github.com/stretchr/testify/require/require_forward.go.tmpl0000644061062106075000000000017712702772371032217 0ustar00stgraberdomain admins00000000000000{{.CommentWithoutT "a"}} func (a *Assertions) {{.DocInfo.Name}}({{.Params}}) { {{.DocInfo.Name}}(a.t, {{.ForwardedParams}}) } lxd-2.0.0/dist/src/github.com/stretchr/testify/require/requirements_test.go0000644061062106075000000001626212702772371031630 0ustar00stgraberdomain admins00000000000000package require import ( "errors" "testing" "time" ) // AssertionTesterInterface defines an interface to be used for testing assertion methods type AssertionTesterInterface interface { TestMethod() } // AssertionTesterConformingObject is an object that conforms to the AssertionTesterInterface interface type AssertionTesterConformingObject struct { } func (a *AssertionTesterConformingObject) TestMethod() { } // AssertionTesterNonConformingObject is an object that does not conform to the AssertionTesterInterface interface type AssertionTesterNonConformingObject struct { } type MockT struct { Failed bool } func (t *MockT) FailNow() { t.Failed = true } func (t *MockT) Errorf(format string, args ...interface{}) { _, _ = format, args } func TestImplements(t *testing.T) { Implements(t, (*AssertionTesterInterface)(nil), new(AssertionTesterConformingObject)) mockT := new(MockT) Implements(mockT, (*AssertionTesterInterface)(nil), new(AssertionTesterNonConformingObject)) if !mockT.Failed { t.Error("Check should fail") } } func TestIsType(t *testing.T) { IsType(t, new(AssertionTesterConformingObject), new(AssertionTesterConformingObject)) mockT := new(MockT) IsType(mockT, new(AssertionTesterConformingObject), new(AssertionTesterNonConformingObject)) if !mockT.Failed { t.Error("Check should fail") } } func TestEqual(t *testing.T) { Equal(t, 1, 1) mockT := new(MockT) Equal(mockT, 1, 2) if !mockT.Failed { t.Error("Check should fail") } } func TestNotEqual(t *testing.T) { NotEqual(t, 1, 2) mockT := new(MockT) NotEqual(mockT, 2, 2) if !mockT.Failed { t.Error("Check should fail") } } func TestExactly(t *testing.T) { a := float32(1) b := float32(1) c := float64(1) Exactly(t, a, b) mockT := new(MockT) Exactly(mockT, a, c) if !mockT.Failed { t.Error("Check should fail") } } func TestNotNil(t *testing.T) { NotNil(t, new(AssertionTesterConformingObject)) mockT := new(MockT) NotNil(mockT, nil) if !mockT.Failed { t.Error("Check should fail") } } func TestNil(t *testing.T) { Nil(t, nil) mockT := new(MockT) Nil(mockT, new(AssertionTesterConformingObject)) if !mockT.Failed { t.Error("Check should fail") } } func TestTrue(t *testing.T) { True(t, true) mockT := new(MockT) True(mockT, false) if !mockT.Failed { t.Error("Check should fail") } } func TestFalse(t *testing.T) { False(t, false) mockT := new(MockT) False(mockT, true) if !mockT.Failed { t.Error("Check should fail") } } func TestContains(t *testing.T) { Contains(t, "Hello World", "Hello") mockT := new(MockT) Contains(mockT, "Hello World", "Salut") if !mockT.Failed { t.Error("Check should fail") } } func TestNotContains(t *testing.T) { NotContains(t, "Hello World", "Hello!") mockT := new(MockT) NotContains(mockT, "Hello World", "Hello") if !mockT.Failed { t.Error("Check should fail") } } func TestPanics(t *testing.T) { Panics(t, func() { panic("Panic!") }) mockT := new(MockT) Panics(mockT, func() {}) if !mockT.Failed { t.Error("Check should fail") } } func TestNotPanics(t *testing.T) { NotPanics(t, func() {}) mockT := new(MockT) NotPanics(mockT, func() { panic("Panic!") }) if !mockT.Failed { t.Error("Check should fail") } } func TestNoError(t *testing.T) { NoError(t, nil) mockT := new(MockT) NoError(mockT, errors.New("some error")) if !mockT.Failed { t.Error("Check should fail") } } func TestError(t *testing.T) { Error(t, errors.New("some error")) mockT := new(MockT) Error(mockT, nil) if !mockT.Failed { t.Error("Check should fail") } } func TestEqualError(t *testing.T) { EqualError(t, errors.New("some error"), "some error") mockT := new(MockT) EqualError(mockT, errors.New("some error"), "Not some error") if !mockT.Failed { t.Error("Check should fail") } } func TestEmpty(t *testing.T) { Empty(t, "") mockT := new(MockT) Empty(mockT, "x") if !mockT.Failed { t.Error("Check should fail") } } func TestNotEmpty(t *testing.T) { NotEmpty(t, "x") mockT := new(MockT) NotEmpty(mockT, "") if !mockT.Failed { t.Error("Check should fail") } } func TestWithinDuration(t *testing.T) { a := time.Now() b := a.Add(10 * time.Second) WithinDuration(t, a, b, 15*time.Second) mockT := new(MockT) WithinDuration(mockT, a, b, 5*time.Second) if !mockT.Failed { t.Error("Check should fail") } } func TestInDelta(t *testing.T) { InDelta(t, 1.001, 1, 0.01) mockT := new(MockT) InDelta(mockT, 1, 2, 0.5) if !mockT.Failed { t.Error("Check should fail") } } func TestZero(t *testing.T) { Zero(t, "") mockT := new(MockT) Zero(mockT, "x") if !mockT.Failed { t.Error("Check should fail") } } func TestNotZero(t *testing.T) { NotZero(t, "x") mockT := new(MockT) NotZero(mockT, "") if !mockT.Failed { t.Error("Check should fail") } } func TestJSONEq_EqualSONString(t *testing.T) { mockT := new(MockT) JSONEq(mockT, `{"hello": "world", "foo": "bar"}`, `{"hello": "world", "foo": "bar"}`) if mockT.Failed { t.Error("Check should pass") } } func TestJSONEq_EquivalentButNotEqual(t *testing.T) { mockT := new(MockT) JSONEq(mockT, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`) if mockT.Failed { t.Error("Check should pass") } } func TestJSONEq_HashOfArraysAndHashes(t *testing.T) { mockT := new(MockT) JSONEq(mockT, "{\r\n\t\"numeric\": 1.5,\r\n\t\"array\": [{\"foo\": \"bar\"}, 1, \"string\", [\"nested\", \"array\", 5.5]],\r\n\t\"hash\": {\"nested\": \"hash\", \"nested_slice\": [\"this\", \"is\", \"nested\"]},\r\n\t\"string\": \"foo\"\r\n}", "{\r\n\t\"numeric\": 1.5,\r\n\t\"hash\": {\"nested\": \"hash\", \"nested_slice\": [\"this\", \"is\", \"nested\"]},\r\n\t\"string\": \"foo\",\r\n\t\"array\": [{\"foo\": \"bar\"}, 1, \"string\", [\"nested\", \"array\", 5.5]]\r\n}") if mockT.Failed { t.Error("Check should pass") } } func TestJSONEq_Array(t *testing.T) { mockT := new(MockT) JSONEq(mockT, `["foo", {"hello": "world", "nested": "hash"}]`, `["foo", {"nested": "hash", "hello": "world"}]`) if mockT.Failed { t.Error("Check should pass") } } func TestJSONEq_HashAndArrayNotEquivalent(t *testing.T) { mockT := new(MockT) JSONEq(mockT, `["foo", {"hello": "world", "nested": "hash"}]`, `{"foo": "bar", {"nested": "hash", "hello": "world"}}`) if !mockT.Failed { t.Error("Check should fail") } } func TestJSONEq_HashesNotEquivalent(t *testing.T) { mockT := new(MockT) JSONEq(mockT, `{"foo": "bar"}`, `{"foo": "bar", "hello": "world"}`) if !mockT.Failed { t.Error("Check should fail") } } func TestJSONEq_ActualIsNotJSON(t *testing.T) { mockT := new(MockT) JSONEq(mockT, `{"foo": "bar"}`, "Not JSON") if !mockT.Failed { t.Error("Check should fail") } } func TestJSONEq_ExpectedIsNotJSON(t *testing.T) { mockT := new(MockT) JSONEq(mockT, "Not JSON", `{"foo": "bar", "hello": "world"}`) if !mockT.Failed { t.Error("Check should fail") } } func TestJSONEq_ExpectedAndActualNotJSON(t *testing.T) { mockT := new(MockT) JSONEq(mockT, "Not JSON", "Not JSON") if !mockT.Failed { t.Error("Check should fail") } } func TestJSONEq_ArraysOfDifferentOrder(t *testing.T) { mockT := new(MockT) JSONEq(mockT, `["foo", {"hello": "world", "nested": "hash"}]`, `[{ "hello": "world", "nested": "hash"}, "foo"]`) if !mockT.Failed { t.Error("Check should fail") } } lxd-2.0.0/dist/src/github.com/stretchr/testify/require/require.go0000644061062106075000000003504612702772371027523 0ustar00stgraberdomain admins00000000000000/* * CODE GENERATED AUTOMATICALLY WITH github.com/stretchr/testify/_codegen * THIS FILE MUST NOT BE EDITED BY HAND */ package require import ( assert "github.com/stretchr/testify/assert" http "net/http" url "net/url" time "time" ) // Condition uses a Comparison to assert a complex condition. func Condition(t TestingT, comp assert.Comparison, msgAndArgs ...interface{}) { if !assert.Condition(t, comp, msgAndArgs...) { t.FailNow() } } // Contains asserts that the specified string, list(array, slice...) or map contains the // specified substring or element. // // assert.Contains(t, "Hello World", "World", "But 'Hello World' does contain 'World'") // assert.Contains(t, ["Hello", "World"], "World", "But ["Hello", "World"] does contain 'World'") // assert.Contains(t, {"Hello": "World"}, "Hello", "But {'Hello': 'World'} does contain 'Hello'") // // Returns whether the assertion was successful (true) or not (false). func Contains(t TestingT, s interface{}, contains interface{}, msgAndArgs ...interface{}) { if !assert.Contains(t, s, contains, msgAndArgs...) { t.FailNow() } } // Empty asserts that the specified object is empty. I.e. nil, "", false, 0 or either // a slice or a channel with len == 0. // // assert.Empty(t, obj) // // Returns whether the assertion was successful (true) or not (false). func Empty(t TestingT, object interface{}, msgAndArgs ...interface{}) { if !assert.Empty(t, object, msgAndArgs...) { t.FailNow() } } // Equal asserts that two objects are equal. // // assert.Equal(t, 123, 123, "123 and 123 should be equal") // // Returns whether the assertion was successful (true) or not (false). func Equal(t TestingT, expected interface{}, actual interface{}, msgAndArgs ...interface{}) { if !assert.Equal(t, expected, actual, msgAndArgs...) { t.FailNow() } } // EqualError asserts that a function returned an error (i.e. not `nil`) // and that it is equal to the provided error. // // actualObj, err := SomeFunction() // if assert.Error(t, err, "An error was expected") { // assert.Equal(t, err, expectedError) // } // // Returns whether the assertion was successful (true) or not (false). func EqualError(t TestingT, theError error, errString string, msgAndArgs ...interface{}) { if !assert.EqualError(t, theError, errString, msgAndArgs...) { t.FailNow() } } // EqualValues asserts that two objects are equal or convertable to the same types // and equal. // // assert.EqualValues(t, uint32(123), int32(123), "123 and 123 should be equal") // // Returns whether the assertion was successful (true) or not (false). func EqualValues(t TestingT, expected interface{}, actual interface{}, msgAndArgs ...interface{}) { if !assert.EqualValues(t, expected, actual, msgAndArgs...) { t.FailNow() } } // Error asserts that a function returned an error (i.e. not `nil`). // // actualObj, err := SomeFunction() // if assert.Error(t, err, "An error was expected") { // assert.Equal(t, err, expectedError) // } // // Returns whether the assertion was successful (true) or not (false). func Error(t TestingT, err error, msgAndArgs ...interface{}) { if !assert.Error(t, err, msgAndArgs...) { t.FailNow() } } // Exactly asserts that two objects are equal is value and type. // // assert.Exactly(t, int32(123), int64(123), "123 and 123 should NOT be equal") // // Returns whether the assertion was successful (true) or not (false). func Exactly(t TestingT, expected interface{}, actual interface{}, msgAndArgs ...interface{}) { if !assert.Exactly(t, expected, actual, msgAndArgs...) { t.FailNow() } } // Fail reports a failure through func Fail(t TestingT, failureMessage string, msgAndArgs ...interface{}) { if !assert.Fail(t, failureMessage, msgAndArgs...) { t.FailNow() } } // FailNow fails test func FailNow(t TestingT, failureMessage string, msgAndArgs ...interface{}) { if !assert.FailNow(t, failureMessage, msgAndArgs...) { t.FailNow() } } // False asserts that the specified value is false. // // assert.False(t, myBool, "myBool should be false") // // Returns whether the assertion was successful (true) or not (false). func False(t TestingT, value bool, msgAndArgs ...interface{}) { if !assert.False(t, value, msgAndArgs...) { t.FailNow() } } // HTTPBodyContains asserts that a specified handler returns a // body that contains a string. // // assert.HTTPBodyContains(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky") // // Returns whether the assertion was successful (true) or not (false). func HTTPBodyContains(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}) { if !assert.HTTPBodyContains(t, handler, method, url, values, str) { t.FailNow() } } // HTTPBodyNotContains asserts that a specified handler returns a // body that does not contain a string. // // assert.HTTPBodyNotContains(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky") // // Returns whether the assertion was successful (true) or not (false). func HTTPBodyNotContains(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}) { if !assert.HTTPBodyNotContains(t, handler, method, url, values, str) { t.FailNow() } } // HTTPError asserts that a specified handler returns an error status code. // // assert.HTTPError(t, myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}} // // Returns whether the assertion was successful (true) or not (false). func HTTPError(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values) { if !assert.HTTPError(t, handler, method, url, values) { t.FailNow() } } // HTTPRedirect asserts that a specified handler returns a redirect status code. // // assert.HTTPRedirect(t, myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}} // // Returns whether the assertion was successful (true) or not (false). func HTTPRedirect(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values) { if !assert.HTTPRedirect(t, handler, method, url, values) { t.FailNow() } } // HTTPSuccess asserts that a specified handler returns a success status code. // // assert.HTTPSuccess(t, myHandler, "POST", "http://www.google.com", nil) // // Returns whether the assertion was successful (true) or not (false). func HTTPSuccess(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values) { if !assert.HTTPSuccess(t, handler, method, url, values) { t.FailNow() } } // Implements asserts that an object is implemented by the specified interface. // // assert.Implements(t, (*MyInterface)(nil), new(MyObject), "MyObject") func Implements(t TestingT, interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) { if !assert.Implements(t, interfaceObject, object, msgAndArgs...) { t.FailNow() } } // InDelta asserts that the two numerals are within delta of each other. // // assert.InDelta(t, math.Pi, (22 / 7.0), 0.01) // // Returns whether the assertion was successful (true) or not (false). func InDelta(t TestingT, expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) { if !assert.InDelta(t, expected, actual, delta, msgAndArgs...) { t.FailNow() } } // InDeltaSlice is the same as InDelta, except it compares two slices. func InDeltaSlice(t TestingT, expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) { if !assert.InDeltaSlice(t, expected, actual, delta, msgAndArgs...) { t.FailNow() } } // InEpsilon asserts that expected and actual have a relative error less than epsilon // // Returns whether the assertion was successful (true) or not (false). func InEpsilon(t TestingT, expected interface{}, actual interface{}, epsilon float64, msgAndArgs ...interface{}) { if !assert.InEpsilon(t, expected, actual, epsilon, msgAndArgs...) { t.FailNow() } } // InEpsilonSlice is the same as InEpsilon, except it compares two slices. func InEpsilonSlice(t TestingT, expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) { if !assert.InEpsilonSlice(t, expected, actual, delta, msgAndArgs...) { t.FailNow() } } // IsType asserts that the specified objects are of the same type. func IsType(t TestingT, expectedType interface{}, object interface{}, msgAndArgs ...interface{}) { if !assert.IsType(t, expectedType, object, msgAndArgs...) { t.FailNow() } } // JSONEq asserts that two JSON strings are equivalent. // // assert.JSONEq(t, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`) // // Returns whether the assertion was successful (true) or not (false). func JSONEq(t TestingT, expected string, actual string, msgAndArgs ...interface{}) { if !assert.JSONEq(t, expected, actual, msgAndArgs...) { t.FailNow() } } // Len asserts that the specified object has specific length. // Len also fails if the object has a type that len() not accept. // // assert.Len(t, mySlice, 3, "The size of slice is not 3") // // Returns whether the assertion was successful (true) or not (false). func Len(t TestingT, object interface{}, length int, msgAndArgs ...interface{}) { if !assert.Len(t, object, length, msgAndArgs...) { t.FailNow() } } // Nil asserts that the specified object is nil. // // assert.Nil(t, err, "err should be nothing") // // Returns whether the assertion was successful (true) or not (false). func Nil(t TestingT, object interface{}, msgAndArgs ...interface{}) { if !assert.Nil(t, object, msgAndArgs...) { t.FailNow() } } // NoError asserts that a function returned no error (i.e. `nil`). // // actualObj, err := SomeFunction() // if assert.NoError(t, err) { // assert.Equal(t, actualObj, expectedObj) // } // // Returns whether the assertion was successful (true) or not (false). func NoError(t TestingT, err error, msgAndArgs ...interface{}) { if !assert.NoError(t, err, msgAndArgs...) { t.FailNow() } } // NotContains asserts that the specified string, list(array, slice...) or map does NOT contain the // specified substring or element. // // assert.NotContains(t, "Hello World", "Earth", "But 'Hello World' does NOT contain 'Earth'") // assert.NotContains(t, ["Hello", "World"], "Earth", "But ['Hello', 'World'] does NOT contain 'Earth'") // assert.NotContains(t, {"Hello": "World"}, "Earth", "But {'Hello': 'World'} does NOT contain 'Earth'") // // Returns whether the assertion was successful (true) or not (false). func NotContains(t TestingT, s interface{}, contains interface{}, msgAndArgs ...interface{}) { if !assert.NotContains(t, s, contains, msgAndArgs...) { t.FailNow() } } // NotEmpty asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either // a slice or a channel with len == 0. // // if assert.NotEmpty(t, obj) { // assert.Equal(t, "two", obj[1]) // } // // Returns whether the assertion was successful (true) or not (false). func NotEmpty(t TestingT, object interface{}, msgAndArgs ...interface{}) { if !assert.NotEmpty(t, object, msgAndArgs...) { t.FailNow() } } // NotEqual asserts that the specified values are NOT equal. // // assert.NotEqual(t, obj1, obj2, "two objects shouldn't be equal") // // Returns whether the assertion was successful (true) or not (false). func NotEqual(t TestingT, expected interface{}, actual interface{}, msgAndArgs ...interface{}) { if !assert.NotEqual(t, expected, actual, msgAndArgs...) { t.FailNow() } } // NotNil asserts that the specified object is not nil. // // assert.NotNil(t, err, "err should be something") // // Returns whether the assertion was successful (true) or not (false). func NotNil(t TestingT, object interface{}, msgAndArgs ...interface{}) { if !assert.NotNil(t, object, msgAndArgs...) { t.FailNow() } } // NotPanics asserts that the code inside the specified PanicTestFunc does NOT panic. // // assert.NotPanics(t, func(){ // RemainCalm() // }, "Calling RemainCalm() should NOT panic") // // Returns whether the assertion was successful (true) or not (false). func NotPanics(t TestingT, f assert.PanicTestFunc, msgAndArgs ...interface{}) { if !assert.NotPanics(t, f, msgAndArgs...) { t.FailNow() } } // NotRegexp asserts that a specified regexp does not match a string. // // assert.NotRegexp(t, regexp.MustCompile("starts"), "it's starting") // assert.NotRegexp(t, "^start", "it's not starting") // // Returns whether the assertion was successful (true) or not (false). func NotRegexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interface{}) { if !assert.NotRegexp(t, rx, str, msgAndArgs...) { t.FailNow() } } // NotZero asserts that i is not the zero value for its type and returns the truth. func NotZero(t TestingT, i interface{}, msgAndArgs ...interface{}) { if !assert.NotZero(t, i, msgAndArgs...) { t.FailNow() } } // Panics asserts that the code inside the specified PanicTestFunc panics. // // assert.Panics(t, func(){ // GoCrazy() // }, "Calling GoCrazy() should panic") // // Returns whether the assertion was successful (true) or not (false). func Panics(t TestingT, f assert.PanicTestFunc, msgAndArgs ...interface{}) { if !assert.Panics(t, f, msgAndArgs...) { t.FailNow() } } // Regexp asserts that a specified regexp matches a string. // // assert.Regexp(t, regexp.MustCompile("start"), "it's starting") // assert.Regexp(t, "start...$", "it's not starting") // // Returns whether the assertion was successful (true) or not (false). func Regexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interface{}) { if !assert.Regexp(t, rx, str, msgAndArgs...) { t.FailNow() } } // True asserts that the specified value is true. // // assert.True(t, myBool, "myBool should be true") // // Returns whether the assertion was successful (true) or not (false). func True(t TestingT, value bool, msgAndArgs ...interface{}) { if !assert.True(t, value, msgAndArgs...) { t.FailNow() } } // WithinDuration asserts that the two times are within duration delta of each other. // // assert.WithinDuration(t, time.Now(), time.Now(), 10*time.Second, "The difference should not be more than 10s") // // Returns whether the assertion was successful (true) or not (false). func WithinDuration(t TestingT, expected time.Time, actual time.Time, delta time.Duration, msgAndArgs ...interface{}) { if !assert.WithinDuration(t, expected, actual, delta, msgAndArgs...) { t.FailNow() } } // Zero asserts that i is the zero value for its type and returns the truth. func Zero(t TestingT, i interface{}, msgAndArgs ...interface{}) { if !assert.Zero(t, i, msgAndArgs...) { t.FailNow() } } lxd-2.0.0/dist/src/github.com/stretchr/testify/require/require.go.tmpl0000644061062106075000000000021712702772371030466 0ustar00stgraberdomain admins00000000000000{{.Comment}} func {{.DocInfo.Name}}(t TestingT, {{.Params}}) { if !assert.{{.DocInfo.Name}}(t, {{.ForwardedParams}}) { t.FailNow() } } lxd-2.0.0/dist/src/github.com/stretchr/testify/require/require_forward.go0000644061062106075000000003235612702772371031250 0ustar00stgraberdomain admins00000000000000/* * CODE GENERATED AUTOMATICALLY WITH github.com/stretchr/testify/_codegen * THIS FILE MUST NOT BE EDITED BY HAND */ package require import ( assert "github.com/stretchr/testify/assert" http "net/http" url "net/url" time "time" ) // Condition uses a Comparison to assert a complex condition. func (a *Assertions) Condition(comp assert.Comparison, msgAndArgs ...interface{}) { Condition(a.t, comp, msgAndArgs...) } // Contains asserts that the specified string, list(array, slice...) or map contains the // specified substring or element. // // a.Contains("Hello World", "World", "But 'Hello World' does contain 'World'") // a.Contains(["Hello", "World"], "World", "But ["Hello", "World"] does contain 'World'") // a.Contains({"Hello": "World"}, "Hello", "But {'Hello': 'World'} does contain 'Hello'") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) Contains(s interface{}, contains interface{}, msgAndArgs ...interface{}) { Contains(a.t, s, contains, msgAndArgs...) } // Empty asserts that the specified object is empty. I.e. nil, "", false, 0 or either // a slice or a channel with len == 0. // // a.Empty(obj) // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) Empty(object interface{}, msgAndArgs ...interface{}) { Empty(a.t, object, msgAndArgs...) } // Equal asserts that two objects are equal. // // a.Equal(123, 123, "123 and 123 should be equal") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) Equal(expected interface{}, actual interface{}, msgAndArgs ...interface{}) { Equal(a.t, expected, actual, msgAndArgs...) } // EqualError asserts that a function returned an error (i.e. not `nil`) // and that it is equal to the provided error. // // actualObj, err := SomeFunction() // if assert.Error(t, err, "An error was expected") { // assert.Equal(t, err, expectedError) // } // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) EqualError(theError error, errString string, msgAndArgs ...interface{}) { EqualError(a.t, theError, errString, msgAndArgs...) } // EqualValues asserts that two objects are equal or convertable to the same types // and equal. // // a.EqualValues(uint32(123), int32(123), "123 and 123 should be equal") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) EqualValues(expected interface{}, actual interface{}, msgAndArgs ...interface{}) { EqualValues(a.t, expected, actual, msgAndArgs...) } // Error asserts that a function returned an error (i.e. not `nil`). // // actualObj, err := SomeFunction() // if a.Error(err, "An error was expected") { // assert.Equal(t, err, expectedError) // } // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) Error(err error, msgAndArgs ...interface{}) { Error(a.t, err, msgAndArgs...) } // Exactly asserts that two objects are equal is value and type. // // a.Exactly(int32(123), int64(123), "123 and 123 should NOT be equal") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) Exactly(expected interface{}, actual interface{}, msgAndArgs ...interface{}) { Exactly(a.t, expected, actual, msgAndArgs...) } // Fail reports a failure through func (a *Assertions) Fail(failureMessage string, msgAndArgs ...interface{}) { Fail(a.t, failureMessage, msgAndArgs...) } // FailNow fails test func (a *Assertions) FailNow(failureMessage string, msgAndArgs ...interface{}) { FailNow(a.t, failureMessage, msgAndArgs...) } // False asserts that the specified value is false. // // a.False(myBool, "myBool should be false") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) False(value bool, msgAndArgs ...interface{}) { False(a.t, value, msgAndArgs...) } // HTTPBodyContains asserts that a specified handler returns a // body that contains a string. // // a.HTTPBodyContains(myHandler, "www.google.com", nil, "I'm Feeling Lucky") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPBodyContains(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}) { HTTPBodyContains(a.t, handler, method, url, values, str) } // HTTPBodyNotContains asserts that a specified handler returns a // body that does not contain a string. // // a.HTTPBodyNotContains(myHandler, "www.google.com", nil, "I'm Feeling Lucky") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPBodyNotContains(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}) { HTTPBodyNotContains(a.t, handler, method, url, values, str) } // HTTPError asserts that a specified handler returns an error status code. // // a.HTTPError(myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}} // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPError(handler http.HandlerFunc, method string, url string, values url.Values) { HTTPError(a.t, handler, method, url, values) } // HTTPRedirect asserts that a specified handler returns a redirect status code. // // a.HTTPRedirect(myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}} // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPRedirect(handler http.HandlerFunc, method string, url string, values url.Values) { HTTPRedirect(a.t, handler, method, url, values) } // HTTPSuccess asserts that a specified handler returns a success status code. // // a.HTTPSuccess(myHandler, "POST", "http://www.google.com", nil) // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPSuccess(handler http.HandlerFunc, method string, url string, values url.Values) { HTTPSuccess(a.t, handler, method, url, values) } // Implements asserts that an object is implemented by the specified interface. // // a.Implements((*MyInterface)(nil), new(MyObject), "MyObject") func (a *Assertions) Implements(interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) { Implements(a.t, interfaceObject, object, msgAndArgs...) } // InDelta asserts that the two numerals are within delta of each other. // // a.InDelta(math.Pi, (22 / 7.0), 0.01) // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) InDelta(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) { InDelta(a.t, expected, actual, delta, msgAndArgs...) } // InDeltaSlice is the same as InDelta, except it compares two slices. func (a *Assertions) InDeltaSlice(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) { InDeltaSlice(a.t, expected, actual, delta, msgAndArgs...) } // InEpsilon asserts that expected and actual have a relative error less than epsilon // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) InEpsilon(expected interface{}, actual interface{}, epsilon float64, msgAndArgs ...interface{}) { InEpsilon(a.t, expected, actual, epsilon, msgAndArgs...) } // InEpsilonSlice is the same as InEpsilon, except it compares two slices. func (a *Assertions) InEpsilonSlice(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) { InEpsilonSlice(a.t, expected, actual, delta, msgAndArgs...) } // IsType asserts that the specified objects are of the same type. func (a *Assertions) IsType(expectedType interface{}, object interface{}, msgAndArgs ...interface{}) { IsType(a.t, expectedType, object, msgAndArgs...) } // JSONEq asserts that two JSON strings are equivalent. // // a.JSONEq(`{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`) // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) JSONEq(expected string, actual string, msgAndArgs ...interface{}) { JSONEq(a.t, expected, actual, msgAndArgs...) } // Len asserts that the specified object has specific length. // Len also fails if the object has a type that len() not accept. // // a.Len(mySlice, 3, "The size of slice is not 3") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) Len(object interface{}, length int, msgAndArgs ...interface{}) { Len(a.t, object, length, msgAndArgs...) } // Nil asserts that the specified object is nil. // // a.Nil(err, "err should be nothing") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) Nil(object interface{}, msgAndArgs ...interface{}) { Nil(a.t, object, msgAndArgs...) } // NoError asserts that a function returned no error (i.e. `nil`). // // actualObj, err := SomeFunction() // if a.NoError(err) { // assert.Equal(t, actualObj, expectedObj) // } // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) NoError(err error, msgAndArgs ...interface{}) { NoError(a.t, err, msgAndArgs...) } // NotContains asserts that the specified string, list(array, slice...) or map does NOT contain the // specified substring or element. // // a.NotContains("Hello World", "Earth", "But 'Hello World' does NOT contain 'Earth'") // a.NotContains(["Hello", "World"], "Earth", "But ['Hello', 'World'] does NOT contain 'Earth'") // a.NotContains({"Hello": "World"}, "Earth", "But {'Hello': 'World'} does NOT contain 'Earth'") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) NotContains(s interface{}, contains interface{}, msgAndArgs ...interface{}) { NotContains(a.t, s, contains, msgAndArgs...) } // NotEmpty asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either // a slice or a channel with len == 0. // // if a.NotEmpty(obj) { // assert.Equal(t, "two", obj[1]) // } // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) NotEmpty(object interface{}, msgAndArgs ...interface{}) { NotEmpty(a.t, object, msgAndArgs...) } // NotEqual asserts that the specified values are NOT equal. // // a.NotEqual(obj1, obj2, "two objects shouldn't be equal") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) NotEqual(expected interface{}, actual interface{}, msgAndArgs ...interface{}) { NotEqual(a.t, expected, actual, msgAndArgs...) } // NotNil asserts that the specified object is not nil. // // a.NotNil(err, "err should be something") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) NotNil(object interface{}, msgAndArgs ...interface{}) { NotNil(a.t, object, msgAndArgs...) } // NotPanics asserts that the code inside the specified PanicTestFunc does NOT panic. // // a.NotPanics(func(){ // RemainCalm() // }, "Calling RemainCalm() should NOT panic") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) NotPanics(f assert.PanicTestFunc, msgAndArgs ...interface{}) { NotPanics(a.t, f, msgAndArgs...) } // NotRegexp asserts that a specified regexp does not match a string. // // a.NotRegexp(regexp.MustCompile("starts"), "it's starting") // a.NotRegexp("^start", "it's not starting") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) NotRegexp(rx interface{}, str interface{}, msgAndArgs ...interface{}) { NotRegexp(a.t, rx, str, msgAndArgs...) } // NotZero asserts that i is not the zero value for its type and returns the truth. func (a *Assertions) NotZero(i interface{}, msgAndArgs ...interface{}) { NotZero(a.t, i, msgAndArgs...) } // Panics asserts that the code inside the specified PanicTestFunc panics. // // a.Panics(func(){ // GoCrazy() // }, "Calling GoCrazy() should panic") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) Panics(f assert.PanicTestFunc, msgAndArgs ...interface{}) { Panics(a.t, f, msgAndArgs...) } // Regexp asserts that a specified regexp matches a string. // // a.Regexp(regexp.MustCompile("start"), "it's starting") // a.Regexp("start...$", "it's not starting") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) Regexp(rx interface{}, str interface{}, msgAndArgs ...interface{}) { Regexp(a.t, rx, str, msgAndArgs...) } // True asserts that the specified value is true. // // a.True(myBool, "myBool should be true") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) True(value bool, msgAndArgs ...interface{}) { True(a.t, value, msgAndArgs...) } // WithinDuration asserts that the two times are within duration delta of each other. // // a.WithinDuration(time.Now(), time.Now(), 10*time.Second, "The difference should not be more than 10s") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) WithinDuration(expected time.Time, actual time.Time, delta time.Duration, msgAndArgs ...interface{}) { WithinDuration(a.t, expected, actual, delta, msgAndArgs...) } // Zero asserts that i is the zero value for its type and returns the truth. func (a *Assertions) Zero(i interface{}, msgAndArgs ...interface{}) { Zero(a.t, i, msgAndArgs...) } lxd-2.0.0/dist/src/github.com/stretchr/testify/require/forward_requirements_test.go0000644061062106075000000002033312702772371033346 0ustar00stgraberdomain admins00000000000000package require import ( "errors" "testing" "time" ) func TestImplementsWrapper(t *testing.T) { require := New(t) require.Implements((*AssertionTesterInterface)(nil), new(AssertionTesterConformingObject)) mockT := new(MockT) mockRequire := New(mockT) mockRequire.Implements((*AssertionTesterInterface)(nil), new(AssertionTesterNonConformingObject)) if !mockT.Failed { t.Error("Check should fail") } } func TestIsTypeWrapper(t *testing.T) { require := New(t) require.IsType(new(AssertionTesterConformingObject), new(AssertionTesterConformingObject)) mockT := new(MockT) mockRequire := New(mockT) mockRequire.IsType(new(AssertionTesterConformingObject), new(AssertionTesterNonConformingObject)) if !mockT.Failed { t.Error("Check should fail") } } func TestEqualWrapper(t *testing.T) { require := New(t) require.Equal(1, 1) mockT := new(MockT) mockRequire := New(mockT) mockRequire.Equal(1, 2) if !mockT.Failed { t.Error("Check should fail") } } func TestNotEqualWrapper(t *testing.T) { require := New(t) require.NotEqual(1, 2) mockT := new(MockT) mockRequire := New(mockT) mockRequire.NotEqual(2, 2) if !mockT.Failed { t.Error("Check should fail") } } func TestExactlyWrapper(t *testing.T) { require := New(t) a := float32(1) b := float32(1) c := float64(1) require.Exactly(a, b) mockT := new(MockT) mockRequire := New(mockT) mockRequire.Exactly(a, c) if !mockT.Failed { t.Error("Check should fail") } } func TestNotNilWrapper(t *testing.T) { require := New(t) require.NotNil(t, new(AssertionTesterConformingObject)) mockT := new(MockT) mockRequire := New(mockT) mockRequire.NotNil(nil) if !mockT.Failed { t.Error("Check should fail") } } func TestNilWrapper(t *testing.T) { require := New(t) require.Nil(nil) mockT := new(MockT) mockRequire := New(mockT) mockRequire.Nil(new(AssertionTesterConformingObject)) if !mockT.Failed { t.Error("Check should fail") } } func TestTrueWrapper(t *testing.T) { require := New(t) require.True(true) mockT := new(MockT) mockRequire := New(mockT) mockRequire.True(false) if !mockT.Failed { t.Error("Check should fail") } } func TestFalseWrapper(t *testing.T) { require := New(t) require.False(false) mockT := new(MockT) mockRequire := New(mockT) mockRequire.False(true) if !mockT.Failed { t.Error("Check should fail") } } func TestContainsWrapper(t *testing.T) { require := New(t) require.Contains("Hello World", "Hello") mockT := new(MockT) mockRequire := New(mockT) mockRequire.Contains("Hello World", "Salut") if !mockT.Failed { t.Error("Check should fail") } } func TestNotContainsWrapper(t *testing.T) { require := New(t) require.NotContains("Hello World", "Hello!") mockT := new(MockT) mockRequire := New(mockT) mockRequire.NotContains("Hello World", "Hello") if !mockT.Failed { t.Error("Check should fail") } } func TestPanicsWrapper(t *testing.T) { require := New(t) require.Panics(func() { panic("Panic!") }) mockT := new(MockT) mockRequire := New(mockT) mockRequire.Panics(func() {}) if !mockT.Failed { t.Error("Check should fail") } } func TestNotPanicsWrapper(t *testing.T) { require := New(t) require.NotPanics(func() {}) mockT := new(MockT) mockRequire := New(mockT) mockRequire.NotPanics(func() { panic("Panic!") }) if !mockT.Failed { t.Error("Check should fail") } } func TestNoErrorWrapper(t *testing.T) { require := New(t) require.NoError(nil) mockT := new(MockT) mockRequire := New(mockT) mockRequire.NoError(errors.New("some error")) if !mockT.Failed { t.Error("Check should fail") } } func TestErrorWrapper(t *testing.T) { require := New(t) require.Error(errors.New("some error")) mockT := new(MockT) mockRequire := New(mockT) mockRequire.Error(nil) if !mockT.Failed { t.Error("Check should fail") } } func TestEqualErrorWrapper(t *testing.T) { require := New(t) require.EqualError(errors.New("some error"), "some error") mockT := new(MockT) mockRequire := New(mockT) mockRequire.EqualError(errors.New("some error"), "Not some error") if !mockT.Failed { t.Error("Check should fail") } } func TestEmptyWrapper(t *testing.T) { require := New(t) require.Empty("") mockT := new(MockT) mockRequire := New(mockT) mockRequire.Empty("x") if !mockT.Failed { t.Error("Check should fail") } } func TestNotEmptyWrapper(t *testing.T) { require := New(t) require.NotEmpty("x") mockT := new(MockT) mockRequire := New(mockT) mockRequire.NotEmpty("") if !mockT.Failed { t.Error("Check should fail") } } func TestWithinDurationWrapper(t *testing.T) { require := New(t) a := time.Now() b := a.Add(10 * time.Second) require.WithinDuration(a, b, 15*time.Second) mockT := new(MockT) mockRequire := New(mockT) mockRequire.WithinDuration(a, b, 5*time.Second) if !mockT.Failed { t.Error("Check should fail") } } func TestInDeltaWrapper(t *testing.T) { require := New(t) require.InDelta(1.001, 1, 0.01) mockT := new(MockT) mockRequire := New(mockT) mockRequire.InDelta(1, 2, 0.5) if !mockT.Failed { t.Error("Check should fail") } } func TestZeroWrapper(t *testing.T) { require := New(t) require.Zero(0) mockT := new(MockT) mockRequire := New(mockT) mockRequire.Zero(1) if !mockT.Failed { t.Error("Check should fail") } } func TestNotZeroWrapper(t *testing.T) { require := New(t) require.NotZero(1) mockT := new(MockT) mockRequire := New(mockT) mockRequire.NotZero(0) if !mockT.Failed { t.Error("Check should fail") } } func TestJSONEqWrapper_EqualSONString(t *testing.T) { mockT := new(MockT) mockRequire := New(mockT) mockRequire.JSONEq(`{"hello": "world", "foo": "bar"}`, `{"hello": "world", "foo": "bar"}`) if mockT.Failed { t.Error("Check should pass") } } func TestJSONEqWrapper_EquivalentButNotEqual(t *testing.T) { mockT := new(MockT) mockRequire := New(mockT) mockRequire.JSONEq(`{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`) if mockT.Failed { t.Error("Check should pass") } } func TestJSONEqWrapper_HashOfArraysAndHashes(t *testing.T) { mockT := new(MockT) mockRequire := New(mockT) mockRequire.JSONEq("{\r\n\t\"numeric\": 1.5,\r\n\t\"array\": [{\"foo\": \"bar\"}, 1, \"string\", [\"nested\", \"array\", 5.5]],\r\n\t\"hash\": {\"nested\": \"hash\", \"nested_slice\": [\"this\", \"is\", \"nested\"]},\r\n\t\"string\": \"foo\"\r\n}", "{\r\n\t\"numeric\": 1.5,\r\n\t\"hash\": {\"nested\": \"hash\", \"nested_slice\": [\"this\", \"is\", \"nested\"]},\r\n\t\"string\": \"foo\",\r\n\t\"array\": [{\"foo\": \"bar\"}, 1, \"string\", [\"nested\", \"array\", 5.5]]\r\n}") if mockT.Failed { t.Error("Check should pass") } } func TestJSONEqWrapper_Array(t *testing.T) { mockT := new(MockT) mockRequire := New(mockT) mockRequire.JSONEq(`["foo", {"hello": "world", "nested": "hash"}]`, `["foo", {"nested": "hash", "hello": "world"}]`) if mockT.Failed { t.Error("Check should pass") } } func TestJSONEqWrapper_HashAndArrayNotEquivalent(t *testing.T) { mockT := new(MockT) mockRequire := New(mockT) mockRequire.JSONEq(`["foo", {"hello": "world", "nested": "hash"}]`, `{"foo": "bar", {"nested": "hash", "hello": "world"}}`) if !mockT.Failed { t.Error("Check should fail") } } func TestJSONEqWrapper_HashesNotEquivalent(t *testing.T) { mockT := new(MockT) mockRequire := New(mockT) mockRequire.JSONEq(`{"foo": "bar"}`, `{"foo": "bar", "hello": "world"}`) if !mockT.Failed { t.Error("Check should fail") } } func TestJSONEqWrapper_ActualIsNotJSON(t *testing.T) { mockT := new(MockT) mockRequire := New(mockT) mockRequire.JSONEq(`{"foo": "bar"}`, "Not JSON") if !mockT.Failed { t.Error("Check should fail") } } func TestJSONEqWrapper_ExpectedIsNotJSON(t *testing.T) { mockT := new(MockT) mockRequire := New(mockT) mockRequire.JSONEq("Not JSON", `{"foo": "bar", "hello": "world"}`) if !mockT.Failed { t.Error("Check should fail") } } func TestJSONEqWrapper_ExpectedAndActualNotJSON(t *testing.T) { mockT := new(MockT) mockRequire := New(mockT) mockRequire.JSONEq("Not JSON", "Not JSON") if !mockT.Failed { t.Error("Check should fail") } } func TestJSONEqWrapper_ArraysOfDifferentOrder(t *testing.T) { mockT := new(MockT) mockRequire := New(mockT) mockRequire.JSONEq(`["foo", {"hello": "world", "nested": "hash"}]`, `[{ "hello": "world", "nested": "hash"}, "foo"]`) if !mockT.Failed { t.Error("Check should fail") } } lxd-2.0.0/dist/src/github.com/stretchr/testify/_codegen/0000755061062106075000000000000012702772371025577 5ustar00stgraberdomain admins00000000000000lxd-2.0.0/dist/src/github.com/stretchr/testify/_codegen/main.go0000644061062106075000000001465412702772371027064 0ustar00stgraberdomain admins00000000000000// This program reads all assertion functions from the assert package and // automatically generates the corersponding requires and forwarded assertions package main import ( "bytes" "flag" "fmt" "go/ast" "go/build" "go/doc" "go/importer" "go/parser" "go/token" "go/types" "io" "io/ioutil" "log" "os" "path" "strings" "text/template" "github.com/ernesto-jimenez/gogen/imports" ) var ( pkg = flag.String("assert-path", "github.com/stretchr/testify/assert", "Path to the assert package") outputPkg = flag.String("output-package", "", "package for the resulting code") tmplFile = flag.String("template", "", "What file to load the function template from") out = flag.String("out", "", "What file to write the source code to") ) func main() { flag.Parse() scope, docs, err := parsePackageSource(*pkg) if err != nil { log.Fatal(err) } importer, funcs, err := analyzeCode(scope, docs) if err != nil { log.Fatal(err) } if err := generateCode(importer, funcs); err != nil { log.Fatal(err) } } func generateCode(importer imports.Importer, funcs []testFunc) error { buff := bytes.NewBuffer(nil) tmplHead, tmplFunc, err := parseTemplates() if err != nil { return err } // Generate header if err := tmplHead.Execute(buff, struct { Name string Imports map[string]string }{ *outputPkg, importer.Imports(), }); err != nil { return err } // Generate funcs for _, fn := range funcs { buff.Write([]byte("\n\n")) if err := tmplFunc.Execute(buff, &fn); err != nil { return err } } // Write file output, err := outputFile() if err != nil { return err } defer output.Close() _, err = io.Copy(output, buff) return err } func parseTemplates() (*template.Template, *template.Template, error) { tmplHead, err := template.New("header").Parse(headerTemplate) if err != nil { return nil, nil, err } if *tmplFile != "" { f, err := ioutil.ReadFile(*tmplFile) if err != nil { return nil, nil, err } funcTemplate = string(f) } tmpl, err := template.New("function").Parse(funcTemplate) if err != nil { return nil, nil, err } return tmplHead, tmpl, nil } func outputFile() (*os.File, error) { filename := *out if filename == "-" || (filename == "" && *tmplFile == "") { return os.Stdout, nil } if filename == "" { filename = strings.TrimSuffix(strings.TrimSuffix(*tmplFile, ".tmpl"), ".go") + ".go" } return os.Create(filename) } // analyzeCode takes the types scope and the docs and returns the import // information and information about all the assertion functions. func analyzeCode(scope *types.Scope, docs *doc.Package) (imports.Importer, []testFunc, error) { testingT := scope.Lookup("TestingT").Type().Underlying().(*types.Interface) importer := imports.New(*outputPkg) var funcs []testFunc // Go through all the top level functions for _, fdocs := range docs.Funcs { // Find the function obj := scope.Lookup(fdocs.Name) fn, ok := obj.(*types.Func) if !ok { continue } // Check function signatuer has at least two arguments sig := fn.Type().(*types.Signature) if sig.Params().Len() < 2 { continue } // Check first argument is of type testingT first, ok := sig.Params().At(0).Type().(*types.Named) if !ok { continue } firstType, ok := first.Underlying().(*types.Interface) if !ok { continue } if !types.Implements(firstType, testingT) { continue } funcs = append(funcs, testFunc{*outputPkg, fdocs, fn}) importer.AddImportsFrom(sig.Params()) } return importer, funcs, nil } // parsePackageSource returns the types scope and the package documentation from the pa func parsePackageSource(pkg string) (*types.Scope, *doc.Package, error) { pd, err := build.Import(pkg, ".", 0) if err != nil { return nil, nil, err } fset := token.NewFileSet() files := make(map[string]*ast.File) fileList := make([]*ast.File, len(pd.GoFiles)) for i, fname := range pd.GoFiles { src, err := ioutil.ReadFile(path.Join(pd.SrcRoot, pd.ImportPath, fname)) if err != nil { return nil, nil, err } f, err := parser.ParseFile(fset, fname, src, parser.ParseComments|parser.AllErrors) if err != nil { return nil, nil, err } files[fname] = f fileList[i] = f } cfg := types.Config{ Importer: importer.Default(), } info := types.Info{ Defs: make(map[*ast.Ident]types.Object), } tp, err := cfg.Check(pkg, fset, fileList, &info) if err != nil { return nil, nil, err } scope := tp.Scope() ap, _ := ast.NewPackage(fset, files, nil, nil) docs := doc.New(ap, pkg, 0) return scope, docs, nil } type testFunc struct { CurrentPkg string DocInfo *doc.Func TypeInfo *types.Func } func (f *testFunc) Qualifier(p *types.Package) string { if p == nil || p.Name() == f.CurrentPkg { return "" } return p.Name() } func (f *testFunc) Params() string { sig := f.TypeInfo.Type().(*types.Signature) params := sig.Params() p := "" comma := "" to := params.Len() var i int if sig.Variadic() { to-- } for i = 1; i < to; i++ { param := params.At(i) p += fmt.Sprintf("%s%s %s", comma, param.Name(), types.TypeString(param.Type(), f.Qualifier)) comma = ", " } if sig.Variadic() { param := params.At(params.Len() - 1) p += fmt.Sprintf("%s%s ...%s", comma, param.Name(), types.TypeString(param.Type().(*types.Slice).Elem(), f.Qualifier)) } return p } func (f *testFunc) ForwardedParams() string { sig := f.TypeInfo.Type().(*types.Signature) params := sig.Params() p := "" comma := "" to := params.Len() var i int if sig.Variadic() { to-- } for i = 1; i < to; i++ { param := params.At(i) p += fmt.Sprintf("%s%s", comma, param.Name()) comma = ", " } if sig.Variadic() { param := params.At(params.Len() - 1) p += fmt.Sprintf("%s%s...", comma, param.Name()) } return p } func (f *testFunc) Comment() string { return "// " + strings.Replace(strings.TrimSpace(f.DocInfo.Doc), "\n", "\n// ", -1) } func (f *testFunc) CommentWithoutT(receiver string) string { search := fmt.Sprintf("assert.%s(t, ", f.DocInfo.Name) replace := fmt.Sprintf("%s.%s(", receiver, f.DocInfo.Name) return strings.Replace(f.Comment(), search, replace, -1) } var headerTemplate = `/* * CODE GENERATED AUTOMATICALLY WITH github.com/stretchr/testify/_codegen * THIS FILE MUST NOT BE EDITED BY HAND */ package {{.Name}} import ( {{range $path, $name := .Imports}} {{$name}} "{{$path}}"{{end}} ) ` var funcTemplate = `{{.Comment}} func (fwd *AssertionsForwarder) {{.DocInfo.Name}}({{.Params}}) bool { return assert.{{.DocInfo.Name}}({{.ForwardedParams}}) }` lxd-2.0.0/dist/src/github.com/stretchr/testify/suite/0000755061062106075000000000000012702772371025165 5ustar00stgraberdomain admins00000000000000lxd-2.0.0/dist/src/github.com/stretchr/testify/suite/interfaces.go0000644061062106075000000000143612702772371027643 0ustar00stgraberdomain admins00000000000000package suite import "testing" // TestingSuite can store and return the current *testing.T context // generated by 'go test'. type TestingSuite interface { T() *testing.T SetT(*testing.T) } // SetupAllSuite has a SetupSuite method, which will run before the // tests in the suite are run. type SetupAllSuite interface { SetupSuite() } // SetupTestSuite has a SetupTest method, which will run before each // test in the suite. type SetupTestSuite interface { SetupTest() } // TearDownAllSuite has a TearDownSuite method, which will run after // all the tests in the suite have been run. type TearDownAllSuite interface { TearDownSuite() } // TearDownTestSuite has a TearDownTest method, which will run after // each test in the suite. type TearDownTestSuite interface { TearDownTest() } lxd-2.0.0/dist/src/github.com/stretchr/testify/suite/suite.go0000644061062106075000000000562412702772371026654 0ustar00stgraberdomain admins00000000000000package suite import ( "flag" "fmt" "os" "reflect" "regexp" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) var matchMethod = flag.String("m", "", "regular expression to select tests of the suite to run") // Suite is a basic testing suite with methods for storing and // retrieving the current *testing.T context. type Suite struct { *assert.Assertions require *require.Assertions t *testing.T } // T retrieves the current *testing.T context. func (suite *Suite) T() *testing.T { return suite.t } // SetT sets the current *testing.T context. func (suite *Suite) SetT(t *testing.T) { suite.t = t suite.Assertions = assert.New(t) suite.require = require.New(t) } // Require returns a require context for suite. func (suite *Suite) Require() *require.Assertions { if suite.require == nil { suite.require = require.New(suite.T()) } return suite.require } // Assert returns an assert context for suite. Normally, you can call // `suite.NoError(expected, actual)`, but for situations where the embedded // methods are overridden (for example, you might want to override // assert.Assertions with require.Assertions), this method is provided so you // can call `suite.Assert().NoError()`. func (suite *Suite) Assert() *assert.Assertions { if suite.Assertions == nil { suite.Assertions = assert.New(suite.T()) } return suite.Assertions } // Run takes a testing suite and runs all of the tests attached // to it. func Run(t *testing.T, suite TestingSuite) { suite.SetT(t) if setupAllSuite, ok := suite.(SetupAllSuite); ok { setupAllSuite.SetupSuite() } defer func() { if tearDownAllSuite, ok := suite.(TearDownAllSuite); ok { tearDownAllSuite.TearDownSuite() } }() methodFinder := reflect.TypeOf(suite) tests := []testing.InternalTest{} for index := 0; index < methodFinder.NumMethod(); index++ { method := methodFinder.Method(index) ok, err := methodFilter(method.Name) if err != nil { fmt.Fprintf(os.Stderr, "testify: invalid regexp for -m: %s\n", err) os.Exit(1) } if ok { test := testing.InternalTest{ Name: method.Name, F: func(t *testing.T) { parentT := suite.T() suite.SetT(t) if setupTestSuite, ok := suite.(SetupTestSuite); ok { setupTestSuite.SetupTest() } defer func() { if tearDownTestSuite, ok := suite.(TearDownTestSuite); ok { tearDownTestSuite.TearDownTest() } suite.SetT(parentT) }() method.Func.Call([]reflect.Value{reflect.ValueOf(suite)}) }, } tests = append(tests, test) } } if !testing.RunTests(func(_, _ string) (bool, error) { return true, nil }, tests) { t.Fail() } } // Filtering method according to set regular expression // specified command-line argument -m func methodFilter(name string) (bool, error) { if ok, _ := regexp.MatchString("^Test", name); !ok { return false, nil } return regexp.MatchString(*matchMethod, name) } lxd-2.0.0/dist/src/github.com/stretchr/testify/suite/suite_test.go0000644061062106075000000001525212702772371027711 0ustar00stgraberdomain admins00000000000000package suite import ( "errors" "io/ioutil" "os" "testing" "github.com/stretchr/testify/assert" ) // SuiteRequireTwice is intended to test the usage of suite.Require in two // different tests type SuiteRequireTwice struct{ Suite } // TestSuiteRequireTwice checks for regressions of issue #149 where // suite.requirements was not initialised in suite.SetT() // A regression would result on these tests panicking rather than failing. func TestSuiteRequireTwice(t *testing.T) { ok := testing.RunTests( func(_, _ string) (bool, error) { return true, nil }, []testing.InternalTest{{ Name: "TestSuiteRequireTwice", F: func(t *testing.T) { suite := new(SuiteRequireTwice) Run(t, suite) }, }}, ) assert.Equal(t, false, ok) } func (s *SuiteRequireTwice) TestRequireOne() { r := s.Require() r.Equal(1, 2) } func (s *SuiteRequireTwice) TestRequireTwo() { r := s.Require() r.Equal(1, 2) } // This suite is intended to store values to make sure that only // testing-suite-related methods are run. It's also a fully // functional example of a testing suite, using setup/teardown methods // and a helper method that is ignored by testify. To make this look // more like a real world example, all tests in the suite perform some // type of assertion. type SuiteTester struct { // Include our basic suite logic. Suite // Keep counts of how many times each method is run. SetupSuiteRunCount int TearDownSuiteRunCount int SetupTestRunCount int TearDownTestRunCount int TestOneRunCount int TestTwoRunCount int NonTestMethodRunCount int } type SuiteSkipTester struct { // Include our basic suite logic. Suite // Keep counts of how many times each method is run. SetupSuiteRunCount int TearDownSuiteRunCount int } // The SetupSuite method will be run by testify once, at the very // start of the testing suite, before any tests are run. func (suite *SuiteTester) SetupSuite() { suite.SetupSuiteRunCount++ } func (suite *SuiteSkipTester) SetupSuite() { suite.SetupSuiteRunCount++ suite.T().Skip() } // The TearDownSuite method will be run by testify once, at the very // end of the testing suite, after all tests have been run. func (suite *SuiteTester) TearDownSuite() { suite.TearDownSuiteRunCount++ } func (suite *SuiteSkipTester) TearDownSuite() { suite.TearDownSuiteRunCount++ } // The SetupTest method will be run before every test in the suite. func (suite *SuiteTester) SetupTest() { suite.SetupTestRunCount++ } // The TearDownTest method will be run after every test in the suite. func (suite *SuiteTester) TearDownTest() { suite.TearDownTestRunCount++ } // Every method in a testing suite that begins with "Test" will be run // as a test. TestOne is an example of a test. For the purposes of // this example, we've included assertions in the tests, since most // tests will issue assertions. func (suite *SuiteTester) TestOne() { beforeCount := suite.TestOneRunCount suite.TestOneRunCount++ assert.Equal(suite.T(), suite.TestOneRunCount, beforeCount+1) suite.Equal(suite.TestOneRunCount, beforeCount+1) } // TestTwo is another example of a test. func (suite *SuiteTester) TestTwo() { beforeCount := suite.TestTwoRunCount suite.TestTwoRunCount++ assert.NotEqual(suite.T(), suite.TestTwoRunCount, beforeCount) suite.NotEqual(suite.TestTwoRunCount, beforeCount) } func (suite *SuiteTester) TestSkip() { suite.T().Skip() } // NonTestMethod does not begin with "Test", so it will not be run by // testify as a test in the suite. This is useful for creating helper // methods for your tests. func (suite *SuiteTester) NonTestMethod() { suite.NonTestMethodRunCount++ } // TestRunSuite will be run by the 'go test' command, so within it, we // can run our suite using the Run(*testing.T, TestingSuite) function. func TestRunSuite(t *testing.T) { suiteTester := new(SuiteTester) Run(t, suiteTester) // Normally, the test would end here. The following are simply // some assertions to ensure that the Run function is working as // intended - they are not part of the example. // The suite was only run once, so the SetupSuite and TearDownSuite // methods should have each been run only once. assert.Equal(t, suiteTester.SetupSuiteRunCount, 1) assert.Equal(t, suiteTester.TearDownSuiteRunCount, 1) // There are three test methods (TestOne, TestTwo, and TestSkip), so // the SetupTest and TearDownTest methods (which should be run once for // each test) should have been run three times. assert.Equal(t, suiteTester.SetupTestRunCount, 3) assert.Equal(t, suiteTester.TearDownTestRunCount, 3) // Each test should have been run once. assert.Equal(t, suiteTester.TestOneRunCount, 1) assert.Equal(t, suiteTester.TestTwoRunCount, 1) // Methods that don't match the test method identifier shouldn't // have been run at all. assert.Equal(t, suiteTester.NonTestMethodRunCount, 0) suiteSkipTester := new(SuiteSkipTester) Run(t, suiteSkipTester) // The suite was only run once, so the SetupSuite and TearDownSuite // methods should have each been run only once, even though SetupSuite // called Skip() assert.Equal(t, suiteSkipTester.SetupSuiteRunCount, 1) assert.Equal(t, suiteSkipTester.TearDownSuiteRunCount, 1) } func TestSuiteGetters(t *testing.T) { suite := new(SuiteTester) suite.SetT(t) assert.NotNil(t, suite.Assert()) assert.Equal(t, suite.Assertions, suite.Assert()) assert.NotNil(t, suite.Require()) assert.Equal(t, suite.require, suite.Require()) } type SuiteLoggingTester struct { Suite } func (s *SuiteLoggingTester) TestLoggingPass() { s.T().Log("TESTLOGPASS") } func (s *SuiteLoggingTester) TestLoggingFail() { s.T().Log("TESTLOGFAIL") assert.NotNil(s.T(), nil) // expected to fail } type StdoutCapture struct { oldStdout *os.File readPipe *os.File } func (sc *StdoutCapture) StartCapture() { sc.oldStdout = os.Stdout sc.readPipe, os.Stdout, _ = os.Pipe() } func (sc *StdoutCapture) StopCapture() (string, error) { if sc.oldStdout == nil || sc.readPipe == nil { return "", errors.New("StartCapture not called before StopCapture") } os.Stdout.Close() os.Stdout = sc.oldStdout bytes, err := ioutil.ReadAll(sc.readPipe) if err != nil { return "", err } return string(bytes), nil } func TestSuiteLogging(t *testing.T) { testT := testing.T{} suiteLoggingTester := new(SuiteLoggingTester) capture := StdoutCapture{} capture.StartCapture() Run(&testT, suiteLoggingTester) output, err := capture.StopCapture() assert.Nil(t, err, "Got an error trying to capture stdout!") // Failed tests' output is always printed assert.Contains(t, output, "TESTLOGFAIL") if testing.Verbose() { // In verbose mode, output from successful tests is also printed assert.Contains(t, output, "TESTLOGPASS") } else { assert.NotContains(t, output, "TESTLOGPASS") } } lxd-2.0.0/dist/src/github.com/stretchr/testify/suite/doc.go0000644061062106075000000000517212702772371026266 0ustar00stgraberdomain admins00000000000000// Package suite contains logic for creating testing suite structs // and running the methods on those structs as tests. The most useful // piece of this package is that you can create setup/teardown methods // on your testing suites, which will run before/after the whole suite // or individual tests (depending on which interface(s) you // implement). // // A testing suite is usually built by first extending the built-in // suite functionality from suite.Suite in testify. Alternatively, // you could reproduce that logic on your own if you wanted (you // just need to implement the TestingSuite interface from // suite/interfaces.go). // // After that, you can implement any of the interfaces in // suite/interfaces.go to add setup/teardown functionality to your // suite, and add any methods that start with "Test" to add tests. // Methods that do not match any suite interfaces and do not begin // with "Test" will not be run by testify, and can safely be used as // helper methods. // // Once you've built your testing suite, you need to run the suite // (using suite.Run from testify) inside any function that matches the // identity that "go test" is already looking for (i.e. // func(*testing.T)). // // Regular expression to select test suites specified command-line // argument "-run". Regular expression to select the methods // of test suites specified command-line argument "-m". // Suite object has assertion methods. // // A crude example: // // Basic imports // import ( // "testing" // "github.com/stretchr/testify/assert" // "github.com/stretchr/testify/suite" // ) // // // Define the suite, and absorb the built-in basic suite // // functionality from testify - including a T() method which // // returns the current testing context // type ExampleTestSuite struct { // suite.Suite // VariableThatShouldStartAtFive int // } // // // Make sure that VariableThatShouldStartAtFive is set to five // // before each test // func (suite *ExampleTestSuite) SetupTest() { // suite.VariableThatShouldStartAtFive = 5 // } // // // All methods that begin with "Test" are run as tests within a // // suite. // func (suite *ExampleTestSuite) TestExample() { // assert.Equal(suite.T(), 5, suite.VariableThatShouldStartAtFive) // suite.Equal(5, suite.VariableThatShouldStartAtFive) // } // // // In order for 'go test' to run this suite, we need to create // // a normal test function and pass our suite to suite.Run // func TestExampleTestSuite(t *testing.T) { // suite.Run(t, new(ExampleTestSuite)) // } package suite lxd-2.0.0/dist/src/github.com/stretchr/testify/http/0000755061062106075000000000000012702772371025013 5ustar00stgraberdomain admins00000000000000lxd-2.0.0/dist/src/github.com/stretchr/testify/http/test_round_tripper.go0000644061062106075000000000057112702772371031300 0ustar00stgraberdomain admins00000000000000package http import ( "github.com/stretchr/testify/mock" "net/http" ) // TestRoundTripper DEPRECATED USE net/http/httptest type TestRoundTripper struct { mock.Mock } // RoundTrip DEPRECATED USE net/http/httptest func (t *TestRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) { args := t.Called(req) return args.Get(0).(*http.Response), args.Error(1) } lxd-2.0.0/dist/src/github.com/stretchr/testify/http/doc.go0000644061062106075000000000007612702772371026112 0ustar00stgraberdomain admins00000000000000// Package http DEPRECATED USE net/http/httptest package http lxd-2.0.0/dist/src/github.com/stretchr/testify/http/test_response_writer.go0000644061062106075000000000230712702772371031635 0ustar00stgraberdomain admins00000000000000package http import ( "net/http" ) // TestResponseWriter DEPRECATED: We recommend you use http://golang.org/pkg/net/http/httptest instead. type TestResponseWriter struct { // StatusCode is the last int written by the call to WriteHeader(int) StatusCode int // Output is a string containing the written bytes using the Write([]byte) func. Output string // header is the internal storage of the http.Header object header http.Header } // Header DEPRECATED: We recommend you use http://golang.org/pkg/net/http/httptest instead. func (rw *TestResponseWriter) Header() http.Header { if rw.header == nil { rw.header = make(http.Header) } return rw.header } // Write DEPRECATED: We recommend you use http://golang.org/pkg/net/http/httptest instead. func (rw *TestResponseWriter) Write(bytes []byte) (int, error) { // assume 200 success if no header has been set if rw.StatusCode == 0 { rw.WriteHeader(200) } // add these bytes to the output string rw.Output = rw.Output + string(bytes) // return normal values return 0, nil } // WriteHeader DEPRECATED: We recommend you use http://golang.org/pkg/net/http/httptest instead. func (rw *TestResponseWriter) WriteHeader(i int) { rw.StatusCode = i } lxd-2.0.0/dist/src/github.com/stretchr/testify/LICENCE.txt0000644061062106075000000000220012702772371025631 0ustar00stgraberdomain admins00000000000000Copyright (c) 2012 - 2013 Mat Ryer and Tyler Bunnell Please consider promoting this project if you find it useful. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. lxd-2.0.0/dist/src/github.com/stretchr/testify/LICENSE0000644061062106075000000000220012702772371025033 0ustar00stgraberdomain admins00000000000000Copyright (c) 2012 - 2013 Mat Ryer and Tyler Bunnell Please consider promoting this project if you find it useful. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. lxd-2.0.0/dist/src/github.com/stretchr/testify/vendor/0000755061062106075000000000000012702772371025331 5ustar00stgraberdomain admins00000000000000lxd-2.0.0/dist/src/github.com/stretchr/testify/vendor/github.com/0000755061062106075000000000000012702772371027370 5ustar00stgraberdomain admins00000000000000lxd-2.0.0/dist/src/github.com/stretchr/testify/vendor/github.com/davecgh/0000755061062106075000000000000012702772371030771 5ustar00stgraberdomain admins00000000000000lxd-2.0.0/dist/src/github.com/stretchr/testify/vendor/github.com/davecgh/go-spew/0000755061062106075000000000000012702772371032352 5ustar00stgraberdomain admins00000000000000lxd-2.0.0/dist/src/github.com/stretchr/testify/vendor/github.com/davecgh/go-spew/spew/0000755061062106075000000000000012702772371033330 5ustar00stgraberdomain admins00000000000000lxd-2.0.0/dist/src/github.com/stretchr/testify/vendor/github.com/davecgh/go-spew/spew/spew.go0000644061062106075000000001351412702772371034641 0ustar00stgraberdomain admins00000000000000/* * Copyright (c) 2013 Dave Collins * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ package spew import ( "fmt" "io" ) // Errorf is a wrapper for fmt.Errorf that treats each argument as if it were // passed with a default Formatter interface returned by NewFormatter. It // returns the formatted string as a value that satisfies error. See // NewFormatter for formatting details. // // This function is shorthand for the following syntax: // // fmt.Errorf(format, spew.NewFormatter(a), spew.NewFormatter(b)) func Errorf(format string, a ...interface{}) (err error) { return fmt.Errorf(format, convertArgs(a)...) } // Fprint is a wrapper for fmt.Fprint that treats each argument as if it were // passed with a default Formatter interface returned by NewFormatter. It // returns the number of bytes written and any write error encountered. See // NewFormatter for formatting details. // // This function is shorthand for the following syntax: // // fmt.Fprint(w, spew.NewFormatter(a), spew.NewFormatter(b)) func Fprint(w io.Writer, a ...interface{}) (n int, err error) { return fmt.Fprint(w, convertArgs(a)...) } // Fprintf is a wrapper for fmt.Fprintf that treats each argument as if it were // passed with a default Formatter interface returned by NewFormatter. It // returns the number of bytes written and any write error encountered. See // NewFormatter for formatting details. // // This function is shorthand for the following syntax: // // fmt.Fprintf(w, format, spew.NewFormatter(a), spew.NewFormatter(b)) func Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error) { return fmt.Fprintf(w, format, convertArgs(a)...) } // Fprintln is a wrapper for fmt.Fprintln that treats each argument as if it // passed with a default Formatter interface returned by NewFormatter. See // NewFormatter for formatting details. // // This function is shorthand for the following syntax: // // fmt.Fprintln(w, spew.NewFormatter(a), spew.NewFormatter(b)) func Fprintln(w io.Writer, a ...interface{}) (n int, err error) { return fmt.Fprintln(w, convertArgs(a)...) } // Print is a wrapper for fmt.Print that treats each argument as if it were // passed with a default Formatter interface returned by NewFormatter. It // returns the number of bytes written and any write error encountered. See // NewFormatter for formatting details. // // This function is shorthand for the following syntax: // // fmt.Print(spew.NewFormatter(a), spew.NewFormatter(b)) func Print(a ...interface{}) (n int, err error) { return fmt.Print(convertArgs(a)...) } // Printf is a wrapper for fmt.Printf that treats each argument as if it were // passed with a default Formatter interface returned by NewFormatter. It // returns the number of bytes written and any write error encountered. See // NewFormatter for formatting details. // // This function is shorthand for the following syntax: // // fmt.Printf(format, spew.NewFormatter(a), spew.NewFormatter(b)) func Printf(format string, a ...interface{}) (n int, err error) { return fmt.Printf(format, convertArgs(a)...) } // Println is a wrapper for fmt.Println that treats each argument as if it were // passed with a default Formatter interface returned by NewFormatter. It // returns the number of bytes written and any write error encountered. See // NewFormatter for formatting details. // // This function is shorthand for the following syntax: // // fmt.Println(spew.NewFormatter(a), spew.NewFormatter(b)) func Println(a ...interface{}) (n int, err error) { return fmt.Println(convertArgs(a)...) } // Sprint is a wrapper for fmt.Sprint that treats each argument as if it were // passed with a default Formatter interface returned by NewFormatter. It // returns the resulting string. See NewFormatter for formatting details. // // This function is shorthand for the following syntax: // // fmt.Sprint(spew.NewFormatter(a), spew.NewFormatter(b)) func Sprint(a ...interface{}) string { return fmt.Sprint(convertArgs(a)...) } // Sprintf is a wrapper for fmt.Sprintf that treats each argument as if it were // passed with a default Formatter interface returned by NewFormatter. It // returns the resulting string. See NewFormatter for formatting details. // // This function is shorthand for the following syntax: // // fmt.Sprintf(format, spew.NewFormatter(a), spew.NewFormatter(b)) func Sprintf(format string, a ...interface{}) string { return fmt.Sprintf(format, convertArgs(a)...) } // Sprintln is a wrapper for fmt.Sprintln that treats each argument as if it // were passed with a default Formatter interface returned by NewFormatter. It // returns the resulting string. See NewFormatter for formatting details. // // This function is shorthand for the following syntax: // // fmt.Sprintln(spew.NewFormatter(a), spew.NewFormatter(b)) func Sprintln(a ...interface{}) string { return fmt.Sprintln(convertArgs(a)...) } // convertArgs accepts a slice of arguments and returns a slice of the same // length with each argument converted to a default spew Formatter interface. func convertArgs(args []interface{}) (formatters []interface{}) { formatters = make([]interface{}, len(args)) for index, arg := range args { formatters[index] = NewFormatter(arg) } return formatters } lxd-2.0.0/dist/src/github.com/stretchr/testify/vendor/github.com/davecgh/go-spew/spew/dump.go0000644061062106075000000003263112702772371034631 0ustar00stgraberdomain admins00000000000000/* * Copyright (c) 2013 Dave Collins * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ package spew import ( "bytes" "encoding/hex" "fmt" "io" "os" "reflect" "regexp" "strconv" "strings" ) var ( // uint8Type is a reflect.Type representing a uint8. It is used to // convert cgo types to uint8 slices for hexdumping. uint8Type = reflect.TypeOf(uint8(0)) // cCharRE is a regular expression that matches a cgo char. // It is used to detect character arrays to hexdump them. cCharRE = regexp.MustCompile("^.*\\._Ctype_char$") // cUnsignedCharRE is a regular expression that matches a cgo unsigned // char. It is used to detect unsigned character arrays to hexdump // them. cUnsignedCharRE = regexp.MustCompile("^.*\\._Ctype_unsignedchar$") // cUint8tCharRE is a regular expression that matches a cgo uint8_t. // It is used to detect uint8_t arrays to hexdump them. cUint8tCharRE = regexp.MustCompile("^.*\\._Ctype_uint8_t$") ) // dumpState contains information about the state of a dump operation. type dumpState struct { w io.Writer depth int pointers map[uintptr]int ignoreNextType bool ignoreNextIndent bool cs *ConfigState } // indent performs indentation according to the depth level and cs.Indent // option. func (d *dumpState) indent() { if d.ignoreNextIndent { d.ignoreNextIndent = false return } d.w.Write(bytes.Repeat([]byte(d.cs.Indent), d.depth)) } // unpackValue returns values inside of non-nil interfaces when possible. // This is useful for data types like structs, arrays, slices, and maps which // can contain varying types packed inside an interface. func (d *dumpState) unpackValue(v reflect.Value) reflect.Value { if v.Kind() == reflect.Interface && !v.IsNil() { v = v.Elem() } return v } // dumpPtr handles formatting of pointers by indirecting them as necessary. func (d *dumpState) dumpPtr(v reflect.Value) { // Remove pointers at or below the current depth from map used to detect // circular refs. for k, depth := range d.pointers { if depth >= d.depth { delete(d.pointers, k) } } // Keep list of all dereferenced pointers to show later. pointerChain := make([]uintptr, 0) // Figure out how many levels of indirection there are by dereferencing // pointers and unpacking interfaces down the chain while detecting circular // references. nilFound := false cycleFound := false indirects := 0 ve := v for ve.Kind() == reflect.Ptr { if ve.IsNil() { nilFound = true break } indirects++ addr := ve.Pointer() pointerChain = append(pointerChain, addr) if pd, ok := d.pointers[addr]; ok && pd < d.depth { cycleFound = true indirects-- break } d.pointers[addr] = d.depth ve = ve.Elem() if ve.Kind() == reflect.Interface { if ve.IsNil() { nilFound = true break } ve = ve.Elem() } } // Display type information. d.w.Write(openParenBytes) d.w.Write(bytes.Repeat(asteriskBytes, indirects)) d.w.Write([]byte(ve.Type().String())) d.w.Write(closeParenBytes) // Display pointer information. if len(pointerChain) > 0 { d.w.Write(openParenBytes) for i, addr := range pointerChain { if i > 0 { d.w.Write(pointerChainBytes) } printHexPtr(d.w, addr) } d.w.Write(closeParenBytes) } // Display dereferenced value. d.w.Write(openParenBytes) switch { case nilFound == true: d.w.Write(nilAngleBytes) case cycleFound == true: d.w.Write(circularBytes) default: d.ignoreNextType = true d.dump(ve) } d.w.Write(closeParenBytes) } // dumpSlice handles formatting of arrays and slices. Byte (uint8 under // reflection) arrays and slices are dumped in hexdump -C fashion. func (d *dumpState) dumpSlice(v reflect.Value) { // Determine whether this type should be hex dumped or not. Also, // for types which should be hexdumped, try to use the underlying data // first, then fall back to trying to convert them to a uint8 slice. var buf []uint8 doConvert := false doHexDump := false numEntries := v.Len() if numEntries > 0 { vt := v.Index(0).Type() vts := vt.String() switch { // C types that need to be converted. case cCharRE.MatchString(vts): fallthrough case cUnsignedCharRE.MatchString(vts): fallthrough case cUint8tCharRE.MatchString(vts): doConvert = true // Try to use existing uint8 slices and fall back to converting // and copying if that fails. case vt.Kind() == reflect.Uint8: // We need an addressable interface to convert the type // to a byte slice. However, the reflect package won't // give us an interface on certain things like // unexported struct fields in order to enforce // visibility rules. We use unsafe, when available, to // bypass these restrictions since this package does not // mutate the values. vs := v if !vs.CanInterface() || !vs.CanAddr() { vs = unsafeReflectValue(vs) } if !UnsafeDisabled { vs = vs.Slice(0, numEntries) // Use the existing uint8 slice if it can be // type asserted. iface := vs.Interface() if slice, ok := iface.([]uint8); ok { buf = slice doHexDump = true break } } // The underlying data needs to be converted if it can't // be type asserted to a uint8 slice. doConvert = true } // Copy and convert the underlying type if needed. if doConvert && vt.ConvertibleTo(uint8Type) { // Convert and copy each element into a uint8 byte // slice. buf = make([]uint8, numEntries) for i := 0; i < numEntries; i++ { vv := v.Index(i) buf[i] = uint8(vv.Convert(uint8Type).Uint()) } doHexDump = true } } // Hexdump the entire slice as needed. if doHexDump { indent := strings.Repeat(d.cs.Indent, d.depth) str := indent + hex.Dump(buf) str = strings.Replace(str, "\n", "\n"+indent, -1) str = strings.TrimRight(str, d.cs.Indent) d.w.Write([]byte(str)) return } // Recursively call dump for each item. for i := 0; i < numEntries; i++ { d.dump(d.unpackValue(v.Index(i))) if i < (numEntries - 1) { d.w.Write(commaNewlineBytes) } else { d.w.Write(newlineBytes) } } } // dump is the main workhorse for dumping a value. It uses the passed reflect // value to figure out what kind of object we are dealing with and formats it // appropriately. It is a recursive function, however circular data structures // are detected and handled properly. func (d *dumpState) dump(v reflect.Value) { // Handle invalid reflect values immediately. kind := v.Kind() if kind == reflect.Invalid { d.w.Write(invalidAngleBytes) return } // Handle pointers specially. if kind == reflect.Ptr { d.indent() d.dumpPtr(v) return } // Print type information unless already handled elsewhere. if !d.ignoreNextType { d.indent() d.w.Write(openParenBytes) d.w.Write([]byte(v.Type().String())) d.w.Write(closeParenBytes) d.w.Write(spaceBytes) } d.ignoreNextType = false // Display length and capacity if the built-in len and cap functions // work with the value's kind and the len/cap itself is non-zero. valueLen, valueCap := 0, 0 switch v.Kind() { case reflect.Array, reflect.Slice, reflect.Chan: valueLen, valueCap = v.Len(), v.Cap() case reflect.Map, reflect.String: valueLen = v.Len() } if valueLen != 0 || valueCap != 0 { d.w.Write(openParenBytes) if valueLen != 0 { d.w.Write(lenEqualsBytes) printInt(d.w, int64(valueLen), 10) } if valueCap != 0 { if valueLen != 0 { d.w.Write(spaceBytes) } d.w.Write(capEqualsBytes) printInt(d.w, int64(valueCap), 10) } d.w.Write(closeParenBytes) d.w.Write(spaceBytes) } // Call Stringer/error interfaces if they exist and the handle methods flag // is enabled if !d.cs.DisableMethods { if (kind != reflect.Invalid) && (kind != reflect.Interface) { if handled := handleMethods(d.cs, d.w, v); handled { return } } } switch kind { case reflect.Invalid: // Do nothing. We should never get here since invalid has already // been handled above. case reflect.Bool: printBool(d.w, v.Bool()) case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int: printInt(d.w, v.Int(), 10) case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint: printUint(d.w, v.Uint(), 10) case reflect.Float32: printFloat(d.w, v.Float(), 32) case reflect.Float64: printFloat(d.w, v.Float(), 64) case reflect.Complex64: printComplex(d.w, v.Complex(), 32) case reflect.Complex128: printComplex(d.w, v.Complex(), 64) case reflect.Slice: if v.IsNil() { d.w.Write(nilAngleBytes) break } fallthrough case reflect.Array: d.w.Write(openBraceNewlineBytes) d.depth++ if (d.cs.MaxDepth != 0) && (d.depth > d.cs.MaxDepth) { d.indent() d.w.Write(maxNewlineBytes) } else { d.dumpSlice(v) } d.depth-- d.indent() d.w.Write(closeBraceBytes) case reflect.String: d.w.Write([]byte(strconv.Quote(v.String()))) case reflect.Interface: // The only time we should get here is for nil interfaces due to // unpackValue calls. if v.IsNil() { d.w.Write(nilAngleBytes) } case reflect.Ptr: // Do nothing. We should never get here since pointers have already // been handled above. case reflect.Map: // nil maps should be indicated as different than empty maps if v.IsNil() { d.w.Write(nilAngleBytes) break } d.w.Write(openBraceNewlineBytes) d.depth++ if (d.cs.MaxDepth != 0) && (d.depth > d.cs.MaxDepth) { d.indent() d.w.Write(maxNewlineBytes) } else { numEntries := v.Len() keys := v.MapKeys() if d.cs.SortKeys { sortValues(keys, d.cs) } for i, key := range keys { d.dump(d.unpackValue(key)) d.w.Write(colonSpaceBytes) d.ignoreNextIndent = true d.dump(d.unpackValue(v.MapIndex(key))) if i < (numEntries - 1) { d.w.Write(commaNewlineBytes) } else { d.w.Write(newlineBytes) } } } d.depth-- d.indent() d.w.Write(closeBraceBytes) case reflect.Struct: d.w.Write(openBraceNewlineBytes) d.depth++ if (d.cs.MaxDepth != 0) && (d.depth > d.cs.MaxDepth) { d.indent() d.w.Write(maxNewlineBytes) } else { vt := v.Type() numFields := v.NumField() for i := 0; i < numFields; i++ { d.indent() vtf := vt.Field(i) d.w.Write([]byte(vtf.Name)) d.w.Write(colonSpaceBytes) d.ignoreNextIndent = true d.dump(d.unpackValue(v.Field(i))) if i < (numFields - 1) { d.w.Write(commaNewlineBytes) } else { d.w.Write(newlineBytes) } } } d.depth-- d.indent() d.w.Write(closeBraceBytes) case reflect.Uintptr: printHexPtr(d.w, uintptr(v.Uint())) case reflect.UnsafePointer, reflect.Chan, reflect.Func: printHexPtr(d.w, v.Pointer()) // There were not any other types at the time this code was written, but // fall back to letting the default fmt package handle it in case any new // types are added. default: if v.CanInterface() { fmt.Fprintf(d.w, "%v", v.Interface()) } else { fmt.Fprintf(d.w, "%v", v.String()) } } } // fdump is a helper function to consolidate the logic from the various public // methods which take varying writers and config states. func fdump(cs *ConfigState, w io.Writer, a ...interface{}) { for _, arg := range a { if arg == nil { w.Write(interfaceBytes) w.Write(spaceBytes) w.Write(nilAngleBytes) w.Write(newlineBytes) continue } d := dumpState{w: w, cs: cs} d.pointers = make(map[uintptr]int) d.dump(reflect.ValueOf(arg)) d.w.Write(newlineBytes) } } // Fdump formats and displays the passed arguments to io.Writer w. It formats // exactly the same as Dump. func Fdump(w io.Writer, a ...interface{}) { fdump(&Config, w, a...) } // Sdump returns a string with the passed arguments formatted exactly the same // as Dump. func Sdump(a ...interface{}) string { var buf bytes.Buffer fdump(&Config, &buf, a...) return buf.String() } /* Dump displays the passed parameters to standard out with newlines, customizable indentation, and additional debug information such as complete types and all pointer addresses used to indirect to the final value. It provides the following features over the built-in printing facilities provided by the fmt package: * Pointers are dereferenced and followed * Circular data structures are detected and handled properly * Custom Stringer/error interfaces are optionally invoked, including on unexported types * Custom types which only implement the Stringer/error interfaces via a pointer receiver are optionally invoked when passing non-pointer variables * Byte arrays and slices are dumped like the hexdump -C command which includes offsets, byte values in hex, and ASCII output The configuration options are controlled by an exported package global, spew.Config. See ConfigState for options documentation. See Fdump if you would prefer dumping to an arbitrary io.Writer or Sdump to get the formatted result as a string. */ func Dump(a ...interface{}) { fdump(&Config, os.Stdout, a...) } lxd-2.0.0/dist/src/github.com/stretchr/testify/vendor/github.com/davecgh/go-spew/spew/bypass.go0000644061062106075000000001307112702772371035162 0ustar00stgraberdomain admins00000000000000// Copyright (c) 2015 Dave Collins // // Permission to use, copy, modify, and distribute this software for any // purpose with or without fee is hereby granted, provided that the above // copyright notice and this permission notice appear in all copies. // // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. // NOTE: Due to the following build constraints, this file will only be compiled // when the code is not running on Google App Engine and "-tags disableunsafe" // is not added to the go build command line. // +build !appengine,!disableunsafe package spew import ( "reflect" "unsafe" ) const ( // UnsafeDisabled is a build-time constant which specifies whether or // not access to the unsafe package is available. UnsafeDisabled = false // ptrSize is the size of a pointer on the current arch. ptrSize = unsafe.Sizeof((*byte)(nil)) ) var ( // offsetPtr, offsetScalar, and offsetFlag are the offsets for the // internal reflect.Value fields. These values are valid before golang // commit ecccf07e7f9d which changed the format. The are also valid // after commit 82f48826c6c7 which changed the format again to mirror // the original format. Code in the init function updates these offsets // as necessary. offsetPtr = uintptr(ptrSize) offsetScalar = uintptr(0) offsetFlag = uintptr(ptrSize * 2) // flagKindWidth and flagKindShift indicate various bits that the // reflect package uses internally to track kind information. // // flagRO indicates whether or not the value field of a reflect.Value is // read-only. // // flagIndir indicates whether the value field of a reflect.Value is // the actual data or a pointer to the data. // // These values are valid before golang commit 90a7c3c86944 which // changed their positions. Code in the init function updates these // flags as necessary. flagKindWidth = uintptr(5) flagKindShift = uintptr(flagKindWidth - 1) flagRO = uintptr(1 << 0) flagIndir = uintptr(1 << 1) ) func init() { // Older versions of reflect.Value stored small integers directly in the // ptr field (which is named val in the older versions). Versions // between commits ecccf07e7f9d and 82f48826c6c7 added a new field named // scalar for this purpose which unfortunately came before the flag // field, so the offset of the flag field is different for those // versions. // // This code constructs a new reflect.Value from a known small integer // and checks if the size of the reflect.Value struct indicates it has // the scalar field. When it does, the offsets are updated accordingly. vv := reflect.ValueOf(0xf00) if unsafe.Sizeof(vv) == (ptrSize * 4) { offsetScalar = ptrSize * 2 offsetFlag = ptrSize * 3 } // Commit 90a7c3c86944 changed the flag positions such that the low // order bits are the kind. This code extracts the kind from the flags // field and ensures it's the correct type. When it's not, the flag // order has been changed to the newer format, so the flags are updated // accordingly. upf := unsafe.Pointer(uintptr(unsafe.Pointer(&vv)) + offsetFlag) upfv := *(*uintptr)(upf) flagKindMask := uintptr((1<>flagKindShift != uintptr(reflect.Int) { flagKindShift = 0 flagRO = 1 << 5 flagIndir = 1 << 6 // Commit adf9b30e5594 modified the flags to separate the // flagRO flag into two bits which specifies whether or not the // field is embedded. This causes flagIndir to move over a bit // and means that flagRO is the combination of either of the // original flagRO bit and the new bit. // // This code detects the change by extracting what used to be // the indirect bit to ensure it's set. When it's not, the flag // order has been changed to the newer format, so the flags are // updated accordingly. if upfv&flagIndir == 0 { flagRO = 3 << 5 flagIndir = 1 << 7 } } } // unsafeReflectValue converts the passed reflect.Value into a one that bypasses // the typical safety restrictions preventing access to unaddressable and // unexported data. It works by digging the raw pointer to the underlying // value out of the protected value and generating a new unprotected (unsafe) // reflect.Value to it. // // This allows us to check for implementations of the Stringer and error // interfaces to be used for pretty printing ordinarily unaddressable and // inaccessible values such as unexported struct fields. func unsafeReflectValue(v reflect.Value) (rv reflect.Value) { indirects := 1 vt := v.Type() upv := unsafe.Pointer(uintptr(unsafe.Pointer(&v)) + offsetPtr) rvf := *(*uintptr)(unsafe.Pointer(uintptr(unsafe.Pointer(&v)) + offsetFlag)) if rvf&flagIndir != 0 { vt = reflect.PtrTo(v.Type()) indirects++ } else if offsetScalar != 0 { // The value is in the scalar field when it's not one of the // reference types. switch vt.Kind() { case reflect.Uintptr: case reflect.Chan: case reflect.Func: case reflect.Map: case reflect.Ptr: case reflect.UnsafePointer: default: upv = unsafe.Pointer(uintptr(unsafe.Pointer(&v)) + offsetScalar) } } pv := reflect.NewAt(vt, upv) rv = pv for i := 0; i < indirects; i++ { rv = rv.Elem() } return rv } lxd-2.0.0/dist/src/github.com/stretchr/testify/vendor/github.com/davecgh/go-spew/spew/bypasssafe.go0000644061062106075000000000315312702772371036021 0ustar00stgraberdomain admins00000000000000// Copyright (c) 2015 Dave Collins // // Permission to use, copy, modify, and distribute this software for any // purpose with or without fee is hereby granted, provided that the above // copyright notice and this permission notice appear in all copies. // // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. // NOTE: Due to the following build constraints, this file will only be compiled // when either the code is running on Google App Engine or "-tags disableunsafe" // is added to the go build command line. // +build appengine disableunsafe package spew import "reflect" const ( // UnsafeDisabled is a build-time constant which specifies whether or // not access to the unsafe package is available. UnsafeDisabled = true ) // unsafeReflectValue typically converts the passed reflect.Value into a one // that bypasses the typical safety restrictions preventing access to // unaddressable and unexported data. However, doing this relies on access to // the unsafe package. This is a stub version which simply returns the passed // reflect.Value when the unsafe package is not available. func unsafeReflectValue(v reflect.Value) reflect.Value { return v } lxd-2.0.0/dist/src/github.com/stretchr/testify/vendor/github.com/davecgh/go-spew/spew/format.go0000644061062106075000000002607512702772371035161 0ustar00stgraberdomain admins00000000000000/* * Copyright (c) 2013 Dave Collins * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ package spew import ( "bytes" "fmt" "reflect" "strconv" "strings" ) // supportedFlags is a list of all the character flags supported by fmt package. const supportedFlags = "0-+# " // formatState implements the fmt.Formatter interface and contains information // about the state of a formatting operation. The NewFormatter function can // be used to get a new Formatter which can be used directly as arguments // in standard fmt package printing calls. type formatState struct { value interface{} fs fmt.State depth int pointers map[uintptr]int ignoreNextType bool cs *ConfigState } // buildDefaultFormat recreates the original format string without precision // and width information to pass in to fmt.Sprintf in the case of an // unrecognized type. Unless new types are added to the language, this // function won't ever be called. func (f *formatState) buildDefaultFormat() (format string) { buf := bytes.NewBuffer(percentBytes) for _, flag := range supportedFlags { if f.fs.Flag(int(flag)) { buf.WriteRune(flag) } } buf.WriteRune('v') format = buf.String() return format } // constructOrigFormat recreates the original format string including precision // and width information to pass along to the standard fmt package. This allows // automatic deferral of all format strings this package doesn't support. func (f *formatState) constructOrigFormat(verb rune) (format string) { buf := bytes.NewBuffer(percentBytes) for _, flag := range supportedFlags { if f.fs.Flag(int(flag)) { buf.WriteRune(flag) } } if width, ok := f.fs.Width(); ok { buf.WriteString(strconv.Itoa(width)) } if precision, ok := f.fs.Precision(); ok { buf.Write(precisionBytes) buf.WriteString(strconv.Itoa(precision)) } buf.WriteRune(verb) format = buf.String() return format } // unpackValue returns values inside of non-nil interfaces when possible and // ensures that types for values which have been unpacked from an interface // are displayed when the show types flag is also set. // This is useful for data types like structs, arrays, slices, and maps which // can contain varying types packed inside an interface. func (f *formatState) unpackValue(v reflect.Value) reflect.Value { if v.Kind() == reflect.Interface { f.ignoreNextType = false if !v.IsNil() { v = v.Elem() } } return v } // formatPtr handles formatting of pointers by indirecting them as necessary. func (f *formatState) formatPtr(v reflect.Value) { // Display nil if top level pointer is nil. showTypes := f.fs.Flag('#') if v.IsNil() && (!showTypes || f.ignoreNextType) { f.fs.Write(nilAngleBytes) return } // Remove pointers at or below the current depth from map used to detect // circular refs. for k, depth := range f.pointers { if depth >= f.depth { delete(f.pointers, k) } } // Keep list of all dereferenced pointers to possibly show later. pointerChain := make([]uintptr, 0) // Figure out how many levels of indirection there are by derferencing // pointers and unpacking interfaces down the chain while detecting circular // references. nilFound := false cycleFound := false indirects := 0 ve := v for ve.Kind() == reflect.Ptr { if ve.IsNil() { nilFound = true break } indirects++ addr := ve.Pointer() pointerChain = append(pointerChain, addr) if pd, ok := f.pointers[addr]; ok && pd < f.depth { cycleFound = true indirects-- break } f.pointers[addr] = f.depth ve = ve.Elem() if ve.Kind() == reflect.Interface { if ve.IsNil() { nilFound = true break } ve = ve.Elem() } } // Display type or indirection level depending on flags. if showTypes && !f.ignoreNextType { f.fs.Write(openParenBytes) f.fs.Write(bytes.Repeat(asteriskBytes, indirects)) f.fs.Write([]byte(ve.Type().String())) f.fs.Write(closeParenBytes) } else { if nilFound || cycleFound { indirects += strings.Count(ve.Type().String(), "*") } f.fs.Write(openAngleBytes) f.fs.Write([]byte(strings.Repeat("*", indirects))) f.fs.Write(closeAngleBytes) } // Display pointer information depending on flags. if f.fs.Flag('+') && (len(pointerChain) > 0) { f.fs.Write(openParenBytes) for i, addr := range pointerChain { if i > 0 { f.fs.Write(pointerChainBytes) } printHexPtr(f.fs, addr) } f.fs.Write(closeParenBytes) } // Display dereferenced value. switch { case nilFound == true: f.fs.Write(nilAngleBytes) case cycleFound == true: f.fs.Write(circularShortBytes) default: f.ignoreNextType = true f.format(ve) } } // format is the main workhorse for providing the Formatter interface. It // uses the passed reflect value to figure out what kind of object we are // dealing with and formats it appropriately. It is a recursive function, // however circular data structures are detected and handled properly. func (f *formatState) format(v reflect.Value) { // Handle invalid reflect values immediately. kind := v.Kind() if kind == reflect.Invalid { f.fs.Write(invalidAngleBytes) return } // Handle pointers specially. if kind == reflect.Ptr { f.formatPtr(v) return } // Print type information unless already handled elsewhere. if !f.ignoreNextType && f.fs.Flag('#') { f.fs.Write(openParenBytes) f.fs.Write([]byte(v.Type().String())) f.fs.Write(closeParenBytes) } f.ignoreNextType = false // Call Stringer/error interfaces if they exist and the handle methods // flag is enabled. if !f.cs.DisableMethods { if (kind != reflect.Invalid) && (kind != reflect.Interface) { if handled := handleMethods(f.cs, f.fs, v); handled { return } } } switch kind { case reflect.Invalid: // Do nothing. We should never get here since invalid has already // been handled above. case reflect.Bool: printBool(f.fs, v.Bool()) case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int: printInt(f.fs, v.Int(), 10) case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint: printUint(f.fs, v.Uint(), 10) case reflect.Float32: printFloat(f.fs, v.Float(), 32) case reflect.Float64: printFloat(f.fs, v.Float(), 64) case reflect.Complex64: printComplex(f.fs, v.Complex(), 32) case reflect.Complex128: printComplex(f.fs, v.Complex(), 64) case reflect.Slice: if v.IsNil() { f.fs.Write(nilAngleBytes) break } fallthrough case reflect.Array: f.fs.Write(openBracketBytes) f.depth++ if (f.cs.MaxDepth != 0) && (f.depth > f.cs.MaxDepth) { f.fs.Write(maxShortBytes) } else { numEntries := v.Len() for i := 0; i < numEntries; i++ { if i > 0 { f.fs.Write(spaceBytes) } f.ignoreNextType = true f.format(f.unpackValue(v.Index(i))) } } f.depth-- f.fs.Write(closeBracketBytes) case reflect.String: f.fs.Write([]byte(v.String())) case reflect.Interface: // The only time we should get here is for nil interfaces due to // unpackValue calls. if v.IsNil() { f.fs.Write(nilAngleBytes) } case reflect.Ptr: // Do nothing. We should never get here since pointers have already // been handled above. case reflect.Map: // nil maps should be indicated as different than empty maps if v.IsNil() { f.fs.Write(nilAngleBytes) break } f.fs.Write(openMapBytes) f.depth++ if (f.cs.MaxDepth != 0) && (f.depth > f.cs.MaxDepth) { f.fs.Write(maxShortBytes) } else { keys := v.MapKeys() if f.cs.SortKeys { sortValues(keys, f.cs) } for i, key := range keys { if i > 0 { f.fs.Write(spaceBytes) } f.ignoreNextType = true f.format(f.unpackValue(key)) f.fs.Write(colonBytes) f.ignoreNextType = true f.format(f.unpackValue(v.MapIndex(key))) } } f.depth-- f.fs.Write(closeMapBytes) case reflect.Struct: numFields := v.NumField() f.fs.Write(openBraceBytes) f.depth++ if (f.cs.MaxDepth != 0) && (f.depth > f.cs.MaxDepth) { f.fs.Write(maxShortBytes) } else { vt := v.Type() for i := 0; i < numFields; i++ { if i > 0 { f.fs.Write(spaceBytes) } vtf := vt.Field(i) if f.fs.Flag('+') || f.fs.Flag('#') { f.fs.Write([]byte(vtf.Name)) f.fs.Write(colonBytes) } f.format(f.unpackValue(v.Field(i))) } } f.depth-- f.fs.Write(closeBraceBytes) case reflect.Uintptr: printHexPtr(f.fs, uintptr(v.Uint())) case reflect.UnsafePointer, reflect.Chan, reflect.Func: printHexPtr(f.fs, v.Pointer()) // There were not any other types at the time this code was written, but // fall back to letting the default fmt package handle it if any get added. default: format := f.buildDefaultFormat() if v.CanInterface() { fmt.Fprintf(f.fs, format, v.Interface()) } else { fmt.Fprintf(f.fs, format, v.String()) } } } // Format satisfies the fmt.Formatter interface. See NewFormatter for usage // details. func (f *formatState) Format(fs fmt.State, verb rune) { f.fs = fs // Use standard formatting for verbs that are not v. if verb != 'v' { format := f.constructOrigFormat(verb) fmt.Fprintf(fs, format, f.value) return } if f.value == nil { if fs.Flag('#') { fs.Write(interfaceBytes) } fs.Write(nilAngleBytes) return } f.format(reflect.ValueOf(f.value)) } // newFormatter is a helper function to consolidate the logic from the various // public methods which take varying config states. func newFormatter(cs *ConfigState, v interface{}) fmt.Formatter { fs := &formatState{value: v, cs: cs} fs.pointers = make(map[uintptr]int) return fs } /* NewFormatter returns a custom formatter that satisfies the fmt.Formatter interface. As a result, it integrates cleanly with standard fmt package printing functions. The formatter is useful for inline printing of smaller data types similar to the standard %v format specifier. The custom formatter only responds to the %v (most compact), %+v (adds pointer addresses), %#v (adds types), or %#+v (adds types and pointer addresses) verb combinations. Any other verbs such as %x and %q will be sent to the the standard fmt package for formatting. In addition, the custom formatter ignores the width and precision arguments (however they will still work on the format specifiers not handled by the custom formatter). Typically this function shouldn't be called directly. It is much easier to make use of the custom formatter by calling one of the convenience functions such as Printf, Println, or Fprintf. */ func NewFormatter(v interface{}) fmt.Formatter { return newFormatter(&Config, v) } lxd-2.0.0/dist/src/github.com/stretchr/testify/vendor/github.com/davecgh/go-spew/spew/common.go0000644061062106075000000002416712702772371035161 0ustar00stgraberdomain admins00000000000000/* * Copyright (c) 2013 Dave Collins * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ package spew import ( "bytes" "fmt" "io" "reflect" "sort" "strconv" ) // Some constants in the form of bytes to avoid string overhead. This mirrors // the technique used in the fmt package. var ( panicBytes = []byte("(PANIC=") plusBytes = []byte("+") iBytes = []byte("i") trueBytes = []byte("true") falseBytes = []byte("false") interfaceBytes = []byte("(interface {})") commaNewlineBytes = []byte(",\n") newlineBytes = []byte("\n") openBraceBytes = []byte("{") openBraceNewlineBytes = []byte("{\n") closeBraceBytes = []byte("}") asteriskBytes = []byte("*") colonBytes = []byte(":") colonSpaceBytes = []byte(": ") openParenBytes = []byte("(") closeParenBytes = []byte(")") spaceBytes = []byte(" ") pointerChainBytes = []byte("->") nilAngleBytes = []byte("") maxNewlineBytes = []byte("\n") maxShortBytes = []byte("") circularBytes = []byte("") circularShortBytes = []byte("") invalidAngleBytes = []byte("") openBracketBytes = []byte("[") closeBracketBytes = []byte("]") percentBytes = []byte("%") precisionBytes = []byte(".") openAngleBytes = []byte("<") closeAngleBytes = []byte(">") openMapBytes = []byte("map[") closeMapBytes = []byte("]") lenEqualsBytes = []byte("len=") capEqualsBytes = []byte("cap=") ) // hexDigits is used to map a decimal value to a hex digit. var hexDigits = "0123456789abcdef" // catchPanic handles any panics that might occur during the handleMethods // calls. func catchPanic(w io.Writer, v reflect.Value) { if err := recover(); err != nil { w.Write(panicBytes) fmt.Fprintf(w, "%v", err) w.Write(closeParenBytes) } } // handleMethods attempts to call the Error and String methods on the underlying // type the passed reflect.Value represents and outputes the result to Writer w. // // It handles panics in any called methods by catching and displaying the error // as the formatted value. func handleMethods(cs *ConfigState, w io.Writer, v reflect.Value) (handled bool) { // We need an interface to check if the type implements the error or // Stringer interface. However, the reflect package won't give us an // interface on certain things like unexported struct fields in order // to enforce visibility rules. We use unsafe, when it's available, // to bypass these restrictions since this package does not mutate the // values. if !v.CanInterface() { if UnsafeDisabled { return false } v = unsafeReflectValue(v) } // Choose whether or not to do error and Stringer interface lookups against // the base type or a pointer to the base type depending on settings. // Technically calling one of these methods with a pointer receiver can // mutate the value, however, types which choose to satisify an error or // Stringer interface with a pointer receiver should not be mutating their // state inside these interface methods. if !cs.DisablePointerMethods && !UnsafeDisabled && !v.CanAddr() { v = unsafeReflectValue(v) } if v.CanAddr() { v = v.Addr() } // Is it an error or Stringer? switch iface := v.Interface().(type) { case error: defer catchPanic(w, v) if cs.ContinueOnMethod { w.Write(openParenBytes) w.Write([]byte(iface.Error())) w.Write(closeParenBytes) w.Write(spaceBytes) return false } w.Write([]byte(iface.Error())) return true case fmt.Stringer: defer catchPanic(w, v) if cs.ContinueOnMethod { w.Write(openParenBytes) w.Write([]byte(iface.String())) w.Write(closeParenBytes) w.Write(spaceBytes) return false } w.Write([]byte(iface.String())) return true } return false } // printBool outputs a boolean value as true or false to Writer w. func printBool(w io.Writer, val bool) { if val { w.Write(trueBytes) } else { w.Write(falseBytes) } } // printInt outputs a signed integer value to Writer w. func printInt(w io.Writer, val int64, base int) { w.Write([]byte(strconv.FormatInt(val, base))) } // printUint outputs an unsigned integer value to Writer w. func printUint(w io.Writer, val uint64, base int) { w.Write([]byte(strconv.FormatUint(val, base))) } // printFloat outputs a floating point value using the specified precision, // which is expected to be 32 or 64bit, to Writer w. func printFloat(w io.Writer, val float64, precision int) { w.Write([]byte(strconv.FormatFloat(val, 'g', -1, precision))) } // printComplex outputs a complex value using the specified float precision // for the real and imaginary parts to Writer w. func printComplex(w io.Writer, c complex128, floatPrecision int) { r := real(c) w.Write(openParenBytes) w.Write([]byte(strconv.FormatFloat(r, 'g', -1, floatPrecision))) i := imag(c) if i >= 0 { w.Write(plusBytes) } w.Write([]byte(strconv.FormatFloat(i, 'g', -1, floatPrecision))) w.Write(iBytes) w.Write(closeParenBytes) } // printHexPtr outputs a uintptr formatted as hexidecimal with a leading '0x' // prefix to Writer w. func printHexPtr(w io.Writer, p uintptr) { // Null pointer. num := uint64(p) if num == 0 { w.Write(nilAngleBytes) return } // Max uint64 is 16 bytes in hex + 2 bytes for '0x' prefix buf := make([]byte, 18) // It's simpler to construct the hex string right to left. base := uint64(16) i := len(buf) - 1 for num >= base { buf[i] = hexDigits[num%base] num /= base i-- } buf[i] = hexDigits[num] // Add '0x' prefix. i-- buf[i] = 'x' i-- buf[i] = '0' // Strip unused leading bytes. buf = buf[i:] w.Write(buf) } // valuesSorter implements sort.Interface to allow a slice of reflect.Value // elements to be sorted. type valuesSorter struct { values []reflect.Value strings []string // either nil or same len and values cs *ConfigState } // newValuesSorter initializes a valuesSorter instance, which holds a set of // surrogate keys on which the data should be sorted. It uses flags in // ConfigState to decide if and how to populate those surrogate keys. func newValuesSorter(values []reflect.Value, cs *ConfigState) sort.Interface { vs := &valuesSorter{values: values, cs: cs} if canSortSimply(vs.values[0].Kind()) { return vs } if !cs.DisableMethods { vs.strings = make([]string, len(values)) for i := range vs.values { b := bytes.Buffer{} if !handleMethods(cs, &b, vs.values[i]) { vs.strings = nil break } vs.strings[i] = b.String() } } if vs.strings == nil && cs.SpewKeys { vs.strings = make([]string, len(values)) for i := range vs.values { vs.strings[i] = Sprintf("%#v", vs.values[i].Interface()) } } return vs } // canSortSimply tests whether a reflect.Kind is a primitive that can be sorted // directly, or whether it should be considered for sorting by surrogate keys // (if the ConfigState allows it). func canSortSimply(kind reflect.Kind) bool { // This switch parallels valueSortLess, except for the default case. switch kind { case reflect.Bool: return true case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int: return true case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint: return true case reflect.Float32, reflect.Float64: return true case reflect.String: return true case reflect.Uintptr: return true case reflect.Array: return true } return false } // Len returns the number of values in the slice. It is part of the // sort.Interface implementation. func (s *valuesSorter) Len() int { return len(s.values) } // Swap swaps the values at the passed indices. It is part of the // sort.Interface implementation. func (s *valuesSorter) Swap(i, j int) { s.values[i], s.values[j] = s.values[j], s.values[i] if s.strings != nil { s.strings[i], s.strings[j] = s.strings[j], s.strings[i] } } // valueSortLess returns whether the first value should sort before the second // value. It is used by valueSorter.Less as part of the sort.Interface // implementation. func valueSortLess(a, b reflect.Value) bool { switch a.Kind() { case reflect.Bool: return !a.Bool() && b.Bool() case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int: return a.Int() < b.Int() case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint: return a.Uint() < b.Uint() case reflect.Float32, reflect.Float64: return a.Float() < b.Float() case reflect.String: return a.String() < b.String() case reflect.Uintptr: return a.Uint() < b.Uint() case reflect.Array: // Compare the contents of both arrays. l := a.Len() for i := 0; i < l; i++ { av := a.Index(i) bv := b.Index(i) if av.Interface() == bv.Interface() { continue } return valueSortLess(av, bv) } } return a.String() < b.String() } // Less returns whether the value at index i should sort before the // value at index j. It is part of the sort.Interface implementation. func (s *valuesSorter) Less(i, j int) bool { if s.strings == nil { return valueSortLess(s.values[i], s.values[j]) } return s.strings[i] < s.strings[j] } // sortValues is a sort function that handles both native types and any type that // can be converted to error or Stringer. Other inputs are sorted according to // their Value.String() value to ensure display stability. func sortValues(values []reflect.Value, cs *ConfigState) { if len(values) == 0 { return } sort.Sort(newValuesSorter(values, cs)) } lxd-2.0.0/dist/src/github.com/stretchr/testify/vendor/github.com/davecgh/go-spew/spew/doc.go0000644061062106075000000001773112702772371034435 0ustar00stgraberdomain admins00000000000000/* * Copyright (c) 2013 Dave Collins * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /* Package spew implements a deep pretty printer for Go data structures to aid in debugging. A quick overview of the additional features spew provides over the built-in printing facilities for Go data types are as follows: * Pointers are dereferenced and followed * Circular data structures are detected and handled properly * Custom Stringer/error interfaces are optionally invoked, including on unexported types * Custom types which only implement the Stringer/error interfaces via a pointer receiver are optionally invoked when passing non-pointer variables * Byte arrays and slices are dumped like the hexdump -C command which includes offsets, byte values in hex, and ASCII output (only when using Dump style) There are two different approaches spew allows for dumping Go data structures: * Dump style which prints with newlines, customizable indentation, and additional debug information such as types and all pointer addresses used to indirect to the final value * A custom Formatter interface that integrates cleanly with the standard fmt package and replaces %v, %+v, %#v, and %#+v to provide inline printing similar to the default %v while providing the additional functionality outlined above and passing unsupported format verbs such as %x and %q along to fmt Quick Start This section demonstrates how to quickly get started with spew. See the sections below for further details on formatting and configuration options. To dump a variable with full newlines, indentation, type, and pointer information use Dump, Fdump, or Sdump: spew.Dump(myVar1, myVar2, ...) spew.Fdump(someWriter, myVar1, myVar2, ...) str := spew.Sdump(myVar1, myVar2, ...) Alternatively, if you would prefer to use format strings with a compacted inline printing style, use the convenience wrappers Printf, Fprintf, etc with %v (most compact), %+v (adds pointer addresses), %#v (adds types), or %#+v (adds types and pointer addresses): spew.Printf("myVar1: %v -- myVar2: %+v", myVar1, myVar2) spew.Printf("myVar3: %#v -- myVar4: %#+v", myVar3, myVar4) spew.Fprintf(someWriter, "myVar1: %v -- myVar2: %+v", myVar1, myVar2) spew.Fprintf(someWriter, "myVar3: %#v -- myVar4: %#+v", myVar3, myVar4) Configuration Options Configuration of spew is handled by fields in the ConfigState type. For convenience, all of the top-level functions use a global state available via the spew.Config global. It is also possible to create a ConfigState instance that provides methods equivalent to the top-level functions. This allows concurrent configuration options. See the ConfigState documentation for more details. The following configuration options are available: * Indent String to use for each indentation level for Dump functions. It is a single space by default. A popular alternative is "\t". * MaxDepth Maximum number of levels to descend into nested data structures. There is no limit by default. * DisableMethods Disables invocation of error and Stringer interface methods. Method invocation is enabled by default. * DisablePointerMethods Disables invocation of error and Stringer interface methods on types which only accept pointer receivers from non-pointer variables. Pointer method invocation is enabled by default. * ContinueOnMethod Enables recursion into types after invoking error and Stringer interface methods. Recursion after method invocation is disabled by default. * SortKeys Specifies map keys should be sorted before being printed. Use this to have a more deterministic, diffable output. Note that only native types (bool, int, uint, floats, uintptr and string) and types which implement error or Stringer interfaces are supported with other types sorted according to the reflect.Value.String() output which guarantees display stability. Natural map order is used by default. * SpewKeys Specifies that, as a last resort attempt, map keys should be spewed to strings and sorted by those strings. This is only considered if SortKeys is true. Dump Usage Simply call spew.Dump with a list of variables you want to dump: spew.Dump(myVar1, myVar2, ...) You may also call spew.Fdump if you would prefer to output to an arbitrary io.Writer. For example, to dump to standard error: spew.Fdump(os.Stderr, myVar1, myVar2, ...) A third option is to call spew.Sdump to get the formatted output as a string: str := spew.Sdump(myVar1, myVar2, ...) Sample Dump Output See the Dump example for details on the setup of the types and variables being shown here. (main.Foo) { unexportedField: (*main.Bar)(0xf84002e210)({ flag: (main.Flag) flagTwo, data: (uintptr) }), ExportedField: (map[interface {}]interface {}) (len=1) { (string) (len=3) "one": (bool) true } } Byte (and uint8) arrays and slices are displayed uniquely like the hexdump -C command as shown. ([]uint8) (len=32 cap=32) { 00000000 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 |............... | 00000010 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 |!"#$%&'()*+,-./0| 00000020 31 32 |12| } Custom Formatter Spew provides a custom formatter that implements the fmt.Formatter interface so that it integrates cleanly with standard fmt package printing functions. The formatter is useful for inline printing of smaller data types similar to the standard %v format specifier. The custom formatter only responds to the %v (most compact), %+v (adds pointer addresses), %#v (adds types), or %#+v (adds types and pointer addresses) verb combinations. Any other verbs such as %x and %q will be sent to the the standard fmt package for formatting. In addition, the custom formatter ignores the width and precision arguments (however they will still work on the format specifiers not handled by the custom formatter). Custom Formatter Usage The simplest way to make use of the spew custom formatter is to call one of the convenience functions such as spew.Printf, spew.Println, or spew.Printf. The functions have syntax you are most likely already familiar with: spew.Printf("myVar1: %v -- myVar2: %+v", myVar1, myVar2) spew.Printf("myVar3: %#v -- myVar4: %#+v", myVar3, myVar4) spew.Println(myVar, myVar2) spew.Fprintf(os.Stderr, "myVar1: %v -- myVar2: %+v", myVar1, myVar2) spew.Fprintf(os.Stderr, "myVar3: %#v -- myVar4: %#+v", myVar3, myVar4) See the Index for the full list convenience functions. Sample Formatter Output Double pointer to a uint8: %v: <**>5 %+v: <**>(0xf8400420d0->0xf8400420c8)5 %#v: (**uint8)5 %#+v: (**uint8)(0xf8400420d0->0xf8400420c8)5 Pointer to circular struct with a uint8 field and a pointer to itself: %v: <*>{1 <*>} %+v: <*>(0xf84003e260){ui8:1 c:<*>(0xf84003e260)} %#v: (*main.circular){ui8:(uint8)1 c:(*main.circular)} %#+v: (*main.circular)(0xf84003e260){ui8:(uint8)1 c:(*main.circular)(0xf84003e260)} See the Printf example for details on the setup of variables being shown here. Errors Since it is possible for custom Stringer/error interfaces to panic, spew detects them and handles them internally by printing the panic information inline with the output. Since spew is intended to provide deep pretty printing capabilities on structures, it intentionally does not return any errors. */ package spew lxd-2.0.0/dist/src/github.com/stretchr/testify/vendor/github.com/davecgh/go-spew/spew/config.go0000644061062106075000000003025512702772371035131 0ustar00stgraberdomain admins00000000000000/* * Copyright (c) 2013 Dave Collins * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ package spew import ( "bytes" "fmt" "io" "os" ) // ConfigState houses the configuration options used by spew to format and // display values. There is a global instance, Config, that is used to control // all top-level Formatter and Dump functionality. Each ConfigState instance // provides methods equivalent to the top-level functions. // // The zero value for ConfigState provides no indentation. You would typically // want to set it to a space or a tab. // // Alternatively, you can use NewDefaultConfig to get a ConfigState instance // with default settings. See the documentation of NewDefaultConfig for default // values. type ConfigState struct { // Indent specifies the string to use for each indentation level. The // global config instance that all top-level functions use set this to a // single space by default. If you would like more indentation, you might // set this to a tab with "\t" or perhaps two spaces with " ". Indent string // MaxDepth controls the maximum number of levels to descend into nested // data structures. The default, 0, means there is no limit. // // NOTE: Circular data structures are properly detected, so it is not // necessary to set this value unless you specifically want to limit deeply // nested data structures. MaxDepth int // DisableMethods specifies whether or not error and Stringer interfaces are // invoked for types that implement them. DisableMethods bool // DisablePointerMethods specifies whether or not to check for and invoke // error and Stringer interfaces on types which only accept a pointer // receiver when the current type is not a pointer. // // NOTE: This might be an unsafe action since calling one of these methods // with a pointer receiver could technically mutate the value, however, // in practice, types which choose to satisify an error or Stringer // interface with a pointer receiver should not be mutating their state // inside these interface methods. As a result, this option relies on // access to the unsafe package, so it will not have any effect when // running in environments without access to the unsafe package such as // Google App Engine or with the "disableunsafe" build tag specified. DisablePointerMethods bool // ContinueOnMethod specifies whether or not recursion should continue once // a custom error or Stringer interface is invoked. The default, false, // means it will print the results of invoking the custom error or Stringer // interface and return immediately instead of continuing to recurse into // the internals of the data type. // // NOTE: This flag does not have any effect if method invocation is disabled // via the DisableMethods or DisablePointerMethods options. ContinueOnMethod bool // SortKeys specifies map keys should be sorted before being printed. Use // this to have a more deterministic, diffable output. Note that only // native types (bool, int, uint, floats, uintptr and string) and types // that support the error or Stringer interfaces (if methods are // enabled) are supported, with other types sorted according to the // reflect.Value.String() output which guarantees display stability. SortKeys bool // SpewKeys specifies that, as a last resort attempt, map keys should // be spewed to strings and sorted by those strings. This is only // considered if SortKeys is true. SpewKeys bool } // Config is the active configuration of the top-level functions. // The configuration can be changed by modifying the contents of spew.Config. var Config = ConfigState{Indent: " "} // Errorf is a wrapper for fmt.Errorf that treats each argument as if it were // passed with a Formatter interface returned by c.NewFormatter. It returns // the formatted string as a value that satisfies error. See NewFormatter // for formatting details. // // This function is shorthand for the following syntax: // // fmt.Errorf(format, c.NewFormatter(a), c.NewFormatter(b)) func (c *ConfigState) Errorf(format string, a ...interface{}) (err error) { return fmt.Errorf(format, c.convertArgs(a)...) } // Fprint is a wrapper for fmt.Fprint that treats each argument as if it were // passed with a Formatter interface returned by c.NewFormatter. It returns // the number of bytes written and any write error encountered. See // NewFormatter for formatting details. // // This function is shorthand for the following syntax: // // fmt.Fprint(w, c.NewFormatter(a), c.NewFormatter(b)) func (c *ConfigState) Fprint(w io.Writer, a ...interface{}) (n int, err error) { return fmt.Fprint(w, c.convertArgs(a)...) } // Fprintf is a wrapper for fmt.Fprintf that treats each argument as if it were // passed with a Formatter interface returned by c.NewFormatter. It returns // the number of bytes written and any write error encountered. See // NewFormatter for formatting details. // // This function is shorthand for the following syntax: // // fmt.Fprintf(w, format, c.NewFormatter(a), c.NewFormatter(b)) func (c *ConfigState) Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error) { return fmt.Fprintf(w, format, c.convertArgs(a)...) } // Fprintln is a wrapper for fmt.Fprintln that treats each argument as if it // passed with a Formatter interface returned by c.NewFormatter. See // NewFormatter for formatting details. // // This function is shorthand for the following syntax: // // fmt.Fprintln(w, c.NewFormatter(a), c.NewFormatter(b)) func (c *ConfigState) Fprintln(w io.Writer, a ...interface{}) (n int, err error) { return fmt.Fprintln(w, c.convertArgs(a)...) } // Print is a wrapper for fmt.Print that treats each argument as if it were // passed with a Formatter interface returned by c.NewFormatter. It returns // the number of bytes written and any write error encountered. See // NewFormatter for formatting details. // // This function is shorthand for the following syntax: // // fmt.Print(c.NewFormatter(a), c.NewFormatter(b)) func (c *ConfigState) Print(a ...interface{}) (n int, err error) { return fmt.Print(c.convertArgs(a)...) } // Printf is a wrapper for fmt.Printf that treats each argument as if it were // passed with a Formatter interface returned by c.NewFormatter. It returns // the number of bytes written and any write error encountered. See // NewFormatter for formatting details. // // This function is shorthand for the following syntax: // // fmt.Printf(format, c.NewFormatter(a), c.NewFormatter(b)) func (c *ConfigState) Printf(format string, a ...interface{}) (n int, err error) { return fmt.Printf(format, c.convertArgs(a)...) } // Println is a wrapper for fmt.Println that treats each argument as if it were // passed with a Formatter interface returned by c.NewFormatter. It returns // the number of bytes written and any write error encountered. See // NewFormatter for formatting details. // // This function is shorthand for the following syntax: // // fmt.Println(c.NewFormatter(a), c.NewFormatter(b)) func (c *ConfigState) Println(a ...interface{}) (n int, err error) { return fmt.Println(c.convertArgs(a)...) } // Sprint is a wrapper for fmt.Sprint that treats each argument as if it were // passed with a Formatter interface returned by c.NewFormatter. It returns // the resulting string. See NewFormatter for formatting details. // // This function is shorthand for the following syntax: // // fmt.Sprint(c.NewFormatter(a), c.NewFormatter(b)) func (c *ConfigState) Sprint(a ...interface{}) string { return fmt.Sprint(c.convertArgs(a)...) } // Sprintf is a wrapper for fmt.Sprintf that treats each argument as if it were // passed with a Formatter interface returned by c.NewFormatter. It returns // the resulting string. See NewFormatter for formatting details. // // This function is shorthand for the following syntax: // // fmt.Sprintf(format, c.NewFormatter(a), c.NewFormatter(b)) func (c *ConfigState) Sprintf(format string, a ...interface{}) string { return fmt.Sprintf(format, c.convertArgs(a)...) } // Sprintln is a wrapper for fmt.Sprintln that treats each argument as if it // were passed with a Formatter interface returned by c.NewFormatter. It // returns the resulting string. See NewFormatter for formatting details. // // This function is shorthand for the following syntax: // // fmt.Sprintln(c.NewFormatter(a), c.NewFormatter(b)) func (c *ConfigState) Sprintln(a ...interface{}) string { return fmt.Sprintln(c.convertArgs(a)...) } /* NewFormatter returns a custom formatter that satisfies the fmt.Formatter interface. As a result, it integrates cleanly with standard fmt package printing functions. The formatter is useful for inline printing of smaller data types similar to the standard %v format specifier. The custom formatter only responds to the %v (most compact), %+v (adds pointer addresses), %#v (adds types), and %#+v (adds types and pointer addresses) verb combinations. Any other verbs such as %x and %q will be sent to the the standard fmt package for formatting. In addition, the custom formatter ignores the width and precision arguments (however they will still work on the format specifiers not handled by the custom formatter). Typically this function shouldn't be called directly. It is much easier to make use of the custom formatter by calling one of the convenience functions such as c.Printf, c.Println, or c.Printf. */ func (c *ConfigState) NewFormatter(v interface{}) fmt.Formatter { return newFormatter(c, v) } // Fdump formats and displays the passed arguments to io.Writer w. It formats // exactly the same as Dump. func (c *ConfigState) Fdump(w io.Writer, a ...interface{}) { fdump(c, w, a...) } /* Dump displays the passed parameters to standard out with newlines, customizable indentation, and additional debug information such as complete types and all pointer addresses used to indirect to the final value. It provides the following features over the built-in printing facilities provided by the fmt package: * Pointers are dereferenced and followed * Circular data structures are detected and handled properly * Custom Stringer/error interfaces are optionally invoked, including on unexported types * Custom types which only implement the Stringer/error interfaces via a pointer receiver are optionally invoked when passing non-pointer variables * Byte arrays and slices are dumped like the hexdump -C command which includes offsets, byte values in hex, and ASCII output The configuration options are controlled by modifying the public members of c. See ConfigState for options documentation. See Fdump if you would prefer dumping to an arbitrary io.Writer or Sdump to get the formatted result as a string. */ func (c *ConfigState) Dump(a ...interface{}) { fdump(c, os.Stdout, a...) } // Sdump returns a string with the passed arguments formatted exactly the same // as Dump. func (c *ConfigState) Sdump(a ...interface{}) string { var buf bytes.Buffer fdump(c, &buf, a...) return buf.String() } // convertArgs accepts a slice of arguments and returns a slice of the same // length with each argument converted to a spew Formatter interface using // the ConfigState associated with s. func (c *ConfigState) convertArgs(args []interface{}) (formatters []interface{}) { formatters = make([]interface{}, len(args)) for index, arg := range args { formatters[index] = newFormatter(c, arg) } return formatters } // NewDefaultConfig returns a ConfigState with the following default settings. // // Indent: " " // MaxDepth: 0 // DisableMethods: false // DisablePointerMethods: false // ContinueOnMethod: false // SortKeys: false func NewDefaultConfig() *ConfigState { return &ConfigState{Indent: " "} } lxd-2.0.0/dist/src/github.com/stretchr/testify/vendor/github.com/davecgh/go-spew/LICENSE0000644061062106075000000000135612702772371033364 0ustar00stgraberdomain admins00000000000000Copyright (c) 2012-2013 Dave Collins Permission to use, copy, modify, and distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. lxd-2.0.0/dist/src/github.com/stretchr/testify/vendor/github.com/stretchr/0000755061062106075000000000000012702772371031226 5ustar00stgraberdomain admins00000000000000lxd-2.0.0/dist/src/github.com/stretchr/testify/vendor/github.com/stretchr/objx/0000755061062106075000000000000012702772371032170 5ustar00stgraberdomain admins00000000000000lxd-2.0.0/dist/src/github.com/stretchr/testify/vendor/github.com/stretchr/objx/tests.go0000644061062106075000000000055212702772371033663 0ustar00stgraberdomain admins00000000000000package objx // Has gets whether there is something at the specified selector // or not. // // If m is nil, Has will always return false. func (m Map) Has(selector string) bool { if m == nil { return false } return !m.Get(selector).IsNil() } // IsNil gets whether the data is nil or not. func (v *Value) IsNil() bool { return v == nil || v.data == nil } lxd-2.0.0/dist/src/github.com/stretchr/testify/vendor/github.com/stretchr/objx/value.go0000644061062106075000000000045412702772371033636 0ustar00stgraberdomain admins00000000000000package objx // Value provides methods for extracting interface{} data in various // types. type Value struct { // data contains the raw data being managed by this Value data interface{} } // Data returns the raw data contained by this Value func (v *Value) Data() interface{} { return v.data } lxd-2.0.0/dist/src/github.com/stretchr/testify/vendor/github.com/stretchr/objx/README.md0000644061062106075000000000013112702772371033442 0ustar00stgraberdomain admins00000000000000# objx * Jump into the [API Documentation](http://godoc.org/github.com/stretchr/objx) lxd-2.0.0/dist/src/github.com/stretchr/testify/vendor/github.com/stretchr/objx/security.go0000644061062106075000000000042112702772371034363 0ustar00stgraberdomain admins00000000000000package objx import ( "crypto/sha1" "encoding/hex" ) // HashWithKey hashes the specified string using the security // key. func HashWithKey(data, key string) string { hash := sha1.New() hash.Write([]byte(data + ":" + key)) return hex.EncodeToString(hash.Sum(nil)) } lxd-2.0.0/dist/src/github.com/stretchr/testify/vendor/github.com/stretchr/objx/constants.go0000644061062106075000000000050512702772371034533 0ustar00stgraberdomain admins00000000000000package objx const ( // PathSeparator is the character used to separate the elements // of the keypath. // // For example, `location.address.city` PathSeparator string = "." // SignatureSeparator is the character that is used to // separate the Base64 string from the security signature. SignatureSeparator = "_" ) lxd-2.0.0/dist/src/github.com/stretchr/testify/vendor/github.com/stretchr/objx/conversions.go0000644061062106075000000000477512702772371035104 0ustar00stgraberdomain admins00000000000000package objx import ( "bytes" "encoding/base64" "encoding/json" "errors" "fmt" "net/url" ) // JSON converts the contained object to a JSON string // representation func (m Map) JSON() (string, error) { result, err := json.Marshal(m) if err != nil { err = errors.New("objx: JSON encode failed with: " + err.Error()) } return string(result), err } // MustJSON converts the contained object to a JSON string // representation and panics if there is an error func (m Map) MustJSON() string { result, err := m.JSON() if err != nil { panic(err.Error()) } return result } // Base64 converts the contained object to a Base64 string // representation of the JSON string representation func (m Map) Base64() (string, error) { var buf bytes.Buffer jsonData, err := m.JSON() if err != nil { return "", err } encoder := base64.NewEncoder(base64.StdEncoding, &buf) encoder.Write([]byte(jsonData)) encoder.Close() return buf.String(), nil } // MustBase64 converts the contained object to a Base64 string // representation of the JSON string representation and panics // if there is an error func (m Map) MustBase64() string { result, err := m.Base64() if err != nil { panic(err.Error()) } return result } // SignedBase64 converts the contained object to a Base64 string // representation of the JSON string representation and signs it // using the provided key. func (m Map) SignedBase64(key string) (string, error) { base64, err := m.Base64() if err != nil { return "", err } sig := HashWithKey(base64, key) return base64 + SignatureSeparator + sig, nil } // MustSignedBase64 converts the contained object to a Base64 string // representation of the JSON string representation and signs it // using the provided key and panics if there is an error func (m Map) MustSignedBase64(key string) string { result, err := m.SignedBase64(key) if err != nil { panic(err.Error()) } return result } /* URL Query ------------------------------------------------ */ // URLValues creates a url.Values object from an Obj. This // function requires that the wrapped object be a map[string]interface{} func (m Map) URLValues() url.Values { vals := make(url.Values) for k, v := range m { //TODO: can this be done without sprintf? vals.Set(k, fmt.Sprintf("%v", v)) } return vals } // URLQuery gets an encoded URL query representing the given // Obj. This function requires that the wrapped object be a // map[string]interface{} func (m Map) URLQuery() (string, error) { return m.URLValues().Encode(), nil } lxd-2.0.0/dist/src/github.com/stretchr/testify/vendor/github.com/stretchr/objx/map.go0000644061062106075000000001246612702772371033305 0ustar00stgraberdomain admins00000000000000package objx import ( "encoding/base64" "encoding/json" "errors" "io/ioutil" "net/url" "strings" ) // MSIConvertable is an interface that defines methods for converting your // custom types to a map[string]interface{} representation. type MSIConvertable interface { // MSI gets a map[string]interface{} (msi) representing the // object. MSI() map[string]interface{} } // Map provides extended functionality for working with // untyped data, in particular map[string]interface (msi). type Map map[string]interface{} // Value returns the internal value instance func (m Map) Value() *Value { return &Value{data: m} } // Nil represents a nil Map. var Nil Map = New(nil) // New creates a new Map containing the map[string]interface{} in the data argument. // If the data argument is not a map[string]interface, New attempts to call the // MSI() method on the MSIConvertable interface to create one. func New(data interface{}) Map { if _, ok := data.(map[string]interface{}); !ok { if converter, ok := data.(MSIConvertable); ok { data = converter.MSI() } else { return nil } } return Map(data.(map[string]interface{})) } // MSI creates a map[string]interface{} and puts it inside a new Map. // // The arguments follow a key, value pattern. // // Panics // // Panics if any key arugment is non-string or if there are an odd number of arguments. // // Example // // To easily create Maps: // // m := objx.MSI("name", "Mat", "age", 29, "subobj", objx.MSI("active", true)) // // // creates an Map equivalent to // m := objx.New(map[string]interface{}{"name": "Mat", "age": 29, "subobj": map[string]interface{}{"active": true}}) func MSI(keyAndValuePairs ...interface{}) Map { newMap := make(map[string]interface{}) keyAndValuePairsLen := len(keyAndValuePairs) if keyAndValuePairsLen%2 != 0 { panic("objx: MSI must have an even number of arguments following the 'key, value' pattern.") } for i := 0; i < keyAndValuePairsLen; i = i + 2 { key := keyAndValuePairs[i] value := keyAndValuePairs[i+1] // make sure the key is a string keyString, keyStringOK := key.(string) if !keyStringOK { panic("objx: MSI must follow 'string, interface{}' pattern. " + keyString + " is not a valid key.") } newMap[keyString] = value } return New(newMap) } // ****** Conversion Constructors // MustFromJSON creates a new Map containing the data specified in the // jsonString. // // Panics if the JSON is invalid. func MustFromJSON(jsonString string) Map { o, err := FromJSON(jsonString) if err != nil { panic("objx: MustFromJSON failed with error: " + err.Error()) } return o } // FromJSON creates a new Map containing the data specified in the // jsonString. // // Returns an error if the JSON is invalid. func FromJSON(jsonString string) (Map, error) { var data interface{} err := json.Unmarshal([]byte(jsonString), &data) if err != nil { return Nil, err } return New(data), nil } // FromBase64 creates a new Obj containing the data specified // in the Base64 string. // // The string is an encoded JSON string returned by Base64 func FromBase64(base64String string) (Map, error) { decoder := base64.NewDecoder(base64.StdEncoding, strings.NewReader(base64String)) decoded, err := ioutil.ReadAll(decoder) if err != nil { return nil, err } return FromJSON(string(decoded)) } // MustFromBase64 creates a new Obj containing the data specified // in the Base64 string and panics if there is an error. // // The string is an encoded JSON string returned by Base64 func MustFromBase64(base64String string) Map { result, err := FromBase64(base64String) if err != nil { panic("objx: MustFromBase64 failed with error: " + err.Error()) } return result } // FromSignedBase64 creates a new Obj containing the data specified // in the Base64 string. // // The string is an encoded JSON string returned by SignedBase64 func FromSignedBase64(base64String, key string) (Map, error) { parts := strings.Split(base64String, SignatureSeparator) if len(parts) != 2 { return nil, errors.New("objx: Signed base64 string is malformed.") } sig := HashWithKey(parts[0], key) if parts[1] != sig { return nil, errors.New("objx: Signature for base64 data does not match.") } return FromBase64(parts[0]) } // MustFromSignedBase64 creates a new Obj containing the data specified // in the Base64 string and panics if there is an error. // // The string is an encoded JSON string returned by Base64 func MustFromSignedBase64(base64String, key string) Map { result, err := FromSignedBase64(base64String, key) if err != nil { panic("objx: MustFromSignedBase64 failed with error: " + err.Error()) } return result } // FromURLQuery generates a new Obj by parsing the specified // query. // // For queries with multiple values, the first value is selected. func FromURLQuery(query string) (Map, error) { vals, err := url.ParseQuery(query) if err != nil { return nil, err } m := make(map[string]interface{}) for k, vals := range vals { m[k] = vals[0] } return New(m), nil } // MustFromURLQuery generates a new Obj by parsing the specified // query. // // For queries with multiple values, the first value is selected. // // Panics if it encounters an error func MustFromURLQuery(query string) Map { o, err := FromURLQuery(query) if err != nil { panic("objx: MustFromURLQuery failed with error: " + err.Error()) } return o } type_specific_codegen.go0000644061062106075000000021614612702772371036764 0ustar00stgraberdomain admins00000000000000lxd-2.0.0/dist/src/github.com/stretchr/testify/vendor/github.com/stretchr/objxpackage objx /* Inter (interface{} and []interface{}) -------------------------------------------------- */ // Inter gets the value as a interface{}, returns the optionalDefault // value or a system default object if the value is the wrong type. func (v *Value) Inter(optionalDefault ...interface{}) interface{} { if s, ok := v.data.(interface{}); ok { return s } if len(optionalDefault) == 1 { return optionalDefault[0] } return nil } // MustInter gets the value as a interface{}. // // Panics if the object is not a interface{}. func (v *Value) MustInter() interface{} { return v.data.(interface{}) } // InterSlice gets the value as a []interface{}, returns the optionalDefault // value or nil if the value is not a []interface{}. func (v *Value) InterSlice(optionalDefault ...[]interface{}) []interface{} { if s, ok := v.data.([]interface{}); ok { return s } if len(optionalDefault) == 1 { return optionalDefault[0] } return nil } // MustInterSlice gets the value as a []interface{}. // // Panics if the object is not a []interface{}. func (v *Value) MustInterSlice() []interface{} { return v.data.([]interface{}) } // IsInter gets whether the object contained is a interface{} or not. func (v *Value) IsInter() bool { _, ok := v.data.(interface{}) return ok } // IsInterSlice gets whether the object contained is a []interface{} or not. func (v *Value) IsInterSlice() bool { _, ok := v.data.([]interface{}) return ok } // EachInter calls the specified callback for each object // in the []interface{}. // // Panics if the object is the wrong type. func (v *Value) EachInter(callback func(int, interface{}) bool) *Value { for index, val := range v.MustInterSlice() { carryon := callback(index, val) if carryon == false { break } } return v } // WhereInter uses the specified decider function to select items // from the []interface{}. The object contained in the result will contain // only the selected items. func (v *Value) WhereInter(decider func(int, interface{}) bool) *Value { var selected []interface{} v.EachInter(func(index int, val interface{}) bool { shouldSelect := decider(index, val) if shouldSelect == false { selected = append(selected, val) } return true }) return &Value{data: selected} } // GroupInter uses the specified grouper function to group the items // keyed by the return of the grouper. The object contained in the // result will contain a map[string][]interface{}. func (v *Value) GroupInter(grouper func(int, interface{}) string) *Value { groups := make(map[string][]interface{}) v.EachInter(func(index int, val interface{}) bool { group := grouper(index, val) if _, ok := groups[group]; !ok { groups[group] = make([]interface{}, 0) } groups[group] = append(groups[group], val) return true }) return &Value{data: groups} } // ReplaceInter uses the specified function to replace each interface{}s // by iterating each item. The data in the returned result will be a // []interface{} containing the replaced items. func (v *Value) ReplaceInter(replacer func(int, interface{}) interface{}) *Value { arr := v.MustInterSlice() replaced := make([]interface{}, len(arr)) v.EachInter(func(index int, val interface{}) bool { replaced[index] = replacer(index, val) return true }) return &Value{data: replaced} } // CollectInter uses the specified collector function to collect a value // for each of the interface{}s in the slice. The data returned will be a // []interface{}. func (v *Value) CollectInter(collector func(int, interface{}) interface{}) *Value { arr := v.MustInterSlice() collected := make([]interface{}, len(arr)) v.EachInter(func(index int, val interface{}) bool { collected[index] = collector(index, val) return true }) return &Value{data: collected} } /* MSI (map[string]interface{} and []map[string]interface{}) -------------------------------------------------- */ // MSI gets the value as a map[string]interface{}, returns the optionalDefault // value or a system default object if the value is the wrong type. func (v *Value) MSI(optionalDefault ...map[string]interface{}) map[string]interface{} { if s, ok := v.data.(map[string]interface{}); ok { return s } if len(optionalDefault) == 1 { return optionalDefault[0] } return nil } // MustMSI gets the value as a map[string]interface{}. // // Panics if the object is not a map[string]interface{}. func (v *Value) MustMSI() map[string]interface{} { return v.data.(map[string]interface{}) } // MSISlice gets the value as a []map[string]interface{}, returns the optionalDefault // value or nil if the value is not a []map[string]interface{}. func (v *Value) MSISlice(optionalDefault ...[]map[string]interface{}) []map[string]interface{} { if s, ok := v.data.([]map[string]interface{}); ok { return s } if len(optionalDefault) == 1 { return optionalDefault[0] } return nil } // MustMSISlice gets the value as a []map[string]interface{}. // // Panics if the object is not a []map[string]interface{}. func (v *Value) MustMSISlice() []map[string]interface{} { return v.data.([]map[string]interface{}) } // IsMSI gets whether the object contained is a map[string]interface{} or not. func (v *Value) IsMSI() bool { _, ok := v.data.(map[string]interface{}) return ok } // IsMSISlice gets whether the object contained is a []map[string]interface{} or not. func (v *Value) IsMSISlice() bool { _, ok := v.data.([]map[string]interface{}) return ok } // EachMSI calls the specified callback for each object // in the []map[string]interface{}. // // Panics if the object is the wrong type. func (v *Value) EachMSI(callback func(int, map[string]interface{}) bool) *Value { for index, val := range v.MustMSISlice() { carryon := callback(index, val) if carryon == false { break } } return v } // WhereMSI uses the specified decider function to select items // from the []map[string]interface{}. The object contained in the result will contain // only the selected items. func (v *Value) WhereMSI(decider func(int, map[string]interface{}) bool) *Value { var selected []map[string]interface{} v.EachMSI(func(index int, val map[string]interface{}) bool { shouldSelect := decider(index, val) if shouldSelect == false { selected = append(selected, val) } return true }) return &Value{data: selected} } // GroupMSI uses the specified grouper function to group the items // keyed by the return of the grouper. The object contained in the // result will contain a map[string][]map[string]interface{}. func (v *Value) GroupMSI(grouper func(int, map[string]interface{}) string) *Value { groups := make(map[string][]map[string]interface{}) v.EachMSI(func(index int, val map[string]interface{}) bool { group := grouper(index, val) if _, ok := groups[group]; !ok { groups[group] = make([]map[string]interface{}, 0) } groups[group] = append(groups[group], val) return true }) return &Value{data: groups} } // ReplaceMSI uses the specified function to replace each map[string]interface{}s // by iterating each item. The data in the returned result will be a // []map[string]interface{} containing the replaced items. func (v *Value) ReplaceMSI(replacer func(int, map[string]interface{}) map[string]interface{}) *Value { arr := v.MustMSISlice() replaced := make([]map[string]interface{}, len(arr)) v.EachMSI(func(index int, val map[string]interface{}) bool { replaced[index] = replacer(index, val) return true }) return &Value{data: replaced} } // CollectMSI uses the specified collector function to collect a value // for each of the map[string]interface{}s in the slice. The data returned will be a // []interface{}. func (v *Value) CollectMSI(collector func(int, map[string]interface{}) interface{}) *Value { arr := v.MustMSISlice() collected := make([]interface{}, len(arr)) v.EachMSI(func(index int, val map[string]interface{}) bool { collected[index] = collector(index, val) return true }) return &Value{data: collected} } /* ObjxMap ((Map) and [](Map)) -------------------------------------------------- */ // ObjxMap gets the value as a (Map), returns the optionalDefault // value or a system default object if the value is the wrong type. func (v *Value) ObjxMap(optionalDefault ...(Map)) Map { if s, ok := v.data.((Map)); ok { return s } if len(optionalDefault) == 1 { return optionalDefault[0] } return New(nil) } // MustObjxMap gets the value as a (Map). // // Panics if the object is not a (Map). func (v *Value) MustObjxMap() Map { return v.data.((Map)) } // ObjxMapSlice gets the value as a [](Map), returns the optionalDefault // value or nil if the value is not a [](Map). func (v *Value) ObjxMapSlice(optionalDefault ...[](Map)) [](Map) { if s, ok := v.data.([](Map)); ok { return s } if len(optionalDefault) == 1 { return optionalDefault[0] } return nil } // MustObjxMapSlice gets the value as a [](Map). // // Panics if the object is not a [](Map). func (v *Value) MustObjxMapSlice() [](Map) { return v.data.([](Map)) } // IsObjxMap gets whether the object contained is a (Map) or not. func (v *Value) IsObjxMap() bool { _, ok := v.data.((Map)) return ok } // IsObjxMapSlice gets whether the object contained is a [](Map) or not. func (v *Value) IsObjxMapSlice() bool { _, ok := v.data.([](Map)) return ok } // EachObjxMap calls the specified callback for each object // in the [](Map). // // Panics if the object is the wrong type. func (v *Value) EachObjxMap(callback func(int, Map) bool) *Value { for index, val := range v.MustObjxMapSlice() { carryon := callback(index, val) if carryon == false { break } } return v } // WhereObjxMap uses the specified decider function to select items // from the [](Map). The object contained in the result will contain // only the selected items. func (v *Value) WhereObjxMap(decider func(int, Map) bool) *Value { var selected [](Map) v.EachObjxMap(func(index int, val Map) bool { shouldSelect := decider(index, val) if shouldSelect == false { selected = append(selected, val) } return true }) return &Value{data: selected} } // GroupObjxMap uses the specified grouper function to group the items // keyed by the return of the grouper. The object contained in the // result will contain a map[string][](Map). func (v *Value) GroupObjxMap(grouper func(int, Map) string) *Value { groups := make(map[string][](Map)) v.EachObjxMap(func(index int, val Map) bool { group := grouper(index, val) if _, ok := groups[group]; !ok { groups[group] = make([](Map), 0) } groups[group] = append(groups[group], val) return true }) return &Value{data: groups} } // ReplaceObjxMap uses the specified function to replace each (Map)s // by iterating each item. The data in the returned result will be a // [](Map) containing the replaced items. func (v *Value) ReplaceObjxMap(replacer func(int, Map) Map) *Value { arr := v.MustObjxMapSlice() replaced := make([](Map), len(arr)) v.EachObjxMap(func(index int, val Map) bool { replaced[index] = replacer(index, val) return true }) return &Value{data: replaced} } // CollectObjxMap uses the specified collector function to collect a value // for each of the (Map)s in the slice. The data returned will be a // []interface{}. func (v *Value) CollectObjxMap(collector func(int, Map) interface{}) *Value { arr := v.MustObjxMapSlice() collected := make([]interface{}, len(arr)) v.EachObjxMap(func(index int, val Map) bool { collected[index] = collector(index, val) return true }) return &Value{data: collected} } /* Bool (bool and []bool) -------------------------------------------------- */ // Bool gets the value as a bool, returns the optionalDefault // value or a system default object if the value is the wrong type. func (v *Value) Bool(optionalDefault ...bool) bool { if s, ok := v.data.(bool); ok { return s } if len(optionalDefault) == 1 { return optionalDefault[0] } return false } // MustBool gets the value as a bool. // // Panics if the object is not a bool. func (v *Value) MustBool() bool { return v.data.(bool) } // BoolSlice gets the value as a []bool, returns the optionalDefault // value or nil if the value is not a []bool. func (v *Value) BoolSlice(optionalDefault ...[]bool) []bool { if s, ok := v.data.([]bool); ok { return s } if len(optionalDefault) == 1 { return optionalDefault[0] } return nil } // MustBoolSlice gets the value as a []bool. // // Panics if the object is not a []bool. func (v *Value) MustBoolSlice() []bool { return v.data.([]bool) } // IsBool gets whether the object contained is a bool or not. func (v *Value) IsBool() bool { _, ok := v.data.(bool) return ok } // IsBoolSlice gets whether the object contained is a []bool or not. func (v *Value) IsBoolSlice() bool { _, ok := v.data.([]bool) return ok } // EachBool calls the specified callback for each object // in the []bool. // // Panics if the object is the wrong type. func (v *Value) EachBool(callback func(int, bool) bool) *Value { for index, val := range v.MustBoolSlice() { carryon := callback(index, val) if carryon == false { break } } return v } // WhereBool uses the specified decider function to select items // from the []bool. The object contained in the result will contain // only the selected items. func (v *Value) WhereBool(decider func(int, bool) bool) *Value { var selected []bool v.EachBool(func(index int, val bool) bool { shouldSelect := decider(index, val) if shouldSelect == false { selected = append(selected, val) } return true }) return &Value{data: selected} } // GroupBool uses the specified grouper function to group the items // keyed by the return of the grouper. The object contained in the // result will contain a map[string][]bool. func (v *Value) GroupBool(grouper func(int, bool) string) *Value { groups := make(map[string][]bool) v.EachBool(func(index int, val bool) bool { group := grouper(index, val) if _, ok := groups[group]; !ok { groups[group] = make([]bool, 0) } groups[group] = append(groups[group], val) return true }) return &Value{data: groups} } // ReplaceBool uses the specified function to replace each bools // by iterating each item. The data in the returned result will be a // []bool containing the replaced items. func (v *Value) ReplaceBool(replacer func(int, bool) bool) *Value { arr := v.MustBoolSlice() replaced := make([]bool, len(arr)) v.EachBool(func(index int, val bool) bool { replaced[index] = replacer(index, val) return true }) return &Value{data: replaced} } // CollectBool uses the specified collector function to collect a value // for each of the bools in the slice. The data returned will be a // []interface{}. func (v *Value) CollectBool(collector func(int, bool) interface{}) *Value { arr := v.MustBoolSlice() collected := make([]interface{}, len(arr)) v.EachBool(func(index int, val bool) bool { collected[index] = collector(index, val) return true }) return &Value{data: collected} } /* Str (string and []string) -------------------------------------------------- */ // Str gets the value as a string, returns the optionalDefault // value or a system default object if the value is the wrong type. func (v *Value) Str(optionalDefault ...string) string { if s, ok := v.data.(string); ok { return s } if len(optionalDefault) == 1 { return optionalDefault[0] } return "" } // MustStr gets the value as a string. // // Panics if the object is not a string. func (v *Value) MustStr() string { return v.data.(string) } // StrSlice gets the value as a []string, returns the optionalDefault // value or nil if the value is not a []string. func (v *Value) StrSlice(optionalDefault ...[]string) []string { if s, ok := v.data.([]string); ok { return s } if len(optionalDefault) == 1 { return optionalDefault[0] } return nil } // MustStrSlice gets the value as a []string. // // Panics if the object is not a []string. func (v *Value) MustStrSlice() []string { return v.data.([]string) } // IsStr gets whether the object contained is a string or not. func (v *Value) IsStr() bool { _, ok := v.data.(string) return ok } // IsStrSlice gets whether the object contained is a []string or not. func (v *Value) IsStrSlice() bool { _, ok := v.data.([]string) return ok } // EachStr calls the specified callback for each object // in the []string. // // Panics if the object is the wrong type. func (v *Value) EachStr(callback func(int, string) bool) *Value { for index, val := range v.MustStrSlice() { carryon := callback(index, val) if carryon == false { break } } return v } // WhereStr uses the specified decider function to select items // from the []string. The object contained in the result will contain // only the selected items. func (v *Value) WhereStr(decider func(int, string) bool) *Value { var selected []string v.EachStr(func(index int, val string) bool { shouldSelect := decider(index, val) if shouldSelect == false { selected = append(selected, val) } return true }) return &Value{data: selected} } // GroupStr uses the specified grouper function to group the items // keyed by the return of the grouper. The object contained in the // result will contain a map[string][]string. func (v *Value) GroupStr(grouper func(int, string) string) *Value { groups := make(map[string][]string) v.EachStr(func(index int, val string) bool { group := grouper(index, val) if _, ok := groups[group]; !ok { groups[group] = make([]string, 0) } groups[group] = append(groups[group], val) return true }) return &Value{data: groups} } // ReplaceStr uses the specified function to replace each strings // by iterating each item. The data in the returned result will be a // []string containing the replaced items. func (v *Value) ReplaceStr(replacer func(int, string) string) *Value { arr := v.MustStrSlice() replaced := make([]string, len(arr)) v.EachStr(func(index int, val string) bool { replaced[index] = replacer(index, val) return true }) return &Value{data: replaced} } // CollectStr uses the specified collector function to collect a value // for each of the strings in the slice. The data returned will be a // []interface{}. func (v *Value) CollectStr(collector func(int, string) interface{}) *Value { arr := v.MustStrSlice() collected := make([]interface{}, len(arr)) v.EachStr(func(index int, val string) bool { collected[index] = collector(index, val) return true }) return &Value{data: collected} } /* Int (int and []int) -------------------------------------------------- */ // Int gets the value as a int, returns the optionalDefault // value or a system default object if the value is the wrong type. func (v *Value) Int(optionalDefault ...int) int { if s, ok := v.data.(int); ok { return s } if len(optionalDefault) == 1 { return optionalDefault[0] } return 0 } // MustInt gets the value as a int. // // Panics if the object is not a int. func (v *Value) MustInt() int { return v.data.(int) } // IntSlice gets the value as a []int, returns the optionalDefault // value or nil if the value is not a []int. func (v *Value) IntSlice(optionalDefault ...[]int) []int { if s, ok := v.data.([]int); ok { return s } if len(optionalDefault) == 1 { return optionalDefault[0] } return nil } // MustIntSlice gets the value as a []int. // // Panics if the object is not a []int. func (v *Value) MustIntSlice() []int { return v.data.([]int) } // IsInt gets whether the object contained is a int or not. func (v *Value) IsInt() bool { _, ok := v.data.(int) return ok } // IsIntSlice gets whether the object contained is a []int or not. func (v *Value) IsIntSlice() bool { _, ok := v.data.([]int) return ok } // EachInt calls the specified callback for each object // in the []int. // // Panics if the object is the wrong type. func (v *Value) EachInt(callback func(int, int) bool) *Value { for index, val := range v.MustIntSlice() { carryon := callback(index, val) if carryon == false { break } } return v } // WhereInt uses the specified decider function to select items // from the []int. The object contained in the result will contain // only the selected items. func (v *Value) WhereInt(decider func(int, int) bool) *Value { var selected []int v.EachInt(func(index int, val int) bool { shouldSelect := decider(index, val) if shouldSelect == false { selected = append(selected, val) } return true }) return &Value{data: selected} } // GroupInt uses the specified grouper function to group the items // keyed by the return of the grouper. The object contained in the // result will contain a map[string][]int. func (v *Value) GroupInt(grouper func(int, int) string) *Value { groups := make(map[string][]int) v.EachInt(func(index int, val int) bool { group := grouper(index, val) if _, ok := groups[group]; !ok { groups[group] = make([]int, 0) } groups[group] = append(groups[group], val) return true }) return &Value{data: groups} } // ReplaceInt uses the specified function to replace each ints // by iterating each item. The data in the returned result will be a // []int containing the replaced items. func (v *Value) ReplaceInt(replacer func(int, int) int) *Value { arr := v.MustIntSlice() replaced := make([]int, len(arr)) v.EachInt(func(index int, val int) bool { replaced[index] = replacer(index, val) return true }) return &Value{data: replaced} } // CollectInt uses the specified collector function to collect a value // for each of the ints in the slice. The data returned will be a // []interface{}. func (v *Value) CollectInt(collector func(int, int) interface{}) *Value { arr := v.MustIntSlice() collected := make([]interface{}, len(arr)) v.EachInt(func(index int, val int) bool { collected[index] = collector(index, val) return true }) return &Value{data: collected} } /* Int8 (int8 and []int8) -------------------------------------------------- */ // Int8 gets the value as a int8, returns the optionalDefault // value or a system default object if the value is the wrong type. func (v *Value) Int8(optionalDefault ...int8) int8 { if s, ok := v.data.(int8); ok { return s } if len(optionalDefault) == 1 { return optionalDefault[0] } return 0 } // MustInt8 gets the value as a int8. // // Panics if the object is not a int8. func (v *Value) MustInt8() int8 { return v.data.(int8) } // Int8Slice gets the value as a []int8, returns the optionalDefault // value or nil if the value is not a []int8. func (v *Value) Int8Slice(optionalDefault ...[]int8) []int8 { if s, ok := v.data.([]int8); ok { return s } if len(optionalDefault) == 1 { return optionalDefault[0] } return nil } // MustInt8Slice gets the value as a []int8. // // Panics if the object is not a []int8. func (v *Value) MustInt8Slice() []int8 { return v.data.([]int8) } // IsInt8 gets whether the object contained is a int8 or not. func (v *Value) IsInt8() bool { _, ok := v.data.(int8) return ok } // IsInt8Slice gets whether the object contained is a []int8 or not. func (v *Value) IsInt8Slice() bool { _, ok := v.data.([]int8) return ok } // EachInt8 calls the specified callback for each object // in the []int8. // // Panics if the object is the wrong type. func (v *Value) EachInt8(callback func(int, int8) bool) *Value { for index, val := range v.MustInt8Slice() { carryon := callback(index, val) if carryon == false { break } } return v } // WhereInt8 uses the specified decider function to select items // from the []int8. The object contained in the result will contain // only the selected items. func (v *Value) WhereInt8(decider func(int, int8) bool) *Value { var selected []int8 v.EachInt8(func(index int, val int8) bool { shouldSelect := decider(index, val) if shouldSelect == false { selected = append(selected, val) } return true }) return &Value{data: selected} } // GroupInt8 uses the specified grouper function to group the items // keyed by the return of the grouper. The object contained in the // result will contain a map[string][]int8. func (v *Value) GroupInt8(grouper func(int, int8) string) *Value { groups := make(map[string][]int8) v.EachInt8(func(index int, val int8) bool { group := grouper(index, val) if _, ok := groups[group]; !ok { groups[group] = make([]int8, 0) } groups[group] = append(groups[group], val) return true }) return &Value{data: groups} } // ReplaceInt8 uses the specified function to replace each int8s // by iterating each item. The data in the returned result will be a // []int8 containing the replaced items. func (v *Value) ReplaceInt8(replacer func(int, int8) int8) *Value { arr := v.MustInt8Slice() replaced := make([]int8, len(arr)) v.EachInt8(func(index int, val int8) bool { replaced[index] = replacer(index, val) return true }) return &Value{data: replaced} } // CollectInt8 uses the specified collector function to collect a value // for each of the int8s in the slice. The data returned will be a // []interface{}. func (v *Value) CollectInt8(collector func(int, int8) interface{}) *Value { arr := v.MustInt8Slice() collected := make([]interface{}, len(arr)) v.EachInt8(func(index int, val int8) bool { collected[index] = collector(index, val) return true }) return &Value{data: collected} } /* Int16 (int16 and []int16) -------------------------------------------------- */ // Int16 gets the value as a int16, returns the optionalDefault // value or a system default object if the value is the wrong type. func (v *Value) Int16(optionalDefault ...int16) int16 { if s, ok := v.data.(int16); ok { return s } if len(optionalDefault) == 1 { return optionalDefault[0] } return 0 } // MustInt16 gets the value as a int16. // // Panics if the object is not a int16. func (v *Value) MustInt16() int16 { return v.data.(int16) } // Int16Slice gets the value as a []int16, returns the optionalDefault // value or nil if the value is not a []int16. func (v *Value) Int16Slice(optionalDefault ...[]int16) []int16 { if s, ok := v.data.([]int16); ok { return s } if len(optionalDefault) == 1 { return optionalDefault[0] } return nil } // MustInt16Slice gets the value as a []int16. // // Panics if the object is not a []int16. func (v *Value) MustInt16Slice() []int16 { return v.data.([]int16) } // IsInt16 gets whether the object contained is a int16 or not. func (v *Value) IsInt16() bool { _, ok := v.data.(int16) return ok } // IsInt16Slice gets whether the object contained is a []int16 or not. func (v *Value) IsInt16Slice() bool { _, ok := v.data.([]int16) return ok } // EachInt16 calls the specified callback for each object // in the []int16. // // Panics if the object is the wrong type. func (v *Value) EachInt16(callback func(int, int16) bool) *Value { for index, val := range v.MustInt16Slice() { carryon := callback(index, val) if carryon == false { break } } return v } // WhereInt16 uses the specified decider function to select items // from the []int16. The object contained in the result will contain // only the selected items. func (v *Value) WhereInt16(decider func(int, int16) bool) *Value { var selected []int16 v.EachInt16(func(index int, val int16) bool { shouldSelect := decider(index, val) if shouldSelect == false { selected = append(selected, val) } return true }) return &Value{data: selected} } // GroupInt16 uses the specified grouper function to group the items // keyed by the return of the grouper. The object contained in the // result will contain a map[string][]int16. func (v *Value) GroupInt16(grouper func(int, int16) string) *Value { groups := make(map[string][]int16) v.EachInt16(func(index int, val int16) bool { group := grouper(index, val) if _, ok := groups[group]; !ok { groups[group] = make([]int16, 0) } groups[group] = append(groups[group], val) return true }) return &Value{data: groups} } // ReplaceInt16 uses the specified function to replace each int16s // by iterating each item. The data in the returned result will be a // []int16 containing the replaced items. func (v *Value) ReplaceInt16(replacer func(int, int16) int16) *Value { arr := v.MustInt16Slice() replaced := make([]int16, len(arr)) v.EachInt16(func(index int, val int16) bool { replaced[index] = replacer(index, val) return true }) return &Value{data: replaced} } // CollectInt16 uses the specified collector function to collect a value // for each of the int16s in the slice. The data returned will be a // []interface{}. func (v *Value) CollectInt16(collector func(int, int16) interface{}) *Value { arr := v.MustInt16Slice() collected := make([]interface{}, len(arr)) v.EachInt16(func(index int, val int16) bool { collected[index] = collector(index, val) return true }) return &Value{data: collected} } /* Int32 (int32 and []int32) -------------------------------------------------- */ // Int32 gets the value as a int32, returns the optionalDefault // value or a system default object if the value is the wrong type. func (v *Value) Int32(optionalDefault ...int32) int32 { if s, ok := v.data.(int32); ok { return s } if len(optionalDefault) == 1 { return optionalDefault[0] } return 0 } // MustInt32 gets the value as a int32. // // Panics if the object is not a int32. func (v *Value) MustInt32() int32 { return v.data.(int32) } // Int32Slice gets the value as a []int32, returns the optionalDefault // value or nil if the value is not a []int32. func (v *Value) Int32Slice(optionalDefault ...[]int32) []int32 { if s, ok := v.data.([]int32); ok { return s } if len(optionalDefault) == 1 { return optionalDefault[0] } return nil } // MustInt32Slice gets the value as a []int32. // // Panics if the object is not a []int32. func (v *Value) MustInt32Slice() []int32 { return v.data.([]int32) } // IsInt32 gets whether the object contained is a int32 or not. func (v *Value) IsInt32() bool { _, ok := v.data.(int32) return ok } // IsInt32Slice gets whether the object contained is a []int32 or not. func (v *Value) IsInt32Slice() bool { _, ok := v.data.([]int32) return ok } // EachInt32 calls the specified callback for each object // in the []int32. // // Panics if the object is the wrong type. func (v *Value) EachInt32(callback func(int, int32) bool) *Value { for index, val := range v.MustInt32Slice() { carryon := callback(index, val) if carryon == false { break } } return v } // WhereInt32 uses the specified decider function to select items // from the []int32. The object contained in the result will contain // only the selected items. func (v *Value) WhereInt32(decider func(int, int32) bool) *Value { var selected []int32 v.EachInt32(func(index int, val int32) bool { shouldSelect := decider(index, val) if shouldSelect == false { selected = append(selected, val) } return true }) return &Value{data: selected} } // GroupInt32 uses the specified grouper function to group the items // keyed by the return of the grouper. The object contained in the // result will contain a map[string][]int32. func (v *Value) GroupInt32(grouper func(int, int32) string) *Value { groups := make(map[string][]int32) v.EachInt32(func(index int, val int32) bool { group := grouper(index, val) if _, ok := groups[group]; !ok { groups[group] = make([]int32, 0) } groups[group] = append(groups[group], val) return true }) return &Value{data: groups} } // ReplaceInt32 uses the specified function to replace each int32s // by iterating each item. The data in the returned result will be a // []int32 containing the replaced items. func (v *Value) ReplaceInt32(replacer func(int, int32) int32) *Value { arr := v.MustInt32Slice() replaced := make([]int32, len(arr)) v.EachInt32(func(index int, val int32) bool { replaced[index] = replacer(index, val) return true }) return &Value{data: replaced} } // CollectInt32 uses the specified collector function to collect a value // for each of the int32s in the slice. The data returned will be a // []interface{}. func (v *Value) CollectInt32(collector func(int, int32) interface{}) *Value { arr := v.MustInt32Slice() collected := make([]interface{}, len(arr)) v.EachInt32(func(index int, val int32) bool { collected[index] = collector(index, val) return true }) return &Value{data: collected} } /* Int64 (int64 and []int64) -------------------------------------------------- */ // Int64 gets the value as a int64, returns the optionalDefault // value or a system default object if the value is the wrong type. func (v *Value) Int64(optionalDefault ...int64) int64 { if s, ok := v.data.(int64); ok { return s } if len(optionalDefault) == 1 { return optionalDefault[0] } return 0 } // MustInt64 gets the value as a int64. // // Panics if the object is not a int64. func (v *Value) MustInt64() int64 { return v.data.(int64) } // Int64Slice gets the value as a []int64, returns the optionalDefault // value or nil if the value is not a []int64. func (v *Value) Int64Slice(optionalDefault ...[]int64) []int64 { if s, ok := v.data.([]int64); ok { return s } if len(optionalDefault) == 1 { return optionalDefault[0] } return nil } // MustInt64Slice gets the value as a []int64. // // Panics if the object is not a []int64. func (v *Value) MustInt64Slice() []int64 { return v.data.([]int64) } // IsInt64 gets whether the object contained is a int64 or not. func (v *Value) IsInt64() bool { _, ok := v.data.(int64) return ok } // IsInt64Slice gets whether the object contained is a []int64 or not. func (v *Value) IsInt64Slice() bool { _, ok := v.data.([]int64) return ok } // EachInt64 calls the specified callback for each object // in the []int64. // // Panics if the object is the wrong type. func (v *Value) EachInt64(callback func(int, int64) bool) *Value { for index, val := range v.MustInt64Slice() { carryon := callback(index, val) if carryon == false { break } } return v } // WhereInt64 uses the specified decider function to select items // from the []int64. The object contained in the result will contain // only the selected items. func (v *Value) WhereInt64(decider func(int, int64) bool) *Value { var selected []int64 v.EachInt64(func(index int, val int64) bool { shouldSelect := decider(index, val) if shouldSelect == false { selected = append(selected, val) } return true }) return &Value{data: selected} } // GroupInt64 uses the specified grouper function to group the items // keyed by the return of the grouper. The object contained in the // result will contain a map[string][]int64. func (v *Value) GroupInt64(grouper func(int, int64) string) *Value { groups := make(map[string][]int64) v.EachInt64(func(index int, val int64) bool { group := grouper(index, val) if _, ok := groups[group]; !ok { groups[group] = make([]int64, 0) } groups[group] = append(groups[group], val) return true }) return &Value{data: groups} } // ReplaceInt64 uses the specified function to replace each int64s // by iterating each item. The data in the returned result will be a // []int64 containing the replaced items. func (v *Value) ReplaceInt64(replacer func(int, int64) int64) *Value { arr := v.MustInt64Slice() replaced := make([]int64, len(arr)) v.EachInt64(func(index int, val int64) bool { replaced[index] = replacer(index, val) return true }) return &Value{data: replaced} } // CollectInt64 uses the specified collector function to collect a value // for each of the int64s in the slice. The data returned will be a // []interface{}. func (v *Value) CollectInt64(collector func(int, int64) interface{}) *Value { arr := v.MustInt64Slice() collected := make([]interface{}, len(arr)) v.EachInt64(func(index int, val int64) bool { collected[index] = collector(index, val) return true }) return &Value{data: collected} } /* Uint (uint and []uint) -------------------------------------------------- */ // Uint gets the value as a uint, returns the optionalDefault // value or a system default object if the value is the wrong type. func (v *Value) Uint(optionalDefault ...uint) uint { if s, ok := v.data.(uint); ok { return s } if len(optionalDefault) == 1 { return optionalDefault[0] } return 0 } // MustUint gets the value as a uint. // // Panics if the object is not a uint. func (v *Value) MustUint() uint { return v.data.(uint) } // UintSlice gets the value as a []uint, returns the optionalDefault // value or nil if the value is not a []uint. func (v *Value) UintSlice(optionalDefault ...[]uint) []uint { if s, ok := v.data.([]uint); ok { return s } if len(optionalDefault) == 1 { return optionalDefault[0] } return nil } // MustUintSlice gets the value as a []uint. // // Panics if the object is not a []uint. func (v *Value) MustUintSlice() []uint { return v.data.([]uint) } // IsUint gets whether the object contained is a uint or not. func (v *Value) IsUint() bool { _, ok := v.data.(uint) return ok } // IsUintSlice gets whether the object contained is a []uint or not. func (v *Value) IsUintSlice() bool { _, ok := v.data.([]uint) return ok } // EachUint calls the specified callback for each object // in the []uint. // // Panics if the object is the wrong type. func (v *Value) EachUint(callback func(int, uint) bool) *Value { for index, val := range v.MustUintSlice() { carryon := callback(index, val) if carryon == false { break } } return v } // WhereUint uses the specified decider function to select items // from the []uint. The object contained in the result will contain // only the selected items. func (v *Value) WhereUint(decider func(int, uint) bool) *Value { var selected []uint v.EachUint(func(index int, val uint) bool { shouldSelect := decider(index, val) if shouldSelect == false { selected = append(selected, val) } return true }) return &Value{data: selected} } // GroupUint uses the specified grouper function to group the items // keyed by the return of the grouper. The object contained in the // result will contain a map[string][]uint. func (v *Value) GroupUint(grouper func(int, uint) string) *Value { groups := make(map[string][]uint) v.EachUint(func(index int, val uint) bool { group := grouper(index, val) if _, ok := groups[group]; !ok { groups[group] = make([]uint, 0) } groups[group] = append(groups[group], val) return true }) return &Value{data: groups} } // ReplaceUint uses the specified function to replace each uints // by iterating each item. The data in the returned result will be a // []uint containing the replaced items. func (v *Value) ReplaceUint(replacer func(int, uint) uint) *Value { arr := v.MustUintSlice() replaced := make([]uint, len(arr)) v.EachUint(func(index int, val uint) bool { replaced[index] = replacer(index, val) return true }) return &Value{data: replaced} } // CollectUint uses the specified collector function to collect a value // for each of the uints in the slice. The data returned will be a // []interface{}. func (v *Value) CollectUint(collector func(int, uint) interface{}) *Value { arr := v.MustUintSlice() collected := make([]interface{}, len(arr)) v.EachUint(func(index int, val uint) bool { collected[index] = collector(index, val) return true }) return &Value{data: collected} } /* Uint8 (uint8 and []uint8) -------------------------------------------------- */ // Uint8 gets the value as a uint8, returns the optionalDefault // value or a system default object if the value is the wrong type. func (v *Value) Uint8(optionalDefault ...uint8) uint8 { if s, ok := v.data.(uint8); ok { return s } if len(optionalDefault) == 1 { return optionalDefault[0] } return 0 } // MustUint8 gets the value as a uint8. // // Panics if the object is not a uint8. func (v *Value) MustUint8() uint8 { return v.data.(uint8) } // Uint8Slice gets the value as a []uint8, returns the optionalDefault // value or nil if the value is not a []uint8. func (v *Value) Uint8Slice(optionalDefault ...[]uint8) []uint8 { if s, ok := v.data.([]uint8); ok { return s } if len(optionalDefault) == 1 { return optionalDefault[0] } return nil } // MustUint8Slice gets the value as a []uint8. // // Panics if the object is not a []uint8. func (v *Value) MustUint8Slice() []uint8 { return v.data.([]uint8) } // IsUint8 gets whether the object contained is a uint8 or not. func (v *Value) IsUint8() bool { _, ok := v.data.(uint8) return ok } // IsUint8Slice gets whether the object contained is a []uint8 or not. func (v *Value) IsUint8Slice() bool { _, ok := v.data.([]uint8) return ok } // EachUint8 calls the specified callback for each object // in the []uint8. // // Panics if the object is the wrong type. func (v *Value) EachUint8(callback func(int, uint8) bool) *Value { for index, val := range v.MustUint8Slice() { carryon := callback(index, val) if carryon == false { break } } return v } // WhereUint8 uses the specified decider function to select items // from the []uint8. The object contained in the result will contain // only the selected items. func (v *Value) WhereUint8(decider func(int, uint8) bool) *Value { var selected []uint8 v.EachUint8(func(index int, val uint8) bool { shouldSelect := decider(index, val) if shouldSelect == false { selected = append(selected, val) } return true }) return &Value{data: selected} } // GroupUint8 uses the specified grouper function to group the items // keyed by the return of the grouper. The object contained in the // result will contain a map[string][]uint8. func (v *Value) GroupUint8(grouper func(int, uint8) string) *Value { groups := make(map[string][]uint8) v.EachUint8(func(index int, val uint8) bool { group := grouper(index, val) if _, ok := groups[group]; !ok { groups[group] = make([]uint8, 0) } groups[group] = append(groups[group], val) return true }) return &Value{data: groups} } // ReplaceUint8 uses the specified function to replace each uint8s // by iterating each item. The data in the returned result will be a // []uint8 containing the replaced items. func (v *Value) ReplaceUint8(replacer func(int, uint8) uint8) *Value { arr := v.MustUint8Slice() replaced := make([]uint8, len(arr)) v.EachUint8(func(index int, val uint8) bool { replaced[index] = replacer(index, val) return true }) return &Value{data: replaced} } // CollectUint8 uses the specified collector function to collect a value // for each of the uint8s in the slice. The data returned will be a // []interface{}. func (v *Value) CollectUint8(collector func(int, uint8) interface{}) *Value { arr := v.MustUint8Slice() collected := make([]interface{}, len(arr)) v.EachUint8(func(index int, val uint8) bool { collected[index] = collector(index, val) return true }) return &Value{data: collected} } /* Uint16 (uint16 and []uint16) -------------------------------------------------- */ // Uint16 gets the value as a uint16, returns the optionalDefault // value or a system default object if the value is the wrong type. func (v *Value) Uint16(optionalDefault ...uint16) uint16 { if s, ok := v.data.(uint16); ok { return s } if len(optionalDefault) == 1 { return optionalDefault[0] } return 0 } // MustUint16 gets the value as a uint16. // // Panics if the object is not a uint16. func (v *Value) MustUint16() uint16 { return v.data.(uint16) } // Uint16Slice gets the value as a []uint16, returns the optionalDefault // value or nil if the value is not a []uint16. func (v *Value) Uint16Slice(optionalDefault ...[]uint16) []uint16 { if s, ok := v.data.([]uint16); ok { return s } if len(optionalDefault) == 1 { return optionalDefault[0] } return nil } // MustUint16Slice gets the value as a []uint16. // // Panics if the object is not a []uint16. func (v *Value) MustUint16Slice() []uint16 { return v.data.([]uint16) } // IsUint16 gets whether the object contained is a uint16 or not. func (v *Value) IsUint16() bool { _, ok := v.data.(uint16) return ok } // IsUint16Slice gets whether the object contained is a []uint16 or not. func (v *Value) IsUint16Slice() bool { _, ok := v.data.([]uint16) return ok } // EachUint16 calls the specified callback for each object // in the []uint16. // // Panics if the object is the wrong type. func (v *Value) EachUint16(callback func(int, uint16) bool) *Value { for index, val := range v.MustUint16Slice() { carryon := callback(index, val) if carryon == false { break } } return v } // WhereUint16 uses the specified decider function to select items // from the []uint16. The object contained in the result will contain // only the selected items. func (v *Value) WhereUint16(decider func(int, uint16) bool) *Value { var selected []uint16 v.EachUint16(func(index int, val uint16) bool { shouldSelect := decider(index, val) if shouldSelect == false { selected = append(selected, val) } return true }) return &Value{data: selected} } // GroupUint16 uses the specified grouper function to group the items // keyed by the return of the grouper. The object contained in the // result will contain a map[string][]uint16. func (v *Value) GroupUint16(grouper func(int, uint16) string) *Value { groups := make(map[string][]uint16) v.EachUint16(func(index int, val uint16) bool { group := grouper(index, val) if _, ok := groups[group]; !ok { groups[group] = make([]uint16, 0) } groups[group] = append(groups[group], val) return true }) return &Value{data: groups} } // ReplaceUint16 uses the specified function to replace each uint16s // by iterating each item. The data in the returned result will be a // []uint16 containing the replaced items. func (v *Value) ReplaceUint16(replacer func(int, uint16) uint16) *Value { arr := v.MustUint16Slice() replaced := make([]uint16, len(arr)) v.EachUint16(func(index int, val uint16) bool { replaced[index] = replacer(index, val) return true }) return &Value{data: replaced} } // CollectUint16 uses the specified collector function to collect a value // for each of the uint16s in the slice. The data returned will be a // []interface{}. func (v *Value) CollectUint16(collector func(int, uint16) interface{}) *Value { arr := v.MustUint16Slice() collected := make([]interface{}, len(arr)) v.EachUint16(func(index int, val uint16) bool { collected[index] = collector(index, val) return true }) return &Value{data: collected} } /* Uint32 (uint32 and []uint32) -------------------------------------------------- */ // Uint32 gets the value as a uint32, returns the optionalDefault // value or a system default object if the value is the wrong type. func (v *Value) Uint32(optionalDefault ...uint32) uint32 { if s, ok := v.data.(uint32); ok { return s } if len(optionalDefault) == 1 { return optionalDefault[0] } return 0 } // MustUint32 gets the value as a uint32. // // Panics if the object is not a uint32. func (v *Value) MustUint32() uint32 { return v.data.(uint32) } // Uint32Slice gets the value as a []uint32, returns the optionalDefault // value or nil if the value is not a []uint32. func (v *Value) Uint32Slice(optionalDefault ...[]uint32) []uint32 { if s, ok := v.data.([]uint32); ok { return s } if len(optionalDefault) == 1 { return optionalDefault[0] } return nil } // MustUint32Slice gets the value as a []uint32. // // Panics if the object is not a []uint32. func (v *Value) MustUint32Slice() []uint32 { return v.data.([]uint32) } // IsUint32 gets whether the object contained is a uint32 or not. func (v *Value) IsUint32() bool { _, ok := v.data.(uint32) return ok } // IsUint32Slice gets whether the object contained is a []uint32 or not. func (v *Value) IsUint32Slice() bool { _, ok := v.data.([]uint32) return ok } // EachUint32 calls the specified callback for each object // in the []uint32. // // Panics if the object is the wrong type. func (v *Value) EachUint32(callback func(int, uint32) bool) *Value { for index, val := range v.MustUint32Slice() { carryon := callback(index, val) if carryon == false { break } } return v } // WhereUint32 uses the specified decider function to select items // from the []uint32. The object contained in the result will contain // only the selected items. func (v *Value) WhereUint32(decider func(int, uint32) bool) *Value { var selected []uint32 v.EachUint32(func(index int, val uint32) bool { shouldSelect := decider(index, val) if shouldSelect == false { selected = append(selected, val) } return true }) return &Value{data: selected} } // GroupUint32 uses the specified grouper function to group the items // keyed by the return of the grouper. The object contained in the // result will contain a map[string][]uint32. func (v *Value) GroupUint32(grouper func(int, uint32) string) *Value { groups := make(map[string][]uint32) v.EachUint32(func(index int, val uint32) bool { group := grouper(index, val) if _, ok := groups[group]; !ok { groups[group] = make([]uint32, 0) } groups[group] = append(groups[group], val) return true }) return &Value{data: groups} } // ReplaceUint32 uses the specified function to replace each uint32s // by iterating each item. The data in the returned result will be a // []uint32 containing the replaced items. func (v *Value) ReplaceUint32(replacer func(int, uint32) uint32) *Value { arr := v.MustUint32Slice() replaced := make([]uint32, len(arr)) v.EachUint32(func(index int, val uint32) bool { replaced[index] = replacer(index, val) return true }) return &Value{data: replaced} } // CollectUint32 uses the specified collector function to collect a value // for each of the uint32s in the slice. The data returned will be a // []interface{}. func (v *Value) CollectUint32(collector func(int, uint32) interface{}) *Value { arr := v.MustUint32Slice() collected := make([]interface{}, len(arr)) v.EachUint32(func(index int, val uint32) bool { collected[index] = collector(index, val) return true }) return &Value{data: collected} } /* Uint64 (uint64 and []uint64) -------------------------------------------------- */ // Uint64 gets the value as a uint64, returns the optionalDefault // value or a system default object if the value is the wrong type. func (v *Value) Uint64(optionalDefault ...uint64) uint64 { if s, ok := v.data.(uint64); ok { return s } if len(optionalDefault) == 1 { return optionalDefault[0] } return 0 } // MustUint64 gets the value as a uint64. // // Panics if the object is not a uint64. func (v *Value) MustUint64() uint64 { return v.data.(uint64) } // Uint64Slice gets the value as a []uint64, returns the optionalDefault // value or nil if the value is not a []uint64. func (v *Value) Uint64Slice(optionalDefault ...[]uint64) []uint64 { if s, ok := v.data.([]uint64); ok { return s } if len(optionalDefault) == 1 { return optionalDefault[0] } return nil } // MustUint64Slice gets the value as a []uint64. // // Panics if the object is not a []uint64. func (v *Value) MustUint64Slice() []uint64 { return v.data.([]uint64) } // IsUint64 gets whether the object contained is a uint64 or not. func (v *Value) IsUint64() bool { _, ok := v.data.(uint64) return ok } // IsUint64Slice gets whether the object contained is a []uint64 or not. func (v *Value) IsUint64Slice() bool { _, ok := v.data.([]uint64) return ok } // EachUint64 calls the specified callback for each object // in the []uint64. // // Panics if the object is the wrong type. func (v *Value) EachUint64(callback func(int, uint64) bool) *Value { for index, val := range v.MustUint64Slice() { carryon := callback(index, val) if carryon == false { break } } return v } // WhereUint64 uses the specified decider function to select items // from the []uint64. The object contained in the result will contain // only the selected items. func (v *Value) WhereUint64(decider func(int, uint64) bool) *Value { var selected []uint64 v.EachUint64(func(index int, val uint64) bool { shouldSelect := decider(index, val) if shouldSelect == false { selected = append(selected, val) } return true }) return &Value{data: selected} } // GroupUint64 uses the specified grouper function to group the items // keyed by the return of the grouper. The object contained in the // result will contain a map[string][]uint64. func (v *Value) GroupUint64(grouper func(int, uint64) string) *Value { groups := make(map[string][]uint64) v.EachUint64(func(index int, val uint64) bool { group := grouper(index, val) if _, ok := groups[group]; !ok { groups[group] = make([]uint64, 0) } groups[group] = append(groups[group], val) return true }) return &Value{data: groups} } // ReplaceUint64 uses the specified function to replace each uint64s // by iterating each item. The data in the returned result will be a // []uint64 containing the replaced items. func (v *Value) ReplaceUint64(replacer func(int, uint64) uint64) *Value { arr := v.MustUint64Slice() replaced := make([]uint64, len(arr)) v.EachUint64(func(index int, val uint64) bool { replaced[index] = replacer(index, val) return true }) return &Value{data: replaced} } // CollectUint64 uses the specified collector function to collect a value // for each of the uint64s in the slice. The data returned will be a // []interface{}. func (v *Value) CollectUint64(collector func(int, uint64) interface{}) *Value { arr := v.MustUint64Slice() collected := make([]interface{}, len(arr)) v.EachUint64(func(index int, val uint64) bool { collected[index] = collector(index, val) return true }) return &Value{data: collected} } /* Uintptr (uintptr and []uintptr) -------------------------------------------------- */ // Uintptr gets the value as a uintptr, returns the optionalDefault // value or a system default object if the value is the wrong type. func (v *Value) Uintptr(optionalDefault ...uintptr) uintptr { if s, ok := v.data.(uintptr); ok { return s } if len(optionalDefault) == 1 { return optionalDefault[0] } return 0 } // MustUintptr gets the value as a uintptr. // // Panics if the object is not a uintptr. func (v *Value) MustUintptr() uintptr { return v.data.(uintptr) } // UintptrSlice gets the value as a []uintptr, returns the optionalDefault // value or nil if the value is not a []uintptr. func (v *Value) UintptrSlice(optionalDefault ...[]uintptr) []uintptr { if s, ok := v.data.([]uintptr); ok { return s } if len(optionalDefault) == 1 { return optionalDefault[0] } return nil } // MustUintptrSlice gets the value as a []uintptr. // // Panics if the object is not a []uintptr. func (v *Value) MustUintptrSlice() []uintptr { return v.data.([]uintptr) } // IsUintptr gets whether the object contained is a uintptr or not. func (v *Value) IsUintptr() bool { _, ok := v.data.(uintptr) return ok } // IsUintptrSlice gets whether the object contained is a []uintptr or not. func (v *Value) IsUintptrSlice() bool { _, ok := v.data.([]uintptr) return ok } // EachUintptr calls the specified callback for each object // in the []uintptr. // // Panics if the object is the wrong type. func (v *Value) EachUintptr(callback func(int, uintptr) bool) *Value { for index, val := range v.MustUintptrSlice() { carryon := callback(index, val) if carryon == false { break } } return v } // WhereUintptr uses the specified decider function to select items // from the []uintptr. The object contained in the result will contain // only the selected items. func (v *Value) WhereUintptr(decider func(int, uintptr) bool) *Value { var selected []uintptr v.EachUintptr(func(index int, val uintptr) bool { shouldSelect := decider(index, val) if shouldSelect == false { selected = append(selected, val) } return true }) return &Value{data: selected} } // GroupUintptr uses the specified grouper function to group the items // keyed by the return of the grouper. The object contained in the // result will contain a map[string][]uintptr. func (v *Value) GroupUintptr(grouper func(int, uintptr) string) *Value { groups := make(map[string][]uintptr) v.EachUintptr(func(index int, val uintptr) bool { group := grouper(index, val) if _, ok := groups[group]; !ok { groups[group] = make([]uintptr, 0) } groups[group] = append(groups[group], val) return true }) return &Value{data: groups} } // ReplaceUintptr uses the specified function to replace each uintptrs // by iterating each item. The data in the returned result will be a // []uintptr containing the replaced items. func (v *Value) ReplaceUintptr(replacer func(int, uintptr) uintptr) *Value { arr := v.MustUintptrSlice() replaced := make([]uintptr, len(arr)) v.EachUintptr(func(index int, val uintptr) bool { replaced[index] = replacer(index, val) return true }) return &Value{data: replaced} } // CollectUintptr uses the specified collector function to collect a value // for each of the uintptrs in the slice. The data returned will be a // []interface{}. func (v *Value) CollectUintptr(collector func(int, uintptr) interface{}) *Value { arr := v.MustUintptrSlice() collected := make([]interface{}, len(arr)) v.EachUintptr(func(index int, val uintptr) bool { collected[index] = collector(index, val) return true }) return &Value{data: collected} } /* Float32 (float32 and []float32) -------------------------------------------------- */ // Float32 gets the value as a float32, returns the optionalDefault // value or a system default object if the value is the wrong type. func (v *Value) Float32(optionalDefault ...float32) float32 { if s, ok := v.data.(float32); ok { return s } if len(optionalDefault) == 1 { return optionalDefault[0] } return 0 } // MustFloat32 gets the value as a float32. // // Panics if the object is not a float32. func (v *Value) MustFloat32() float32 { return v.data.(float32) } // Float32Slice gets the value as a []float32, returns the optionalDefault // value or nil if the value is not a []float32. func (v *Value) Float32Slice(optionalDefault ...[]float32) []float32 { if s, ok := v.data.([]float32); ok { return s } if len(optionalDefault) == 1 { return optionalDefault[0] } return nil } // MustFloat32Slice gets the value as a []float32. // // Panics if the object is not a []float32. func (v *Value) MustFloat32Slice() []float32 { return v.data.([]float32) } // IsFloat32 gets whether the object contained is a float32 or not. func (v *Value) IsFloat32() bool { _, ok := v.data.(float32) return ok } // IsFloat32Slice gets whether the object contained is a []float32 or not. func (v *Value) IsFloat32Slice() bool { _, ok := v.data.([]float32) return ok } // EachFloat32 calls the specified callback for each object // in the []float32. // // Panics if the object is the wrong type. func (v *Value) EachFloat32(callback func(int, float32) bool) *Value { for index, val := range v.MustFloat32Slice() { carryon := callback(index, val) if carryon == false { break } } return v } // WhereFloat32 uses the specified decider function to select items // from the []float32. The object contained in the result will contain // only the selected items. func (v *Value) WhereFloat32(decider func(int, float32) bool) *Value { var selected []float32 v.EachFloat32(func(index int, val float32) bool { shouldSelect := decider(index, val) if shouldSelect == false { selected = append(selected, val) } return true }) return &Value{data: selected} } // GroupFloat32 uses the specified grouper function to group the items // keyed by the return of the grouper. The object contained in the // result will contain a map[string][]float32. func (v *Value) GroupFloat32(grouper func(int, float32) string) *Value { groups := make(map[string][]float32) v.EachFloat32(func(index int, val float32) bool { group := grouper(index, val) if _, ok := groups[group]; !ok { groups[group] = make([]float32, 0) } groups[group] = append(groups[group], val) return true }) return &Value{data: groups} } // ReplaceFloat32 uses the specified function to replace each float32s // by iterating each item. The data in the returned result will be a // []float32 containing the replaced items. func (v *Value) ReplaceFloat32(replacer func(int, float32) float32) *Value { arr := v.MustFloat32Slice() replaced := make([]float32, len(arr)) v.EachFloat32(func(index int, val float32) bool { replaced[index] = replacer(index, val) return true }) return &Value{data: replaced} } // CollectFloat32 uses the specified collector function to collect a value // for each of the float32s in the slice. The data returned will be a // []interface{}. func (v *Value) CollectFloat32(collector func(int, float32) interface{}) *Value { arr := v.MustFloat32Slice() collected := make([]interface{}, len(arr)) v.EachFloat32(func(index int, val float32) bool { collected[index] = collector(index, val) return true }) return &Value{data: collected} } /* Float64 (float64 and []float64) -------------------------------------------------- */ // Float64 gets the value as a float64, returns the optionalDefault // value or a system default object if the value is the wrong type. func (v *Value) Float64(optionalDefault ...float64) float64 { if s, ok := v.data.(float64); ok { return s } if len(optionalDefault) == 1 { return optionalDefault[0] } return 0 } // MustFloat64 gets the value as a float64. // // Panics if the object is not a float64. func (v *Value) MustFloat64() float64 { return v.data.(float64) } // Float64Slice gets the value as a []float64, returns the optionalDefault // value or nil if the value is not a []float64. func (v *Value) Float64Slice(optionalDefault ...[]float64) []float64 { if s, ok := v.data.([]float64); ok { return s } if len(optionalDefault) == 1 { return optionalDefault[0] } return nil } // MustFloat64Slice gets the value as a []float64. // // Panics if the object is not a []float64. func (v *Value) MustFloat64Slice() []float64 { return v.data.([]float64) } // IsFloat64 gets whether the object contained is a float64 or not. func (v *Value) IsFloat64() bool { _, ok := v.data.(float64) return ok } // IsFloat64Slice gets whether the object contained is a []float64 or not. func (v *Value) IsFloat64Slice() bool { _, ok := v.data.([]float64) return ok } // EachFloat64 calls the specified callback for each object // in the []float64. // // Panics if the object is the wrong type. func (v *Value) EachFloat64(callback func(int, float64) bool) *Value { for index, val := range v.MustFloat64Slice() { carryon := callback(index, val) if carryon == false { break } } return v } // WhereFloat64 uses the specified decider function to select items // from the []float64. The object contained in the result will contain // only the selected items. func (v *Value) WhereFloat64(decider func(int, float64) bool) *Value { var selected []float64 v.EachFloat64(func(index int, val float64) bool { shouldSelect := decider(index, val) if shouldSelect == false { selected = append(selected, val) } return true }) return &Value{data: selected} } // GroupFloat64 uses the specified grouper function to group the items // keyed by the return of the grouper. The object contained in the // result will contain a map[string][]float64. func (v *Value) GroupFloat64(grouper func(int, float64) string) *Value { groups := make(map[string][]float64) v.EachFloat64(func(index int, val float64) bool { group := grouper(index, val) if _, ok := groups[group]; !ok { groups[group] = make([]float64, 0) } groups[group] = append(groups[group], val) return true }) return &Value{data: groups} } // ReplaceFloat64 uses the specified function to replace each float64s // by iterating each item. The data in the returned result will be a // []float64 containing the replaced items. func (v *Value) ReplaceFloat64(replacer func(int, float64) float64) *Value { arr := v.MustFloat64Slice() replaced := make([]float64, len(arr)) v.EachFloat64(func(index int, val float64) bool { replaced[index] = replacer(index, val) return true }) return &Value{data: replaced} } // CollectFloat64 uses the specified collector function to collect a value // for each of the float64s in the slice. The data returned will be a // []interface{}. func (v *Value) CollectFloat64(collector func(int, float64) interface{}) *Value { arr := v.MustFloat64Slice() collected := make([]interface{}, len(arr)) v.EachFloat64(func(index int, val float64) bool { collected[index] = collector(index, val) return true }) return &Value{data: collected} } /* Complex64 (complex64 and []complex64) -------------------------------------------------- */ // Complex64 gets the value as a complex64, returns the optionalDefault // value or a system default object if the value is the wrong type. func (v *Value) Complex64(optionalDefault ...complex64) complex64 { if s, ok := v.data.(complex64); ok { return s } if len(optionalDefault) == 1 { return optionalDefault[0] } return 0 } // MustComplex64 gets the value as a complex64. // // Panics if the object is not a complex64. func (v *Value) MustComplex64() complex64 { return v.data.(complex64) } // Complex64Slice gets the value as a []complex64, returns the optionalDefault // value or nil if the value is not a []complex64. func (v *Value) Complex64Slice(optionalDefault ...[]complex64) []complex64 { if s, ok := v.data.([]complex64); ok { return s } if len(optionalDefault) == 1 { return optionalDefault[0] } return nil } // MustComplex64Slice gets the value as a []complex64. // // Panics if the object is not a []complex64. func (v *Value) MustComplex64Slice() []complex64 { return v.data.([]complex64) } // IsComplex64 gets whether the object contained is a complex64 or not. func (v *Value) IsComplex64() bool { _, ok := v.data.(complex64) return ok } // IsComplex64Slice gets whether the object contained is a []complex64 or not. func (v *Value) IsComplex64Slice() bool { _, ok := v.data.([]complex64) return ok } // EachComplex64 calls the specified callback for each object // in the []complex64. // // Panics if the object is the wrong type. func (v *Value) EachComplex64(callback func(int, complex64) bool) *Value { for index, val := range v.MustComplex64Slice() { carryon := callback(index, val) if carryon == false { break } } return v } // WhereComplex64 uses the specified decider function to select items // from the []complex64. The object contained in the result will contain // only the selected items. func (v *Value) WhereComplex64(decider func(int, complex64) bool) *Value { var selected []complex64 v.EachComplex64(func(index int, val complex64) bool { shouldSelect := decider(index, val) if shouldSelect == false { selected = append(selected, val) } return true }) return &Value{data: selected} } // GroupComplex64 uses the specified grouper function to group the items // keyed by the return of the grouper. The object contained in the // result will contain a map[string][]complex64. func (v *Value) GroupComplex64(grouper func(int, complex64) string) *Value { groups := make(map[string][]complex64) v.EachComplex64(func(index int, val complex64) bool { group := grouper(index, val) if _, ok := groups[group]; !ok { groups[group] = make([]complex64, 0) } groups[group] = append(groups[group], val) return true }) return &Value{data: groups} } // ReplaceComplex64 uses the specified function to replace each complex64s // by iterating each item. The data in the returned result will be a // []complex64 containing the replaced items. func (v *Value) ReplaceComplex64(replacer func(int, complex64) complex64) *Value { arr := v.MustComplex64Slice() replaced := make([]complex64, len(arr)) v.EachComplex64(func(index int, val complex64) bool { replaced[index] = replacer(index, val) return true }) return &Value{data: replaced} } // CollectComplex64 uses the specified collector function to collect a value // for each of the complex64s in the slice. The data returned will be a // []interface{}. func (v *Value) CollectComplex64(collector func(int, complex64) interface{}) *Value { arr := v.MustComplex64Slice() collected := make([]interface{}, len(arr)) v.EachComplex64(func(index int, val complex64) bool { collected[index] = collector(index, val) return true }) return &Value{data: collected} } /* Complex128 (complex128 and []complex128) -------------------------------------------------- */ // Complex128 gets the value as a complex128, returns the optionalDefault // value or a system default object if the value is the wrong type. func (v *Value) Complex128(optionalDefault ...complex128) complex128 { if s, ok := v.data.(complex128); ok { return s } if len(optionalDefault) == 1 { return optionalDefault[0] } return 0 } // MustComplex128 gets the value as a complex128. // // Panics if the object is not a complex128. func (v *Value) MustComplex128() complex128 { return v.data.(complex128) } // Complex128Slice gets the value as a []complex128, returns the optionalDefault // value or nil if the value is not a []complex128. func (v *Value) Complex128Slice(optionalDefault ...[]complex128) []complex128 { if s, ok := v.data.([]complex128); ok { return s } if len(optionalDefault) == 1 { return optionalDefault[0] } return nil } // MustComplex128Slice gets the value as a []complex128. // // Panics if the object is not a []complex128. func (v *Value) MustComplex128Slice() []complex128 { return v.data.([]complex128) } // IsComplex128 gets whether the object contained is a complex128 or not. func (v *Value) IsComplex128() bool { _, ok := v.data.(complex128) return ok } // IsComplex128Slice gets whether the object contained is a []complex128 or not. func (v *Value) IsComplex128Slice() bool { _, ok := v.data.([]complex128) return ok } // EachComplex128 calls the specified callback for each object // in the []complex128. // // Panics if the object is the wrong type. func (v *Value) EachComplex128(callback func(int, complex128) bool) *Value { for index, val := range v.MustComplex128Slice() { carryon := callback(index, val) if carryon == false { break } } return v } // WhereComplex128 uses the specified decider function to select items // from the []complex128. The object contained in the result will contain // only the selected items. func (v *Value) WhereComplex128(decider func(int, complex128) bool) *Value { var selected []complex128 v.EachComplex128(func(index int, val complex128) bool { shouldSelect := decider(index, val) if shouldSelect == false { selected = append(selected, val) } return true }) return &Value{data: selected} } // GroupComplex128 uses the specified grouper function to group the items // keyed by the return of the grouper. The object contained in the // result will contain a map[string][]complex128. func (v *Value) GroupComplex128(grouper func(int, complex128) string) *Value { groups := make(map[string][]complex128) v.EachComplex128(func(index int, val complex128) bool { group := grouper(index, val) if _, ok := groups[group]; !ok { groups[group] = make([]complex128, 0) } groups[group] = append(groups[group], val) return true }) return &Value{data: groups} } // ReplaceComplex128 uses the specified function to replace each complex128s // by iterating each item. The data in the returned result will be a // []complex128 containing the replaced items. func (v *Value) ReplaceComplex128(replacer func(int, complex128) complex128) *Value { arr := v.MustComplex128Slice() replaced := make([]complex128, len(arr)) v.EachComplex128(func(index int, val complex128) bool { replaced[index] = replacer(index, val) return true }) return &Value{data: replaced} } // CollectComplex128 uses the specified collector function to collect a value // for each of the complex128s in the slice. The data returned will be a // []interface{}. func (v *Value) CollectComplex128(collector func(int, complex128) interface{}) *Value { arr := v.MustComplex128Slice() collected := make([]interface{}, len(arr)) v.EachComplex128(func(index int, val complex128) bool { collected[index] = collector(index, val) return true }) return &Value{data: collected} } lxd-2.0.0/dist/src/github.com/stretchr/testify/vendor/github.com/stretchr/objx/accessors.go0000644061062106075000000001034112702772371034503 0ustar00stgraberdomain admins00000000000000package objx import ( "fmt" "regexp" "strconv" "strings" ) // arrayAccesRegexString is the regex used to extract the array number // from the access path const arrayAccesRegexString = `^(.+)\[([0-9]+)\]$` // arrayAccesRegex is the compiled arrayAccesRegexString var arrayAccesRegex = regexp.MustCompile(arrayAccesRegexString) // Get gets the value using the specified selector and // returns it inside a new Obj object. // // If it cannot find the value, Get will return a nil // value inside an instance of Obj. // // Get can only operate directly on map[string]interface{} and []interface. // // Example // // To access the title of the third chapter of the second book, do: // // o.Get("books[1].chapters[2].title") func (m Map) Get(selector string) *Value { rawObj := access(m, selector, nil, false, false) return &Value{data: rawObj} } // Set sets the value using the specified selector and // returns the object on which Set was called. // // Set can only operate directly on map[string]interface{} and []interface // // Example // // To set the title of the third chapter of the second book, do: // // o.Set("books[1].chapters[2].title","Time to Go") func (m Map) Set(selector string, value interface{}) Map { access(m, selector, value, true, false) return m } // access accesses the object using the selector and performs the // appropriate action. func access(current, selector, value interface{}, isSet, panics bool) interface{} { switch selector.(type) { case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64: if array, ok := current.([]interface{}); ok { index := intFromInterface(selector) if index >= len(array) { if panics { panic(fmt.Sprintf("objx: Index %d is out of range. Slice only contains %d items.", index, len(array))) } return nil } return array[index] } return nil case string: selStr := selector.(string) selSegs := strings.SplitN(selStr, PathSeparator, 2) thisSel := selSegs[0] index := -1 var err error // https://github.com/stretchr/objx/issues/12 if strings.Contains(thisSel, "[") { arrayMatches := arrayAccesRegex.FindStringSubmatch(thisSel) if len(arrayMatches) > 0 { // Get the key into the map thisSel = arrayMatches[1] // Get the index into the array at the key index, err = strconv.Atoi(arrayMatches[2]) if err != nil { // This should never happen. If it does, something has gone // seriously wrong. Panic. panic("objx: Array index is not an integer. Must use array[int].") } } } if curMap, ok := current.(Map); ok { current = map[string]interface{}(curMap) } // get the object in question switch current.(type) { case map[string]interface{}: curMSI := current.(map[string]interface{}) if len(selSegs) <= 1 && isSet { curMSI[thisSel] = value return nil } else { current = curMSI[thisSel] } default: current = nil } if current == nil && panics { panic(fmt.Sprintf("objx: '%v' invalid on object.", selector)) } // do we need to access the item of an array? if index > -1 { if array, ok := current.([]interface{}); ok { if index < len(array) { current = array[index] } else { if panics { panic(fmt.Sprintf("objx: Index %d is out of range. Slice only contains %d items.", index, len(array))) } current = nil } } } if len(selSegs) > 1 { current = access(current, selSegs[1], value, isSet, panics) } } return current } // intFromInterface converts an interface object to the largest // representation of an unsigned integer using a type switch and // assertions func intFromInterface(selector interface{}) int { var value int switch selector.(type) { case int: value = selector.(int) case int8: value = int(selector.(int8)) case int16: value = int(selector.(int16)) case int32: value = int(selector.(int32)) case int64: value = int(selector.(int64)) case uint: value = int(selector.(uint)) case uint8: value = int(selector.(uint8)) case uint16: value = int(selector.(uint16)) case uint32: value = int(selector.(uint32)) case uint64: value = int(selector.(uint64)) default: panic("objx: array access argument is not an integer type (this should never happen)") } return value } lxd-2.0.0/dist/src/github.com/stretchr/testify/vendor/github.com/stretchr/objx/LICENSE.md0000644061062106075000000000213712702772371033577 0ustar00stgraberdomain admins00000000000000objx - by Mat Ryer and Tyler Bunnell The MIT License (MIT) Copyright (c) 2014 Stretchr, Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. lxd-2.0.0/dist/src/github.com/stretchr/testify/vendor/github.com/stretchr/objx/mutations.go0000644061062106075000000000407312702772371034546 0ustar00stgraberdomain admins00000000000000package objx // Exclude returns a new Map with the keys in the specified []string // excluded. func (d Map) Exclude(exclude []string) Map { excluded := make(Map) for k, v := range d { var shouldInclude bool = true for _, toExclude := range exclude { if k == toExclude { shouldInclude = false break } } if shouldInclude { excluded[k] = v } } return excluded } // Copy creates a shallow copy of the Obj. func (m Map) Copy() Map { copied := make(map[string]interface{}) for k, v := range m { copied[k] = v } return New(copied) } // Merge blends the specified map with a copy of this map and returns the result. // // Keys that appear in both will be selected from the specified map. // This method requires that the wrapped object be a map[string]interface{} func (m Map) Merge(merge Map) Map { return m.Copy().MergeHere(merge) } // Merge blends the specified map with this map and returns the current map. // // Keys that appear in both will be selected from the specified map. The original map // will be modified. This method requires that // the wrapped object be a map[string]interface{} func (m Map) MergeHere(merge Map) Map { for k, v := range merge { m[k] = v } return m } // Transform builds a new Obj giving the transformer a chance // to change the keys and values as it goes. This method requires that // the wrapped object be a map[string]interface{} func (m Map) Transform(transformer func(key string, value interface{}) (string, interface{})) Map { newMap := make(map[string]interface{}) for k, v := range m { modifiedKey, modifiedVal := transformer(k, v) newMap[modifiedKey] = modifiedVal } return New(newMap) } // TransformKeys builds a new map using the specified key mapping. // // Unspecified keys will be unaltered. // This method requires that the wrapped object be a map[string]interface{} func (m Map) TransformKeys(mapping map[string]string) Map { return m.Transform(func(key string, value interface{}) (string, interface{}) { if newKey, ok := mapping[key]; ok { return newKey, value } return key, value }) } lxd-2.0.0/dist/src/github.com/stretchr/testify/vendor/github.com/stretchr/objx/doc.go0000644061062106075000000000444312702772371033271 0ustar00stgraberdomain admins00000000000000// objx - Go package for dealing with maps, slices, JSON and other data. // // Overview // // Objx provides the `objx.Map` type, which is a `map[string]interface{}` that exposes // a powerful `Get` method (among others) that allows you to easily and quickly get // access to data within the map, without having to worry too much about type assertions, // missing data, default values etc. // // Pattern // // Objx uses a preditable pattern to make access data from within `map[string]interface{}'s // easy. // // Call one of the `objx.` functions to create your `objx.Map` to get going: // // m, err := objx.FromJSON(json) // // NOTE: Any methods or functions with the `Must` prefix will panic if something goes wrong, // the rest will be optimistic and try to figure things out without panicking. // // Use `Get` to access the value you're interested in. You can use dot and array // notation too: // // m.Get("places[0].latlng") // // Once you have saught the `Value` you're interested in, you can use the `Is*` methods // to determine its type. // // if m.Get("code").IsStr() { /* ... */ } // // Or you can just assume the type, and use one of the strong type methods to // extract the real value: // // m.Get("code").Int() // // If there's no value there (or if it's the wrong type) then a default value // will be returned, or you can be explicit about the default value. // // Get("code").Int(-1) // // If you're dealing with a slice of data as a value, Objx provides many useful // methods for iterating, manipulating and selecting that data. You can find out more // by exploring the index below. // // Reading data // // A simple example of how to use Objx: // // // use MustFromJSON to make an objx.Map from some JSON // m := objx.MustFromJSON(`{"name": "Mat", "age": 30}`) // // // get the details // name := m.Get("name").Str() // age := m.Get("age").Int() // // // get their nickname (or use their name if they // // don't have one) // nickname := m.Get("nickname").Str(name) // // Ranging // // Since `objx.Map` is a `map[string]interface{}` you can treat it as such. For // example, to `range` the data, do what you would expect: // // m := objx.MustFromJSON(json) // for key, value := range m { // // /* ... do your magic ... */ // // } package objx lxd-2.0.0/dist/src/github.com/stretchr/testify/vendor/github.com/stretchr/objx/codegen/0000755061062106075000000000000012702772371033574 5ustar00stgraberdomain admins00000000000000lxd-2.0.0/dist/src/github.com/stretchr/testify/vendor/github.com/stretchr/objx/codegen/template.txt0000644061062106075000000001536212702772371036157 0ustar00stgraberdomain admins00000000000000/* {4} ({1} and []{1}) -------------------------------------------------- */ // {4} gets the value as a {1}, returns the optionalDefault // value or a system default object if the value is the wrong type. func (v *Value) {4}(optionalDefault ...{1}) {1} { if s, ok := v.data.({1}); ok { return s } if len(optionalDefault) == 1 { return optionalDefault[0] } return {3} } // Must{4} gets the value as a {1}. // // Panics if the object is not a {1}. func (v *Value) Must{4}() {1} { return v.data.({1}) } // {4}Slice gets the value as a []{1}, returns the optionalDefault // value or nil if the value is not a []{1}. func (v *Value) {4}Slice(optionalDefault ...[]{1}) []{1} { if s, ok := v.data.([]{1}); ok { return s } if len(optionalDefault) == 1 { return optionalDefault[0] } return nil } // Must{4}Slice gets the value as a []{1}. // // Panics if the object is not a []{1}. func (v *Value) Must{4}Slice() []{1} { return v.data.([]{1}) } // Is{4} gets whether the object contained is a {1} or not. func (v *Value) Is{4}() bool { _, ok := v.data.({1}) return ok } // Is{4}Slice gets whether the object contained is a []{1} or not. func (v *Value) Is{4}Slice() bool { _, ok := v.data.([]{1}) return ok } // Each{4} calls the specified callback for each object // in the []{1}. // // Panics if the object is the wrong type. func (v *Value) Each{4}(callback func(int, {1}) bool) *Value { for index, val := range v.Must{4}Slice() { carryon := callback(index, val) if carryon == false { break } } return v } // Where{4} uses the specified decider function to select items // from the []{1}. The object contained in the result will contain // only the selected items. func (v *Value) Where{4}(decider func(int, {1}) bool) *Value { var selected []{1} v.Each{4}(func(index int, val {1}) bool { shouldSelect := decider(index, val) if shouldSelect == false { selected = append(selected, val) } return true }) return &Value{data:selected} } // Group{4} uses the specified grouper function to group the items // keyed by the return of the grouper. The object contained in the // result will contain a map[string][]{1}. func (v *Value) Group{4}(grouper func(int, {1}) string) *Value { groups := make(map[string][]{1}) v.Each{4}(func(index int, val {1}) bool { group := grouper(index, val) if _, ok := groups[group]; !ok { groups[group] = make([]{1}, 0) } groups[group] = append(groups[group], val) return true }) return &Value{data:groups} } // Replace{4} uses the specified function to replace each {1}s // by iterating each item. The data in the returned result will be a // []{1} containing the replaced items. func (v *Value) Replace{4}(replacer func(int, {1}) {1}) *Value { arr := v.Must{4}Slice() replaced := make([]{1}, len(arr)) v.Each{4}(func(index int, val {1}) bool { replaced[index] = replacer(index, val) return true }) return &Value{data:replaced} } // Collect{4} uses the specified collector function to collect a value // for each of the {1}s in the slice. The data returned will be a // []interface{}. func (v *Value) Collect{4}(collector func(int, {1}) interface{}) *Value { arr := v.Must{4}Slice() collected := make([]interface{}, len(arr)) v.Each{4}(func(index int, val {1}) bool { collected[index] = collector(index, val) return true }) return &Value{data:collected} } // ************************************************************ // TESTS // ************************************************************ func Test{4}(t *testing.T) { val := {1}( {2} ) m := map[string]interface{}{"value": val, "nothing": nil} assert.Equal(t, val, New(m).Get("value").{4}()) assert.Equal(t, val, New(m).Get("value").Must{4}()) assert.Equal(t, {1}({3}), New(m).Get("nothing").{4}()) assert.Equal(t, val, New(m).Get("nothing").{4}({2})) assert.Panics(t, func() { New(m).Get("age").Must{4}() }) } func Test{4}Slice(t *testing.T) { val := {1}( {2} ) m := map[string]interface{}{"value": []{1}{ val }, "nothing": nil} assert.Equal(t, val, New(m).Get("value").{4}Slice()[0]) assert.Equal(t, val, New(m).Get("value").Must{4}Slice()[0]) assert.Equal(t, []{1}(nil), New(m).Get("nothing").{4}Slice()) assert.Equal(t, val, New(m).Get("nothing").{4}Slice( []{1}{ {1}({2}) } )[0]) assert.Panics(t, func() { New(m).Get("nothing").Must{4}Slice() }) } func TestIs{4}(t *testing.T) { var v *Value v = &Value{data: {1}({2})} assert.True(t, v.Is{4}()) v = &Value{data: []{1}{ {1}({2}) }} assert.True(t, v.Is{4}Slice()) } func TestEach{4}(t *testing.T) { v := &Value{data: []{1}{ {1}({2}), {1}({2}), {1}({2}), {1}({2}), {1}({2}) }} count := 0 replacedVals := make([]{1}, 0) assert.Equal(t, v, v.Each{4}(func(i int, val {1}) bool { count++ replacedVals = append(replacedVals, val) // abort early if i == 2 { return false } return true })) assert.Equal(t, count, 3) assert.Equal(t, replacedVals[0], v.Must{4}Slice()[0]) assert.Equal(t, replacedVals[1], v.Must{4}Slice()[1]) assert.Equal(t, replacedVals[2], v.Must{4}Slice()[2]) } func TestWhere{4}(t *testing.T) { v := &Value{data: []{1}{ {1}({2}), {1}({2}), {1}({2}), {1}({2}), {1}({2}), {1}({2}) }} selected := v.Where{4}(func(i int, val {1}) bool { return i%2==0 }).Must{4}Slice() assert.Equal(t, 3, len(selected)) } func TestGroup{4}(t *testing.T) { v := &Value{data: []{1}{ {1}({2}), {1}({2}), {1}({2}), {1}({2}), {1}({2}), {1}({2}) }} grouped := v.Group{4}(func(i int, val {1}) string { return fmt.Sprintf("%v", i%2==0) }).data.(map[string][]{1}) assert.Equal(t, 2, len(grouped)) assert.Equal(t, 3, len(grouped["true"])) assert.Equal(t, 3, len(grouped["false"])) } func TestReplace{4}(t *testing.T) { v := &Value{data: []{1}{ {1}({2}), {1}({2}), {1}({2}), {1}({2}), {1}({2}), {1}({2}) }} rawArr := v.Must{4}Slice() replaced := v.Replace{4}(func(index int, val {1}) {1} { if index < len(rawArr)-1 { return rawArr[index+1] } return rawArr[0] }) replacedArr := replaced.Must{4}Slice() if assert.Equal(t, 6, len(replacedArr)) { assert.Equal(t, replacedArr[0], rawArr[1]) assert.Equal(t, replacedArr[1], rawArr[2]) assert.Equal(t, replacedArr[2], rawArr[3]) assert.Equal(t, replacedArr[3], rawArr[4]) assert.Equal(t, replacedArr[4], rawArr[5]) assert.Equal(t, replacedArr[5], rawArr[0]) } } func TestCollect{4}(t *testing.T) { v := &Value{data: []{1}{ {1}({2}), {1}({2}), {1}({2}), {1}({2}), {1}({2}), {1}({2}) }} collected := v.Collect{4}(func(index int, val {1}) interface{} { return index }) collectedArr := collected.MustInterSlice() if assert.Equal(t, 6, len(collectedArr)) { assert.Equal(t, collectedArr[0], 0) assert.Equal(t, collectedArr[1], 1) assert.Equal(t, collectedArr[2], 2) assert.Equal(t, collectedArr[3], 3) assert.Equal(t, collectedArr[4], 4) assert.Equal(t, collectedArr[5], 5) } } types_list.txt0000644061062106075000000000110712702772371036454 0ustar00stgraberdomain admins00000000000000lxd-2.0.0/dist/src/github.com/stretchr/testify/vendor/github.com/stretchr/objx/codegenInterface,interface{},"something",nil,Inter Map,map[string]interface{},map[string]interface{}{"name":"Tyler"},nil,MSI ObjxMap,(Map),New(1),New(nil),ObjxMap Bool,bool,true,false,Bool String,string,"hello","",Str Int,int,1,0,Int Int8,int8,1,0,Int8 Int16,int16,1,0,Int16 Int32,int32,1,0,Int32 Int64,int64,1,0,Int64 Uint,uint,1,0,Uint Uint8,uint8,1,0,Uint8 Uint16,uint16,1,0,Uint16 Uint32,uint32,1,0,Uint32 Uint64,uint64,1,0,Uint64 Uintptr,uintptr,1,0,Uintptr Float32,float32,1,0,Float32 Float64,float64,1,0,Float64 Complex64,complex64,1,0,Complex64 Complex128,complex128,1,0,Complex128 array-access.txt0000644061062106075000000000053012702772371036631 0ustar00stgraberdomain admins00000000000000lxd-2.0.0/dist/src/github.com/stretchr/testify/vendor/github.com/stretchr/objx/codegen case []{1}: a := object.([]{1}) if isSet { a[index] = value.({1}) } else { if index >= len(a) { if panics { panic(fmt.Sprintf("objx: Index %d is out of range because the []{1} only contains %d items.", index, len(a))) } return nil } else { return a[index] } } lxd-2.0.0/dist/src/github.com/stretchr/testify/vendor/github.com/stretchr/objx/codegen/index.html0000644061062106075000000000261412702772371035574 0ustar00stgraberdomain admins00000000000000 Codegen

Template

Use {x} as a placeholder for each argument.

Arguments (comma separated)

One block per line

Output

lxd-2.0.0/dist/src/github.com/stretchr/testify/vendor/github.com/pmezard/0000755061062106075000000000000012702772371031032 5ustar00stgraberdomain admins00000000000000lxd-2.0.0/dist/src/github.com/stretchr/testify/vendor/github.com/pmezard/go-difflib/0000755061062106075000000000000012702772371033034 5ustar00stgraberdomain admins00000000000000lxd-2.0.0/dist/src/github.com/stretchr/testify/vendor/github.com/pmezard/go-difflib/difflib/0000755061062106075000000000000012702772371034433 5ustar00stgraberdomain admins00000000000000difflib.go0000644061062106075000000005403212702772371036306 0ustar00stgraberdomain admins00000000000000lxd-2.0.0/dist/src/github.com/stretchr/testify/vendor/github.com/pmezard/go-difflib/difflib// Package difflib is a partial port of Python difflib module. // // It provides tools to compare sequences of strings and generate textual diffs. // // The following class and functions have been ported: // // - SequenceMatcher // // - unified_diff // // - context_diff // // Getting unified diffs was the main goal of the port. Keep in mind this code // is mostly suitable to output text differences in a human friendly way, there // are no guarantees generated diffs are consumable by patch(1). package difflib import ( "bufio" "bytes" "fmt" "io" "strings" ) func min(a, b int) int { if a < b { return a } return b } func max(a, b int) int { if a > b { return a } return b } func calculateRatio(matches, length int) float64 { if length > 0 { return 2.0 * float64(matches) / float64(length) } return 1.0 } type Match struct { A int B int Size int } type OpCode struct { Tag byte I1 int I2 int J1 int J2 int } // SequenceMatcher compares sequence of strings. The basic // algorithm predates, and is a little fancier than, an algorithm // published in the late 1980's by Ratcliff and Obershelp under the // hyperbolic name "gestalt pattern matching". The basic idea is to find // the longest contiguous matching subsequence that contains no "junk" // elements (R-O doesn't address junk). The same idea is then applied // recursively to the pieces of the sequences to the left and to the right // of the matching subsequence. This does not yield minimal edit // sequences, but does tend to yield matches that "look right" to people. // // SequenceMatcher tries to compute a "human-friendly diff" between two // sequences. Unlike e.g. UNIX(tm) diff, the fundamental notion is the // longest *contiguous* & junk-free matching subsequence. That's what // catches peoples' eyes. The Windows(tm) windiff has another interesting // notion, pairing up elements that appear uniquely in each sequence. // That, and the method here, appear to yield more intuitive difference // reports than does diff. This method appears to be the least vulnerable // to synching up on blocks of "junk lines", though (like blank lines in // ordinary text files, or maybe "

" lines in HTML files). That may be // because this is the only method of the 3 that has a *concept* of // "junk" . // // Timing: Basic R-O is cubic time worst case and quadratic time expected // case. SequenceMatcher is quadratic time for the worst case and has // expected-case behavior dependent in a complicated way on how many // elements the sequences have in common; best case time is linear. type SequenceMatcher struct { a []string b []string b2j map[string][]int IsJunk func(string) bool autoJunk bool bJunk map[string]struct{} matchingBlocks []Match fullBCount map[string]int bPopular map[string]struct{} opCodes []OpCode } func NewMatcher(a, b []string) *SequenceMatcher { m := SequenceMatcher{autoJunk: true} m.SetSeqs(a, b) return &m } func NewMatcherWithJunk(a, b []string, autoJunk bool, isJunk func(string) bool) *SequenceMatcher { m := SequenceMatcher{IsJunk: isJunk, autoJunk: autoJunk} m.SetSeqs(a, b) return &m } // Set two sequences to be compared. func (m *SequenceMatcher) SetSeqs(a, b []string) { m.SetSeq1(a) m.SetSeq2(b) } // Set the first sequence to be compared. The second sequence to be compared is // not changed. // // SequenceMatcher computes and caches detailed information about the second // sequence, so if you want to compare one sequence S against many sequences, // use .SetSeq2(s) once and call .SetSeq1(x) repeatedly for each of the other // sequences. // // See also SetSeqs() and SetSeq2(). func (m *SequenceMatcher) SetSeq1(a []string) { if &a == &m.a { return } m.a = a m.matchingBlocks = nil m.opCodes = nil } // Set the second sequence to be compared. The first sequence to be compared is // not changed. func (m *SequenceMatcher) SetSeq2(b []string) { if &b == &m.b { return } m.b = b m.matchingBlocks = nil m.opCodes = nil m.fullBCount = nil m.chainB() } func (m *SequenceMatcher) chainB() { // Populate line -> index mapping b2j := map[string][]int{} for i, s := range m.b { indices := b2j[s] indices = append(indices, i) b2j[s] = indices } // Purge junk elements m.bJunk = map[string]struct{}{} if m.IsJunk != nil { junk := m.bJunk for s, _ := range b2j { if m.IsJunk(s) { junk[s] = struct{}{} } } for s, _ := range junk { delete(b2j, s) } } // Purge remaining popular elements popular := map[string]struct{}{} n := len(m.b) if m.autoJunk && n >= 200 { ntest := n/100 + 1 for s, indices := range b2j { if len(indices) > ntest { popular[s] = struct{}{} } } for s, _ := range popular { delete(b2j, s) } } m.bPopular = popular m.b2j = b2j } func (m *SequenceMatcher) isBJunk(s string) bool { _, ok := m.bJunk[s] return ok } // Find longest matching block in a[alo:ahi] and b[blo:bhi]. // // If IsJunk is not defined: // // Return (i,j,k) such that a[i:i+k] is equal to b[j:j+k], where // alo <= i <= i+k <= ahi // blo <= j <= j+k <= bhi // and for all (i',j',k') meeting those conditions, // k >= k' // i <= i' // and if i == i', j <= j' // // In other words, of all maximal matching blocks, return one that // starts earliest in a, and of all those maximal matching blocks that // start earliest in a, return the one that starts earliest in b. // // If IsJunk is defined, first the longest matching block is // determined as above, but with the additional restriction that no // junk element appears in the block. Then that block is extended as // far as possible by matching (only) junk elements on both sides. So // the resulting block never matches on junk except as identical junk // happens to be adjacent to an "interesting" match. // // If no blocks match, return (alo, blo, 0). func (m *SequenceMatcher) findLongestMatch(alo, ahi, blo, bhi int) Match { // CAUTION: stripping common prefix or suffix would be incorrect. // E.g., // ab // acab // Longest matching block is "ab", but if common prefix is // stripped, it's "a" (tied with "b"). UNIX(tm) diff does so // strip, so ends up claiming that ab is changed to acab by // inserting "ca" in the middle. That's minimal but unintuitive: // "it's obvious" that someone inserted "ac" at the front. // Windiff ends up at the same place as diff, but by pairing up // the unique 'b's and then matching the first two 'a's. besti, bestj, bestsize := alo, blo, 0 // find longest junk-free match // during an iteration of the loop, j2len[j] = length of longest // junk-free match ending with a[i-1] and b[j] j2len := map[int]int{} for i := alo; i != ahi; i++ { // look at all instances of a[i] in b; note that because // b2j has no junk keys, the loop is skipped if a[i] is junk newj2len := map[int]int{} for _, j := range m.b2j[m.a[i]] { // a[i] matches b[j] if j < blo { continue } if j >= bhi { break } k := j2len[j-1] + 1 newj2len[j] = k if k > bestsize { besti, bestj, bestsize = i-k+1, j-k+1, k } } j2len = newj2len } // Extend the best by non-junk elements on each end. In particular, // "popular" non-junk elements aren't in b2j, which greatly speeds // the inner loop above, but also means "the best" match so far // doesn't contain any junk *or* popular non-junk elements. for besti > alo && bestj > blo && !m.isBJunk(m.b[bestj-1]) && m.a[besti-1] == m.b[bestj-1] { besti, bestj, bestsize = besti-1, bestj-1, bestsize+1 } for besti+bestsize < ahi && bestj+bestsize < bhi && !m.isBJunk(m.b[bestj+bestsize]) && m.a[besti+bestsize] == m.b[bestj+bestsize] { bestsize += 1 } // Now that we have a wholly interesting match (albeit possibly // empty!), we may as well suck up the matching junk on each // side of it too. Can't think of a good reason not to, and it // saves post-processing the (possibly considerable) expense of // figuring out what to do with it. In the case of an empty // interesting match, this is clearly the right thing to do, // because no other kind of match is possible in the regions. for besti > alo && bestj > blo && m.isBJunk(m.b[bestj-1]) && m.a[besti-1] == m.b[bestj-1] { besti, bestj, bestsize = besti-1, bestj-1, bestsize+1 } for besti+bestsize < ahi && bestj+bestsize < bhi && m.isBJunk(m.b[bestj+bestsize]) && m.a[besti+bestsize] == m.b[bestj+bestsize] { bestsize += 1 } return Match{A: besti, B: bestj, Size: bestsize} } // Return list of triples describing matching subsequences. // // Each triple is of the form (i, j, n), and means that // a[i:i+n] == b[j:j+n]. The triples are monotonically increasing in // i and in j. It's also guaranteed that if (i, j, n) and (i', j', n') are // adjacent triples in the list, and the second is not the last triple in the // list, then i+n != i' or j+n != j'. IOW, adjacent triples never describe // adjacent equal blocks. // // The last triple is a dummy, (len(a), len(b), 0), and is the only // triple with n==0. func (m *SequenceMatcher) GetMatchingBlocks() []Match { if m.matchingBlocks != nil { return m.matchingBlocks } var matchBlocks func(alo, ahi, blo, bhi int, matched []Match) []Match matchBlocks = func(alo, ahi, blo, bhi int, matched []Match) []Match { match := m.findLongestMatch(alo, ahi, blo, bhi) i, j, k := match.A, match.B, match.Size if match.Size > 0 { if alo < i && blo < j { matched = matchBlocks(alo, i, blo, j, matched) } matched = append(matched, match) if i+k < ahi && j+k < bhi { matched = matchBlocks(i+k, ahi, j+k, bhi, matched) } } return matched } matched := matchBlocks(0, len(m.a), 0, len(m.b), nil) // It's possible that we have adjacent equal blocks in the // matching_blocks list now. nonAdjacent := []Match{} i1, j1, k1 := 0, 0, 0 for _, b := range matched { // Is this block adjacent to i1, j1, k1? i2, j2, k2 := b.A, b.B, b.Size if i1+k1 == i2 && j1+k1 == j2 { // Yes, so collapse them -- this just increases the length of // the first block by the length of the second, and the first // block so lengthened remains the block to compare against. k1 += k2 } else { // Not adjacent. Remember the first block (k1==0 means it's // the dummy we started with), and make the second block the // new block to compare against. if k1 > 0 { nonAdjacent = append(nonAdjacent, Match{i1, j1, k1}) } i1, j1, k1 = i2, j2, k2 } } if k1 > 0 { nonAdjacent = append(nonAdjacent, Match{i1, j1, k1}) } nonAdjacent = append(nonAdjacent, Match{len(m.a), len(m.b), 0}) m.matchingBlocks = nonAdjacent return m.matchingBlocks } // Return list of 5-tuples describing how to turn a into b. // // Each tuple is of the form (tag, i1, i2, j1, j2). The first tuple // has i1 == j1 == 0, and remaining tuples have i1 == the i2 from the // tuple preceding it, and likewise for j1 == the previous j2. // // The tags are characters, with these meanings: // // 'r' (replace): a[i1:i2] should be replaced by b[j1:j2] // // 'd' (delete): a[i1:i2] should be deleted, j1==j2 in this case. // // 'i' (insert): b[j1:j2] should be inserted at a[i1:i1], i1==i2 in this case. // // 'e' (equal): a[i1:i2] == b[j1:j2] func (m *SequenceMatcher) GetOpCodes() []OpCode { if m.opCodes != nil { return m.opCodes } i, j := 0, 0 matching := m.GetMatchingBlocks() opCodes := make([]OpCode, 0, len(matching)) for _, m := range matching { // invariant: we've pumped out correct diffs to change // a[:i] into b[:j], and the next matching block is // a[ai:ai+size] == b[bj:bj+size]. So we need to pump // out a diff to change a[i:ai] into b[j:bj], pump out // the matching block, and move (i,j) beyond the match ai, bj, size := m.A, m.B, m.Size tag := byte(0) if i < ai && j < bj { tag = 'r' } else if i < ai { tag = 'd' } else if j < bj { tag = 'i' } if tag > 0 { opCodes = append(opCodes, OpCode{tag, i, ai, j, bj}) } i, j = ai+size, bj+size // the list of matching blocks is terminated by a // sentinel with size 0 if size > 0 { opCodes = append(opCodes, OpCode{'e', ai, i, bj, j}) } } m.opCodes = opCodes return m.opCodes } // Isolate change clusters by eliminating ranges with no changes. // // Return a generator of groups with up to n lines of context. // Each group is in the same format as returned by GetOpCodes(). func (m *SequenceMatcher) GetGroupedOpCodes(n int) [][]OpCode { if n < 0 { n = 3 } codes := m.GetOpCodes() if len(codes) == 0 { codes = []OpCode{OpCode{'e', 0, 1, 0, 1}} } // Fixup leading and trailing groups if they show no changes. if codes[0].Tag == 'e' { c := codes[0] i1, i2, j1, j2 := c.I1, c.I2, c.J1, c.J2 codes[0] = OpCode{c.Tag, max(i1, i2-n), i2, max(j1, j2-n), j2} } if codes[len(codes)-1].Tag == 'e' { c := codes[len(codes)-1] i1, i2, j1, j2 := c.I1, c.I2, c.J1, c.J2 codes[len(codes)-1] = OpCode{c.Tag, i1, min(i2, i1+n), j1, min(j2, j1+n)} } nn := n + n groups := [][]OpCode{} group := []OpCode{} for _, c := range codes { i1, i2, j1, j2 := c.I1, c.I2, c.J1, c.J2 // End the current group and start a new one whenever // there is a large range with no changes. if c.Tag == 'e' && i2-i1 > nn { group = append(group, OpCode{c.Tag, i1, min(i2, i1+n), j1, min(j2, j1+n)}) groups = append(groups, group) group = []OpCode{} i1, j1 = max(i1, i2-n), max(j1, j2-n) } group = append(group, OpCode{c.Tag, i1, i2, j1, j2}) } if len(group) > 0 && !(len(group) == 1 && group[0].Tag == 'e') { groups = append(groups, group) } return groups } // Return a measure of the sequences' similarity (float in [0,1]). // // Where T is the total number of elements in both sequences, and // M is the number of matches, this is 2.0*M / T. // Note that this is 1 if the sequences are identical, and 0 if // they have nothing in common. // // .Ratio() is expensive to compute if you haven't already computed // .GetMatchingBlocks() or .GetOpCodes(), in which case you may // want to try .QuickRatio() or .RealQuickRation() first to get an // upper bound. func (m *SequenceMatcher) Ratio() float64 { matches := 0 for _, m := range m.GetMatchingBlocks() { matches += m.Size } return calculateRatio(matches, len(m.a)+len(m.b)) } // Return an upper bound on ratio() relatively quickly. // // This isn't defined beyond that it is an upper bound on .Ratio(), and // is faster to compute. func (m *SequenceMatcher) QuickRatio() float64 { // viewing a and b as multisets, set matches to the cardinality // of their intersection; this counts the number of matches // without regard to order, so is clearly an upper bound if m.fullBCount == nil { m.fullBCount = map[string]int{} for _, s := range m.b { m.fullBCount[s] = m.fullBCount[s] + 1 } } // avail[x] is the number of times x appears in 'b' less the // number of times we've seen it in 'a' so far ... kinda avail := map[string]int{} matches := 0 for _, s := range m.a { n, ok := avail[s] if !ok { n = m.fullBCount[s] } avail[s] = n - 1 if n > 0 { matches += 1 } } return calculateRatio(matches, len(m.a)+len(m.b)) } // Return an upper bound on ratio() very quickly. // // This isn't defined beyond that it is an upper bound on .Ratio(), and // is faster to compute than either .Ratio() or .QuickRatio(). func (m *SequenceMatcher) RealQuickRatio() float64 { la, lb := len(m.a), len(m.b) return calculateRatio(min(la, lb), la+lb) } // Convert range to the "ed" format func formatRangeUnified(start, stop int) string { // Per the diff spec at http://www.unix.org/single_unix_specification/ beginning := start + 1 // lines start numbering with one length := stop - start if length == 1 { return fmt.Sprintf("%d", beginning) } if length == 0 { beginning -= 1 // empty ranges begin at line just before the range } return fmt.Sprintf("%d,%d", beginning, length) } // Unified diff parameters type UnifiedDiff struct { A []string // First sequence lines FromFile string // First file name FromDate string // First file time B []string // Second sequence lines ToFile string // Second file name ToDate string // Second file time Eol string // Headers end of line, defaults to LF Context int // Number of context lines } // Compare two sequences of lines; generate the delta as a unified diff. // // Unified diffs are a compact way of showing line changes and a few // lines of context. The number of context lines is set by 'n' which // defaults to three. // // By default, the diff control lines (those with ---, +++, or @@) are // created with a trailing newline. This is helpful so that inputs // created from file.readlines() result in diffs that are suitable for // file.writelines() since both the inputs and outputs have trailing // newlines. // // For inputs that do not have trailing newlines, set the lineterm // argument to "" so that the output will be uniformly newline free. // // The unidiff format normally has a header for filenames and modification // times. Any or all of these may be specified using strings for // 'fromfile', 'tofile', 'fromfiledate', and 'tofiledate'. // The modification times are normally expressed in the ISO 8601 format. func WriteUnifiedDiff(writer io.Writer, diff UnifiedDiff) error { buf := bufio.NewWriter(writer) defer buf.Flush() w := func(format string, args ...interface{}) error { _, err := buf.WriteString(fmt.Sprintf(format, args...)) return err } if len(diff.Eol) == 0 { diff.Eol = "\n" } started := false m := NewMatcher(diff.A, diff.B) for _, g := range m.GetGroupedOpCodes(diff.Context) { if !started { started = true fromDate := "" if len(diff.FromDate) > 0 { fromDate = "\t" + diff.FromDate } toDate := "" if len(diff.ToDate) > 0 { toDate = "\t" + diff.ToDate } err := w("--- %s%s%s", diff.FromFile, fromDate, diff.Eol) if err != nil { return err } err = w("+++ %s%s%s", diff.ToFile, toDate, diff.Eol) if err != nil { return err } } first, last := g[0], g[len(g)-1] range1 := formatRangeUnified(first.I1, last.I2) range2 := formatRangeUnified(first.J1, last.J2) if err := w("@@ -%s +%s @@%s", range1, range2, diff.Eol); err != nil { return err } for _, c := range g { i1, i2, j1, j2 := c.I1, c.I2, c.J1, c.J2 if c.Tag == 'e' { for _, line := range diff.A[i1:i2] { if err := w(" " + line); err != nil { return err } } continue } if c.Tag == 'r' || c.Tag == 'd' { for _, line := range diff.A[i1:i2] { if err := w("-" + line); err != nil { return err } } } if c.Tag == 'r' || c.Tag == 'i' { for _, line := range diff.B[j1:j2] { if err := w("+" + line); err != nil { return err } } } } } return nil } // Like WriteUnifiedDiff but returns the diff a string. func GetUnifiedDiffString(diff UnifiedDiff) (string, error) { w := &bytes.Buffer{} err := WriteUnifiedDiff(w, diff) return string(w.Bytes()), err } // Convert range to the "ed" format. func formatRangeContext(start, stop int) string { // Per the diff spec at http://www.unix.org/single_unix_specification/ beginning := start + 1 // lines start numbering with one length := stop - start if length == 0 { beginning -= 1 // empty ranges begin at line just before the range } if length <= 1 { return fmt.Sprintf("%d", beginning) } return fmt.Sprintf("%d,%d", beginning, beginning+length-1) } type ContextDiff UnifiedDiff // Compare two sequences of lines; generate the delta as a context diff. // // Context diffs are a compact way of showing line changes and a few // lines of context. The number of context lines is set by diff.Context // which defaults to three. // // By default, the diff control lines (those with *** or ---) are // created with a trailing newline. // // For inputs that do not have trailing newlines, set the diff.Eol // argument to "" so that the output will be uniformly newline free. // // The context diff format normally has a header for filenames and // modification times. Any or all of these may be specified using // strings for diff.FromFile, diff.ToFile, diff.FromDate, diff.ToDate. // The modification times are normally expressed in the ISO 8601 format. // If not specified, the strings default to blanks. func WriteContextDiff(writer io.Writer, diff ContextDiff) error { buf := bufio.NewWriter(writer) defer buf.Flush() var diffErr error w := func(format string, args ...interface{}) { _, err := buf.WriteString(fmt.Sprintf(format, args...)) if diffErr == nil && err != nil { diffErr = err } } if len(diff.Eol) == 0 { diff.Eol = "\n" } prefix := map[byte]string{ 'i': "+ ", 'd': "- ", 'r': "! ", 'e': " ", } started := false m := NewMatcher(diff.A, diff.B) for _, g := range m.GetGroupedOpCodes(diff.Context) { if !started { started = true fromDate := "" if len(diff.FromDate) > 0 { fromDate = "\t" + diff.FromDate } toDate := "" if len(diff.ToDate) > 0 { toDate = "\t" + diff.ToDate } w("*** %s%s%s", diff.FromFile, fromDate, diff.Eol) w("--- %s%s%s", diff.ToFile, toDate, diff.Eol) } first, last := g[0], g[len(g)-1] w("***************" + diff.Eol) range1 := formatRangeContext(first.I1, last.I2) w("*** %s ****%s", range1, diff.Eol) for _, c := range g { if c.Tag == 'r' || c.Tag == 'd' { for _, cc := range g { if cc.Tag == 'i' { continue } for _, line := range diff.A[cc.I1:cc.I2] { w(prefix[cc.Tag] + line) } } break } } range2 := formatRangeContext(first.J1, last.J2) w("--- %s ----%s", range2, diff.Eol) for _, c := range g { if c.Tag == 'r' || c.Tag == 'i' { for _, cc := range g { if cc.Tag == 'd' { continue } for _, line := range diff.B[cc.J1:cc.J2] { w(prefix[cc.Tag] + line) } } break } } } return diffErr } // Like WriteContextDiff but returns the diff a string. func GetContextDiffString(diff ContextDiff) (string, error) { w := &bytes.Buffer{} err := WriteContextDiff(w, diff) return string(w.Bytes()), err } // Split a string on "\n" while preserving them. The output can be used // as input for UnifiedDiff and ContextDiff structures. func SplitLines(s string) []string { lines := strings.SplitAfter(s, "\n") lines[len(lines)-1] += "\n" return lines } lxd-2.0.0/dist/src/github.com/stretchr/testify/vendor/github.com/pmezard/go-difflib/LICENSE0000644061062106075000000000264512702772371034050 0ustar00stgraberdomain admins00000000000000Copyright (c) 2013, Patrick Mezard All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. The names of its contributors may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. lxd-2.0.0/dist/src/github.com/stretchr/testify/Godeps/0000755061062106075000000000000012702772371025255 5ustar00stgraberdomain admins00000000000000lxd-2.0.0/dist/src/github.com/stretchr/testify/Godeps/Godeps.json0000644061062106075000000000071012702772371027367 0ustar00stgraberdomain admins00000000000000{ "ImportPath": "github.com/stretchr/testify", "GoVersion": "go1.5", "Packages": [ "./..." ], "Deps": [ { "ImportPath": "github.com/davecgh/go-spew/spew", "Rev": "5215b55f46b2b919f50a1df0eaa5886afe4e3b3d" }, { "ImportPath": "github.com/pmezard/go-difflib/difflib", "Rev": "d8ed2627bdf02c080bf22230dbb337003b7aba2d" }, { "ImportPath": "github.com/stretchr/objx", "Rev": "cbeaeb16a013161a98496fad62933b1d21786672" } ] } lxd-2.0.0/dist/src/github.com/stretchr/testify/Godeps/Readme0000644061062106075000000000021012702772371026366 0ustar00stgraberdomain admins00000000000000This directory tree is generated automatically by godep. Please do not edit. See https://github.com/tools/godep for more information. lxd-2.0.0/dist/src/github.com/golang/0000755061062106075000000000000012702772347021761 5ustar00stgraberdomain admins00000000000000lxd-2.0.0/dist/src/github.com/golang/protobuf/0000755061062106075000000000000012702772352023615 5ustar00stgraberdomain admins00000000000000lxd-2.0.0/dist/src/github.com/golang/protobuf/jsonpb/0000755061062106075000000000000012702772352025110 5ustar00stgraberdomain admins00000000000000lxd-2.0.0/dist/src/github.com/golang/protobuf/jsonpb/jsonpb.go0000644061062106075000000004737312702772352026750 0ustar00stgraberdomain admins00000000000000// Go support for Protocol Buffers - Google's data interchange format // // Copyright 2015 The Go Authors. All rights reserved. // https://github.com/golang/protobuf // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /* Package jsonpb provides marshaling and unmarshaling between protocol buffers and JSON. It follows the specification at https://developers.google.com/protocol-buffers/docs/proto3#json. This package produces a different output than the standard "encoding/json" package, which does not operate correctly on protocol buffers. */ package jsonpb import ( "bytes" "encoding/json" "errors" "fmt" "io" "reflect" "sort" "strconv" "strings" "time" "github.com/golang/protobuf/proto" ) var ( byteArrayType = reflect.TypeOf([]byte{}) ) // Marshaler is a configurable object for converting between // protocol buffer objects and a JSON representation for them. type Marshaler struct { // Whether to render enum values as integers, as opposed to string values. EnumsAsInts bool // Whether to render fields with zero values. EmitDefaults bool // A string to indent each level by. The presence of this field will // also cause a space to appear between the field separator and // value, and for newlines to be appear between fields and array // elements. Indent string // Whether to use the original (.proto) name for fields. OrigName bool } // Marshal marshals a protocol buffer into JSON. func (m *Marshaler) Marshal(out io.Writer, pb proto.Message) error { writer := &errWriter{writer: out} return m.marshalObject(writer, pb, "") } // MarshalToString converts a protocol buffer object to JSON string. func (m *Marshaler) MarshalToString(pb proto.Message) (string, error) { var buf bytes.Buffer if err := m.Marshal(&buf, pb); err != nil { return "", err } return buf.String(), nil } type int32Slice []int32 // For sorting extensions ids to ensure stable output. func (s int32Slice) Len() int { return len(s) } func (s int32Slice) Less(i, j int) bool { return s[i] < s[j] } func (s int32Slice) Swap(i, j int) { s[i], s[j] = s[j], s[i] } // marshalObject writes a struct to the Writer. func (m *Marshaler) marshalObject(out *errWriter, v proto.Message, indent string) error { s := reflect.ValueOf(v).Elem() // Handle well-known types. type wkt interface { XXX_WellKnownType() string } if wkt, ok := v.(wkt); ok { switch wkt.XXX_WellKnownType() { case "DoubleValue", "FloatValue", "Int64Value", "UInt64Value", "Int32Value", "UInt32Value", "BoolValue", "StringValue", "BytesValue": // "Wrappers use the same representation in JSON // as the wrapped primitive type, ..." sprop := proto.GetProperties(s.Type()) return m.marshalValue(out, sprop.Prop[0], s.Field(0), indent) case "Duration": // "Generated output always contains 3, 6, or 9 fractional digits, // depending on required precision." s, ns := s.Field(0).Int(), s.Field(1).Int() d := time.Duration(s)*time.Second + time.Duration(ns)*time.Nanosecond x := fmt.Sprintf("%.9f", d.Seconds()) x = strings.TrimSuffix(x, "000") x = strings.TrimSuffix(x, "000") out.write(`"`) out.write(x) out.write(`s"`) return out.err case "Struct": // Let marshalValue handle the `fields` map. // TODO: pass the correct Properties if needed. return m.marshalValue(out, &proto.Properties{}, s.Field(0), indent) case "Timestamp": // "RFC 3339, where generated output will always be Z-normalized // and uses 3, 6 or 9 fractional digits." s, ns := s.Field(0).Int(), s.Field(1).Int() t := time.Unix(s, ns).UTC() // time.RFC3339Nano isn't exactly right (we need to get 3/6/9 fractional digits). x := t.Format("2006-01-02T15:04:05.000000000") x = strings.TrimSuffix(x, "000") x = strings.TrimSuffix(x, "000") out.write(`"`) out.write(x) out.write(`Z"`) return out.err case "Value": // Value has a single oneof. kind := s.Field(0) if kind.IsNil() { // "absence of any variant indicates an error" return errors.New("nil Value") } // oneof -> *T -> T -> T.F x := kind.Elem().Elem().Field(0) // TODO: pass the correct Properties if needed. return m.marshalValue(out, &proto.Properties{}, x, indent) } } out.write("{") if m.Indent != "" { out.write("\n") } firstField := true for i := 0; i < s.NumField(); i++ { value := s.Field(i) valueField := s.Type().Field(i) if strings.HasPrefix(valueField.Name, "XXX_") { continue } // IsNil will panic on most value kinds. switch value.Kind() { case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice: if value.IsNil() { continue } } if !m.EmitDefaults { switch value.Kind() { case reflect.Bool: if !value.Bool() { continue } case reflect.Int32, reflect.Int64: if value.Int() == 0 { continue } case reflect.Uint32, reflect.Uint64: if value.Uint() == 0 { continue } case reflect.Float32, reflect.Float64: if value.Float() == 0 { continue } case reflect.String: if value.Len() == 0 { continue } } } // Oneof fields need special handling. if valueField.Tag.Get("protobuf_oneof") != "" { // value is an interface containing &T{real_value}. sv := value.Elem().Elem() // interface -> *T -> T value = sv.Field(0) valueField = sv.Type().Field(0) } prop := jsonProperties(valueField, m.OrigName) if !firstField { m.writeSep(out) } if err := m.marshalField(out, prop, value, indent); err != nil { return err } firstField = false } // Handle proto2 extensions. if ep, ok := v.(extendableProto); ok { extensions := proto.RegisteredExtensions(v) extensionMap := ep.ExtensionMap() // Sort extensions for stable output. ids := make([]int32, 0, len(extensionMap)) for id := range extensionMap { ids = append(ids, id) } sort.Sort(int32Slice(ids)) for _, id := range ids { desc := extensions[id] if desc == nil { // unknown extension continue } ext, extErr := proto.GetExtension(ep, desc) if extErr != nil { return extErr } value := reflect.ValueOf(ext) var prop proto.Properties prop.Parse(desc.Tag) prop.JSONName = fmt.Sprintf("[%s]", desc.Name) if !firstField { m.writeSep(out) } if err := m.marshalField(out, &prop, value, indent); err != nil { return err } firstField = false } } if m.Indent != "" { out.write("\n") out.write(indent) } out.write("}") return out.err } func (m *Marshaler) writeSep(out *errWriter) { if m.Indent != "" { out.write(",\n") } else { out.write(",") } } // marshalField writes field description and value to the Writer. func (m *Marshaler) marshalField(out *errWriter, prop *proto.Properties, v reflect.Value, indent string) error { if m.Indent != "" { out.write(indent) out.write(m.Indent) } out.write(`"`) out.write(prop.JSONName) out.write(`":`) if m.Indent != "" { out.write(" ") } if err := m.marshalValue(out, prop, v, indent); err != nil { return err } return nil } // marshalValue writes the value to the Writer. func (m *Marshaler) marshalValue(out *errWriter, prop *proto.Properties, v reflect.Value, indent string) error { var err error v = reflect.Indirect(v) // Handle repeated elements. if v.Type() != byteArrayType && v.Kind() == reflect.Slice { out.write("[") comma := "" for i := 0; i < v.Len(); i++ { sliceVal := v.Index(i) out.write(comma) if m.Indent != "" { out.write("\n") out.write(indent) out.write(m.Indent) out.write(m.Indent) } m.marshalValue(out, prop, sliceVal, indent+m.Indent) comma = "," } if m.Indent != "" { out.write("\n") out.write(indent) out.write(m.Indent) } out.write("]") return out.err } // Handle well-known types. // Most are handled up in marshalObject (because 99% are messages). type wkt interface { XXX_WellKnownType() string } if wkt, ok := v.Interface().(wkt); ok { switch wkt.XXX_WellKnownType() { case "NullValue": out.write("null") return out.err } } // Handle enumerations. if !m.EnumsAsInts && prop.Enum != "" { // Unknown enum values will are stringified by the proto library as their // value. Such values should _not_ be quoted or they will be interpreted // as an enum string instead of their value. enumStr := v.Interface().(fmt.Stringer).String() var valStr string if v.Kind() == reflect.Ptr { valStr = strconv.Itoa(int(v.Elem().Int())) } else { valStr = strconv.Itoa(int(v.Int())) } isKnownEnum := enumStr != valStr if isKnownEnum { out.write(`"`) } out.write(enumStr) if isKnownEnum { out.write(`"`) } return out.err } // Handle nested messages. if v.Kind() == reflect.Struct { return m.marshalObject(out, v.Addr().Interface().(proto.Message), indent+m.Indent) } // Handle maps. // Since Go randomizes map iteration, we sort keys for stable output. if v.Kind() == reflect.Map { out.write(`{`) keys := v.MapKeys() sort.Sort(mapKeys(keys)) for i, k := range keys { if i > 0 { out.write(`,`) } if m.Indent != "" { out.write("\n") out.write(indent) out.write(m.Indent) out.write(m.Indent) } b, err := json.Marshal(k.Interface()) if err != nil { return err } s := string(b) // If the JSON is not a string value, encode it again to make it one. if !strings.HasPrefix(s, `"`) { b, err := json.Marshal(s) if err != nil { return err } s = string(b) } out.write(s) out.write(`:`) if m.Indent != "" { out.write(` `) } if err := m.marshalValue(out, prop, v.MapIndex(k), indent+m.Indent); err != nil { return err } } if m.Indent != "" { out.write("\n") out.write(indent) out.write(m.Indent) } out.write(`}`) return out.err } // Default handling defers to the encoding/json library. b, err := json.Marshal(v.Interface()) if err != nil { return err } needToQuote := string(b[0]) != `"` && (v.Kind() == reflect.Int64 || v.Kind() == reflect.Uint64) if needToQuote { out.write(`"`) } out.write(string(b)) if needToQuote { out.write(`"`) } return out.err } // UnmarshalNext unmarshals the next protocol buffer from a JSON object stream. // This function is lenient and will decode any options permutations of the // related Marshaler. func UnmarshalNext(dec *json.Decoder, pb proto.Message) error { inputValue := json.RawMessage{} if err := dec.Decode(&inputValue); err != nil { return err } return unmarshalValue(reflect.ValueOf(pb).Elem(), inputValue) } // Unmarshal unmarshals a JSON object stream into a protocol // buffer. This function is lenient and will decode any options // permutations of the related Marshaler. func Unmarshal(r io.Reader, pb proto.Message) error { dec := json.NewDecoder(r) return UnmarshalNext(dec, pb) } // UnmarshalString will populate the fields of a protocol buffer based // on a JSON string. This function is lenient and will decode any options // permutations of the related Marshaler. func UnmarshalString(str string, pb proto.Message) error { return Unmarshal(strings.NewReader(str), pb) } // unmarshalValue converts/copies a value into the target. func unmarshalValue(target reflect.Value, inputValue json.RawMessage) error { targetType := target.Type() // Allocate memory for pointer fields. if targetType.Kind() == reflect.Ptr { target.Set(reflect.New(targetType.Elem())) return unmarshalValue(target.Elem(), inputValue) } // Handle well-known types. type wkt interface { XXX_WellKnownType() string } if wkt, ok := target.Addr().Interface().(wkt); ok { switch wkt.XXX_WellKnownType() { case "DoubleValue", "FloatValue", "Int64Value", "UInt64Value", "Int32Value", "UInt32Value", "BoolValue", "StringValue", "BytesValue": // "Wrappers use the same representation in JSON // as the wrapped primitive type, except that null is allowed." // encoding/json will turn JSON `null` into Go `nil`, // so we don't have to do any extra work. return unmarshalValue(target.Field(0), inputValue) case "Duration": unq, err := strconv.Unquote(string(inputValue)) if err != nil { return err } d, err := time.ParseDuration(unq) if err != nil { return fmt.Errorf("bad Duration: %v", err) } ns := d.Nanoseconds() s := ns / 1e9 ns %= 1e9 target.Field(0).SetInt(s) target.Field(1).SetInt(ns) return nil case "Timestamp": unq, err := strconv.Unquote(string(inputValue)) if err != nil { return err } t, err := time.Parse(time.RFC3339Nano, unq) if err != nil { return fmt.Errorf("bad Timestamp: %v", err) } ns := t.UnixNano() s := ns / 1e9 ns %= 1e9 target.Field(0).SetInt(s) target.Field(1).SetInt(ns) return nil } } // Handle nested messages. if targetType.Kind() == reflect.Struct { var jsonFields map[string]json.RawMessage if err := json.Unmarshal(inputValue, &jsonFields); err != nil { return err } consumeField := func(prop *proto.Properties) (json.RawMessage, bool) { // Be liberal in what names we accept; both orig_name and camelName are okay. fieldNames := acceptedJSONFieldNames(prop) vOrig, okOrig := jsonFields[fieldNames.orig] vCamel, okCamel := jsonFields[fieldNames.camel] if !okOrig && !okCamel { return nil, false } // If, for some reason, both are present in the data, favour the camelName. var raw json.RawMessage if okOrig { raw = vOrig delete(jsonFields, fieldNames.orig) } if okCamel { raw = vCamel delete(jsonFields, fieldNames.camel) } return raw, true } sprops := proto.GetProperties(targetType) for i := 0; i < target.NumField(); i++ { ft := target.Type().Field(i) if strings.HasPrefix(ft.Name, "XXX_") { continue } valueForField, ok := consumeField(sprops.Prop[i]) if !ok { continue } // Handle enums, which have an underlying type of int32, // and may appear as strings. We do this while handling // the struct so we have access to the enum info. // The case of an enum appearing as a number is handled // by the recursive call to unmarshalValue. if enum := sprops.Prop[i].Enum; valueForField[0] == '"' && enum != "" { vmap := proto.EnumValueMap(enum) // Don't need to do unquoting; valid enum names // are from a limited character set. s := valueForField[1 : len(valueForField)-1] n, ok := vmap[string(s)] if !ok { return fmt.Errorf("unknown value %q for enum %s", s, enum) } f := target.Field(i) if f.Kind() == reflect.Ptr { // proto2 f.Set(reflect.New(f.Type().Elem())) f = f.Elem() } f.SetInt(int64(n)) continue } if err := unmarshalValue(target.Field(i), valueForField); err != nil { return err } } // Check for any oneof fields. if len(jsonFields) > 0 { for _, oop := range sprops.OneofTypes { raw, ok := consumeField(oop.Prop) if !ok { continue } nv := reflect.New(oop.Type.Elem()) target.Field(oop.Field).Set(nv) if err := unmarshalValue(nv.Elem().Field(0), raw); err != nil { return err } } } if len(jsonFields) > 0 { // Pick any field to be the scapegoat. var f string for fname := range jsonFields { f = fname break } return fmt.Errorf("unknown field %q in %v", f, targetType) } return nil } // Handle arrays (which aren't encoded bytes) if targetType != byteArrayType && targetType.Kind() == reflect.Slice { var slc []json.RawMessage if err := json.Unmarshal(inputValue, &slc); err != nil { return err } len := len(slc) target.Set(reflect.MakeSlice(targetType, len, len)) for i := 0; i < len; i++ { if err := unmarshalValue(target.Index(i), slc[i]); err != nil { return err } } return nil } // Handle maps (whose keys are always strings) if targetType.Kind() == reflect.Map { var mp map[string]json.RawMessage if err := json.Unmarshal(inputValue, &mp); err != nil { return err } target.Set(reflect.MakeMap(targetType)) for ks, raw := range mp { // Unmarshal map key. The core json library already decoded the key into a // string, so we handle that specially. Other types were quoted post-serialization. var k reflect.Value if targetType.Key().Kind() == reflect.String { k = reflect.ValueOf(ks) } else { k = reflect.New(targetType.Key()).Elem() if err := unmarshalValue(k, json.RawMessage(ks)); err != nil { return err } } // Unmarshal map value. v := reflect.New(targetType.Elem()).Elem() if err := unmarshalValue(v, raw); err != nil { return err } target.SetMapIndex(k, v) } return nil } // 64-bit integers can be encoded as strings. In this case we drop // the quotes and proceed as normal. isNum := targetType.Kind() == reflect.Int64 || targetType.Kind() == reflect.Uint64 if isNum && strings.HasPrefix(string(inputValue), `"`) { inputValue = inputValue[1 : len(inputValue)-1] } // Use the encoding/json for parsing other value types. return json.Unmarshal(inputValue, target.Addr().Interface()) } // jsonProperties returns parsed proto.Properties for the field and corrects JSONName attribute. func jsonProperties(f reflect.StructField, origName bool) *proto.Properties { var prop proto.Properties prop.Init(f.Type, f.Name, f.Tag.Get("protobuf"), &f) if origName || prop.JSONName == "" { prop.JSONName = prop.OrigName } return &prop } type fieldNames struct { orig, camel string } func acceptedJSONFieldNames(prop *proto.Properties) fieldNames { opts := fieldNames{orig: prop.OrigName, camel: prop.OrigName} if prop.JSONName != "" { opts.camel = prop.JSONName } return opts } // extendableProto is an interface implemented by any protocol buffer that may be extended. type extendableProto interface { proto.Message ExtensionRangeArray() []proto.ExtensionRange ExtensionMap() map[int32]proto.Extension } // Writer wrapper inspired by https://blog.golang.org/errors-are-values type errWriter struct { writer io.Writer err error } func (w *errWriter) write(str string) { if w.err != nil { return } _, w.err = w.writer.Write([]byte(str)) } // Map fields may have key types of non-float scalars, strings and enums. // The easiest way to sort them in some deterministic order is to use fmt. // If this turns out to be inefficient we can always consider other options, // such as doing a Schwartzian transform. type mapKeys []reflect.Value func (s mapKeys) Len() int { return len(s) } func (s mapKeys) Swap(i, j int) { s[i], s[j] = s[j], s[i] } func (s mapKeys) Less(i, j int) bool { return fmt.Sprint(s[i].Interface()) < fmt.Sprint(s[j].Interface()) } lxd-2.0.0/dist/src/github.com/golang/protobuf/jsonpb/jsonpb_test_proto/0000755061062106075000000000000012702772352030665 5ustar00stgraberdomain admins00000000000000lxd-2.0.0/dist/src/github.com/golang/protobuf/jsonpb/jsonpb_test_proto/more_test_objects.proto0000644061062106075000000000360112702772352035464 0ustar00stgraberdomain admins00000000000000// Go support for Protocol Buffers - Google's data interchange format // // Copyright 2015 The Go Authors. All rights reserved. // https://github.com/golang/protobuf // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. syntax = "proto3"; package jsonpb; message Simple3 { double dub = 1; } message Mappy { map nummy = 1; map strry = 2; map objjy = 3; map buggy = 4; map booly = 5; } lxd-2.0.0/dist/src/github.com/golang/protobuf/jsonpb/jsonpb_test_proto/test_objects.pb.go0000644061062106075000000006126312702772352034314 0ustar00stgraberdomain admins00000000000000// Code generated by protoc-gen-go. // source: test_objects.proto // DO NOT EDIT! package jsonpb import proto "github.com/golang/protobuf/proto" import fmt "fmt" import math "math" import google_protobuf "github.com/golang/protobuf/ptypes/duration" import google_protobuf1 "github.com/golang/protobuf/ptypes/struct" import google_protobuf2 "github.com/golang/protobuf/ptypes/timestamp" import google_protobuf3 "github.com/golang/protobuf/ptypes/wrappers" // Reference imports to suppress errors if they are not otherwise used. var _ = proto.Marshal var _ = fmt.Errorf var _ = math.Inf type Widget_Color int32 const ( Widget_RED Widget_Color = 0 Widget_GREEN Widget_Color = 1 Widget_BLUE Widget_Color = 2 ) var Widget_Color_name = map[int32]string{ 0: "RED", 1: "GREEN", 2: "BLUE", } var Widget_Color_value = map[string]int32{ "RED": 0, "GREEN": 1, "BLUE": 2, } func (x Widget_Color) Enum() *Widget_Color { p := new(Widget_Color) *p = x return p } func (x Widget_Color) String() string { return proto.EnumName(Widget_Color_name, int32(x)) } func (x *Widget_Color) UnmarshalJSON(data []byte) error { value, err := proto.UnmarshalJSONEnum(Widget_Color_value, data, "Widget_Color") if err != nil { return err } *x = Widget_Color(value) return nil } func (Widget_Color) EnumDescriptor() ([]byte, []int) { return fileDescriptor1, []int{2, 0} } // Test message for holding primitive types. type Simple struct { OBool *bool `protobuf:"varint,1,opt,name=o_bool,json=oBool" json:"o_bool,omitempty"` OInt32 *int32 `protobuf:"varint,2,opt,name=o_int32,json=oInt32" json:"o_int32,omitempty"` OInt64 *int64 `protobuf:"varint,3,opt,name=o_int64,json=oInt64" json:"o_int64,omitempty"` OUint32 *uint32 `protobuf:"varint,4,opt,name=o_uint32,json=oUint32" json:"o_uint32,omitempty"` OUint64 *uint64 `protobuf:"varint,5,opt,name=o_uint64,json=oUint64" json:"o_uint64,omitempty"` OSint32 *int32 `protobuf:"zigzag32,6,opt,name=o_sint32,json=oSint32" json:"o_sint32,omitempty"` OSint64 *int64 `protobuf:"zigzag64,7,opt,name=o_sint64,json=oSint64" json:"o_sint64,omitempty"` OFloat *float32 `protobuf:"fixed32,8,opt,name=o_float,json=oFloat" json:"o_float,omitempty"` ODouble *float64 `protobuf:"fixed64,9,opt,name=o_double,json=oDouble" json:"o_double,omitempty"` OString *string `protobuf:"bytes,10,opt,name=o_string,json=oString" json:"o_string,omitempty"` OBytes []byte `protobuf:"bytes,11,opt,name=o_bytes,json=oBytes" json:"o_bytes,omitempty"` XXX_unrecognized []byte `json:"-"` } func (m *Simple) Reset() { *m = Simple{} } func (m *Simple) String() string { return proto.CompactTextString(m) } func (*Simple) ProtoMessage() {} func (*Simple) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{0} } func (m *Simple) GetOBool() bool { if m != nil && m.OBool != nil { return *m.OBool } return false } func (m *Simple) GetOInt32() int32 { if m != nil && m.OInt32 != nil { return *m.OInt32 } return 0 } func (m *Simple) GetOInt64() int64 { if m != nil && m.OInt64 != nil { return *m.OInt64 } return 0 } func (m *Simple) GetOUint32() uint32 { if m != nil && m.OUint32 != nil { return *m.OUint32 } return 0 } func (m *Simple) GetOUint64() uint64 { if m != nil && m.OUint64 != nil { return *m.OUint64 } return 0 } func (m *Simple) GetOSint32() int32 { if m != nil && m.OSint32 != nil { return *m.OSint32 } return 0 } func (m *Simple) GetOSint64() int64 { if m != nil && m.OSint64 != nil { return *m.OSint64 } return 0 } func (m *Simple) GetOFloat() float32 { if m != nil && m.OFloat != nil { return *m.OFloat } return 0 } func (m *Simple) GetODouble() float64 { if m != nil && m.ODouble != nil { return *m.ODouble } return 0 } func (m *Simple) GetOString() string { if m != nil && m.OString != nil { return *m.OString } return "" } func (m *Simple) GetOBytes() []byte { if m != nil { return m.OBytes } return nil } // Test message for holding repeated primitives. type Repeats struct { RBool []bool `protobuf:"varint,1,rep,name=r_bool,json=rBool" json:"r_bool,omitempty"` RInt32 []int32 `protobuf:"varint,2,rep,name=r_int32,json=rInt32" json:"r_int32,omitempty"` RInt64 []int64 `protobuf:"varint,3,rep,name=r_int64,json=rInt64" json:"r_int64,omitempty"` RUint32 []uint32 `protobuf:"varint,4,rep,name=r_uint32,json=rUint32" json:"r_uint32,omitempty"` RUint64 []uint64 `protobuf:"varint,5,rep,name=r_uint64,json=rUint64" json:"r_uint64,omitempty"` RSint32 []int32 `protobuf:"zigzag32,6,rep,name=r_sint32,json=rSint32" json:"r_sint32,omitempty"` RSint64 []int64 `protobuf:"zigzag64,7,rep,name=r_sint64,json=rSint64" json:"r_sint64,omitempty"` RFloat []float32 `protobuf:"fixed32,8,rep,name=r_float,json=rFloat" json:"r_float,omitempty"` RDouble []float64 `protobuf:"fixed64,9,rep,name=r_double,json=rDouble" json:"r_double,omitempty"` RString []string `protobuf:"bytes,10,rep,name=r_string,json=rString" json:"r_string,omitempty"` RBytes [][]byte `protobuf:"bytes,11,rep,name=r_bytes,json=rBytes" json:"r_bytes,omitempty"` XXX_unrecognized []byte `json:"-"` } func (m *Repeats) Reset() { *m = Repeats{} } func (m *Repeats) String() string { return proto.CompactTextString(m) } func (*Repeats) ProtoMessage() {} func (*Repeats) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{1} } func (m *Repeats) GetRBool() []bool { if m != nil { return m.RBool } return nil } func (m *Repeats) GetRInt32() []int32 { if m != nil { return m.RInt32 } return nil } func (m *Repeats) GetRInt64() []int64 { if m != nil { return m.RInt64 } return nil } func (m *Repeats) GetRUint32() []uint32 { if m != nil { return m.RUint32 } return nil } func (m *Repeats) GetRUint64() []uint64 { if m != nil { return m.RUint64 } return nil } func (m *Repeats) GetRSint32() []int32 { if m != nil { return m.RSint32 } return nil } func (m *Repeats) GetRSint64() []int64 { if m != nil { return m.RSint64 } return nil } func (m *Repeats) GetRFloat() []float32 { if m != nil { return m.RFloat } return nil } func (m *Repeats) GetRDouble() []float64 { if m != nil { return m.RDouble } return nil } func (m *Repeats) GetRString() []string { if m != nil { return m.RString } return nil } func (m *Repeats) GetRBytes() [][]byte { if m != nil { return m.RBytes } return nil } // Test message for holding enums and nested messages. type Widget struct { Color *Widget_Color `protobuf:"varint,1,opt,name=color,enum=jsonpb.Widget_Color" json:"color,omitempty"` RColor []Widget_Color `protobuf:"varint,2,rep,name=r_color,json=rColor,enum=jsonpb.Widget_Color" json:"r_color,omitempty"` Simple *Simple `protobuf:"bytes,10,opt,name=simple" json:"simple,omitempty"` RSimple []*Simple `protobuf:"bytes,11,rep,name=r_simple,json=rSimple" json:"r_simple,omitempty"` Repeats *Repeats `protobuf:"bytes,20,opt,name=repeats" json:"repeats,omitempty"` RRepeats []*Repeats `protobuf:"bytes,21,rep,name=r_repeats,json=rRepeats" json:"r_repeats,omitempty"` XXX_unrecognized []byte `json:"-"` } func (m *Widget) Reset() { *m = Widget{} } func (m *Widget) String() string { return proto.CompactTextString(m) } func (*Widget) ProtoMessage() {} func (*Widget) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{2} } func (m *Widget) GetColor() Widget_Color { if m != nil && m.Color != nil { return *m.Color } return Widget_RED } func (m *Widget) GetRColor() []Widget_Color { if m != nil { return m.RColor } return nil } func (m *Widget) GetSimple() *Simple { if m != nil { return m.Simple } return nil } func (m *Widget) GetRSimple() []*Simple { if m != nil { return m.RSimple } return nil } func (m *Widget) GetRepeats() *Repeats { if m != nil { return m.Repeats } return nil } func (m *Widget) GetRRepeats() []*Repeats { if m != nil { return m.RRepeats } return nil } type Maps struct { MInt64Str map[int64]string `protobuf:"bytes,1,rep,name=m_int64_str,json=mInt64Str" json:"m_int64_str,omitempty" protobuf_key:"varint,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` MBoolSimple map[bool]*Simple `protobuf:"bytes,2,rep,name=m_bool_simple,json=mBoolSimple" json:"m_bool_simple,omitempty" protobuf_key:"varint,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` XXX_unrecognized []byte `json:"-"` } func (m *Maps) Reset() { *m = Maps{} } func (m *Maps) String() string { return proto.CompactTextString(m) } func (*Maps) ProtoMessage() {} func (*Maps) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{3} } func (m *Maps) GetMInt64Str() map[int64]string { if m != nil { return m.MInt64Str } return nil } func (m *Maps) GetMBoolSimple() map[bool]*Simple { if m != nil { return m.MBoolSimple } return nil } type MsgWithOneof struct { // Types that are valid to be assigned to Union: // *MsgWithOneof_Title // *MsgWithOneof_Salary // *MsgWithOneof_Country Union isMsgWithOneof_Union `protobuf_oneof:"union"` XXX_unrecognized []byte `json:"-"` } func (m *MsgWithOneof) Reset() { *m = MsgWithOneof{} } func (m *MsgWithOneof) String() string { return proto.CompactTextString(m) } func (*MsgWithOneof) ProtoMessage() {} func (*MsgWithOneof) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{4} } type isMsgWithOneof_Union interface { isMsgWithOneof_Union() } type MsgWithOneof_Title struct { Title string `protobuf:"bytes,1,opt,name=title,oneof"` } type MsgWithOneof_Salary struct { Salary int64 `protobuf:"varint,2,opt,name=salary,oneof"` } type MsgWithOneof_Country struct { Country string `protobuf:"bytes,3,opt,name=Country,json=country,oneof"` } func (*MsgWithOneof_Title) isMsgWithOneof_Union() {} func (*MsgWithOneof_Salary) isMsgWithOneof_Union() {} func (*MsgWithOneof_Country) isMsgWithOneof_Union() {} func (m *MsgWithOneof) GetUnion() isMsgWithOneof_Union { if m != nil { return m.Union } return nil } func (m *MsgWithOneof) GetTitle() string { if x, ok := m.GetUnion().(*MsgWithOneof_Title); ok { return x.Title } return "" } func (m *MsgWithOneof) GetSalary() int64 { if x, ok := m.GetUnion().(*MsgWithOneof_Salary); ok { return x.Salary } return 0 } func (m *MsgWithOneof) GetCountry() string { if x, ok := m.GetUnion().(*MsgWithOneof_Country); ok { return x.Country } return "" } // XXX_OneofFuncs is for the internal use of the proto package. func (*MsgWithOneof) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) { return _MsgWithOneof_OneofMarshaler, _MsgWithOneof_OneofUnmarshaler, _MsgWithOneof_OneofSizer, []interface{}{ (*MsgWithOneof_Title)(nil), (*MsgWithOneof_Salary)(nil), (*MsgWithOneof_Country)(nil), } } func _MsgWithOneof_OneofMarshaler(msg proto.Message, b *proto.Buffer) error { m := msg.(*MsgWithOneof) // union switch x := m.Union.(type) { case *MsgWithOneof_Title: b.EncodeVarint(1<<3 | proto.WireBytes) b.EncodeStringBytes(x.Title) case *MsgWithOneof_Salary: b.EncodeVarint(2<<3 | proto.WireVarint) b.EncodeVarint(uint64(x.Salary)) case *MsgWithOneof_Country: b.EncodeVarint(3<<3 | proto.WireBytes) b.EncodeStringBytes(x.Country) case nil: default: return fmt.Errorf("MsgWithOneof.Union has unexpected type %T", x) } return nil } func _MsgWithOneof_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) { m := msg.(*MsgWithOneof) switch tag { case 1: // union.title if wire != proto.WireBytes { return true, proto.ErrInternalBadWireType } x, err := b.DecodeStringBytes() m.Union = &MsgWithOneof_Title{x} return true, err case 2: // union.salary if wire != proto.WireVarint { return true, proto.ErrInternalBadWireType } x, err := b.DecodeVarint() m.Union = &MsgWithOneof_Salary{int64(x)} return true, err case 3: // union.Country if wire != proto.WireBytes { return true, proto.ErrInternalBadWireType } x, err := b.DecodeStringBytes() m.Union = &MsgWithOneof_Country{x} return true, err default: return false, nil } } func _MsgWithOneof_OneofSizer(msg proto.Message) (n int) { m := msg.(*MsgWithOneof) // union switch x := m.Union.(type) { case *MsgWithOneof_Title: n += proto.SizeVarint(1<<3 | proto.WireBytes) n += proto.SizeVarint(uint64(len(x.Title))) n += len(x.Title) case *MsgWithOneof_Salary: n += proto.SizeVarint(2<<3 | proto.WireVarint) n += proto.SizeVarint(uint64(x.Salary)) case *MsgWithOneof_Country: n += proto.SizeVarint(3<<3 | proto.WireBytes) n += proto.SizeVarint(uint64(len(x.Country))) n += len(x.Country) case nil: default: panic(fmt.Sprintf("proto: unexpected type %T in oneof", x)) } return n } type Real struct { Value *float64 `protobuf:"fixed64,1,opt,name=value" json:"value,omitempty"` XXX_extensions map[int32]proto.Extension `json:"-"` XXX_unrecognized []byte `json:"-"` } func (m *Real) Reset() { *m = Real{} } func (m *Real) String() string { return proto.CompactTextString(m) } func (*Real) ProtoMessage() {} func (*Real) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{5} } var extRange_Real = []proto.ExtensionRange{ {100, 536870911}, } func (*Real) ExtensionRangeArray() []proto.ExtensionRange { return extRange_Real } func (m *Real) ExtensionMap() map[int32]proto.Extension { if m.XXX_extensions == nil { m.XXX_extensions = make(map[int32]proto.Extension) } return m.XXX_extensions } func (m *Real) GetValue() float64 { if m != nil && m.Value != nil { return *m.Value } return 0 } type Complex struct { Imaginary *float64 `protobuf:"fixed64,1,opt,name=imaginary" json:"imaginary,omitempty"` XXX_extensions map[int32]proto.Extension `json:"-"` XXX_unrecognized []byte `json:"-"` } func (m *Complex) Reset() { *m = Complex{} } func (m *Complex) String() string { return proto.CompactTextString(m) } func (*Complex) ProtoMessage() {} func (*Complex) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{6} } var extRange_Complex = []proto.ExtensionRange{ {100, 536870911}, } func (*Complex) ExtensionRangeArray() []proto.ExtensionRange { return extRange_Complex } func (m *Complex) ExtensionMap() map[int32]proto.Extension { if m.XXX_extensions == nil { m.XXX_extensions = make(map[int32]proto.Extension) } return m.XXX_extensions } func (m *Complex) GetImaginary() float64 { if m != nil && m.Imaginary != nil { return *m.Imaginary } return 0 } var E_Complex_RealExtension = &proto.ExtensionDesc{ ExtendedType: (*Real)(nil), ExtensionType: (*Complex)(nil), Field: 123, Name: "jsonpb.Complex.real_extension", Tag: "bytes,123,opt,name=real_extension,json=realExtension", } type KnownTypes struct { Dur *google_protobuf.Duration `protobuf:"bytes,1,opt,name=dur" json:"dur,omitempty"` St *google_protobuf1.Struct `protobuf:"bytes,12,opt,name=st" json:"st,omitempty"` Ts *google_protobuf2.Timestamp `protobuf:"bytes,2,opt,name=ts" json:"ts,omitempty"` Dbl *google_protobuf3.DoubleValue `protobuf:"bytes,3,opt,name=dbl" json:"dbl,omitempty"` Flt *google_protobuf3.FloatValue `protobuf:"bytes,4,opt,name=flt" json:"flt,omitempty"` I64 *google_protobuf3.Int64Value `protobuf:"bytes,5,opt,name=i64" json:"i64,omitempty"` U64 *google_protobuf3.UInt64Value `protobuf:"bytes,6,opt,name=u64" json:"u64,omitempty"` I32 *google_protobuf3.Int32Value `protobuf:"bytes,7,opt,name=i32" json:"i32,omitempty"` U32 *google_protobuf3.UInt32Value `protobuf:"bytes,8,opt,name=u32" json:"u32,omitempty"` Bool *google_protobuf3.BoolValue `protobuf:"bytes,9,opt,name=bool" json:"bool,omitempty"` Str *google_protobuf3.StringValue `protobuf:"bytes,10,opt,name=str" json:"str,omitempty"` Bytes *google_protobuf3.BytesValue `protobuf:"bytes,11,opt,name=bytes" json:"bytes,omitempty"` XXX_unrecognized []byte `json:"-"` } func (m *KnownTypes) Reset() { *m = KnownTypes{} } func (m *KnownTypes) String() string { return proto.CompactTextString(m) } func (*KnownTypes) ProtoMessage() {} func (*KnownTypes) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{7} } func (m *KnownTypes) GetDur() *google_protobuf.Duration { if m != nil { return m.Dur } return nil } func (m *KnownTypes) GetSt() *google_protobuf1.Struct { if m != nil { return m.St } return nil } func (m *KnownTypes) GetTs() *google_protobuf2.Timestamp { if m != nil { return m.Ts } return nil } func (m *KnownTypes) GetDbl() *google_protobuf3.DoubleValue { if m != nil { return m.Dbl } return nil } func (m *KnownTypes) GetFlt() *google_protobuf3.FloatValue { if m != nil { return m.Flt } return nil } func (m *KnownTypes) GetI64() *google_protobuf3.Int64Value { if m != nil { return m.I64 } return nil } func (m *KnownTypes) GetU64() *google_protobuf3.UInt64Value { if m != nil { return m.U64 } return nil } func (m *KnownTypes) GetI32() *google_protobuf3.Int32Value { if m != nil { return m.I32 } return nil } func (m *KnownTypes) GetU32() *google_protobuf3.UInt32Value { if m != nil { return m.U32 } return nil } func (m *KnownTypes) GetBool() *google_protobuf3.BoolValue { if m != nil { return m.Bool } return nil } func (m *KnownTypes) GetStr() *google_protobuf3.StringValue { if m != nil { return m.Str } return nil } func (m *KnownTypes) GetBytes() *google_protobuf3.BytesValue { if m != nil { return m.Bytes } return nil } var E_Name = &proto.ExtensionDesc{ ExtendedType: (*Real)(nil), ExtensionType: (*string)(nil), Field: 124, Name: "jsonpb.name", Tag: "bytes,124,opt,name=name", } func init() { proto.RegisterType((*Simple)(nil), "jsonpb.Simple") proto.RegisterType((*Repeats)(nil), "jsonpb.Repeats") proto.RegisterType((*Widget)(nil), "jsonpb.Widget") proto.RegisterType((*Maps)(nil), "jsonpb.Maps") proto.RegisterType((*MsgWithOneof)(nil), "jsonpb.MsgWithOneof") proto.RegisterType((*Real)(nil), "jsonpb.Real") proto.RegisterType((*Complex)(nil), "jsonpb.Complex") proto.RegisterType((*KnownTypes)(nil), "jsonpb.KnownTypes") proto.RegisterEnum("jsonpb.Widget_Color", Widget_Color_name, Widget_Color_value) proto.RegisterExtension(E_Complex_RealExtension) proto.RegisterExtension(E_Name) } var fileDescriptor1 = []byte{ // 988 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x7c, 0x55, 0xdd, 0x72, 0xdb, 0x44, 0x14, 0xae, 0xb5, 0x96, 0x65, 0xaf, 0x93, 0x60, 0x76, 0x52, 0xaa, 0x9a, 0x00, 0x1d, 0x0f, 0x14, 0x28, 0xe0, 0x0e, 0x6e, 0xa7, 0xc3, 0x14, 0x6e, 0x48, 0x63, 0x7e, 0x06, 0x52, 0x66, 0x36, 0x0d, 0xbd, 0xf4, 0xc8, 0x89, 0x62, 0x54, 0x64, 0xad, 0x66, 0xb5, 0x22, 0xcd, 0xc0, 0x05, 0x0f, 0xc1, 0x2b, 0xc0, 0x23, 0x70, 0xc9, 0xb3, 0x71, 0xce, 0x59, 0x49, 0xeb, 0xd8, 0x75, 0x73, 0x13, 0x9f, 0xfd, 0xbe, 0xf3, 0xe9, 0xec, 0xb7, 0x67, 0xcf, 0x72, 0x61, 0xe2, 0xc2, 0xcc, 0xd4, 0xfc, 0x45, 0x7c, 0x66, 0x8a, 0x71, 0xae, 0x95, 0x51, 0xa2, 0xf3, 0xa2, 0x50, 0x59, 0x3e, 0x1f, 0xbe, 0xbb, 0x50, 0x6a, 0x91, 0xc6, 0xf7, 0x69, 0x75, 0x5e, 0x5e, 0xdc, 0x3f, 0x2f, 0x75, 0x64, 0x12, 0x95, 0x59, 0xde, 0xf0, 0x60, 0x1d, 0x2f, 0x8c, 0x2e, 0xcf, 0x4c, 0x85, 0xbe, 0xb7, 0x8e, 0x9a, 0x64, 0x09, 0xdf, 0x8a, 0x96, 0x79, 0x45, 0xd8, 0x90, 0xbf, 0xd4, 0x51, 0x9e, 0xc7, 0xba, 0x2a, 0x63, 0xf4, 0xb7, 0xc7, 0x3b, 0x27, 0xc9, 0x32, 0x4f, 0x63, 0x71, 0x93, 0x77, 0xd4, 0x6c, 0xae, 0x54, 0x1a, 0xb6, 0xee, 0xb4, 0x3e, 0xea, 0x4a, 0x5f, 0x1d, 0x42, 0x20, 0x6e, 0xf1, 0x40, 0xcd, 0x92, 0xcc, 0x3c, 0x98, 0x84, 0x1e, 0xac, 0xfb, 0xb2, 0xa3, 0xbe, 0xc7, 0xa8, 0x01, 0x1e, 0x3d, 0x0c, 0x19, 0x00, 0xcc, 0x02, 0x8f, 0x1e, 0x8a, 0xdb, 0xbc, 0xab, 0x66, 0xa5, 0x4d, 0x69, 0x03, 0xb2, 0x2b, 0x03, 0x75, 0x4a, 0xa1, 0x83, 0x20, 0xc9, 0x07, 0xa8, 0x5d, 0x41, 0x75, 0x56, 0x61, 0xb3, 0x3a, 0x00, 0xbd, 0x09, 0xd0, 0xc9, 0x4a, 0x56, 0x61, 0xb3, 0x02, 0x80, 0x44, 0x05, 0x41, 0x16, 0x15, 0x71, 0x91, 0xaa, 0xc8, 0x84, 0x5d, 0x40, 0x3c, 0x28, 0xe2, 0x1b, 0x8c, 0x6c, 0xce, 0xb9, 0x2a, 0xe7, 0x69, 0x1c, 0xf6, 0x00, 0x69, 0x41, 0xce, 0x11, 0x85, 0x95, 0x9c, 0xd1, 0x49, 0xb6, 0x08, 0x39, 0x40, 0x3d, 0x94, 0xa3, 0xd0, 0xca, 0xcd, 0xaf, 0xe0, 0xbc, 0xc2, 0x3e, 0x20, 0x3b, 0x20, 0x77, 0x88, 0xd1, 0xe8, 0x1f, 0x8f, 0x07, 0x32, 0xce, 0xe3, 0xc8, 0x14, 0x68, 0x94, 0xae, 0x8d, 0x62, 0x68, 0x94, 0xae, 0x8d, 0xd2, 0x8d, 0x51, 0x0c, 0x8d, 0xd2, 0x8d, 0x51, 0xba, 0x31, 0x8a, 0xa1, 0x51, 0xba, 0x31, 0x4a, 0x3b, 0xa3, 0x18, 0x1a, 0xa5, 0x9d, 0x51, 0xda, 0x19, 0xc5, 0xd0, 0x28, 0xed, 0x8c, 0xd2, 0xce, 0x28, 0x86, 0x46, 0xe9, 0x93, 0x95, 0xac, 0xc6, 0x28, 0x86, 0x46, 0x69, 0x67, 0x94, 0x6e, 0x8c, 0x62, 0x68, 0x94, 0x6e, 0x8c, 0xd2, 0xce, 0x28, 0x86, 0x46, 0x69, 0x67, 0x94, 0x76, 0x46, 0x31, 0x34, 0x4a, 0x3b, 0xa3, 0x74, 0x63, 0x14, 0x43, 0xa3, 0xb4, 0x35, 0xea, 0x5f, 0x68, 0xa8, 0xe7, 0xc9, 0xf9, 0x22, 0x36, 0xe2, 0x1e, 0xf7, 0xcf, 0x54, 0xaa, 0x34, 0xf5, 0xd3, 0xde, 0x64, 0x7f, 0x6c, 0x5b, 0x7e, 0x6c, 0xe1, 0xf1, 0x13, 0xc4, 0xa4, 0xa5, 0x88, 0xcf, 0x50, 0xcf, 0xb2, 0xd1, 0xbc, 0x6d, 0xec, 0x8e, 0xa6, 0xff, 0xe2, 0x2e, 0xef, 0x14, 0xd4, 0xb5, 0x74, 0x80, 0xfd, 0xc9, 0x5e, 0xcd, 0xb6, 0xbd, 0x2c, 0x2b, 0x54, 0x7c, 0x6c, 0x0d, 0x21, 0x26, 0xd6, 0xb9, 0xc9, 0x44, 0x83, 0x2a, 0x6a, 0xa0, 0xed, 0x01, 0x87, 0xfb, 0xa4, 0xf9, 0x46, 0xcd, 0xac, 0xce, 0x5d, 0xd6, 0xb8, 0xf8, 0x94, 0xf7, 0xf4, 0xac, 0x26, 0xdf, 0x24, 0xd9, 0x0d, 0x72, 0x57, 0x57, 0xbf, 0x46, 0x1f, 0x70, 0xdf, 0x16, 0x1d, 0x70, 0x26, 0xa7, 0x47, 0x83, 0x1b, 0xa2, 0xc7, 0xfd, 0x6f, 0xe5, 0x74, 0xfa, 0x74, 0xd0, 0x12, 0x5d, 0xde, 0x3e, 0xfc, 0xf1, 0x74, 0x3a, 0xf0, 0x46, 0x7f, 0x79, 0xbc, 0x7d, 0x1c, 0xe5, 0x85, 0xf8, 0x92, 0xf7, 0x97, 0xb6, 0x5d, 0xd0, 0x7b, 0xea, 0xb1, 0xfe, 0xe4, 0xed, 0x5a, 0x1f, 0x29, 0xe3, 0x63, 0xea, 0x1f, 0x38, 0x8a, 0x69, 0x66, 0xf4, 0x95, 0xec, 0x2d, 0xeb, 0x58, 0x7c, 0xcd, 0x77, 0x97, 0xd4, 0x9b, 0xf5, 0xae, 0x3d, 0x4a, 0x7f, 0xe7, 0x7a, 0x3a, 0xf6, 0xab, 0xdd, 0xb6, 0x15, 0xe8, 0x2f, 0xdd, 0xca, 0xf0, 0x2b, 0xbe, 0x77, 0x5d, 0x5f, 0x0c, 0x38, 0xfb, 0x35, 0xbe, 0xa2, 0x63, 0x64, 0x12, 0x7f, 0x8a, 0x7d, 0xee, 0xff, 0x16, 0xa5, 0x65, 0x4c, 0x23, 0xa1, 0x27, 0x6d, 0xf0, 0xd8, 0xfb, 0xa2, 0x35, 0x7c, 0xca, 0x07, 0xeb, 0xf2, 0xab, 0xf9, 0x5d, 0x9b, 0xff, 0xfe, 0x6a, 0xfe, 0xe6, 0xa1, 0x38, 0xbd, 0x51, 0xcc, 0x77, 0x8e, 0x8b, 0xc5, 0xf3, 0xc4, 0xfc, 0xf2, 0x53, 0x16, 0xab, 0x0b, 0xf1, 0x16, 0xf7, 0x4d, 0x62, 0x60, 0x63, 0xa8, 0xd6, 0xfb, 0xee, 0x86, 0xb4, 0xa1, 0x08, 0xa1, 0x23, 0xa2, 0x34, 0xd2, 0x57, 0x24, 0xc9, 0x00, 0xa8, 0x62, 0x31, 0xe4, 0xc1, 0x13, 0x55, 0x62, 0x21, 0x34, 0xa7, 0x30, 0x27, 0x38, 0xb3, 0x0b, 0x87, 0x01, 0xf7, 0xcb, 0x0c, 0x86, 0xed, 0xe8, 0x2e, 0x6f, 0xcb, 0x38, 0x4a, 0xdd, 0xc6, 0x5a, 0x34, 0x33, 0x6c, 0x70, 0xaf, 0xdb, 0x3d, 0x1f, 0xfc, 0x09, 0x7f, 0xde, 0xe8, 0x12, 0xc5, 0xb0, 0xc6, 0x97, 0xe2, 0x80, 0xf7, 0x92, 0x65, 0xb4, 0x48, 0x32, 0xfc, 0xa8, 0xa5, 0xbb, 0x05, 0x97, 0x32, 0x39, 0xe2, 0x7b, 0x1a, 0xa4, 0x67, 0xf1, 0x4b, 0x13, 0x67, 0x05, 0x7c, 0x4c, 0xec, 0xb8, 0x66, 0x89, 0xd2, 0xf0, 0xf7, 0xeb, 0xdd, 0x56, 0xc9, 0xcb, 0x5d, 0x4c, 0x9a, 0xd6, 0x39, 0xa3, 0xff, 0xda, 0x9c, 0xff, 0x90, 0xa9, 0xcb, 0xec, 0xd9, 0x55, 0x1e, 0x17, 0xe2, 0x13, 0xce, 0xe0, 0xa1, 0xa0, 0xcf, 0xf6, 0x27, 0xb7, 0xc7, 0x76, 0xca, 0x8f, 0xeb, 0x29, 0x3f, 0x3e, 0xaa, 0x1e, 0x11, 0x89, 0x2c, 0xf1, 0x21, 0xf7, 0x0a, 0x13, 0xee, 0x10, 0xf7, 0xd6, 0x06, 0xf7, 0x84, 0x1e, 0x14, 0x09, 0x14, 0xb8, 0xb1, 0x1e, 0x74, 0xb4, 0x3d, 0x93, 0xe1, 0x06, 0xf1, 0x59, 0xfd, 0xb6, 0x48, 0x60, 0x89, 0x31, 0x54, 0x30, 0x4f, 0xc9, 0xd2, 0xfe, 0xe4, 0x60, 0xb3, 0x02, 0x1a, 0x21, 0x3f, 0xa3, 0x7d, 0x12, 0x89, 0x70, 0xc3, 0xd9, 0x45, 0x6a, 0xe8, 0x41, 0xc0, 0x76, 0x5e, 0xe7, 0xd3, 0x30, 0xaa, 0xe8, 0xc0, 0x43, 0x7a, 0x52, 0x3d, 0x12, 0xaf, 0xa2, 0x53, 0x83, 0x56, 0x74, 0xe0, 0x61, 0x35, 0x25, 0xd0, 0x3b, 0x5b, 0xaa, 0x39, 0x5d, 0xe5, 0x03, 0x91, 0xe4, 0x61, 0x7e, 0x06, 0xdb, 0xe5, 0x1f, 0x4c, 0x6a, 0x79, 0x18, 0xac, 0x28, 0x0f, 0xf4, 0xee, 0x6b, 0xe4, 0x1b, 0x7e, 0x49, 0xfc, 0x36, 0x3d, 0x10, 0xbd, 0x2d, 0x56, 0xe2, 0x0d, 0xb1, 0x74, 0xe2, 0xa1, 0x3e, 0xde, 0x75, 0xbe, 0x45, 0xdf, 0x0e, 0xdd, 0x4a, 0x1f, 0x88, 0xe2, 0x73, 0xee, 0xbb, 0x57, 0xea, 0x55, 0x1b, 0xa0, 0x61, 0x6c, 0x13, 0x2c, 0xf3, 0xf1, 0x1d, 0xde, 0xce, 0xa2, 0x65, 0xbc, 0xd6, 0x7c, 0x7f, 0xd0, 0xfd, 0x25, 0xe4, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x39, 0x6b, 0x15, 0x0e, 0xa7, 0x08, 0x00, 0x00, } lxd-2.0.0/dist/src/github.com/golang/protobuf/jsonpb/jsonpb_test_proto/more_test_objects.pb.go0000644061062106075000000001106012702772352035324 0ustar00stgraberdomain admins00000000000000// Code generated by protoc-gen-go. // source: more_test_objects.proto // DO NOT EDIT! /* Package jsonpb is a generated protocol buffer package. It is generated from these files: more_test_objects.proto test_objects.proto It has these top-level messages: Simple3 Mappy Simple Repeats Widget Maps MsgWithOneof Real Complex KnownTypes */ package jsonpb import proto "github.com/golang/protobuf/proto" import fmt "fmt" import math "math" // Reference imports to suppress errors if they are not otherwise used. var _ = proto.Marshal var _ = fmt.Errorf var _ = math.Inf // This is a compile-time assertion to ensure that this generated file // is compatible with the proto package it is being compiled against. const _ = proto.ProtoPackageIsVersion1 type Simple3 struct { Dub float64 `protobuf:"fixed64,1,opt,name=dub" json:"dub,omitempty"` } func (m *Simple3) Reset() { *m = Simple3{} } func (m *Simple3) String() string { return proto.CompactTextString(m) } func (*Simple3) ProtoMessage() {} func (*Simple3) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } type Mappy struct { Nummy map[int64]int32 `protobuf:"bytes,1,rep,name=nummy" json:"nummy,omitempty" protobuf_key:"varint,1,opt,name=key" protobuf_val:"varint,2,opt,name=value"` Strry map[string]string `protobuf:"bytes,2,rep,name=strry" json:"strry,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` Objjy map[int32]*Simple3 `protobuf:"bytes,3,rep,name=objjy" json:"objjy,omitempty" protobuf_key:"varint,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` Buggy map[int64]string `protobuf:"bytes,4,rep,name=buggy" json:"buggy,omitempty" protobuf_key:"varint,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` Booly map[bool]bool `protobuf:"bytes,5,rep,name=booly" json:"booly,omitempty" protobuf_key:"varint,1,opt,name=key" protobuf_val:"varint,2,opt,name=value"` } func (m *Mappy) Reset() { *m = Mappy{} } func (m *Mappy) String() string { return proto.CompactTextString(m) } func (*Mappy) ProtoMessage() {} func (*Mappy) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } func (m *Mappy) GetNummy() map[int64]int32 { if m != nil { return m.Nummy } return nil } func (m *Mappy) GetStrry() map[string]string { if m != nil { return m.Strry } return nil } func (m *Mappy) GetObjjy() map[int32]*Simple3 { if m != nil { return m.Objjy } return nil } func (m *Mappy) GetBuggy() map[int64]string { if m != nil { return m.Buggy } return nil } func (m *Mappy) GetBooly() map[bool]bool { if m != nil { return m.Booly } return nil } func init() { proto.RegisterType((*Simple3)(nil), "jsonpb.Simple3") proto.RegisterType((*Mappy)(nil), "jsonpb.Mappy") } var fileDescriptor0 = []byte{ // 288 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x84, 0x92, 0x41, 0x4b, 0xc3, 0x30, 0x14, 0xc7, 0xe9, 0xba, 0xcc, 0xf5, 0xed, 0xa0, 0x14, 0xc1, 0xa0, 0x17, 0x19, 0x08, 0x3d, 0xe5, 0xb0, 0x5d, 0x86, 0x47, 0xc1, 0x83, 0x07, 0x15, 0xba, 0x0f, 0x30, 0x16, 0x0d, 0xc3, 0xda, 0x36, 0x21, 0x4d, 0x85, 0x7c, 0x25, 0x3f, 0xa5, 0x7d, 0x69, 0x67, 0xc3, 0x08, 0xec, 0xf6, 0xca, 0xff, 0xf7, 0x83, 0xf7, 0x7f, 0x0d, 0xdc, 0x54, 0x52, 0x8b, 0x9d, 0x11, 0x8d, 0xd9, 0x49, 0x5e, 0x88, 0x0f, 0xd3, 0x30, 0xa5, 0xa5, 0x91, 0xe9, 0xac, 0x68, 0x64, 0xad, 0xf8, 0xf2, 0x0e, 0x2e, 0xb6, 0x5f, 0x95, 0x2a, 0xc5, 0x3a, 0xbd, 0x82, 0xf8, 0xb3, 0xe5, 0x34, 0xba, 0x8f, 0xb2, 0x28, 0xc7, 0x71, 0xf9, 0x3b, 0x05, 0xf2, 0xba, 0x57, 0xca, 0xa6, 0x0c, 0x48, 0xdd, 0x56, 0x95, 0xed, 0xd2, 0x38, 0x5b, 0xac, 0x28, 0xeb, 0x75, 0xe6, 0x52, 0xf6, 0x86, 0xd1, 0x73, 0x6d, 0xb4, 0xcd, 0x7b, 0x0c, 0xf9, 0xc6, 0x68, 0x6d, 0xe9, 0x24, 0xc4, 0x6f, 0x31, 0x1a, 0x78, 0x87, 0x21, 0xdf, 0xed, 0x57, 0x58, 0x1a, 0x87, 0xf8, 0x77, 0x8c, 0x06, 0xde, 0x61, 0xc8, 0xf3, 0xf6, 0x70, 0xb0, 0x74, 0x1a, 0xe2, 0x9f, 0x30, 0x1a, 0x78, 0x87, 0x39, 0x5e, 0xca, 0xd2, 0x52, 0x12, 0xe4, 0x31, 0x3a, 0xf2, 0x38, 0xdf, 0x6e, 0x00, 0xc6, 0x52, 0x78, 0x99, 0x6f, 0x61, 0xdd, 0x65, 0xe2, 0x1c, 0xc7, 0xf4, 0x1a, 0xc8, 0xcf, 0xbe, 0x6c, 0x45, 0xd7, 0x2f, 0xca, 0x48, 0xde, 0x7f, 0x3c, 0x4e, 0x36, 0x11, 0x9a, 0x63, 0x3d, 0xdf, 0x4c, 0x02, 0x66, 0xe2, 0x9b, 0x2f, 0x00, 0x63, 0x51, 0xdf, 0x24, 0xbd, 0xf9, 0xe0, 0x9b, 0x8b, 0xd5, 0xe5, 0xb1, 0xc3, 0xf0, 0xff, 0x4e, 0x96, 0x18, 0x6f, 0x70, 0x6e, 0xfd, 0xe4, 0xd4, 0xfc, 0xbf, 0x86, 0x6f, 0xce, 0x03, 0xe6, 0xdc, 0x33, 0xf9, 0xcc, 0x3d, 0xac, 0xf5, 0x5f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x39, 0x61, 0xe7, 0x9b, 0x73, 0x02, 0x00, 0x00, } lxd-2.0.0/dist/src/github.com/golang/protobuf/jsonpb/jsonpb_test_proto/test_objects.proto0000644061062106075000000000775412702772352034457 0ustar00stgraberdomain admins00000000000000// Go support for Protocol Buffers - Google's data interchange format // // Copyright 2015 The Go Authors. All rights reserved. // https://github.com/golang/protobuf // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. syntax = "proto2"; import "google/protobuf/duration.proto"; import "google/protobuf/struct.proto"; import "google/protobuf/timestamp.proto"; import "google/protobuf/wrappers.proto"; package jsonpb; // Test message for holding primitive types. message Simple { optional bool o_bool = 1; optional int32 o_int32 = 2; optional int64 o_int64 = 3; optional uint32 o_uint32 = 4; optional uint64 o_uint64 = 5; optional sint32 o_sint32 = 6; optional sint64 o_sint64 = 7; optional float o_float = 8; optional double o_double = 9; optional string o_string = 10; optional bytes o_bytes = 11; } // Test message for holding repeated primitives. message Repeats { repeated bool r_bool = 1; repeated int32 r_int32 = 2; repeated int64 r_int64 = 3; repeated uint32 r_uint32 = 4; repeated uint64 r_uint64 = 5; repeated sint32 r_sint32 = 6; repeated sint64 r_sint64 = 7; repeated float r_float = 8; repeated double r_double = 9; repeated string r_string = 10; repeated bytes r_bytes = 11; } // Test message for holding enums and nested messages. message Widget { enum Color { RED = 0; GREEN = 1; BLUE = 2; }; optional Color color = 1; repeated Color r_color = 2; optional Simple simple = 10; repeated Simple r_simple = 11; optional Repeats repeats = 20; repeated Repeats r_repeats = 21; } message Maps { map m_int64_str = 1; map m_bool_simple = 2; } message MsgWithOneof { oneof union { string title = 1; int64 salary = 2; string Country = 3; } } message Real { optional double value = 1; extensions 100 to max; } extend Real { optional string name = 124; } message Complex { extend Real { optional Complex real_extension = 123; } optional double imaginary = 1; extensions 100 to max; } message KnownTypes { optional google.protobuf.Duration dur = 1; optional google.protobuf.Struct st = 12; optional google.protobuf.Timestamp ts = 2; optional google.protobuf.DoubleValue dbl = 3; optional google.protobuf.FloatValue flt = 4; optional google.protobuf.Int64Value i64 = 5; optional google.protobuf.UInt64Value u64 = 6; optional google.protobuf.Int32Value i32 = 7; optional google.protobuf.UInt32Value u32 = 8; optional google.protobuf.BoolValue bool = 9; optional google.protobuf.StringValue str = 10; optional google.protobuf.BytesValue bytes = 11; } lxd-2.0.0/dist/src/github.com/golang/protobuf/jsonpb/jsonpb_test_proto/Makefile0000644061062106075000000000367012702772352032333 0ustar00stgraberdomain admins00000000000000# Go support for Protocol Buffers - Google's data interchange format # # Copyright 2015 The Go Authors. All rights reserved. # https://github.com/golang/protobuf # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. regenerate: protoc --go_out=Mgoogle/protobuf/duration.proto=github.com/golang/protobuf/ptypes/duration,Mgoogle/protobuf/struct.proto=github.com/golang/protobuf/ptypes/struct,Mgoogle/protobuf/timestamp.proto=github.com/golang/protobuf/ptypes/timestamp,Mgoogle/protobuf/wrappers.proto=github.com/golang/protobuf/ptypes/wrappers:. *.proto lxd-2.0.0/dist/src/github.com/golang/protobuf/jsonpb/jsonpb_test.go0000644061062106075000000003760712702772352030006 0ustar00stgraberdomain admins00000000000000// Go support for Protocol Buffers - Google's data interchange format // // Copyright 2015 The Go Authors. All rights reserved. // https://github.com/golang/protobuf // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package jsonpb import ( "bytes" "encoding/json" "io" "reflect" "testing" "github.com/golang/protobuf/proto" pb "github.com/golang/protobuf/jsonpb/jsonpb_test_proto" proto3pb "github.com/golang/protobuf/proto/proto3_proto" durpb "github.com/golang/protobuf/ptypes/duration" stpb "github.com/golang/protobuf/ptypes/struct" tspb "github.com/golang/protobuf/ptypes/timestamp" wpb "github.com/golang/protobuf/ptypes/wrappers" ) var ( marshaler = Marshaler{} marshalerAllOptions = Marshaler{ Indent: " ", } simpleObject = &pb.Simple{ OInt32: proto.Int32(-32), OInt64: proto.Int64(-6400000000), OUint32: proto.Uint32(32), OUint64: proto.Uint64(6400000000), OSint32: proto.Int32(-13), OSint64: proto.Int64(-2600000000), OFloat: proto.Float32(3.14), ODouble: proto.Float64(6.02214179e23), OBool: proto.Bool(true), OString: proto.String("hello \"there\""), OBytes: []byte("beep boop"), } simpleObjectJSON = `{` + `"oBool":true,` + `"oInt32":-32,` + `"oInt64":"-6400000000",` + `"oUint32":32,` + `"oUint64":"6400000000",` + `"oSint32":-13,` + `"oSint64":"-2600000000",` + `"oFloat":3.14,` + `"oDouble":6.02214179e+23,` + `"oString":"hello \"there\"",` + `"oBytes":"YmVlcCBib29w"` + `}` simpleObjectPrettyJSON = `{ "oBool": true, "oInt32": -32, "oInt64": "-6400000000", "oUint32": 32, "oUint64": "6400000000", "oSint32": -13, "oSint64": "-2600000000", "oFloat": 3.14, "oDouble": 6.02214179e+23, "oString": "hello \"there\"", "oBytes": "YmVlcCBib29w" }` repeatsObject = &pb.Repeats{ RBool: []bool{true, false, true}, RInt32: []int32{-3, -4, -5}, RInt64: []int64{-123456789, -987654321}, RUint32: []uint32{1, 2, 3}, RUint64: []uint64{6789012345, 3456789012}, RSint32: []int32{-1, -2, -3}, RSint64: []int64{-6789012345, -3456789012}, RFloat: []float32{3.14, 6.28}, RDouble: []float64{299792458, 6.62606957e-34}, RString: []string{"happy", "days"}, RBytes: [][]byte{[]byte("skittles"), []byte("m&m's")}, } repeatsObjectJSON = `{` + `"rBool":[true,false,true],` + `"rInt32":[-3,-4,-5],` + `"rInt64":["-123456789","-987654321"],` + `"rUint32":[1,2,3],` + `"rUint64":["6789012345","3456789012"],` + `"rSint32":[-1,-2,-3],` + `"rSint64":["-6789012345","-3456789012"],` + `"rFloat":[3.14,6.28],` + `"rDouble":[2.99792458e+08,6.62606957e-34],` + `"rString":["happy","days"],` + `"rBytes":["c2tpdHRsZXM=","bSZtJ3M="]` + `}` repeatsObjectPrettyJSON = `{ "rBool": [ true, false, true ], "rInt32": [ -3, -4, -5 ], "rInt64": [ "-123456789", "-987654321" ], "rUint32": [ 1, 2, 3 ], "rUint64": [ "6789012345", "3456789012" ], "rSint32": [ -1, -2, -3 ], "rSint64": [ "-6789012345", "-3456789012" ], "rFloat": [ 3.14, 6.28 ], "rDouble": [ 2.99792458e+08, 6.62606957e-34 ], "rString": [ "happy", "days" ], "rBytes": [ "c2tpdHRsZXM=", "bSZtJ3M=" ] }` innerSimple = &pb.Simple{OInt32: proto.Int32(-32)} innerSimple2 = &pb.Simple{OInt64: proto.Int64(25)} innerRepeats = &pb.Repeats{RString: []string{"roses", "red"}} innerRepeats2 = &pb.Repeats{RString: []string{"violets", "blue"}} complexObject = &pb.Widget{ Color: pb.Widget_GREEN.Enum(), RColor: []pb.Widget_Color{pb.Widget_RED, pb.Widget_GREEN, pb.Widget_BLUE}, Simple: innerSimple, RSimple: []*pb.Simple{innerSimple, innerSimple2}, Repeats: innerRepeats, RRepeats: []*pb.Repeats{innerRepeats, innerRepeats2}, } complexObjectJSON = `{"color":"GREEN",` + `"rColor":["RED","GREEN","BLUE"],` + `"simple":{"oInt32":-32},` + `"rSimple":[{"oInt32":-32},{"oInt64":"25"}],` + `"repeats":{"rString":["roses","red"]},` + `"rRepeats":[{"rString":["roses","red"]},{"rString":["violets","blue"]}]` + `}` complexObjectPrettyJSON = `{ "color": "GREEN", "rColor": [ "RED", "GREEN", "BLUE" ], "simple": { "oInt32": -32 }, "rSimple": [ { "oInt32": -32 }, { "oInt64": "25" } ], "repeats": { "rString": [ "roses", "red" ] }, "rRepeats": [ { "rString": [ "roses", "red" ] }, { "rString": [ "violets", "blue" ] } ] }` colorPrettyJSON = `{ "color": 2 }` colorListPrettyJSON = `{ "color": 1000, "rColor": [ "RED" ] }` nummyPrettyJSON = `{ "nummy": { "1": 2, "3": 4 } }` objjyPrettyJSON = `{ "objjy": { "1": { "dub": 1 } } }` realNumber = &pb.Real{Value: proto.Float64(3.14159265359)} realNumberName = "Pi" complexNumber = &pb.Complex{Imaginary: proto.Float64(0.5772156649)} realNumberJSON = `{` + `"value":3.14159265359,` + `"[jsonpb.Complex.real_extension]":{"imaginary":0.5772156649},` + `"[jsonpb.name]":"Pi"` + `}` ) func init() { if err := proto.SetExtension(realNumber, pb.E_Name, &realNumberName); err != nil { panic(err) } if err := proto.SetExtension(realNumber, pb.E_Complex_RealExtension, complexNumber); err != nil { panic(err) } } var marshalingTests = []struct { desc string marshaler Marshaler pb proto.Message json string }{ {"simple flat object", marshaler, simpleObject, simpleObjectJSON}, {"simple pretty object", marshalerAllOptions, simpleObject, simpleObjectPrettyJSON}, {"repeated fields flat object", marshaler, repeatsObject, repeatsObjectJSON}, {"repeated fields pretty object", marshalerAllOptions, repeatsObject, repeatsObjectPrettyJSON}, {"nested message/enum flat object", marshaler, complexObject, complexObjectJSON}, {"nested message/enum pretty object", marshalerAllOptions, complexObject, complexObjectPrettyJSON}, {"enum-string flat object", Marshaler{}, &pb.Widget{Color: pb.Widget_BLUE.Enum()}, `{"color":"BLUE"}`}, {"enum-value pretty object", Marshaler{EnumsAsInts: true, Indent: " "}, &pb.Widget{Color: pb.Widget_BLUE.Enum()}, colorPrettyJSON}, {"unknown enum value object", marshalerAllOptions, &pb.Widget{Color: pb.Widget_Color(1000).Enum(), RColor: []pb.Widget_Color{pb.Widget_RED}}, colorListPrettyJSON}, {"empty value", marshaler, &pb.Simple3{}, `{}`}, {"empty value emitted", Marshaler{EmitDefaults: true}, &pb.Simple3{}, `{"dub":0}`}, {"map", marshaler, &pb.Mappy{Nummy: map[int64]int32{1: 2, 3: 4}}, `{"nummy":{"1":2,"3":4}}`}, {"map", marshalerAllOptions, &pb.Mappy{Nummy: map[int64]int32{1: 2, 3: 4}}, nummyPrettyJSON}, {"map", marshaler, &pb.Mappy{Strry: map[string]string{`"one"`: "two", "three": "four"}}, `{"strry":{"\"one\"":"two","three":"four"}}`}, {"map", marshaler, &pb.Mappy{Objjy: map[int32]*pb.Simple3{1: &pb.Simple3{Dub: 1}}}, `{"objjy":{"1":{"dub":1}}}`}, {"map", marshalerAllOptions, &pb.Mappy{Objjy: map[int32]*pb.Simple3{1: &pb.Simple3{Dub: 1}}}, objjyPrettyJSON}, {"map", marshaler, &pb.Mappy{Buggy: map[int64]string{1234: "yup"}}, `{"buggy":{"1234":"yup"}}`}, {"map", marshaler, &pb.Mappy{Booly: map[bool]bool{false: true}}, `{"booly":{"false":true}}`}, {"proto2 map", marshaler, &pb.Maps{MInt64Str: map[int64]string{213: "cat"}}, `{"mInt64Str":{"213":"cat"}}`}, {"proto2 map", marshaler, &pb.Maps{MBoolSimple: map[bool]*pb.Simple{true: &pb.Simple{OInt32: proto.Int32(1)}}}, `{"mBoolSimple":{"true":{"oInt32":1}}}`}, {"oneof, not set", marshaler, &pb.MsgWithOneof{}, `{}`}, {"oneof, set", marshaler, &pb.MsgWithOneof{Union: &pb.MsgWithOneof_Title{"Grand Poobah"}}, `{"title":"Grand Poobah"}`}, {"force orig_name", Marshaler{OrigName: true}, &pb.Simple{OInt32: proto.Int32(4)}, `{"o_int32":4}`}, {"proto2 extension", marshaler, realNumber, realNumberJSON}, {"Duration", marshaler, &pb.KnownTypes{Dur: &durpb.Duration{Seconds: 3}}, `{"dur":"3.000s"}`}, {"Struct", marshaler, &pb.KnownTypes{St: &stpb.Struct{ Fields: map[string]*stpb.Value{ "one": &stpb.Value{Kind: &stpb.Value_StringValue{"loneliest number"}}, "two": &stpb.Value{Kind: &stpb.Value_NullValue{stpb.NullValue_NULL_VALUE}}, }, }}, `{"st":{"one":"loneliest number","two":null}}`}, {"Timestamp", marshaler, &pb.KnownTypes{Ts: &tspb.Timestamp{Seconds: 14e8, Nanos: 21e6}}, `{"ts":"2014-05-13T16:53:20.021Z"}`}, {"DoubleValue", marshaler, &pb.KnownTypes{Dbl: &wpb.DoubleValue{Value: 1.2}}, `{"dbl":1.2}`}, {"FloatValue", marshaler, &pb.KnownTypes{Flt: &wpb.FloatValue{Value: 1.2}}, `{"flt":1.2}`}, {"Int64Value", marshaler, &pb.KnownTypes{I64: &wpb.Int64Value{Value: -3}}, `{"i64":"-3"}`}, {"UInt64Value", marshaler, &pb.KnownTypes{U64: &wpb.UInt64Value{Value: 3}}, `{"u64":"3"}`}, {"Int32Value", marshaler, &pb.KnownTypes{I32: &wpb.Int32Value{Value: -4}}, `{"i32":-4}`}, {"UInt32Value", marshaler, &pb.KnownTypes{U32: &wpb.UInt32Value{Value: 4}}, `{"u32":4}`}, {"BoolValue", marshaler, &pb.KnownTypes{Bool: &wpb.BoolValue{Value: true}}, `{"bool":true}`}, {"StringValue", marshaler, &pb.KnownTypes{Str: &wpb.StringValue{Value: "plush"}}, `{"str":"plush"}`}, {"BytesValue", marshaler, &pb.KnownTypes{Bytes: &wpb.BytesValue{Value: []byte("wow")}}, `{"bytes":"d293"}`}, } func TestMarshaling(t *testing.T) { for _, tt := range marshalingTests { json, err := tt.marshaler.MarshalToString(tt.pb) if err != nil { t.Errorf("%s: marshaling error: %v", tt.desc, err) } else if tt.json != json { t.Errorf("%s: got [%v] want [%v]", tt.desc, json, tt.json) } } } var unmarshalingTests = []struct { desc string json string pb proto.Message }{ {"simple flat object", simpleObjectJSON, simpleObject}, {"simple pretty object", simpleObjectPrettyJSON, simpleObject}, {"repeated fields flat object", repeatsObjectJSON, repeatsObject}, {"repeated fields pretty object", repeatsObjectPrettyJSON, repeatsObject}, {"nested message/enum flat object", complexObjectJSON, complexObject}, {"nested message/enum pretty object", complexObjectPrettyJSON, complexObject}, {"enum-string object", `{"color":"BLUE"}`, &pb.Widget{Color: pb.Widget_BLUE.Enum()}}, {"enum-value object", "{\n \"color\": 2\n}", &pb.Widget{Color: pb.Widget_BLUE.Enum()}}, {"proto3 enum string", `{"hilarity":"PUNS"}`, &proto3pb.Message{Hilarity: proto3pb.Message_PUNS}}, {"proto3 enum value", `{"hilarity":1}`, &proto3pb.Message{Hilarity: proto3pb.Message_PUNS}}, {"unknown enum value object", "{\n \"color\": 1000,\n \"r_color\": [\n \"RED\"\n ]\n}", &pb.Widget{Color: pb.Widget_Color(1000).Enum(), RColor: []pb.Widget_Color{pb.Widget_RED}}}, {"unquoted int64 object", `{"oInt64":-314}`, &pb.Simple{OInt64: proto.Int64(-314)}}, {"unquoted uint64 object", `{"oUint64":123}`, &pb.Simple{OUint64: proto.Uint64(123)}}, {"map", `{"nummy":{"1":2,"3":4}}`, &pb.Mappy{Nummy: map[int64]int32{1: 2, 3: 4}}}, {"map", `{"strry":{"\"one\"":"two","three":"four"}}`, &pb.Mappy{Strry: map[string]string{`"one"`: "two", "three": "four"}}}, {"map", `{"objjy":{"1":{"dub":1}}}`, &pb.Mappy{Objjy: map[int32]*pb.Simple3{1: &pb.Simple3{Dub: 1}}}}, {"oneof", `{"salary":31000}`, &pb.MsgWithOneof{Union: &pb.MsgWithOneof_Salary{31000}}}, {"oneof spec name", `{"country":"Australia"}`, &pb.MsgWithOneof{Union: &pb.MsgWithOneof_Country{"Australia"}}}, {"oneof orig_name", `{"Country":"Australia"}`, &pb.MsgWithOneof{Union: &pb.MsgWithOneof_Country{"Australia"}}}, {"orig_name input", `{"o_bool":true}`, &pb.Simple{OBool: proto.Bool(true)}}, {"camelName input", `{"oBool":true}`, &pb.Simple{OBool: proto.Bool(true)}}, {"Duration", `{"dur":"3.000s"}`, &pb.KnownTypes{Dur: &durpb.Duration{Seconds: 3}}}, {"Timestamp", `{"ts":"2014-05-13T16:53:20.021Z"}`, &pb.KnownTypes{Ts: &tspb.Timestamp{Seconds: 14e8, Nanos: 21e6}}}, {"DoubleValue", `{"dbl":1.2}`, &pb.KnownTypes{Dbl: &wpb.DoubleValue{Value: 1.2}}}, {"FloatValue", `{"flt":1.2}`, &pb.KnownTypes{Flt: &wpb.FloatValue{Value: 1.2}}}, {"Int64Value", `{"i64":"-3"}`, &pb.KnownTypes{I64: &wpb.Int64Value{Value: -3}}}, {"UInt64Value", `{"u64":"3"}`, &pb.KnownTypes{U64: &wpb.UInt64Value{Value: 3}}}, {"Int32Value", `{"i32":-4}`, &pb.KnownTypes{I32: &wpb.Int32Value{Value: -4}}}, {"UInt32Value", `{"u32":4}`, &pb.KnownTypes{U32: &wpb.UInt32Value{Value: 4}}}, {"BoolValue", `{"bool":true}`, &pb.KnownTypes{Bool: &wpb.BoolValue{Value: true}}}, {"StringValue", `{"str":"plush"}`, &pb.KnownTypes{Str: &wpb.StringValue{Value: "plush"}}}, {"BytesValue", `{"bytes":"d293"}`, &pb.KnownTypes{Bytes: &wpb.BytesValue{Value: []byte("wow")}}}, // `null` is also a permissible value. Let's just test one. {"null DoubleValue", `{"dbl":null}`, &pb.KnownTypes{Dbl: &wpb.DoubleValue{}}}, } func TestUnmarshaling(t *testing.T) { for _, tt := range unmarshalingTests { // Make a new instance of the type of our expected object. p := reflect.New(reflect.TypeOf(tt.pb).Elem()).Interface().(proto.Message) err := UnmarshalString(tt.json, p) if err != nil { t.Errorf("%s: %v", tt.desc, err) continue } // For easier diffs, compare text strings of the protos. exp := proto.MarshalTextString(tt.pb) act := proto.MarshalTextString(p) if string(exp) != string(act) { t.Errorf("%s: got [%s] want [%s]", tt.desc, act, exp) } } } func TestUnmarshalNext(t *testing.T) { // Create a buffer with many concatenated JSON objects. var b bytes.Buffer for _, tt := range unmarshalingTests { b.WriteString(tt.json) } dec := json.NewDecoder(&b) for _, tt := range unmarshalingTests { // Make a new instance of the type of our expected object. p := reflect.New(reflect.TypeOf(tt.pb).Elem()).Interface().(proto.Message) err := UnmarshalNext(dec, p) if err != nil { t.Errorf("%s: %v", tt.desc, err) continue } // For easier diffs, compare text strings of the protos. exp := proto.MarshalTextString(tt.pb) act := proto.MarshalTextString(p) if string(exp) != string(act) { t.Errorf("%s: got [%s] want [%s]", tt.desc, act, exp) } } p := &pb.Simple{} err := UnmarshalNext(dec, p) if err != io.EOF { t.Errorf("eof: got %v, expected io.EOF", err) } } var unmarshalingShouldError = []struct { desc string in string pb proto.Message }{ {"a value", "666", new(pb.Simple)}, {"gibberish", "{adskja123;l23=-=", new(pb.Simple)}, {"unknown enum name", `{"hilarity":"DAVE"}`, new(proto3pb.Message)}, } func TestUnmarshalingBadInput(t *testing.T) { for _, tt := range unmarshalingShouldError { err := UnmarshalString(tt.in, tt.pb) if err == nil { t.Errorf("an error was expected when parsing %q instead of an object", tt.desc) } } } lxd-2.0.0/dist/src/github.com/golang/protobuf/proto/0000755061062106075000000000000012702772352024760 5ustar00stgraberdomain admins00000000000000lxd-2.0.0/dist/src/github.com/golang/protobuf/proto/text_test.go0000644061062106075000000002756312702772352027347 0ustar00stgraberdomain admins00000000000000// Go support for Protocol Buffers - Google's data interchange format // // Copyright 2010 The Go Authors. All rights reserved. // https://github.com/golang/protobuf // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package proto_test import ( "bytes" "errors" "io/ioutil" "math" "strings" "testing" "github.com/golang/protobuf/proto" proto3pb "github.com/golang/protobuf/proto/proto3_proto" pb "github.com/golang/protobuf/proto/testdata" ) // textMessage implements the methods that allow it to marshal and unmarshal // itself as text. type textMessage struct { } func (*textMessage) MarshalText() ([]byte, error) { return []byte("custom"), nil } func (*textMessage) UnmarshalText(bytes []byte) error { if string(bytes) != "custom" { return errors.New("expected 'custom'") } return nil } func (*textMessage) Reset() {} func (*textMessage) String() string { return "" } func (*textMessage) ProtoMessage() {} func newTestMessage() *pb.MyMessage { msg := &pb.MyMessage{ Count: proto.Int32(42), Name: proto.String("Dave"), Quote: proto.String(`"I didn't want to go."`), Pet: []string{"bunny", "kitty", "horsey"}, Inner: &pb.InnerMessage{ Host: proto.String("footrest.syd"), Port: proto.Int32(7001), Connected: proto.Bool(true), }, Others: []*pb.OtherMessage{ { Key: proto.Int64(0xdeadbeef), Value: []byte{1, 65, 7, 12}, }, { Weight: proto.Float32(6.022), Inner: &pb.InnerMessage{ Host: proto.String("lesha.mtv"), Port: proto.Int32(8002), }, }, }, Bikeshed: pb.MyMessage_BLUE.Enum(), Somegroup: &pb.MyMessage_SomeGroup{ GroupField: proto.Int32(8), }, // One normally wouldn't do this. // This is an undeclared tag 13, as a varint (wire type 0) with value 4. XXX_unrecognized: []byte{13<<3 | 0, 4}, } ext := &pb.Ext{ Data: proto.String("Big gobs for big rats"), } if err := proto.SetExtension(msg, pb.E_Ext_More, ext); err != nil { panic(err) } greetings := []string{"adg", "easy", "cow"} if err := proto.SetExtension(msg, pb.E_Greeting, greetings); err != nil { panic(err) } // Add an unknown extension. We marshal a pb.Ext, and fake the ID. b, err := proto.Marshal(&pb.Ext{Data: proto.String("3G skiing")}) if err != nil { panic(err) } b = append(proto.EncodeVarint(201<<3|proto.WireBytes), b...) proto.SetRawExtension(msg, 201, b) // Extensions can be plain fields, too, so let's test that. b = append(proto.EncodeVarint(202<<3|proto.WireVarint), 19) proto.SetRawExtension(msg, 202, b) return msg } const text = `count: 42 name: "Dave" quote: "\"I didn't want to go.\"" pet: "bunny" pet: "kitty" pet: "horsey" inner: < host: "footrest.syd" port: 7001 connected: true > others: < key: 3735928559 value: "\001A\007\014" > others: < weight: 6.022 inner: < host: "lesha.mtv" port: 8002 > > bikeshed: BLUE SomeGroup { group_field: 8 } /* 2 unknown bytes */ 13: 4 [testdata.Ext.more]: < data: "Big gobs for big rats" > [testdata.greeting]: "adg" [testdata.greeting]: "easy" [testdata.greeting]: "cow" /* 13 unknown bytes */ 201: "\t3G skiing" /* 3 unknown bytes */ 202: 19 ` func TestMarshalText(t *testing.T) { buf := new(bytes.Buffer) if err := proto.MarshalText(buf, newTestMessage()); err != nil { t.Fatalf("proto.MarshalText: %v", err) } s := buf.String() if s != text { t.Errorf("Got:\n===\n%v===\nExpected:\n===\n%v===\n", s, text) } } func TestMarshalTextCustomMessage(t *testing.T) { buf := new(bytes.Buffer) if err := proto.MarshalText(buf, &textMessage{}); err != nil { t.Fatalf("proto.MarshalText: %v", err) } s := buf.String() if s != "custom" { t.Errorf("Got %q, expected %q", s, "custom") } } func TestMarshalTextNil(t *testing.T) { want := "" tests := []proto.Message{nil, (*pb.MyMessage)(nil)} for i, test := range tests { buf := new(bytes.Buffer) if err := proto.MarshalText(buf, test); err != nil { t.Fatal(err) } if got := buf.String(); got != want { t.Errorf("%d: got %q want %q", i, got, want) } } } func TestMarshalTextUnknownEnum(t *testing.T) { // The Color enum only specifies values 0-2. m := &pb.MyMessage{Bikeshed: pb.MyMessage_Color(3).Enum()} got := m.String() const want = `bikeshed:3 ` if got != want { t.Errorf("\n got %q\nwant %q", got, want) } } func TestTextOneof(t *testing.T) { tests := []struct { m proto.Message want string }{ // zero message {&pb.Communique{}, ``}, // scalar field {&pb.Communique{Union: &pb.Communique_Number{4}}, `number:4`}, // message field {&pb.Communique{Union: &pb.Communique_Msg{ &pb.Strings{StringField: proto.String("why hello!")}, }}, `msg:`}, // bad oneof (should not panic) {&pb.Communique{Union: &pb.Communique_Msg{nil}}, `msg:/* nil */`}, } for _, test := range tests { got := strings.TrimSpace(test.m.String()) if got != test.want { t.Errorf("\n got %s\nwant %s", got, test.want) } } } func BenchmarkMarshalTextBuffered(b *testing.B) { buf := new(bytes.Buffer) m := newTestMessage() for i := 0; i < b.N; i++ { buf.Reset() proto.MarshalText(buf, m) } } func BenchmarkMarshalTextUnbuffered(b *testing.B) { w := ioutil.Discard m := newTestMessage() for i := 0; i < b.N; i++ { proto.MarshalText(w, m) } } func compact(src string) string { // s/[ \n]+/ /g; s/ $//; dst := make([]byte, len(src)) space, comment := false, false j := 0 for i := 0; i < len(src); i++ { if strings.HasPrefix(src[i:], "/*") { comment = true i++ continue } if comment && strings.HasPrefix(src[i:], "*/") { comment = false i++ continue } if comment { continue } c := src[i] if c == ' ' || c == '\n' { space = true continue } if j > 0 && (dst[j-1] == ':' || dst[j-1] == '<' || dst[j-1] == '{') { space = false } if c == '{' { space = false } if space { dst[j] = ' ' j++ space = false } dst[j] = c j++ } if space { dst[j] = ' ' j++ } return string(dst[0:j]) } var compactText = compact(text) func TestCompactText(t *testing.T) { s := proto.CompactTextString(newTestMessage()) if s != compactText { t.Errorf("Got:\n===\n%v===\nExpected:\n===\n%v\n===\n", s, compactText) } } func TestStringEscaping(t *testing.T) { testCases := []struct { in *pb.Strings out string }{ { // Test data from C++ test (TextFormatTest.StringEscape). // Single divergence: we don't escape apostrophes. &pb.Strings{StringField: proto.String("\"A string with ' characters \n and \r newlines and \t tabs and \001 slashes \\ and multiple spaces")}, "string_field: \"\\\"A string with ' characters \\n and \\r newlines and \\t tabs and \\001 slashes \\\\ and multiple spaces\"\n", }, { // Test data from the same C++ test. &pb.Strings{StringField: proto.String("\350\260\267\346\255\214")}, "string_field: \"\\350\\260\\267\\346\\255\\214\"\n", }, { // Some UTF-8. &pb.Strings{StringField: proto.String("\x00\x01\xff\x81")}, `string_field: "\000\001\377\201"` + "\n", }, } for i, tc := range testCases { var buf bytes.Buffer if err := proto.MarshalText(&buf, tc.in); err != nil { t.Errorf("proto.MarsalText: %v", err) continue } s := buf.String() if s != tc.out { t.Errorf("#%d: Got:\n%s\nExpected:\n%s\n", i, s, tc.out) continue } // Check round-trip. pb := new(pb.Strings) if err := proto.UnmarshalText(s, pb); err != nil { t.Errorf("#%d: UnmarshalText: %v", i, err) continue } if !proto.Equal(pb, tc.in) { t.Errorf("#%d: Round-trip failed:\nstart: %v\n end: %v", i, tc.in, pb) } } } // A limitedWriter accepts some output before it fails. // This is a proxy for something like a nearly-full or imminently-failing disk, // or a network connection that is about to die. type limitedWriter struct { b bytes.Buffer limit int } var outOfSpace = errors.New("proto: insufficient space") func (w *limitedWriter) Write(p []byte) (n int, err error) { var avail = w.limit - w.b.Len() if avail <= 0 { return 0, outOfSpace } if len(p) <= avail { return w.b.Write(p) } n, _ = w.b.Write(p[:avail]) return n, outOfSpace } func TestMarshalTextFailing(t *testing.T) { // Try lots of different sizes to exercise more error code-paths. for lim := 0; lim < len(text); lim++ { buf := new(limitedWriter) buf.limit = lim err := proto.MarshalText(buf, newTestMessage()) // We expect a certain error, but also some partial results in the buffer. if err != outOfSpace { t.Errorf("Got:\n===\n%v===\nExpected:\n===\n%v===\n", err, outOfSpace) } s := buf.b.String() x := text[:buf.limit] if s != x { t.Errorf("Got:\n===\n%v===\nExpected:\n===\n%v===\n", s, x) } } } func TestFloats(t *testing.T) { tests := []struct { f float64 want string }{ {0, "0"}, {4.7, "4.7"}, {math.Inf(1), "inf"}, {math.Inf(-1), "-inf"}, {math.NaN(), "nan"}, } for _, test := range tests { msg := &pb.FloatingPoint{F: &test.f} got := strings.TrimSpace(msg.String()) want := `f:` + test.want if got != want { t.Errorf("f=%f: got %q, want %q", test.f, got, want) } } } func TestRepeatedNilText(t *testing.T) { m := &pb.MessageList{ Message: []*pb.MessageList_Message{ nil, &pb.MessageList_Message{ Name: proto.String("Horse"), }, nil, }, } want := `Message Message { name: "Horse" } Message ` if s := proto.MarshalTextString(m); s != want { t.Errorf(" got: %s\nwant: %s", s, want) } } func TestProto3Text(t *testing.T) { tests := []struct { m proto.Message want string }{ // zero message {&proto3pb.Message{}, ``}, // zero message except for an empty byte slice {&proto3pb.Message{Data: []byte{}}, ``}, // trivial case {&proto3pb.Message{Name: "Rob", HeightInCm: 175}, `name:"Rob" height_in_cm:175`}, // empty map {&pb.MessageWithMap{}, ``}, // non-empty map; map format is the same as a repeated struct, // and they are sorted by key (numerically for numeric keys). { &pb.MessageWithMap{NameMapping: map[int32]string{ -1: "Negatory", 7: "Lucky", 1234: "Feist", 6345789: "Otis", }}, `name_mapping: ` + `name_mapping: ` + `name_mapping: ` + `name_mapping:`, }, // map with nil value; not well-defined, but we shouldn't crash { &pb.MessageWithMap{MsgMapping: map[int64]*pb.FloatingPoint{7: nil}}, `msg_mapping:`, }, } for _, test := range tests { got := strings.TrimSpace(test.m.String()) if got != test.want { t.Errorf("\n got %s\nwant %s", got, test.want) } } } lxd-2.0.0/dist/src/github.com/golang/protobuf/proto/text_parser_test.go0000644061062106075000000003163012702772352030711 0ustar00stgraberdomain admins00000000000000// Go support for Protocol Buffers - Google's data interchange format // // Copyright 2010 The Go Authors. All rights reserved. // https://github.com/golang/protobuf // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package proto_test import ( "math" "reflect" "testing" . "github.com/golang/protobuf/proto" proto3pb "github.com/golang/protobuf/proto/proto3_proto" . "github.com/golang/protobuf/proto/testdata" ) type UnmarshalTextTest struct { in string err string // if "", no error expected out *MyMessage } func buildExtStructTest(text string) UnmarshalTextTest { msg := &MyMessage{ Count: Int32(42), } SetExtension(msg, E_Ext_More, &Ext{ Data: String("Hello, world!"), }) return UnmarshalTextTest{in: text, out: msg} } func buildExtDataTest(text string) UnmarshalTextTest { msg := &MyMessage{ Count: Int32(42), } SetExtension(msg, E_Ext_Text, String("Hello, world!")) SetExtension(msg, E_Ext_Number, Int32(1729)) return UnmarshalTextTest{in: text, out: msg} } func buildExtRepStringTest(text string) UnmarshalTextTest { msg := &MyMessage{ Count: Int32(42), } if err := SetExtension(msg, E_Greeting, []string{"bula", "hola"}); err != nil { panic(err) } return UnmarshalTextTest{in: text, out: msg} } var unMarshalTextTests = []UnmarshalTextTest{ // Basic { in: " count:42\n name:\"Dave\" ", out: &MyMessage{ Count: Int32(42), Name: String("Dave"), }, }, // Empty quoted string { in: `count:42 name:""`, out: &MyMessage{ Count: Int32(42), Name: String(""), }, }, // Quoted string concatenation with double quotes { in: `count:42 name: "My name is "` + "\n" + `"elsewhere"`, out: &MyMessage{ Count: Int32(42), Name: String("My name is elsewhere"), }, }, // Quoted string concatenation with single quotes { in: "count:42 name: 'My name is '\n'elsewhere'", out: &MyMessage{ Count: Int32(42), Name: String("My name is elsewhere"), }, }, // Quoted string concatenations with mixed quotes { in: "count:42 name: 'My name is '\n\"elsewhere\"", out: &MyMessage{ Count: Int32(42), Name: String("My name is elsewhere"), }, }, { in: "count:42 name: \"My name is \"\n'elsewhere'", out: &MyMessage{ Count: Int32(42), Name: String("My name is elsewhere"), }, }, // Quoted string with escaped apostrophe { in: `count:42 name: "HOLIDAY - New Year\'s Day"`, out: &MyMessage{ Count: Int32(42), Name: String("HOLIDAY - New Year's Day"), }, }, // Quoted string with single quote { in: `count:42 name: 'Roger "The Ramster" Ramjet'`, out: &MyMessage{ Count: Int32(42), Name: String(`Roger "The Ramster" Ramjet`), }, }, // Quoted string with all the accepted special characters from the C++ test { in: `count:42 name: ` + "\"\\\"A string with \\' characters \\n and \\r newlines and \\t tabs and \\001 slashes \\\\ and multiple spaces\"", out: &MyMessage{ Count: Int32(42), Name: String("\"A string with ' characters \n and \r newlines and \t tabs and \001 slashes \\ and multiple spaces"), }, }, // Quoted string with quoted backslash { in: `count:42 name: "\\'xyz"`, out: &MyMessage{ Count: Int32(42), Name: String(`\'xyz`), }, }, // Quoted string with UTF-8 bytes. { in: "count:42 name: '\303\277\302\201\xAB'", out: &MyMessage{ Count: Int32(42), Name: String("\303\277\302\201\xAB"), }, }, // Bad quoted string { in: `inner: < host: "\0" >` + "\n", err: `line 1.15: invalid quoted string "\0": \0 requires 2 following digits`, }, // Number too large for int64 { in: "count: 1 others { key: 123456789012345678901 }", err: "line 1.23: invalid int64: 123456789012345678901", }, // Number too large for int32 { in: "count: 1234567890123", err: "line 1.7: invalid int32: 1234567890123", }, // Number in hexadecimal { in: "count: 0x2beef", out: &MyMessage{ Count: Int32(0x2beef), }, }, // Number in octal { in: "count: 024601", out: &MyMessage{ Count: Int32(024601), }, }, // Floating point number with "f" suffix { in: "count: 4 others:< weight: 17.0f >", out: &MyMessage{ Count: Int32(4), Others: []*OtherMessage{ { Weight: Float32(17), }, }, }, }, // Floating point positive infinity { in: "count: 4 bigfloat: inf", out: &MyMessage{ Count: Int32(4), Bigfloat: Float64(math.Inf(1)), }, }, // Floating point negative infinity { in: "count: 4 bigfloat: -inf", out: &MyMessage{ Count: Int32(4), Bigfloat: Float64(math.Inf(-1)), }, }, // Number too large for float32 { in: "others:< weight: 12345678901234567890123456789012345678901234567890 >", err: "line 1.17: invalid float32: 12345678901234567890123456789012345678901234567890", }, // Number posing as a quoted string { in: `inner: < host: 12 >` + "\n", err: `line 1.15: invalid string: 12`, }, // Quoted string posing as int32 { in: `count: "12"`, err: `line 1.7: invalid int32: "12"`, }, // Quoted string posing a float32 { in: `others:< weight: "17.4" >`, err: `line 1.17: invalid float32: "17.4"`, }, // Enum { in: `count:42 bikeshed: BLUE`, out: &MyMessage{ Count: Int32(42), Bikeshed: MyMessage_BLUE.Enum(), }, }, // Repeated field { in: `count:42 pet: "horsey" pet:"bunny"`, out: &MyMessage{ Count: Int32(42), Pet: []string{"horsey", "bunny"}, }, }, // Repeated field with list notation { in: `count:42 pet: ["horsey", "bunny"]`, out: &MyMessage{ Count: Int32(42), Pet: []string{"horsey", "bunny"}, }, }, // Repeated message with/without colon and <>/{} { in: `count:42 others:{} others{} others:<> others:{}`, out: &MyMessage{ Count: Int32(42), Others: []*OtherMessage{ {}, {}, {}, {}, }, }, }, // Missing colon for inner message { in: `count:42 inner < host: "cauchy.syd" >`, out: &MyMessage{ Count: Int32(42), Inner: &InnerMessage{ Host: String("cauchy.syd"), }, }, }, // Missing colon for string field { in: `name "Dave"`, err: `line 1.5: expected ':', found "\"Dave\""`, }, // Missing colon for int32 field { in: `count 42`, err: `line 1.6: expected ':', found "42"`, }, // Missing required field { in: `name: "Pawel"`, err: `proto: required field "testdata.MyMessage.count" not set`, out: &MyMessage{ Name: String("Pawel"), }, }, // Repeated non-repeated field { in: `name: "Rob" name: "Russ"`, err: `line 1.12: non-repeated field "name" was repeated`, }, // Group { in: `count: 17 SomeGroup { group_field: 12 }`, out: &MyMessage{ Count: Int32(17), Somegroup: &MyMessage_SomeGroup{ GroupField: Int32(12), }, }, }, // Semicolon between fields { in: `count:3;name:"Calvin"`, out: &MyMessage{ Count: Int32(3), Name: String("Calvin"), }, }, // Comma between fields { in: `count:4,name:"Ezekiel"`, out: &MyMessage{ Count: Int32(4), Name: String("Ezekiel"), }, }, // Extension buildExtStructTest(`count: 42 [testdata.Ext.more]:`), buildExtStructTest(`count: 42 [testdata.Ext.more] {data:"Hello, world!"}`), buildExtDataTest(`count: 42 [testdata.Ext.text]:"Hello, world!" [testdata.Ext.number]:1729`), buildExtRepStringTest(`count: 42 [testdata.greeting]:"bula" [testdata.greeting]:"hola"`), // Big all-in-one { in: "count:42 # Meaning\n" + `name:"Dave" ` + `quote:"\"I didn't want to go.\"" ` + `pet:"bunny" ` + `pet:"kitty" ` + `pet:"horsey" ` + `inner:<` + ` host:"footrest.syd" ` + ` port:7001 ` + ` connected:true ` + `> ` + `others:<` + ` key:3735928559 ` + ` value:"\x01A\a\f" ` + `> ` + `others:<` + " weight:58.9 # Atomic weight of Co\n" + ` inner:<` + ` host:"lesha.mtv" ` + ` port:8002 ` + ` >` + `>`, out: &MyMessage{ Count: Int32(42), Name: String("Dave"), Quote: String(`"I didn't want to go."`), Pet: []string{"bunny", "kitty", "horsey"}, Inner: &InnerMessage{ Host: String("footrest.syd"), Port: Int32(7001), Connected: Bool(true), }, Others: []*OtherMessage{ { Key: Int64(3735928559), Value: []byte{0x1, 'A', '\a', '\f'}, }, { Weight: Float32(58.9), Inner: &InnerMessage{ Host: String("lesha.mtv"), Port: Int32(8002), }, }, }, }, }, } func TestUnmarshalText(t *testing.T) { for i, test := range unMarshalTextTests { pb := new(MyMessage) err := UnmarshalText(test.in, pb) if test.err == "" { // We don't expect failure. if err != nil { t.Errorf("Test %d: Unexpected error: %v", i, err) } else if !reflect.DeepEqual(pb, test.out) { t.Errorf("Test %d: Incorrect populated \nHave: %v\nWant: %v", i, pb, test.out) } } else { // We do expect failure. if err == nil { t.Errorf("Test %d: Didn't get expected error: %v", i, test.err) } else if err.Error() != test.err { t.Errorf("Test %d: Incorrect error.\nHave: %v\nWant: %v", i, err.Error(), test.err) } else if _, ok := err.(*RequiredNotSetError); ok && test.out != nil && !reflect.DeepEqual(pb, test.out) { t.Errorf("Test %d: Incorrect populated \nHave: %v\nWant: %v", i, pb, test.out) } } } } func TestUnmarshalTextCustomMessage(t *testing.T) { msg := &textMessage{} if err := UnmarshalText("custom", msg); err != nil { t.Errorf("Unexpected error from custom unmarshal: %v", err) } if UnmarshalText("not custom", msg) == nil { t.Errorf("Didn't get expected error from custom unmarshal") } } // Regression test; this caused a panic. func TestRepeatedEnum(t *testing.T) { pb := new(RepeatedEnum) if err := UnmarshalText("color: RED", pb); err != nil { t.Fatal(err) } exp := &RepeatedEnum{ Color: []RepeatedEnum_Color{RepeatedEnum_RED}, } if !Equal(pb, exp) { t.Errorf("Incorrect populated \nHave: %v\nWant: %v", pb, exp) } } func TestProto3TextParsing(t *testing.T) { m := new(proto3pb.Message) const in = `name: "Wallace" true_scotsman: true` want := &proto3pb.Message{ Name: "Wallace", TrueScotsman: true, } if err := UnmarshalText(in, m); err != nil { t.Fatal(err) } if !Equal(m, want) { t.Errorf("\n got %v\nwant %v", m, want) } } func TestMapParsing(t *testing.T) { m := new(MessageWithMap) const in = `name_mapping: name_mapping:` + `msg_mapping:,>` + // separating commas are okay `msg_mapping>` + // no colon after "value" `byte_mapping:` want := &MessageWithMap{ NameMapping: map[int32]string{ 1: "Beatles", 1234: "Feist", }, MsgMapping: map[int64]*FloatingPoint{ -4: {F: Float64(2.0)}, -2: {F: Float64(4.0)}, }, ByteMapping: map[bool][]byte{ true: []byte("so be it"), }, } if err := UnmarshalText(in, m); err != nil { t.Fatal(err) } if !Equal(m, want) { t.Errorf("\n got %v\nwant %v", m, want) } } func TestOneofParsing(t *testing.T) { const in = `name:"Shrek"` m := new(Communique) want := &Communique{Union: &Communique_Name{"Shrek"}} if err := UnmarshalText(in, m); err != nil { t.Fatal(err) } if !Equal(m, want) { t.Errorf("\n got %v\nwant %v", m, want) } } var benchInput string func init() { benchInput = "count: 4\n" for i := 0; i < 1000; i++ { benchInput += "pet: \"fido\"\n" } // Check it is valid input. pb := new(MyMessage) err := UnmarshalText(benchInput, pb) if err != nil { panic("Bad benchmark input: " + err.Error()) } } func BenchmarkUnmarshalText(b *testing.B) { pb := new(MyMessage) for i := 0; i < b.N; i++ { UnmarshalText(benchInput, pb) } b.SetBytes(int64(len(benchInput))) } lxd-2.0.0/dist/src/github.com/golang/protobuf/proto/extensions_test.go0000644061062106075000000003244212702772352030552 0ustar00stgraberdomain admins00000000000000// Go support for Protocol Buffers - Google's data interchange format // // Copyright 2014 The Go Authors. All rights reserved. // https://github.com/golang/protobuf // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package proto_test import ( "bytes" "fmt" "reflect" "testing" "github.com/golang/protobuf/proto" pb "github.com/golang/protobuf/proto/testdata" ) func TestGetExtensionsWithMissingExtensions(t *testing.T) { msg := &pb.MyMessage{} ext1 := &pb.Ext{} if err := proto.SetExtension(msg, pb.E_Ext_More, ext1); err != nil { t.Fatalf("Could not set ext1: %s", ext1) } exts, err := proto.GetExtensions(msg, []*proto.ExtensionDesc{ pb.E_Ext_More, pb.E_Ext_Text, }) if err != nil { t.Fatalf("GetExtensions() failed: %s", err) } if exts[0] != ext1 { t.Errorf("ext1 not in returned extensions: %T %v", exts[0], exts[0]) } if exts[1] != nil { t.Errorf("ext2 in returned extensions: %T %v", exts[1], exts[1]) } } func TestGetExtensionStability(t *testing.T) { check := func(m *pb.MyMessage) bool { ext1, err := proto.GetExtension(m, pb.E_Ext_More) if err != nil { t.Fatalf("GetExtension() failed: %s", err) } ext2, err := proto.GetExtension(m, pb.E_Ext_More) if err != nil { t.Fatalf("GetExtension() failed: %s", err) } return ext1 == ext2 } msg := &pb.MyMessage{Count: proto.Int32(4)} ext0 := &pb.Ext{} if err := proto.SetExtension(msg, pb.E_Ext_More, ext0); err != nil { t.Fatalf("Could not set ext1: %s", ext0) } if !check(msg) { t.Errorf("GetExtension() not stable before marshaling") } bb, err := proto.Marshal(msg) if err != nil { t.Fatalf("Marshal() failed: %s", err) } msg1 := &pb.MyMessage{} err = proto.Unmarshal(bb, msg1) if err != nil { t.Fatalf("Unmarshal() failed: %s", err) } if !check(msg1) { t.Errorf("GetExtension() not stable after unmarshaling") } } func TestGetExtensionDefaults(t *testing.T) { var setFloat64 float64 = 1 var setFloat32 float32 = 2 var setInt32 int32 = 3 var setInt64 int64 = 4 var setUint32 uint32 = 5 var setUint64 uint64 = 6 var setBool = true var setBool2 = false var setString = "Goodnight string" var setBytes = []byte("Goodnight bytes") var setEnum = pb.DefaultsMessage_TWO type testcase struct { ext *proto.ExtensionDesc // Extension we are testing. want interface{} // Expected value of extension, or nil (meaning that GetExtension will fail). def interface{} // Expected value of extension after ClearExtension(). } tests := []testcase{ {pb.E_NoDefaultDouble, setFloat64, nil}, {pb.E_NoDefaultFloat, setFloat32, nil}, {pb.E_NoDefaultInt32, setInt32, nil}, {pb.E_NoDefaultInt64, setInt64, nil}, {pb.E_NoDefaultUint32, setUint32, nil}, {pb.E_NoDefaultUint64, setUint64, nil}, {pb.E_NoDefaultSint32, setInt32, nil}, {pb.E_NoDefaultSint64, setInt64, nil}, {pb.E_NoDefaultFixed32, setUint32, nil}, {pb.E_NoDefaultFixed64, setUint64, nil}, {pb.E_NoDefaultSfixed32, setInt32, nil}, {pb.E_NoDefaultSfixed64, setInt64, nil}, {pb.E_NoDefaultBool, setBool, nil}, {pb.E_NoDefaultBool, setBool2, nil}, {pb.E_NoDefaultString, setString, nil}, {pb.E_NoDefaultBytes, setBytes, nil}, {pb.E_NoDefaultEnum, setEnum, nil}, {pb.E_DefaultDouble, setFloat64, float64(3.1415)}, {pb.E_DefaultFloat, setFloat32, float32(3.14)}, {pb.E_DefaultInt32, setInt32, int32(42)}, {pb.E_DefaultInt64, setInt64, int64(43)}, {pb.E_DefaultUint32, setUint32, uint32(44)}, {pb.E_DefaultUint64, setUint64, uint64(45)}, {pb.E_DefaultSint32, setInt32, int32(46)}, {pb.E_DefaultSint64, setInt64, int64(47)}, {pb.E_DefaultFixed32, setUint32, uint32(48)}, {pb.E_DefaultFixed64, setUint64, uint64(49)}, {pb.E_DefaultSfixed32, setInt32, int32(50)}, {pb.E_DefaultSfixed64, setInt64, int64(51)}, {pb.E_DefaultBool, setBool, true}, {pb.E_DefaultBool, setBool2, true}, {pb.E_DefaultString, setString, "Hello, string"}, {pb.E_DefaultBytes, setBytes, []byte("Hello, bytes")}, {pb.E_DefaultEnum, setEnum, pb.DefaultsMessage_ONE}, } checkVal := func(test testcase, msg *pb.DefaultsMessage, valWant interface{}) error { val, err := proto.GetExtension(msg, test.ext) if err != nil { if valWant != nil { return fmt.Errorf("GetExtension(): %s", err) } if want := proto.ErrMissingExtension; err != want { return fmt.Errorf("Unexpected error: got %v, want %v", err, want) } return nil } // All proto2 extension values are either a pointer to a value or a slice of values. ty := reflect.TypeOf(val) tyWant := reflect.TypeOf(test.ext.ExtensionType) if got, want := ty, tyWant; got != want { return fmt.Errorf("unexpected reflect.TypeOf(): got %v want %v", got, want) } tye := ty.Elem() tyeWant := tyWant.Elem() if got, want := tye, tyeWant; got != want { return fmt.Errorf("unexpected reflect.TypeOf().Elem(): got %v want %v", got, want) } // Check the name of the type of the value. // If it is an enum it will be type int32 with the name of the enum. if got, want := tye.Name(), tye.Name(); got != want { return fmt.Errorf("unexpected reflect.TypeOf().Elem().Name(): got %v want %v", got, want) } // Check that value is what we expect. // If we have a pointer in val, get the value it points to. valExp := val if ty.Kind() == reflect.Ptr { valExp = reflect.ValueOf(val).Elem().Interface() } if got, want := valExp, valWant; !reflect.DeepEqual(got, want) { return fmt.Errorf("unexpected reflect.DeepEqual(): got %v want %v", got, want) } return nil } setTo := func(test testcase) interface{} { setTo := reflect.ValueOf(test.want) if typ := reflect.TypeOf(test.ext.ExtensionType); typ.Kind() == reflect.Ptr { setTo = reflect.New(typ).Elem() setTo.Set(reflect.New(setTo.Type().Elem())) setTo.Elem().Set(reflect.ValueOf(test.want)) } return setTo.Interface() } for _, test := range tests { msg := &pb.DefaultsMessage{} name := test.ext.Name // Check the initial value. if err := checkVal(test, msg, test.def); err != nil { t.Errorf("%s: %v", name, err) } // Set the per-type value and check value. name = fmt.Sprintf("%s (set to %T %v)", name, test.want, test.want) if err := proto.SetExtension(msg, test.ext, setTo(test)); err != nil { t.Errorf("%s: SetExtension(): %v", name, err) continue } if err := checkVal(test, msg, test.want); err != nil { t.Errorf("%s: %v", name, err) continue } // Set and check the value. name += " (cleared)" proto.ClearExtension(msg, test.ext) if err := checkVal(test, msg, test.def); err != nil { t.Errorf("%s: %v", name, err) } } } func TestExtensionsRoundTrip(t *testing.T) { msg := &pb.MyMessage{} ext1 := &pb.Ext{ Data: proto.String("hi"), } ext2 := &pb.Ext{ Data: proto.String("there"), } exists := proto.HasExtension(msg, pb.E_Ext_More) if exists { t.Error("Extension More present unexpectedly") } if err := proto.SetExtension(msg, pb.E_Ext_More, ext1); err != nil { t.Error(err) } if err := proto.SetExtension(msg, pb.E_Ext_More, ext2); err != nil { t.Error(err) } e, err := proto.GetExtension(msg, pb.E_Ext_More) if err != nil { t.Error(err) } x, ok := e.(*pb.Ext) if !ok { t.Errorf("e has type %T, expected testdata.Ext", e) } else if *x.Data != "there" { t.Errorf("SetExtension failed to overwrite, got %+v, not 'there'", x) } proto.ClearExtension(msg, pb.E_Ext_More) if _, err = proto.GetExtension(msg, pb.E_Ext_More); err != proto.ErrMissingExtension { t.Errorf("got %v, expected ErrMissingExtension", e) } if _, err := proto.GetExtension(msg, pb.E_X215); err == nil { t.Error("expected bad extension error, got nil") } if err := proto.SetExtension(msg, pb.E_X215, 12); err == nil { t.Error("expected extension err") } if err := proto.SetExtension(msg, pb.E_Ext_More, 12); err == nil { t.Error("expected some sort of type mismatch error, got nil") } } func TestNilExtension(t *testing.T) { msg := &pb.MyMessage{ Count: proto.Int32(1), } if err := proto.SetExtension(msg, pb.E_Ext_Text, proto.String("hello")); err != nil { t.Fatal(err) } if err := proto.SetExtension(msg, pb.E_Ext_More, (*pb.Ext)(nil)); err == nil { t.Error("expected SetExtension to fail due to a nil extension") } else if want := "proto: SetExtension called with nil value of type *testdata.Ext"; err.Error() != want { t.Errorf("expected error %v, got %v", want, err) } // Note: if the behavior of Marshal is ever changed to ignore nil extensions, update // this test to verify that E_Ext_Text is properly propagated through marshal->unmarshal. } func TestMarshalUnmarshalRepeatedExtension(t *testing.T) { // Add a repeated extension to the result. tests := []struct { name string ext []*pb.ComplexExtension }{ { "two fields", []*pb.ComplexExtension{ {First: proto.Int32(7)}, {Second: proto.Int32(11)}, }, }, { "repeated field", []*pb.ComplexExtension{ {Third: []int32{1000}}, {Third: []int32{2000}}, }, }, { "two fields and repeated field", []*pb.ComplexExtension{ {Third: []int32{1000}}, {First: proto.Int32(9)}, {Second: proto.Int32(21)}, {Third: []int32{2000}}, }, }, } for _, test := range tests { // Marshal message with a repeated extension. msg1 := new(pb.OtherMessage) err := proto.SetExtension(msg1, pb.E_RComplex, test.ext) if err != nil { t.Fatalf("[%s] Error setting extension: %v", test.name, err) } b, err := proto.Marshal(msg1) if err != nil { t.Fatalf("[%s] Error marshaling message: %v", test.name, err) } // Unmarshal and read the merged proto. msg2 := new(pb.OtherMessage) err = proto.Unmarshal(b, msg2) if err != nil { t.Fatalf("[%s] Error unmarshaling message: %v", test.name, err) } e, err := proto.GetExtension(msg2, pb.E_RComplex) if err != nil { t.Fatalf("[%s] Error getting extension: %v", test.name, err) } ext := e.([]*pb.ComplexExtension) if ext == nil { t.Fatalf("[%s] Invalid extension", test.name) } if !reflect.DeepEqual(ext, test.ext) { t.Errorf("[%s] Wrong value for ComplexExtension: got: %v want: %v\n", test.name, ext, test.ext) } } } func TestUnmarshalRepeatingNonRepeatedExtension(t *testing.T) { // We may see multiple instances of the same extension in the wire // format. For example, the proto compiler may encode custom options in // this way. Here, we verify that we merge the extensions together. tests := []struct { name string ext []*pb.ComplexExtension }{ { "two fields", []*pb.ComplexExtension{ {First: proto.Int32(7)}, {Second: proto.Int32(11)}, }, }, { "repeated field", []*pb.ComplexExtension{ {Third: []int32{1000}}, {Third: []int32{2000}}, }, }, { "two fields and repeated field", []*pb.ComplexExtension{ {Third: []int32{1000}}, {First: proto.Int32(9)}, {Second: proto.Int32(21)}, {Third: []int32{2000}}, }, }, } for _, test := range tests { var buf bytes.Buffer var want pb.ComplexExtension // Generate a serialized representation of a repeated extension // by catenating bytes together. for i, e := range test.ext { // Merge to create the wanted proto. proto.Merge(&want, e) // serialize the message msg := new(pb.OtherMessage) err := proto.SetExtension(msg, pb.E_Complex, e) if err != nil { t.Fatalf("[%s] Error setting extension %d: %v", test.name, i, err) } b, err := proto.Marshal(msg) if err != nil { t.Fatalf("[%s] Error marshaling message %d: %v", test.name, i, err) } buf.Write(b) } // Unmarshal and read the merged proto. msg2 := new(pb.OtherMessage) err := proto.Unmarshal(buf.Bytes(), msg2) if err != nil { t.Fatalf("[%s] Error unmarshaling message: %v", test.name, err) } e, err := proto.GetExtension(msg2, pb.E_Complex) if err != nil { t.Fatalf("[%s] Error getting extension: %v", test.name, err) } ext := e.(*pb.ComplexExtension) if ext == nil { t.Fatalf("[%s] Invalid extension", test.name) } if !reflect.DeepEqual(*ext, want) { t.Errorf("[%s] Wrong value for ComplexExtension: got: %s want: %s\n", test.name, ext, want) } } } lxd-2.0.0/dist/src/github.com/golang/protobuf/proto/lib.go0000644061062106075000000005674212702772352026073 0ustar00stgraberdomain admins00000000000000// Go support for Protocol Buffers - Google's data interchange format // // Copyright 2010 The Go Authors. All rights reserved. // https://github.com/golang/protobuf // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /* Package proto converts data structures to and from the wire format of protocol buffers. It works in concert with the Go source code generated for .proto files by the protocol compiler. A summary of the properties of the protocol buffer interface for a protocol buffer variable v: - Names are turned from camel_case to CamelCase for export. - There are no methods on v to set fields; just treat them as structure fields. - There are getters that return a field's value if set, and return the field's default value if unset. The getters work even if the receiver is a nil message. - The zero value for a struct is its correct initialization state. All desired fields must be set before marshaling. - A Reset() method will restore a protobuf struct to its zero state. - Non-repeated fields are pointers to the values; nil means unset. That is, optional or required field int32 f becomes F *int32. - Repeated fields are slices. - Helper functions are available to aid the setting of fields. msg.Foo = proto.String("hello") // set field - Constants are defined to hold the default values of all fields that have them. They have the form Default_StructName_FieldName. Because the getter methods handle defaulted values, direct use of these constants should be rare. - Enums are given type names and maps from names to values. Enum values are prefixed by the enclosing message's name, or by the enum's type name if it is a top-level enum. Enum types have a String method, and a Enum method to assist in message construction. - Nested messages, groups and enums have type names prefixed with the name of the surrounding message type. - Extensions are given descriptor names that start with E_, followed by an underscore-delimited list of the nested messages that contain it (if any) followed by the CamelCased name of the extension field itself. HasExtension, ClearExtension, GetExtension and SetExtension are functions for manipulating extensions. - Oneof field sets are given a single field in their message, with distinguished wrapper types for each possible field value. - Marshal and Unmarshal are functions to encode and decode the wire format. When the .proto file specifies `syntax="proto3"`, there are some differences: - Non-repeated fields of non-message type are values instead of pointers. - Getters are only generated for message and oneof fields. - Enum types do not get an Enum method. The simplest way to describe this is to see an example. Given file test.proto, containing package example; enum FOO { X = 17; } message Test { required string label = 1; optional int32 type = 2 [default=77]; repeated int64 reps = 3; optional group OptionalGroup = 4 { required string RequiredField = 5; } oneof union { int32 number = 6; string name = 7; } } The resulting file, test.pb.go, is: package example import proto "github.com/golang/protobuf/proto" import math "math" type FOO int32 const ( FOO_X FOO = 17 ) var FOO_name = map[int32]string{ 17: "X", } var FOO_value = map[string]int32{ "X": 17, } func (x FOO) Enum() *FOO { p := new(FOO) *p = x return p } func (x FOO) String() string { return proto.EnumName(FOO_name, int32(x)) } func (x *FOO) UnmarshalJSON(data []byte) error { value, err := proto.UnmarshalJSONEnum(FOO_value, data) if err != nil { return err } *x = FOO(value) return nil } type Test struct { Label *string `protobuf:"bytes,1,req,name=label" json:"label,omitempty"` Type *int32 `protobuf:"varint,2,opt,name=type,def=77" json:"type,omitempty"` Reps []int64 `protobuf:"varint,3,rep,name=reps" json:"reps,omitempty"` Optionalgroup *Test_OptionalGroup `protobuf:"group,4,opt,name=OptionalGroup" json:"optionalgroup,omitempty"` // Types that are valid to be assigned to Union: // *Test_Number // *Test_Name Union isTest_Union `protobuf_oneof:"union"` XXX_unrecognized []byte `json:"-"` } func (m *Test) Reset() { *m = Test{} } func (m *Test) String() string { return proto.CompactTextString(m) } func (*Test) ProtoMessage() {} type isTest_Union interface { isTest_Union() } type Test_Number struct { Number int32 `protobuf:"varint,6,opt,name=number"` } type Test_Name struct { Name string `protobuf:"bytes,7,opt,name=name"` } func (*Test_Number) isTest_Union() {} func (*Test_Name) isTest_Union() {} func (m *Test) GetUnion() isTest_Union { if m != nil { return m.Union } return nil } const Default_Test_Type int32 = 77 func (m *Test) GetLabel() string { if m != nil && m.Label != nil { return *m.Label } return "" } func (m *Test) GetType() int32 { if m != nil && m.Type != nil { return *m.Type } return Default_Test_Type } func (m *Test) GetOptionalgroup() *Test_OptionalGroup { if m != nil { return m.Optionalgroup } return nil } type Test_OptionalGroup struct { RequiredField *string `protobuf:"bytes,5,req" json:"RequiredField,omitempty"` } func (m *Test_OptionalGroup) Reset() { *m = Test_OptionalGroup{} } func (m *Test_OptionalGroup) String() string { return proto.CompactTextString(m) } func (m *Test_OptionalGroup) GetRequiredField() string { if m != nil && m.RequiredField != nil { return *m.RequiredField } return "" } func (m *Test) GetNumber() int32 { if x, ok := m.GetUnion().(*Test_Number); ok { return x.Number } return 0 } func (m *Test) GetName() string { if x, ok := m.GetUnion().(*Test_Name); ok { return x.Name } return "" } func init() { proto.RegisterEnum("example.FOO", FOO_name, FOO_value) } To create and play with a Test object: package main import ( "log" "github.com/golang/protobuf/proto" pb "./example.pb" ) func main() { test := &pb.Test{ Label: proto.String("hello"), Type: proto.Int32(17), Reps: []int64{1, 2, 3}, Optionalgroup: &pb.Test_OptionalGroup{ RequiredField: proto.String("good bye"), }, Union: &pb.Test_Name{"fred"}, } data, err := proto.Marshal(test) if err != nil { log.Fatal("marshaling error: ", err) } newTest := &pb.Test{} err = proto.Unmarshal(data, newTest) if err != nil { log.Fatal("unmarshaling error: ", err) } // Now test and newTest contain the same data. if test.GetLabel() != newTest.GetLabel() { log.Fatalf("data mismatch %q != %q", test.GetLabel(), newTest.GetLabel()) } // Use a type switch to determine which oneof was set. switch u := test.Union.(type) { case *pb.Test_Number: // u.Number contains the number. case *pb.Test_Name: // u.Name contains the string. } // etc. } */ package proto import ( "encoding/json" "fmt" "log" "reflect" "sort" "strconv" "sync" ) // Message is implemented by generated protocol buffer messages. type Message interface { Reset() String() string ProtoMessage() } // Stats records allocation details about the protocol buffer encoders // and decoders. Useful for tuning the library itself. type Stats struct { Emalloc uint64 // mallocs in encode Dmalloc uint64 // mallocs in decode Encode uint64 // number of encodes Decode uint64 // number of decodes Chit uint64 // number of cache hits Cmiss uint64 // number of cache misses Size uint64 // number of sizes } // Set to true to enable stats collection. const collectStats = false var stats Stats // GetStats returns a copy of the global Stats structure. func GetStats() Stats { return stats } // A Buffer is a buffer manager for marshaling and unmarshaling // protocol buffers. It may be reused between invocations to // reduce memory usage. It is not necessary to use a Buffer; // the global functions Marshal and Unmarshal create a // temporary Buffer and are fine for most applications. type Buffer struct { buf []byte // encode/decode byte stream index int // write point // pools of basic types to amortize allocation. bools []bool uint32s []uint32 uint64s []uint64 // extra pools, only used with pointer_reflect.go int32s []int32 int64s []int64 float32s []float32 float64s []float64 } // NewBuffer allocates a new Buffer and initializes its internal data to // the contents of the argument slice. func NewBuffer(e []byte) *Buffer { return &Buffer{buf: e} } // Reset resets the Buffer, ready for marshaling a new protocol buffer. func (p *Buffer) Reset() { p.buf = p.buf[0:0] // for reading/writing p.index = 0 // for reading } // SetBuf replaces the internal buffer with the slice, // ready for unmarshaling the contents of the slice. func (p *Buffer) SetBuf(s []byte) { p.buf = s p.index = 0 } // Bytes returns the contents of the Buffer. func (p *Buffer) Bytes() []byte { return p.buf } /* * Helper routines for simplifying the creation of optional fields of basic type. */ // Bool is a helper routine that allocates a new bool value // to store v and returns a pointer to it. func Bool(v bool) *bool { return &v } // Int32 is a helper routine that allocates a new int32 value // to store v and returns a pointer to it. func Int32(v int32) *int32 { return &v } // Int is a helper routine that allocates a new int32 value // to store v and returns a pointer to it, but unlike Int32 // its argument value is an int. func Int(v int) *int32 { p := new(int32) *p = int32(v) return p } // Int64 is a helper routine that allocates a new int64 value // to store v and returns a pointer to it. func Int64(v int64) *int64 { return &v } // Float32 is a helper routine that allocates a new float32 value // to store v and returns a pointer to it. func Float32(v float32) *float32 { return &v } // Float64 is a helper routine that allocates a new float64 value // to store v and returns a pointer to it. func Float64(v float64) *float64 { return &v } // Uint32 is a helper routine that allocates a new uint32 value // to store v and returns a pointer to it. func Uint32(v uint32) *uint32 { return &v } // Uint64 is a helper routine that allocates a new uint64 value // to store v and returns a pointer to it. func Uint64(v uint64) *uint64 { return &v } // String is a helper routine that allocates a new string value // to store v and returns a pointer to it. func String(v string) *string { return &v } // EnumName is a helper function to simplify printing protocol buffer enums // by name. Given an enum map and a value, it returns a useful string. func EnumName(m map[int32]string, v int32) string { s, ok := m[v] if ok { return s } return strconv.Itoa(int(v)) } // UnmarshalJSONEnum is a helper function to simplify recovering enum int values // from their JSON-encoded representation. Given a map from the enum's symbolic // names to its int values, and a byte buffer containing the JSON-encoded // value, it returns an int32 that can be cast to the enum type by the caller. // // The function can deal with both JSON representations, numeric and symbolic. func UnmarshalJSONEnum(m map[string]int32, data []byte, enumName string) (int32, error) { if data[0] == '"' { // New style: enums are strings. var repr string if err := json.Unmarshal(data, &repr); err != nil { return -1, err } val, ok := m[repr] if !ok { return 0, fmt.Errorf("unrecognized enum %s value %q", enumName, repr) } return val, nil } // Old style: enums are ints. var val int32 if err := json.Unmarshal(data, &val); err != nil { return 0, fmt.Errorf("cannot unmarshal %#q into enum %s", data, enumName) } return val, nil } // DebugPrint dumps the encoded data in b in a debugging format with a header // including the string s. Used in testing but made available for general debugging. func (p *Buffer) DebugPrint(s string, b []byte) { var u uint64 obuf := p.buf index := p.index p.buf = b p.index = 0 depth := 0 fmt.Printf("\n--- %s ---\n", s) out: for { for i := 0; i < depth; i++ { fmt.Print(" ") } index := p.index if index == len(p.buf) { break } op, err := p.DecodeVarint() if err != nil { fmt.Printf("%3d: fetching op err %v\n", index, err) break out } tag := op >> 3 wire := op & 7 switch wire { default: fmt.Printf("%3d: t=%3d unknown wire=%d\n", index, tag, wire) break out case WireBytes: var r []byte r, err = p.DecodeRawBytes(false) if err != nil { break out } fmt.Printf("%3d: t=%3d bytes [%d]", index, tag, len(r)) if len(r) <= 6 { for i := 0; i < len(r); i++ { fmt.Printf(" %.2x", r[i]) } } else { for i := 0; i < 3; i++ { fmt.Printf(" %.2x", r[i]) } fmt.Printf(" ..") for i := len(r) - 3; i < len(r); i++ { fmt.Printf(" %.2x", r[i]) } } fmt.Printf("\n") case WireFixed32: u, err = p.DecodeFixed32() if err != nil { fmt.Printf("%3d: t=%3d fix32 err %v\n", index, tag, err) break out } fmt.Printf("%3d: t=%3d fix32 %d\n", index, tag, u) case WireFixed64: u, err = p.DecodeFixed64() if err != nil { fmt.Printf("%3d: t=%3d fix64 err %v\n", index, tag, err) break out } fmt.Printf("%3d: t=%3d fix64 %d\n", index, tag, u) case WireVarint: u, err = p.DecodeVarint() if err != nil { fmt.Printf("%3d: t=%3d varint err %v\n", index, tag, err) break out } fmt.Printf("%3d: t=%3d varint %d\n", index, tag, u) case WireStartGroup: fmt.Printf("%3d: t=%3d start\n", index, tag) depth++ case WireEndGroup: depth-- fmt.Printf("%3d: t=%3d end\n", index, tag) } } if depth != 0 { fmt.Printf("%3d: start-end not balanced %d\n", p.index, depth) } fmt.Printf("\n") p.buf = obuf p.index = index } // SetDefaults sets unset protocol buffer fields to their default values. // It only modifies fields that are both unset and have defined defaults. // It recursively sets default values in any non-nil sub-messages. func SetDefaults(pb Message) { setDefaults(reflect.ValueOf(pb), true, false) } // v is a pointer to a struct. func setDefaults(v reflect.Value, recur, zeros bool) { v = v.Elem() defaultMu.RLock() dm, ok := defaults[v.Type()] defaultMu.RUnlock() if !ok { dm = buildDefaultMessage(v.Type()) defaultMu.Lock() defaults[v.Type()] = dm defaultMu.Unlock() } for _, sf := range dm.scalars { f := v.Field(sf.index) if !f.IsNil() { // field already set continue } dv := sf.value if dv == nil && !zeros { // no explicit default, and don't want to set zeros continue } fptr := f.Addr().Interface() // **T // TODO: Consider batching the allocations we do here. switch sf.kind { case reflect.Bool: b := new(bool) if dv != nil { *b = dv.(bool) } *(fptr.(**bool)) = b case reflect.Float32: f := new(float32) if dv != nil { *f = dv.(float32) } *(fptr.(**float32)) = f case reflect.Float64: f := new(float64) if dv != nil { *f = dv.(float64) } *(fptr.(**float64)) = f case reflect.Int32: // might be an enum if ft := f.Type(); ft != int32PtrType { // enum f.Set(reflect.New(ft.Elem())) if dv != nil { f.Elem().SetInt(int64(dv.(int32))) } } else { // int32 field i := new(int32) if dv != nil { *i = dv.(int32) } *(fptr.(**int32)) = i } case reflect.Int64: i := new(int64) if dv != nil { *i = dv.(int64) } *(fptr.(**int64)) = i case reflect.String: s := new(string) if dv != nil { *s = dv.(string) } *(fptr.(**string)) = s case reflect.Uint8: // exceptional case: []byte var b []byte if dv != nil { db := dv.([]byte) b = make([]byte, len(db)) copy(b, db) } else { b = []byte{} } *(fptr.(*[]byte)) = b case reflect.Uint32: u := new(uint32) if dv != nil { *u = dv.(uint32) } *(fptr.(**uint32)) = u case reflect.Uint64: u := new(uint64) if dv != nil { *u = dv.(uint64) } *(fptr.(**uint64)) = u default: log.Printf("proto: can't set default for field %v (sf.kind=%v)", f, sf.kind) } } for _, ni := range dm.nested { f := v.Field(ni) // f is *T or []*T or map[T]*T switch f.Kind() { case reflect.Ptr: if f.IsNil() { continue } setDefaults(f, recur, zeros) case reflect.Slice: for i := 0; i < f.Len(); i++ { e := f.Index(i) if e.IsNil() { continue } setDefaults(e, recur, zeros) } case reflect.Map: for _, k := range f.MapKeys() { e := f.MapIndex(k) if e.IsNil() { continue } setDefaults(e, recur, zeros) } } } } var ( // defaults maps a protocol buffer struct type to a slice of the fields, // with its scalar fields set to their proto-declared non-zero default values. defaultMu sync.RWMutex defaults = make(map[reflect.Type]defaultMessage) int32PtrType = reflect.TypeOf((*int32)(nil)) ) // defaultMessage represents information about the default values of a message. type defaultMessage struct { scalars []scalarField nested []int // struct field index of nested messages } type scalarField struct { index int // struct field index kind reflect.Kind // element type (the T in *T or []T) value interface{} // the proto-declared default value, or nil } // t is a struct type. func buildDefaultMessage(t reflect.Type) (dm defaultMessage) { sprop := GetProperties(t) for _, prop := range sprop.Prop { fi, ok := sprop.decoderTags.get(prop.Tag) if !ok { // XXX_unrecognized continue } ft := t.Field(fi).Type sf, nested, err := fieldDefault(ft, prop) switch { case err != nil: log.Print(err) case nested: dm.nested = append(dm.nested, fi) case sf != nil: sf.index = fi dm.scalars = append(dm.scalars, *sf) } } return dm } // fieldDefault returns the scalarField for field type ft. // sf will be nil if the field can not have a default. // nestedMessage will be true if this is a nested message. // Note that sf.index is not set on return. func fieldDefault(ft reflect.Type, prop *Properties) (sf *scalarField, nestedMessage bool, err error) { var canHaveDefault bool switch ft.Kind() { case reflect.Ptr: if ft.Elem().Kind() == reflect.Struct { nestedMessage = true } else { canHaveDefault = true // proto2 scalar field } case reflect.Slice: switch ft.Elem().Kind() { case reflect.Ptr: nestedMessage = true // repeated message case reflect.Uint8: canHaveDefault = true // bytes field } case reflect.Map: if ft.Elem().Kind() == reflect.Ptr { nestedMessage = true // map with message values } } if !canHaveDefault { if nestedMessage { return nil, true, nil } return nil, false, nil } // We now know that ft is a pointer or slice. sf = &scalarField{kind: ft.Elem().Kind()} // scalar fields without defaults if !prop.HasDefault { return sf, false, nil } // a scalar field: either *T or []byte switch ft.Elem().Kind() { case reflect.Bool: x, err := strconv.ParseBool(prop.Default) if err != nil { return nil, false, fmt.Errorf("proto: bad default bool %q: %v", prop.Default, err) } sf.value = x case reflect.Float32: x, err := strconv.ParseFloat(prop.Default, 32) if err != nil { return nil, false, fmt.Errorf("proto: bad default float32 %q: %v", prop.Default, err) } sf.value = float32(x) case reflect.Float64: x, err := strconv.ParseFloat(prop.Default, 64) if err != nil { return nil, false, fmt.Errorf("proto: bad default float64 %q: %v", prop.Default, err) } sf.value = x case reflect.Int32: x, err := strconv.ParseInt(prop.Default, 10, 32) if err != nil { return nil, false, fmt.Errorf("proto: bad default int32 %q: %v", prop.Default, err) } sf.value = int32(x) case reflect.Int64: x, err := strconv.ParseInt(prop.Default, 10, 64) if err != nil { return nil, false, fmt.Errorf("proto: bad default int64 %q: %v", prop.Default, err) } sf.value = x case reflect.String: sf.value = prop.Default case reflect.Uint8: // []byte (not *uint8) sf.value = []byte(prop.Default) case reflect.Uint32: x, err := strconv.ParseUint(prop.Default, 10, 32) if err != nil { return nil, false, fmt.Errorf("proto: bad default uint32 %q: %v", prop.Default, err) } sf.value = uint32(x) case reflect.Uint64: x, err := strconv.ParseUint(prop.Default, 10, 64) if err != nil { return nil, false, fmt.Errorf("proto: bad default uint64 %q: %v", prop.Default, err) } sf.value = x default: return nil, false, fmt.Errorf("proto: unhandled def kind %v", ft.Elem().Kind()) } return sf, false, nil } // Map fields may have key types of non-float scalars, strings and enums. // The easiest way to sort them in some deterministic order is to use fmt. // If this turns out to be inefficient we can always consider other options, // such as doing a Schwartzian transform. func mapKeys(vs []reflect.Value) sort.Interface { s := mapKeySorter{ vs: vs, // default Less function: textual comparison less: func(a, b reflect.Value) bool { return fmt.Sprint(a.Interface()) < fmt.Sprint(b.Interface()) }, } // Type specialization per https://developers.google.com/protocol-buffers/docs/proto#maps; // numeric keys are sorted numerically. if len(vs) == 0 { return s } switch vs[0].Kind() { case reflect.Int32, reflect.Int64: s.less = func(a, b reflect.Value) bool { return a.Int() < b.Int() } case reflect.Uint32, reflect.Uint64: s.less = func(a, b reflect.Value) bool { return a.Uint() < b.Uint() } } return s } type mapKeySorter struct { vs []reflect.Value less func(a, b reflect.Value) bool } func (s mapKeySorter) Len() int { return len(s.vs) } func (s mapKeySorter) Swap(i, j int) { s.vs[i], s.vs[j] = s.vs[j], s.vs[i] } func (s mapKeySorter) Less(i, j int) bool { return s.less(s.vs[i], s.vs[j]) } // isProto3Zero reports whether v is a zero proto3 value. func isProto3Zero(v reflect.Value) bool { switch v.Kind() { case reflect.Bool: return !v.Bool() case reflect.Int32, reflect.Int64: return v.Int() == 0 case reflect.Uint32, reflect.Uint64: return v.Uint() == 0 case reflect.Float32, reflect.Float64: return v.Float() == 0 case reflect.String: return v.String() == "" } return false } // ProtoPackageIsVersion1 is referenced from generated protocol buffer files // to assert that that code is compatible with this version of the proto package. const ProtoPackageIsVersion1 = true lxd-2.0.0/dist/src/github.com/golang/protobuf/proto/proto3_proto/0000755061062106075000000000000012702772352027431 5ustar00stgraberdomain admins00000000000000lxd-2.0.0/dist/src/github.com/golang/protobuf/proto/proto3_proto/proto3.proto0000644061062106075000000000457012702772352031752 0ustar00stgraberdomain admins00000000000000// Go support for Protocol Buffers - Google's data interchange format // // Copyright 2014 The Go Authors. All rights reserved. // https://github.com/golang/protobuf // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. syntax = "proto3"; import "google/protobuf/any.proto"; import "testdata/test.proto"; package proto3_proto; message Message { enum Humour { UNKNOWN = 0; PUNS = 1; SLAPSTICK = 2; BILL_BAILEY = 3; } string name = 1; Humour hilarity = 2; uint32 height_in_cm = 3; bytes data = 4; int64 result_count = 7; bool true_scotsman = 8; float score = 9; repeated uint64 key = 5; Nested nested = 6; map terrain = 10; testdata.SubDefaults proto2_field = 11; map proto2_value = 13; google.protobuf.Any anything = 14; repeated google.protobuf.Any many_things = 15; } message Nested { string bunny = 1; } message MessageWithMap { map byte_mapping = 1; } lxd-2.0.0/dist/src/github.com/golang/protobuf/proto/proto3_proto/proto3.pb.go0000644061062106075000000002213212702772352031606 0ustar00stgraberdomain admins00000000000000// Code generated by protoc-gen-go. // source: proto3_proto/proto3.proto // DO NOT EDIT! /* Package proto3_proto is a generated protocol buffer package. It is generated from these files: proto3_proto/proto3.proto It has these top-level messages: Message Nested MessageWithMap */ package proto3_proto import proto "github.com/golang/protobuf/proto" import fmt "fmt" import math "math" import google_protobuf "github.com/golang/protobuf/ptypes/any" import testdata "github.com/golang/protobuf/proto/testdata" // Reference imports to suppress errors if they are not otherwise used. var _ = proto.Marshal var _ = fmt.Errorf var _ = math.Inf // This is a compile-time assertion to ensure that this generated file // is compatible with the proto package it is being compiled against. const _ = proto.ProtoPackageIsVersion1 type Message_Humour int32 const ( Message_UNKNOWN Message_Humour = 0 Message_PUNS Message_Humour = 1 Message_SLAPSTICK Message_Humour = 2 Message_BILL_BAILEY Message_Humour = 3 ) var Message_Humour_name = map[int32]string{ 0: "UNKNOWN", 1: "PUNS", 2: "SLAPSTICK", 3: "BILL_BAILEY", } var Message_Humour_value = map[string]int32{ "UNKNOWN": 0, "PUNS": 1, "SLAPSTICK": 2, "BILL_BAILEY": 3, } func (x Message_Humour) String() string { return proto.EnumName(Message_Humour_name, int32(x)) } func (Message_Humour) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{0, 0} } type Message struct { Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` Hilarity Message_Humour `protobuf:"varint,2,opt,name=hilarity,enum=proto3_proto.Message_Humour" json:"hilarity,omitempty"` HeightInCm uint32 `protobuf:"varint,3,opt,name=height_in_cm,json=heightInCm" json:"height_in_cm,omitempty"` Data []byte `protobuf:"bytes,4,opt,name=data,proto3" json:"data,omitempty"` ResultCount int64 `protobuf:"varint,7,opt,name=result_count,json=resultCount" json:"result_count,omitempty"` TrueScotsman bool `protobuf:"varint,8,opt,name=true_scotsman,json=trueScotsman" json:"true_scotsman,omitempty"` Score float32 `protobuf:"fixed32,9,opt,name=score" json:"score,omitempty"` Key []uint64 `protobuf:"varint,5,rep,name=key" json:"key,omitempty"` Nested *Nested `protobuf:"bytes,6,opt,name=nested" json:"nested,omitempty"` Terrain map[string]*Nested `protobuf:"bytes,10,rep,name=terrain" json:"terrain,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` Proto2Field *testdata.SubDefaults `protobuf:"bytes,11,opt,name=proto2_field,json=proto2Field" json:"proto2_field,omitempty"` Proto2Value map[string]*testdata.SubDefaults `protobuf:"bytes,13,rep,name=proto2_value,json=proto2Value" json:"proto2_value,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` Anything *google_protobuf.Any `protobuf:"bytes,14,opt,name=anything" json:"anything,omitempty"` ManyThings []*google_protobuf.Any `protobuf:"bytes,15,rep,name=many_things,json=manyThings" json:"many_things,omitempty"` } func (m *Message) Reset() { *m = Message{} } func (m *Message) String() string { return proto.CompactTextString(m) } func (*Message) ProtoMessage() {} func (*Message) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } func (m *Message) GetNested() *Nested { if m != nil { return m.Nested } return nil } func (m *Message) GetTerrain() map[string]*Nested { if m != nil { return m.Terrain } return nil } func (m *Message) GetProto2Field() *testdata.SubDefaults { if m != nil { return m.Proto2Field } return nil } func (m *Message) GetProto2Value() map[string]*testdata.SubDefaults { if m != nil { return m.Proto2Value } return nil } func (m *Message) GetAnything() *google_protobuf.Any { if m != nil { return m.Anything } return nil } func (m *Message) GetManyThings() []*google_protobuf.Any { if m != nil { return m.ManyThings } return nil } type Nested struct { Bunny string `protobuf:"bytes,1,opt,name=bunny" json:"bunny,omitempty"` } func (m *Nested) Reset() { *m = Nested{} } func (m *Nested) String() string { return proto.CompactTextString(m) } func (*Nested) ProtoMessage() {} func (*Nested) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } type MessageWithMap struct { ByteMapping map[bool][]byte `protobuf:"bytes,1,rep,name=byte_mapping,json=byteMapping" json:"byte_mapping,omitempty" protobuf_key:"varint,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value,proto3"` } func (m *MessageWithMap) Reset() { *m = MessageWithMap{} } func (m *MessageWithMap) String() string { return proto.CompactTextString(m) } func (*MessageWithMap) ProtoMessage() {} func (*MessageWithMap) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} } func (m *MessageWithMap) GetByteMapping() map[bool][]byte { if m != nil { return m.ByteMapping } return nil } func init() { proto.RegisterType((*Message)(nil), "proto3_proto.Message") proto.RegisterType((*Nested)(nil), "proto3_proto.Nested") proto.RegisterType((*MessageWithMap)(nil), "proto3_proto.MessageWithMap") proto.RegisterEnum("proto3_proto.Message_Humour", Message_Humour_name, Message_Humour_value) } var fileDescriptor0 = []byte{ // 593 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x7c, 0x92, 0xff, 0x6e, 0xd3, 0x30, 0x10, 0xc7, 0x49, 0xdb, 0xa5, 0xd9, 0x25, 0xdd, 0x22, 0x33, 0x24, 0xaf, 0x42, 0x68, 0x14, 0x09, 0x4d, 0xfc, 0xc8, 0x50, 0x11, 0xd2, 0x84, 0x10, 0x68, 0x1b, 0x43, 0x54, 0xeb, 0x4a, 0xe5, 0x6e, 0x4c, 0xfc, 0x15, 0x39, 0xad, 0xdb, 0x46, 0x34, 0x4e, 0x95, 0x38, 0x48, 0x79, 0x1d, 0xde, 0x84, 0x37, 0xc3, 0xb1, 0xd3, 0x2e, 0x9b, 0x0a, 0x7f, 0xd9, 0xbe, 0xfb, 0xdc, 0x9d, 0xef, 0x7b, 0x07, 0xfb, 0xcb, 0x24, 0x16, 0xf1, 0x5b, 0x5f, 0x1d, 0x47, 0xfa, 0xe1, 0xa9, 0x03, 0x39, 0x55, 0x57, 0x7b, 0x7f, 0x16, 0xc7, 0xb3, 0x05, 0xd3, 0x48, 0x90, 0x4d, 0x8f, 0x28, 0xcf, 0x35, 0xd8, 0x7e, 0x28, 0x58, 0x2a, 0x26, 0x54, 0xd0, 0xa3, 0xe2, 0xa2, 0x8d, 0x9d, 0x3f, 0x26, 0x34, 0x2f, 0x59, 0x9a, 0xd2, 0x19, 0x43, 0x08, 0x1a, 0x9c, 0x46, 0x0c, 0x1b, 0x07, 0xc6, 0xe1, 0x36, 0x51, 0x77, 0x74, 0x0c, 0xd6, 0x3c, 0x5c, 0xd0, 0x24, 0x14, 0x39, 0xae, 0x49, 0xfb, 0x4e, 0xf7, 0xb1, 0x57, 0x2d, 0xe8, 0x95, 0xc1, 0xde, 0xd7, 0x2c, 0x8a, 0xb3, 0x84, 0xac, 0x69, 0x74, 0x00, 0xce, 0x9c, 0x85, 0xb3, 0xb9, 0xf0, 0x43, 0xee, 0x8f, 0x23, 0x5c, 0x97, 0xd1, 0x2d, 0x02, 0xda, 0xd6, 0xe3, 0x67, 0x51, 0x51, 0xaf, 0xf8, 0x0e, 0x6e, 0x48, 0x8f, 0x43, 0xd4, 0x1d, 0x3d, 0x05, 0x27, 0x61, 0x69, 0xb6, 0x10, 0xfe, 0x38, 0xce, 0xb8, 0xc0, 0x4d, 0xe9, 0xab, 0x13, 0x5b, 0xdb, 0xce, 0x0a, 0x13, 0x7a, 0x06, 0x2d, 0x91, 0x64, 0xcc, 0x4f, 0xc7, 0xb1, 0x48, 0x23, 0xca, 0xb1, 0x25, 0x19, 0x8b, 0x38, 0x85, 0x71, 0x54, 0xda, 0xd0, 0x1e, 0x6c, 0x49, 0x7f, 0xc2, 0xf0, 0xb6, 0x74, 0xd6, 0x88, 0x7e, 0x20, 0x17, 0xea, 0x3f, 0x59, 0x8e, 0xb7, 0x0e, 0xea, 0x87, 0x0d, 0x52, 0x5c, 0xd1, 0x2b, 0x30, 0xb9, 0x54, 0x83, 0x4d, 0xb0, 0x29, 0x41, 0xbb, 0xbb, 0x77, 0xb7, 0xbb, 0x81, 0xf2, 0x91, 0x92, 0x41, 0x1f, 0xa0, 0x29, 0x58, 0x92, 0xd0, 0x90, 0x63, 0x90, 0x39, 0xec, 0x6e, 0x67, 0xb3, 0x18, 0x57, 0x1a, 0x3a, 0xe7, 0x22, 0xc9, 0xc9, 0x2a, 0x44, 0x6a, 0xa9, 0x67, 0xd5, 0xf5, 0xa7, 0x21, 0x5b, 0x4c, 0xb0, 0xad, 0x2a, 0x3e, 0xf2, 0x56, 0x73, 0xf1, 0x46, 0x59, 0xf0, 0x99, 0x4d, 0xa9, 0xec, 0x34, 0x25, 0xb6, 0x46, 0xbf, 0x14, 0x24, 0xea, 0xad, 0x23, 0x7f, 0xd1, 0x45, 0xc6, 0x70, 0x4b, 0x15, 0x7f, 0xbe, 0xb9, 0xf8, 0x50, 0x91, 0xdf, 0x0b, 0x50, 0x7f, 0xa0, 0x4c, 0xa5, 0x2c, 0xe8, 0x0d, 0x58, 0x72, 0x25, 0xc4, 0x3c, 0xe4, 0x33, 0xbc, 0x53, 0xb6, 0xac, 0x77, 0xc6, 0x5b, 0xed, 0x8c, 0x77, 0xc2, 0x73, 0xb2, 0xa6, 0xd0, 0x3b, 0xb0, 0xa5, 0xa2, 0xb9, 0xaf, 0x5e, 0x29, 0xde, 0x55, 0xb5, 0x37, 0x07, 0x41, 0x01, 0x5e, 0x29, 0xae, 0x3d, 0x04, 0xa7, 0x2a, 0xc3, 0x4a, 0x7b, 0xbd, 0x5c, 0x4a, 0xfb, 0x17, 0xb0, 0xa5, 0xdb, 0xa9, 0xfd, 0x47, 0x7a, 0x8d, 0xbc, 0xaf, 0x1d, 0x1b, 0xed, 0x6b, 0x70, 0xef, 0xf7, 0xb6, 0x21, 0xeb, 0xcb, 0xbb, 0x59, 0xff, 0x21, 0xef, 0x6d, 0xda, 0xce, 0x27, 0x30, 0xf5, 0xf2, 0x22, 0x1b, 0x9a, 0xd7, 0x83, 0x8b, 0xc1, 0xb7, 0x9b, 0x81, 0xfb, 0x00, 0x59, 0xd0, 0x18, 0x5e, 0x0f, 0x46, 0xae, 0x81, 0x5a, 0xb0, 0x3d, 0xea, 0x9f, 0x0c, 0x47, 0x57, 0xbd, 0xb3, 0x0b, 0xb7, 0x86, 0x76, 0xc1, 0x3e, 0xed, 0xf5, 0xfb, 0xfe, 0xe9, 0x49, 0xaf, 0x7f, 0xfe, 0xc3, 0xad, 0x77, 0x9e, 0x80, 0xa9, 0x3f, 0x5b, 0x6c, 0x5d, 0x90, 0x71, 0xbe, 0xfa, 0x8f, 0x7e, 0x74, 0x7e, 0x1b, 0xb0, 0x53, 0x0e, 0xe7, 0x26, 0x14, 0xf3, 0x4b, 0xba, 0x44, 0x52, 0x9c, 0x20, 0x17, 0xcc, 0x8f, 0xe8, 0x72, 0x59, 0x4c, 0xc2, 0x50, 0xa2, 0xbe, 0xde, 0x38, 0xd0, 0x32, 0xc6, 0x3b, 0x95, 0x01, 0x97, 0x9a, 0x2f, 0xe7, 0x1a, 0xdc, 0x5a, 0xda, 0x1f, 0xc1, 0xbd, 0x0f, 0x54, 0xc5, 0xb1, 0xb4, 0x38, 0x7b, 0x55, 0x71, 0x9c, 0x8a, 0x0a, 0x81, 0xa9, 0x4b, 0xff, 0x0d, 0x00, 0x00, 0xff, 0xff, 0xab, 0x07, 0xe8, 0xfe, 0x6a, 0x04, 0x00, 0x00, } lxd-2.0.0/dist/src/github.com/golang/protobuf/proto/size2_test.go0000644061062106075000000000443612702772352027411 0ustar00stgraberdomain admins00000000000000// Go support for Protocol Buffers - Google's data interchange format // // Copyright 2012 The Go Authors. All rights reserved. // https://github.com/golang/protobuf // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package proto import ( "testing" ) // This is a separate file and package from size_test.go because that one uses // generated messages and thus may not be in package proto without having a circular // dependency, whereas this file tests unexported details of size.go. func TestVarintSize(t *testing.T) { // Check the edge cases carefully. testCases := []struct { n uint64 size int }{ {0, 1}, {1, 1}, {127, 1}, {128, 2}, {16383, 2}, {16384, 3}, {1<<63 - 1, 9}, {1 << 63, 10}, } for _, tc := range testCases { size := sizeVarint(tc.n) if size != tc.size { t.Errorf("sizeVarint(%d) = %d, want %d", tc.n, size, tc.size) } } } lxd-2.0.0/dist/src/github.com/golang/protobuf/proto/pointer_reflect.go0000644061062106075000000003255312702772352030503 0ustar00stgraberdomain admins00000000000000// Go support for Protocol Buffers - Google's data interchange format // // Copyright 2012 The Go Authors. All rights reserved. // https://github.com/golang/protobuf // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // +build appengine js // This file contains an implementation of proto field accesses using package reflect. // It is slower than the code in pointer_unsafe.go but it avoids package unsafe and can // be used on App Engine. package proto import ( "math" "reflect" ) // A structPointer is a pointer to a struct. type structPointer struct { v reflect.Value } // toStructPointer returns a structPointer equivalent to the given reflect value. // The reflect value must itself be a pointer to a struct. func toStructPointer(v reflect.Value) structPointer { return structPointer{v} } // IsNil reports whether p is nil. func structPointer_IsNil(p structPointer) bool { return p.v.IsNil() } // Interface returns the struct pointer as an interface value. func structPointer_Interface(p structPointer, _ reflect.Type) interface{} { return p.v.Interface() } // A field identifies a field in a struct, accessible from a structPointer. // In this implementation, a field is identified by the sequence of field indices // passed to reflect's FieldByIndex. type field []int // toField returns a field equivalent to the given reflect field. func toField(f *reflect.StructField) field { return f.Index } // invalidField is an invalid field identifier. var invalidField = field(nil) // IsValid reports whether the field identifier is valid. func (f field) IsValid() bool { return f != nil } // field returns the given field in the struct as a reflect value. func structPointer_field(p structPointer, f field) reflect.Value { // Special case: an extension map entry with a value of type T // passes a *T to the struct-handling code with a zero field, // expecting that it will be treated as equivalent to *struct{ X T }, // which has the same memory layout. We have to handle that case // specially, because reflect will panic if we call FieldByIndex on a // non-struct. if f == nil { return p.v.Elem() } return p.v.Elem().FieldByIndex(f) } // ifield returns the given field in the struct as an interface value. func structPointer_ifield(p structPointer, f field) interface{} { return structPointer_field(p, f).Addr().Interface() } // Bytes returns the address of a []byte field in the struct. func structPointer_Bytes(p structPointer, f field) *[]byte { return structPointer_ifield(p, f).(*[]byte) } // BytesSlice returns the address of a [][]byte field in the struct. func structPointer_BytesSlice(p structPointer, f field) *[][]byte { return structPointer_ifield(p, f).(*[][]byte) } // Bool returns the address of a *bool field in the struct. func structPointer_Bool(p structPointer, f field) **bool { return structPointer_ifield(p, f).(**bool) } // BoolVal returns the address of a bool field in the struct. func structPointer_BoolVal(p structPointer, f field) *bool { return structPointer_ifield(p, f).(*bool) } // BoolSlice returns the address of a []bool field in the struct. func structPointer_BoolSlice(p structPointer, f field) *[]bool { return structPointer_ifield(p, f).(*[]bool) } // String returns the address of a *string field in the struct. func structPointer_String(p structPointer, f field) **string { return structPointer_ifield(p, f).(**string) } // StringVal returns the address of a string field in the struct. func structPointer_StringVal(p structPointer, f field) *string { return structPointer_ifield(p, f).(*string) } // StringSlice returns the address of a []string field in the struct. func structPointer_StringSlice(p structPointer, f field) *[]string { return structPointer_ifield(p, f).(*[]string) } // ExtMap returns the address of an extension map field in the struct. func structPointer_ExtMap(p structPointer, f field) *map[int32]Extension { return structPointer_ifield(p, f).(*map[int32]Extension) } // NewAt returns the reflect.Value for a pointer to a field in the struct. func structPointer_NewAt(p structPointer, f field, typ reflect.Type) reflect.Value { return structPointer_field(p, f).Addr() } // SetStructPointer writes a *struct field in the struct. func structPointer_SetStructPointer(p structPointer, f field, q structPointer) { structPointer_field(p, f).Set(q.v) } // GetStructPointer reads a *struct field in the struct. func structPointer_GetStructPointer(p structPointer, f field) structPointer { return structPointer{structPointer_field(p, f)} } // StructPointerSlice the address of a []*struct field in the struct. func structPointer_StructPointerSlice(p structPointer, f field) structPointerSlice { return structPointerSlice{structPointer_field(p, f)} } // A structPointerSlice represents the address of a slice of pointers to structs // (themselves messages or groups). That is, v.Type() is *[]*struct{...}. type structPointerSlice struct { v reflect.Value } func (p structPointerSlice) Len() int { return p.v.Len() } func (p structPointerSlice) Index(i int) structPointer { return structPointer{p.v.Index(i)} } func (p structPointerSlice) Append(q structPointer) { p.v.Set(reflect.Append(p.v, q.v)) } var ( int32Type = reflect.TypeOf(int32(0)) uint32Type = reflect.TypeOf(uint32(0)) float32Type = reflect.TypeOf(float32(0)) int64Type = reflect.TypeOf(int64(0)) uint64Type = reflect.TypeOf(uint64(0)) float64Type = reflect.TypeOf(float64(0)) ) // A word32 represents a field of type *int32, *uint32, *float32, or *enum. // That is, v.Type() is *int32, *uint32, *float32, or *enum and v is assignable. type word32 struct { v reflect.Value } // IsNil reports whether p is nil. func word32_IsNil(p word32) bool { return p.v.IsNil() } // Set sets p to point at a newly allocated word with bits set to x. func word32_Set(p word32, o *Buffer, x uint32) { t := p.v.Type().Elem() switch t { case int32Type: if len(o.int32s) == 0 { o.int32s = make([]int32, uint32PoolSize) } o.int32s[0] = int32(x) p.v.Set(reflect.ValueOf(&o.int32s[0])) o.int32s = o.int32s[1:] return case uint32Type: if len(o.uint32s) == 0 { o.uint32s = make([]uint32, uint32PoolSize) } o.uint32s[0] = x p.v.Set(reflect.ValueOf(&o.uint32s[0])) o.uint32s = o.uint32s[1:] return case float32Type: if len(o.float32s) == 0 { o.float32s = make([]float32, uint32PoolSize) } o.float32s[0] = math.Float32frombits(x) p.v.Set(reflect.ValueOf(&o.float32s[0])) o.float32s = o.float32s[1:] return } // must be enum p.v.Set(reflect.New(t)) p.v.Elem().SetInt(int64(int32(x))) } // Get gets the bits pointed at by p, as a uint32. func word32_Get(p word32) uint32 { elem := p.v.Elem() switch elem.Kind() { case reflect.Int32: return uint32(elem.Int()) case reflect.Uint32: return uint32(elem.Uint()) case reflect.Float32: return math.Float32bits(float32(elem.Float())) } panic("unreachable") } // Word32 returns a reference to a *int32, *uint32, *float32, or *enum field in the struct. func structPointer_Word32(p structPointer, f field) word32 { return word32{structPointer_field(p, f)} } // A word32Val represents a field of type int32, uint32, float32, or enum. // That is, v.Type() is int32, uint32, float32, or enum and v is assignable. type word32Val struct { v reflect.Value } // Set sets *p to x. func word32Val_Set(p word32Val, x uint32) { switch p.v.Type() { case int32Type: p.v.SetInt(int64(x)) return case uint32Type: p.v.SetUint(uint64(x)) return case float32Type: p.v.SetFloat(float64(math.Float32frombits(x))) return } // must be enum p.v.SetInt(int64(int32(x))) } // Get gets the bits pointed at by p, as a uint32. func word32Val_Get(p word32Val) uint32 { elem := p.v switch elem.Kind() { case reflect.Int32: return uint32(elem.Int()) case reflect.Uint32: return uint32(elem.Uint()) case reflect.Float32: return math.Float32bits(float32(elem.Float())) } panic("unreachable") } // Word32Val returns a reference to a int32, uint32, float32, or enum field in the struct. func structPointer_Word32Val(p structPointer, f field) word32Val { return word32Val{structPointer_field(p, f)} } // A word32Slice is a slice of 32-bit values. // That is, v.Type() is []int32, []uint32, []float32, or []enum. type word32Slice struct { v reflect.Value } func (p word32Slice) Append(x uint32) { n, m := p.v.Len(), p.v.Cap() if n < m { p.v.SetLen(n + 1) } else { t := p.v.Type().Elem() p.v.Set(reflect.Append(p.v, reflect.Zero(t))) } elem := p.v.Index(n) switch elem.Kind() { case reflect.Int32: elem.SetInt(int64(int32(x))) case reflect.Uint32: elem.SetUint(uint64(x)) case reflect.Float32: elem.SetFloat(float64(math.Float32frombits(x))) } } func (p word32Slice) Len() int { return p.v.Len() } func (p word32Slice) Index(i int) uint32 { elem := p.v.Index(i) switch elem.Kind() { case reflect.Int32: return uint32(elem.Int()) case reflect.Uint32: return uint32(elem.Uint()) case reflect.Float32: return math.Float32bits(float32(elem.Float())) } panic("unreachable") } // Word32Slice returns a reference to a []int32, []uint32, []float32, or []enum field in the struct. func structPointer_Word32Slice(p structPointer, f field) word32Slice { return word32Slice{structPointer_field(p, f)} } // word64 is like word32 but for 64-bit values. type word64 struct { v reflect.Value } func word64_Set(p word64, o *Buffer, x uint64) { t := p.v.Type().Elem() switch t { case int64Type: if len(o.int64s) == 0 { o.int64s = make([]int64, uint64PoolSize) } o.int64s[0] = int64(x) p.v.Set(reflect.ValueOf(&o.int64s[0])) o.int64s = o.int64s[1:] return case uint64Type: if len(o.uint64s) == 0 { o.uint64s = make([]uint64, uint64PoolSize) } o.uint64s[0] = x p.v.Set(reflect.ValueOf(&o.uint64s[0])) o.uint64s = o.uint64s[1:] return case float64Type: if len(o.float64s) == 0 { o.float64s = make([]float64, uint64PoolSize) } o.float64s[0] = math.Float64frombits(x) p.v.Set(reflect.ValueOf(&o.float64s[0])) o.float64s = o.float64s[1:] return } panic("unreachable") } func word64_IsNil(p word64) bool { return p.v.IsNil() } func word64_Get(p word64) uint64 { elem := p.v.Elem() switch elem.Kind() { case reflect.Int64: return uint64(elem.Int()) case reflect.Uint64: return elem.Uint() case reflect.Float64: return math.Float64bits(elem.Float()) } panic("unreachable") } func structPointer_Word64(p structPointer, f field) word64 { return word64{structPointer_field(p, f)} } // word64Val is like word32Val but for 64-bit values. type word64Val struct { v reflect.Value } func word64Val_Set(p word64Val, o *Buffer, x uint64) { switch p.v.Type() { case int64Type: p.v.SetInt(int64(x)) return case uint64Type: p.v.SetUint(x) return case float64Type: p.v.SetFloat(math.Float64frombits(x)) return } panic("unreachable") } func word64Val_Get(p word64Val) uint64 { elem := p.v switch elem.Kind() { case reflect.Int64: return uint64(elem.Int()) case reflect.Uint64: return elem.Uint() case reflect.Float64: return math.Float64bits(elem.Float()) } panic("unreachable") } func structPointer_Word64Val(p structPointer, f field) word64Val { return word64Val{structPointer_field(p, f)} } type word64Slice struct { v reflect.Value } func (p word64Slice) Append(x uint64) { n, m := p.v.Len(), p.v.Cap() if n < m { p.v.SetLen(n + 1) } else { t := p.v.Type().Elem() p.v.Set(reflect.Append(p.v, reflect.Zero(t))) } elem := p.v.Index(n) switch elem.Kind() { case reflect.Int64: elem.SetInt(int64(int64(x))) case reflect.Uint64: elem.SetUint(uint64(x)) case reflect.Float64: elem.SetFloat(float64(math.Float64frombits(x))) } } func (p word64Slice) Len() int { return p.v.Len() } func (p word64Slice) Index(i int) uint64 { elem := p.v.Index(i) switch elem.Kind() { case reflect.Int64: return uint64(elem.Int()) case reflect.Uint64: return uint64(elem.Uint()) case reflect.Float64: return math.Float64bits(float64(elem.Float())) } panic("unreachable") } func structPointer_Word64Slice(p structPointer, f field) word64Slice { return word64Slice{structPointer_field(p, f)} } lxd-2.0.0/dist/src/github.com/golang/protobuf/proto/message_set_test.go0000644061062106075000000000475712702772352030662 0ustar00stgraberdomain admins00000000000000// Go support for Protocol Buffers - Google's data interchange format // // Copyright 2014 The Go Authors. All rights reserved. // https://github.com/golang/protobuf // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package proto import ( "bytes" "testing" ) func TestUnmarshalMessageSetWithDuplicate(t *testing.T) { // Check that a repeated message set entry will be concatenated. in := &messageSet{ Item: []*_MessageSet_Item{ {TypeId: Int32(12345), Message: []byte("hoo")}, {TypeId: Int32(12345), Message: []byte("hah")}, }, } b, err := Marshal(in) if err != nil { t.Fatalf("Marshal: %v", err) } t.Logf("Marshaled bytes: %q", b) m := make(map[int32]Extension) if err := UnmarshalMessageSet(b, m); err != nil { t.Fatalf("UnmarshalMessageSet: %v", err) } ext, ok := m[12345] if !ok { t.Fatalf("Didn't retrieve extension 12345; map is %v", m) } // Skip wire type/field number and length varints. got := skipVarint(skipVarint(ext.enc)) if want := []byte("hoohah"); !bytes.Equal(got, want) { t.Errorf("Combined extension is %q, want %q", got, want) } } lxd-2.0.0/dist/src/github.com/golang/protobuf/proto/clone_test.go0000644061062106075000000001566412702772352027462 0ustar00stgraberdomain admins00000000000000// Go support for Protocol Buffers - Google's data interchange format // // Copyright 2011 The Go Authors. All rights reserved. // https://github.com/golang/protobuf // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package proto_test import ( "testing" "github.com/golang/protobuf/proto" proto3pb "github.com/golang/protobuf/proto/proto3_proto" pb "github.com/golang/protobuf/proto/testdata" ) var cloneTestMessage = &pb.MyMessage{ Count: proto.Int32(42), Name: proto.String("Dave"), Pet: []string{"bunny", "kitty", "horsey"}, Inner: &pb.InnerMessage{ Host: proto.String("niles"), Port: proto.Int32(9099), Connected: proto.Bool(true), }, Others: []*pb.OtherMessage{ { Value: []byte("some bytes"), }, }, Somegroup: &pb.MyMessage_SomeGroup{ GroupField: proto.Int32(6), }, RepBytes: [][]byte{[]byte("sham"), []byte("wow")}, } func init() { ext := &pb.Ext{ Data: proto.String("extension"), } if err := proto.SetExtension(cloneTestMessage, pb.E_Ext_More, ext); err != nil { panic("SetExtension: " + err.Error()) } } func TestClone(t *testing.T) { m := proto.Clone(cloneTestMessage).(*pb.MyMessage) if !proto.Equal(m, cloneTestMessage) { t.Errorf("Clone(%v) = %v", cloneTestMessage, m) } // Verify it was a deep copy. *m.Inner.Port++ if proto.Equal(m, cloneTestMessage) { t.Error("Mutating clone changed the original") } // Byte fields and repeated fields should be copied. if &m.Pet[0] == &cloneTestMessage.Pet[0] { t.Error("Pet: repeated field not copied") } if &m.Others[0] == &cloneTestMessage.Others[0] { t.Error("Others: repeated field not copied") } if &m.Others[0].Value[0] == &cloneTestMessage.Others[0].Value[0] { t.Error("Others[0].Value: bytes field not copied") } if &m.RepBytes[0] == &cloneTestMessage.RepBytes[0] { t.Error("RepBytes: repeated field not copied") } if &m.RepBytes[0][0] == &cloneTestMessage.RepBytes[0][0] { t.Error("RepBytes[0]: bytes field not copied") } } func TestCloneNil(t *testing.T) { var m *pb.MyMessage if c := proto.Clone(m); !proto.Equal(m, c) { t.Errorf("Clone(%v) = %v", m, c) } } var mergeTests = []struct { src, dst, want proto.Message }{ { src: &pb.MyMessage{ Count: proto.Int32(42), }, dst: &pb.MyMessage{ Name: proto.String("Dave"), }, want: &pb.MyMessage{ Count: proto.Int32(42), Name: proto.String("Dave"), }, }, { src: &pb.MyMessage{ Inner: &pb.InnerMessage{ Host: proto.String("hey"), Connected: proto.Bool(true), }, Pet: []string{"horsey"}, Others: []*pb.OtherMessage{ { Value: []byte("some bytes"), }, }, }, dst: &pb.MyMessage{ Inner: &pb.InnerMessage{ Host: proto.String("niles"), Port: proto.Int32(9099), }, Pet: []string{"bunny", "kitty"}, Others: []*pb.OtherMessage{ { Key: proto.Int64(31415926535), }, { // Explicitly test a src=nil field Inner: nil, }, }, }, want: &pb.MyMessage{ Inner: &pb.InnerMessage{ Host: proto.String("hey"), Connected: proto.Bool(true), Port: proto.Int32(9099), }, Pet: []string{"bunny", "kitty", "horsey"}, Others: []*pb.OtherMessage{ { Key: proto.Int64(31415926535), }, {}, { Value: []byte("some bytes"), }, }, }, }, { src: &pb.MyMessage{ RepBytes: [][]byte{[]byte("wow")}, }, dst: &pb.MyMessage{ Somegroup: &pb.MyMessage_SomeGroup{ GroupField: proto.Int32(6), }, RepBytes: [][]byte{[]byte("sham")}, }, want: &pb.MyMessage{ Somegroup: &pb.MyMessage_SomeGroup{ GroupField: proto.Int32(6), }, RepBytes: [][]byte{[]byte("sham"), []byte("wow")}, }, }, // Check that a scalar bytes field replaces rather than appends. { src: &pb.OtherMessage{Value: []byte("foo")}, dst: &pb.OtherMessage{Value: []byte("bar")}, want: &pb.OtherMessage{Value: []byte("foo")}, }, { src: &pb.MessageWithMap{ NameMapping: map[int32]string{6: "Nigel"}, MsgMapping: map[int64]*pb.FloatingPoint{ 0x4001: &pb.FloatingPoint{F: proto.Float64(2.0)}, }, ByteMapping: map[bool][]byte{true: []byte("wowsa")}, }, dst: &pb.MessageWithMap{ NameMapping: map[int32]string{ 6: "Bruce", // should be overwritten 7: "Andrew", }, }, want: &pb.MessageWithMap{ NameMapping: map[int32]string{ 6: "Nigel", 7: "Andrew", }, MsgMapping: map[int64]*pb.FloatingPoint{ 0x4001: &pb.FloatingPoint{F: proto.Float64(2.0)}, }, ByteMapping: map[bool][]byte{true: []byte("wowsa")}, }, }, // proto3 shouldn't merge zero values, // in the same way that proto2 shouldn't merge nils. { src: &proto3pb.Message{ Name: "Aaron", Data: []byte(""), // zero value, but not nil }, dst: &proto3pb.Message{ HeightInCm: 176, Data: []byte("texas!"), }, want: &proto3pb.Message{ Name: "Aaron", HeightInCm: 176, Data: []byte("texas!"), }, }, // Oneof fields should merge by assignment. { src: &pb.Communique{ Union: &pb.Communique_Number{41}, }, dst: &pb.Communique{ Union: &pb.Communique_Name{"Bobby Tables"}, }, want: &pb.Communique{ Union: &pb.Communique_Number{41}, }, }, // Oneof nil is the same as not set. { src: &pb.Communique{}, dst: &pb.Communique{ Union: &pb.Communique_Name{"Bobby Tables"}, }, want: &pb.Communique{ Union: &pb.Communique_Name{"Bobby Tables"}, }, }, } func TestMerge(t *testing.T) { for _, m := range mergeTests { got := proto.Clone(m.dst) proto.Merge(got, m.src) if !proto.Equal(got, m.want) { t.Errorf("Merge(%v, %v)\n got %v\nwant %v\n", m.dst, m.src, got, m.want) } } } lxd-2.0.0/dist/src/github.com/golang/protobuf/proto/clone.go0000644061062106075000000001534312702772352026415 0ustar00stgraberdomain admins00000000000000// Go support for Protocol Buffers - Google's data interchange format // // Copyright 2011 The Go Authors. All rights reserved. // https://github.com/golang/protobuf // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Protocol buffer deep copy and merge. // TODO: RawMessage. package proto import ( "log" "reflect" "strings" ) // Clone returns a deep copy of a protocol buffer. func Clone(pb Message) Message { in := reflect.ValueOf(pb) if in.IsNil() { return pb } out := reflect.New(in.Type().Elem()) // out is empty so a merge is a deep copy. mergeStruct(out.Elem(), in.Elem()) return out.Interface().(Message) } // Merge merges src into dst. // Required and optional fields that are set in src will be set to that value in dst. // Elements of repeated fields will be appended. // Merge panics if src and dst are not the same type, or if dst is nil. func Merge(dst, src Message) { in := reflect.ValueOf(src) out := reflect.ValueOf(dst) if out.IsNil() { panic("proto: nil destination") } if in.Type() != out.Type() { // Explicit test prior to mergeStruct so that mistyped nils will fail panic("proto: type mismatch") } if in.IsNil() { // Merging nil into non-nil is a quiet no-op return } mergeStruct(out.Elem(), in.Elem()) } func mergeStruct(out, in reflect.Value) { sprop := GetProperties(in.Type()) for i := 0; i < in.NumField(); i++ { f := in.Type().Field(i) if strings.HasPrefix(f.Name, "XXX_") { continue } mergeAny(out.Field(i), in.Field(i), false, sprop.Prop[i]) } if emIn, ok := in.Addr().Interface().(extendableProto); ok { emOut := out.Addr().Interface().(extendableProto) mergeExtension(emOut.ExtensionMap(), emIn.ExtensionMap()) } uf := in.FieldByName("XXX_unrecognized") if !uf.IsValid() { return } uin := uf.Bytes() if len(uin) > 0 { out.FieldByName("XXX_unrecognized").SetBytes(append([]byte(nil), uin...)) } } // mergeAny performs a merge between two values of the same type. // viaPtr indicates whether the values were indirected through a pointer (implying proto2). // prop is set if this is a struct field (it may be nil). func mergeAny(out, in reflect.Value, viaPtr bool, prop *Properties) { if in.Type() == protoMessageType { if !in.IsNil() { if out.IsNil() { out.Set(reflect.ValueOf(Clone(in.Interface().(Message)))) } else { Merge(out.Interface().(Message), in.Interface().(Message)) } } return } switch in.Kind() { case reflect.Bool, reflect.Float32, reflect.Float64, reflect.Int32, reflect.Int64, reflect.String, reflect.Uint32, reflect.Uint64: if !viaPtr && isProto3Zero(in) { return } out.Set(in) case reflect.Interface: // Probably a oneof field; copy non-nil values. if in.IsNil() { return } // Allocate destination if it is not set, or set to a different type. // Otherwise we will merge as normal. if out.IsNil() || out.Elem().Type() != in.Elem().Type() { out.Set(reflect.New(in.Elem().Elem().Type())) // interface -> *T -> T -> new(T) } mergeAny(out.Elem(), in.Elem(), false, nil) case reflect.Map: if in.Len() == 0 { return } if out.IsNil() { out.Set(reflect.MakeMap(in.Type())) } // For maps with value types of *T or []byte we need to deep copy each value. elemKind := in.Type().Elem().Kind() for _, key := range in.MapKeys() { var val reflect.Value switch elemKind { case reflect.Ptr: val = reflect.New(in.Type().Elem().Elem()) mergeAny(val, in.MapIndex(key), false, nil) case reflect.Slice: val = in.MapIndex(key) val = reflect.ValueOf(append([]byte{}, val.Bytes()...)) default: val = in.MapIndex(key) } out.SetMapIndex(key, val) } case reflect.Ptr: if in.IsNil() { return } if out.IsNil() { out.Set(reflect.New(in.Elem().Type())) } mergeAny(out.Elem(), in.Elem(), true, nil) case reflect.Slice: if in.IsNil() { return } if in.Type().Elem().Kind() == reflect.Uint8 { // []byte is a scalar bytes field, not a repeated field. // Edge case: if this is in a proto3 message, a zero length // bytes field is considered the zero value, and should not // be merged. if prop != nil && prop.proto3 && in.Len() == 0 { return } // Make a deep copy. // Append to []byte{} instead of []byte(nil) so that we never end up // with a nil result. out.SetBytes(append([]byte{}, in.Bytes()...)) return } n := in.Len() if out.IsNil() { out.Set(reflect.MakeSlice(in.Type(), 0, n)) } switch in.Type().Elem().Kind() { case reflect.Bool, reflect.Float32, reflect.Float64, reflect.Int32, reflect.Int64, reflect.String, reflect.Uint32, reflect.Uint64: out.Set(reflect.AppendSlice(out, in)) default: for i := 0; i < n; i++ { x := reflect.Indirect(reflect.New(in.Type().Elem())) mergeAny(x, in.Index(i), false, nil) out.Set(reflect.Append(out, x)) } } case reflect.Struct: mergeStruct(out, in) default: // unknown type, so not a protocol buffer log.Printf("proto: don't know how to copy %v", in) } } func mergeExtension(out, in map[int32]Extension) { for extNum, eIn := range in { eOut := Extension{desc: eIn.desc} if eIn.value != nil { v := reflect.New(reflect.TypeOf(eIn.value)).Elem() mergeAny(v, reflect.ValueOf(eIn.value), false, nil) eOut.value = v.Interface() } if eIn.enc != nil { eOut.enc = make([]byte, len(eIn.enc)) copy(eOut.enc, eIn.enc) } out[extNum] = eOut } } lxd-2.0.0/dist/src/github.com/golang/protobuf/proto/any_test.go0000644061062106075000000001753212702772352027145 0ustar00stgraberdomain admins00000000000000// Go support for Protocol Buffers - Google's data interchange format // // Copyright 2016 The Go Authors. All rights reserved. // https://github.com/golang/protobuf // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package proto_test import ( "strings" "testing" "github.com/golang/protobuf/proto" pb "github.com/golang/protobuf/proto/proto3_proto" testpb "github.com/golang/protobuf/proto/testdata" anypb "github.com/golang/protobuf/ptypes/any" ) var ( expandedMarshaler = proto.TextMarshaler{ExpandAny: true} expandedCompactMarshaler = proto.TextMarshaler{Compact: true, ExpandAny: true} ) // anyEqual reports whether two messages which may be google.protobuf.Any or may // contain google.protobuf.Any fields are equal. We can't use proto.Equal for // comparison, because semantically equivalent messages may be marshaled to // binary in different tag order. Instead, trust that TextMarshaler with // ExpandAny option works and compare the text marshaling results. func anyEqual(got, want proto.Message) bool { // if messages are proto.Equal, no need to marshal. if proto.Equal(got, want) { return true } g := expandedMarshaler.Text(got) w := expandedMarshaler.Text(want) return g == w } type golden struct { m proto.Message t, c string } var goldenMessages = makeGolden() func makeGolden() []golden { nested := &pb.Nested{Bunny: "Monty"} nb, err := proto.Marshal(nested) if err != nil { panic(err) } m1 := &pb.Message{ Name: "David", ResultCount: 47, Anything: &anypb.Any{TypeUrl: "type.googleapis.com/" + proto.MessageName(nested), Value: nb}, } m2 := &pb.Message{ Name: "David", ResultCount: 47, Anything: &anypb.Any{TypeUrl: "http://[::1]/type.googleapis.com/" + proto.MessageName(nested), Value: nb}, } m3 := &pb.Message{ Name: "David", ResultCount: 47, Anything: &anypb.Any{TypeUrl: `type.googleapis.com/"/` + proto.MessageName(nested), Value: nb}, } m4 := &pb.Message{ Name: "David", ResultCount: 47, Anything: &anypb.Any{TypeUrl: "type.googleapis.com/a/path/" + proto.MessageName(nested), Value: nb}, } m5 := &anypb.Any{TypeUrl: "type.googleapis.com/" + proto.MessageName(nested), Value: nb} any1 := &testpb.MyMessage{Count: proto.Int32(47), Name: proto.String("David")} proto.SetExtension(any1, testpb.E_Ext_More, &testpb.Ext{Data: proto.String("foo")}) proto.SetExtension(any1, testpb.E_Ext_Text, proto.String("bar")) any1b, err := proto.Marshal(any1) if err != nil { panic(err) } any2 := &testpb.MyMessage{Count: proto.Int32(42), Bikeshed: testpb.MyMessage_GREEN.Enum(), RepBytes: [][]byte{[]byte("roboto")}} proto.SetExtension(any2, testpb.E_Ext_More, &testpb.Ext{Data: proto.String("baz")}) any2b, err := proto.Marshal(any2) if err != nil { panic(err) } m6 := &pb.Message{ Name: "David", ResultCount: 47, Anything: &anypb.Any{TypeUrl: "type.googleapis.com/" + proto.MessageName(any1), Value: any1b}, ManyThings: []*anypb.Any{ &anypb.Any{TypeUrl: "type.googleapis.com/" + proto.MessageName(any2), Value: any2b}, &anypb.Any{TypeUrl: "type.googleapis.com/" + proto.MessageName(any1), Value: any1b}, }, } const ( m1Golden = ` name: "David" result_count: 47 anything: < [type.googleapis.com/proto3_proto.Nested]: < bunny: "Monty" > > ` m2Golden = ` name: "David" result_count: 47 anything: < ["http://[::1]/type.googleapis.com/proto3_proto.Nested"]: < bunny: "Monty" > > ` m3Golden = ` name: "David" result_count: 47 anything: < ["type.googleapis.com/\"/proto3_proto.Nested"]: < bunny: "Monty" > > ` m4Golden = ` name: "David" result_count: 47 anything: < [type.googleapis.com/a/path/proto3_proto.Nested]: < bunny: "Monty" > > ` m5Golden = ` [type.googleapis.com/proto3_proto.Nested]: < bunny: "Monty" > ` m6Golden = ` name: "David" result_count: 47 anything: < [type.googleapis.com/testdata.MyMessage]: < count: 47 name: "David" [testdata.Ext.more]: < data: "foo" > [testdata.Ext.text]: "bar" > > many_things: < [type.googleapis.com/testdata.MyMessage]: < count: 42 bikeshed: GREEN rep_bytes: "roboto" [testdata.Ext.more]: < data: "baz" > > > many_things: < [type.googleapis.com/testdata.MyMessage]: < count: 47 name: "David" [testdata.Ext.more]: < data: "foo" > [testdata.Ext.text]: "bar" > > ` ) return []golden{ {m1, strings.TrimSpace(m1Golden) + "\n", strings.TrimSpace(compact(m1Golden)) + " "}, {m2, strings.TrimSpace(m2Golden) + "\n", strings.TrimSpace(compact(m2Golden)) + " "}, {m3, strings.TrimSpace(m3Golden) + "\n", strings.TrimSpace(compact(m3Golden)) + " "}, {m4, strings.TrimSpace(m4Golden) + "\n", strings.TrimSpace(compact(m4Golden)) + " "}, {m5, strings.TrimSpace(m5Golden) + "\n", strings.TrimSpace(compact(m5Golden)) + " "}, {m6, strings.TrimSpace(m6Golden) + "\n", strings.TrimSpace(compact(m6Golden)) + " "}, } } func TestMarshalGolden(t *testing.T) { for _, tt := range goldenMessages { if got, want := expandedMarshaler.Text(tt.m), tt.t; got != want { t.Errorf("message %v: got:\n%s\nwant:\n%s", tt.m, got, want) } if got, want := expandedCompactMarshaler.Text(tt.m), tt.c; got != want { t.Errorf("message %v: got:\n`%s`\nwant:\n`%s`", tt.m, got, want) } } } func TestUnmarshalGolden(t *testing.T) { for _, tt := range goldenMessages { want := tt.m got := proto.Clone(tt.m) got.Reset() if err := proto.UnmarshalText(tt.t, got); err != nil { t.Errorf("failed to unmarshal\n%s\nerror: %v", tt.t, err) } if !anyEqual(got, want) { t.Errorf("message:\n%s\ngot:\n%s\nwant:\n%s", tt.t, got, want) } got.Reset() if err := proto.UnmarshalText(tt.c, got); err != nil { t.Errorf("failed to unmarshal\n%s\nerror: %v", tt.c, err) } if !anyEqual(got, want) { t.Errorf("message:\n%s\ngot:\n%s\nwant:\n%s", tt.c, got, want) } } } func TestMarsahlUnknownAny(t *testing.T) { m := &pb.Message{ Anything: &anypb.Any{ TypeUrl: "foo", Value: []byte("bar"), }, } want := `anything: < type_url: "foo" value: "bar" > ` got := expandedMarshaler.Text(m) if got != want { t.Errorf("got\n`%s`\nwant\n`%s`", got, want) } } func TestAmbiguousAny(t *testing.T) { pb := &anypb.Any{} err := proto.UnmarshalText(` [type.googleapis.com/proto3_proto.Nested]: < bunny: "Monty" > type_url: "ttt/proto3_proto.Nested" `, pb) t.Logf("result: %v (error: %v)", expandedMarshaler.Text(pb), err) if err != nil { t.Errorf("failed to parse ambiguous Any message: %v", err) } } lxd-2.0.0/dist/src/github.com/golang/protobuf/proto/proto3_test.go0000644061062106075000000000773112702772352027604 0ustar00stgraberdomain admins00000000000000// Go support for Protocol Buffers - Google's data interchange format // // Copyright 2014 The Go Authors. All rights reserved. // https://github.com/golang/protobuf // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package proto_test import ( "testing" "github.com/golang/protobuf/proto" pb "github.com/golang/protobuf/proto/proto3_proto" tpb "github.com/golang/protobuf/proto/testdata" ) func TestProto3ZeroValues(t *testing.T) { tests := []struct { desc string m proto.Message }{ {"zero message", &pb.Message{}}, {"empty bytes field", &pb.Message{Data: []byte{}}}, } for _, test := range tests { b, err := proto.Marshal(test.m) if err != nil { t.Errorf("%s: proto.Marshal: %v", test.desc, err) continue } if len(b) > 0 { t.Errorf("%s: Encoding is non-empty: %q", test.desc, b) } } } func TestRoundTripProto3(t *testing.T) { m := &pb.Message{ Name: "David", // (2 | 1<<3): 0x0a 0x05 "David" Hilarity: pb.Message_PUNS, // (0 | 2<<3): 0x10 0x01 HeightInCm: 178, // (0 | 3<<3): 0x18 0xb2 0x01 Data: []byte("roboto"), // (2 | 4<<3): 0x20 0x06 "roboto" ResultCount: 47, // (0 | 7<<3): 0x38 0x2f TrueScotsman: true, // (0 | 8<<3): 0x40 0x01 Score: 8.1, // (5 | 9<<3): 0x4d <8.1> Key: []uint64{1, 0xdeadbeef}, Nested: &pb.Nested{ Bunny: "Monty", }, } t.Logf(" m: %v", m) b, err := proto.Marshal(m) if err != nil { t.Fatalf("proto.Marshal: %v", err) } t.Logf(" b: %q", b) m2 := new(pb.Message) if err := proto.Unmarshal(b, m2); err != nil { t.Fatalf("proto.Unmarshal: %v", err) } t.Logf("m2: %v", m2) if !proto.Equal(m, m2) { t.Errorf("proto.Equal returned false:\n m: %v\nm2: %v", m, m2) } } func TestProto3SetDefaults(t *testing.T) { in := &pb.Message{ Terrain: map[string]*pb.Nested{ "meadow": new(pb.Nested), }, Proto2Field: new(tpb.SubDefaults), Proto2Value: map[string]*tpb.SubDefaults{ "badlands": new(tpb.SubDefaults), }, } got := proto.Clone(in).(*pb.Message) proto.SetDefaults(got) // There are no defaults in proto3. Everything should be the zero value, but // we need to remember to set defaults for nested proto2 messages. want := &pb.Message{ Terrain: map[string]*pb.Nested{ "meadow": new(pb.Nested), }, Proto2Field: &tpb.SubDefaults{N: proto.Int64(7)}, Proto2Value: map[string]*tpb.SubDefaults{ "badlands": &tpb.SubDefaults{N: proto.Int64(7)}, }, } if !proto.Equal(got, want) { t.Errorf("with in = %v\nproto.SetDefaults(in) =>\ngot %v\nwant %v", in, got, want) } } lxd-2.0.0/dist/src/github.com/golang/protobuf/proto/extensions.go0000644061062106075000000003120712702772352027511 0ustar00stgraberdomain admins00000000000000// Go support for Protocol Buffers - Google's data interchange format // // Copyright 2010 The Go Authors. All rights reserved. // https://github.com/golang/protobuf // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package proto /* * Types and routines for supporting protocol buffer extensions. */ import ( "errors" "fmt" "reflect" "strconv" "sync" ) // ErrMissingExtension is the error returned by GetExtension if the named extension is not in the message. var ErrMissingExtension = errors.New("proto: missing extension") // ExtensionRange represents a range of message extensions for a protocol buffer. // Used in code generated by the protocol compiler. type ExtensionRange struct { Start, End int32 // both inclusive } // extendableProto is an interface implemented by any protocol buffer that may be extended. type extendableProto interface { Message ExtensionRangeArray() []ExtensionRange ExtensionMap() map[int32]Extension } var extendableProtoType = reflect.TypeOf((*extendableProto)(nil)).Elem() // ExtensionDesc represents an extension specification. // Used in generated code from the protocol compiler. type ExtensionDesc struct { ExtendedType Message // nil pointer to the type that is being extended ExtensionType interface{} // nil pointer to the extension type Field int32 // field number Name string // fully-qualified name of extension, for text formatting Tag string // protobuf tag style } func (ed *ExtensionDesc) repeated() bool { t := reflect.TypeOf(ed.ExtensionType) return t.Kind() == reflect.Slice && t.Elem().Kind() != reflect.Uint8 } // Extension represents an extension in a message. type Extension struct { // When an extension is stored in a message using SetExtension // only desc and value are set. When the message is marshaled // enc will be set to the encoded form of the message. // // When a message is unmarshaled and contains extensions, each // extension will have only enc set. When such an extension is // accessed using GetExtension (or GetExtensions) desc and value // will be set. desc *ExtensionDesc value interface{} enc []byte } // SetRawExtension is for testing only. func SetRawExtension(base extendableProto, id int32, b []byte) { base.ExtensionMap()[id] = Extension{enc: b} } // isExtensionField returns true iff the given field number is in an extension range. func isExtensionField(pb extendableProto, field int32) bool { for _, er := range pb.ExtensionRangeArray() { if er.Start <= field && field <= er.End { return true } } return false } // checkExtensionTypes checks that the given extension is valid for pb. func checkExtensionTypes(pb extendableProto, extension *ExtensionDesc) error { // Check the extended type. if a, b := reflect.TypeOf(pb), reflect.TypeOf(extension.ExtendedType); a != b { return errors.New("proto: bad extended type; " + b.String() + " does not extend " + a.String()) } // Check the range. if !isExtensionField(pb, extension.Field) { return errors.New("proto: bad extension number; not in declared ranges") } return nil } // extPropKey is sufficient to uniquely identify an extension. type extPropKey struct { base reflect.Type field int32 } var extProp = struct { sync.RWMutex m map[extPropKey]*Properties }{ m: make(map[extPropKey]*Properties), } func extensionProperties(ed *ExtensionDesc) *Properties { key := extPropKey{base: reflect.TypeOf(ed.ExtendedType), field: ed.Field} extProp.RLock() if prop, ok := extProp.m[key]; ok { extProp.RUnlock() return prop } extProp.RUnlock() extProp.Lock() defer extProp.Unlock() // Check again. if prop, ok := extProp.m[key]; ok { return prop } prop := new(Properties) prop.Init(reflect.TypeOf(ed.ExtensionType), "unknown_name", ed.Tag, nil) extProp.m[key] = prop return prop } // encodeExtensionMap encodes any unmarshaled (unencoded) extensions in m. func encodeExtensionMap(m map[int32]Extension) error { for k, e := range m { if e.value == nil || e.desc == nil { // Extension is only in its encoded form. continue } // We don't skip extensions that have an encoded form set, // because the extension value may have been mutated after // the last time this function was called. et := reflect.TypeOf(e.desc.ExtensionType) props := extensionProperties(e.desc) p := NewBuffer(nil) // If e.value has type T, the encoder expects a *struct{ X T }. // Pass a *T with a zero field and hope it all works out. x := reflect.New(et) x.Elem().Set(reflect.ValueOf(e.value)) if err := props.enc(p, props, toStructPointer(x)); err != nil { return err } e.enc = p.buf m[k] = e } return nil } func sizeExtensionMap(m map[int32]Extension) (n int) { for _, e := range m { if e.value == nil || e.desc == nil { // Extension is only in its encoded form. n += len(e.enc) continue } // We don't skip extensions that have an encoded form set, // because the extension value may have been mutated after // the last time this function was called. et := reflect.TypeOf(e.desc.ExtensionType) props := extensionProperties(e.desc) // If e.value has type T, the encoder expects a *struct{ X T }. // Pass a *T with a zero field and hope it all works out. x := reflect.New(et) x.Elem().Set(reflect.ValueOf(e.value)) n += props.size(props, toStructPointer(x)) } return } // HasExtension returns whether the given extension is present in pb. func HasExtension(pb extendableProto, extension *ExtensionDesc) bool { // TODO: Check types, field numbers, etc.? _, ok := pb.ExtensionMap()[extension.Field] return ok } // ClearExtension removes the given extension from pb. func ClearExtension(pb extendableProto, extension *ExtensionDesc) { // TODO: Check types, field numbers, etc.? delete(pb.ExtensionMap(), extension.Field) } // GetExtension parses and returns the given extension of pb. // If the extension is not present and has no default value it returns ErrMissingExtension. func GetExtension(pb extendableProto, extension *ExtensionDesc) (interface{}, error) { if err := checkExtensionTypes(pb, extension); err != nil { return nil, err } emap := pb.ExtensionMap() e, ok := emap[extension.Field] if !ok { // defaultExtensionValue returns the default value or // ErrMissingExtension if there is no default. return defaultExtensionValue(extension) } if e.value != nil { // Already decoded. Check the descriptor, though. if e.desc != extension { // This shouldn't happen. If it does, it means that // GetExtension was called twice with two different // descriptors with the same field number. return nil, errors.New("proto: descriptor conflict") } return e.value, nil } v, err := decodeExtension(e.enc, extension) if err != nil { return nil, err } // Remember the decoded version and drop the encoded version. // That way it is safe to mutate what we return. e.value = v e.desc = extension e.enc = nil emap[extension.Field] = e return e.value, nil } // defaultExtensionValue returns the default value for extension. // If no default for an extension is defined ErrMissingExtension is returned. func defaultExtensionValue(extension *ExtensionDesc) (interface{}, error) { t := reflect.TypeOf(extension.ExtensionType) props := extensionProperties(extension) sf, _, err := fieldDefault(t, props) if err != nil { return nil, err } if sf == nil || sf.value == nil { // There is no default value. return nil, ErrMissingExtension } if t.Kind() != reflect.Ptr { // We do not need to return a Ptr, we can directly return sf.value. return sf.value, nil } // We need to return an interface{} that is a pointer to sf.value. value := reflect.New(t).Elem() value.Set(reflect.New(value.Type().Elem())) if sf.kind == reflect.Int32 { // We may have an int32 or an enum, but the underlying data is int32. // Since we can't set an int32 into a non int32 reflect.value directly // set it as a int32. value.Elem().SetInt(int64(sf.value.(int32))) } else { value.Elem().Set(reflect.ValueOf(sf.value)) } return value.Interface(), nil } // decodeExtension decodes an extension encoded in b. func decodeExtension(b []byte, extension *ExtensionDesc) (interface{}, error) { o := NewBuffer(b) t := reflect.TypeOf(extension.ExtensionType) props := extensionProperties(extension) // t is a pointer to a struct, pointer to basic type or a slice. // Allocate a "field" to store the pointer/slice itself; the // pointer/slice will be stored here. We pass // the address of this field to props.dec. // This passes a zero field and a *t and lets props.dec // interpret it as a *struct{ x t }. value := reflect.New(t).Elem() for { // Discard wire type and field number varint. It isn't needed. if _, err := o.DecodeVarint(); err != nil { return nil, err } if err := props.dec(o, props, toStructPointer(value.Addr())); err != nil { return nil, err } if o.index >= len(o.buf) { break } } return value.Interface(), nil } // GetExtensions returns a slice of the extensions present in pb that are also listed in es. // The returned slice has the same length as es; missing extensions will appear as nil elements. func GetExtensions(pb Message, es []*ExtensionDesc) (extensions []interface{}, err error) { epb, ok := pb.(extendableProto) if !ok { err = errors.New("proto: not an extendable proto") return } extensions = make([]interface{}, len(es)) for i, e := range es { extensions[i], err = GetExtension(epb, e) if err == ErrMissingExtension { err = nil } if err != nil { return } } return } // SetExtension sets the specified extension of pb to the specified value. func SetExtension(pb extendableProto, extension *ExtensionDesc, value interface{}) error { if err := checkExtensionTypes(pb, extension); err != nil { return err } typ := reflect.TypeOf(extension.ExtensionType) if typ != reflect.TypeOf(value) { return errors.New("proto: bad extension value type") } // nil extension values need to be caught early, because the // encoder can't distinguish an ErrNil due to a nil extension // from an ErrNil due to a missing field. Extensions are // always optional, so the encoder would just swallow the error // and drop all the extensions from the encoded message. if reflect.ValueOf(value).IsNil() { return fmt.Errorf("proto: SetExtension called with nil value of type %T", value) } pb.ExtensionMap()[extension.Field] = Extension{desc: extension, value: value} return nil } // A global registry of extensions. // The generated code will register the generated descriptors by calling RegisterExtension. var extensionMaps = make(map[reflect.Type]map[int32]*ExtensionDesc) // RegisterExtension is called from the generated code. func RegisterExtension(desc *ExtensionDesc) { st := reflect.TypeOf(desc.ExtendedType).Elem() m := extensionMaps[st] if m == nil { m = make(map[int32]*ExtensionDesc) extensionMaps[st] = m } if _, ok := m[desc.Field]; ok { panic("proto: duplicate extension registered: " + st.String() + " " + strconv.Itoa(int(desc.Field))) } m[desc.Field] = desc } // RegisteredExtensions returns a map of the registered extensions of a // protocol buffer struct, indexed by the extension number. // The argument pb should be a nil pointer to the struct type. func RegisteredExtensions(pb Message) map[int32]*ExtensionDesc { return extensionMaps[reflect.TypeOf(pb).Elem()] } lxd-2.0.0/dist/src/github.com/golang/protobuf/proto/properties.go0000644061062106075000000006106012702772352027506 0ustar00stgraberdomain admins00000000000000// Go support for Protocol Buffers - Google's data interchange format // // Copyright 2010 The Go Authors. All rights reserved. // https://github.com/golang/protobuf // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package proto /* * Routines for encoding data into the wire format for protocol buffers. */ import ( "fmt" "log" "os" "reflect" "sort" "strconv" "strings" "sync" ) const debug bool = false // Constants that identify the encoding of a value on the wire. const ( WireVarint = 0 WireFixed64 = 1 WireBytes = 2 WireStartGroup = 3 WireEndGroup = 4 WireFixed32 = 5 ) const startSize = 10 // initial slice/string sizes // Encoders are defined in encode.go // An encoder outputs the full representation of a field, including its // tag and encoder type. type encoder func(p *Buffer, prop *Properties, base structPointer) error // A valueEncoder encodes a single integer in a particular encoding. type valueEncoder func(o *Buffer, x uint64) error // Sizers are defined in encode.go // A sizer returns the encoded size of a field, including its tag and encoder // type. type sizer func(prop *Properties, base structPointer) int // A valueSizer returns the encoded size of a single integer in a particular // encoding. type valueSizer func(x uint64) int // Decoders are defined in decode.go // A decoder creates a value from its wire representation. // Unrecognized subelements are saved in unrec. type decoder func(p *Buffer, prop *Properties, base structPointer) error // A valueDecoder decodes a single integer in a particular encoding. type valueDecoder func(o *Buffer) (x uint64, err error) // A oneofMarshaler does the marshaling for all oneof fields in a message. type oneofMarshaler func(Message, *Buffer) error // A oneofUnmarshaler does the unmarshaling for a oneof field in a message. type oneofUnmarshaler func(Message, int, int, *Buffer) (bool, error) // A oneofSizer does the sizing for all oneof fields in a message. type oneofSizer func(Message) int // tagMap is an optimization over map[int]int for typical protocol buffer // use-cases. Encoded protocol buffers are often in tag order with small tag // numbers. type tagMap struct { fastTags []int slowTags map[int]int } // tagMapFastLimit is the upper bound on the tag number that will be stored in // the tagMap slice rather than its map. const tagMapFastLimit = 1024 func (p *tagMap) get(t int) (int, bool) { if t > 0 && t < tagMapFastLimit { if t >= len(p.fastTags) { return 0, false } fi := p.fastTags[t] return fi, fi >= 0 } fi, ok := p.slowTags[t] return fi, ok } func (p *tagMap) put(t int, fi int) { if t > 0 && t < tagMapFastLimit { for len(p.fastTags) < t+1 { p.fastTags = append(p.fastTags, -1) } p.fastTags[t] = fi return } if p.slowTags == nil { p.slowTags = make(map[int]int) } p.slowTags[t] = fi } // StructProperties represents properties for all the fields of a struct. // decoderTags and decoderOrigNames should only be used by the decoder. type StructProperties struct { Prop []*Properties // properties for each field reqCount int // required count decoderTags tagMap // map from proto tag to struct field number decoderOrigNames map[string]int // map from original name to struct field number order []int // list of struct field numbers in tag order unrecField field // field id of the XXX_unrecognized []byte field extendable bool // is this an extendable proto oneofMarshaler oneofMarshaler oneofUnmarshaler oneofUnmarshaler oneofSizer oneofSizer stype reflect.Type // OneofTypes contains information about the oneof fields in this message. // It is keyed by the original name of a field. OneofTypes map[string]*OneofProperties } // OneofProperties represents information about a specific field in a oneof. type OneofProperties struct { Type reflect.Type // pointer to generated struct type for this oneof field Field int // struct field number of the containing oneof in the message Prop *Properties } // Implement the sorting interface so we can sort the fields in tag order, as recommended by the spec. // See encode.go, (*Buffer).enc_struct. func (sp *StructProperties) Len() int { return len(sp.order) } func (sp *StructProperties) Less(i, j int) bool { return sp.Prop[sp.order[i]].Tag < sp.Prop[sp.order[j]].Tag } func (sp *StructProperties) Swap(i, j int) { sp.order[i], sp.order[j] = sp.order[j], sp.order[i] } // Properties represents the protocol-specific behavior of a single struct field. type Properties struct { Name string // name of the field, for error messages OrigName string // original name before protocol compiler (always set) JSONName string // name to use for JSON; determined by protoc Wire string WireType int Tag int Required bool Optional bool Repeated bool Packed bool // relevant for repeated primitives only Enum string // set for enum types only proto3 bool // whether this is known to be a proto3 field; set for []byte only oneof bool // whether this is a oneof field Default string // default value HasDefault bool // whether an explicit default was provided def_uint64 uint64 enc encoder valEnc valueEncoder // set for bool and numeric types only field field tagcode []byte // encoding of EncodeVarint((Tag<<3)|WireType) tagbuf [8]byte stype reflect.Type // set for struct types only sprop *StructProperties // set for struct types only isMarshaler bool isUnmarshaler bool mtype reflect.Type // set for map types only mkeyprop *Properties // set for map types only mvalprop *Properties // set for map types only size sizer valSize valueSizer // set for bool and numeric types only dec decoder valDec valueDecoder // set for bool and numeric types only // If this is a packable field, this will be the decoder for the packed version of the field. packedDec decoder } // String formats the properties in the protobuf struct field tag style. func (p *Properties) String() string { s := p.Wire s = "," s += strconv.Itoa(p.Tag) if p.Required { s += ",req" } if p.Optional { s += ",opt" } if p.Repeated { s += ",rep" } if p.Packed { s += ",packed" } s += ",name=" + p.OrigName if p.JSONName != p.OrigName { s += ",json=" + p.JSONName } if p.proto3 { s += ",proto3" } if p.oneof { s += ",oneof" } if len(p.Enum) > 0 { s += ",enum=" + p.Enum } if p.HasDefault { s += ",def=" + p.Default } return s } // Parse populates p by parsing a string in the protobuf struct field tag style. func (p *Properties) Parse(s string) { // "bytes,49,opt,name=foo,def=hello!" fields := strings.Split(s, ",") // breaks def=, but handled below. if len(fields) < 2 { fmt.Fprintf(os.Stderr, "proto: tag has too few fields: %q\n", s) return } p.Wire = fields[0] switch p.Wire { case "varint": p.WireType = WireVarint p.valEnc = (*Buffer).EncodeVarint p.valDec = (*Buffer).DecodeVarint p.valSize = sizeVarint case "fixed32": p.WireType = WireFixed32 p.valEnc = (*Buffer).EncodeFixed32 p.valDec = (*Buffer).DecodeFixed32 p.valSize = sizeFixed32 case "fixed64": p.WireType = WireFixed64 p.valEnc = (*Buffer).EncodeFixed64 p.valDec = (*Buffer).DecodeFixed64 p.valSize = sizeFixed64 case "zigzag32": p.WireType = WireVarint p.valEnc = (*Buffer).EncodeZigzag32 p.valDec = (*Buffer).DecodeZigzag32 p.valSize = sizeZigzag32 case "zigzag64": p.WireType = WireVarint p.valEnc = (*Buffer).EncodeZigzag64 p.valDec = (*Buffer).DecodeZigzag64 p.valSize = sizeZigzag64 case "bytes", "group": p.WireType = WireBytes // no numeric converter for non-numeric types default: fmt.Fprintf(os.Stderr, "proto: tag has unknown wire type: %q\n", s) return } var err error p.Tag, err = strconv.Atoi(fields[1]) if err != nil { return } for i := 2; i < len(fields); i++ { f := fields[i] switch { case f == "req": p.Required = true case f == "opt": p.Optional = true case f == "rep": p.Repeated = true case f == "packed": p.Packed = true case strings.HasPrefix(f, "name="): p.OrigName = f[5:] case strings.HasPrefix(f, "json="): p.JSONName = f[5:] case strings.HasPrefix(f, "enum="): p.Enum = f[5:] case f == "proto3": p.proto3 = true case f == "oneof": p.oneof = true case strings.HasPrefix(f, "def="): p.HasDefault = true p.Default = f[4:] // rest of string if i+1 < len(fields) { // Commas aren't escaped, and def is always last. p.Default += "," + strings.Join(fields[i+1:], ",") break } } } } func logNoSliceEnc(t1, t2 reflect.Type) { fmt.Fprintf(os.Stderr, "proto: no slice oenc for %T = []%T\n", t1, t2) } var protoMessageType = reflect.TypeOf((*Message)(nil)).Elem() // Initialize the fields for encoding and decoding. func (p *Properties) setEncAndDec(typ reflect.Type, f *reflect.StructField, lockGetProp bool) { p.enc = nil p.dec = nil p.size = nil switch t1 := typ; t1.Kind() { default: fmt.Fprintf(os.Stderr, "proto: no coders for %v\n", t1) // proto3 scalar types case reflect.Bool: p.enc = (*Buffer).enc_proto3_bool p.dec = (*Buffer).dec_proto3_bool p.size = size_proto3_bool case reflect.Int32: p.enc = (*Buffer).enc_proto3_int32 p.dec = (*Buffer).dec_proto3_int32 p.size = size_proto3_int32 case reflect.Uint32: p.enc = (*Buffer).enc_proto3_uint32 p.dec = (*Buffer).dec_proto3_int32 // can reuse p.size = size_proto3_uint32 case reflect.Int64, reflect.Uint64: p.enc = (*Buffer).enc_proto3_int64 p.dec = (*Buffer).dec_proto3_int64 p.size = size_proto3_int64 case reflect.Float32: p.enc = (*Buffer).enc_proto3_uint32 // can just treat them as bits p.dec = (*Buffer).dec_proto3_int32 p.size = size_proto3_uint32 case reflect.Float64: p.enc = (*Buffer).enc_proto3_int64 // can just treat them as bits p.dec = (*Buffer).dec_proto3_int64 p.size = size_proto3_int64 case reflect.String: p.enc = (*Buffer).enc_proto3_string p.dec = (*Buffer).dec_proto3_string p.size = size_proto3_string case reflect.Ptr: switch t2 := t1.Elem(); t2.Kind() { default: fmt.Fprintf(os.Stderr, "proto: no encoder function for %v -> %v\n", t1, t2) break case reflect.Bool: p.enc = (*Buffer).enc_bool p.dec = (*Buffer).dec_bool p.size = size_bool case reflect.Int32: p.enc = (*Buffer).enc_int32 p.dec = (*Buffer).dec_int32 p.size = size_int32 case reflect.Uint32: p.enc = (*Buffer).enc_uint32 p.dec = (*Buffer).dec_int32 // can reuse p.size = size_uint32 case reflect.Int64, reflect.Uint64: p.enc = (*Buffer).enc_int64 p.dec = (*Buffer).dec_int64 p.size = size_int64 case reflect.Float32: p.enc = (*Buffer).enc_uint32 // can just treat them as bits p.dec = (*Buffer).dec_int32 p.size = size_uint32 case reflect.Float64: p.enc = (*Buffer).enc_int64 // can just treat them as bits p.dec = (*Buffer).dec_int64 p.size = size_int64 case reflect.String: p.enc = (*Buffer).enc_string p.dec = (*Buffer).dec_string p.size = size_string case reflect.Struct: p.stype = t1.Elem() p.isMarshaler = isMarshaler(t1) p.isUnmarshaler = isUnmarshaler(t1) if p.Wire == "bytes" { p.enc = (*Buffer).enc_struct_message p.dec = (*Buffer).dec_struct_message p.size = size_struct_message } else { p.enc = (*Buffer).enc_struct_group p.dec = (*Buffer).dec_struct_group p.size = size_struct_group } } case reflect.Slice: switch t2 := t1.Elem(); t2.Kind() { default: logNoSliceEnc(t1, t2) break case reflect.Bool: if p.Packed { p.enc = (*Buffer).enc_slice_packed_bool p.size = size_slice_packed_bool } else { p.enc = (*Buffer).enc_slice_bool p.size = size_slice_bool } p.dec = (*Buffer).dec_slice_bool p.packedDec = (*Buffer).dec_slice_packed_bool case reflect.Int32: if p.Packed { p.enc = (*Buffer).enc_slice_packed_int32 p.size = size_slice_packed_int32 } else { p.enc = (*Buffer).enc_slice_int32 p.size = size_slice_int32 } p.dec = (*Buffer).dec_slice_int32 p.packedDec = (*Buffer).dec_slice_packed_int32 case reflect.Uint32: if p.Packed { p.enc = (*Buffer).enc_slice_packed_uint32 p.size = size_slice_packed_uint32 } else { p.enc = (*Buffer).enc_slice_uint32 p.size = size_slice_uint32 } p.dec = (*Buffer).dec_slice_int32 p.packedDec = (*Buffer).dec_slice_packed_int32 case reflect.Int64, reflect.Uint64: if p.Packed { p.enc = (*Buffer).enc_slice_packed_int64 p.size = size_slice_packed_int64 } else { p.enc = (*Buffer).enc_slice_int64 p.size = size_slice_int64 } p.dec = (*Buffer).dec_slice_int64 p.packedDec = (*Buffer).dec_slice_packed_int64 case reflect.Uint8: p.enc = (*Buffer).enc_slice_byte p.dec = (*Buffer).dec_slice_byte p.size = size_slice_byte // This is a []byte, which is either a bytes field, // or the value of a map field. In the latter case, // we always encode an empty []byte, so we should not // use the proto3 enc/size funcs. // f == nil iff this is the key/value of a map field. if p.proto3 && f != nil { p.enc = (*Buffer).enc_proto3_slice_byte p.size = size_proto3_slice_byte } case reflect.Float32, reflect.Float64: switch t2.Bits() { case 32: // can just treat them as bits if p.Packed { p.enc = (*Buffer).enc_slice_packed_uint32 p.size = size_slice_packed_uint32 } else { p.enc = (*Buffer).enc_slice_uint32 p.size = size_slice_uint32 } p.dec = (*Buffer).dec_slice_int32 p.packedDec = (*Buffer).dec_slice_packed_int32 case 64: // can just treat them as bits if p.Packed { p.enc = (*Buffer).enc_slice_packed_int64 p.size = size_slice_packed_int64 } else { p.enc = (*Buffer).enc_slice_int64 p.size = size_slice_int64 } p.dec = (*Buffer).dec_slice_int64 p.packedDec = (*Buffer).dec_slice_packed_int64 default: logNoSliceEnc(t1, t2) break } case reflect.String: p.enc = (*Buffer).enc_slice_string p.dec = (*Buffer).dec_slice_string p.size = size_slice_string case reflect.Ptr: switch t3 := t2.Elem(); t3.Kind() { default: fmt.Fprintf(os.Stderr, "proto: no ptr oenc for %T -> %T -> %T\n", t1, t2, t3) break case reflect.Struct: p.stype = t2.Elem() p.isMarshaler = isMarshaler(t2) p.isUnmarshaler = isUnmarshaler(t2) if p.Wire == "bytes" { p.enc = (*Buffer).enc_slice_struct_message p.dec = (*Buffer).dec_slice_struct_message p.size = size_slice_struct_message } else { p.enc = (*Buffer).enc_slice_struct_group p.dec = (*Buffer).dec_slice_struct_group p.size = size_slice_struct_group } } case reflect.Slice: switch t2.Elem().Kind() { default: fmt.Fprintf(os.Stderr, "proto: no slice elem oenc for %T -> %T -> %T\n", t1, t2, t2.Elem()) break case reflect.Uint8: p.enc = (*Buffer).enc_slice_slice_byte p.dec = (*Buffer).dec_slice_slice_byte p.size = size_slice_slice_byte } } case reflect.Map: p.enc = (*Buffer).enc_new_map p.dec = (*Buffer).dec_new_map p.size = size_new_map p.mtype = t1 p.mkeyprop = &Properties{} p.mkeyprop.init(reflect.PtrTo(p.mtype.Key()), "Key", f.Tag.Get("protobuf_key"), nil, lockGetProp) p.mvalprop = &Properties{} vtype := p.mtype.Elem() if vtype.Kind() != reflect.Ptr && vtype.Kind() != reflect.Slice { // The value type is not a message (*T) or bytes ([]byte), // so we need encoders for the pointer to this type. vtype = reflect.PtrTo(vtype) } p.mvalprop.init(vtype, "Value", f.Tag.Get("protobuf_val"), nil, lockGetProp) } // precalculate tag code wire := p.WireType if p.Packed { wire = WireBytes } x := uint32(p.Tag)<<3 | uint32(wire) i := 0 for i = 0; x > 127; i++ { p.tagbuf[i] = 0x80 | uint8(x&0x7F) x >>= 7 } p.tagbuf[i] = uint8(x) p.tagcode = p.tagbuf[0 : i+1] if p.stype != nil { if lockGetProp { p.sprop = GetProperties(p.stype) } else { p.sprop = getPropertiesLocked(p.stype) } } } var ( marshalerType = reflect.TypeOf((*Marshaler)(nil)).Elem() unmarshalerType = reflect.TypeOf((*Unmarshaler)(nil)).Elem() ) // isMarshaler reports whether type t implements Marshaler. func isMarshaler(t reflect.Type) bool { // We're checking for (likely) pointer-receiver methods // so if t is not a pointer, something is very wrong. // The calls above only invoke isMarshaler on pointer types. if t.Kind() != reflect.Ptr { panic("proto: misuse of isMarshaler") } return t.Implements(marshalerType) } // isUnmarshaler reports whether type t implements Unmarshaler. func isUnmarshaler(t reflect.Type) bool { // We're checking for (likely) pointer-receiver methods // so if t is not a pointer, something is very wrong. // The calls above only invoke isUnmarshaler on pointer types. if t.Kind() != reflect.Ptr { panic("proto: misuse of isUnmarshaler") } return t.Implements(unmarshalerType) } // Init populates the properties from a protocol buffer struct tag. func (p *Properties) Init(typ reflect.Type, name, tag string, f *reflect.StructField) { p.init(typ, name, tag, f, true) } func (p *Properties) init(typ reflect.Type, name, tag string, f *reflect.StructField, lockGetProp bool) { // "bytes,49,opt,def=hello!" p.Name = name p.OrigName = name if f != nil { p.field = toField(f) } if tag == "" { return } p.Parse(tag) p.setEncAndDec(typ, f, lockGetProp) } var ( propertiesMu sync.RWMutex propertiesMap = make(map[reflect.Type]*StructProperties) ) // GetProperties returns the list of properties for the type represented by t. // t must represent a generated struct type of a protocol message. func GetProperties(t reflect.Type) *StructProperties { if t.Kind() != reflect.Struct { panic("proto: type must have kind struct") } // Most calls to GetProperties in a long-running program will be // retrieving details for types we have seen before. propertiesMu.RLock() sprop, ok := propertiesMap[t] propertiesMu.RUnlock() if ok { if collectStats { stats.Chit++ } return sprop } propertiesMu.Lock() sprop = getPropertiesLocked(t) propertiesMu.Unlock() return sprop } // getPropertiesLocked requires that propertiesMu is held. func getPropertiesLocked(t reflect.Type) *StructProperties { if prop, ok := propertiesMap[t]; ok { if collectStats { stats.Chit++ } return prop } if collectStats { stats.Cmiss++ } prop := new(StructProperties) // in case of recursive protos, fill this in now. propertiesMap[t] = prop // build properties prop.extendable = reflect.PtrTo(t).Implements(extendableProtoType) prop.unrecField = invalidField prop.Prop = make([]*Properties, t.NumField()) prop.order = make([]int, t.NumField()) for i := 0; i < t.NumField(); i++ { f := t.Field(i) p := new(Properties) name := f.Name p.init(f.Type, name, f.Tag.Get("protobuf"), &f, false) if f.Name == "XXX_extensions" { // special case p.enc = (*Buffer).enc_map p.dec = nil // not needed p.size = size_map } if f.Name == "XXX_unrecognized" { // special case prop.unrecField = toField(&f) } oneof := f.Tag.Get("protobuf_oneof") != "" // special case prop.Prop[i] = p prop.order[i] = i if debug { print(i, " ", f.Name, " ", t.String(), " ") if p.Tag > 0 { print(p.String()) } print("\n") } if p.enc == nil && !strings.HasPrefix(f.Name, "XXX_") && !oneof { fmt.Fprintln(os.Stderr, "proto: no encoder for", f.Name, f.Type.String(), "[GetProperties]") } } // Re-order prop.order. sort.Sort(prop) type oneofMessage interface { XXX_OneofFuncs() (func(Message, *Buffer) error, func(Message, int, int, *Buffer) (bool, error), func(Message) int, []interface{}) } if om, ok := reflect.Zero(reflect.PtrTo(t)).Interface().(oneofMessage); ok { var oots []interface{} prop.oneofMarshaler, prop.oneofUnmarshaler, prop.oneofSizer, oots = om.XXX_OneofFuncs() prop.stype = t // Interpret oneof metadata. prop.OneofTypes = make(map[string]*OneofProperties) for _, oot := range oots { oop := &OneofProperties{ Type: reflect.ValueOf(oot).Type(), // *T Prop: new(Properties), } sft := oop.Type.Elem().Field(0) oop.Prop.Name = sft.Name oop.Prop.Parse(sft.Tag.Get("protobuf")) // There will be exactly one interface field that // this new value is assignable to. for i := 0; i < t.NumField(); i++ { f := t.Field(i) if f.Type.Kind() != reflect.Interface { continue } if !oop.Type.AssignableTo(f.Type) { continue } oop.Field = i break } prop.OneofTypes[oop.Prop.OrigName] = oop } } // build required counts // build tags reqCount := 0 prop.decoderOrigNames = make(map[string]int) for i, p := range prop.Prop { if strings.HasPrefix(p.Name, "XXX_") { // Internal fields should not appear in tags/origNames maps. // They are handled specially when encoding and decoding. continue } if p.Required { reqCount++ } prop.decoderTags.put(p.Tag, i) prop.decoderOrigNames[p.OrigName] = i } prop.reqCount = reqCount return prop } // Return the Properties object for the x[0]'th field of the structure. func propByIndex(t reflect.Type, x []int) *Properties { if len(x) != 1 { fmt.Fprintf(os.Stderr, "proto: field index dimension %d (not 1) for type %s\n", len(x), t) return nil } prop := GetProperties(t) return prop.Prop[x[0]] } // Get the address and type of a pointer to a struct from an interface. func getbase(pb Message) (t reflect.Type, b structPointer, err error) { if pb == nil { err = ErrNil return } // get the reflect type of the pointer to the struct. t = reflect.TypeOf(pb) // get the address of the struct. value := reflect.ValueOf(pb) b = toStructPointer(value) return } // A global registry of enum types. // The generated code will register the generated maps by calling RegisterEnum. var enumValueMaps = make(map[string]map[string]int32) // RegisterEnum is called from the generated code to install the enum descriptor // maps into the global table to aid parsing text format protocol buffers. func RegisterEnum(typeName string, unusedNameMap map[int32]string, valueMap map[string]int32) { if _, ok := enumValueMaps[typeName]; ok { panic("proto: duplicate enum registered: " + typeName) } enumValueMaps[typeName] = valueMap } // EnumValueMap returns the mapping from names to integers of the // enum type enumType, or a nil if not found. func EnumValueMap(enumType string) map[string]int32 { return enumValueMaps[enumType] } // A registry of all linked message types. // The string is a fully-qualified proto name ("pkg.Message"). var ( protoTypes = make(map[string]reflect.Type) revProtoTypes = make(map[reflect.Type]string) ) // RegisterType is called from generated code and maps from the fully qualified // proto name to the type (pointer to struct) of the protocol buffer. func RegisterType(x Message, name string) { if _, ok := protoTypes[name]; ok { // TODO: Some day, make this a panic. log.Printf("proto: duplicate proto type registered: %s", name) return } t := reflect.TypeOf(x) protoTypes[name] = t revProtoTypes[t] = name } // MessageName returns the fully-qualified proto name for the given message type. func MessageName(x Message) string { return revProtoTypes[reflect.TypeOf(x)] } // MessageType returns the message type (pointer to struct) for a named message. func MessageType(name string) reflect.Type { return protoTypes[name] } lxd-2.0.0/dist/src/github.com/golang/protobuf/proto/decode.go0000644061062106075000000005467312702772352026551 0ustar00stgraberdomain admins00000000000000// Go support for Protocol Buffers - Google's data interchange format // // Copyright 2010 The Go Authors. All rights reserved. // https://github.com/golang/protobuf // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package proto /* * Routines for decoding protocol buffer data to construct in-memory representations. */ import ( "errors" "fmt" "io" "os" "reflect" ) // errOverflow is returned when an integer is too large to be represented. var errOverflow = errors.New("proto: integer overflow") // ErrInternalBadWireType is returned by generated code when an incorrect // wire type is encountered. It does not get returned to user code. var ErrInternalBadWireType = errors.New("proto: internal error: bad wiretype for oneof") // The fundamental decoders that interpret bytes on the wire. // Those that take integer types all return uint64 and are // therefore of type valueDecoder. // DecodeVarint reads a varint-encoded integer from the slice. // It returns the integer and the number of bytes consumed, or // zero if there is not enough. // This is the format for the // int32, int64, uint32, uint64, bool, and enum // protocol buffer types. func DecodeVarint(buf []byte) (x uint64, n int) { // x, n already 0 for shift := uint(0); shift < 64; shift += 7 { if n >= len(buf) { return 0, 0 } b := uint64(buf[n]) n++ x |= (b & 0x7F) << shift if (b & 0x80) == 0 { return x, n } } // The number is too large to represent in a 64-bit value. return 0, 0 } // DecodeVarint reads a varint-encoded integer from the Buffer. // This is the format for the // int32, int64, uint32, uint64, bool, and enum // protocol buffer types. func (p *Buffer) DecodeVarint() (x uint64, err error) { // x, err already 0 i := p.index l := len(p.buf) for shift := uint(0); shift < 64; shift += 7 { if i >= l { err = io.ErrUnexpectedEOF return } b := p.buf[i] i++ x |= (uint64(b) & 0x7F) << shift if b < 0x80 { p.index = i return } } // The number is too large to represent in a 64-bit value. err = errOverflow return } // DecodeFixed64 reads a 64-bit integer from the Buffer. // This is the format for the // fixed64, sfixed64, and double protocol buffer types. func (p *Buffer) DecodeFixed64() (x uint64, err error) { // x, err already 0 i := p.index + 8 if i < 0 || i > len(p.buf) { err = io.ErrUnexpectedEOF return } p.index = i x = uint64(p.buf[i-8]) x |= uint64(p.buf[i-7]) << 8 x |= uint64(p.buf[i-6]) << 16 x |= uint64(p.buf[i-5]) << 24 x |= uint64(p.buf[i-4]) << 32 x |= uint64(p.buf[i-3]) << 40 x |= uint64(p.buf[i-2]) << 48 x |= uint64(p.buf[i-1]) << 56 return } // DecodeFixed32 reads a 32-bit integer from the Buffer. // This is the format for the // fixed32, sfixed32, and float protocol buffer types. func (p *Buffer) DecodeFixed32() (x uint64, err error) { // x, err already 0 i := p.index + 4 if i < 0 || i > len(p.buf) { err = io.ErrUnexpectedEOF return } p.index = i x = uint64(p.buf[i-4]) x |= uint64(p.buf[i-3]) << 8 x |= uint64(p.buf[i-2]) << 16 x |= uint64(p.buf[i-1]) << 24 return } // DecodeZigzag64 reads a zigzag-encoded 64-bit integer // from the Buffer. // This is the format used for the sint64 protocol buffer type. func (p *Buffer) DecodeZigzag64() (x uint64, err error) { x, err = p.DecodeVarint() if err != nil { return } x = (x >> 1) ^ uint64((int64(x&1)<<63)>>63) return } // DecodeZigzag32 reads a zigzag-encoded 32-bit integer // from the Buffer. // This is the format used for the sint32 protocol buffer type. func (p *Buffer) DecodeZigzag32() (x uint64, err error) { x, err = p.DecodeVarint() if err != nil { return } x = uint64((uint32(x) >> 1) ^ uint32((int32(x&1)<<31)>>31)) return } // These are not ValueDecoders: they produce an array of bytes or a string. // bytes, embedded messages // DecodeRawBytes reads a count-delimited byte buffer from the Buffer. // This is the format used for the bytes protocol buffer // type and for embedded messages. func (p *Buffer) DecodeRawBytes(alloc bool) (buf []byte, err error) { n, err := p.DecodeVarint() if err != nil { return nil, err } nb := int(n) if nb < 0 { return nil, fmt.Errorf("proto: bad byte length %d", nb) } end := p.index + nb if end < p.index || end > len(p.buf) { return nil, io.ErrUnexpectedEOF } if !alloc { // todo: check if can get more uses of alloc=false buf = p.buf[p.index:end] p.index += nb return } buf = make([]byte, nb) copy(buf, p.buf[p.index:]) p.index += nb return } // DecodeStringBytes reads an encoded string from the Buffer. // This is the format used for the proto2 string type. func (p *Buffer) DecodeStringBytes() (s string, err error) { buf, err := p.DecodeRawBytes(false) if err != nil { return } return string(buf), nil } // Skip the next item in the buffer. Its wire type is decoded and presented as an argument. // If the protocol buffer has extensions, and the field matches, add it as an extension. // Otherwise, if the XXX_unrecognized field exists, append the skipped data there. func (o *Buffer) skipAndSave(t reflect.Type, tag, wire int, base structPointer, unrecField field) error { oi := o.index err := o.skip(t, tag, wire) if err != nil { return err } if !unrecField.IsValid() { return nil } ptr := structPointer_Bytes(base, unrecField) // Add the skipped field to struct field obuf := o.buf o.buf = *ptr o.EncodeVarint(uint64(tag<<3 | wire)) *ptr = append(o.buf, obuf[oi:o.index]...) o.buf = obuf return nil } // Skip the next item in the buffer. Its wire type is decoded and presented as an argument. func (o *Buffer) skip(t reflect.Type, tag, wire int) error { var u uint64 var err error switch wire { case WireVarint: _, err = o.DecodeVarint() case WireFixed64: _, err = o.DecodeFixed64() case WireBytes: _, err = o.DecodeRawBytes(false) case WireFixed32: _, err = o.DecodeFixed32() case WireStartGroup: for { u, err = o.DecodeVarint() if err != nil { break } fwire := int(u & 0x7) if fwire == WireEndGroup { break } ftag := int(u >> 3) err = o.skip(t, ftag, fwire) if err != nil { break } } default: err = fmt.Errorf("proto: can't skip unknown wire type %d for %s", wire, t) } return err } // Unmarshaler is the interface representing objects that can // unmarshal themselves. The method should reset the receiver before // decoding starts. The argument points to data that may be // overwritten, so implementations should not keep references to the // buffer. type Unmarshaler interface { Unmarshal([]byte) error } // Unmarshal parses the protocol buffer representation in buf and places the // decoded result in pb. If the struct underlying pb does not match // the data in buf, the results can be unpredictable. // // Unmarshal resets pb before starting to unmarshal, so any // existing data in pb is always removed. Use UnmarshalMerge // to preserve and append to existing data. func Unmarshal(buf []byte, pb Message) error { pb.Reset() return UnmarshalMerge(buf, pb) } // UnmarshalMerge parses the protocol buffer representation in buf and // writes the decoded result to pb. If the struct underlying pb does not match // the data in buf, the results can be unpredictable. // // UnmarshalMerge merges into existing data in pb. // Most code should use Unmarshal instead. func UnmarshalMerge(buf []byte, pb Message) error { // If the object can unmarshal itself, let it. if u, ok := pb.(Unmarshaler); ok { return u.Unmarshal(buf) } return NewBuffer(buf).Unmarshal(pb) } // DecodeMessage reads a count-delimited message from the Buffer. func (p *Buffer) DecodeMessage(pb Message) error { enc, err := p.DecodeRawBytes(false) if err != nil { return err } return NewBuffer(enc).Unmarshal(pb) } // DecodeGroup reads a tag-delimited group from the Buffer. func (p *Buffer) DecodeGroup(pb Message) error { typ, base, err := getbase(pb) if err != nil { return err } return p.unmarshalType(typ.Elem(), GetProperties(typ.Elem()), true, base) } // Unmarshal parses the protocol buffer representation in the // Buffer and places the decoded result in pb. If the struct // underlying pb does not match the data in the buffer, the results can be // unpredictable. func (p *Buffer) Unmarshal(pb Message) error { // If the object can unmarshal itself, let it. if u, ok := pb.(Unmarshaler); ok { err := u.Unmarshal(p.buf[p.index:]) p.index = len(p.buf) return err } typ, base, err := getbase(pb) if err != nil { return err } err = p.unmarshalType(typ.Elem(), GetProperties(typ.Elem()), false, base) if collectStats { stats.Decode++ } return err } // unmarshalType does the work of unmarshaling a structure. func (o *Buffer) unmarshalType(st reflect.Type, prop *StructProperties, is_group bool, base structPointer) error { var state errorState required, reqFields := prop.reqCount, uint64(0) var err error for err == nil && o.index < len(o.buf) { oi := o.index var u uint64 u, err = o.DecodeVarint() if err != nil { break } wire := int(u & 0x7) if wire == WireEndGroup { if is_group { return nil // input is satisfied } return fmt.Errorf("proto: %s: wiretype end group for non-group", st) } tag := int(u >> 3) if tag <= 0 { return fmt.Errorf("proto: %s: illegal tag %d (wire type %d)", st, tag, wire) } fieldnum, ok := prop.decoderTags.get(tag) if !ok { // Maybe it's an extension? if prop.extendable { if e := structPointer_Interface(base, st).(extendableProto); isExtensionField(e, int32(tag)) { if err = o.skip(st, tag, wire); err == nil { ext := e.ExtensionMap()[int32(tag)] // may be missing ext.enc = append(ext.enc, o.buf[oi:o.index]...) e.ExtensionMap()[int32(tag)] = ext } continue } } // Maybe it's a oneof? if prop.oneofUnmarshaler != nil { m := structPointer_Interface(base, st).(Message) // First return value indicates whether tag is a oneof field. ok, err = prop.oneofUnmarshaler(m, tag, wire, o) if err == ErrInternalBadWireType { // Map the error to something more descriptive. // Do the formatting here to save generated code space. err = fmt.Errorf("bad wiretype for oneof field in %T", m) } if ok { continue } } err = o.skipAndSave(st, tag, wire, base, prop.unrecField) continue } p := prop.Prop[fieldnum] if p.dec == nil { fmt.Fprintf(os.Stderr, "proto: no protobuf decoder for %s.%s\n", st, st.Field(fieldnum).Name) continue } dec := p.dec if wire != WireStartGroup && wire != p.WireType { if wire == WireBytes && p.packedDec != nil { // a packable field dec = p.packedDec } else { err = fmt.Errorf("proto: bad wiretype for field %s.%s: got wiretype %d, want %d", st, st.Field(fieldnum).Name, wire, p.WireType) continue } } decErr := dec(o, p, base) if decErr != nil && !state.shouldContinue(decErr, p) { err = decErr } if err == nil && p.Required { // Successfully decoded a required field. if tag <= 64 { // use bitmap for fields 1-64 to catch field reuse. var mask uint64 = 1 << uint64(tag-1) if reqFields&mask == 0 { // new required field reqFields |= mask required-- } } else { // This is imprecise. It can be fooled by a required field // with a tag > 64 that is encoded twice; that's very rare. // A fully correct implementation would require allocating // a data structure, which we would like to avoid. required-- } } } if err == nil { if is_group { return io.ErrUnexpectedEOF } if state.err != nil { return state.err } if required > 0 { // Not enough information to determine the exact field. If we use extra // CPU, we could determine the field only if the missing required field // has a tag <= 64 and we check reqFields. return &RequiredNotSetError{"{Unknown}"} } } return err } // Individual type decoders // For each, // u is the decoded value, // v is a pointer to the field (pointer) in the struct // Sizes of the pools to allocate inside the Buffer. // The goal is modest amortization and allocation // on at least 16-byte boundaries. const ( boolPoolSize = 16 uint32PoolSize = 8 uint64PoolSize = 4 ) // Decode a bool. func (o *Buffer) dec_bool(p *Properties, base structPointer) error { u, err := p.valDec(o) if err != nil { return err } if len(o.bools) == 0 { o.bools = make([]bool, boolPoolSize) } o.bools[0] = u != 0 *structPointer_Bool(base, p.field) = &o.bools[0] o.bools = o.bools[1:] return nil } func (o *Buffer) dec_proto3_bool(p *Properties, base structPointer) error { u, err := p.valDec(o) if err != nil { return err } *structPointer_BoolVal(base, p.field) = u != 0 return nil } // Decode an int32. func (o *Buffer) dec_int32(p *Properties, base structPointer) error { u, err := p.valDec(o) if err != nil { return err } word32_Set(structPointer_Word32(base, p.field), o, uint32(u)) return nil } func (o *Buffer) dec_proto3_int32(p *Properties, base structPointer) error { u, err := p.valDec(o) if err != nil { return err } word32Val_Set(structPointer_Word32Val(base, p.field), uint32(u)) return nil } // Decode an int64. func (o *Buffer) dec_int64(p *Properties, base structPointer) error { u, err := p.valDec(o) if err != nil { return err } word64_Set(structPointer_Word64(base, p.field), o, u) return nil } func (o *Buffer) dec_proto3_int64(p *Properties, base structPointer) error { u, err := p.valDec(o) if err != nil { return err } word64Val_Set(structPointer_Word64Val(base, p.field), o, u) return nil } // Decode a string. func (o *Buffer) dec_string(p *Properties, base structPointer) error { s, err := o.DecodeStringBytes() if err != nil { return err } *structPointer_String(base, p.field) = &s return nil } func (o *Buffer) dec_proto3_string(p *Properties, base structPointer) error { s, err := o.DecodeStringBytes() if err != nil { return err } *structPointer_StringVal(base, p.field) = s return nil } // Decode a slice of bytes ([]byte). func (o *Buffer) dec_slice_byte(p *Properties, base structPointer) error { b, err := o.DecodeRawBytes(true) if err != nil { return err } *structPointer_Bytes(base, p.field) = b return nil } // Decode a slice of bools ([]bool). func (o *Buffer) dec_slice_bool(p *Properties, base structPointer) error { u, err := p.valDec(o) if err != nil { return err } v := structPointer_BoolSlice(base, p.field) *v = append(*v, u != 0) return nil } // Decode a slice of bools ([]bool) in packed format. func (o *Buffer) dec_slice_packed_bool(p *Properties, base structPointer) error { v := structPointer_BoolSlice(base, p.field) nn, err := o.DecodeVarint() if err != nil { return err } nb := int(nn) // number of bytes of encoded bools fin := o.index + nb if fin < o.index { return errOverflow } y := *v for o.index < fin { u, err := p.valDec(o) if err != nil { return err } y = append(y, u != 0) } *v = y return nil } // Decode a slice of int32s ([]int32). func (o *Buffer) dec_slice_int32(p *Properties, base structPointer) error { u, err := p.valDec(o) if err != nil { return err } structPointer_Word32Slice(base, p.field).Append(uint32(u)) return nil } // Decode a slice of int32s ([]int32) in packed format. func (o *Buffer) dec_slice_packed_int32(p *Properties, base structPointer) error { v := structPointer_Word32Slice(base, p.field) nn, err := o.DecodeVarint() if err != nil { return err } nb := int(nn) // number of bytes of encoded int32s fin := o.index + nb if fin < o.index { return errOverflow } for o.index < fin { u, err := p.valDec(o) if err != nil { return err } v.Append(uint32(u)) } return nil } // Decode a slice of int64s ([]int64). func (o *Buffer) dec_slice_int64(p *Properties, base structPointer) error { u, err := p.valDec(o) if err != nil { return err } structPointer_Word64Slice(base, p.field).Append(u) return nil } // Decode a slice of int64s ([]int64) in packed format. func (o *Buffer) dec_slice_packed_int64(p *Properties, base structPointer) error { v := structPointer_Word64Slice(base, p.field) nn, err := o.DecodeVarint() if err != nil { return err } nb := int(nn) // number of bytes of encoded int64s fin := o.index + nb if fin < o.index { return errOverflow } for o.index < fin { u, err := p.valDec(o) if err != nil { return err } v.Append(u) } return nil } // Decode a slice of strings ([]string). func (o *Buffer) dec_slice_string(p *Properties, base structPointer) error { s, err := o.DecodeStringBytes() if err != nil { return err } v := structPointer_StringSlice(base, p.field) *v = append(*v, s) return nil } // Decode a slice of slice of bytes ([][]byte). func (o *Buffer) dec_slice_slice_byte(p *Properties, base structPointer) error { b, err := o.DecodeRawBytes(true) if err != nil { return err } v := structPointer_BytesSlice(base, p.field) *v = append(*v, b) return nil } // Decode a map field. func (o *Buffer) dec_new_map(p *Properties, base structPointer) error { raw, err := o.DecodeRawBytes(false) if err != nil { return err } oi := o.index // index at the end of this map entry o.index -= len(raw) // move buffer back to start of map entry mptr := structPointer_NewAt(base, p.field, p.mtype) // *map[K]V if mptr.Elem().IsNil() { mptr.Elem().Set(reflect.MakeMap(mptr.Type().Elem())) } v := mptr.Elem() // map[K]V // Prepare addressable doubly-indirect placeholders for the key and value types. // See enc_new_map for why. keyptr := reflect.New(reflect.PtrTo(p.mtype.Key())).Elem() // addressable *K keybase := toStructPointer(keyptr.Addr()) // **K var valbase structPointer var valptr reflect.Value switch p.mtype.Elem().Kind() { case reflect.Slice: // []byte var dummy []byte valptr = reflect.ValueOf(&dummy) // *[]byte valbase = toStructPointer(valptr) // *[]byte case reflect.Ptr: // message; valptr is **Msg; need to allocate the intermediate pointer valptr = reflect.New(reflect.PtrTo(p.mtype.Elem())).Elem() // addressable *V valptr.Set(reflect.New(valptr.Type().Elem())) valbase = toStructPointer(valptr) default: // everything else valptr = reflect.New(reflect.PtrTo(p.mtype.Elem())).Elem() // addressable *V valbase = toStructPointer(valptr.Addr()) // **V } // Decode. // This parses a restricted wire format, namely the encoding of a message // with two fields. See enc_new_map for the format. for o.index < oi { // tagcode for key and value properties are always a single byte // because they have tags 1 and 2. tagcode := o.buf[o.index] o.index++ switch tagcode { case p.mkeyprop.tagcode[0]: if err := p.mkeyprop.dec(o, p.mkeyprop, keybase); err != nil { return err } case p.mvalprop.tagcode[0]: if err := p.mvalprop.dec(o, p.mvalprop, valbase); err != nil { return err } default: // TODO: Should we silently skip this instead? return fmt.Errorf("proto: bad map data tag %d", raw[0]) } } keyelem, valelem := keyptr.Elem(), valptr.Elem() if !keyelem.IsValid() { keyelem = reflect.Zero(p.mtype.Key()) } if !valelem.IsValid() { valelem = reflect.Zero(p.mtype.Elem()) } v.SetMapIndex(keyelem, valelem) return nil } // Decode a group. func (o *Buffer) dec_struct_group(p *Properties, base structPointer) error { bas := structPointer_GetStructPointer(base, p.field) if structPointer_IsNil(bas) { // allocate new nested message bas = toStructPointer(reflect.New(p.stype)) structPointer_SetStructPointer(base, p.field, bas) } return o.unmarshalType(p.stype, p.sprop, true, bas) } // Decode an embedded message. func (o *Buffer) dec_struct_message(p *Properties, base structPointer) (err error) { raw, e := o.DecodeRawBytes(false) if e != nil { return e } bas := structPointer_GetStructPointer(base, p.field) if structPointer_IsNil(bas) { // allocate new nested message bas = toStructPointer(reflect.New(p.stype)) structPointer_SetStructPointer(base, p.field, bas) } // If the object can unmarshal itself, let it. if p.isUnmarshaler { iv := structPointer_Interface(bas, p.stype) return iv.(Unmarshaler).Unmarshal(raw) } obuf := o.buf oi := o.index o.buf = raw o.index = 0 err = o.unmarshalType(p.stype, p.sprop, false, bas) o.buf = obuf o.index = oi return err } // Decode a slice of embedded messages. func (o *Buffer) dec_slice_struct_message(p *Properties, base structPointer) error { return o.dec_slice_struct(p, false, base) } // Decode a slice of embedded groups. func (o *Buffer) dec_slice_struct_group(p *Properties, base structPointer) error { return o.dec_slice_struct(p, true, base) } // Decode a slice of structs ([]*struct). func (o *Buffer) dec_slice_struct(p *Properties, is_group bool, base structPointer) error { v := reflect.New(p.stype) bas := toStructPointer(v) structPointer_StructPointerSlice(base, p.field).Append(bas) if is_group { err := o.unmarshalType(p.stype, p.sprop, is_group, bas) return err } raw, err := o.DecodeRawBytes(false) if err != nil { return err } // If the object can unmarshal itself, let it. if p.isUnmarshaler { iv := v.Interface() return iv.(Unmarshaler).Unmarshal(raw) } obuf := o.buf oi := o.index o.buf = raw o.index = 0 err = o.unmarshalType(p.stype, p.sprop, is_group, bas) o.buf = obuf o.index = oi return err } lxd-2.0.0/dist/src/github.com/golang/protobuf/proto/equal_test.go0000644061062106075000000002001612702772352027454 0ustar00stgraberdomain admins00000000000000// Go support for Protocol Buffers - Google's data interchange format // // Copyright 2011 The Go Authors. All rights reserved. // https://github.com/golang/protobuf // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package proto_test import ( "testing" . "github.com/golang/protobuf/proto" proto3pb "github.com/golang/protobuf/proto/proto3_proto" pb "github.com/golang/protobuf/proto/testdata" ) // Four identical base messages. // The init function adds extensions to some of them. var messageWithoutExtension = &pb.MyMessage{Count: Int32(7)} var messageWithExtension1a = &pb.MyMessage{Count: Int32(7)} var messageWithExtension1b = &pb.MyMessage{Count: Int32(7)} var messageWithExtension2 = &pb.MyMessage{Count: Int32(7)} // Two messages with non-message extensions. var messageWithInt32Extension1 = &pb.MyMessage{Count: Int32(8)} var messageWithInt32Extension2 = &pb.MyMessage{Count: Int32(8)} func init() { ext1 := &pb.Ext{Data: String("Kirk")} ext2 := &pb.Ext{Data: String("Picard")} // messageWithExtension1a has ext1, but never marshals it. if err := SetExtension(messageWithExtension1a, pb.E_Ext_More, ext1); err != nil { panic("SetExtension on 1a failed: " + err.Error()) } // messageWithExtension1b is the unmarshaled form of messageWithExtension1a. if err := SetExtension(messageWithExtension1b, pb.E_Ext_More, ext1); err != nil { panic("SetExtension on 1b failed: " + err.Error()) } buf, err := Marshal(messageWithExtension1b) if err != nil { panic("Marshal of 1b failed: " + err.Error()) } messageWithExtension1b.Reset() if err := Unmarshal(buf, messageWithExtension1b); err != nil { panic("Unmarshal of 1b failed: " + err.Error()) } // messageWithExtension2 has ext2. if err := SetExtension(messageWithExtension2, pb.E_Ext_More, ext2); err != nil { panic("SetExtension on 2 failed: " + err.Error()) } if err := SetExtension(messageWithInt32Extension1, pb.E_Ext_Number, Int32(23)); err != nil { panic("SetExtension on Int32-1 failed: " + err.Error()) } if err := SetExtension(messageWithInt32Extension1, pb.E_Ext_Number, Int32(24)); err != nil { panic("SetExtension on Int32-2 failed: " + err.Error()) } } var EqualTests = []struct { desc string a, b Message exp bool }{ {"different types", &pb.GoEnum{}, &pb.GoTestField{}, false}, {"equal empty", &pb.GoEnum{}, &pb.GoEnum{}, true}, {"nil vs nil", nil, nil, true}, {"typed nil vs typed nil", (*pb.GoEnum)(nil), (*pb.GoEnum)(nil), true}, {"typed nil vs empty", (*pb.GoEnum)(nil), &pb.GoEnum{}, false}, {"different typed nil", (*pb.GoEnum)(nil), (*pb.GoTestField)(nil), false}, {"one set field, one unset field", &pb.GoTestField{Label: String("foo")}, &pb.GoTestField{}, false}, {"one set field zero, one unset field", &pb.GoTest{Param: Int32(0)}, &pb.GoTest{}, false}, {"different set fields", &pb.GoTestField{Label: String("foo")}, &pb.GoTestField{Label: String("bar")}, false}, {"equal set", &pb.GoTestField{Label: String("foo")}, &pb.GoTestField{Label: String("foo")}, true}, {"repeated, one set", &pb.GoTest{F_Int32Repeated: []int32{2, 3}}, &pb.GoTest{}, false}, {"repeated, different length", &pb.GoTest{F_Int32Repeated: []int32{2, 3}}, &pb.GoTest{F_Int32Repeated: []int32{2}}, false}, {"repeated, different value", &pb.GoTest{F_Int32Repeated: []int32{2}}, &pb.GoTest{F_Int32Repeated: []int32{3}}, false}, {"repeated, equal", &pb.GoTest{F_Int32Repeated: []int32{2, 4}}, &pb.GoTest{F_Int32Repeated: []int32{2, 4}}, true}, {"repeated, nil equal nil", &pb.GoTest{F_Int32Repeated: nil}, &pb.GoTest{F_Int32Repeated: nil}, true}, {"repeated, nil equal empty", &pb.GoTest{F_Int32Repeated: nil}, &pb.GoTest{F_Int32Repeated: []int32{}}, true}, {"repeated, empty equal nil", &pb.GoTest{F_Int32Repeated: []int32{}}, &pb.GoTest{F_Int32Repeated: nil}, true}, { "nested, different", &pb.GoTest{RequiredField: &pb.GoTestField{Label: String("foo")}}, &pb.GoTest{RequiredField: &pb.GoTestField{Label: String("bar")}}, false, }, { "nested, equal", &pb.GoTest{RequiredField: &pb.GoTestField{Label: String("wow")}}, &pb.GoTest{RequiredField: &pb.GoTestField{Label: String("wow")}}, true, }, {"bytes", &pb.OtherMessage{Value: []byte("foo")}, &pb.OtherMessage{Value: []byte("foo")}, true}, {"bytes, empty", &pb.OtherMessage{Value: []byte{}}, &pb.OtherMessage{Value: []byte{}}, true}, {"bytes, empty vs nil", &pb.OtherMessage{Value: []byte{}}, &pb.OtherMessage{Value: nil}, false}, { "repeated bytes", &pb.MyMessage{RepBytes: [][]byte{[]byte("sham"), []byte("wow")}}, &pb.MyMessage{RepBytes: [][]byte{[]byte("sham"), []byte("wow")}}, true, }, // In proto3, []byte{} and []byte(nil) are equal. {"proto3 bytes, empty vs nil", &proto3pb.Message{Data: []byte{}}, &proto3pb.Message{Data: nil}, true}, {"extension vs. no extension", messageWithoutExtension, messageWithExtension1a, false}, {"extension vs. same extension", messageWithExtension1a, messageWithExtension1b, true}, {"extension vs. different extension", messageWithExtension1a, messageWithExtension2, false}, {"int32 extension vs. itself", messageWithInt32Extension1, messageWithInt32Extension1, true}, {"int32 extension vs. a different int32", messageWithInt32Extension1, messageWithInt32Extension2, false}, { "message with group", &pb.MyMessage{ Count: Int32(1), Somegroup: &pb.MyMessage_SomeGroup{ GroupField: Int32(5), }, }, &pb.MyMessage{ Count: Int32(1), Somegroup: &pb.MyMessage_SomeGroup{ GroupField: Int32(5), }, }, true, }, { "map same", &pb.MessageWithMap{NameMapping: map[int32]string{1: "Ken"}}, &pb.MessageWithMap{NameMapping: map[int32]string{1: "Ken"}}, true, }, { "map different entry", &pb.MessageWithMap{NameMapping: map[int32]string{1: "Ken"}}, &pb.MessageWithMap{NameMapping: map[int32]string{2: "Rob"}}, false, }, { "map different key only", &pb.MessageWithMap{NameMapping: map[int32]string{1: "Ken"}}, &pb.MessageWithMap{NameMapping: map[int32]string{2: "Ken"}}, false, }, { "map different value only", &pb.MessageWithMap{NameMapping: map[int32]string{1: "Ken"}}, &pb.MessageWithMap{NameMapping: map[int32]string{1: "Rob"}}, false, }, { "oneof same", &pb.Communique{Union: &pb.Communique_Number{41}}, &pb.Communique{Union: &pb.Communique_Number{41}}, true, }, { "oneof one nil", &pb.Communique{Union: &pb.Communique_Number{41}}, &pb.Communique{}, false, }, { "oneof different", &pb.Communique{Union: &pb.Communique_Number{41}}, &pb.Communique{Union: &pb.Communique_Name{"Bobby Tables"}}, false, }, } func TestEqual(t *testing.T) { for _, tc := range EqualTests { if res := Equal(tc.a, tc.b); res != tc.exp { t.Errorf("%v: Equal(%v, %v) = %v, want %v", tc.desc, tc.a, tc.b, res, tc.exp) } } } lxd-2.0.0/dist/src/github.com/golang/protobuf/proto/size_test.go0000644061062106075000000001752212702772352027327 0ustar00stgraberdomain admins00000000000000// Go support for Protocol Buffers - Google's data interchange format // // Copyright 2012 The Go Authors. All rights reserved. // https://github.com/golang/protobuf // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package proto_test import ( "log" "strings" "testing" . "github.com/golang/protobuf/proto" proto3pb "github.com/golang/protobuf/proto/proto3_proto" pb "github.com/golang/protobuf/proto/testdata" ) var messageWithExtension1 = &pb.MyMessage{Count: Int32(7)} // messageWithExtension2 is in equal_test.go. var messageWithExtension3 = &pb.MyMessage{Count: Int32(8)} func init() { if err := SetExtension(messageWithExtension1, pb.E_Ext_More, &pb.Ext{Data: String("Abbott")}); err != nil { log.Panicf("SetExtension: %v", err) } if err := SetExtension(messageWithExtension3, pb.E_Ext_More, &pb.Ext{Data: String("Costello")}); err != nil { log.Panicf("SetExtension: %v", err) } // Force messageWithExtension3 to have the extension encoded. Marshal(messageWithExtension3) } var SizeTests = []struct { desc string pb Message }{ {"empty", &pb.OtherMessage{}}, // Basic types. {"bool", &pb.Defaults{F_Bool: Bool(true)}}, {"int32", &pb.Defaults{F_Int32: Int32(12)}}, {"negative int32", &pb.Defaults{F_Int32: Int32(-1)}}, {"small int64", &pb.Defaults{F_Int64: Int64(1)}}, {"big int64", &pb.Defaults{F_Int64: Int64(1 << 20)}}, {"negative int64", &pb.Defaults{F_Int64: Int64(-1)}}, {"fixed32", &pb.Defaults{F_Fixed32: Uint32(71)}}, {"fixed64", &pb.Defaults{F_Fixed64: Uint64(72)}}, {"uint32", &pb.Defaults{F_Uint32: Uint32(123)}}, {"uint64", &pb.Defaults{F_Uint64: Uint64(124)}}, {"float", &pb.Defaults{F_Float: Float32(12.6)}}, {"double", &pb.Defaults{F_Double: Float64(13.9)}}, {"string", &pb.Defaults{F_String: String("niles")}}, {"bytes", &pb.Defaults{F_Bytes: []byte("wowsa")}}, {"bytes, empty", &pb.Defaults{F_Bytes: []byte{}}}, {"sint32", &pb.Defaults{F_Sint32: Int32(65)}}, {"sint64", &pb.Defaults{F_Sint64: Int64(67)}}, {"enum", &pb.Defaults{F_Enum: pb.Defaults_BLUE.Enum()}}, // Repeated. {"empty repeated bool", &pb.MoreRepeated{Bools: []bool{}}}, {"repeated bool", &pb.MoreRepeated{Bools: []bool{false, true, true, false}}}, {"packed repeated bool", &pb.MoreRepeated{BoolsPacked: []bool{false, true, true, false, true, true, true}}}, {"repeated int32", &pb.MoreRepeated{Ints: []int32{1, 12203, 1729, -1}}}, {"repeated int32 packed", &pb.MoreRepeated{IntsPacked: []int32{1, 12203, 1729}}}, {"repeated int64 packed", &pb.MoreRepeated{Int64SPacked: []int64{ // Need enough large numbers to verify that the header is counting the number of bytes // for the field, not the number of elements. 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, }}}, {"repeated string", &pb.MoreRepeated{Strings: []string{"r", "ken", "gri"}}}, {"repeated fixed", &pb.MoreRepeated{Fixeds: []uint32{1, 2, 3, 4}}}, // Nested. {"nested", &pb.OldMessage{Nested: &pb.OldMessage_Nested{Name: String("whatever")}}}, {"group", &pb.GroupOld{G: &pb.GroupOld_G{X: Int32(12345)}}}, // Other things. {"unrecognized", &pb.MoreRepeated{XXX_unrecognized: []byte{13<<3 | 0, 4}}}, {"extension (unencoded)", messageWithExtension1}, {"extension (encoded)", messageWithExtension3}, // proto3 message {"proto3 empty", &proto3pb.Message{}}, {"proto3 bool", &proto3pb.Message{TrueScotsman: true}}, {"proto3 int64", &proto3pb.Message{ResultCount: 1}}, {"proto3 uint32", &proto3pb.Message{HeightInCm: 123}}, {"proto3 float", &proto3pb.Message{Score: 12.6}}, {"proto3 string", &proto3pb.Message{Name: "Snezana"}}, {"proto3 bytes", &proto3pb.Message{Data: []byte("wowsa")}}, {"proto3 bytes, empty", &proto3pb.Message{Data: []byte{}}}, {"proto3 enum", &proto3pb.Message{Hilarity: proto3pb.Message_PUNS}}, {"proto3 map field with empty bytes", &proto3pb.MessageWithMap{ByteMapping: map[bool][]byte{false: []byte{}}}}, {"map field", &pb.MessageWithMap{NameMapping: map[int32]string{1: "Rob", 7: "Andrew"}}}, {"map field with message", &pb.MessageWithMap{MsgMapping: map[int64]*pb.FloatingPoint{0x7001: &pb.FloatingPoint{F: Float64(2.0)}}}}, {"map field with bytes", &pb.MessageWithMap{ByteMapping: map[bool][]byte{true: []byte("this time for sure")}}}, {"map field with empty bytes", &pb.MessageWithMap{ByteMapping: map[bool][]byte{true: []byte{}}}}, {"map field with big entry", &pb.MessageWithMap{NameMapping: map[int32]string{8: strings.Repeat("x", 125)}}}, {"map field with big key and val", &pb.MessageWithMap{StrToStr: map[string]string{strings.Repeat("x", 70): strings.Repeat("y", 70)}}}, {"map field with big numeric key", &pb.MessageWithMap{NameMapping: map[int32]string{0xf00d: "om nom nom"}}}, {"oneof not set", &pb.Oneof{}}, {"oneof bool", &pb.Oneof{Union: &pb.Oneof_F_Bool{true}}}, {"oneof zero int32", &pb.Oneof{Union: &pb.Oneof_F_Int32{0}}}, {"oneof big int32", &pb.Oneof{Union: &pb.Oneof_F_Int32{1 << 20}}}, {"oneof int64", &pb.Oneof{Union: &pb.Oneof_F_Int64{42}}}, {"oneof fixed32", &pb.Oneof{Union: &pb.Oneof_F_Fixed32{43}}}, {"oneof fixed64", &pb.Oneof{Union: &pb.Oneof_F_Fixed64{44}}}, {"oneof uint32", &pb.Oneof{Union: &pb.Oneof_F_Uint32{45}}}, {"oneof uint64", &pb.Oneof{Union: &pb.Oneof_F_Uint64{46}}}, {"oneof float", &pb.Oneof{Union: &pb.Oneof_F_Float{47.1}}}, {"oneof double", &pb.Oneof{Union: &pb.Oneof_F_Double{48.9}}}, {"oneof string", &pb.Oneof{Union: &pb.Oneof_F_String{"Rhythmic Fman"}}}, {"oneof bytes", &pb.Oneof{Union: &pb.Oneof_F_Bytes{[]byte("let go")}}}, {"oneof sint32", &pb.Oneof{Union: &pb.Oneof_F_Sint32{50}}}, {"oneof sint64", &pb.Oneof{Union: &pb.Oneof_F_Sint64{51}}}, {"oneof enum", &pb.Oneof{Union: &pb.Oneof_F_Enum{pb.MyMessage_BLUE}}}, {"message for oneof", &pb.GoTestField{Label: String("k"), Type: String("v")}}, {"oneof message", &pb.Oneof{Union: &pb.Oneof_F_Message{&pb.GoTestField{Label: String("k"), Type: String("v")}}}}, {"oneof group", &pb.Oneof{Union: &pb.Oneof_FGroup{&pb.Oneof_F_Group{X: Int32(52)}}}}, {"oneof largest tag", &pb.Oneof{Union: &pb.Oneof_F_Largest_Tag{1}}}, {"multiple oneofs", &pb.Oneof{Union: &pb.Oneof_F_Int32{1}, Tormato: &pb.Oneof_Value{2}}}, } func TestSize(t *testing.T) { for _, tc := range SizeTests { size := Size(tc.pb) b, err := Marshal(tc.pb) if err != nil { t.Errorf("%v: Marshal failed: %v", tc.desc, err) continue } if size != len(b) { t.Errorf("%v: Size(%v) = %d, want %d", tc.desc, tc.pb, size, len(b)) t.Logf("%v: bytes: %#v", tc.desc, b) } } } lxd-2.0.0/dist/src/github.com/golang/protobuf/proto/encode.go0000644061062106075000000010223112702772352026543 0ustar00stgraberdomain admins00000000000000// Go support for Protocol Buffers - Google's data interchange format // // Copyright 2010 The Go Authors. All rights reserved. // https://github.com/golang/protobuf // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package proto /* * Routines for encoding data into the wire format for protocol buffers. */ import ( "errors" "fmt" "reflect" "sort" ) // RequiredNotSetError is the error returned if Marshal is called with // a protocol buffer struct whose required fields have not // all been initialized. It is also the error returned if Unmarshal is // called with an encoded protocol buffer that does not include all the // required fields. // // When printed, RequiredNotSetError reports the first unset required field in a // message. If the field cannot be precisely determined, it is reported as // "{Unknown}". type RequiredNotSetError struct { field string } func (e *RequiredNotSetError) Error() string { return fmt.Sprintf("proto: required field %q not set", e.field) } var ( // errRepeatedHasNil is the error returned if Marshal is called with // a struct with a repeated field containing a nil element. errRepeatedHasNil = errors.New("proto: repeated field has nil element") // errOneofHasNil is the error returned if Marshal is called with // a struct with a oneof field containing a nil element. errOneofHasNil = errors.New("proto: oneof field has nil value") // ErrNil is the error returned if Marshal is called with nil. ErrNil = errors.New("proto: Marshal called with nil") ) // The fundamental encoders that put bytes on the wire. // Those that take integer types all accept uint64 and are // therefore of type valueEncoder. const maxVarintBytes = 10 // maximum length of a varint // EncodeVarint returns the varint encoding of x. // This is the format for the // int32, int64, uint32, uint64, bool, and enum // protocol buffer types. // Not used by the package itself, but helpful to clients // wishing to use the same encoding. func EncodeVarint(x uint64) []byte { var buf [maxVarintBytes]byte var n int for n = 0; x > 127; n++ { buf[n] = 0x80 | uint8(x&0x7F) x >>= 7 } buf[n] = uint8(x) n++ return buf[0:n] } // EncodeVarint writes a varint-encoded integer to the Buffer. // This is the format for the // int32, int64, uint32, uint64, bool, and enum // protocol buffer types. func (p *Buffer) EncodeVarint(x uint64) error { for x >= 1<<7 { p.buf = append(p.buf, uint8(x&0x7f|0x80)) x >>= 7 } p.buf = append(p.buf, uint8(x)) return nil } // SizeVarint returns the varint encoding size of an integer. func SizeVarint(x uint64) int { return sizeVarint(x) } func sizeVarint(x uint64) (n int) { for { n++ x >>= 7 if x == 0 { break } } return n } // EncodeFixed64 writes a 64-bit integer to the Buffer. // This is the format for the // fixed64, sfixed64, and double protocol buffer types. func (p *Buffer) EncodeFixed64(x uint64) error { p.buf = append(p.buf, uint8(x), uint8(x>>8), uint8(x>>16), uint8(x>>24), uint8(x>>32), uint8(x>>40), uint8(x>>48), uint8(x>>56)) return nil } func sizeFixed64(x uint64) int { return 8 } // EncodeFixed32 writes a 32-bit integer to the Buffer. // This is the format for the // fixed32, sfixed32, and float protocol buffer types. func (p *Buffer) EncodeFixed32(x uint64) error { p.buf = append(p.buf, uint8(x), uint8(x>>8), uint8(x>>16), uint8(x>>24)) return nil } func sizeFixed32(x uint64) int { return 4 } // EncodeZigzag64 writes a zigzag-encoded 64-bit integer // to the Buffer. // This is the format used for the sint64 protocol buffer type. func (p *Buffer) EncodeZigzag64(x uint64) error { // use signed number to get arithmetic right shift. return p.EncodeVarint(uint64((x << 1) ^ uint64((int64(x) >> 63)))) } func sizeZigzag64(x uint64) int { return sizeVarint(uint64((x << 1) ^ uint64((int64(x) >> 63)))) } // EncodeZigzag32 writes a zigzag-encoded 32-bit integer // to the Buffer. // This is the format used for the sint32 protocol buffer type. func (p *Buffer) EncodeZigzag32(x uint64) error { // use signed number to get arithmetic right shift. return p.EncodeVarint(uint64((uint32(x) << 1) ^ uint32((int32(x) >> 31)))) } func sizeZigzag32(x uint64) int { return sizeVarint(uint64((uint32(x) << 1) ^ uint32((int32(x) >> 31)))) } // EncodeRawBytes writes a count-delimited byte buffer to the Buffer. // This is the format used for the bytes protocol buffer // type and for embedded messages. func (p *Buffer) EncodeRawBytes(b []byte) error { p.EncodeVarint(uint64(len(b))) p.buf = append(p.buf, b...) return nil } func sizeRawBytes(b []byte) int { return sizeVarint(uint64(len(b))) + len(b) } // EncodeStringBytes writes an encoded string to the Buffer. // This is the format used for the proto2 string type. func (p *Buffer) EncodeStringBytes(s string) error { p.EncodeVarint(uint64(len(s))) p.buf = append(p.buf, s...) return nil } func sizeStringBytes(s string) int { return sizeVarint(uint64(len(s))) + len(s) } // Marshaler is the interface representing objects that can marshal themselves. type Marshaler interface { Marshal() ([]byte, error) } // Marshal takes the protocol buffer // and encodes it into the wire format, returning the data. func Marshal(pb Message) ([]byte, error) { // Can the object marshal itself? if m, ok := pb.(Marshaler); ok { return m.Marshal() } p := NewBuffer(nil) err := p.Marshal(pb) var state errorState if err != nil && !state.shouldContinue(err, nil) { return nil, err } if p.buf == nil && err == nil { // Return a non-nil slice on success. return []byte{}, nil } return p.buf, err } // EncodeMessage writes the protocol buffer to the Buffer, // prefixed by a varint-encoded length. func (p *Buffer) EncodeMessage(pb Message) error { t, base, err := getbase(pb) if structPointer_IsNil(base) { return ErrNil } if err == nil { var state errorState err = p.enc_len_struct(GetProperties(t.Elem()), base, &state) } return err } // Marshal takes the protocol buffer // and encodes it into the wire format, writing the result to the // Buffer. func (p *Buffer) Marshal(pb Message) error { // Can the object marshal itself? if m, ok := pb.(Marshaler); ok { data, err := m.Marshal() if err != nil { return err } p.buf = append(p.buf, data...) return nil } t, base, err := getbase(pb) if structPointer_IsNil(base) { return ErrNil } if err == nil { err = p.enc_struct(GetProperties(t.Elem()), base) } if collectStats { stats.Encode++ } return err } // Size returns the encoded size of a protocol buffer. func Size(pb Message) (n int) { // Can the object marshal itself? If so, Size is slow. // TODO: add Size to Marshaler, or add a Sizer interface. if m, ok := pb.(Marshaler); ok { b, _ := m.Marshal() return len(b) } t, base, err := getbase(pb) if structPointer_IsNil(base) { return 0 } if err == nil { n = size_struct(GetProperties(t.Elem()), base) } if collectStats { stats.Size++ } return } // Individual type encoders. // Encode a bool. func (o *Buffer) enc_bool(p *Properties, base structPointer) error { v := *structPointer_Bool(base, p.field) if v == nil { return ErrNil } x := 0 if *v { x = 1 } o.buf = append(o.buf, p.tagcode...) p.valEnc(o, uint64(x)) return nil } func (o *Buffer) enc_proto3_bool(p *Properties, base structPointer) error { v := *structPointer_BoolVal(base, p.field) if !v { return ErrNil } o.buf = append(o.buf, p.tagcode...) p.valEnc(o, 1) return nil } func size_bool(p *Properties, base structPointer) int { v := *structPointer_Bool(base, p.field) if v == nil { return 0 } return len(p.tagcode) + 1 // each bool takes exactly one byte } func size_proto3_bool(p *Properties, base structPointer) int { v := *structPointer_BoolVal(base, p.field) if !v && !p.oneof { return 0 } return len(p.tagcode) + 1 // each bool takes exactly one byte } // Encode an int32. func (o *Buffer) enc_int32(p *Properties, base structPointer) error { v := structPointer_Word32(base, p.field) if word32_IsNil(v) { return ErrNil } x := int32(word32_Get(v)) // permit sign extension to use full 64-bit range o.buf = append(o.buf, p.tagcode...) p.valEnc(o, uint64(x)) return nil } func (o *Buffer) enc_proto3_int32(p *Properties, base structPointer) error { v := structPointer_Word32Val(base, p.field) x := int32(word32Val_Get(v)) // permit sign extension to use full 64-bit range if x == 0 { return ErrNil } o.buf = append(o.buf, p.tagcode...) p.valEnc(o, uint64(x)) return nil } func size_int32(p *Properties, base structPointer) (n int) { v := structPointer_Word32(base, p.field) if word32_IsNil(v) { return 0 } x := int32(word32_Get(v)) // permit sign extension to use full 64-bit range n += len(p.tagcode) n += p.valSize(uint64(x)) return } func size_proto3_int32(p *Properties, base structPointer) (n int) { v := structPointer_Word32Val(base, p.field) x := int32(word32Val_Get(v)) // permit sign extension to use full 64-bit range if x == 0 && !p.oneof { return 0 } n += len(p.tagcode) n += p.valSize(uint64(x)) return } // Encode a uint32. // Exactly the same as int32, except for no sign extension. func (o *Buffer) enc_uint32(p *Properties, base structPointer) error { v := structPointer_Word32(base, p.field) if word32_IsNil(v) { return ErrNil } x := word32_Get(v) o.buf = append(o.buf, p.tagcode...) p.valEnc(o, uint64(x)) return nil } func (o *Buffer) enc_proto3_uint32(p *Properties, base structPointer) error { v := structPointer_Word32Val(base, p.field) x := word32Val_Get(v) if x == 0 { return ErrNil } o.buf = append(o.buf, p.tagcode...) p.valEnc(o, uint64(x)) return nil } func size_uint32(p *Properties, base structPointer) (n int) { v := structPointer_Word32(base, p.field) if word32_IsNil(v) { return 0 } x := word32_Get(v) n += len(p.tagcode) n += p.valSize(uint64(x)) return } func size_proto3_uint32(p *Properties, base structPointer) (n int) { v := structPointer_Word32Val(base, p.field) x := word32Val_Get(v) if x == 0 && !p.oneof { return 0 } n += len(p.tagcode) n += p.valSize(uint64(x)) return } // Encode an int64. func (o *Buffer) enc_int64(p *Properties, base structPointer) error { v := structPointer_Word64(base, p.field) if word64_IsNil(v) { return ErrNil } x := word64_Get(v) o.buf = append(o.buf, p.tagcode...) p.valEnc(o, x) return nil } func (o *Buffer) enc_proto3_int64(p *Properties, base structPointer) error { v := structPointer_Word64Val(base, p.field) x := word64Val_Get(v) if x == 0 { return ErrNil } o.buf = append(o.buf, p.tagcode...) p.valEnc(o, x) return nil } func size_int64(p *Properties, base structPointer) (n int) { v := structPointer_Word64(base, p.field) if word64_IsNil(v) { return 0 } x := word64_Get(v) n += len(p.tagcode) n += p.valSize(x) return } func size_proto3_int64(p *Properties, base structPointer) (n int) { v := structPointer_Word64Val(base, p.field) x := word64Val_Get(v) if x == 0 && !p.oneof { return 0 } n += len(p.tagcode) n += p.valSize(x) return } // Encode a string. func (o *Buffer) enc_string(p *Properties, base structPointer) error { v := *structPointer_String(base, p.field) if v == nil { return ErrNil } x := *v o.buf = append(o.buf, p.tagcode...) o.EncodeStringBytes(x) return nil } func (o *Buffer) enc_proto3_string(p *Properties, base structPointer) error { v := *structPointer_StringVal(base, p.field) if v == "" { return ErrNil } o.buf = append(o.buf, p.tagcode...) o.EncodeStringBytes(v) return nil } func size_string(p *Properties, base structPointer) (n int) { v := *structPointer_String(base, p.field) if v == nil { return 0 } x := *v n += len(p.tagcode) n += sizeStringBytes(x) return } func size_proto3_string(p *Properties, base structPointer) (n int) { v := *structPointer_StringVal(base, p.field) if v == "" && !p.oneof { return 0 } n += len(p.tagcode) n += sizeStringBytes(v) return } // All protocol buffer fields are nillable, but be careful. func isNil(v reflect.Value) bool { switch v.Kind() { case reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice: return v.IsNil() } return false } // Encode a message struct. func (o *Buffer) enc_struct_message(p *Properties, base structPointer) error { var state errorState structp := structPointer_GetStructPointer(base, p.field) if structPointer_IsNil(structp) { return ErrNil } // Can the object marshal itself? if p.isMarshaler { m := structPointer_Interface(structp, p.stype).(Marshaler) data, err := m.Marshal() if err != nil && !state.shouldContinue(err, nil) { return err } o.buf = append(o.buf, p.tagcode...) o.EncodeRawBytes(data) return state.err } o.buf = append(o.buf, p.tagcode...) return o.enc_len_struct(p.sprop, structp, &state) } func size_struct_message(p *Properties, base structPointer) int { structp := structPointer_GetStructPointer(base, p.field) if structPointer_IsNil(structp) { return 0 } // Can the object marshal itself? if p.isMarshaler { m := structPointer_Interface(structp, p.stype).(Marshaler) data, _ := m.Marshal() n0 := len(p.tagcode) n1 := sizeRawBytes(data) return n0 + n1 } n0 := len(p.tagcode) n1 := size_struct(p.sprop, structp) n2 := sizeVarint(uint64(n1)) // size of encoded length return n0 + n1 + n2 } // Encode a group struct. func (o *Buffer) enc_struct_group(p *Properties, base structPointer) error { var state errorState b := structPointer_GetStructPointer(base, p.field) if structPointer_IsNil(b) { return ErrNil } o.EncodeVarint(uint64((p.Tag << 3) | WireStartGroup)) err := o.enc_struct(p.sprop, b) if err != nil && !state.shouldContinue(err, nil) { return err } o.EncodeVarint(uint64((p.Tag << 3) | WireEndGroup)) return state.err } func size_struct_group(p *Properties, base structPointer) (n int) { b := structPointer_GetStructPointer(base, p.field) if structPointer_IsNil(b) { return 0 } n += sizeVarint(uint64((p.Tag << 3) | WireStartGroup)) n += size_struct(p.sprop, b) n += sizeVarint(uint64((p.Tag << 3) | WireEndGroup)) return } // Encode a slice of bools ([]bool). func (o *Buffer) enc_slice_bool(p *Properties, base structPointer) error { s := *structPointer_BoolSlice(base, p.field) l := len(s) if l == 0 { return ErrNil } for _, x := range s { o.buf = append(o.buf, p.tagcode...) v := uint64(0) if x { v = 1 } p.valEnc(o, v) } return nil } func size_slice_bool(p *Properties, base structPointer) int { s := *structPointer_BoolSlice(base, p.field) l := len(s) if l == 0 { return 0 } return l * (len(p.tagcode) + 1) // each bool takes exactly one byte } // Encode a slice of bools ([]bool) in packed format. func (o *Buffer) enc_slice_packed_bool(p *Properties, base structPointer) error { s := *structPointer_BoolSlice(base, p.field) l := len(s) if l == 0 { return ErrNil } o.buf = append(o.buf, p.tagcode...) o.EncodeVarint(uint64(l)) // each bool takes exactly one byte for _, x := range s { v := uint64(0) if x { v = 1 } p.valEnc(o, v) } return nil } func size_slice_packed_bool(p *Properties, base structPointer) (n int) { s := *structPointer_BoolSlice(base, p.field) l := len(s) if l == 0 { return 0 } n += len(p.tagcode) n += sizeVarint(uint64(l)) n += l // each bool takes exactly one byte return } // Encode a slice of bytes ([]byte). func (o *Buffer) enc_slice_byte(p *Properties, base structPointer) error { s := *structPointer_Bytes(base, p.field) if s == nil { return ErrNil } o.buf = append(o.buf, p.tagcode...) o.EncodeRawBytes(s) return nil } func (o *Buffer) enc_proto3_slice_byte(p *Properties, base structPointer) error { s := *structPointer_Bytes(base, p.field) if len(s) == 0 { return ErrNil } o.buf = append(o.buf, p.tagcode...) o.EncodeRawBytes(s) return nil } func size_slice_byte(p *Properties, base structPointer) (n int) { s := *structPointer_Bytes(base, p.field) if s == nil && !p.oneof { return 0 } n += len(p.tagcode) n += sizeRawBytes(s) return } func size_proto3_slice_byte(p *Properties, base structPointer) (n int) { s := *structPointer_Bytes(base, p.field) if len(s) == 0 && !p.oneof { return 0 } n += len(p.tagcode) n += sizeRawBytes(s) return } // Encode a slice of int32s ([]int32). func (o *Buffer) enc_slice_int32(p *Properties, base structPointer) error { s := structPointer_Word32Slice(base, p.field) l := s.Len() if l == 0 { return ErrNil } for i := 0; i < l; i++ { o.buf = append(o.buf, p.tagcode...) x := int32(s.Index(i)) // permit sign extension to use full 64-bit range p.valEnc(o, uint64(x)) } return nil } func size_slice_int32(p *Properties, base structPointer) (n int) { s := structPointer_Word32Slice(base, p.field) l := s.Len() if l == 0 { return 0 } for i := 0; i < l; i++ { n += len(p.tagcode) x := int32(s.Index(i)) // permit sign extension to use full 64-bit range n += p.valSize(uint64(x)) } return } // Encode a slice of int32s ([]int32) in packed format. func (o *Buffer) enc_slice_packed_int32(p *Properties, base structPointer) error { s := structPointer_Word32Slice(base, p.field) l := s.Len() if l == 0 { return ErrNil } // TODO: Reuse a Buffer. buf := NewBuffer(nil) for i := 0; i < l; i++ { x := int32(s.Index(i)) // permit sign extension to use full 64-bit range p.valEnc(buf, uint64(x)) } o.buf = append(o.buf, p.tagcode...) o.EncodeVarint(uint64(len(buf.buf))) o.buf = append(o.buf, buf.buf...) return nil } func size_slice_packed_int32(p *Properties, base structPointer) (n int) { s := structPointer_Word32Slice(base, p.field) l := s.Len() if l == 0 { return 0 } var bufSize int for i := 0; i < l; i++ { x := int32(s.Index(i)) // permit sign extension to use full 64-bit range bufSize += p.valSize(uint64(x)) } n += len(p.tagcode) n += sizeVarint(uint64(bufSize)) n += bufSize return } // Encode a slice of uint32s ([]uint32). // Exactly the same as int32, except for no sign extension. func (o *Buffer) enc_slice_uint32(p *Properties, base structPointer) error { s := structPointer_Word32Slice(base, p.field) l := s.Len() if l == 0 { return ErrNil } for i := 0; i < l; i++ { o.buf = append(o.buf, p.tagcode...) x := s.Index(i) p.valEnc(o, uint64(x)) } return nil } func size_slice_uint32(p *Properties, base structPointer) (n int) { s := structPointer_Word32Slice(base, p.field) l := s.Len() if l == 0 { return 0 } for i := 0; i < l; i++ { n += len(p.tagcode) x := s.Index(i) n += p.valSize(uint64(x)) } return } // Encode a slice of uint32s ([]uint32) in packed format. // Exactly the same as int32, except for no sign extension. func (o *Buffer) enc_slice_packed_uint32(p *Properties, base structPointer) error { s := structPointer_Word32Slice(base, p.field) l := s.Len() if l == 0 { return ErrNil } // TODO: Reuse a Buffer. buf := NewBuffer(nil) for i := 0; i < l; i++ { p.valEnc(buf, uint64(s.Index(i))) } o.buf = append(o.buf, p.tagcode...) o.EncodeVarint(uint64(len(buf.buf))) o.buf = append(o.buf, buf.buf...) return nil } func size_slice_packed_uint32(p *Properties, base structPointer) (n int) { s := structPointer_Word32Slice(base, p.field) l := s.Len() if l == 0 { return 0 } var bufSize int for i := 0; i < l; i++ { bufSize += p.valSize(uint64(s.Index(i))) } n += len(p.tagcode) n += sizeVarint(uint64(bufSize)) n += bufSize return } // Encode a slice of int64s ([]int64). func (o *Buffer) enc_slice_int64(p *Properties, base structPointer) error { s := structPointer_Word64Slice(base, p.field) l := s.Len() if l == 0 { return ErrNil } for i := 0; i < l; i++ { o.buf = append(o.buf, p.tagcode...) p.valEnc(o, s.Index(i)) } return nil } func size_slice_int64(p *Properties, base structPointer) (n int) { s := structPointer_Word64Slice(base, p.field) l := s.Len() if l == 0 { return 0 } for i := 0; i < l; i++ { n += len(p.tagcode) n += p.valSize(s.Index(i)) } return } // Encode a slice of int64s ([]int64) in packed format. func (o *Buffer) enc_slice_packed_int64(p *Properties, base structPointer) error { s := structPointer_Word64Slice(base, p.field) l := s.Len() if l == 0 { return ErrNil } // TODO: Reuse a Buffer. buf := NewBuffer(nil) for i := 0; i < l; i++ { p.valEnc(buf, s.Index(i)) } o.buf = append(o.buf, p.tagcode...) o.EncodeVarint(uint64(len(buf.buf))) o.buf = append(o.buf, buf.buf...) return nil } func size_slice_packed_int64(p *Properties, base structPointer) (n int) { s := structPointer_Word64Slice(base, p.field) l := s.Len() if l == 0 { return 0 } var bufSize int for i := 0; i < l; i++ { bufSize += p.valSize(s.Index(i)) } n += len(p.tagcode) n += sizeVarint(uint64(bufSize)) n += bufSize return } // Encode a slice of slice of bytes ([][]byte). func (o *Buffer) enc_slice_slice_byte(p *Properties, base structPointer) error { ss := *structPointer_BytesSlice(base, p.field) l := len(ss) if l == 0 { return ErrNil } for i := 0; i < l; i++ { o.buf = append(o.buf, p.tagcode...) o.EncodeRawBytes(ss[i]) } return nil } func size_slice_slice_byte(p *Properties, base structPointer) (n int) { ss := *structPointer_BytesSlice(base, p.field) l := len(ss) if l == 0 { return 0 } n += l * len(p.tagcode) for i := 0; i < l; i++ { n += sizeRawBytes(ss[i]) } return } // Encode a slice of strings ([]string). func (o *Buffer) enc_slice_string(p *Properties, base structPointer) error { ss := *structPointer_StringSlice(base, p.field) l := len(ss) for i := 0; i < l; i++ { o.buf = append(o.buf, p.tagcode...) o.EncodeStringBytes(ss[i]) } return nil } func size_slice_string(p *Properties, base structPointer) (n int) { ss := *structPointer_StringSlice(base, p.field) l := len(ss) n += l * len(p.tagcode) for i := 0; i < l; i++ { n += sizeStringBytes(ss[i]) } return } // Encode a slice of message structs ([]*struct). func (o *Buffer) enc_slice_struct_message(p *Properties, base structPointer) error { var state errorState s := structPointer_StructPointerSlice(base, p.field) l := s.Len() for i := 0; i < l; i++ { structp := s.Index(i) if structPointer_IsNil(structp) { return errRepeatedHasNil } // Can the object marshal itself? if p.isMarshaler { m := structPointer_Interface(structp, p.stype).(Marshaler) data, err := m.Marshal() if err != nil && !state.shouldContinue(err, nil) { return err } o.buf = append(o.buf, p.tagcode...) o.EncodeRawBytes(data) continue } o.buf = append(o.buf, p.tagcode...) err := o.enc_len_struct(p.sprop, structp, &state) if err != nil && !state.shouldContinue(err, nil) { if err == ErrNil { return errRepeatedHasNil } return err } } return state.err } func size_slice_struct_message(p *Properties, base structPointer) (n int) { s := structPointer_StructPointerSlice(base, p.field) l := s.Len() n += l * len(p.tagcode) for i := 0; i < l; i++ { structp := s.Index(i) if structPointer_IsNil(structp) { return // return the size up to this point } // Can the object marshal itself? if p.isMarshaler { m := structPointer_Interface(structp, p.stype).(Marshaler) data, _ := m.Marshal() n += len(p.tagcode) n += sizeRawBytes(data) continue } n0 := size_struct(p.sprop, structp) n1 := sizeVarint(uint64(n0)) // size of encoded length n += n0 + n1 } return } // Encode a slice of group structs ([]*struct). func (o *Buffer) enc_slice_struct_group(p *Properties, base structPointer) error { var state errorState s := structPointer_StructPointerSlice(base, p.field) l := s.Len() for i := 0; i < l; i++ { b := s.Index(i) if structPointer_IsNil(b) { return errRepeatedHasNil } o.EncodeVarint(uint64((p.Tag << 3) | WireStartGroup)) err := o.enc_struct(p.sprop, b) if err != nil && !state.shouldContinue(err, nil) { if err == ErrNil { return errRepeatedHasNil } return err } o.EncodeVarint(uint64((p.Tag << 3) | WireEndGroup)) } return state.err } func size_slice_struct_group(p *Properties, base structPointer) (n int) { s := structPointer_StructPointerSlice(base, p.field) l := s.Len() n += l * sizeVarint(uint64((p.Tag<<3)|WireStartGroup)) n += l * sizeVarint(uint64((p.Tag<<3)|WireEndGroup)) for i := 0; i < l; i++ { b := s.Index(i) if structPointer_IsNil(b) { return // return size up to this point } n += size_struct(p.sprop, b) } return } // Encode an extension map. func (o *Buffer) enc_map(p *Properties, base structPointer) error { v := *structPointer_ExtMap(base, p.field) if err := encodeExtensionMap(v); err != nil { return err } // Fast-path for common cases: zero or one extensions. if len(v) <= 1 { for _, e := range v { o.buf = append(o.buf, e.enc...) } return nil } // Sort keys to provide a deterministic encoding. keys := make([]int, 0, len(v)) for k := range v { keys = append(keys, int(k)) } sort.Ints(keys) for _, k := range keys { o.buf = append(o.buf, v[int32(k)].enc...) } return nil } func size_map(p *Properties, base structPointer) int { v := *structPointer_ExtMap(base, p.field) return sizeExtensionMap(v) } // Encode a map field. func (o *Buffer) enc_new_map(p *Properties, base structPointer) error { var state errorState // XXX: or do we need to plumb this through? /* A map defined as map map_field = N; is encoded in the same way as message MapFieldEntry { key_type key = 1; value_type value = 2; } repeated MapFieldEntry map_field = N; */ v := structPointer_NewAt(base, p.field, p.mtype).Elem() // map[K]V if v.Len() == 0 { return nil } keycopy, valcopy, keybase, valbase := mapEncodeScratch(p.mtype) enc := func() error { if err := p.mkeyprop.enc(o, p.mkeyprop, keybase); err != nil { return err } if err := p.mvalprop.enc(o, p.mvalprop, valbase); err != nil { return err } return nil } // Don't sort map keys. It is not required by the spec, and C++ doesn't do it. for _, key := range v.MapKeys() { val := v.MapIndex(key) // The only illegal map entry values are nil message pointers. if val.Kind() == reflect.Ptr && val.IsNil() { return errors.New("proto: map has nil element") } keycopy.Set(key) valcopy.Set(val) o.buf = append(o.buf, p.tagcode...) if err := o.enc_len_thing(enc, &state); err != nil { return err } } return nil } func size_new_map(p *Properties, base structPointer) int { v := structPointer_NewAt(base, p.field, p.mtype).Elem() // map[K]V keycopy, valcopy, keybase, valbase := mapEncodeScratch(p.mtype) n := 0 for _, key := range v.MapKeys() { val := v.MapIndex(key) keycopy.Set(key) valcopy.Set(val) // Tag codes for key and val are the responsibility of the sub-sizer. keysize := p.mkeyprop.size(p.mkeyprop, keybase) valsize := p.mvalprop.size(p.mvalprop, valbase) entry := keysize + valsize // Add on tag code and length of map entry itself. n += len(p.tagcode) + sizeVarint(uint64(entry)) + entry } return n } // mapEncodeScratch returns a new reflect.Value matching the map's value type, // and a structPointer suitable for passing to an encoder or sizer. func mapEncodeScratch(mapType reflect.Type) (keycopy, valcopy reflect.Value, keybase, valbase structPointer) { // Prepare addressable doubly-indirect placeholders for the key and value types. // This is needed because the element-type encoders expect **T, but the map iteration produces T. keycopy = reflect.New(mapType.Key()).Elem() // addressable K keyptr := reflect.New(reflect.PtrTo(keycopy.Type())).Elem() // addressable *K keyptr.Set(keycopy.Addr()) // keybase = toStructPointer(keyptr.Addr()) // **K // Value types are more varied and require special handling. switch mapType.Elem().Kind() { case reflect.Slice: // []byte var dummy []byte valcopy = reflect.ValueOf(&dummy).Elem() // addressable []byte valbase = toStructPointer(valcopy.Addr()) case reflect.Ptr: // message; the generated field type is map[K]*Msg (so V is *Msg), // so we only need one level of indirection. valcopy = reflect.New(mapType.Elem()).Elem() // addressable V valbase = toStructPointer(valcopy.Addr()) default: // everything else valcopy = reflect.New(mapType.Elem()).Elem() // addressable V valptr := reflect.New(reflect.PtrTo(valcopy.Type())).Elem() // addressable *V valptr.Set(valcopy.Addr()) // valbase = toStructPointer(valptr.Addr()) // **V } return } // Encode a struct. func (o *Buffer) enc_struct(prop *StructProperties, base structPointer) error { var state errorState // Encode fields in tag order so that decoders may use optimizations // that depend on the ordering. // https://developers.google.com/protocol-buffers/docs/encoding#order for _, i := range prop.order { p := prop.Prop[i] if p.enc != nil { err := p.enc(o, p, base) if err != nil { if err == ErrNil { if p.Required && state.err == nil { state.err = &RequiredNotSetError{p.Name} } } else if err == errRepeatedHasNil { // Give more context to nil values in repeated fields. return errors.New("repeated field " + p.OrigName + " has nil element") } else if !state.shouldContinue(err, p) { return err } } } } // Do oneof fields. if prop.oneofMarshaler != nil { m := structPointer_Interface(base, prop.stype).(Message) if err := prop.oneofMarshaler(m, o); err == ErrNil { return errOneofHasNil } else if err != nil { return err } } // Add unrecognized fields at the end. if prop.unrecField.IsValid() { v := *structPointer_Bytes(base, prop.unrecField) if len(v) > 0 { o.buf = append(o.buf, v...) } } return state.err } func size_struct(prop *StructProperties, base structPointer) (n int) { for _, i := range prop.order { p := prop.Prop[i] if p.size != nil { n += p.size(p, base) } } // Add unrecognized fields at the end. if prop.unrecField.IsValid() { v := *structPointer_Bytes(base, prop.unrecField) n += len(v) } // Factor in any oneof fields. if prop.oneofSizer != nil { m := structPointer_Interface(base, prop.stype).(Message) n += prop.oneofSizer(m) } return } var zeroes [20]byte // longer than any conceivable sizeVarint // Encode a struct, preceded by its encoded length (as a varint). func (o *Buffer) enc_len_struct(prop *StructProperties, base structPointer, state *errorState) error { return o.enc_len_thing(func() error { return o.enc_struct(prop, base) }, state) } // Encode something, preceded by its encoded length (as a varint). func (o *Buffer) enc_len_thing(enc func() error, state *errorState) error { iLen := len(o.buf) o.buf = append(o.buf, 0, 0, 0, 0) // reserve four bytes for length iMsg := len(o.buf) err := enc() if err != nil && !state.shouldContinue(err, nil) { return err } lMsg := len(o.buf) - iMsg lLen := sizeVarint(uint64(lMsg)) switch x := lLen - (iMsg - iLen); { case x > 0: // actual length is x bytes larger than the space we reserved // Move msg x bytes right. o.buf = append(o.buf, zeroes[:x]...) copy(o.buf[iMsg+x:], o.buf[iMsg:iMsg+lMsg]) case x < 0: // actual length is x bytes smaller than the space we reserved // Move msg x bytes left. copy(o.buf[iMsg+x:], o.buf[iMsg:iMsg+lMsg]) o.buf = o.buf[:len(o.buf)+x] // x is negative } // Encode the length in the reserved space. o.buf = o.buf[:iLen] o.EncodeVarint(uint64(lMsg)) o.buf = o.buf[:len(o.buf)+lMsg] return state.err } // errorState maintains the first error that occurs and updates that error // with additional context. type errorState struct { err error } // shouldContinue reports whether encoding should continue upon encountering the // given error. If the error is RequiredNotSetError, shouldContinue returns true // and, if this is the first appearance of that error, remembers it for future // reporting. // // If prop is not nil, it may update any error with additional context about the // field with the error. func (s *errorState) shouldContinue(err error, prop *Properties) bool { // Ignore unset required fields. reqNotSet, ok := err.(*RequiredNotSetError) if !ok { return false } if s.err == nil { if prop != nil { err = &RequiredNotSetError{prop.Name + "." + reqNotSet.field} } s.err = err } return true } lxd-2.0.0/dist/src/github.com/golang/protobuf/proto/equal.go0000644061062106075000000001721012702772352026417 0ustar00stgraberdomain admins00000000000000// Go support for Protocol Buffers - Google's data interchange format // // Copyright 2011 The Go Authors. All rights reserved. // https://github.com/golang/protobuf // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Protocol buffer comparison. package proto import ( "bytes" "log" "reflect" "strings" ) /* Equal returns true iff protocol buffers a and b are equal. The arguments must both be pointers to protocol buffer structs. Equality is defined in this way: - Two messages are equal iff they are the same type, corresponding fields are equal, unknown field sets are equal, and extensions sets are equal. - Two set scalar fields are equal iff their values are equal. If the fields are of a floating-point type, remember that NaN != x for all x, including NaN. If the message is defined in a proto3 .proto file, fields are not "set"; specifically, zero length proto3 "bytes" fields are equal (nil == {}). - Two repeated fields are equal iff their lengths are the same, and their corresponding elements are equal (a "bytes" field, although represented by []byte, is not a repeated field) - Two unset fields are equal. - Two unknown field sets are equal if their current encoded state is equal. - Two extension sets are equal iff they have corresponding elements that are pairwise equal. - Every other combination of things are not equal. The return value is undefined if a and b are not protocol buffers. */ func Equal(a, b Message) bool { if a == nil || b == nil { return a == b } v1, v2 := reflect.ValueOf(a), reflect.ValueOf(b) if v1.Type() != v2.Type() { return false } if v1.Kind() == reflect.Ptr { if v1.IsNil() { return v2.IsNil() } if v2.IsNil() { return false } v1, v2 = v1.Elem(), v2.Elem() } if v1.Kind() != reflect.Struct { return false } return equalStruct(v1, v2) } // v1 and v2 are known to have the same type. func equalStruct(v1, v2 reflect.Value) bool { sprop := GetProperties(v1.Type()) for i := 0; i < v1.NumField(); i++ { f := v1.Type().Field(i) if strings.HasPrefix(f.Name, "XXX_") { continue } f1, f2 := v1.Field(i), v2.Field(i) if f.Type.Kind() == reflect.Ptr { if n1, n2 := f1.IsNil(), f2.IsNil(); n1 && n2 { // both unset continue } else if n1 != n2 { // set/unset mismatch return false } b1, ok := f1.Interface().(raw) if ok { b2 := f2.Interface().(raw) // RawMessage if !bytes.Equal(b1.Bytes(), b2.Bytes()) { return false } continue } f1, f2 = f1.Elem(), f2.Elem() } if !equalAny(f1, f2, sprop.Prop[i]) { return false } } if em1 := v1.FieldByName("XXX_extensions"); em1.IsValid() { em2 := v2.FieldByName("XXX_extensions") if !equalExtensions(v1.Type(), em1.Interface().(map[int32]Extension), em2.Interface().(map[int32]Extension)) { return false } } uf := v1.FieldByName("XXX_unrecognized") if !uf.IsValid() { return true } u1 := uf.Bytes() u2 := v2.FieldByName("XXX_unrecognized").Bytes() if !bytes.Equal(u1, u2) { return false } return true } // v1 and v2 are known to have the same type. // prop may be nil. func equalAny(v1, v2 reflect.Value, prop *Properties) bool { if v1.Type() == protoMessageType { m1, _ := v1.Interface().(Message) m2, _ := v2.Interface().(Message) return Equal(m1, m2) } switch v1.Kind() { case reflect.Bool: return v1.Bool() == v2.Bool() case reflect.Float32, reflect.Float64: return v1.Float() == v2.Float() case reflect.Int32, reflect.Int64: return v1.Int() == v2.Int() case reflect.Interface: // Probably a oneof field; compare the inner values. n1, n2 := v1.IsNil(), v2.IsNil() if n1 || n2 { return n1 == n2 } e1, e2 := v1.Elem(), v2.Elem() if e1.Type() != e2.Type() { return false } return equalAny(e1, e2, nil) case reflect.Map: if v1.Len() != v2.Len() { return false } for _, key := range v1.MapKeys() { val2 := v2.MapIndex(key) if !val2.IsValid() { // This key was not found in the second map. return false } if !equalAny(v1.MapIndex(key), val2, nil) { return false } } return true case reflect.Ptr: return equalAny(v1.Elem(), v2.Elem(), prop) case reflect.Slice: if v1.Type().Elem().Kind() == reflect.Uint8 { // short circuit: []byte // Edge case: if this is in a proto3 message, a zero length // bytes field is considered the zero value. if prop != nil && prop.proto3 && v1.Len() == 0 && v2.Len() == 0 { return true } if v1.IsNil() != v2.IsNil() { return false } return bytes.Equal(v1.Interface().([]byte), v2.Interface().([]byte)) } if v1.Len() != v2.Len() { return false } for i := 0; i < v1.Len(); i++ { if !equalAny(v1.Index(i), v2.Index(i), prop) { return false } } return true case reflect.String: return v1.Interface().(string) == v2.Interface().(string) case reflect.Struct: return equalStruct(v1, v2) case reflect.Uint32, reflect.Uint64: return v1.Uint() == v2.Uint() } // unknown type, so not a protocol buffer log.Printf("proto: don't know how to compare %v", v1) return false } // base is the struct type that the extensions are based on. // em1 and em2 are extension maps. func equalExtensions(base reflect.Type, em1, em2 map[int32]Extension) bool { if len(em1) != len(em2) { return false } for extNum, e1 := range em1 { e2, ok := em2[extNum] if !ok { return false } m1, m2 := e1.value, e2.value if m1 != nil && m2 != nil { // Both are unencoded. if !equalAny(reflect.ValueOf(m1), reflect.ValueOf(m2), nil) { return false } continue } // At least one is encoded. To do a semantically correct comparison // we need to unmarshal them first. var desc *ExtensionDesc if m := extensionMaps[base]; m != nil { desc = m[extNum] } if desc == nil { log.Printf("proto: don't know how to compare extension %d of %v", extNum, base) continue } var err error if m1 == nil { m1, err = decodeExtension(e1.enc, desc) } if m2 == nil && err == nil { m2, err = decodeExtension(e2.enc, desc) } if err != nil { // The encoded form is invalid. log.Printf("proto: badly encoded extension %d of %v: %v", extNum, base, err) return false } if !equalAny(reflect.ValueOf(m1), reflect.ValueOf(m2), nil) { return false } } return true } lxd-2.0.0/dist/src/github.com/golang/protobuf/proto/all_test.go0000644061062106075000000017703112702772352027127 0ustar00stgraberdomain admins00000000000000// Go support for Protocol Buffers - Google's data interchange format // // Copyright 2010 The Go Authors. All rights reserved. // https://github.com/golang/protobuf // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package proto_test import ( "bytes" "encoding/json" "errors" "fmt" "math" "math/rand" "reflect" "runtime/debug" "strings" "testing" "time" . "github.com/golang/protobuf/proto" . "github.com/golang/protobuf/proto/testdata" ) var globalO *Buffer func old() *Buffer { if globalO == nil { globalO = NewBuffer(nil) } globalO.Reset() return globalO } func equalbytes(b1, b2 []byte, t *testing.T) { if len(b1) != len(b2) { t.Errorf("wrong lengths: 2*%d != %d", len(b1), len(b2)) return } for i := 0; i < len(b1); i++ { if b1[i] != b2[i] { t.Errorf("bad byte[%d]:%x %x: %s %s", i, b1[i], b2[i], b1, b2) } } } func initGoTestField() *GoTestField { f := new(GoTestField) f.Label = String("label") f.Type = String("type") return f } // These are all structurally equivalent but the tag numbers differ. // (It's remarkable that required, optional, and repeated all have // 8 letters.) func initGoTest_RequiredGroup() *GoTest_RequiredGroup { return &GoTest_RequiredGroup{ RequiredField: String("required"), } } func initGoTest_OptionalGroup() *GoTest_OptionalGroup { return &GoTest_OptionalGroup{ RequiredField: String("optional"), } } func initGoTest_RepeatedGroup() *GoTest_RepeatedGroup { return &GoTest_RepeatedGroup{ RequiredField: String("repeated"), } } func initGoTest(setdefaults bool) *GoTest { pb := new(GoTest) if setdefaults { pb.F_BoolDefaulted = Bool(Default_GoTest_F_BoolDefaulted) pb.F_Int32Defaulted = Int32(Default_GoTest_F_Int32Defaulted) pb.F_Int64Defaulted = Int64(Default_GoTest_F_Int64Defaulted) pb.F_Fixed32Defaulted = Uint32(Default_GoTest_F_Fixed32Defaulted) pb.F_Fixed64Defaulted = Uint64(Default_GoTest_F_Fixed64Defaulted) pb.F_Uint32Defaulted = Uint32(Default_GoTest_F_Uint32Defaulted) pb.F_Uint64Defaulted = Uint64(Default_GoTest_F_Uint64Defaulted) pb.F_FloatDefaulted = Float32(Default_GoTest_F_FloatDefaulted) pb.F_DoubleDefaulted = Float64(Default_GoTest_F_DoubleDefaulted) pb.F_StringDefaulted = String(Default_GoTest_F_StringDefaulted) pb.F_BytesDefaulted = Default_GoTest_F_BytesDefaulted pb.F_Sint32Defaulted = Int32(Default_GoTest_F_Sint32Defaulted) pb.F_Sint64Defaulted = Int64(Default_GoTest_F_Sint64Defaulted) } pb.Kind = GoTest_TIME.Enum() pb.RequiredField = initGoTestField() pb.F_BoolRequired = Bool(true) pb.F_Int32Required = Int32(3) pb.F_Int64Required = Int64(6) pb.F_Fixed32Required = Uint32(32) pb.F_Fixed64Required = Uint64(64) pb.F_Uint32Required = Uint32(3232) pb.F_Uint64Required = Uint64(6464) pb.F_FloatRequired = Float32(3232) pb.F_DoubleRequired = Float64(6464) pb.F_StringRequired = String("string") pb.F_BytesRequired = []byte("bytes") pb.F_Sint32Required = Int32(-32) pb.F_Sint64Required = Int64(-64) pb.Requiredgroup = initGoTest_RequiredGroup() return pb } func fail(msg string, b *bytes.Buffer, s string, t *testing.T) { data := b.Bytes() ld := len(data) ls := len(s) / 2 fmt.Printf("fail %s ld=%d ls=%d\n", msg, ld, ls) // find the interesting spot - n n := ls if ld < ls { n = ld } j := 0 for i := 0; i < n; i++ { bs := hex(s[j])*16 + hex(s[j+1]) j += 2 if data[i] == bs { continue } n = i break } l := n - 10 if l < 0 { l = 0 } h := n + 10 // find the interesting spot - n fmt.Printf("is[%d]:", l) for i := l; i < h; i++ { if i >= ld { fmt.Printf(" --") continue } fmt.Printf(" %.2x", data[i]) } fmt.Printf("\n") fmt.Printf("sb[%d]:", l) for i := l; i < h; i++ { if i >= ls { fmt.Printf(" --") continue } bs := hex(s[j])*16 + hex(s[j+1]) j += 2 fmt.Printf(" %.2x", bs) } fmt.Printf("\n") t.Fail() // t.Errorf("%s: \ngood: %s\nbad: %x", msg, s, b.Bytes()) // Print the output in a partially-decoded format; can // be helpful when updating the test. It produces the output // that is pasted, with minor edits, into the argument to verify(). // data := b.Bytes() // nesting := 0 // for b.Len() > 0 { // start := len(data) - b.Len() // var u uint64 // u, err := DecodeVarint(b) // if err != nil { // fmt.Printf("decode error on varint:", err) // return // } // wire := u & 0x7 // tag := u >> 3 // switch wire { // case WireVarint: // v, err := DecodeVarint(b) // if err != nil { // fmt.Printf("decode error on varint:", err) // return // } // fmt.Printf("\t\t\"%x\" // field %d, encoding %d, value %d\n", // data[start:len(data)-b.Len()], tag, wire, v) // case WireFixed32: // v, err := DecodeFixed32(b) // if err != nil { // fmt.Printf("decode error on fixed32:", err) // return // } // fmt.Printf("\t\t\"%x\" // field %d, encoding %d, value %d\n", // data[start:len(data)-b.Len()], tag, wire, v) // case WireFixed64: // v, err := DecodeFixed64(b) // if err != nil { // fmt.Printf("decode error on fixed64:", err) // return // } // fmt.Printf("\t\t\"%x\" // field %d, encoding %d, value %d\n", // data[start:len(data)-b.Len()], tag, wire, v) // case WireBytes: // nb, err := DecodeVarint(b) // if err != nil { // fmt.Printf("decode error on bytes:", err) // return // } // after_tag := len(data) - b.Len() // str := make([]byte, nb) // _, err = b.Read(str) // if err != nil { // fmt.Printf("decode error on bytes:", err) // return // } // fmt.Printf("\t\t\"%x\" \"%x\" // field %d, encoding %d (FIELD)\n", // data[start:after_tag], str, tag, wire) // case WireStartGroup: // nesting++ // fmt.Printf("\t\t\"%x\"\t\t// start group field %d level %d\n", // data[start:len(data)-b.Len()], tag, nesting) // case WireEndGroup: // fmt.Printf("\t\t\"%x\"\t\t// end group field %d level %d\n", // data[start:len(data)-b.Len()], tag, nesting) // nesting-- // default: // fmt.Printf("unrecognized wire type %d\n", wire) // return // } // } } func hex(c uint8) uint8 { if '0' <= c && c <= '9' { return c - '0' } if 'a' <= c && c <= 'f' { return 10 + c - 'a' } if 'A' <= c && c <= 'F' { return 10 + c - 'A' } return 0 } func equal(b []byte, s string, t *testing.T) bool { if 2*len(b) != len(s) { // fail(fmt.Sprintf("wrong lengths: 2*%d != %d", len(b), len(s)), b, s, t) fmt.Printf("wrong lengths: 2*%d != %d\n", len(b), len(s)) return false } for i, j := 0, 0; i < len(b); i, j = i+1, j+2 { x := hex(s[j])*16 + hex(s[j+1]) if b[i] != x { // fail(fmt.Sprintf("bad byte[%d]:%x %x", i, b[i], x), b, s, t) fmt.Printf("bad byte[%d]:%x %x", i, b[i], x) return false } } return true } func overify(t *testing.T, pb *GoTest, expected string) { o := old() err := o.Marshal(pb) if err != nil { fmt.Printf("overify marshal-1 err = %v", err) o.DebugPrint("", o.Bytes()) t.Fatalf("expected = %s", expected) } if !equal(o.Bytes(), expected, t) { o.DebugPrint("overify neq 1", o.Bytes()) t.Fatalf("expected = %s", expected) } // Now test Unmarshal by recreating the original buffer. pbd := new(GoTest) err = o.Unmarshal(pbd) if err != nil { t.Fatalf("overify unmarshal err = %v", err) o.DebugPrint("", o.Bytes()) t.Fatalf("string = %s", expected) } o.Reset() err = o.Marshal(pbd) if err != nil { t.Errorf("overify marshal-2 err = %v", err) o.DebugPrint("", o.Bytes()) t.Fatalf("string = %s", expected) } if !equal(o.Bytes(), expected, t) { o.DebugPrint("overify neq 2", o.Bytes()) t.Fatalf("string = %s", expected) } } // Simple tests for numeric encode/decode primitives (varint, etc.) func TestNumericPrimitives(t *testing.T) { for i := uint64(0); i < 1e6; i += 111 { o := old() if o.EncodeVarint(i) != nil { t.Error("EncodeVarint") break } x, e := o.DecodeVarint() if e != nil { t.Fatal("DecodeVarint") } if x != i { t.Fatal("varint decode fail:", i, x) } o = old() if o.EncodeFixed32(i) != nil { t.Fatal("encFixed32") } x, e = o.DecodeFixed32() if e != nil { t.Fatal("decFixed32") } if x != i { t.Fatal("fixed32 decode fail:", i, x) } o = old() if o.EncodeFixed64(i*1234567) != nil { t.Error("encFixed64") break } x, e = o.DecodeFixed64() if e != nil { t.Error("decFixed64") break } if x != i*1234567 { t.Error("fixed64 decode fail:", i*1234567, x) break } o = old() i32 := int32(i - 12345) if o.EncodeZigzag32(uint64(i32)) != nil { t.Fatal("EncodeZigzag32") } x, e = o.DecodeZigzag32() if e != nil { t.Fatal("DecodeZigzag32") } if x != uint64(uint32(i32)) { t.Fatal("zigzag32 decode fail:", i32, x) } o = old() i64 := int64(i - 12345) if o.EncodeZigzag64(uint64(i64)) != nil { t.Fatal("EncodeZigzag64") } x, e = o.DecodeZigzag64() if e != nil { t.Fatal("DecodeZigzag64") } if x != uint64(i64) { t.Fatal("zigzag64 decode fail:", i64, x) } } } // fakeMarshaler is a simple struct implementing Marshaler and Message interfaces. type fakeMarshaler struct { b []byte err error } func (f *fakeMarshaler) Marshal() ([]byte, error) { return f.b, f.err } func (f *fakeMarshaler) String() string { return fmt.Sprintf("Bytes: %v Error: %v", f.b, f.err) } func (f *fakeMarshaler) ProtoMessage() {} func (f *fakeMarshaler) Reset() {} type msgWithFakeMarshaler struct { M *fakeMarshaler `protobuf:"bytes,1,opt,name=fake"` } func (m *msgWithFakeMarshaler) String() string { return CompactTextString(m) } func (m *msgWithFakeMarshaler) ProtoMessage() {} func (m *msgWithFakeMarshaler) Reset() {} // Simple tests for proto messages that implement the Marshaler interface. func TestMarshalerEncoding(t *testing.T) { tests := []struct { name string m Message want []byte wantErr error }{ { name: "Marshaler that fails", m: &fakeMarshaler{ err: errors.New("some marshal err"), b: []byte{5, 6, 7}, }, // Since there's an error, nothing should be written to buffer. want: nil, wantErr: errors.New("some marshal err"), }, { name: "Marshaler that fails with RequiredNotSetError", m: &msgWithFakeMarshaler{ M: &fakeMarshaler{ err: &RequiredNotSetError{}, b: []byte{5, 6, 7}, }, }, // Since there's an error that can be continued after, // the buffer should be written. want: []byte{ 10, 3, // for &msgWithFakeMarshaler 5, 6, 7, // for &fakeMarshaler }, wantErr: &RequiredNotSetError{}, }, { name: "Marshaler that succeeds", m: &fakeMarshaler{ b: []byte{0, 1, 2, 3, 4, 127, 255}, }, want: []byte{0, 1, 2, 3, 4, 127, 255}, wantErr: nil, }, } for _, test := range tests { b := NewBuffer(nil) err := b.Marshal(test.m) if _, ok := err.(*RequiredNotSetError); ok { // We're not in package proto, so we can only assert the type in this case. err = &RequiredNotSetError{} } if !reflect.DeepEqual(test.wantErr, err) { t.Errorf("%s: got err %v wanted %v", test.name, err, test.wantErr) } if !reflect.DeepEqual(test.want, b.Bytes()) { t.Errorf("%s: got bytes %v wanted %v", test.name, b.Bytes(), test.want) } } } // Simple tests for bytes func TestBytesPrimitives(t *testing.T) { o := old() bytes := []byte{'n', 'o', 'w', ' ', 'i', 's', ' ', 't', 'h', 'e', ' ', 't', 'i', 'm', 'e'} if o.EncodeRawBytes(bytes) != nil { t.Error("EncodeRawBytes") } decb, e := o.DecodeRawBytes(false) if e != nil { t.Error("DecodeRawBytes") } equalbytes(bytes, decb, t) } // Simple tests for strings func TestStringPrimitives(t *testing.T) { o := old() s := "now is the time" if o.EncodeStringBytes(s) != nil { t.Error("enc_string") } decs, e := o.DecodeStringBytes() if e != nil { t.Error("dec_string") } if s != decs { t.Error("string encode/decode fail:", s, decs) } } // Do we catch the "required bit not set" case? func TestRequiredBit(t *testing.T) { o := old() pb := new(GoTest) err := o.Marshal(pb) if err == nil { t.Error("did not catch missing required fields") } else if strings.Index(err.Error(), "Kind") < 0 { t.Error("wrong error type:", err) } } // Check that all fields are nil. // Clearly silly, and a residue from a more interesting test with an earlier, // different initialization property, but it once caught a compiler bug so // it lives. func checkInitialized(pb *GoTest, t *testing.T) { if pb.F_BoolDefaulted != nil { t.Error("New or Reset did not set boolean:", *pb.F_BoolDefaulted) } if pb.F_Int32Defaulted != nil { t.Error("New or Reset did not set int32:", *pb.F_Int32Defaulted) } if pb.F_Int64Defaulted != nil { t.Error("New or Reset did not set int64:", *pb.F_Int64Defaulted) } if pb.F_Fixed32Defaulted != nil { t.Error("New or Reset did not set fixed32:", *pb.F_Fixed32Defaulted) } if pb.F_Fixed64Defaulted != nil { t.Error("New or Reset did not set fixed64:", *pb.F_Fixed64Defaulted) } if pb.F_Uint32Defaulted != nil { t.Error("New or Reset did not set uint32:", *pb.F_Uint32Defaulted) } if pb.F_Uint64Defaulted != nil { t.Error("New or Reset did not set uint64:", *pb.F_Uint64Defaulted) } if pb.F_FloatDefaulted != nil { t.Error("New or Reset did not set float:", *pb.F_FloatDefaulted) } if pb.F_DoubleDefaulted != nil { t.Error("New or Reset did not set double:", *pb.F_DoubleDefaulted) } if pb.F_StringDefaulted != nil { t.Error("New or Reset did not set string:", *pb.F_StringDefaulted) } if pb.F_BytesDefaulted != nil { t.Error("New or Reset did not set bytes:", string(pb.F_BytesDefaulted)) } if pb.F_Sint32Defaulted != nil { t.Error("New or Reset did not set int32:", *pb.F_Sint32Defaulted) } if pb.F_Sint64Defaulted != nil { t.Error("New or Reset did not set int64:", *pb.F_Sint64Defaulted) } } // Does Reset() reset? func TestReset(t *testing.T) { pb := initGoTest(true) // muck with some values pb.F_BoolDefaulted = Bool(false) pb.F_Int32Defaulted = Int32(237) pb.F_Int64Defaulted = Int64(12346) pb.F_Fixed32Defaulted = Uint32(32000) pb.F_Fixed64Defaulted = Uint64(666) pb.F_Uint32Defaulted = Uint32(323232) pb.F_Uint64Defaulted = nil pb.F_FloatDefaulted = nil pb.F_DoubleDefaulted = Float64(0) pb.F_StringDefaulted = String("gotcha") pb.F_BytesDefaulted = []byte("asdfasdf") pb.F_Sint32Defaulted = Int32(123) pb.F_Sint64Defaulted = Int64(789) pb.Reset() checkInitialized(pb, t) } // All required fields set, no defaults provided. func TestEncodeDecode1(t *testing.T) { pb := initGoTest(false) overify(t, pb, "0807"+ // field 1, encoding 0, value 7 "220d"+"0a056c6162656c120474797065"+ // field 4, encoding 2 (GoTestField) "5001"+ // field 10, encoding 0, value 1 "5803"+ // field 11, encoding 0, value 3 "6006"+ // field 12, encoding 0, value 6 "6d20000000"+ // field 13, encoding 5, value 0x20 "714000000000000000"+ // field 14, encoding 1, value 0x40 "78a019"+ // field 15, encoding 0, value 0xca0 = 3232 "8001c032"+ // field 16, encoding 0, value 0x1940 = 6464 "8d0100004a45"+ // field 17, encoding 5, value 3232.0 "9101000000000040b940"+ // field 18, encoding 1, value 6464.0 "9a0106"+"737472696e67"+ // field 19, encoding 2, string "string" "b304"+ // field 70, encoding 3, start group "ba0408"+"7265717569726564"+ // field 71, encoding 2, string "required" "b404"+ // field 70, encoding 4, end group "aa0605"+"6279746573"+ // field 101, encoding 2, string "bytes" "b0063f"+ // field 102, encoding 0, 0x3f zigzag32 "b8067f") // field 103, encoding 0, 0x7f zigzag64 } // All required fields set, defaults provided. func TestEncodeDecode2(t *testing.T) { pb := initGoTest(true) overify(t, pb, "0807"+ // field 1, encoding 0, value 7 "220d"+"0a056c6162656c120474797065"+ // field 4, encoding 2 (GoTestField) "5001"+ // field 10, encoding 0, value 1 "5803"+ // field 11, encoding 0, value 3 "6006"+ // field 12, encoding 0, value 6 "6d20000000"+ // field 13, encoding 5, value 32 "714000000000000000"+ // field 14, encoding 1, value 64 "78a019"+ // field 15, encoding 0, value 3232 "8001c032"+ // field 16, encoding 0, value 6464 "8d0100004a45"+ // field 17, encoding 5, value 3232.0 "9101000000000040b940"+ // field 18, encoding 1, value 6464.0 "9a0106"+"737472696e67"+ // field 19, encoding 2 string "string" "c00201"+ // field 40, encoding 0, value 1 "c80220"+ // field 41, encoding 0, value 32 "d00240"+ // field 42, encoding 0, value 64 "dd0240010000"+ // field 43, encoding 5, value 320 "e1028002000000000000"+ // field 44, encoding 1, value 640 "e8028019"+ // field 45, encoding 0, value 3200 "f0028032"+ // field 46, encoding 0, value 6400 "fd02e0659948"+ // field 47, encoding 5, value 314159.0 "81030000000050971041"+ // field 48, encoding 1, value 271828.0 "8a0310"+"68656c6c6f2c2022776f726c6421220a"+ // field 49, encoding 2 string "hello, \"world!\"\n" "b304"+ // start group field 70 level 1 "ba0408"+"7265717569726564"+ // field 71, encoding 2, string "required" "b404"+ // end group field 70 level 1 "aa0605"+"6279746573"+ // field 101, encoding 2 string "bytes" "b0063f"+ // field 102, encoding 0, 0x3f zigzag32 "b8067f"+ // field 103, encoding 0, 0x7f zigzag64 "8a1907"+"4269676e6f7365"+ // field 401, encoding 2, string "Bignose" "90193f"+ // field 402, encoding 0, value 63 "98197f") // field 403, encoding 0, value 127 } // All default fields set to their default value by hand func TestEncodeDecode3(t *testing.T) { pb := initGoTest(false) pb.F_BoolDefaulted = Bool(true) pb.F_Int32Defaulted = Int32(32) pb.F_Int64Defaulted = Int64(64) pb.F_Fixed32Defaulted = Uint32(320) pb.F_Fixed64Defaulted = Uint64(640) pb.F_Uint32Defaulted = Uint32(3200) pb.F_Uint64Defaulted = Uint64(6400) pb.F_FloatDefaulted = Float32(314159) pb.F_DoubleDefaulted = Float64(271828) pb.F_StringDefaulted = String("hello, \"world!\"\n") pb.F_BytesDefaulted = []byte("Bignose") pb.F_Sint32Defaulted = Int32(-32) pb.F_Sint64Defaulted = Int64(-64) overify(t, pb, "0807"+ // field 1, encoding 0, value 7 "220d"+"0a056c6162656c120474797065"+ // field 4, encoding 2 (GoTestField) "5001"+ // field 10, encoding 0, value 1 "5803"+ // field 11, encoding 0, value 3 "6006"+ // field 12, encoding 0, value 6 "6d20000000"+ // field 13, encoding 5, value 32 "714000000000000000"+ // field 14, encoding 1, value 64 "78a019"+ // field 15, encoding 0, value 3232 "8001c032"+ // field 16, encoding 0, value 6464 "8d0100004a45"+ // field 17, encoding 5, value 3232.0 "9101000000000040b940"+ // field 18, encoding 1, value 6464.0 "9a0106"+"737472696e67"+ // field 19, encoding 2 string "string" "c00201"+ // field 40, encoding 0, value 1 "c80220"+ // field 41, encoding 0, value 32 "d00240"+ // field 42, encoding 0, value 64 "dd0240010000"+ // field 43, encoding 5, value 320 "e1028002000000000000"+ // field 44, encoding 1, value 640 "e8028019"+ // field 45, encoding 0, value 3200 "f0028032"+ // field 46, encoding 0, value 6400 "fd02e0659948"+ // field 47, encoding 5, value 314159.0 "81030000000050971041"+ // field 48, encoding 1, value 271828.0 "8a0310"+"68656c6c6f2c2022776f726c6421220a"+ // field 49, encoding 2 string "hello, \"world!\"\n" "b304"+ // start group field 70 level 1 "ba0408"+"7265717569726564"+ // field 71, encoding 2, string "required" "b404"+ // end group field 70 level 1 "aa0605"+"6279746573"+ // field 101, encoding 2 string "bytes" "b0063f"+ // field 102, encoding 0, 0x3f zigzag32 "b8067f"+ // field 103, encoding 0, 0x7f zigzag64 "8a1907"+"4269676e6f7365"+ // field 401, encoding 2, string "Bignose" "90193f"+ // field 402, encoding 0, value 63 "98197f") // field 403, encoding 0, value 127 } // All required fields set, defaults provided, all non-defaulted optional fields have values. func TestEncodeDecode4(t *testing.T) { pb := initGoTest(true) pb.Table = String("hello") pb.Param = Int32(7) pb.OptionalField = initGoTestField() pb.F_BoolOptional = Bool(true) pb.F_Int32Optional = Int32(32) pb.F_Int64Optional = Int64(64) pb.F_Fixed32Optional = Uint32(3232) pb.F_Fixed64Optional = Uint64(6464) pb.F_Uint32Optional = Uint32(323232) pb.F_Uint64Optional = Uint64(646464) pb.F_FloatOptional = Float32(32.) pb.F_DoubleOptional = Float64(64.) pb.F_StringOptional = String("hello") pb.F_BytesOptional = []byte("Bignose") pb.F_Sint32Optional = Int32(-32) pb.F_Sint64Optional = Int64(-64) pb.Optionalgroup = initGoTest_OptionalGroup() overify(t, pb, "0807"+ // field 1, encoding 0, value 7 "1205"+"68656c6c6f"+ // field 2, encoding 2, string "hello" "1807"+ // field 3, encoding 0, value 7 "220d"+"0a056c6162656c120474797065"+ // field 4, encoding 2 (GoTestField) "320d"+"0a056c6162656c120474797065"+ // field 6, encoding 2 (GoTestField) "5001"+ // field 10, encoding 0, value 1 "5803"+ // field 11, encoding 0, value 3 "6006"+ // field 12, encoding 0, value 6 "6d20000000"+ // field 13, encoding 5, value 32 "714000000000000000"+ // field 14, encoding 1, value 64 "78a019"+ // field 15, encoding 0, value 3232 "8001c032"+ // field 16, encoding 0, value 6464 "8d0100004a45"+ // field 17, encoding 5, value 3232.0 "9101000000000040b940"+ // field 18, encoding 1, value 6464.0 "9a0106"+"737472696e67"+ // field 19, encoding 2 string "string" "f00101"+ // field 30, encoding 0, value 1 "f80120"+ // field 31, encoding 0, value 32 "800240"+ // field 32, encoding 0, value 64 "8d02a00c0000"+ // field 33, encoding 5, value 3232 "91024019000000000000"+ // field 34, encoding 1, value 6464 "9802a0dd13"+ // field 35, encoding 0, value 323232 "a002c0ba27"+ // field 36, encoding 0, value 646464 "ad0200000042"+ // field 37, encoding 5, value 32.0 "b1020000000000005040"+ // field 38, encoding 1, value 64.0 "ba0205"+"68656c6c6f"+ // field 39, encoding 2, string "hello" "c00201"+ // field 40, encoding 0, value 1 "c80220"+ // field 41, encoding 0, value 32 "d00240"+ // field 42, encoding 0, value 64 "dd0240010000"+ // field 43, encoding 5, value 320 "e1028002000000000000"+ // field 44, encoding 1, value 640 "e8028019"+ // field 45, encoding 0, value 3200 "f0028032"+ // field 46, encoding 0, value 6400 "fd02e0659948"+ // field 47, encoding 5, value 314159.0 "81030000000050971041"+ // field 48, encoding 1, value 271828.0 "8a0310"+"68656c6c6f2c2022776f726c6421220a"+ // field 49, encoding 2 string "hello, \"world!\"\n" "b304"+ // start group field 70 level 1 "ba0408"+"7265717569726564"+ // field 71, encoding 2, string "required" "b404"+ // end group field 70 level 1 "d305"+ // start group field 90 level 1 "da0508"+"6f7074696f6e616c"+ // field 91, encoding 2, string "optional" "d405"+ // end group field 90 level 1 "aa0605"+"6279746573"+ // field 101, encoding 2 string "bytes" "b0063f"+ // field 102, encoding 0, 0x3f zigzag32 "b8067f"+ // field 103, encoding 0, 0x7f zigzag64 "ea1207"+"4269676e6f7365"+ // field 301, encoding 2, string "Bignose" "f0123f"+ // field 302, encoding 0, value 63 "f8127f"+ // field 303, encoding 0, value 127 "8a1907"+"4269676e6f7365"+ // field 401, encoding 2, string "Bignose" "90193f"+ // field 402, encoding 0, value 63 "98197f") // field 403, encoding 0, value 127 } // All required fields set, defaults provided, all repeated fields given two values. func TestEncodeDecode5(t *testing.T) { pb := initGoTest(true) pb.RepeatedField = []*GoTestField{initGoTestField(), initGoTestField()} pb.F_BoolRepeated = []bool{false, true} pb.F_Int32Repeated = []int32{32, 33} pb.F_Int64Repeated = []int64{64, 65} pb.F_Fixed32Repeated = []uint32{3232, 3333} pb.F_Fixed64Repeated = []uint64{6464, 6565} pb.F_Uint32Repeated = []uint32{323232, 333333} pb.F_Uint64Repeated = []uint64{646464, 656565} pb.F_FloatRepeated = []float32{32., 33.} pb.F_DoubleRepeated = []float64{64., 65.} pb.F_StringRepeated = []string{"hello", "sailor"} pb.F_BytesRepeated = [][]byte{[]byte("big"), []byte("nose")} pb.F_Sint32Repeated = []int32{32, -32} pb.F_Sint64Repeated = []int64{64, -64} pb.Repeatedgroup = []*GoTest_RepeatedGroup{initGoTest_RepeatedGroup(), initGoTest_RepeatedGroup()} overify(t, pb, "0807"+ // field 1, encoding 0, value 7 "220d"+"0a056c6162656c120474797065"+ // field 4, encoding 2 (GoTestField) "2a0d"+"0a056c6162656c120474797065"+ // field 5, encoding 2 (GoTestField) "2a0d"+"0a056c6162656c120474797065"+ // field 5, encoding 2 (GoTestField) "5001"+ // field 10, encoding 0, value 1 "5803"+ // field 11, encoding 0, value 3 "6006"+ // field 12, encoding 0, value 6 "6d20000000"+ // field 13, encoding 5, value 32 "714000000000000000"+ // field 14, encoding 1, value 64 "78a019"+ // field 15, encoding 0, value 3232 "8001c032"+ // field 16, encoding 0, value 6464 "8d0100004a45"+ // field 17, encoding 5, value 3232.0 "9101000000000040b940"+ // field 18, encoding 1, value 6464.0 "9a0106"+"737472696e67"+ // field 19, encoding 2 string "string" "a00100"+ // field 20, encoding 0, value 0 "a00101"+ // field 20, encoding 0, value 1 "a80120"+ // field 21, encoding 0, value 32 "a80121"+ // field 21, encoding 0, value 33 "b00140"+ // field 22, encoding 0, value 64 "b00141"+ // field 22, encoding 0, value 65 "bd01a00c0000"+ // field 23, encoding 5, value 3232 "bd01050d0000"+ // field 23, encoding 5, value 3333 "c1014019000000000000"+ // field 24, encoding 1, value 6464 "c101a519000000000000"+ // field 24, encoding 1, value 6565 "c801a0dd13"+ // field 25, encoding 0, value 323232 "c80195ac14"+ // field 25, encoding 0, value 333333 "d001c0ba27"+ // field 26, encoding 0, value 646464 "d001b58928"+ // field 26, encoding 0, value 656565 "dd0100000042"+ // field 27, encoding 5, value 32.0 "dd0100000442"+ // field 27, encoding 5, value 33.0 "e1010000000000005040"+ // field 28, encoding 1, value 64.0 "e1010000000000405040"+ // field 28, encoding 1, value 65.0 "ea0105"+"68656c6c6f"+ // field 29, encoding 2, string "hello" "ea0106"+"7361696c6f72"+ // field 29, encoding 2, string "sailor" "c00201"+ // field 40, encoding 0, value 1 "c80220"+ // field 41, encoding 0, value 32 "d00240"+ // field 42, encoding 0, value 64 "dd0240010000"+ // field 43, encoding 5, value 320 "e1028002000000000000"+ // field 44, encoding 1, value 640 "e8028019"+ // field 45, encoding 0, value 3200 "f0028032"+ // field 46, encoding 0, value 6400 "fd02e0659948"+ // field 47, encoding 5, value 314159.0 "81030000000050971041"+ // field 48, encoding 1, value 271828.0 "8a0310"+"68656c6c6f2c2022776f726c6421220a"+ // field 49, encoding 2 string "hello, \"world!\"\n" "b304"+ // start group field 70 level 1 "ba0408"+"7265717569726564"+ // field 71, encoding 2, string "required" "b404"+ // end group field 70 level 1 "8305"+ // start group field 80 level 1 "8a0508"+"7265706561746564"+ // field 81, encoding 2, string "repeated" "8405"+ // end group field 80 level 1 "8305"+ // start group field 80 level 1 "8a0508"+"7265706561746564"+ // field 81, encoding 2, string "repeated" "8405"+ // end group field 80 level 1 "aa0605"+"6279746573"+ // field 101, encoding 2 string "bytes" "b0063f"+ // field 102, encoding 0, 0x3f zigzag32 "b8067f"+ // field 103, encoding 0, 0x7f zigzag64 "ca0c03"+"626967"+ // field 201, encoding 2, string "big" "ca0c04"+"6e6f7365"+ // field 201, encoding 2, string "nose" "d00c40"+ // field 202, encoding 0, value 32 "d00c3f"+ // field 202, encoding 0, value -32 "d80c8001"+ // field 203, encoding 0, value 64 "d80c7f"+ // field 203, encoding 0, value -64 "8a1907"+"4269676e6f7365"+ // field 401, encoding 2, string "Bignose" "90193f"+ // field 402, encoding 0, value 63 "98197f") // field 403, encoding 0, value 127 } // All required fields set, all packed repeated fields given two values. func TestEncodeDecode6(t *testing.T) { pb := initGoTest(false) pb.F_BoolRepeatedPacked = []bool{false, true} pb.F_Int32RepeatedPacked = []int32{32, 33} pb.F_Int64RepeatedPacked = []int64{64, 65} pb.F_Fixed32RepeatedPacked = []uint32{3232, 3333} pb.F_Fixed64RepeatedPacked = []uint64{6464, 6565} pb.F_Uint32RepeatedPacked = []uint32{323232, 333333} pb.F_Uint64RepeatedPacked = []uint64{646464, 656565} pb.F_FloatRepeatedPacked = []float32{32., 33.} pb.F_DoubleRepeatedPacked = []float64{64., 65.} pb.F_Sint32RepeatedPacked = []int32{32, -32} pb.F_Sint64RepeatedPacked = []int64{64, -64} overify(t, pb, "0807"+ // field 1, encoding 0, value 7 "220d"+"0a056c6162656c120474797065"+ // field 4, encoding 2 (GoTestField) "5001"+ // field 10, encoding 0, value 1 "5803"+ // field 11, encoding 0, value 3 "6006"+ // field 12, encoding 0, value 6 "6d20000000"+ // field 13, encoding 5, value 32 "714000000000000000"+ // field 14, encoding 1, value 64 "78a019"+ // field 15, encoding 0, value 3232 "8001c032"+ // field 16, encoding 0, value 6464 "8d0100004a45"+ // field 17, encoding 5, value 3232.0 "9101000000000040b940"+ // field 18, encoding 1, value 6464.0 "9a0106"+"737472696e67"+ // field 19, encoding 2 string "string" "9203020001"+ // field 50, encoding 2, 2 bytes, value 0, value 1 "9a03022021"+ // field 51, encoding 2, 2 bytes, value 32, value 33 "a203024041"+ // field 52, encoding 2, 2 bytes, value 64, value 65 "aa0308"+ // field 53, encoding 2, 8 bytes "a00c0000050d0000"+ // value 3232, value 3333 "b20310"+ // field 54, encoding 2, 16 bytes "4019000000000000a519000000000000"+ // value 6464, value 6565 "ba0306"+ // field 55, encoding 2, 6 bytes "a0dd1395ac14"+ // value 323232, value 333333 "c20306"+ // field 56, encoding 2, 6 bytes "c0ba27b58928"+ // value 646464, value 656565 "ca0308"+ // field 57, encoding 2, 8 bytes "0000004200000442"+ // value 32.0, value 33.0 "d20310"+ // field 58, encoding 2, 16 bytes "00000000000050400000000000405040"+ // value 64.0, value 65.0 "b304"+ // start group field 70 level 1 "ba0408"+"7265717569726564"+ // field 71, encoding 2, string "required" "b404"+ // end group field 70 level 1 "aa0605"+"6279746573"+ // field 101, encoding 2 string "bytes" "b0063f"+ // field 102, encoding 0, 0x3f zigzag32 "b8067f"+ // field 103, encoding 0, 0x7f zigzag64 "b21f02"+ // field 502, encoding 2, 2 bytes "403f"+ // value 32, value -32 "ba1f03"+ // field 503, encoding 2, 3 bytes "80017f") // value 64, value -64 } // Test that we can encode empty bytes fields. func TestEncodeDecodeBytes1(t *testing.T) { pb := initGoTest(false) // Create our bytes pb.F_BytesRequired = []byte{} pb.F_BytesRepeated = [][]byte{{}} pb.F_BytesOptional = []byte{} d, err := Marshal(pb) if err != nil { t.Error(err) } pbd := new(GoTest) if err := Unmarshal(d, pbd); err != nil { t.Error(err) } if pbd.F_BytesRequired == nil || len(pbd.F_BytesRequired) != 0 { t.Error("required empty bytes field is incorrect") } if pbd.F_BytesRepeated == nil || len(pbd.F_BytesRepeated) == 1 && pbd.F_BytesRepeated[0] == nil { t.Error("repeated empty bytes field is incorrect") } if pbd.F_BytesOptional == nil || len(pbd.F_BytesOptional) != 0 { t.Error("optional empty bytes field is incorrect") } } // Test that we encode nil-valued fields of a repeated bytes field correctly. // Since entries in a repeated field cannot be nil, nil must mean empty value. func TestEncodeDecodeBytes2(t *testing.T) { pb := initGoTest(false) // Create our bytes pb.F_BytesRepeated = [][]byte{nil} d, err := Marshal(pb) if err != nil { t.Error(err) } pbd := new(GoTest) if err := Unmarshal(d, pbd); err != nil { t.Error(err) } if len(pbd.F_BytesRepeated) != 1 || pbd.F_BytesRepeated[0] == nil { t.Error("Unexpected value for repeated bytes field") } } // All required fields set, defaults provided, all repeated fields given two values. func TestSkippingUnrecognizedFields(t *testing.T) { o := old() pb := initGoTestField() // Marshal it normally. o.Marshal(pb) // Now new a GoSkipTest record. skip := &GoSkipTest{ SkipInt32: Int32(32), SkipFixed32: Uint32(3232), SkipFixed64: Uint64(6464), SkipString: String("skipper"), Skipgroup: &GoSkipTest_SkipGroup{ GroupInt32: Int32(75), GroupString: String("wxyz"), }, } // Marshal it into same buffer. o.Marshal(skip) pbd := new(GoTestField) o.Unmarshal(pbd) // The __unrecognized field should be a marshaling of GoSkipTest skipd := new(GoSkipTest) o.SetBuf(pbd.XXX_unrecognized) o.Unmarshal(skipd) if *skipd.SkipInt32 != *skip.SkipInt32 { t.Error("skip int32", skipd.SkipInt32) } if *skipd.SkipFixed32 != *skip.SkipFixed32 { t.Error("skip fixed32", skipd.SkipFixed32) } if *skipd.SkipFixed64 != *skip.SkipFixed64 { t.Error("skip fixed64", skipd.SkipFixed64) } if *skipd.SkipString != *skip.SkipString { t.Error("skip string", *skipd.SkipString) } if *skipd.Skipgroup.GroupInt32 != *skip.Skipgroup.GroupInt32 { t.Error("skip group int32", skipd.Skipgroup.GroupInt32) } if *skipd.Skipgroup.GroupString != *skip.Skipgroup.GroupString { t.Error("skip group string", *skipd.Skipgroup.GroupString) } } // Check that unrecognized fields of a submessage are preserved. func TestSubmessageUnrecognizedFields(t *testing.T) { nm := &NewMessage{ Nested: &NewMessage_Nested{ Name: String("Nigel"), FoodGroup: String("carbs"), }, } b, err := Marshal(nm) if err != nil { t.Fatalf("Marshal of NewMessage: %v", err) } // Unmarshal into an OldMessage. om := new(OldMessage) if err := Unmarshal(b, om); err != nil { t.Fatalf("Unmarshal to OldMessage: %v", err) } exp := &OldMessage{ Nested: &OldMessage_Nested{ Name: String("Nigel"), // normal protocol buffer users should not do this XXX_unrecognized: []byte("\x12\x05carbs"), }, } if !Equal(om, exp) { t.Errorf("om = %v, want %v", om, exp) } // Clone the OldMessage. om = Clone(om).(*OldMessage) if !Equal(om, exp) { t.Errorf("Clone(om) = %v, want %v", om, exp) } // Marshal the OldMessage, then unmarshal it into an empty NewMessage. if b, err = Marshal(om); err != nil { t.Fatalf("Marshal of OldMessage: %v", err) } t.Logf("Marshal(%v) -> %q", om, b) nm2 := new(NewMessage) if err := Unmarshal(b, nm2); err != nil { t.Fatalf("Unmarshal to NewMessage: %v", err) } if !Equal(nm, nm2) { t.Errorf("NewMessage round-trip: %v => %v", nm, nm2) } } // Check that an int32 field can be upgraded to an int64 field. func TestNegativeInt32(t *testing.T) { om := &OldMessage{ Num: Int32(-1), } b, err := Marshal(om) if err != nil { t.Fatalf("Marshal of OldMessage: %v", err) } // Check the size. It should be 11 bytes; // 1 for the field/wire type, and 10 for the negative number. if len(b) != 11 { t.Errorf("%v marshaled as %q, wanted 11 bytes", om, b) } // Unmarshal into a NewMessage. nm := new(NewMessage) if err := Unmarshal(b, nm); err != nil { t.Fatalf("Unmarshal to NewMessage: %v", err) } want := &NewMessage{ Num: Int64(-1), } if !Equal(nm, want) { t.Errorf("nm = %v, want %v", nm, want) } } // Check that we can grow an array (repeated field) to have many elements. // This test doesn't depend only on our encoding; for variety, it makes sure // we create, encode, and decode the correct contents explicitly. It's therefore // a bit messier. // This test also uses (and hence tests) the Marshal/Unmarshal functions // instead of the methods. func TestBigRepeated(t *testing.T) { pb := initGoTest(true) // Create the arrays const N = 50 // Internally the library starts much smaller. pb.Repeatedgroup = make([]*GoTest_RepeatedGroup, N) pb.F_Sint64Repeated = make([]int64, N) pb.F_Sint32Repeated = make([]int32, N) pb.F_BytesRepeated = make([][]byte, N) pb.F_StringRepeated = make([]string, N) pb.F_DoubleRepeated = make([]float64, N) pb.F_FloatRepeated = make([]float32, N) pb.F_Uint64Repeated = make([]uint64, N) pb.F_Uint32Repeated = make([]uint32, N) pb.F_Fixed64Repeated = make([]uint64, N) pb.F_Fixed32Repeated = make([]uint32, N) pb.F_Int64Repeated = make([]int64, N) pb.F_Int32Repeated = make([]int32, N) pb.F_BoolRepeated = make([]bool, N) pb.RepeatedField = make([]*GoTestField, N) // Fill in the arrays with checkable values. igtf := initGoTestField() igtrg := initGoTest_RepeatedGroup() for i := 0; i < N; i++ { pb.Repeatedgroup[i] = igtrg pb.F_Sint64Repeated[i] = int64(i) pb.F_Sint32Repeated[i] = int32(i) s := fmt.Sprint(i) pb.F_BytesRepeated[i] = []byte(s) pb.F_StringRepeated[i] = s pb.F_DoubleRepeated[i] = float64(i) pb.F_FloatRepeated[i] = float32(i) pb.F_Uint64Repeated[i] = uint64(i) pb.F_Uint32Repeated[i] = uint32(i) pb.F_Fixed64Repeated[i] = uint64(i) pb.F_Fixed32Repeated[i] = uint32(i) pb.F_Int64Repeated[i] = int64(i) pb.F_Int32Repeated[i] = int32(i) pb.F_BoolRepeated[i] = i%2 == 0 pb.RepeatedField[i] = igtf } // Marshal. buf, _ := Marshal(pb) // Now test Unmarshal by recreating the original buffer. pbd := new(GoTest) Unmarshal(buf, pbd) // Check the checkable values for i := uint64(0); i < N; i++ { if pbd.Repeatedgroup[i] == nil { // TODO: more checking? t.Error("pbd.Repeatedgroup bad") } var x uint64 x = uint64(pbd.F_Sint64Repeated[i]) if x != i { t.Error("pbd.F_Sint64Repeated bad", x, i) } x = uint64(pbd.F_Sint32Repeated[i]) if x != i { t.Error("pbd.F_Sint32Repeated bad", x, i) } s := fmt.Sprint(i) equalbytes(pbd.F_BytesRepeated[i], []byte(s), t) if pbd.F_StringRepeated[i] != s { t.Error("pbd.F_Sint32Repeated bad", pbd.F_StringRepeated[i], i) } x = uint64(pbd.F_DoubleRepeated[i]) if x != i { t.Error("pbd.F_DoubleRepeated bad", x, i) } x = uint64(pbd.F_FloatRepeated[i]) if x != i { t.Error("pbd.F_FloatRepeated bad", x, i) } x = pbd.F_Uint64Repeated[i] if x != i { t.Error("pbd.F_Uint64Repeated bad", x, i) } x = uint64(pbd.F_Uint32Repeated[i]) if x != i { t.Error("pbd.F_Uint32Repeated bad", x, i) } x = pbd.F_Fixed64Repeated[i] if x != i { t.Error("pbd.F_Fixed64Repeated bad", x, i) } x = uint64(pbd.F_Fixed32Repeated[i]) if x != i { t.Error("pbd.F_Fixed32Repeated bad", x, i) } x = uint64(pbd.F_Int64Repeated[i]) if x != i { t.Error("pbd.F_Int64Repeated bad", x, i) } x = uint64(pbd.F_Int32Repeated[i]) if x != i { t.Error("pbd.F_Int32Repeated bad", x, i) } if pbd.F_BoolRepeated[i] != (i%2 == 0) { t.Error("pbd.F_BoolRepeated bad", x, i) } if pbd.RepeatedField[i] == nil { // TODO: more checking? t.Error("pbd.RepeatedField bad") } } } // Verify we give a useful message when decoding to the wrong structure type. func TestTypeMismatch(t *testing.T) { pb1 := initGoTest(true) // Marshal o := old() o.Marshal(pb1) // Now Unmarshal it to the wrong type. pb2 := initGoTestField() err := o.Unmarshal(pb2) if err == nil { t.Error("expected error, got no error") } else if !strings.Contains(err.Error(), "bad wiretype") { t.Error("expected bad wiretype error, got", err) } } func encodeDecode(t *testing.T, in, out Message, msg string) { buf, err := Marshal(in) if err != nil { t.Fatalf("failed marshaling %v: %v", msg, err) } if err := Unmarshal(buf, out); err != nil { t.Fatalf("failed unmarshaling %v: %v", msg, err) } } func TestPackedNonPackedDecoderSwitching(t *testing.T) { np, p := new(NonPackedTest), new(PackedTest) // non-packed -> packed np.A = []int32{0, 1, 1, 2, 3, 5} encodeDecode(t, np, p, "non-packed -> packed") if !reflect.DeepEqual(np.A, p.B) { t.Errorf("failed non-packed -> packed; np.A=%+v, p.B=%+v", np.A, p.B) } // packed -> non-packed np.Reset() p.B = []int32{3, 1, 4, 1, 5, 9} encodeDecode(t, p, np, "packed -> non-packed") if !reflect.DeepEqual(p.B, np.A) { t.Errorf("failed packed -> non-packed; p.B=%+v, np.A=%+v", p.B, np.A) } } func TestProto1RepeatedGroup(t *testing.T) { pb := &MessageList{ Message: []*MessageList_Message{ { Name: String("blah"), Count: Int32(7), }, // NOTE: pb.Message[1] is a nil nil, }, } o := old() err := o.Marshal(pb) if err == nil || !strings.Contains(err.Error(), "repeated field Message has nil") { t.Fatalf("unexpected or no error when marshaling: %v", err) } } // Test that enums work. Checks for a bug introduced by making enums // named types instead of int32: newInt32FromUint64 would crash with // a type mismatch in reflect.PointTo. func TestEnum(t *testing.T) { pb := new(GoEnum) pb.Foo = FOO_FOO1.Enum() o := old() if err := o.Marshal(pb); err != nil { t.Fatal("error encoding enum:", err) } pb1 := new(GoEnum) if err := o.Unmarshal(pb1); err != nil { t.Fatal("error decoding enum:", err) } if *pb1.Foo != FOO_FOO1 { t.Error("expected 7 but got ", *pb1.Foo) } } // Enum types have String methods. Check that enum fields can be printed. // We don't care what the value actually is, just as long as it doesn't crash. func TestPrintingNilEnumFields(t *testing.T) { pb := new(GoEnum) fmt.Sprintf("%+v", pb) } // Verify that absent required fields cause Marshal/Unmarshal to return errors. func TestRequiredFieldEnforcement(t *testing.T) { pb := new(GoTestField) _, err := Marshal(pb) if err == nil { t.Error("marshal: expected error, got nil") } else if strings.Index(err.Error(), "Label") < 0 { t.Errorf("marshal: bad error type: %v", err) } // A slightly sneaky, yet valid, proto. It encodes the same required field twice, // so simply counting the required fields is insufficient. // field 1, encoding 2, value "hi" buf := []byte("\x0A\x02hi\x0A\x02hi") err = Unmarshal(buf, pb) if err == nil { t.Error("unmarshal: expected error, got nil") } else if strings.Index(err.Error(), "{Unknown}") < 0 { t.Errorf("unmarshal: bad error type: %v", err) } } func TestTypedNilMarshal(t *testing.T) { // A typed nil should return ErrNil and not crash. { var m *GoEnum if _, err := Marshal(m); err != ErrNil { t.Errorf("Marshal(%#v): got %v, want ErrNil", m, err) } } { m := &Communique{Union: &Communique_Msg{nil}} if _, err := Marshal(m); err == nil || err == ErrNil { t.Errorf("Marshal(%#v): got %v, want errOneofHasNil", m, err) } } } // A type that implements the Marshaler interface, but is not nillable. type nonNillableInt uint64 func (nni nonNillableInt) Marshal() ([]byte, error) { return EncodeVarint(uint64(nni)), nil } type NNIMessage struct { nni nonNillableInt } func (*NNIMessage) Reset() {} func (*NNIMessage) String() string { return "" } func (*NNIMessage) ProtoMessage() {} // A type that implements the Marshaler interface and is nillable. type nillableMessage struct { x uint64 } func (nm *nillableMessage) Marshal() ([]byte, error) { return EncodeVarint(nm.x), nil } type NMMessage struct { nm *nillableMessage } func (*NMMessage) Reset() {} func (*NMMessage) String() string { return "" } func (*NMMessage) ProtoMessage() {} // Verify a type that uses the Marshaler interface, but has a nil pointer. func TestNilMarshaler(t *testing.T) { // Try a struct with a Marshaler field that is nil. // It should be directly marshable. nmm := new(NMMessage) if _, err := Marshal(nmm); err != nil { t.Error("unexpected error marshaling nmm: ", err) } // Try a struct with a Marshaler field that is not nillable. nnim := new(NNIMessage) nnim.nni = 7 var _ Marshaler = nnim.nni // verify it is truly a Marshaler if _, err := Marshal(nnim); err != nil { t.Error("unexpected error marshaling nnim: ", err) } } func TestAllSetDefaults(t *testing.T) { // Exercise SetDefaults with all scalar field types. m := &Defaults{ // NaN != NaN, so override that here. F_Nan: Float32(1.7), } expected := &Defaults{ F_Bool: Bool(true), F_Int32: Int32(32), F_Int64: Int64(64), F_Fixed32: Uint32(320), F_Fixed64: Uint64(640), F_Uint32: Uint32(3200), F_Uint64: Uint64(6400), F_Float: Float32(314159), F_Double: Float64(271828), F_String: String(`hello, "world!"` + "\n"), F_Bytes: []byte("Bignose"), F_Sint32: Int32(-32), F_Sint64: Int64(-64), F_Enum: Defaults_GREEN.Enum(), F_Pinf: Float32(float32(math.Inf(1))), F_Ninf: Float32(float32(math.Inf(-1))), F_Nan: Float32(1.7), StrZero: String(""), } SetDefaults(m) if !Equal(m, expected) { t.Errorf("SetDefaults failed\n got %v\nwant %v", m, expected) } } func TestSetDefaultsWithSetField(t *testing.T) { // Check that a set value is not overridden. m := &Defaults{ F_Int32: Int32(12), } SetDefaults(m) if v := m.GetF_Int32(); v != 12 { t.Errorf("m.FInt32 = %v, want 12", v) } } func TestSetDefaultsWithSubMessage(t *testing.T) { m := &OtherMessage{ Key: Int64(123), Inner: &InnerMessage{ Host: String("gopher"), }, } expected := &OtherMessage{ Key: Int64(123), Inner: &InnerMessage{ Host: String("gopher"), Port: Int32(4000), }, } SetDefaults(m) if !Equal(m, expected) { t.Errorf("\n got %v\nwant %v", m, expected) } } func TestSetDefaultsWithRepeatedSubMessage(t *testing.T) { m := &MyMessage{ RepInner: []*InnerMessage{{}}, } expected := &MyMessage{ RepInner: []*InnerMessage{{ Port: Int32(4000), }}, } SetDefaults(m) if !Equal(m, expected) { t.Errorf("\n got %v\nwant %v", m, expected) } } func TestSetDefaultWithRepeatedNonMessage(t *testing.T) { m := &MyMessage{ Pet: []string{"turtle", "wombat"}, } expected := Clone(m) SetDefaults(m) if !Equal(m, expected) { t.Errorf("\n got %v\nwant %v", m, expected) } } func TestMaximumTagNumber(t *testing.T) { m := &MaxTag{ LastField: String("natural goat essence"), } buf, err := Marshal(m) if err != nil { t.Fatalf("proto.Marshal failed: %v", err) } m2 := new(MaxTag) if err := Unmarshal(buf, m2); err != nil { t.Fatalf("proto.Unmarshal failed: %v", err) } if got, want := m2.GetLastField(), *m.LastField; got != want { t.Errorf("got %q, want %q", got, want) } } func TestJSON(t *testing.T) { m := &MyMessage{ Count: Int32(4), Pet: []string{"bunny", "kitty"}, Inner: &InnerMessage{ Host: String("cauchy"), }, Bikeshed: MyMessage_GREEN.Enum(), } const expected = `{"count":4,"pet":["bunny","kitty"],"inner":{"host":"cauchy"},"bikeshed":1}` b, err := json.Marshal(m) if err != nil { t.Fatalf("json.Marshal failed: %v", err) } s := string(b) if s != expected { t.Errorf("got %s\nwant %s", s, expected) } received := new(MyMessage) if err := json.Unmarshal(b, received); err != nil { t.Fatalf("json.Unmarshal failed: %v", err) } if !Equal(received, m) { t.Fatalf("got %s, want %s", received, m) } // Test unmarshalling of JSON with symbolic enum name. const old = `{"count":4,"pet":["bunny","kitty"],"inner":{"host":"cauchy"},"bikeshed":"GREEN"}` received.Reset() if err := json.Unmarshal([]byte(old), received); err != nil { t.Fatalf("json.Unmarshal failed: %v", err) } if !Equal(received, m) { t.Fatalf("got %s, want %s", received, m) } } func TestBadWireType(t *testing.T) { b := []byte{7<<3 | 6} // field 7, wire type 6 pb := new(OtherMessage) if err := Unmarshal(b, pb); err == nil { t.Errorf("Unmarshal did not fail") } else if !strings.Contains(err.Error(), "unknown wire type") { t.Errorf("wrong error: %v", err) } } func TestBytesWithInvalidLength(t *testing.T) { // If a byte sequence has an invalid (negative) length, Unmarshal should not panic. b := []byte{2<<3 | WireBytes, 0xff, 0xff, 0xff, 0xff, 0xff, 0} Unmarshal(b, new(MyMessage)) } func TestLengthOverflow(t *testing.T) { // Overflowing a length should not panic. b := []byte{2<<3 | WireBytes, 1, 1, 3<<3 | WireBytes, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x01} Unmarshal(b, new(MyMessage)) } func TestVarintOverflow(t *testing.T) { // Overflowing a 64-bit length should not be allowed. b := []byte{1<<3 | WireVarint, 0x01, 3<<3 | WireBytes, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x01} if err := Unmarshal(b, new(MyMessage)); err == nil { t.Fatalf("Overflowed uint64 length without error") } } func TestUnmarshalFuzz(t *testing.T) { const N = 1000 seed := time.Now().UnixNano() t.Logf("RNG seed is %d", seed) rng := rand.New(rand.NewSource(seed)) buf := make([]byte, 20) for i := 0; i < N; i++ { for j := range buf { buf[j] = byte(rng.Intn(256)) } fuzzUnmarshal(t, buf) } } func TestMergeMessages(t *testing.T) { pb := &MessageList{Message: []*MessageList_Message{{Name: String("x"), Count: Int32(1)}}} data, err := Marshal(pb) if err != nil { t.Fatalf("Marshal: %v", err) } pb1 := new(MessageList) if err := Unmarshal(data, pb1); err != nil { t.Fatalf("first Unmarshal: %v", err) } if err := Unmarshal(data, pb1); err != nil { t.Fatalf("second Unmarshal: %v", err) } if len(pb1.Message) != 1 { t.Errorf("two Unmarshals produced %d Messages, want 1", len(pb1.Message)) } pb2 := new(MessageList) if err := UnmarshalMerge(data, pb2); err != nil { t.Fatalf("first UnmarshalMerge: %v", err) } if err := UnmarshalMerge(data, pb2); err != nil { t.Fatalf("second UnmarshalMerge: %v", err) } if len(pb2.Message) != 2 { t.Errorf("two UnmarshalMerges produced %d Messages, want 2", len(pb2.Message)) } } func TestExtensionMarshalOrder(t *testing.T) { m := &MyMessage{Count: Int(123)} if err := SetExtension(m, E_Ext_More, &Ext{Data: String("alpha")}); err != nil { t.Fatalf("SetExtension: %v", err) } if err := SetExtension(m, E_Ext_Text, String("aleph")); err != nil { t.Fatalf("SetExtension: %v", err) } if err := SetExtension(m, E_Ext_Number, Int32(1)); err != nil { t.Fatalf("SetExtension: %v", err) } // Serialize m several times, and check we get the same bytes each time. var orig []byte for i := 0; i < 100; i++ { b, err := Marshal(m) if err != nil { t.Fatalf("Marshal: %v", err) } if i == 0 { orig = b continue } if !bytes.Equal(b, orig) { t.Errorf("Bytes differ on attempt #%d", i) } } } // Many extensions, because small maps might not iterate differently on each iteration. var exts = []*ExtensionDesc{ E_X201, E_X202, E_X203, E_X204, E_X205, E_X206, E_X207, E_X208, E_X209, E_X210, E_X211, E_X212, E_X213, E_X214, E_X215, E_X216, E_X217, E_X218, E_X219, E_X220, E_X221, E_X222, E_X223, E_X224, E_X225, E_X226, E_X227, E_X228, E_X229, E_X230, E_X231, E_X232, E_X233, E_X234, E_X235, E_X236, E_X237, E_X238, E_X239, E_X240, E_X241, E_X242, E_X243, E_X244, E_X245, E_X246, E_X247, E_X248, E_X249, E_X250, } func TestMessageSetMarshalOrder(t *testing.T) { m := &MyMessageSet{} for _, x := range exts { if err := SetExtension(m, x, &Empty{}); err != nil { t.Fatalf("SetExtension: %v", err) } } buf, err := Marshal(m) if err != nil { t.Fatalf("Marshal: %v", err) } // Serialize m several times, and check we get the same bytes each time. for i := 0; i < 10; i++ { b1, err := Marshal(m) if err != nil { t.Fatalf("Marshal: %v", err) } if !bytes.Equal(b1, buf) { t.Errorf("Bytes differ on re-Marshal #%d", i) } m2 := &MyMessageSet{} if err := Unmarshal(buf, m2); err != nil { t.Errorf("Unmarshal: %v", err) } b2, err := Marshal(m2) if err != nil { t.Errorf("re-Marshal: %v", err) } if !bytes.Equal(b2, buf) { t.Errorf("Bytes differ on round-trip #%d", i) } } } func TestUnmarshalMergesMessages(t *testing.T) { // If a nested message occurs twice in the input, // the fields should be merged when decoding. a := &OtherMessage{ Key: Int64(123), Inner: &InnerMessage{ Host: String("polhode"), Port: Int32(1234), }, } aData, err := Marshal(a) if err != nil { t.Fatalf("Marshal(a): %v", err) } b := &OtherMessage{ Weight: Float32(1.2), Inner: &InnerMessage{ Host: String("herpolhode"), Connected: Bool(true), }, } bData, err := Marshal(b) if err != nil { t.Fatalf("Marshal(b): %v", err) } want := &OtherMessage{ Key: Int64(123), Weight: Float32(1.2), Inner: &InnerMessage{ Host: String("herpolhode"), Port: Int32(1234), Connected: Bool(true), }, } got := new(OtherMessage) if err := Unmarshal(append(aData, bData...), got); err != nil { t.Fatalf("Unmarshal: %v", err) } if !Equal(got, want) { t.Errorf("\n got %v\nwant %v", got, want) } } func TestEncodingSizes(t *testing.T) { tests := []struct { m Message n int }{ {&Defaults{F_Int32: Int32(math.MaxInt32)}, 6}, {&Defaults{F_Int32: Int32(math.MinInt32)}, 11}, {&Defaults{F_Uint32: Uint32(uint32(math.MaxInt32) + 1)}, 6}, {&Defaults{F_Uint32: Uint32(math.MaxUint32)}, 6}, } for _, test := range tests { b, err := Marshal(test.m) if err != nil { t.Errorf("Marshal(%v): %v", test.m, err) continue } if len(b) != test.n { t.Errorf("Marshal(%v) yielded %d bytes, want %d bytes", test.m, len(b), test.n) } } } func TestRequiredNotSetError(t *testing.T) { pb := initGoTest(false) pb.RequiredField.Label = nil pb.F_Int32Required = nil pb.F_Int64Required = nil expected := "0807" + // field 1, encoding 0, value 7 "2206" + "120474797065" + // field 4, encoding 2 (GoTestField) "5001" + // field 10, encoding 0, value 1 "6d20000000" + // field 13, encoding 5, value 0x20 "714000000000000000" + // field 14, encoding 1, value 0x40 "78a019" + // field 15, encoding 0, value 0xca0 = 3232 "8001c032" + // field 16, encoding 0, value 0x1940 = 6464 "8d0100004a45" + // field 17, encoding 5, value 3232.0 "9101000000000040b940" + // field 18, encoding 1, value 6464.0 "9a0106" + "737472696e67" + // field 19, encoding 2, string "string" "b304" + // field 70, encoding 3, start group "ba0408" + "7265717569726564" + // field 71, encoding 2, string "required" "b404" + // field 70, encoding 4, end group "aa0605" + "6279746573" + // field 101, encoding 2, string "bytes" "b0063f" + // field 102, encoding 0, 0x3f zigzag32 "b8067f" // field 103, encoding 0, 0x7f zigzag64 o := old() bytes, err := Marshal(pb) if _, ok := err.(*RequiredNotSetError); !ok { fmt.Printf("marshal-1 err = %v, want *RequiredNotSetError", err) o.DebugPrint("", bytes) t.Fatalf("expected = %s", expected) } if strings.Index(err.Error(), "RequiredField.Label") < 0 { t.Errorf("marshal-1 wrong err msg: %v", err) } if !equal(bytes, expected, t) { o.DebugPrint("neq 1", bytes) t.Fatalf("expected = %s", expected) } // Now test Unmarshal by recreating the original buffer. pbd := new(GoTest) err = Unmarshal(bytes, pbd) if _, ok := err.(*RequiredNotSetError); !ok { t.Fatalf("unmarshal err = %v, want *RequiredNotSetError", err) o.DebugPrint("", bytes) t.Fatalf("string = %s", expected) } if strings.Index(err.Error(), "RequiredField.{Unknown}") < 0 { t.Errorf("unmarshal wrong err msg: %v", err) } bytes, err = Marshal(pbd) if _, ok := err.(*RequiredNotSetError); !ok { t.Errorf("marshal-2 err = %v, want *RequiredNotSetError", err) o.DebugPrint("", bytes) t.Fatalf("string = %s", expected) } if strings.Index(err.Error(), "RequiredField.Label") < 0 { t.Errorf("marshal-2 wrong err msg: %v", err) } if !equal(bytes, expected, t) { o.DebugPrint("neq 2", bytes) t.Fatalf("string = %s", expected) } } func fuzzUnmarshal(t *testing.T, data []byte) { defer func() { if e := recover(); e != nil { t.Errorf("These bytes caused a panic: %+v", data) t.Logf("Stack:\n%s", debug.Stack()) t.FailNow() } }() pb := new(MyMessage) Unmarshal(data, pb) } func TestMapFieldMarshal(t *testing.T) { m := &MessageWithMap{ NameMapping: map[int32]string{ 1: "Rob", 4: "Ian", 8: "Dave", }, } b, err := Marshal(m) if err != nil { t.Fatalf("Marshal: %v", err) } // b should be the concatenation of these three byte sequences in some order. parts := []string{ "\n\a\b\x01\x12\x03Rob", "\n\a\b\x04\x12\x03Ian", "\n\b\b\x08\x12\x04Dave", } ok := false for i := range parts { for j := range parts { if j == i { continue } for k := range parts { if k == i || k == j { continue } try := parts[i] + parts[j] + parts[k] if bytes.Equal(b, []byte(try)) { ok = true break } } } } if !ok { t.Fatalf("Incorrect Marshal output.\n got %q\nwant %q (or a permutation of that)", b, parts[0]+parts[1]+parts[2]) } t.Logf("FYI b: %q", b) (new(Buffer)).DebugPrint("Dump of b", b) } func TestMapFieldRoundTrips(t *testing.T) { m := &MessageWithMap{ NameMapping: map[int32]string{ 1: "Rob", 4: "Ian", 8: "Dave", }, MsgMapping: map[int64]*FloatingPoint{ 0x7001: &FloatingPoint{F: Float64(2.0)}, }, ByteMapping: map[bool][]byte{ false: []byte("that's not right!"), true: []byte("aye, 'tis true!"), }, } b, err := Marshal(m) if err != nil { t.Fatalf("Marshal: %v", err) } t.Logf("FYI b: %q", b) m2 := new(MessageWithMap) if err := Unmarshal(b, m2); err != nil { t.Fatalf("Unmarshal: %v", err) } for _, pair := range [][2]interface{}{ {m.NameMapping, m2.NameMapping}, {m.MsgMapping, m2.MsgMapping}, {m.ByteMapping, m2.ByteMapping}, } { if !reflect.DeepEqual(pair[0], pair[1]) { t.Errorf("Map did not survive a round trip.\ninitial: %v\n final: %v", pair[0], pair[1]) } } } func TestMapFieldWithNil(t *testing.T) { m := &MessageWithMap{ MsgMapping: map[int64]*FloatingPoint{ 1: nil, }, } b, err := Marshal(m) if err == nil { t.Fatalf("Marshal of bad map should have failed, got these bytes: %v", b) } } func TestDecodeMapFieldMissingKey(t *testing.T) { b := []byte{ 0x0A, 0x03, // message, tag 1 (name_mapping), of length 3 bytes // no key 0x12, 0x01, 0x6D, // string value of length 1 byte, value "m" } got := &MessageWithMap{} err := Unmarshal(b, got) if err != nil { t.Fatalf("failed to marshal map with missing key: %v", err) } want := &MessageWithMap{NameMapping: map[int32]string{0: "m"}} if !Equal(got, want) { t.Errorf("Unmarshaled map with no key was not as expected. got: %v, want %v", got, want) } } func TestDecodeMapFieldMissingValue(t *testing.T) { b := []byte{ 0x0A, 0x02, // message, tag 1 (name_mapping), of length 2 bytes 0x08, 0x01, // varint key, value 1 // no value } got := &MessageWithMap{} err := Unmarshal(b, got) if err != nil { t.Fatalf("failed to marshal map with missing value: %v", err) } want := &MessageWithMap{NameMapping: map[int32]string{1: ""}} if !Equal(got, want) { t.Errorf("Unmarshaled map with no value was not as expected. got: %v, want %v", got, want) } } func TestOneof(t *testing.T) { m := &Communique{} b, err := Marshal(m) if err != nil { t.Fatalf("Marshal of empty message with oneof: %v", err) } if len(b) != 0 { t.Errorf("Marshal of empty message yielded too many bytes: %v", b) } m = &Communique{ Union: &Communique_Name{"Barry"}, } // Round-trip. b, err = Marshal(m) if err != nil { t.Fatalf("Marshal of message with oneof: %v", err) } if len(b) != 7 { // name tag/wire (1) + name len (1) + name (5) t.Errorf("Incorrect marshal of message with oneof: %v", b) } m.Reset() if err := Unmarshal(b, m); err != nil { t.Fatalf("Unmarshal of message with oneof: %v", err) } if x, ok := m.Union.(*Communique_Name); !ok || x.Name != "Barry" { t.Errorf("After round trip, Union = %+v", m.Union) } if name := m.GetName(); name != "Barry" { t.Errorf("After round trip, GetName = %q, want %q", name, "Barry") } // Let's try with a message in the oneof. m.Union = &Communique_Msg{&Strings{StringField: String("deep deep string")}} b, err = Marshal(m) if err != nil { t.Fatalf("Marshal of message with oneof set to message: %v", err) } if len(b) != 20 { // msg tag/wire (1) + msg len (1) + msg (1 + 1 + 16) t.Errorf("Incorrect marshal of message with oneof set to message: %v", b) } m.Reset() if err := Unmarshal(b, m); err != nil { t.Fatalf("Unmarshal of message with oneof set to message: %v", err) } ss, ok := m.Union.(*Communique_Msg) if !ok || ss.Msg.GetStringField() != "deep deep string" { t.Errorf("After round trip with oneof set to message, Union = %+v", m.Union) } } func TestInefficientPackedBool(t *testing.T) { // https://github.com/golang/protobuf/issues/76 inp := []byte{ 0x12, 0x02, // 0x12 = 2<<3|2; 2 bytes // Usually a bool should take a single byte, // but it is permitted to be any varint. 0xb9, 0x30, } if err := Unmarshal(inp, new(MoreRepeated)); err != nil { t.Error(err) } } // Benchmarks func testMsg() *GoTest { pb := initGoTest(true) const N = 1000 // Internally the library starts much smaller. pb.F_Int32Repeated = make([]int32, N) pb.F_DoubleRepeated = make([]float64, N) for i := 0; i < N; i++ { pb.F_Int32Repeated[i] = int32(i) pb.F_DoubleRepeated[i] = float64(i) } return pb } func bytesMsg() *GoTest { pb := initGoTest(true) buf := make([]byte, 4000) for i := range buf { buf[i] = byte(i) } pb.F_BytesDefaulted = buf return pb } func benchmarkMarshal(b *testing.B, pb Message, marshal func(Message) ([]byte, error)) { d, _ := marshal(pb) b.SetBytes(int64(len(d))) b.ResetTimer() for i := 0; i < b.N; i++ { marshal(pb) } } func benchmarkBufferMarshal(b *testing.B, pb Message) { p := NewBuffer(nil) benchmarkMarshal(b, pb, func(pb0 Message) ([]byte, error) { p.Reset() err := p.Marshal(pb0) return p.Bytes(), err }) } func benchmarkSize(b *testing.B, pb Message) { benchmarkMarshal(b, pb, func(pb0 Message) ([]byte, error) { Size(pb) return nil, nil }) } func newOf(pb Message) Message { in := reflect.ValueOf(pb) if in.IsNil() { return pb } return reflect.New(in.Type().Elem()).Interface().(Message) } func benchmarkUnmarshal(b *testing.B, pb Message, unmarshal func([]byte, Message) error) { d, _ := Marshal(pb) b.SetBytes(int64(len(d))) pbd := newOf(pb) b.ResetTimer() for i := 0; i < b.N; i++ { unmarshal(d, pbd) } } func benchmarkBufferUnmarshal(b *testing.B, pb Message) { p := NewBuffer(nil) benchmarkUnmarshal(b, pb, func(d []byte, pb0 Message) error { p.SetBuf(d) return p.Unmarshal(pb0) }) } // Benchmark{Marshal,BufferMarshal,Size,Unmarshal,BufferUnmarshal}{,Bytes} func BenchmarkMarshal(b *testing.B) { benchmarkMarshal(b, testMsg(), Marshal) } func BenchmarkBufferMarshal(b *testing.B) { benchmarkBufferMarshal(b, testMsg()) } func BenchmarkSize(b *testing.B) { benchmarkSize(b, testMsg()) } func BenchmarkUnmarshal(b *testing.B) { benchmarkUnmarshal(b, testMsg(), Unmarshal) } func BenchmarkBufferUnmarshal(b *testing.B) { benchmarkBufferUnmarshal(b, testMsg()) } func BenchmarkMarshalBytes(b *testing.B) { benchmarkMarshal(b, bytesMsg(), Marshal) } func BenchmarkBufferMarshalBytes(b *testing.B) { benchmarkBufferMarshal(b, bytesMsg()) } func BenchmarkSizeBytes(b *testing.B) { benchmarkSize(b, bytesMsg()) } func BenchmarkUnmarshalBytes(b *testing.B) { benchmarkUnmarshal(b, bytesMsg(), Unmarshal) } func BenchmarkBufferUnmarshalBytes(b *testing.B) { benchmarkBufferUnmarshal(b, bytesMsg()) } func BenchmarkUnmarshalUnrecognizedFields(b *testing.B) { b.StopTimer() pb := initGoTestField() skip := &GoSkipTest{ SkipInt32: Int32(32), SkipFixed32: Uint32(3232), SkipFixed64: Uint64(6464), SkipString: String("skipper"), Skipgroup: &GoSkipTest_SkipGroup{ GroupInt32: Int32(75), GroupString: String("wxyz"), }, } pbd := new(GoTestField) p := NewBuffer(nil) p.Marshal(pb) p.Marshal(skip) p2 := NewBuffer(nil) b.StartTimer() for i := 0; i < b.N; i++ { p2.SetBuf(p.Bytes()) p2.Unmarshal(pbd) } } lxd-2.0.0/dist/src/github.com/golang/protobuf/proto/Makefile0000644061062106075000000000361612702772352026426 0ustar00stgraberdomain admins00000000000000# Go support for Protocol Buffers - Google's data interchange format # # Copyright 2010 The Go Authors. All rights reserved. # https://github.com/golang/protobuf # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. install: go install test: install generate-test-pbs go test generate-test-pbs: make install make -C testdata protoc --go_out=Mtestdata/test.proto=github.com/golang/protobuf/proto/testdata,Mgoogle/protobuf/any.proto=github.com/golang/protobuf/ptypes/any:. proto3_proto/proto3.proto make lxd-2.0.0/dist/src/github.com/golang/protobuf/proto/pointer_unsafe.go0000644061062106075000000002216512702772352030336 0ustar00stgraberdomain admins00000000000000// Go support for Protocol Buffers - Google's data interchange format // // Copyright 2012 The Go Authors. All rights reserved. // https://github.com/golang/protobuf // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // +build !appengine,!js // This file contains the implementation of the proto field accesses using package unsafe. package proto import ( "reflect" "unsafe" ) // NOTE: These type_Foo functions would more idiomatically be methods, // but Go does not allow methods on pointer types, and we must preserve // some pointer type for the garbage collector. We use these // funcs with clunky names as our poor approximation to methods. // // An alternative would be // type structPointer struct { p unsafe.Pointer } // but that does not registerize as well. // A structPointer is a pointer to a struct. type structPointer unsafe.Pointer // toStructPointer returns a structPointer equivalent to the given reflect value. func toStructPointer(v reflect.Value) structPointer { return structPointer(unsafe.Pointer(v.Pointer())) } // IsNil reports whether p is nil. func structPointer_IsNil(p structPointer) bool { return p == nil } // Interface returns the struct pointer, assumed to have element type t, // as an interface value. func structPointer_Interface(p structPointer, t reflect.Type) interface{} { return reflect.NewAt(t, unsafe.Pointer(p)).Interface() } // A field identifies a field in a struct, accessible from a structPointer. // In this implementation, a field is identified by its byte offset from the start of the struct. type field uintptr // toField returns a field equivalent to the given reflect field. func toField(f *reflect.StructField) field { return field(f.Offset) } // invalidField is an invalid field identifier. const invalidField = ^field(0) // IsValid reports whether the field identifier is valid. func (f field) IsValid() bool { return f != ^field(0) } // Bytes returns the address of a []byte field in the struct. func structPointer_Bytes(p structPointer, f field) *[]byte { return (*[]byte)(unsafe.Pointer(uintptr(p) + uintptr(f))) } // BytesSlice returns the address of a [][]byte field in the struct. func structPointer_BytesSlice(p structPointer, f field) *[][]byte { return (*[][]byte)(unsafe.Pointer(uintptr(p) + uintptr(f))) } // Bool returns the address of a *bool field in the struct. func structPointer_Bool(p structPointer, f field) **bool { return (**bool)(unsafe.Pointer(uintptr(p) + uintptr(f))) } // BoolVal returns the address of a bool field in the struct. func structPointer_BoolVal(p structPointer, f field) *bool { return (*bool)(unsafe.Pointer(uintptr(p) + uintptr(f))) } // BoolSlice returns the address of a []bool field in the struct. func structPointer_BoolSlice(p structPointer, f field) *[]bool { return (*[]bool)(unsafe.Pointer(uintptr(p) + uintptr(f))) } // String returns the address of a *string field in the struct. func structPointer_String(p structPointer, f field) **string { return (**string)(unsafe.Pointer(uintptr(p) + uintptr(f))) } // StringVal returns the address of a string field in the struct. func structPointer_StringVal(p structPointer, f field) *string { return (*string)(unsafe.Pointer(uintptr(p) + uintptr(f))) } // StringSlice returns the address of a []string field in the struct. func structPointer_StringSlice(p structPointer, f field) *[]string { return (*[]string)(unsafe.Pointer(uintptr(p) + uintptr(f))) } // ExtMap returns the address of an extension map field in the struct. func structPointer_ExtMap(p structPointer, f field) *map[int32]Extension { return (*map[int32]Extension)(unsafe.Pointer(uintptr(p) + uintptr(f))) } // NewAt returns the reflect.Value for a pointer to a field in the struct. func structPointer_NewAt(p structPointer, f field, typ reflect.Type) reflect.Value { return reflect.NewAt(typ, unsafe.Pointer(uintptr(p)+uintptr(f))) } // SetStructPointer writes a *struct field in the struct. func structPointer_SetStructPointer(p structPointer, f field, q structPointer) { *(*structPointer)(unsafe.Pointer(uintptr(p) + uintptr(f))) = q } // GetStructPointer reads a *struct field in the struct. func structPointer_GetStructPointer(p structPointer, f field) structPointer { return *(*structPointer)(unsafe.Pointer(uintptr(p) + uintptr(f))) } // StructPointerSlice the address of a []*struct field in the struct. func structPointer_StructPointerSlice(p structPointer, f field) *structPointerSlice { return (*structPointerSlice)(unsafe.Pointer(uintptr(p) + uintptr(f))) } // A structPointerSlice represents a slice of pointers to structs (themselves submessages or groups). type structPointerSlice []structPointer func (v *structPointerSlice) Len() int { return len(*v) } func (v *structPointerSlice) Index(i int) structPointer { return (*v)[i] } func (v *structPointerSlice) Append(p structPointer) { *v = append(*v, p) } // A word32 is the address of a "pointer to 32-bit value" field. type word32 **uint32 // IsNil reports whether *v is nil. func word32_IsNil(p word32) bool { return *p == nil } // Set sets *v to point at a newly allocated word set to x. func word32_Set(p word32, o *Buffer, x uint32) { if len(o.uint32s) == 0 { o.uint32s = make([]uint32, uint32PoolSize) } o.uint32s[0] = x *p = &o.uint32s[0] o.uint32s = o.uint32s[1:] } // Get gets the value pointed at by *v. func word32_Get(p word32) uint32 { return **p } // Word32 returns the address of a *int32, *uint32, *float32, or *enum field in the struct. func structPointer_Word32(p structPointer, f field) word32 { return word32((**uint32)(unsafe.Pointer(uintptr(p) + uintptr(f)))) } // A word32Val is the address of a 32-bit value field. type word32Val *uint32 // Set sets *p to x. func word32Val_Set(p word32Val, x uint32) { *p = x } // Get gets the value pointed at by p. func word32Val_Get(p word32Val) uint32 { return *p } // Word32Val returns the address of a *int32, *uint32, *float32, or *enum field in the struct. func structPointer_Word32Val(p structPointer, f field) word32Val { return word32Val((*uint32)(unsafe.Pointer(uintptr(p) + uintptr(f)))) } // A word32Slice is a slice of 32-bit values. type word32Slice []uint32 func (v *word32Slice) Append(x uint32) { *v = append(*v, x) } func (v *word32Slice) Len() int { return len(*v) } func (v *word32Slice) Index(i int) uint32 { return (*v)[i] } // Word32Slice returns the address of a []int32, []uint32, []float32, or []enum field in the struct. func structPointer_Word32Slice(p structPointer, f field) *word32Slice { return (*word32Slice)(unsafe.Pointer(uintptr(p) + uintptr(f))) } // word64 is like word32 but for 64-bit values. type word64 **uint64 func word64_Set(p word64, o *Buffer, x uint64) { if len(o.uint64s) == 0 { o.uint64s = make([]uint64, uint64PoolSize) } o.uint64s[0] = x *p = &o.uint64s[0] o.uint64s = o.uint64s[1:] } func word64_IsNil(p word64) bool { return *p == nil } func word64_Get(p word64) uint64 { return **p } func structPointer_Word64(p structPointer, f field) word64 { return word64((**uint64)(unsafe.Pointer(uintptr(p) + uintptr(f)))) } // word64Val is like word32Val but for 64-bit values. type word64Val *uint64 func word64Val_Set(p word64Val, o *Buffer, x uint64) { *p = x } func word64Val_Get(p word64Val) uint64 { return *p } func structPointer_Word64Val(p structPointer, f field) word64Val { return word64Val((*uint64)(unsafe.Pointer(uintptr(p) + uintptr(f)))) } // word64Slice is like word32Slice but for 64-bit values. type word64Slice []uint64 func (v *word64Slice) Append(x uint64) { *v = append(*v, x) } func (v *word64Slice) Len() int { return len(*v) } func (v *word64Slice) Index(i int) uint64 { return (*v)[i] } func structPointer_Word64Slice(p structPointer, f field) *word64Slice { return (*word64Slice)(unsafe.Pointer(uintptr(p) + uintptr(f))) } lxd-2.0.0/dist/src/github.com/golang/protobuf/proto/text.go0000644061062106075000000005124212702772352026277 0ustar00stgraberdomain admins00000000000000// Go support for Protocol Buffers - Google's data interchange format // // Copyright 2010 The Go Authors. All rights reserved. // https://github.com/golang/protobuf // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package proto // Functions for writing the text protocol buffer format. import ( "bufio" "bytes" "encoding" "errors" "fmt" "io" "log" "math" "reflect" "sort" "strings" ) var ( newline = []byte("\n") spaces = []byte(" ") gtNewline = []byte(">\n") endBraceNewline = []byte("}\n") backslashN = []byte{'\\', 'n'} backslashR = []byte{'\\', 'r'} backslashT = []byte{'\\', 't'} backslashDQ = []byte{'\\', '"'} backslashBS = []byte{'\\', '\\'} posInf = []byte("inf") negInf = []byte("-inf") nan = []byte("nan") ) type writer interface { io.Writer WriteByte(byte) error } // textWriter is an io.Writer that tracks its indentation level. type textWriter struct { ind int complete bool // if the current position is a complete line compact bool // whether to write out as a one-liner w writer } func (w *textWriter) WriteString(s string) (n int, err error) { if !strings.Contains(s, "\n") { if !w.compact && w.complete { w.writeIndent() } w.complete = false return io.WriteString(w.w, s) } // WriteString is typically called without newlines, so this // codepath and its copy are rare. We copy to avoid // duplicating all of Write's logic here. return w.Write([]byte(s)) } func (w *textWriter) Write(p []byte) (n int, err error) { newlines := bytes.Count(p, newline) if newlines == 0 { if !w.compact && w.complete { w.writeIndent() } n, err = w.w.Write(p) w.complete = false return n, err } frags := bytes.SplitN(p, newline, newlines+1) if w.compact { for i, frag := range frags { if i > 0 { if err := w.w.WriteByte(' '); err != nil { return n, err } n++ } nn, err := w.w.Write(frag) n += nn if err != nil { return n, err } } return n, nil } for i, frag := range frags { if w.complete { w.writeIndent() } nn, err := w.w.Write(frag) n += nn if err != nil { return n, err } if i+1 < len(frags) { if err := w.w.WriteByte('\n'); err != nil { return n, err } n++ } } w.complete = len(frags[len(frags)-1]) == 0 return n, nil } func (w *textWriter) WriteByte(c byte) error { if w.compact && c == '\n' { c = ' ' } if !w.compact && w.complete { w.writeIndent() } err := w.w.WriteByte(c) w.complete = c == '\n' return err } func (w *textWriter) indent() { w.ind++ } func (w *textWriter) unindent() { if w.ind == 0 { log.Printf("proto: textWriter unindented too far") return } w.ind-- } func writeName(w *textWriter, props *Properties) error { if _, err := w.WriteString(props.OrigName); err != nil { return err } if props.Wire != "group" { return w.WriteByte(':') } return nil } // raw is the interface satisfied by RawMessage. type raw interface { Bytes() []byte } func requiresQuotes(u string) bool { // When type URL contains any characters except [0-9A-Za-z./\-]*, it must be quoted. for _, ch := range u { switch { case ch == '.' || ch == '/' || ch == '_': continue case '0' <= ch && ch <= '9': continue case 'A' <= ch && ch <= 'Z': continue case 'a' <= ch && ch <= 'z': continue default: return true } } return false } // isAny reports whether sv is a google.protobuf.Any message func isAny(sv reflect.Value) bool { type wkt interface { XXX_WellKnownType() string } t, ok := sv.Addr().Interface().(wkt) return ok && t.XXX_WellKnownType() == "Any" } // writeProto3Any writes an expanded google.protobuf.Any message. // // It returns (false, nil) if sv value can't be unmarshaled (e.g. because // required messages are not linked in). // // It returns (true, error) when sv was written in expanded format or an error // was encountered. func (tm *TextMarshaler) writeProto3Any(w *textWriter, sv reflect.Value) (bool, error) { turl := sv.FieldByName("TypeUrl") val := sv.FieldByName("Value") if !turl.IsValid() || !val.IsValid() { return true, errors.New("proto: invalid google.protobuf.Any message") } b, ok := val.Interface().([]byte) if !ok { return true, errors.New("proto: invalid google.protobuf.Any message") } parts := strings.Split(turl.String(), "/") mt := MessageType(parts[len(parts)-1]) if mt == nil { return false, nil } m := reflect.New(mt.Elem()) if err := Unmarshal(b, m.Interface().(Message)); err != nil { return false, nil } w.Write([]byte("[")) u := turl.String() if requiresQuotes(u) { writeString(w, u) } else { w.Write([]byte(u)) } if w.compact { w.Write([]byte("]:<")) } else { w.Write([]byte("]: <\n")) w.ind++ } if err := tm.writeStruct(w, m.Elem()); err != nil { return true, err } if w.compact { w.Write([]byte("> ")) } else { w.ind-- w.Write([]byte(">\n")) } return true, nil } func (tm *TextMarshaler) writeStruct(w *textWriter, sv reflect.Value) error { if tm.ExpandAny && isAny(sv) { if canExpand, err := tm.writeProto3Any(w, sv); canExpand { return err } } st := sv.Type() sprops := GetProperties(st) for i := 0; i < sv.NumField(); i++ { fv := sv.Field(i) props := sprops.Prop[i] name := st.Field(i).Name if strings.HasPrefix(name, "XXX_") { // There are two XXX_ fields: // XXX_unrecognized []byte // XXX_extensions map[int32]proto.Extension // The first is handled here; // the second is handled at the bottom of this function. if name == "XXX_unrecognized" && !fv.IsNil() { if err := writeUnknownStruct(w, fv.Interface().([]byte)); err != nil { return err } } continue } if fv.Kind() == reflect.Ptr && fv.IsNil() { // Field not filled in. This could be an optional field or // a required field that wasn't filled in. Either way, there // isn't anything we can show for it. continue } if fv.Kind() == reflect.Slice && fv.IsNil() { // Repeated field that is empty, or a bytes field that is unused. continue } if props.Repeated && fv.Kind() == reflect.Slice { // Repeated field. for j := 0; j < fv.Len(); j++ { if err := writeName(w, props); err != nil { return err } if !w.compact { if err := w.WriteByte(' '); err != nil { return err } } v := fv.Index(j) if v.Kind() == reflect.Ptr && v.IsNil() { // A nil message in a repeated field is not valid, // but we can handle that more gracefully than panicking. if _, err := w.Write([]byte("\n")); err != nil { return err } continue } if err := tm.writeAny(w, v, props); err != nil { return err } if err := w.WriteByte('\n'); err != nil { return err } } continue } if fv.Kind() == reflect.Map { // Map fields are rendered as a repeated struct with key/value fields. keys := fv.MapKeys() sort.Sort(mapKeys(keys)) for _, key := range keys { val := fv.MapIndex(key) if err := writeName(w, props); err != nil { return err } if !w.compact { if err := w.WriteByte(' '); err != nil { return err } } // open struct if err := w.WriteByte('<'); err != nil { return err } if !w.compact { if err := w.WriteByte('\n'); err != nil { return err } } w.indent() // key if _, err := w.WriteString("key:"); err != nil { return err } if !w.compact { if err := w.WriteByte(' '); err != nil { return err } } if err := tm.writeAny(w, key, props.mkeyprop); err != nil { return err } if err := w.WriteByte('\n'); err != nil { return err } // nil values aren't legal, but we can avoid panicking because of them. if val.Kind() != reflect.Ptr || !val.IsNil() { // value if _, err := w.WriteString("value:"); err != nil { return err } if !w.compact { if err := w.WriteByte(' '); err != nil { return err } } if err := tm.writeAny(w, val, props.mvalprop); err != nil { return err } if err := w.WriteByte('\n'); err != nil { return err } } // close struct w.unindent() if err := w.WriteByte('>'); err != nil { return err } if err := w.WriteByte('\n'); err != nil { return err } } continue } if props.proto3 && fv.Kind() == reflect.Slice && fv.Len() == 0 { // empty bytes field continue } if fv.Kind() != reflect.Ptr && fv.Kind() != reflect.Slice { // proto3 non-repeated scalar field; skip if zero value if isProto3Zero(fv) { continue } } if fv.Kind() == reflect.Interface { // Check if it is a oneof. if st.Field(i).Tag.Get("protobuf_oneof") != "" { // fv is nil, or holds a pointer to generated struct. // That generated struct has exactly one field, // which has a protobuf struct tag. if fv.IsNil() { continue } inner := fv.Elem().Elem() // interface -> *T -> T tag := inner.Type().Field(0).Tag.Get("protobuf") props = new(Properties) // Overwrite the outer props var, but not its pointee. props.Parse(tag) // Write the value in the oneof, not the oneof itself. fv = inner.Field(0) // Special case to cope with malformed messages gracefully: // If the value in the oneof is a nil pointer, don't panic // in writeAny. if fv.Kind() == reflect.Ptr && fv.IsNil() { // Use errors.New so writeAny won't render quotes. msg := errors.New("/* nil */") fv = reflect.ValueOf(&msg).Elem() } } } if err := writeName(w, props); err != nil { return err } if !w.compact { if err := w.WriteByte(' '); err != nil { return err } } if b, ok := fv.Interface().(raw); ok { if err := writeRaw(w, b.Bytes()); err != nil { return err } continue } // Enums have a String method, so writeAny will work fine. if err := tm.writeAny(w, fv, props); err != nil { return err } if err := w.WriteByte('\n'); err != nil { return err } } // Extensions (the XXX_extensions field). pv := sv.Addr() if pv.Type().Implements(extendableProtoType) { if err := tm.writeExtensions(w, pv); err != nil { return err } } return nil } // writeRaw writes an uninterpreted raw message. func writeRaw(w *textWriter, b []byte) error { if err := w.WriteByte('<'); err != nil { return err } if !w.compact { if err := w.WriteByte('\n'); err != nil { return err } } w.indent() if err := writeUnknownStruct(w, b); err != nil { return err } w.unindent() if err := w.WriteByte('>'); err != nil { return err } return nil } // writeAny writes an arbitrary field. func (tm *TextMarshaler) writeAny(w *textWriter, v reflect.Value, props *Properties) error { v = reflect.Indirect(v) // Floats have special cases. if v.Kind() == reflect.Float32 || v.Kind() == reflect.Float64 { x := v.Float() var b []byte switch { case math.IsInf(x, 1): b = posInf case math.IsInf(x, -1): b = negInf case math.IsNaN(x): b = nan } if b != nil { _, err := w.Write(b) return err } // Other values are handled below. } // We don't attempt to serialise every possible value type; only those // that can occur in protocol buffers. switch v.Kind() { case reflect.Slice: // Should only be a []byte; repeated fields are handled in writeStruct. if err := writeString(w, string(v.Interface().([]byte))); err != nil { return err } case reflect.String: if err := writeString(w, v.String()); err != nil { return err } case reflect.Struct: // Required/optional group/message. var bra, ket byte = '<', '>' if props != nil && props.Wire == "group" { bra, ket = '{', '}' } if err := w.WriteByte(bra); err != nil { return err } if !w.compact { if err := w.WriteByte('\n'); err != nil { return err } } w.indent() if etm, ok := v.Interface().(encoding.TextMarshaler); ok { text, err := etm.MarshalText() if err != nil { return err } if _, err = w.Write(text); err != nil { return err } } else if err := tm.writeStruct(w, v); err != nil { return err } w.unindent() if err := w.WriteByte(ket); err != nil { return err } default: _, err := fmt.Fprint(w, v.Interface()) return err } return nil } // equivalent to C's isprint. func isprint(c byte) bool { return c >= 0x20 && c < 0x7f } // writeString writes a string in the protocol buffer text format. // It is similar to strconv.Quote except we don't use Go escape sequences, // we treat the string as a byte sequence, and we use octal escapes. // These differences are to maintain interoperability with the other // languages' implementations of the text format. func writeString(w *textWriter, s string) error { // use WriteByte here to get any needed indent if err := w.WriteByte('"'); err != nil { return err } // Loop over the bytes, not the runes. for i := 0; i < len(s); i++ { var err error // Divergence from C++: we don't escape apostrophes. // There's no need to escape them, and the C++ parser // copes with a naked apostrophe. switch c := s[i]; c { case '\n': _, err = w.w.Write(backslashN) case '\r': _, err = w.w.Write(backslashR) case '\t': _, err = w.w.Write(backslashT) case '"': _, err = w.w.Write(backslashDQ) case '\\': _, err = w.w.Write(backslashBS) default: if isprint(c) { err = w.w.WriteByte(c) } else { _, err = fmt.Fprintf(w.w, "\\%03o", c) } } if err != nil { return err } } return w.WriteByte('"') } func writeUnknownStruct(w *textWriter, data []byte) (err error) { if !w.compact { if _, err := fmt.Fprintf(w, "/* %d unknown bytes */\n", len(data)); err != nil { return err } } b := NewBuffer(data) for b.index < len(b.buf) { x, err := b.DecodeVarint() if err != nil { _, err := fmt.Fprintf(w, "/* %v */\n", err) return err } wire, tag := x&7, x>>3 if wire == WireEndGroup { w.unindent() if _, err := w.Write(endBraceNewline); err != nil { return err } continue } if _, err := fmt.Fprint(w, tag); err != nil { return err } if wire != WireStartGroup { if err := w.WriteByte(':'); err != nil { return err } } if !w.compact || wire == WireStartGroup { if err := w.WriteByte(' '); err != nil { return err } } switch wire { case WireBytes: buf, e := b.DecodeRawBytes(false) if e == nil { _, err = fmt.Fprintf(w, "%q", buf) } else { _, err = fmt.Fprintf(w, "/* %v */", e) } case WireFixed32: x, err = b.DecodeFixed32() err = writeUnknownInt(w, x, err) case WireFixed64: x, err = b.DecodeFixed64() err = writeUnknownInt(w, x, err) case WireStartGroup: err = w.WriteByte('{') w.indent() case WireVarint: x, err = b.DecodeVarint() err = writeUnknownInt(w, x, err) default: _, err = fmt.Fprintf(w, "/* unknown wire type %d */", wire) } if err != nil { return err } if err = w.WriteByte('\n'); err != nil { return err } } return nil } func writeUnknownInt(w *textWriter, x uint64, err error) error { if err == nil { _, err = fmt.Fprint(w, x) } else { _, err = fmt.Fprintf(w, "/* %v */", err) } return err } type int32Slice []int32 func (s int32Slice) Len() int { return len(s) } func (s int32Slice) Less(i, j int) bool { return s[i] < s[j] } func (s int32Slice) Swap(i, j int) { s[i], s[j] = s[j], s[i] } // writeExtensions writes all the extensions in pv. // pv is assumed to be a pointer to a protocol message struct that is extendable. func (tm *TextMarshaler) writeExtensions(w *textWriter, pv reflect.Value) error { emap := extensionMaps[pv.Type().Elem()] ep := pv.Interface().(extendableProto) // Order the extensions by ID. // This isn't strictly necessary, but it will give us // canonical output, which will also make testing easier. m := ep.ExtensionMap() ids := make([]int32, 0, len(m)) for id := range m { ids = append(ids, id) } sort.Sort(int32Slice(ids)) for _, extNum := range ids { ext := m[extNum] var desc *ExtensionDesc if emap != nil { desc = emap[extNum] } if desc == nil { // Unknown extension. if err := writeUnknownStruct(w, ext.enc); err != nil { return err } continue } pb, err := GetExtension(ep, desc) if err != nil { return fmt.Errorf("failed getting extension: %v", err) } // Repeated extensions will appear as a slice. if !desc.repeated() { if err := tm.writeExtension(w, desc.Name, pb); err != nil { return err } } else { v := reflect.ValueOf(pb) for i := 0; i < v.Len(); i++ { if err := tm.writeExtension(w, desc.Name, v.Index(i).Interface()); err != nil { return err } } } } return nil } func (tm *TextMarshaler) writeExtension(w *textWriter, name string, pb interface{}) error { if _, err := fmt.Fprintf(w, "[%s]:", name); err != nil { return err } if !w.compact { if err := w.WriteByte(' '); err != nil { return err } } if err := tm.writeAny(w, reflect.ValueOf(pb), nil); err != nil { return err } if err := w.WriteByte('\n'); err != nil { return err } return nil } func (w *textWriter) writeIndent() { if !w.complete { return } remain := w.ind * 2 for remain > 0 { n := remain if n > len(spaces) { n = len(spaces) } w.w.Write(spaces[:n]) remain -= n } w.complete = false } // TextMarshaler is a configurable text format marshaler. type TextMarshaler struct { Compact bool // use compact text format (one line). ExpandAny bool // expand google.protobuf.Any messages of known types } // Marshal writes a given protocol buffer in text format. // The only errors returned are from w. func (tm *TextMarshaler) Marshal(w io.Writer, pb Message) error { val := reflect.ValueOf(pb) if pb == nil || val.IsNil() { w.Write([]byte("")) return nil } var bw *bufio.Writer ww, ok := w.(writer) if !ok { bw = bufio.NewWriter(w) ww = bw } aw := &textWriter{ w: ww, complete: true, compact: tm.Compact, } if etm, ok := pb.(encoding.TextMarshaler); ok { text, err := etm.MarshalText() if err != nil { return err } if _, err = aw.Write(text); err != nil { return err } if bw != nil { return bw.Flush() } return nil } // Dereference the received pointer so we don't have outer < and >. v := reflect.Indirect(val) if err := tm.writeStruct(aw, v); err != nil { return err } if bw != nil { return bw.Flush() } return nil } // Text is the same as Marshal, but returns the string directly. func (tm *TextMarshaler) Text(pb Message) string { var buf bytes.Buffer tm.Marshal(&buf, pb) return buf.String() } var ( defaultTextMarshaler = TextMarshaler{} compactTextMarshaler = TextMarshaler{Compact: true} ) // TODO: consider removing some of the Marshal functions below. // MarshalText writes a given protocol buffer in text format. // The only errors returned are from w. func MarshalText(w io.Writer, pb Message) error { return defaultTextMarshaler.Marshal(w, pb) } // MarshalTextString is the same as MarshalText, but returns the string directly. func MarshalTextString(pb Message) string { return defaultTextMarshaler.Text(pb) } // CompactText writes a given protocol buffer in compact text format (one line). func CompactText(w io.Writer, pb Message) error { return compactTextMarshaler.Marshal(w, pb) } // CompactTextString is the same as CompactText, but returns the string directly. func CompactTextString(pb Message) string { return compactTextMarshaler.Text(pb) } lxd-2.0.0/dist/src/github.com/golang/protobuf/proto/text_parser.go0000644061062106075000000005223312702772352027654 0ustar00stgraberdomain admins00000000000000// Go support for Protocol Buffers - Google's data interchange format // // Copyright 2010 The Go Authors. All rights reserved. // https://github.com/golang/protobuf // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package proto // Functions for parsing the Text protocol buffer format. // TODO: message sets. import ( "encoding" "errors" "fmt" "reflect" "strconv" "strings" "unicode/utf8" ) type ParseError struct { Message string Line int // 1-based line number Offset int // 0-based byte offset from start of input } func (p *ParseError) Error() string { if p.Line == 1 { // show offset only for first line return fmt.Sprintf("line 1.%d: %v", p.Offset, p.Message) } return fmt.Sprintf("line %d: %v", p.Line, p.Message) } type token struct { value string err *ParseError line int // line number offset int // byte number from start of input, not start of line unquoted string // the unquoted version of value, if it was a quoted string } func (t *token) String() string { if t.err == nil { return fmt.Sprintf("%q (line=%d, offset=%d)", t.value, t.line, t.offset) } return fmt.Sprintf("parse error: %v", t.err) } type textParser struct { s string // remaining input done bool // whether the parsing is finished (success or error) backed bool // whether back() was called offset, line int cur token } func newTextParser(s string) *textParser { p := new(textParser) p.s = s p.line = 1 p.cur.line = 1 return p } func (p *textParser) errorf(format string, a ...interface{}) *ParseError { pe := &ParseError{fmt.Sprintf(format, a...), p.cur.line, p.cur.offset} p.cur.err = pe p.done = true return pe } // Numbers and identifiers are matched by [-+._A-Za-z0-9] func isIdentOrNumberChar(c byte) bool { switch { case 'A' <= c && c <= 'Z', 'a' <= c && c <= 'z': return true case '0' <= c && c <= '9': return true } switch c { case '-', '+', '.', '_': return true } return false } func isWhitespace(c byte) bool { switch c { case ' ', '\t', '\n', '\r': return true } return false } func isQuote(c byte) bool { switch c { case '"', '\'': return true } return false } func (p *textParser) skipWhitespace() { i := 0 for i < len(p.s) && (isWhitespace(p.s[i]) || p.s[i] == '#') { if p.s[i] == '#' { // comment; skip to end of line or input for i < len(p.s) && p.s[i] != '\n' { i++ } if i == len(p.s) { break } } if p.s[i] == '\n' { p.line++ } i++ } p.offset += i p.s = p.s[i:len(p.s)] if len(p.s) == 0 { p.done = true } } func (p *textParser) advance() { // Skip whitespace p.skipWhitespace() if p.done { return } // Start of non-whitespace p.cur.err = nil p.cur.offset, p.cur.line = p.offset, p.line p.cur.unquoted = "" switch p.s[0] { case '<', '>', '{', '}', ':', '[', ']', ';', ',', '/': // Single symbol p.cur.value, p.s = p.s[0:1], p.s[1:len(p.s)] case '"', '\'': // Quoted string i := 1 for i < len(p.s) && p.s[i] != p.s[0] && p.s[i] != '\n' { if p.s[i] == '\\' && i+1 < len(p.s) { // skip escaped char i++ } i++ } if i >= len(p.s) || p.s[i] != p.s[0] { p.errorf("unmatched quote") return } unq, err := unquoteC(p.s[1:i], rune(p.s[0])) if err != nil { p.errorf("invalid quoted string %s: %v", p.s[0:i+1], err) return } p.cur.value, p.s = p.s[0:i+1], p.s[i+1:len(p.s)] p.cur.unquoted = unq default: i := 0 for i < len(p.s) && isIdentOrNumberChar(p.s[i]) { i++ } if i == 0 { p.errorf("unexpected byte %#x", p.s[0]) return } p.cur.value, p.s = p.s[0:i], p.s[i:len(p.s)] } p.offset += len(p.cur.value) } var ( errBadUTF8 = errors.New("proto: bad UTF-8") errBadHex = errors.New("proto: bad hexadecimal") ) func unquoteC(s string, quote rune) (string, error) { // This is based on C++'s tokenizer.cc. // Despite its name, this is *not* parsing C syntax. // For instance, "\0" is an invalid quoted string. // Avoid allocation in trivial cases. simple := true for _, r := range s { if r == '\\' || r == quote { simple = false break } } if simple { return s, nil } buf := make([]byte, 0, 3*len(s)/2) for len(s) > 0 { r, n := utf8.DecodeRuneInString(s) if r == utf8.RuneError && n == 1 { return "", errBadUTF8 } s = s[n:] if r != '\\' { if r < utf8.RuneSelf { buf = append(buf, byte(r)) } else { buf = append(buf, string(r)...) } continue } ch, tail, err := unescape(s) if err != nil { return "", err } buf = append(buf, ch...) s = tail } return string(buf), nil } func unescape(s string) (ch string, tail string, err error) { r, n := utf8.DecodeRuneInString(s) if r == utf8.RuneError && n == 1 { return "", "", errBadUTF8 } s = s[n:] switch r { case 'a': return "\a", s, nil case 'b': return "\b", s, nil case 'f': return "\f", s, nil case 'n': return "\n", s, nil case 'r': return "\r", s, nil case 't': return "\t", s, nil case 'v': return "\v", s, nil case '?': return "?", s, nil // trigraph workaround case '\'', '"', '\\': return string(r), s, nil case '0', '1', '2', '3', '4', '5', '6', '7', 'x', 'X': if len(s) < 2 { return "", "", fmt.Errorf(`\%c requires 2 following digits`, r) } base := 8 ss := s[:2] s = s[2:] if r == 'x' || r == 'X' { base = 16 } else { ss = string(r) + ss } i, err := strconv.ParseUint(ss, base, 8) if err != nil { return "", "", err } return string([]byte{byte(i)}), s, nil case 'u', 'U': n := 4 if r == 'U' { n = 8 } if len(s) < n { return "", "", fmt.Errorf(`\%c requires %d digits`, r, n) } bs := make([]byte, n/2) for i := 0; i < n; i += 2 { a, ok1 := unhex(s[i]) b, ok2 := unhex(s[i+1]) if !ok1 || !ok2 { return "", "", errBadHex } bs[i/2] = a<<4 | b } s = s[n:] return string(bs), s, nil } return "", "", fmt.Errorf(`unknown escape \%c`, r) } // Adapted from src/pkg/strconv/quote.go. func unhex(b byte) (v byte, ok bool) { switch { case '0' <= b && b <= '9': return b - '0', true case 'a' <= b && b <= 'f': return b - 'a' + 10, true case 'A' <= b && b <= 'F': return b - 'A' + 10, true } return 0, false } // Back off the parser by one token. Can only be done between calls to next(). // It makes the next advance() a no-op. func (p *textParser) back() { p.backed = true } // Advances the parser and returns the new current token. func (p *textParser) next() *token { if p.backed || p.done { p.backed = false return &p.cur } p.advance() if p.done { p.cur.value = "" } else if len(p.cur.value) > 0 && isQuote(p.cur.value[0]) { // Look for multiple quoted strings separated by whitespace, // and concatenate them. cat := p.cur for { p.skipWhitespace() if p.done || !isQuote(p.s[0]) { break } p.advance() if p.cur.err != nil { return &p.cur } cat.value += " " + p.cur.value cat.unquoted += p.cur.unquoted } p.done = false // parser may have seen EOF, but we want to return cat p.cur = cat } return &p.cur } func (p *textParser) consumeToken(s string) error { tok := p.next() if tok.err != nil { return tok.err } if tok.value != s { p.back() return p.errorf("expected %q, found %q", s, tok.value) } return nil } // Return a RequiredNotSetError indicating which required field was not set. func (p *textParser) missingRequiredFieldError(sv reflect.Value) *RequiredNotSetError { st := sv.Type() sprops := GetProperties(st) for i := 0; i < st.NumField(); i++ { if !isNil(sv.Field(i)) { continue } props := sprops.Prop[i] if props.Required { return &RequiredNotSetError{fmt.Sprintf("%v.%v", st, props.OrigName)} } } return &RequiredNotSetError{fmt.Sprintf("%v.", st)} // should not happen } // Returns the index in the struct for the named field, as well as the parsed tag properties. func structFieldByName(sprops *StructProperties, name string) (int, *Properties, bool) { i, ok := sprops.decoderOrigNames[name] if ok { return i, sprops.Prop[i], true } return -1, nil, false } // Consume a ':' from the input stream (if the next token is a colon), // returning an error if a colon is needed but not present. func (p *textParser) checkForColon(props *Properties, typ reflect.Type) *ParseError { tok := p.next() if tok.err != nil { return tok.err } if tok.value != ":" { // Colon is optional when the field is a group or message. needColon := true switch props.Wire { case "group": needColon = false case "bytes": // A "bytes" field is either a message, a string, or a repeated field; // those three become *T, *string and []T respectively, so we can check for // this field being a pointer to a non-string. if typ.Kind() == reflect.Ptr { // *T or *string if typ.Elem().Kind() == reflect.String { break } } else if typ.Kind() == reflect.Slice { // []T or []*T if typ.Elem().Kind() != reflect.Ptr { break } } else if typ.Kind() == reflect.String { // The proto3 exception is for a string field, // which requires a colon. break } needColon = false } if needColon { return p.errorf("expected ':', found %q", tok.value) } p.back() } return nil } func (p *textParser) readStruct(sv reflect.Value, terminator string) error { st := sv.Type() sprops := GetProperties(st) reqCount := sprops.reqCount var reqFieldErr error fieldSet := make(map[string]bool) // A struct is a sequence of "name: value", terminated by one of // '>' or '}', or the end of the input. A name may also be // "[extension]" or "[type/url]". // // The whole struct can also be an expanded Any message, like: // [type/url] < ... struct contents ... > for { tok := p.next() if tok.err != nil { return tok.err } if tok.value == terminator { break } if tok.value == "[" { // Looks like an extension or an Any. // // TODO: Check whether we need to handle // namespace rooted names (e.g. ".something.Foo"). extName, err := p.consumeExtName() if err != nil { return err } if s := strings.LastIndex(extName, "/"); s >= 0 { // If it contains a slash, it's an Any type URL. messageName := extName[s+1:] mt := MessageType(messageName) if mt == nil { return p.errorf("unrecognized message %q in google.protobuf.Any", messageName) } tok = p.next() if tok.err != nil { return tok.err } // consume an optional colon if tok.value == ":" { tok = p.next() if tok.err != nil { return tok.err } } var terminator string switch tok.value { case "<": terminator = ">" case "{": terminator = "}" default: return p.errorf("expected '{' or '<', found %q", tok.value) } v := reflect.New(mt.Elem()) if pe := p.readStruct(v.Elem(), terminator); pe != nil { return pe } b, err := Marshal(v.Interface().(Message)) if err != nil { return p.errorf("failed to marshal message of type %q: %v", messageName, err) } sv.FieldByName("TypeUrl").SetString(extName) sv.FieldByName("Value").SetBytes(b) continue } var desc *ExtensionDesc // This could be faster, but it's functional. // TODO: Do something smarter than a linear scan. for _, d := range RegisteredExtensions(reflect.New(st).Interface().(Message)) { if d.Name == extName { desc = d break } } if desc == nil { return p.errorf("unrecognized extension %q", extName) } props := &Properties{} props.Parse(desc.Tag) typ := reflect.TypeOf(desc.ExtensionType) if err := p.checkForColon(props, typ); err != nil { return err } rep := desc.repeated() // Read the extension structure, and set it in // the value we're constructing. var ext reflect.Value if !rep { ext = reflect.New(typ).Elem() } else { ext = reflect.New(typ.Elem()).Elem() } if err := p.readAny(ext, props); err != nil { if _, ok := err.(*RequiredNotSetError); !ok { return err } reqFieldErr = err } ep := sv.Addr().Interface().(extendableProto) if !rep { SetExtension(ep, desc, ext.Interface()) } else { old, err := GetExtension(ep, desc) var sl reflect.Value if err == nil { sl = reflect.ValueOf(old) // existing slice } else { sl = reflect.MakeSlice(typ, 0, 1) } sl = reflect.Append(sl, ext) SetExtension(ep, desc, sl.Interface()) } if err := p.consumeOptionalSeparator(); err != nil { return err } continue } // This is a normal, non-extension field. name := tok.value var dst reflect.Value fi, props, ok := structFieldByName(sprops, name) if ok { dst = sv.Field(fi) } else if oop, ok := sprops.OneofTypes[name]; ok { // It is a oneof. props = oop.Prop nv := reflect.New(oop.Type.Elem()) dst = nv.Elem().Field(0) sv.Field(oop.Field).Set(nv) } if !dst.IsValid() { return p.errorf("unknown field name %q in %v", name, st) } if dst.Kind() == reflect.Map { // Consume any colon. if err := p.checkForColon(props, dst.Type()); err != nil { return err } // Construct the map if it doesn't already exist. if dst.IsNil() { dst.Set(reflect.MakeMap(dst.Type())) } key := reflect.New(dst.Type().Key()).Elem() val := reflect.New(dst.Type().Elem()).Elem() // The map entry should be this sequence of tokens: // < key : KEY value : VALUE > // Technically the "key" and "value" could come in any order, // but in practice they won't. tok := p.next() var terminator string switch tok.value { case "<": terminator = ">" case "{": terminator = "}" default: return p.errorf("expected '{' or '<', found %q", tok.value) } if err := p.consumeToken("key"); err != nil { return err } if err := p.consumeToken(":"); err != nil { return err } if err := p.readAny(key, props.mkeyprop); err != nil { return err } if err := p.consumeOptionalSeparator(); err != nil { return err } if err := p.consumeToken("value"); err != nil { return err } if err := p.checkForColon(props.mvalprop, dst.Type().Elem()); err != nil { return err } if err := p.readAny(val, props.mvalprop); err != nil { return err } if err := p.consumeOptionalSeparator(); err != nil { return err } if err := p.consumeToken(terminator); err != nil { return err } dst.SetMapIndex(key, val) continue } // Check that it's not already set if it's not a repeated field. if !props.Repeated && fieldSet[name] { return p.errorf("non-repeated field %q was repeated", name) } if err := p.checkForColon(props, dst.Type()); err != nil { return err } // Parse into the field. fieldSet[name] = true if err := p.readAny(dst, props); err != nil { if _, ok := err.(*RequiredNotSetError); !ok { return err } reqFieldErr = err } else if props.Required { reqCount-- } if err := p.consumeOptionalSeparator(); err != nil { return err } } if reqCount > 0 { return p.missingRequiredFieldError(sv) } return reqFieldErr } // consumeExtName consumes extension name or expanded Any type URL and the // following ']'. It returns the name or URL consumed. func (p *textParser) consumeExtName() (string, error) { tok := p.next() if tok.err != nil { return "", tok.err } // If extension name or type url is quoted, it's a single token. if len(tok.value) > 2 && isQuote(tok.value[0]) && tok.value[len(tok.value)-1] == tok.value[0] { name, err := unquoteC(tok.value[1:len(tok.value)-1], rune(tok.value[0])) if err != nil { return "", err } return name, p.consumeToken("]") } // Consume everything up to "]" var parts []string for tok.value != "]" { parts = append(parts, tok.value) tok = p.next() if tok.err != nil { return "", p.errorf("unrecognized type_url or extension name: %s", tok.err) } } return strings.Join(parts, ""), nil } // consumeOptionalSeparator consumes an optional semicolon or comma. // It is used in readStruct to provide backward compatibility. func (p *textParser) consumeOptionalSeparator() error { tok := p.next() if tok.err != nil { return tok.err } if tok.value != ";" && tok.value != "," { p.back() } return nil } func (p *textParser) readAny(v reflect.Value, props *Properties) error { tok := p.next() if tok.err != nil { return tok.err } if tok.value == "" { return p.errorf("unexpected EOF") } switch fv := v; fv.Kind() { case reflect.Slice: at := v.Type() if at.Elem().Kind() == reflect.Uint8 { // Special case for []byte if tok.value[0] != '"' && tok.value[0] != '\'' { // Deliberately written out here, as the error after // this switch statement would write "invalid []byte: ...", // which is not as user-friendly. return p.errorf("invalid string: %v", tok.value) } bytes := []byte(tok.unquoted) fv.Set(reflect.ValueOf(bytes)) return nil } // Repeated field. if tok.value == "[" { // Repeated field with list notation, like [1,2,3]. for { fv.Set(reflect.Append(fv, reflect.New(at.Elem()).Elem())) err := p.readAny(fv.Index(fv.Len()-1), props) if err != nil { return err } tok := p.next() if tok.err != nil { return tok.err } if tok.value == "]" { break } if tok.value != "," { return p.errorf("Expected ']' or ',' found %q", tok.value) } } return nil } // One value of the repeated field. p.back() fv.Set(reflect.Append(fv, reflect.New(at.Elem()).Elem())) return p.readAny(fv.Index(fv.Len()-1), props) case reflect.Bool: // Either "true", "false", 1 or 0. switch tok.value { case "true", "1": fv.SetBool(true) return nil case "false", "0": fv.SetBool(false) return nil } case reflect.Float32, reflect.Float64: v := tok.value // Ignore 'f' for compatibility with output generated by C++, but don't // remove 'f' when the value is "-inf" or "inf". if strings.HasSuffix(v, "f") && tok.value != "-inf" && tok.value != "inf" { v = v[:len(v)-1] } if f, err := strconv.ParseFloat(v, fv.Type().Bits()); err == nil { fv.SetFloat(f) return nil } case reflect.Int32: if x, err := strconv.ParseInt(tok.value, 0, 32); err == nil { fv.SetInt(x) return nil } if len(props.Enum) == 0 { break } m, ok := enumValueMaps[props.Enum] if !ok { break } x, ok := m[tok.value] if !ok { break } fv.SetInt(int64(x)) return nil case reflect.Int64: if x, err := strconv.ParseInt(tok.value, 0, 64); err == nil { fv.SetInt(x) return nil } case reflect.Ptr: // A basic field (indirected through pointer), or a repeated message/group p.back() fv.Set(reflect.New(fv.Type().Elem())) return p.readAny(fv.Elem(), props) case reflect.String: if tok.value[0] == '"' || tok.value[0] == '\'' { fv.SetString(tok.unquoted) return nil } case reflect.Struct: var terminator string switch tok.value { case "{": terminator = "}" case "<": terminator = ">" default: return p.errorf("expected '{' or '<', found %q", tok.value) } // TODO: Handle nested messages which implement encoding.TextUnmarshaler. return p.readStruct(fv, terminator) case reflect.Uint32: if x, err := strconv.ParseUint(tok.value, 0, 32); err == nil { fv.SetUint(uint64(x)) return nil } case reflect.Uint64: if x, err := strconv.ParseUint(tok.value, 0, 64); err == nil { fv.SetUint(x) return nil } } return p.errorf("invalid %v: %v", v.Type(), tok.value) } // UnmarshalText reads a protocol buffer in Text format. UnmarshalText resets pb // before starting to unmarshal, so any existing data in pb is always removed. // If a required field is not set and no other error occurs, // UnmarshalText returns *RequiredNotSetError. func UnmarshalText(s string, pb Message) error { if um, ok := pb.(encoding.TextUnmarshaler); ok { err := um.UnmarshalText([]byte(s)) return err } pb.Reset() v := reflect.ValueOf(pb) if pe := newTextParser(s).readStruct(v.Elem(), ""); pe != nil { return pe } return nil } lxd-2.0.0/dist/src/github.com/golang/protobuf/proto/message_set.go0000644061062106075000000002025612702772352027613 0ustar00stgraberdomain admins00000000000000// Go support for Protocol Buffers - Google's data interchange format // // Copyright 2010 The Go Authors. All rights reserved. // https://github.com/golang/protobuf // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package proto /* * Support for message sets. */ import ( "bytes" "encoding/json" "errors" "fmt" "reflect" "sort" ) // errNoMessageTypeID occurs when a protocol buffer does not have a message type ID. // A message type ID is required for storing a protocol buffer in a message set. var errNoMessageTypeID = errors.New("proto does not have a message type ID") // The first two types (_MessageSet_Item and messageSet) // model what the protocol compiler produces for the following protocol message: // message MessageSet { // repeated group Item = 1 { // required int32 type_id = 2; // required string message = 3; // }; // } // That is the MessageSet wire format. We can't use a proto to generate these // because that would introduce a circular dependency between it and this package. type _MessageSet_Item struct { TypeId *int32 `protobuf:"varint,2,req,name=type_id"` Message []byte `protobuf:"bytes,3,req,name=message"` } type messageSet struct { Item []*_MessageSet_Item `protobuf:"group,1,rep"` XXX_unrecognized []byte // TODO: caching? } // Make sure messageSet is a Message. var _ Message = (*messageSet)(nil) // messageTypeIder is an interface satisfied by a protocol buffer type // that may be stored in a MessageSet. type messageTypeIder interface { MessageTypeId() int32 } func (ms *messageSet) find(pb Message) *_MessageSet_Item { mti, ok := pb.(messageTypeIder) if !ok { return nil } id := mti.MessageTypeId() for _, item := range ms.Item { if *item.TypeId == id { return item } } return nil } func (ms *messageSet) Has(pb Message) bool { if ms.find(pb) != nil { return true } return false } func (ms *messageSet) Unmarshal(pb Message) error { if item := ms.find(pb); item != nil { return Unmarshal(item.Message, pb) } if _, ok := pb.(messageTypeIder); !ok { return errNoMessageTypeID } return nil // TODO: return error instead? } func (ms *messageSet) Marshal(pb Message) error { msg, err := Marshal(pb) if err != nil { return err } if item := ms.find(pb); item != nil { // reuse existing item item.Message = msg return nil } mti, ok := pb.(messageTypeIder) if !ok { return errNoMessageTypeID } mtid := mti.MessageTypeId() ms.Item = append(ms.Item, &_MessageSet_Item{ TypeId: &mtid, Message: msg, }) return nil } func (ms *messageSet) Reset() { *ms = messageSet{} } func (ms *messageSet) String() string { return CompactTextString(ms) } func (*messageSet) ProtoMessage() {} // Support for the message_set_wire_format message option. func skipVarint(buf []byte) []byte { i := 0 for ; buf[i]&0x80 != 0; i++ { } return buf[i+1:] } // MarshalMessageSet encodes the extension map represented by m in the message set wire format. // It is called by generated Marshal methods on protocol buffer messages with the message_set_wire_format option. func MarshalMessageSet(m map[int32]Extension) ([]byte, error) { if err := encodeExtensionMap(m); err != nil { return nil, err } // Sort extension IDs to provide a deterministic encoding. // See also enc_map in encode.go. ids := make([]int, 0, len(m)) for id := range m { ids = append(ids, int(id)) } sort.Ints(ids) ms := &messageSet{Item: make([]*_MessageSet_Item, 0, len(m))} for _, id := range ids { e := m[int32(id)] // Remove the wire type and field number varint, as well as the length varint. msg := skipVarint(skipVarint(e.enc)) ms.Item = append(ms.Item, &_MessageSet_Item{ TypeId: Int32(int32(id)), Message: msg, }) } return Marshal(ms) } // UnmarshalMessageSet decodes the extension map encoded in buf in the message set wire format. // It is called by generated Unmarshal methods on protocol buffer messages with the message_set_wire_format option. func UnmarshalMessageSet(buf []byte, m map[int32]Extension) error { ms := new(messageSet) if err := Unmarshal(buf, ms); err != nil { return err } for _, item := range ms.Item { id := *item.TypeId msg := item.Message // Restore wire type and field number varint, plus length varint. // Be careful to preserve duplicate items. b := EncodeVarint(uint64(id)<<3 | WireBytes) if ext, ok := m[id]; ok { // Existing data; rip off the tag and length varint // so we join the new data correctly. // We can assume that ext.enc is set because we are unmarshaling. o := ext.enc[len(b):] // skip wire type and field number _, n := DecodeVarint(o) // calculate length of length varint o = o[n:] // skip length varint msg = append(o, msg...) // join old data and new data } b = append(b, EncodeVarint(uint64(len(msg)))...) b = append(b, msg...) m[id] = Extension{enc: b} } return nil } // MarshalMessageSetJSON encodes the extension map represented by m in JSON format. // It is called by generated MarshalJSON methods on protocol buffer messages with the message_set_wire_format option. func MarshalMessageSetJSON(m map[int32]Extension) ([]byte, error) { var b bytes.Buffer b.WriteByte('{') // Process the map in key order for deterministic output. ids := make([]int32, 0, len(m)) for id := range m { ids = append(ids, id) } sort.Sort(int32Slice(ids)) // int32Slice defined in text.go for i, id := range ids { ext := m[id] if i > 0 { b.WriteByte(',') } msd, ok := messageSetMap[id] if !ok { // Unknown type; we can't render it, so skip it. continue } fmt.Fprintf(&b, `"[%s]":`, msd.name) x := ext.value if x == nil { x = reflect.New(msd.t.Elem()).Interface() if err := Unmarshal(ext.enc, x.(Message)); err != nil { return nil, err } } d, err := json.Marshal(x) if err != nil { return nil, err } b.Write(d) } b.WriteByte('}') return b.Bytes(), nil } // UnmarshalMessageSetJSON decodes the extension map encoded in buf in JSON format. // It is called by generated UnmarshalJSON methods on protocol buffer messages with the message_set_wire_format option. func UnmarshalMessageSetJSON(buf []byte, m map[int32]Extension) error { // Common-case fast path. if len(buf) == 0 || bytes.Equal(buf, []byte("{}")) { return nil } // This is fairly tricky, and it's not clear that it is needed. return errors.New("TODO: UnmarshalMessageSetJSON not yet implemented") } // A global registry of types that can be used in a MessageSet. var messageSetMap = make(map[int32]messageSetDesc) type messageSetDesc struct { t reflect.Type // pointer to struct name string } // RegisterMessageSetType is called from the generated code. func RegisterMessageSetType(m Message, fieldNum int32, name string) { messageSetMap[fieldNum] = messageSetDesc{ t: reflect.TypeOf(m), name: name, } } lxd-2.0.0/dist/src/github.com/golang/protobuf/proto/testdata/0000755061062106075000000000000012702772352026571 5ustar00stgraberdomain admins00000000000000lxd-2.0.0/dist/src/github.com/golang/protobuf/proto/testdata/golden_test.go0000644061062106075000000000556012702772352031435 0ustar00stgraberdomain admins00000000000000// Go support for Protocol Buffers - Google's data interchange format // // Copyright 2012 The Go Authors. All rights reserved. // https://github.com/golang/protobuf // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Verify that the compiler output for test.proto is unchanged. package testdata import ( "crypto/sha1" "fmt" "io/ioutil" "os" "os/exec" "path/filepath" "testing" ) // sum returns in string form (for easy comparison) the SHA-1 hash of the named file. func sum(t *testing.T, name string) string { data, err := ioutil.ReadFile(name) if err != nil { t.Fatal(err) } t.Logf("sum(%q): length is %d", name, len(data)) hash := sha1.New() _, err = hash.Write(data) if err != nil { t.Fatal(err) } return fmt.Sprintf("% x", hash.Sum(nil)) } func run(t *testing.T, name string, args ...string) { cmd := exec.Command(name, args...) cmd.Stdin = os.Stdin cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr err := cmd.Run() if err != nil { t.Fatal(err) } } func TestGolden(t *testing.T) { // Compute the original checksum. goldenSum := sum(t, "test.pb.go") // Run the proto compiler. run(t, "protoc", "--go_out="+os.TempDir(), "test.proto") newFile := filepath.Join(os.TempDir(), "test.pb.go") defer os.Remove(newFile) // Compute the new checksum. newSum := sum(t, newFile) // Verify if newSum != goldenSum { run(t, "diff", "-u", "test.pb.go", newFile) t.Fatal("Code generated by protoc-gen-go has changed; update test.pb.go") } } lxd-2.0.0/dist/src/github.com/golang/protobuf/proto/testdata/test.pb.go0000644061062106075000000042161312702772352030506 0ustar00stgraberdomain admins00000000000000// Code generated by protoc-gen-go. // source: test.proto // DO NOT EDIT! /* Package testdata is a generated protocol buffer package. It is generated from these files: test.proto It has these top-level messages: GoEnum GoTestField GoTest GoSkipTest NonPackedTest PackedTest MaxTag OldMessage NewMessage InnerMessage OtherMessage MyMessage Ext ComplexExtension DefaultsMessage MyMessageSet Empty MessageList Strings Defaults SubDefaults RepeatedEnum MoreRepeated GroupOld GroupNew FloatingPoint MessageWithMap Oneof Communique */ package testdata import proto "github.com/golang/protobuf/proto" import fmt "fmt" import math "math" // Reference imports to suppress errors if they are not otherwise used. var _ = proto.Marshal var _ = fmt.Errorf var _ = math.Inf // This is a compile-time assertion to ensure that this generated file // is compatible with the proto package it is being compiled against. const _ = proto.ProtoPackageIsVersion1 type FOO int32 const ( FOO_FOO1 FOO = 1 ) var FOO_name = map[int32]string{ 1: "FOO1", } var FOO_value = map[string]int32{ "FOO1": 1, } func (x FOO) Enum() *FOO { p := new(FOO) *p = x return p } func (x FOO) String() string { return proto.EnumName(FOO_name, int32(x)) } func (x *FOO) UnmarshalJSON(data []byte) error { value, err := proto.UnmarshalJSONEnum(FOO_value, data, "FOO") if err != nil { return err } *x = FOO(value) return nil } func (FOO) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } // An enum, for completeness. type GoTest_KIND int32 const ( GoTest_VOID GoTest_KIND = 0 // Basic types GoTest_BOOL GoTest_KIND = 1 GoTest_BYTES GoTest_KIND = 2 GoTest_FINGERPRINT GoTest_KIND = 3 GoTest_FLOAT GoTest_KIND = 4 GoTest_INT GoTest_KIND = 5 GoTest_STRING GoTest_KIND = 6 GoTest_TIME GoTest_KIND = 7 // Groupings GoTest_TUPLE GoTest_KIND = 8 GoTest_ARRAY GoTest_KIND = 9 GoTest_MAP GoTest_KIND = 10 // Table types GoTest_TABLE GoTest_KIND = 11 // Functions GoTest_FUNCTION GoTest_KIND = 12 ) var GoTest_KIND_name = map[int32]string{ 0: "VOID", 1: "BOOL", 2: "BYTES", 3: "FINGERPRINT", 4: "FLOAT", 5: "INT", 6: "STRING", 7: "TIME", 8: "TUPLE", 9: "ARRAY", 10: "MAP", 11: "TABLE", 12: "FUNCTION", } var GoTest_KIND_value = map[string]int32{ "VOID": 0, "BOOL": 1, "BYTES": 2, "FINGERPRINT": 3, "FLOAT": 4, "INT": 5, "STRING": 6, "TIME": 7, "TUPLE": 8, "ARRAY": 9, "MAP": 10, "TABLE": 11, "FUNCTION": 12, } func (x GoTest_KIND) Enum() *GoTest_KIND { p := new(GoTest_KIND) *p = x return p } func (x GoTest_KIND) String() string { return proto.EnumName(GoTest_KIND_name, int32(x)) } func (x *GoTest_KIND) UnmarshalJSON(data []byte) error { value, err := proto.UnmarshalJSONEnum(GoTest_KIND_value, data, "GoTest_KIND") if err != nil { return err } *x = GoTest_KIND(value) return nil } func (GoTest_KIND) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{2, 0} } type MyMessage_Color int32 const ( MyMessage_RED MyMessage_Color = 0 MyMessage_GREEN MyMessage_Color = 1 MyMessage_BLUE MyMessage_Color = 2 ) var MyMessage_Color_name = map[int32]string{ 0: "RED", 1: "GREEN", 2: "BLUE", } var MyMessage_Color_value = map[string]int32{ "RED": 0, "GREEN": 1, "BLUE": 2, } func (x MyMessage_Color) Enum() *MyMessage_Color { p := new(MyMessage_Color) *p = x return p } func (x MyMessage_Color) String() string { return proto.EnumName(MyMessage_Color_name, int32(x)) } func (x *MyMessage_Color) UnmarshalJSON(data []byte) error { value, err := proto.UnmarshalJSONEnum(MyMessage_Color_value, data, "MyMessage_Color") if err != nil { return err } *x = MyMessage_Color(value) return nil } func (MyMessage_Color) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{11, 0} } type DefaultsMessage_DefaultsEnum int32 const ( DefaultsMessage_ZERO DefaultsMessage_DefaultsEnum = 0 DefaultsMessage_ONE DefaultsMessage_DefaultsEnum = 1 DefaultsMessage_TWO DefaultsMessage_DefaultsEnum = 2 ) var DefaultsMessage_DefaultsEnum_name = map[int32]string{ 0: "ZERO", 1: "ONE", 2: "TWO", } var DefaultsMessage_DefaultsEnum_value = map[string]int32{ "ZERO": 0, "ONE": 1, "TWO": 2, } func (x DefaultsMessage_DefaultsEnum) Enum() *DefaultsMessage_DefaultsEnum { p := new(DefaultsMessage_DefaultsEnum) *p = x return p } func (x DefaultsMessage_DefaultsEnum) String() string { return proto.EnumName(DefaultsMessage_DefaultsEnum_name, int32(x)) } func (x *DefaultsMessage_DefaultsEnum) UnmarshalJSON(data []byte) error { value, err := proto.UnmarshalJSONEnum(DefaultsMessage_DefaultsEnum_value, data, "DefaultsMessage_DefaultsEnum") if err != nil { return err } *x = DefaultsMessage_DefaultsEnum(value) return nil } func (DefaultsMessage_DefaultsEnum) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{14, 0} } type Defaults_Color int32 const ( Defaults_RED Defaults_Color = 0 Defaults_GREEN Defaults_Color = 1 Defaults_BLUE Defaults_Color = 2 ) var Defaults_Color_name = map[int32]string{ 0: "RED", 1: "GREEN", 2: "BLUE", } var Defaults_Color_value = map[string]int32{ "RED": 0, "GREEN": 1, "BLUE": 2, } func (x Defaults_Color) Enum() *Defaults_Color { p := new(Defaults_Color) *p = x return p } func (x Defaults_Color) String() string { return proto.EnumName(Defaults_Color_name, int32(x)) } func (x *Defaults_Color) UnmarshalJSON(data []byte) error { value, err := proto.UnmarshalJSONEnum(Defaults_Color_value, data, "Defaults_Color") if err != nil { return err } *x = Defaults_Color(value) return nil } func (Defaults_Color) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{19, 0} } type RepeatedEnum_Color int32 const ( RepeatedEnum_RED RepeatedEnum_Color = 1 ) var RepeatedEnum_Color_name = map[int32]string{ 1: "RED", } var RepeatedEnum_Color_value = map[string]int32{ "RED": 1, } func (x RepeatedEnum_Color) Enum() *RepeatedEnum_Color { p := new(RepeatedEnum_Color) *p = x return p } func (x RepeatedEnum_Color) String() string { return proto.EnumName(RepeatedEnum_Color_name, int32(x)) } func (x *RepeatedEnum_Color) UnmarshalJSON(data []byte) error { value, err := proto.UnmarshalJSONEnum(RepeatedEnum_Color_value, data, "RepeatedEnum_Color") if err != nil { return err } *x = RepeatedEnum_Color(value) return nil } func (RepeatedEnum_Color) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{21, 0} } type GoEnum struct { Foo *FOO `protobuf:"varint,1,req,name=foo,enum=testdata.FOO" json:"foo,omitempty"` XXX_unrecognized []byte `json:"-"` } func (m *GoEnum) Reset() { *m = GoEnum{} } func (m *GoEnum) String() string { return proto.CompactTextString(m) } func (*GoEnum) ProtoMessage() {} func (*GoEnum) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } func (m *GoEnum) GetFoo() FOO { if m != nil && m.Foo != nil { return *m.Foo } return FOO_FOO1 } type GoTestField struct { Label *string `protobuf:"bytes,1,req,name=Label,json=label" json:"Label,omitempty"` Type *string `protobuf:"bytes,2,req,name=Type,json=type" json:"Type,omitempty"` XXX_unrecognized []byte `json:"-"` } func (m *GoTestField) Reset() { *m = GoTestField{} } func (m *GoTestField) String() string { return proto.CompactTextString(m) } func (*GoTestField) ProtoMessage() {} func (*GoTestField) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } func (m *GoTestField) GetLabel() string { if m != nil && m.Label != nil { return *m.Label } return "" } func (m *GoTestField) GetType() string { if m != nil && m.Type != nil { return *m.Type } return "" } type GoTest struct { // Some typical parameters Kind *GoTest_KIND `protobuf:"varint,1,req,name=Kind,json=kind,enum=testdata.GoTest_KIND" json:"Kind,omitempty"` Table *string `protobuf:"bytes,2,opt,name=Table,json=table" json:"Table,omitempty"` Param *int32 `protobuf:"varint,3,opt,name=Param,json=param" json:"Param,omitempty"` // Required, repeated and optional foreign fields. RequiredField *GoTestField `protobuf:"bytes,4,req,name=RequiredField,json=requiredField" json:"RequiredField,omitempty"` RepeatedField []*GoTestField `protobuf:"bytes,5,rep,name=RepeatedField,json=repeatedField" json:"RepeatedField,omitempty"` OptionalField *GoTestField `protobuf:"bytes,6,opt,name=OptionalField,json=optionalField" json:"OptionalField,omitempty"` // Required fields of all basic types F_BoolRequired *bool `protobuf:"varint,10,req,name=F_Bool_required,json=fBoolRequired" json:"F_Bool_required,omitempty"` F_Int32Required *int32 `protobuf:"varint,11,req,name=F_Int32_required,json=fInt32Required" json:"F_Int32_required,omitempty"` F_Int64Required *int64 `protobuf:"varint,12,req,name=F_Int64_required,json=fInt64Required" json:"F_Int64_required,omitempty"` F_Fixed32Required *uint32 `protobuf:"fixed32,13,req,name=F_Fixed32_required,json=fFixed32Required" json:"F_Fixed32_required,omitempty"` F_Fixed64Required *uint64 `protobuf:"fixed64,14,req,name=F_Fixed64_required,json=fFixed64Required" json:"F_Fixed64_required,omitempty"` F_Uint32Required *uint32 `protobuf:"varint,15,req,name=F_Uint32_required,json=fUint32Required" json:"F_Uint32_required,omitempty"` F_Uint64Required *uint64 `protobuf:"varint,16,req,name=F_Uint64_required,json=fUint64Required" json:"F_Uint64_required,omitempty"` F_FloatRequired *float32 `protobuf:"fixed32,17,req,name=F_Float_required,json=fFloatRequired" json:"F_Float_required,omitempty"` F_DoubleRequired *float64 `protobuf:"fixed64,18,req,name=F_Double_required,json=fDoubleRequired" json:"F_Double_required,omitempty"` F_StringRequired *string `protobuf:"bytes,19,req,name=F_String_required,json=fStringRequired" json:"F_String_required,omitempty"` F_BytesRequired []byte `protobuf:"bytes,101,req,name=F_Bytes_required,json=fBytesRequired" json:"F_Bytes_required,omitempty"` F_Sint32Required *int32 `protobuf:"zigzag32,102,req,name=F_Sint32_required,json=fSint32Required" json:"F_Sint32_required,omitempty"` F_Sint64Required *int64 `protobuf:"zigzag64,103,req,name=F_Sint64_required,json=fSint64Required" json:"F_Sint64_required,omitempty"` // Repeated fields of all basic types F_BoolRepeated []bool `protobuf:"varint,20,rep,name=F_Bool_repeated,json=fBoolRepeated" json:"F_Bool_repeated,omitempty"` F_Int32Repeated []int32 `protobuf:"varint,21,rep,name=F_Int32_repeated,json=fInt32Repeated" json:"F_Int32_repeated,omitempty"` F_Int64Repeated []int64 `protobuf:"varint,22,rep,name=F_Int64_repeated,json=fInt64Repeated" json:"F_Int64_repeated,omitempty"` F_Fixed32Repeated []uint32 `protobuf:"fixed32,23,rep,name=F_Fixed32_repeated,json=fFixed32Repeated" json:"F_Fixed32_repeated,omitempty"` F_Fixed64Repeated []uint64 `protobuf:"fixed64,24,rep,name=F_Fixed64_repeated,json=fFixed64Repeated" json:"F_Fixed64_repeated,omitempty"` F_Uint32Repeated []uint32 `protobuf:"varint,25,rep,name=F_Uint32_repeated,json=fUint32Repeated" json:"F_Uint32_repeated,omitempty"` F_Uint64Repeated []uint64 `protobuf:"varint,26,rep,name=F_Uint64_repeated,json=fUint64Repeated" json:"F_Uint64_repeated,omitempty"` F_FloatRepeated []float32 `protobuf:"fixed32,27,rep,name=F_Float_repeated,json=fFloatRepeated" json:"F_Float_repeated,omitempty"` F_DoubleRepeated []float64 `protobuf:"fixed64,28,rep,name=F_Double_repeated,json=fDoubleRepeated" json:"F_Double_repeated,omitempty"` F_StringRepeated []string `protobuf:"bytes,29,rep,name=F_String_repeated,json=fStringRepeated" json:"F_String_repeated,omitempty"` F_BytesRepeated [][]byte `protobuf:"bytes,201,rep,name=F_Bytes_repeated,json=fBytesRepeated" json:"F_Bytes_repeated,omitempty"` F_Sint32Repeated []int32 `protobuf:"zigzag32,202,rep,name=F_Sint32_repeated,json=fSint32Repeated" json:"F_Sint32_repeated,omitempty"` F_Sint64Repeated []int64 `protobuf:"zigzag64,203,rep,name=F_Sint64_repeated,json=fSint64Repeated" json:"F_Sint64_repeated,omitempty"` // Optional fields of all basic types F_BoolOptional *bool `protobuf:"varint,30,opt,name=F_Bool_optional,json=fBoolOptional" json:"F_Bool_optional,omitempty"` F_Int32Optional *int32 `protobuf:"varint,31,opt,name=F_Int32_optional,json=fInt32Optional" json:"F_Int32_optional,omitempty"` F_Int64Optional *int64 `protobuf:"varint,32,opt,name=F_Int64_optional,json=fInt64Optional" json:"F_Int64_optional,omitempty"` F_Fixed32Optional *uint32 `protobuf:"fixed32,33,opt,name=F_Fixed32_optional,json=fFixed32Optional" json:"F_Fixed32_optional,omitempty"` F_Fixed64Optional *uint64 `protobuf:"fixed64,34,opt,name=F_Fixed64_optional,json=fFixed64Optional" json:"F_Fixed64_optional,omitempty"` F_Uint32Optional *uint32 `protobuf:"varint,35,opt,name=F_Uint32_optional,json=fUint32Optional" json:"F_Uint32_optional,omitempty"` F_Uint64Optional *uint64 `protobuf:"varint,36,opt,name=F_Uint64_optional,json=fUint64Optional" json:"F_Uint64_optional,omitempty"` F_FloatOptional *float32 `protobuf:"fixed32,37,opt,name=F_Float_optional,json=fFloatOptional" json:"F_Float_optional,omitempty"` F_DoubleOptional *float64 `protobuf:"fixed64,38,opt,name=F_Double_optional,json=fDoubleOptional" json:"F_Double_optional,omitempty"` F_StringOptional *string `protobuf:"bytes,39,opt,name=F_String_optional,json=fStringOptional" json:"F_String_optional,omitempty"` F_BytesOptional []byte `protobuf:"bytes,301,opt,name=F_Bytes_optional,json=fBytesOptional" json:"F_Bytes_optional,omitempty"` F_Sint32Optional *int32 `protobuf:"zigzag32,302,opt,name=F_Sint32_optional,json=fSint32Optional" json:"F_Sint32_optional,omitempty"` F_Sint64Optional *int64 `protobuf:"zigzag64,303,opt,name=F_Sint64_optional,json=fSint64Optional" json:"F_Sint64_optional,omitempty"` // Default-valued fields of all basic types F_BoolDefaulted *bool `protobuf:"varint,40,opt,name=F_Bool_defaulted,json=fBoolDefaulted,def=1" json:"F_Bool_defaulted,omitempty"` F_Int32Defaulted *int32 `protobuf:"varint,41,opt,name=F_Int32_defaulted,json=fInt32Defaulted,def=32" json:"F_Int32_defaulted,omitempty"` F_Int64Defaulted *int64 `protobuf:"varint,42,opt,name=F_Int64_defaulted,json=fInt64Defaulted,def=64" json:"F_Int64_defaulted,omitempty"` F_Fixed32Defaulted *uint32 `protobuf:"fixed32,43,opt,name=F_Fixed32_defaulted,json=fFixed32Defaulted,def=320" json:"F_Fixed32_defaulted,omitempty"` F_Fixed64Defaulted *uint64 `protobuf:"fixed64,44,opt,name=F_Fixed64_defaulted,json=fFixed64Defaulted,def=640" json:"F_Fixed64_defaulted,omitempty"` F_Uint32Defaulted *uint32 `protobuf:"varint,45,opt,name=F_Uint32_defaulted,json=fUint32Defaulted,def=3200" json:"F_Uint32_defaulted,omitempty"` F_Uint64Defaulted *uint64 `protobuf:"varint,46,opt,name=F_Uint64_defaulted,json=fUint64Defaulted,def=6400" json:"F_Uint64_defaulted,omitempty"` F_FloatDefaulted *float32 `protobuf:"fixed32,47,opt,name=F_Float_defaulted,json=fFloatDefaulted,def=314159" json:"F_Float_defaulted,omitempty"` F_DoubleDefaulted *float64 `protobuf:"fixed64,48,opt,name=F_Double_defaulted,json=fDoubleDefaulted,def=271828" json:"F_Double_defaulted,omitempty"` F_StringDefaulted *string `protobuf:"bytes,49,opt,name=F_String_defaulted,json=fStringDefaulted,def=hello, \"world!\"\n" json:"F_String_defaulted,omitempty"` F_BytesDefaulted []byte `protobuf:"bytes,401,opt,name=F_Bytes_defaulted,json=fBytesDefaulted,def=Bignose" json:"F_Bytes_defaulted,omitempty"` F_Sint32Defaulted *int32 `protobuf:"zigzag32,402,opt,name=F_Sint32_defaulted,json=fSint32Defaulted,def=-32" json:"F_Sint32_defaulted,omitempty"` F_Sint64Defaulted *int64 `protobuf:"zigzag64,403,opt,name=F_Sint64_defaulted,json=fSint64Defaulted,def=-64" json:"F_Sint64_defaulted,omitempty"` // Packed repeated fields (no string or bytes). F_BoolRepeatedPacked []bool `protobuf:"varint,50,rep,packed,name=F_Bool_repeated_packed,json=fBoolRepeatedPacked" json:"F_Bool_repeated_packed,omitempty"` F_Int32RepeatedPacked []int32 `protobuf:"varint,51,rep,packed,name=F_Int32_repeated_packed,json=fInt32RepeatedPacked" json:"F_Int32_repeated_packed,omitempty"` F_Int64RepeatedPacked []int64 `protobuf:"varint,52,rep,packed,name=F_Int64_repeated_packed,json=fInt64RepeatedPacked" json:"F_Int64_repeated_packed,omitempty"` F_Fixed32RepeatedPacked []uint32 `protobuf:"fixed32,53,rep,packed,name=F_Fixed32_repeated_packed,json=fFixed32RepeatedPacked" json:"F_Fixed32_repeated_packed,omitempty"` F_Fixed64RepeatedPacked []uint64 `protobuf:"fixed64,54,rep,packed,name=F_Fixed64_repeated_packed,json=fFixed64RepeatedPacked" json:"F_Fixed64_repeated_packed,omitempty"` F_Uint32RepeatedPacked []uint32 `protobuf:"varint,55,rep,packed,name=F_Uint32_repeated_packed,json=fUint32RepeatedPacked" json:"F_Uint32_repeated_packed,omitempty"` F_Uint64RepeatedPacked []uint64 `protobuf:"varint,56,rep,packed,name=F_Uint64_repeated_packed,json=fUint64RepeatedPacked" json:"F_Uint64_repeated_packed,omitempty"` F_FloatRepeatedPacked []float32 `protobuf:"fixed32,57,rep,packed,name=F_Float_repeated_packed,json=fFloatRepeatedPacked" json:"F_Float_repeated_packed,omitempty"` F_DoubleRepeatedPacked []float64 `protobuf:"fixed64,58,rep,packed,name=F_Double_repeated_packed,json=fDoubleRepeatedPacked" json:"F_Double_repeated_packed,omitempty"` F_Sint32RepeatedPacked []int32 `protobuf:"zigzag32,502,rep,packed,name=F_Sint32_repeated_packed,json=fSint32RepeatedPacked" json:"F_Sint32_repeated_packed,omitempty"` F_Sint64RepeatedPacked []int64 `protobuf:"zigzag64,503,rep,packed,name=F_Sint64_repeated_packed,json=fSint64RepeatedPacked" json:"F_Sint64_repeated_packed,omitempty"` Requiredgroup *GoTest_RequiredGroup `protobuf:"group,70,req,name=RequiredGroup,json=requiredgroup" json:"requiredgroup,omitempty"` Repeatedgroup []*GoTest_RepeatedGroup `protobuf:"group,80,rep,name=RepeatedGroup,json=repeatedgroup" json:"repeatedgroup,omitempty"` Optionalgroup *GoTest_OptionalGroup `protobuf:"group,90,opt,name=OptionalGroup,json=optionalgroup" json:"optionalgroup,omitempty"` XXX_unrecognized []byte `json:"-"` } func (m *GoTest) Reset() { *m = GoTest{} } func (m *GoTest) String() string { return proto.CompactTextString(m) } func (*GoTest) ProtoMessage() {} func (*GoTest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} } const Default_GoTest_F_BoolDefaulted bool = true const Default_GoTest_F_Int32Defaulted int32 = 32 const Default_GoTest_F_Int64Defaulted int64 = 64 const Default_GoTest_F_Fixed32Defaulted uint32 = 320 const Default_GoTest_F_Fixed64Defaulted uint64 = 640 const Default_GoTest_F_Uint32Defaulted uint32 = 3200 const Default_GoTest_F_Uint64Defaulted uint64 = 6400 const Default_GoTest_F_FloatDefaulted float32 = 314159 const Default_GoTest_F_DoubleDefaulted float64 = 271828 const Default_GoTest_F_StringDefaulted string = "hello, \"world!\"\n" var Default_GoTest_F_BytesDefaulted []byte = []byte("Bignose") const Default_GoTest_F_Sint32Defaulted int32 = -32 const Default_GoTest_F_Sint64Defaulted int64 = -64 func (m *GoTest) GetKind() GoTest_KIND { if m != nil && m.Kind != nil { return *m.Kind } return GoTest_VOID } func (m *GoTest) GetTable() string { if m != nil && m.Table != nil { return *m.Table } return "" } func (m *GoTest) GetParam() int32 { if m != nil && m.Param != nil { return *m.Param } return 0 } func (m *GoTest) GetRequiredField() *GoTestField { if m != nil { return m.RequiredField } return nil } func (m *GoTest) GetRepeatedField() []*GoTestField { if m != nil { return m.RepeatedField } return nil } func (m *GoTest) GetOptionalField() *GoTestField { if m != nil { return m.OptionalField } return nil } func (m *GoTest) GetF_BoolRequired() bool { if m != nil && m.F_BoolRequired != nil { return *m.F_BoolRequired } return false } func (m *GoTest) GetF_Int32Required() int32 { if m != nil && m.F_Int32Required != nil { return *m.F_Int32Required } return 0 } func (m *GoTest) GetF_Int64Required() int64 { if m != nil && m.F_Int64Required != nil { return *m.F_Int64Required } return 0 } func (m *GoTest) GetF_Fixed32Required() uint32 { if m != nil && m.F_Fixed32Required != nil { return *m.F_Fixed32Required } return 0 } func (m *GoTest) GetF_Fixed64Required() uint64 { if m != nil && m.F_Fixed64Required != nil { return *m.F_Fixed64Required } return 0 } func (m *GoTest) GetF_Uint32Required() uint32 { if m != nil && m.F_Uint32Required != nil { return *m.F_Uint32Required } return 0 } func (m *GoTest) GetF_Uint64Required() uint64 { if m != nil && m.F_Uint64Required != nil { return *m.F_Uint64Required } return 0 } func (m *GoTest) GetF_FloatRequired() float32 { if m != nil && m.F_FloatRequired != nil { return *m.F_FloatRequired } return 0 } func (m *GoTest) GetF_DoubleRequired() float64 { if m != nil && m.F_DoubleRequired != nil { return *m.F_DoubleRequired } return 0 } func (m *GoTest) GetF_StringRequired() string { if m != nil && m.F_StringRequired != nil { return *m.F_StringRequired } return "" } func (m *GoTest) GetF_BytesRequired() []byte { if m != nil { return m.F_BytesRequired } return nil } func (m *GoTest) GetF_Sint32Required() int32 { if m != nil && m.F_Sint32Required != nil { return *m.F_Sint32Required } return 0 } func (m *GoTest) GetF_Sint64Required() int64 { if m != nil && m.F_Sint64Required != nil { return *m.F_Sint64Required } return 0 } func (m *GoTest) GetF_BoolRepeated() []bool { if m != nil { return m.F_BoolRepeated } return nil } func (m *GoTest) GetF_Int32Repeated() []int32 { if m != nil { return m.F_Int32Repeated } return nil } func (m *GoTest) GetF_Int64Repeated() []int64 { if m != nil { return m.F_Int64Repeated } return nil } func (m *GoTest) GetF_Fixed32Repeated() []uint32 { if m != nil { return m.F_Fixed32Repeated } return nil } func (m *GoTest) GetF_Fixed64Repeated() []uint64 { if m != nil { return m.F_Fixed64Repeated } return nil } func (m *GoTest) GetF_Uint32Repeated() []uint32 { if m != nil { return m.F_Uint32Repeated } return nil } func (m *GoTest) GetF_Uint64Repeated() []uint64 { if m != nil { return m.F_Uint64Repeated } return nil } func (m *GoTest) GetF_FloatRepeated() []float32 { if m != nil { return m.F_FloatRepeated } return nil } func (m *GoTest) GetF_DoubleRepeated() []float64 { if m != nil { return m.F_DoubleRepeated } return nil } func (m *GoTest) GetF_StringRepeated() []string { if m != nil { return m.F_StringRepeated } return nil } func (m *GoTest) GetF_BytesRepeated() [][]byte { if m != nil { return m.F_BytesRepeated } return nil } func (m *GoTest) GetF_Sint32Repeated() []int32 { if m != nil { return m.F_Sint32Repeated } return nil } func (m *GoTest) GetF_Sint64Repeated() []int64 { if m != nil { return m.F_Sint64Repeated } return nil } func (m *GoTest) GetF_BoolOptional() bool { if m != nil && m.F_BoolOptional != nil { return *m.F_BoolOptional } return false } func (m *GoTest) GetF_Int32Optional() int32 { if m != nil && m.F_Int32Optional != nil { return *m.F_Int32Optional } return 0 } func (m *GoTest) GetF_Int64Optional() int64 { if m != nil && m.F_Int64Optional != nil { return *m.F_Int64Optional } return 0 } func (m *GoTest) GetF_Fixed32Optional() uint32 { if m != nil && m.F_Fixed32Optional != nil { return *m.F_Fixed32Optional } return 0 } func (m *GoTest) GetF_Fixed64Optional() uint64 { if m != nil && m.F_Fixed64Optional != nil { return *m.F_Fixed64Optional } return 0 } func (m *GoTest) GetF_Uint32Optional() uint32 { if m != nil && m.F_Uint32Optional != nil { return *m.F_Uint32Optional } return 0 } func (m *GoTest) GetF_Uint64Optional() uint64 { if m != nil && m.F_Uint64Optional != nil { return *m.F_Uint64Optional } return 0 } func (m *GoTest) GetF_FloatOptional() float32 { if m != nil && m.F_FloatOptional != nil { return *m.F_FloatOptional } return 0 } func (m *GoTest) GetF_DoubleOptional() float64 { if m != nil && m.F_DoubleOptional != nil { return *m.F_DoubleOptional } return 0 } func (m *GoTest) GetF_StringOptional() string { if m != nil && m.F_StringOptional != nil { return *m.F_StringOptional } return "" } func (m *GoTest) GetF_BytesOptional() []byte { if m != nil { return m.F_BytesOptional } return nil } func (m *GoTest) GetF_Sint32Optional() int32 { if m != nil && m.F_Sint32Optional != nil { return *m.F_Sint32Optional } return 0 } func (m *GoTest) GetF_Sint64Optional() int64 { if m != nil && m.F_Sint64Optional != nil { return *m.F_Sint64Optional } return 0 } func (m *GoTest) GetF_BoolDefaulted() bool { if m != nil && m.F_BoolDefaulted != nil { return *m.F_BoolDefaulted } return Default_GoTest_F_BoolDefaulted } func (m *GoTest) GetF_Int32Defaulted() int32 { if m != nil && m.F_Int32Defaulted != nil { return *m.F_Int32Defaulted } return Default_GoTest_F_Int32Defaulted } func (m *GoTest) GetF_Int64Defaulted() int64 { if m != nil && m.F_Int64Defaulted != nil { return *m.F_Int64Defaulted } return Default_GoTest_F_Int64Defaulted } func (m *GoTest) GetF_Fixed32Defaulted() uint32 { if m != nil && m.F_Fixed32Defaulted != nil { return *m.F_Fixed32Defaulted } return Default_GoTest_F_Fixed32Defaulted } func (m *GoTest) GetF_Fixed64Defaulted() uint64 { if m != nil && m.F_Fixed64Defaulted != nil { return *m.F_Fixed64Defaulted } return Default_GoTest_F_Fixed64Defaulted } func (m *GoTest) GetF_Uint32Defaulted() uint32 { if m != nil && m.F_Uint32Defaulted != nil { return *m.F_Uint32Defaulted } return Default_GoTest_F_Uint32Defaulted } func (m *GoTest) GetF_Uint64Defaulted() uint64 { if m != nil && m.F_Uint64Defaulted != nil { return *m.F_Uint64Defaulted } return Default_GoTest_F_Uint64Defaulted } func (m *GoTest) GetF_FloatDefaulted() float32 { if m != nil && m.F_FloatDefaulted != nil { return *m.F_FloatDefaulted } return Default_GoTest_F_FloatDefaulted } func (m *GoTest) GetF_DoubleDefaulted() float64 { if m != nil && m.F_DoubleDefaulted != nil { return *m.F_DoubleDefaulted } return Default_GoTest_F_DoubleDefaulted } func (m *GoTest) GetF_StringDefaulted() string { if m != nil && m.F_StringDefaulted != nil { return *m.F_StringDefaulted } return Default_GoTest_F_StringDefaulted } func (m *GoTest) GetF_BytesDefaulted() []byte { if m != nil && m.F_BytesDefaulted != nil { return m.F_BytesDefaulted } return append([]byte(nil), Default_GoTest_F_BytesDefaulted...) } func (m *GoTest) GetF_Sint32Defaulted() int32 { if m != nil && m.F_Sint32Defaulted != nil { return *m.F_Sint32Defaulted } return Default_GoTest_F_Sint32Defaulted } func (m *GoTest) GetF_Sint64Defaulted() int64 { if m != nil && m.F_Sint64Defaulted != nil { return *m.F_Sint64Defaulted } return Default_GoTest_F_Sint64Defaulted } func (m *GoTest) GetF_BoolRepeatedPacked() []bool { if m != nil { return m.F_BoolRepeatedPacked } return nil } func (m *GoTest) GetF_Int32RepeatedPacked() []int32 { if m != nil { return m.F_Int32RepeatedPacked } return nil } func (m *GoTest) GetF_Int64RepeatedPacked() []int64 { if m != nil { return m.F_Int64RepeatedPacked } return nil } func (m *GoTest) GetF_Fixed32RepeatedPacked() []uint32 { if m != nil { return m.F_Fixed32RepeatedPacked } return nil } func (m *GoTest) GetF_Fixed64RepeatedPacked() []uint64 { if m != nil { return m.F_Fixed64RepeatedPacked } return nil } func (m *GoTest) GetF_Uint32RepeatedPacked() []uint32 { if m != nil { return m.F_Uint32RepeatedPacked } return nil } func (m *GoTest) GetF_Uint64RepeatedPacked() []uint64 { if m != nil { return m.F_Uint64RepeatedPacked } return nil } func (m *GoTest) GetF_FloatRepeatedPacked() []float32 { if m != nil { return m.F_FloatRepeatedPacked } return nil } func (m *GoTest) GetF_DoubleRepeatedPacked() []float64 { if m != nil { return m.F_DoubleRepeatedPacked } return nil } func (m *GoTest) GetF_Sint32RepeatedPacked() []int32 { if m != nil { return m.F_Sint32RepeatedPacked } return nil } func (m *GoTest) GetF_Sint64RepeatedPacked() []int64 { if m != nil { return m.F_Sint64RepeatedPacked } return nil } func (m *GoTest) GetRequiredgroup() *GoTest_RequiredGroup { if m != nil { return m.Requiredgroup } return nil } func (m *GoTest) GetRepeatedgroup() []*GoTest_RepeatedGroup { if m != nil { return m.Repeatedgroup } return nil } func (m *GoTest) GetOptionalgroup() *GoTest_OptionalGroup { if m != nil { return m.Optionalgroup } return nil } // Required, repeated, and optional groups. type GoTest_RequiredGroup struct { RequiredField *string `protobuf:"bytes,71,req,name=RequiredField,json=requiredField" json:"RequiredField,omitempty"` XXX_unrecognized []byte `json:"-"` } func (m *GoTest_RequiredGroup) Reset() { *m = GoTest_RequiredGroup{} } func (m *GoTest_RequiredGroup) String() string { return proto.CompactTextString(m) } func (*GoTest_RequiredGroup) ProtoMessage() {} func (*GoTest_RequiredGroup) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2, 0} } func (m *GoTest_RequiredGroup) GetRequiredField() string { if m != nil && m.RequiredField != nil { return *m.RequiredField } return "" } type GoTest_RepeatedGroup struct { RequiredField *string `protobuf:"bytes,81,req,name=RequiredField,json=requiredField" json:"RequiredField,omitempty"` XXX_unrecognized []byte `json:"-"` } func (m *GoTest_RepeatedGroup) Reset() { *m = GoTest_RepeatedGroup{} } func (m *GoTest_RepeatedGroup) String() string { return proto.CompactTextString(m) } func (*GoTest_RepeatedGroup) ProtoMessage() {} func (*GoTest_RepeatedGroup) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2, 1} } func (m *GoTest_RepeatedGroup) GetRequiredField() string { if m != nil && m.RequiredField != nil { return *m.RequiredField } return "" } type GoTest_OptionalGroup struct { RequiredField *string `protobuf:"bytes,91,req,name=RequiredField,json=requiredField" json:"RequiredField,omitempty"` XXX_unrecognized []byte `json:"-"` } func (m *GoTest_OptionalGroup) Reset() { *m = GoTest_OptionalGroup{} } func (m *GoTest_OptionalGroup) String() string { return proto.CompactTextString(m) } func (*GoTest_OptionalGroup) ProtoMessage() {} func (*GoTest_OptionalGroup) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2, 2} } func (m *GoTest_OptionalGroup) GetRequiredField() string { if m != nil && m.RequiredField != nil { return *m.RequiredField } return "" } // For testing skipping of unrecognized fields. // Numbers are all big, larger than tag numbers in GoTestField, // the message used in the corresponding test. type GoSkipTest struct { SkipInt32 *int32 `protobuf:"varint,11,req,name=skip_int32,json=skipInt32" json:"skip_int32,omitempty"` SkipFixed32 *uint32 `protobuf:"fixed32,12,req,name=skip_fixed32,json=skipFixed32" json:"skip_fixed32,omitempty"` SkipFixed64 *uint64 `protobuf:"fixed64,13,req,name=skip_fixed64,json=skipFixed64" json:"skip_fixed64,omitempty"` SkipString *string `protobuf:"bytes,14,req,name=skip_string,json=skipString" json:"skip_string,omitempty"` Skipgroup *GoSkipTest_SkipGroup `protobuf:"group,15,req,name=SkipGroup,json=skipgroup" json:"skipgroup,omitempty"` XXX_unrecognized []byte `json:"-"` } func (m *GoSkipTest) Reset() { *m = GoSkipTest{} } func (m *GoSkipTest) String() string { return proto.CompactTextString(m) } func (*GoSkipTest) ProtoMessage() {} func (*GoSkipTest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} } func (m *GoSkipTest) GetSkipInt32() int32 { if m != nil && m.SkipInt32 != nil { return *m.SkipInt32 } return 0 } func (m *GoSkipTest) GetSkipFixed32() uint32 { if m != nil && m.SkipFixed32 != nil { return *m.SkipFixed32 } return 0 } func (m *GoSkipTest) GetSkipFixed64() uint64 { if m != nil && m.SkipFixed64 != nil { return *m.SkipFixed64 } return 0 } func (m *GoSkipTest) GetSkipString() string { if m != nil && m.SkipString != nil { return *m.SkipString } return "" } func (m *GoSkipTest) GetSkipgroup() *GoSkipTest_SkipGroup { if m != nil { return m.Skipgroup } return nil } type GoSkipTest_SkipGroup struct { GroupInt32 *int32 `protobuf:"varint,16,req,name=group_int32,json=groupInt32" json:"group_int32,omitempty"` GroupString *string `protobuf:"bytes,17,req,name=group_string,json=groupString" json:"group_string,omitempty"` XXX_unrecognized []byte `json:"-"` } func (m *GoSkipTest_SkipGroup) Reset() { *m = GoSkipTest_SkipGroup{} } func (m *GoSkipTest_SkipGroup) String() string { return proto.CompactTextString(m) } func (*GoSkipTest_SkipGroup) ProtoMessage() {} func (*GoSkipTest_SkipGroup) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3, 0} } func (m *GoSkipTest_SkipGroup) GetGroupInt32() int32 { if m != nil && m.GroupInt32 != nil { return *m.GroupInt32 } return 0 } func (m *GoSkipTest_SkipGroup) GetGroupString() string { if m != nil && m.GroupString != nil { return *m.GroupString } return "" } // For testing packed/non-packed decoder switching. // A serialized instance of one should be deserializable as the other. type NonPackedTest struct { A []int32 `protobuf:"varint,1,rep,name=a" json:"a,omitempty"` XXX_unrecognized []byte `json:"-"` } func (m *NonPackedTest) Reset() { *m = NonPackedTest{} } func (m *NonPackedTest) String() string { return proto.CompactTextString(m) } func (*NonPackedTest) ProtoMessage() {} func (*NonPackedTest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} } func (m *NonPackedTest) GetA() []int32 { if m != nil { return m.A } return nil } type PackedTest struct { B []int32 `protobuf:"varint,1,rep,packed,name=b" json:"b,omitempty"` XXX_unrecognized []byte `json:"-"` } func (m *PackedTest) Reset() { *m = PackedTest{} } func (m *PackedTest) String() string { return proto.CompactTextString(m) } func (*PackedTest) ProtoMessage() {} func (*PackedTest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} } func (m *PackedTest) GetB() []int32 { if m != nil { return m.B } return nil } type MaxTag struct { // Maximum possible tag number. LastField *string `protobuf:"bytes,536870911,opt,name=last_field,json=lastField" json:"last_field,omitempty"` XXX_unrecognized []byte `json:"-"` } func (m *MaxTag) Reset() { *m = MaxTag{} } func (m *MaxTag) String() string { return proto.CompactTextString(m) } func (*MaxTag) ProtoMessage() {} func (*MaxTag) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{6} } func (m *MaxTag) GetLastField() string { if m != nil && m.LastField != nil { return *m.LastField } return "" } type OldMessage struct { Nested *OldMessage_Nested `protobuf:"bytes,1,opt,name=nested" json:"nested,omitempty"` Num *int32 `protobuf:"varint,2,opt,name=num" json:"num,omitempty"` XXX_unrecognized []byte `json:"-"` } func (m *OldMessage) Reset() { *m = OldMessage{} } func (m *OldMessage) String() string { return proto.CompactTextString(m) } func (*OldMessage) ProtoMessage() {} func (*OldMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{7} } func (m *OldMessage) GetNested() *OldMessage_Nested { if m != nil { return m.Nested } return nil } func (m *OldMessage) GetNum() int32 { if m != nil && m.Num != nil { return *m.Num } return 0 } type OldMessage_Nested struct { Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` XXX_unrecognized []byte `json:"-"` } func (m *OldMessage_Nested) Reset() { *m = OldMessage_Nested{} } func (m *OldMessage_Nested) String() string { return proto.CompactTextString(m) } func (*OldMessage_Nested) ProtoMessage() {} func (*OldMessage_Nested) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{7, 0} } func (m *OldMessage_Nested) GetName() string { if m != nil && m.Name != nil { return *m.Name } return "" } // NewMessage is wire compatible with OldMessage; // imagine it as a future version. type NewMessage struct { Nested *NewMessage_Nested `protobuf:"bytes,1,opt,name=nested" json:"nested,omitempty"` // This is an int32 in OldMessage. Num *int64 `protobuf:"varint,2,opt,name=num" json:"num,omitempty"` XXX_unrecognized []byte `json:"-"` } func (m *NewMessage) Reset() { *m = NewMessage{} } func (m *NewMessage) String() string { return proto.CompactTextString(m) } func (*NewMessage) ProtoMessage() {} func (*NewMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{8} } func (m *NewMessage) GetNested() *NewMessage_Nested { if m != nil { return m.Nested } return nil } func (m *NewMessage) GetNum() int64 { if m != nil && m.Num != nil { return *m.Num } return 0 } type NewMessage_Nested struct { Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` FoodGroup *string `protobuf:"bytes,2,opt,name=food_group,json=foodGroup" json:"food_group,omitempty"` XXX_unrecognized []byte `json:"-"` } func (m *NewMessage_Nested) Reset() { *m = NewMessage_Nested{} } func (m *NewMessage_Nested) String() string { return proto.CompactTextString(m) } func (*NewMessage_Nested) ProtoMessage() {} func (*NewMessage_Nested) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{8, 0} } func (m *NewMessage_Nested) GetName() string { if m != nil && m.Name != nil { return *m.Name } return "" } func (m *NewMessage_Nested) GetFoodGroup() string { if m != nil && m.FoodGroup != nil { return *m.FoodGroup } return "" } type InnerMessage struct { Host *string `protobuf:"bytes,1,req,name=host" json:"host,omitempty"` Port *int32 `protobuf:"varint,2,opt,name=port,def=4000" json:"port,omitempty"` Connected *bool `protobuf:"varint,3,opt,name=connected" json:"connected,omitempty"` XXX_unrecognized []byte `json:"-"` } func (m *InnerMessage) Reset() { *m = InnerMessage{} } func (m *InnerMessage) String() string { return proto.CompactTextString(m) } func (*InnerMessage) ProtoMessage() {} func (*InnerMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{9} } const Default_InnerMessage_Port int32 = 4000 func (m *InnerMessage) GetHost() string { if m != nil && m.Host != nil { return *m.Host } return "" } func (m *InnerMessage) GetPort() int32 { if m != nil && m.Port != nil { return *m.Port } return Default_InnerMessage_Port } func (m *InnerMessage) GetConnected() bool { if m != nil && m.Connected != nil { return *m.Connected } return false } type OtherMessage struct { Key *int64 `protobuf:"varint,1,opt,name=key" json:"key,omitempty"` Value []byte `protobuf:"bytes,2,opt,name=value" json:"value,omitempty"` Weight *float32 `protobuf:"fixed32,3,opt,name=weight" json:"weight,omitempty"` Inner *InnerMessage `protobuf:"bytes,4,opt,name=inner" json:"inner,omitempty"` XXX_extensions map[int32]proto.Extension `json:"-"` XXX_unrecognized []byte `json:"-"` } func (m *OtherMessage) Reset() { *m = OtherMessage{} } func (m *OtherMessage) String() string { return proto.CompactTextString(m) } func (*OtherMessage) ProtoMessage() {} func (*OtherMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{10} } var extRange_OtherMessage = []proto.ExtensionRange{ {100, 536870911}, } func (*OtherMessage) ExtensionRangeArray() []proto.ExtensionRange { return extRange_OtherMessage } func (m *OtherMessage) ExtensionMap() map[int32]proto.Extension { if m.XXX_extensions == nil { m.XXX_extensions = make(map[int32]proto.Extension) } return m.XXX_extensions } func (m *OtherMessage) GetKey() int64 { if m != nil && m.Key != nil { return *m.Key } return 0 } func (m *OtherMessage) GetValue() []byte { if m != nil { return m.Value } return nil } func (m *OtherMessage) GetWeight() float32 { if m != nil && m.Weight != nil { return *m.Weight } return 0 } func (m *OtherMessage) GetInner() *InnerMessage { if m != nil { return m.Inner } return nil } type MyMessage struct { Count *int32 `protobuf:"varint,1,req,name=count" json:"count,omitempty"` Name *string `protobuf:"bytes,2,opt,name=name" json:"name,omitempty"` Quote *string `protobuf:"bytes,3,opt,name=quote" json:"quote,omitempty"` Pet []string `protobuf:"bytes,4,rep,name=pet" json:"pet,omitempty"` Inner *InnerMessage `protobuf:"bytes,5,opt,name=inner" json:"inner,omitempty"` Others []*OtherMessage `protobuf:"bytes,6,rep,name=others" json:"others,omitempty"` RepInner []*InnerMessage `protobuf:"bytes,12,rep,name=rep_inner,json=repInner" json:"rep_inner,omitempty"` Bikeshed *MyMessage_Color `protobuf:"varint,7,opt,name=bikeshed,enum=testdata.MyMessage_Color" json:"bikeshed,omitempty"` Somegroup *MyMessage_SomeGroup `protobuf:"group,8,opt,name=SomeGroup,json=somegroup" json:"somegroup,omitempty"` // This field becomes [][]byte in the generated code. RepBytes [][]byte `protobuf:"bytes,10,rep,name=rep_bytes,json=repBytes" json:"rep_bytes,omitempty"` Bigfloat *float64 `protobuf:"fixed64,11,opt,name=bigfloat" json:"bigfloat,omitempty"` XXX_extensions map[int32]proto.Extension `json:"-"` XXX_unrecognized []byte `json:"-"` } func (m *MyMessage) Reset() { *m = MyMessage{} } func (m *MyMessage) String() string { return proto.CompactTextString(m) } func (*MyMessage) ProtoMessage() {} func (*MyMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{11} } var extRange_MyMessage = []proto.ExtensionRange{ {100, 536870911}, } func (*MyMessage) ExtensionRangeArray() []proto.ExtensionRange { return extRange_MyMessage } func (m *MyMessage) ExtensionMap() map[int32]proto.Extension { if m.XXX_extensions == nil { m.XXX_extensions = make(map[int32]proto.Extension) } return m.XXX_extensions } func (m *MyMessage) GetCount() int32 { if m != nil && m.Count != nil { return *m.Count } return 0 } func (m *MyMessage) GetName() string { if m != nil && m.Name != nil { return *m.Name } return "" } func (m *MyMessage) GetQuote() string { if m != nil && m.Quote != nil { return *m.Quote } return "" } func (m *MyMessage) GetPet() []string { if m != nil { return m.Pet } return nil } func (m *MyMessage) GetInner() *InnerMessage { if m != nil { return m.Inner } return nil } func (m *MyMessage) GetOthers() []*OtherMessage { if m != nil { return m.Others } return nil } func (m *MyMessage) GetRepInner() []*InnerMessage { if m != nil { return m.RepInner } return nil } func (m *MyMessage) GetBikeshed() MyMessage_Color { if m != nil && m.Bikeshed != nil { return *m.Bikeshed } return MyMessage_RED } func (m *MyMessage) GetSomegroup() *MyMessage_SomeGroup { if m != nil { return m.Somegroup } return nil } func (m *MyMessage) GetRepBytes() [][]byte { if m != nil { return m.RepBytes } return nil } func (m *MyMessage) GetBigfloat() float64 { if m != nil && m.Bigfloat != nil { return *m.Bigfloat } return 0 } type MyMessage_SomeGroup struct { GroupField *int32 `protobuf:"varint,9,opt,name=group_field,json=groupField" json:"group_field,omitempty"` XXX_unrecognized []byte `json:"-"` } func (m *MyMessage_SomeGroup) Reset() { *m = MyMessage_SomeGroup{} } func (m *MyMessage_SomeGroup) String() string { return proto.CompactTextString(m) } func (*MyMessage_SomeGroup) ProtoMessage() {} func (*MyMessage_SomeGroup) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{11, 0} } func (m *MyMessage_SomeGroup) GetGroupField() int32 { if m != nil && m.GroupField != nil { return *m.GroupField } return 0 } type Ext struct { Data *string `protobuf:"bytes,1,opt,name=data" json:"data,omitempty"` XXX_unrecognized []byte `json:"-"` } func (m *Ext) Reset() { *m = Ext{} } func (m *Ext) String() string { return proto.CompactTextString(m) } func (*Ext) ProtoMessage() {} func (*Ext) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{12} } func (m *Ext) GetData() string { if m != nil && m.Data != nil { return *m.Data } return "" } var E_Ext_More = &proto.ExtensionDesc{ ExtendedType: (*MyMessage)(nil), ExtensionType: (*Ext)(nil), Field: 103, Name: "testdata.Ext.more", Tag: "bytes,103,opt,name=more", } var E_Ext_Text = &proto.ExtensionDesc{ ExtendedType: (*MyMessage)(nil), ExtensionType: (*string)(nil), Field: 104, Name: "testdata.Ext.text", Tag: "bytes,104,opt,name=text", } var E_Ext_Number = &proto.ExtensionDesc{ ExtendedType: (*MyMessage)(nil), ExtensionType: (*int32)(nil), Field: 105, Name: "testdata.Ext.number", Tag: "varint,105,opt,name=number", } type ComplexExtension struct { First *int32 `protobuf:"varint,1,opt,name=first" json:"first,omitempty"` Second *int32 `protobuf:"varint,2,opt,name=second" json:"second,omitempty"` Third []int32 `protobuf:"varint,3,rep,name=third" json:"third,omitempty"` XXX_unrecognized []byte `json:"-"` } func (m *ComplexExtension) Reset() { *m = ComplexExtension{} } func (m *ComplexExtension) String() string { return proto.CompactTextString(m) } func (*ComplexExtension) ProtoMessage() {} func (*ComplexExtension) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{13} } func (m *ComplexExtension) GetFirst() int32 { if m != nil && m.First != nil { return *m.First } return 0 } func (m *ComplexExtension) GetSecond() int32 { if m != nil && m.Second != nil { return *m.Second } return 0 } func (m *ComplexExtension) GetThird() []int32 { if m != nil { return m.Third } return nil } type DefaultsMessage struct { XXX_extensions map[int32]proto.Extension `json:"-"` XXX_unrecognized []byte `json:"-"` } func (m *DefaultsMessage) Reset() { *m = DefaultsMessage{} } func (m *DefaultsMessage) String() string { return proto.CompactTextString(m) } func (*DefaultsMessage) ProtoMessage() {} func (*DefaultsMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{14} } var extRange_DefaultsMessage = []proto.ExtensionRange{ {100, 536870911}, } func (*DefaultsMessage) ExtensionRangeArray() []proto.ExtensionRange { return extRange_DefaultsMessage } func (m *DefaultsMessage) ExtensionMap() map[int32]proto.Extension { if m.XXX_extensions == nil { m.XXX_extensions = make(map[int32]proto.Extension) } return m.XXX_extensions } type MyMessageSet struct { XXX_extensions map[int32]proto.Extension `json:"-"` XXX_unrecognized []byte `json:"-"` } func (m *MyMessageSet) Reset() { *m = MyMessageSet{} } func (m *MyMessageSet) String() string { return proto.CompactTextString(m) } func (*MyMessageSet) ProtoMessage() {} func (*MyMessageSet) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{15} } func (m *MyMessageSet) Marshal() ([]byte, error) { return proto.MarshalMessageSet(m.ExtensionMap()) } func (m *MyMessageSet) Unmarshal(buf []byte) error { return proto.UnmarshalMessageSet(buf, m.ExtensionMap()) } func (m *MyMessageSet) MarshalJSON() ([]byte, error) { return proto.MarshalMessageSetJSON(m.XXX_extensions) } func (m *MyMessageSet) UnmarshalJSON(buf []byte) error { return proto.UnmarshalMessageSetJSON(buf, m.XXX_extensions) } // ensure MyMessageSet satisfies proto.Marshaler and proto.Unmarshaler var _ proto.Marshaler = (*MyMessageSet)(nil) var _ proto.Unmarshaler = (*MyMessageSet)(nil) var extRange_MyMessageSet = []proto.ExtensionRange{ {100, 2147483646}, } func (*MyMessageSet) ExtensionRangeArray() []proto.ExtensionRange { return extRange_MyMessageSet } func (m *MyMessageSet) ExtensionMap() map[int32]proto.Extension { if m.XXX_extensions == nil { m.XXX_extensions = make(map[int32]proto.Extension) } return m.XXX_extensions } type Empty struct { XXX_unrecognized []byte `json:"-"` } func (m *Empty) Reset() { *m = Empty{} } func (m *Empty) String() string { return proto.CompactTextString(m) } func (*Empty) ProtoMessage() {} func (*Empty) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{16} } type MessageList struct { Message []*MessageList_Message `protobuf:"group,1,rep,name=Message,json=message" json:"message,omitempty"` XXX_unrecognized []byte `json:"-"` } func (m *MessageList) Reset() { *m = MessageList{} } func (m *MessageList) String() string { return proto.CompactTextString(m) } func (*MessageList) ProtoMessage() {} func (*MessageList) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{17} } func (m *MessageList) GetMessage() []*MessageList_Message { if m != nil { return m.Message } return nil } type MessageList_Message struct { Name *string `protobuf:"bytes,2,req,name=name" json:"name,omitempty"` Count *int32 `protobuf:"varint,3,req,name=count" json:"count,omitempty"` XXX_unrecognized []byte `json:"-"` } func (m *MessageList_Message) Reset() { *m = MessageList_Message{} } func (m *MessageList_Message) String() string { return proto.CompactTextString(m) } func (*MessageList_Message) ProtoMessage() {} func (*MessageList_Message) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{17, 0} } func (m *MessageList_Message) GetName() string { if m != nil && m.Name != nil { return *m.Name } return "" } func (m *MessageList_Message) GetCount() int32 { if m != nil && m.Count != nil { return *m.Count } return 0 } type Strings struct { StringField *string `protobuf:"bytes,1,opt,name=string_field,json=stringField" json:"string_field,omitempty"` BytesField []byte `protobuf:"bytes,2,opt,name=bytes_field,json=bytesField" json:"bytes_field,omitempty"` XXX_unrecognized []byte `json:"-"` } func (m *Strings) Reset() { *m = Strings{} } func (m *Strings) String() string { return proto.CompactTextString(m) } func (*Strings) ProtoMessage() {} func (*Strings) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{18} } func (m *Strings) GetStringField() string { if m != nil && m.StringField != nil { return *m.StringField } return "" } func (m *Strings) GetBytesField() []byte { if m != nil { return m.BytesField } return nil } type Defaults struct { // Default-valued fields of all basic types. // Same as GoTest, but copied here to make testing easier. F_Bool *bool `protobuf:"varint,1,opt,name=F_Bool,json=fBool,def=1" json:"F_Bool,omitempty"` F_Int32 *int32 `protobuf:"varint,2,opt,name=F_Int32,json=fInt32,def=32" json:"F_Int32,omitempty"` F_Int64 *int64 `protobuf:"varint,3,opt,name=F_Int64,json=fInt64,def=64" json:"F_Int64,omitempty"` F_Fixed32 *uint32 `protobuf:"fixed32,4,opt,name=F_Fixed32,json=fFixed32,def=320" json:"F_Fixed32,omitempty"` F_Fixed64 *uint64 `protobuf:"fixed64,5,opt,name=F_Fixed64,json=fFixed64,def=640" json:"F_Fixed64,omitempty"` F_Uint32 *uint32 `protobuf:"varint,6,opt,name=F_Uint32,json=fUint32,def=3200" json:"F_Uint32,omitempty"` F_Uint64 *uint64 `protobuf:"varint,7,opt,name=F_Uint64,json=fUint64,def=6400" json:"F_Uint64,omitempty"` F_Float *float32 `protobuf:"fixed32,8,opt,name=F_Float,json=fFloat,def=314159" json:"F_Float,omitempty"` F_Double *float64 `protobuf:"fixed64,9,opt,name=F_Double,json=fDouble,def=271828" json:"F_Double,omitempty"` F_String *string `protobuf:"bytes,10,opt,name=F_String,json=fString,def=hello, \"world!\"\n" json:"F_String,omitempty"` F_Bytes []byte `protobuf:"bytes,11,opt,name=F_Bytes,json=fBytes,def=Bignose" json:"F_Bytes,omitempty"` F_Sint32 *int32 `protobuf:"zigzag32,12,opt,name=F_Sint32,json=fSint32,def=-32" json:"F_Sint32,omitempty"` F_Sint64 *int64 `protobuf:"zigzag64,13,opt,name=F_Sint64,json=fSint64,def=-64" json:"F_Sint64,omitempty"` F_Enum *Defaults_Color `protobuf:"varint,14,opt,name=F_Enum,json=fEnum,enum=testdata.Defaults_Color,def=1" json:"F_Enum,omitempty"` // More fields with crazy defaults. F_Pinf *float32 `protobuf:"fixed32,15,opt,name=F_Pinf,json=fPinf,def=inf" json:"F_Pinf,omitempty"` F_Ninf *float32 `protobuf:"fixed32,16,opt,name=F_Ninf,json=fNinf,def=-inf" json:"F_Ninf,omitempty"` F_Nan *float32 `protobuf:"fixed32,17,opt,name=F_Nan,json=fNan,def=nan" json:"F_Nan,omitempty"` // Sub-message. Sub *SubDefaults `protobuf:"bytes,18,opt,name=sub" json:"sub,omitempty"` // Redundant but explicit defaults. StrZero *string `protobuf:"bytes,19,opt,name=str_zero,json=strZero,def=" json:"str_zero,omitempty"` XXX_unrecognized []byte `json:"-"` } func (m *Defaults) Reset() { *m = Defaults{} } func (m *Defaults) String() string { return proto.CompactTextString(m) } func (*Defaults) ProtoMessage() {} func (*Defaults) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{19} } const Default_Defaults_F_Bool bool = true const Default_Defaults_F_Int32 int32 = 32 const Default_Defaults_F_Int64 int64 = 64 const Default_Defaults_F_Fixed32 uint32 = 320 const Default_Defaults_F_Fixed64 uint64 = 640 const Default_Defaults_F_Uint32 uint32 = 3200 const Default_Defaults_F_Uint64 uint64 = 6400 const Default_Defaults_F_Float float32 = 314159 const Default_Defaults_F_Double float64 = 271828 const Default_Defaults_F_String string = "hello, \"world!\"\n" var Default_Defaults_F_Bytes []byte = []byte("Bignose") const Default_Defaults_F_Sint32 int32 = -32 const Default_Defaults_F_Sint64 int64 = -64 const Default_Defaults_F_Enum Defaults_Color = Defaults_GREEN var Default_Defaults_F_Pinf float32 = float32(math.Inf(1)) var Default_Defaults_F_Ninf float32 = float32(math.Inf(-1)) var Default_Defaults_F_Nan float32 = float32(math.NaN()) func (m *Defaults) GetF_Bool() bool { if m != nil && m.F_Bool != nil { return *m.F_Bool } return Default_Defaults_F_Bool } func (m *Defaults) GetF_Int32() int32 { if m != nil && m.F_Int32 != nil { return *m.F_Int32 } return Default_Defaults_F_Int32 } func (m *Defaults) GetF_Int64() int64 { if m != nil && m.F_Int64 != nil { return *m.F_Int64 } return Default_Defaults_F_Int64 } func (m *Defaults) GetF_Fixed32() uint32 { if m != nil && m.F_Fixed32 != nil { return *m.F_Fixed32 } return Default_Defaults_F_Fixed32 } func (m *Defaults) GetF_Fixed64() uint64 { if m != nil && m.F_Fixed64 != nil { return *m.F_Fixed64 } return Default_Defaults_F_Fixed64 } func (m *Defaults) GetF_Uint32() uint32 { if m != nil && m.F_Uint32 != nil { return *m.F_Uint32 } return Default_Defaults_F_Uint32 } func (m *Defaults) GetF_Uint64() uint64 { if m != nil && m.F_Uint64 != nil { return *m.F_Uint64 } return Default_Defaults_F_Uint64 } func (m *Defaults) GetF_Float() float32 { if m != nil && m.F_Float != nil { return *m.F_Float } return Default_Defaults_F_Float } func (m *Defaults) GetF_Double() float64 { if m != nil && m.F_Double != nil { return *m.F_Double } return Default_Defaults_F_Double } func (m *Defaults) GetF_String() string { if m != nil && m.F_String != nil { return *m.F_String } return Default_Defaults_F_String } func (m *Defaults) GetF_Bytes() []byte { if m != nil && m.F_Bytes != nil { return m.F_Bytes } return append([]byte(nil), Default_Defaults_F_Bytes...) } func (m *Defaults) GetF_Sint32() int32 { if m != nil && m.F_Sint32 != nil { return *m.F_Sint32 } return Default_Defaults_F_Sint32 } func (m *Defaults) GetF_Sint64() int64 { if m != nil && m.F_Sint64 != nil { return *m.F_Sint64 } return Default_Defaults_F_Sint64 } func (m *Defaults) GetF_Enum() Defaults_Color { if m != nil && m.F_Enum != nil { return *m.F_Enum } return Default_Defaults_F_Enum } func (m *Defaults) GetF_Pinf() float32 { if m != nil && m.F_Pinf != nil { return *m.F_Pinf } return Default_Defaults_F_Pinf } func (m *Defaults) GetF_Ninf() float32 { if m != nil && m.F_Ninf != nil { return *m.F_Ninf } return Default_Defaults_F_Ninf } func (m *Defaults) GetF_Nan() float32 { if m != nil && m.F_Nan != nil { return *m.F_Nan } return Default_Defaults_F_Nan } func (m *Defaults) GetSub() *SubDefaults { if m != nil { return m.Sub } return nil } func (m *Defaults) GetStrZero() string { if m != nil && m.StrZero != nil { return *m.StrZero } return "" } type SubDefaults struct { N *int64 `protobuf:"varint,1,opt,name=n,def=7" json:"n,omitempty"` XXX_unrecognized []byte `json:"-"` } func (m *SubDefaults) Reset() { *m = SubDefaults{} } func (m *SubDefaults) String() string { return proto.CompactTextString(m) } func (*SubDefaults) ProtoMessage() {} func (*SubDefaults) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{20} } const Default_SubDefaults_N int64 = 7 func (m *SubDefaults) GetN() int64 { if m != nil && m.N != nil { return *m.N } return Default_SubDefaults_N } type RepeatedEnum struct { Color []RepeatedEnum_Color `protobuf:"varint,1,rep,name=color,enum=testdata.RepeatedEnum_Color" json:"color,omitempty"` XXX_unrecognized []byte `json:"-"` } func (m *RepeatedEnum) Reset() { *m = RepeatedEnum{} } func (m *RepeatedEnum) String() string { return proto.CompactTextString(m) } func (*RepeatedEnum) ProtoMessage() {} func (*RepeatedEnum) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{21} } func (m *RepeatedEnum) GetColor() []RepeatedEnum_Color { if m != nil { return m.Color } return nil } type MoreRepeated struct { Bools []bool `protobuf:"varint,1,rep,name=bools" json:"bools,omitempty"` BoolsPacked []bool `protobuf:"varint,2,rep,packed,name=bools_packed,json=boolsPacked" json:"bools_packed,omitempty"` Ints []int32 `protobuf:"varint,3,rep,name=ints" json:"ints,omitempty"` IntsPacked []int32 `protobuf:"varint,4,rep,packed,name=ints_packed,json=intsPacked" json:"ints_packed,omitempty"` Int64SPacked []int64 `protobuf:"varint,7,rep,packed,name=int64s_packed,json=int64sPacked" json:"int64s_packed,omitempty"` Strings []string `protobuf:"bytes,5,rep,name=strings" json:"strings,omitempty"` Fixeds []uint32 `protobuf:"fixed32,6,rep,name=fixeds" json:"fixeds,omitempty"` XXX_unrecognized []byte `json:"-"` } func (m *MoreRepeated) Reset() { *m = MoreRepeated{} } func (m *MoreRepeated) String() string { return proto.CompactTextString(m) } func (*MoreRepeated) ProtoMessage() {} func (*MoreRepeated) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{22} } func (m *MoreRepeated) GetBools() []bool { if m != nil { return m.Bools } return nil } func (m *MoreRepeated) GetBoolsPacked() []bool { if m != nil { return m.BoolsPacked } return nil } func (m *MoreRepeated) GetInts() []int32 { if m != nil { return m.Ints } return nil } func (m *MoreRepeated) GetIntsPacked() []int32 { if m != nil { return m.IntsPacked } return nil } func (m *MoreRepeated) GetInt64SPacked() []int64 { if m != nil { return m.Int64SPacked } return nil } func (m *MoreRepeated) GetStrings() []string { if m != nil { return m.Strings } return nil } func (m *MoreRepeated) GetFixeds() []uint32 { if m != nil { return m.Fixeds } return nil } type GroupOld struct { G *GroupOld_G `protobuf:"group,101,opt,name=G,json=g" json:"g,omitempty"` XXX_unrecognized []byte `json:"-"` } func (m *GroupOld) Reset() { *m = GroupOld{} } func (m *GroupOld) String() string { return proto.CompactTextString(m) } func (*GroupOld) ProtoMessage() {} func (*GroupOld) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{23} } func (m *GroupOld) GetG() *GroupOld_G { if m != nil { return m.G } return nil } type GroupOld_G struct { X *int32 `protobuf:"varint,2,opt,name=x" json:"x,omitempty"` XXX_unrecognized []byte `json:"-"` } func (m *GroupOld_G) Reset() { *m = GroupOld_G{} } func (m *GroupOld_G) String() string { return proto.CompactTextString(m) } func (*GroupOld_G) ProtoMessage() {} func (*GroupOld_G) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{23, 0} } func (m *GroupOld_G) GetX() int32 { if m != nil && m.X != nil { return *m.X } return 0 } type GroupNew struct { G *GroupNew_G `protobuf:"group,101,opt,name=G,json=g" json:"g,omitempty"` XXX_unrecognized []byte `json:"-"` } func (m *GroupNew) Reset() { *m = GroupNew{} } func (m *GroupNew) String() string { return proto.CompactTextString(m) } func (*GroupNew) ProtoMessage() {} func (*GroupNew) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{24} } func (m *GroupNew) GetG() *GroupNew_G { if m != nil { return m.G } return nil } type GroupNew_G struct { X *int32 `protobuf:"varint,2,opt,name=x" json:"x,omitempty"` Y *int32 `protobuf:"varint,3,opt,name=y" json:"y,omitempty"` XXX_unrecognized []byte `json:"-"` } func (m *GroupNew_G) Reset() { *m = GroupNew_G{} } func (m *GroupNew_G) String() string { return proto.CompactTextString(m) } func (*GroupNew_G) ProtoMessage() {} func (*GroupNew_G) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{24, 0} } func (m *GroupNew_G) GetX() int32 { if m != nil && m.X != nil { return *m.X } return 0 } func (m *GroupNew_G) GetY() int32 { if m != nil && m.Y != nil { return *m.Y } return 0 } type FloatingPoint struct { F *float64 `protobuf:"fixed64,1,req,name=f" json:"f,omitempty"` XXX_unrecognized []byte `json:"-"` } func (m *FloatingPoint) Reset() { *m = FloatingPoint{} } func (m *FloatingPoint) String() string { return proto.CompactTextString(m) } func (*FloatingPoint) ProtoMessage() {} func (*FloatingPoint) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{25} } func (m *FloatingPoint) GetF() float64 { if m != nil && m.F != nil { return *m.F } return 0 } type MessageWithMap struct { NameMapping map[int32]string `protobuf:"bytes,1,rep,name=name_mapping,json=nameMapping" json:"name_mapping,omitempty" protobuf_key:"varint,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` MsgMapping map[int64]*FloatingPoint `protobuf:"bytes,2,rep,name=msg_mapping,json=msgMapping" json:"msg_mapping,omitempty" protobuf_key:"zigzag64,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` ByteMapping map[bool][]byte `protobuf:"bytes,3,rep,name=byte_mapping,json=byteMapping" json:"byte_mapping,omitempty" protobuf_key:"varint,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` StrToStr map[string]string `protobuf:"bytes,4,rep,name=str_to_str,json=strToStr" json:"str_to_str,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` XXX_unrecognized []byte `json:"-"` } func (m *MessageWithMap) Reset() { *m = MessageWithMap{} } func (m *MessageWithMap) String() string { return proto.CompactTextString(m) } func (*MessageWithMap) ProtoMessage() {} func (*MessageWithMap) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{26} } func (m *MessageWithMap) GetNameMapping() map[int32]string { if m != nil { return m.NameMapping } return nil } func (m *MessageWithMap) GetMsgMapping() map[int64]*FloatingPoint { if m != nil { return m.MsgMapping } return nil } func (m *MessageWithMap) GetByteMapping() map[bool][]byte { if m != nil { return m.ByteMapping } return nil } func (m *MessageWithMap) GetStrToStr() map[string]string { if m != nil { return m.StrToStr } return nil } type Oneof struct { // Types that are valid to be assigned to Union: // *Oneof_F_Bool // *Oneof_F_Int32 // *Oneof_F_Int64 // *Oneof_F_Fixed32 // *Oneof_F_Fixed64 // *Oneof_F_Uint32 // *Oneof_F_Uint64 // *Oneof_F_Float // *Oneof_F_Double // *Oneof_F_String // *Oneof_F_Bytes // *Oneof_F_Sint32 // *Oneof_F_Sint64 // *Oneof_F_Enum // *Oneof_F_Message // *Oneof_FGroup // *Oneof_F_Largest_Tag Union isOneof_Union `protobuf_oneof:"union"` // Types that are valid to be assigned to Tormato: // *Oneof_Value Tormato isOneof_Tormato `protobuf_oneof:"tormato"` XXX_unrecognized []byte `json:"-"` } func (m *Oneof) Reset() { *m = Oneof{} } func (m *Oneof) String() string { return proto.CompactTextString(m) } func (*Oneof) ProtoMessage() {} func (*Oneof) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{27} } type isOneof_Union interface { isOneof_Union() } type isOneof_Tormato interface { isOneof_Tormato() } type Oneof_F_Bool struct { F_Bool bool `protobuf:"varint,1,opt,name=F_Bool,json=fBool,oneof"` } type Oneof_F_Int32 struct { F_Int32 int32 `protobuf:"varint,2,opt,name=F_Int32,json=fInt32,oneof"` } type Oneof_F_Int64 struct { F_Int64 int64 `protobuf:"varint,3,opt,name=F_Int64,json=fInt64,oneof"` } type Oneof_F_Fixed32 struct { F_Fixed32 uint32 `protobuf:"fixed32,4,opt,name=F_Fixed32,json=fFixed32,oneof"` } type Oneof_F_Fixed64 struct { F_Fixed64 uint64 `protobuf:"fixed64,5,opt,name=F_Fixed64,json=fFixed64,oneof"` } type Oneof_F_Uint32 struct { F_Uint32 uint32 `protobuf:"varint,6,opt,name=F_Uint32,json=fUint32,oneof"` } type Oneof_F_Uint64 struct { F_Uint64 uint64 `protobuf:"varint,7,opt,name=F_Uint64,json=fUint64,oneof"` } type Oneof_F_Float struct { F_Float float32 `protobuf:"fixed32,8,opt,name=F_Float,json=fFloat,oneof"` } type Oneof_F_Double struct { F_Double float64 `protobuf:"fixed64,9,opt,name=F_Double,json=fDouble,oneof"` } type Oneof_F_String struct { F_String string `protobuf:"bytes,10,opt,name=F_String,json=fString,oneof"` } type Oneof_F_Bytes struct { F_Bytes []byte `protobuf:"bytes,11,opt,name=F_Bytes,json=fBytes,oneof"` } type Oneof_F_Sint32 struct { F_Sint32 int32 `protobuf:"zigzag32,12,opt,name=F_Sint32,json=fSint32,oneof"` } type Oneof_F_Sint64 struct { F_Sint64 int64 `protobuf:"zigzag64,13,opt,name=F_Sint64,json=fSint64,oneof"` } type Oneof_F_Enum struct { F_Enum MyMessage_Color `protobuf:"varint,14,opt,name=F_Enum,json=fEnum,enum=testdata.MyMessage_Color,oneof"` } type Oneof_F_Message struct { F_Message *GoTestField `protobuf:"bytes,15,opt,name=F_Message,json=fMessage,oneof"` } type Oneof_FGroup struct { FGroup *Oneof_F_Group `protobuf:"group,16,opt,name=F_Group,json=fGroup,oneof"` } type Oneof_F_Largest_Tag struct { F_Largest_Tag int32 `protobuf:"varint,536870911,opt,name=F_Largest_Tag,json=fLargestTag,oneof"` } type Oneof_Value struct { Value int32 `protobuf:"varint,100,opt,name=value,oneof"` } func (*Oneof_F_Bool) isOneof_Union() {} func (*Oneof_F_Int32) isOneof_Union() {} func (*Oneof_F_Int64) isOneof_Union() {} func (*Oneof_F_Fixed32) isOneof_Union() {} func (*Oneof_F_Fixed64) isOneof_Union() {} func (*Oneof_F_Uint32) isOneof_Union() {} func (*Oneof_F_Uint64) isOneof_Union() {} func (*Oneof_F_Float) isOneof_Union() {} func (*Oneof_F_Double) isOneof_Union() {} func (*Oneof_F_String) isOneof_Union() {} func (*Oneof_F_Bytes) isOneof_Union() {} func (*Oneof_F_Sint32) isOneof_Union() {} func (*Oneof_F_Sint64) isOneof_Union() {} func (*Oneof_F_Enum) isOneof_Union() {} func (*Oneof_F_Message) isOneof_Union() {} func (*Oneof_FGroup) isOneof_Union() {} func (*Oneof_F_Largest_Tag) isOneof_Union() {} func (*Oneof_Value) isOneof_Tormato() {} func (m *Oneof) GetUnion() isOneof_Union { if m != nil { return m.Union } return nil } func (m *Oneof) GetTormato() isOneof_Tormato { if m != nil { return m.Tormato } return nil } func (m *Oneof) GetF_Bool() bool { if x, ok := m.GetUnion().(*Oneof_F_Bool); ok { return x.F_Bool } return false } func (m *Oneof) GetF_Int32() int32 { if x, ok := m.GetUnion().(*Oneof_F_Int32); ok { return x.F_Int32 } return 0 } func (m *Oneof) GetF_Int64() int64 { if x, ok := m.GetUnion().(*Oneof_F_Int64); ok { return x.F_Int64 } return 0 } func (m *Oneof) GetF_Fixed32() uint32 { if x, ok := m.GetUnion().(*Oneof_F_Fixed32); ok { return x.F_Fixed32 } return 0 } func (m *Oneof) GetF_Fixed64() uint64 { if x, ok := m.GetUnion().(*Oneof_F_Fixed64); ok { return x.F_Fixed64 } return 0 } func (m *Oneof) GetF_Uint32() uint32 { if x, ok := m.GetUnion().(*Oneof_F_Uint32); ok { return x.F_Uint32 } return 0 } func (m *Oneof) GetF_Uint64() uint64 { if x, ok := m.GetUnion().(*Oneof_F_Uint64); ok { return x.F_Uint64 } return 0 } func (m *Oneof) GetF_Float() float32 { if x, ok := m.GetUnion().(*Oneof_F_Float); ok { return x.F_Float } return 0 } func (m *Oneof) GetF_Double() float64 { if x, ok := m.GetUnion().(*Oneof_F_Double); ok { return x.F_Double } return 0 } func (m *Oneof) GetF_String() string { if x, ok := m.GetUnion().(*Oneof_F_String); ok { return x.F_String } return "" } func (m *Oneof) GetF_Bytes() []byte { if x, ok := m.GetUnion().(*Oneof_F_Bytes); ok { return x.F_Bytes } return nil } func (m *Oneof) GetF_Sint32() int32 { if x, ok := m.GetUnion().(*Oneof_F_Sint32); ok { return x.F_Sint32 } return 0 } func (m *Oneof) GetF_Sint64() int64 { if x, ok := m.GetUnion().(*Oneof_F_Sint64); ok { return x.F_Sint64 } return 0 } func (m *Oneof) GetF_Enum() MyMessage_Color { if x, ok := m.GetUnion().(*Oneof_F_Enum); ok { return x.F_Enum } return MyMessage_RED } func (m *Oneof) GetF_Message() *GoTestField { if x, ok := m.GetUnion().(*Oneof_F_Message); ok { return x.F_Message } return nil } func (m *Oneof) GetFGroup() *Oneof_F_Group { if x, ok := m.GetUnion().(*Oneof_FGroup); ok { return x.FGroup } return nil } func (m *Oneof) GetF_Largest_Tag() int32 { if x, ok := m.GetUnion().(*Oneof_F_Largest_Tag); ok { return x.F_Largest_Tag } return 0 } func (m *Oneof) GetValue() int32 { if x, ok := m.GetTormato().(*Oneof_Value); ok { return x.Value } return 0 } // XXX_OneofFuncs is for the internal use of the proto package. func (*Oneof) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) { return _Oneof_OneofMarshaler, _Oneof_OneofUnmarshaler, _Oneof_OneofSizer, []interface{}{ (*Oneof_F_Bool)(nil), (*Oneof_F_Int32)(nil), (*Oneof_F_Int64)(nil), (*Oneof_F_Fixed32)(nil), (*Oneof_F_Fixed64)(nil), (*Oneof_F_Uint32)(nil), (*Oneof_F_Uint64)(nil), (*Oneof_F_Float)(nil), (*Oneof_F_Double)(nil), (*Oneof_F_String)(nil), (*Oneof_F_Bytes)(nil), (*Oneof_F_Sint32)(nil), (*Oneof_F_Sint64)(nil), (*Oneof_F_Enum)(nil), (*Oneof_F_Message)(nil), (*Oneof_FGroup)(nil), (*Oneof_F_Largest_Tag)(nil), (*Oneof_Value)(nil), } } func _Oneof_OneofMarshaler(msg proto.Message, b *proto.Buffer) error { m := msg.(*Oneof) // union switch x := m.Union.(type) { case *Oneof_F_Bool: t := uint64(0) if x.F_Bool { t = 1 } b.EncodeVarint(1<<3 | proto.WireVarint) b.EncodeVarint(t) case *Oneof_F_Int32: b.EncodeVarint(2<<3 | proto.WireVarint) b.EncodeVarint(uint64(x.F_Int32)) case *Oneof_F_Int64: b.EncodeVarint(3<<3 | proto.WireVarint) b.EncodeVarint(uint64(x.F_Int64)) case *Oneof_F_Fixed32: b.EncodeVarint(4<<3 | proto.WireFixed32) b.EncodeFixed32(uint64(x.F_Fixed32)) case *Oneof_F_Fixed64: b.EncodeVarint(5<<3 | proto.WireFixed64) b.EncodeFixed64(uint64(x.F_Fixed64)) case *Oneof_F_Uint32: b.EncodeVarint(6<<3 | proto.WireVarint) b.EncodeVarint(uint64(x.F_Uint32)) case *Oneof_F_Uint64: b.EncodeVarint(7<<3 | proto.WireVarint) b.EncodeVarint(uint64(x.F_Uint64)) case *Oneof_F_Float: b.EncodeVarint(8<<3 | proto.WireFixed32) b.EncodeFixed32(uint64(math.Float32bits(x.F_Float))) case *Oneof_F_Double: b.EncodeVarint(9<<3 | proto.WireFixed64) b.EncodeFixed64(math.Float64bits(x.F_Double)) case *Oneof_F_String: b.EncodeVarint(10<<3 | proto.WireBytes) b.EncodeStringBytes(x.F_String) case *Oneof_F_Bytes: b.EncodeVarint(11<<3 | proto.WireBytes) b.EncodeRawBytes(x.F_Bytes) case *Oneof_F_Sint32: b.EncodeVarint(12<<3 | proto.WireVarint) b.EncodeZigzag32(uint64(x.F_Sint32)) case *Oneof_F_Sint64: b.EncodeVarint(13<<3 | proto.WireVarint) b.EncodeZigzag64(uint64(x.F_Sint64)) case *Oneof_F_Enum: b.EncodeVarint(14<<3 | proto.WireVarint) b.EncodeVarint(uint64(x.F_Enum)) case *Oneof_F_Message: b.EncodeVarint(15<<3 | proto.WireBytes) if err := b.EncodeMessage(x.F_Message); err != nil { return err } case *Oneof_FGroup: b.EncodeVarint(16<<3 | proto.WireStartGroup) if err := b.Marshal(x.FGroup); err != nil { return err } b.EncodeVarint(16<<3 | proto.WireEndGroup) case *Oneof_F_Largest_Tag: b.EncodeVarint(536870911<<3 | proto.WireVarint) b.EncodeVarint(uint64(x.F_Largest_Tag)) case nil: default: return fmt.Errorf("Oneof.Union has unexpected type %T", x) } // tormato switch x := m.Tormato.(type) { case *Oneof_Value: b.EncodeVarint(100<<3 | proto.WireVarint) b.EncodeVarint(uint64(x.Value)) case nil: default: return fmt.Errorf("Oneof.Tormato has unexpected type %T", x) } return nil } func _Oneof_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) { m := msg.(*Oneof) switch tag { case 1: // union.F_Bool if wire != proto.WireVarint { return true, proto.ErrInternalBadWireType } x, err := b.DecodeVarint() m.Union = &Oneof_F_Bool{x != 0} return true, err case 2: // union.F_Int32 if wire != proto.WireVarint { return true, proto.ErrInternalBadWireType } x, err := b.DecodeVarint() m.Union = &Oneof_F_Int32{int32(x)} return true, err case 3: // union.F_Int64 if wire != proto.WireVarint { return true, proto.ErrInternalBadWireType } x, err := b.DecodeVarint() m.Union = &Oneof_F_Int64{int64(x)} return true, err case 4: // union.F_Fixed32 if wire != proto.WireFixed32 { return true, proto.ErrInternalBadWireType } x, err := b.DecodeFixed32() m.Union = &Oneof_F_Fixed32{uint32(x)} return true, err case 5: // union.F_Fixed64 if wire != proto.WireFixed64 { return true, proto.ErrInternalBadWireType } x, err := b.DecodeFixed64() m.Union = &Oneof_F_Fixed64{x} return true, err case 6: // union.F_Uint32 if wire != proto.WireVarint { return true, proto.ErrInternalBadWireType } x, err := b.DecodeVarint() m.Union = &Oneof_F_Uint32{uint32(x)} return true, err case 7: // union.F_Uint64 if wire != proto.WireVarint { return true, proto.ErrInternalBadWireType } x, err := b.DecodeVarint() m.Union = &Oneof_F_Uint64{x} return true, err case 8: // union.F_Float if wire != proto.WireFixed32 { return true, proto.ErrInternalBadWireType } x, err := b.DecodeFixed32() m.Union = &Oneof_F_Float{math.Float32frombits(uint32(x))} return true, err case 9: // union.F_Double if wire != proto.WireFixed64 { return true, proto.ErrInternalBadWireType } x, err := b.DecodeFixed64() m.Union = &Oneof_F_Double{math.Float64frombits(x)} return true, err case 10: // union.F_String if wire != proto.WireBytes { return true, proto.ErrInternalBadWireType } x, err := b.DecodeStringBytes() m.Union = &Oneof_F_String{x} return true, err case 11: // union.F_Bytes if wire != proto.WireBytes { return true, proto.ErrInternalBadWireType } x, err := b.DecodeRawBytes(true) m.Union = &Oneof_F_Bytes{x} return true, err case 12: // union.F_Sint32 if wire != proto.WireVarint { return true, proto.ErrInternalBadWireType } x, err := b.DecodeZigzag32() m.Union = &Oneof_F_Sint32{int32(x)} return true, err case 13: // union.F_Sint64 if wire != proto.WireVarint { return true, proto.ErrInternalBadWireType } x, err := b.DecodeZigzag64() m.Union = &Oneof_F_Sint64{int64(x)} return true, err case 14: // union.F_Enum if wire != proto.WireVarint { return true, proto.ErrInternalBadWireType } x, err := b.DecodeVarint() m.Union = &Oneof_F_Enum{MyMessage_Color(x)} return true, err case 15: // union.F_Message if wire != proto.WireBytes { return true, proto.ErrInternalBadWireType } msg := new(GoTestField) err := b.DecodeMessage(msg) m.Union = &Oneof_F_Message{msg} return true, err case 16: // union.f_group if wire != proto.WireStartGroup { return true, proto.ErrInternalBadWireType } msg := new(Oneof_F_Group) err := b.DecodeGroup(msg) m.Union = &Oneof_FGroup{msg} return true, err case 536870911: // union.F_Largest_Tag if wire != proto.WireVarint { return true, proto.ErrInternalBadWireType } x, err := b.DecodeVarint() m.Union = &Oneof_F_Largest_Tag{int32(x)} return true, err case 100: // tormato.value if wire != proto.WireVarint { return true, proto.ErrInternalBadWireType } x, err := b.DecodeVarint() m.Tormato = &Oneof_Value{int32(x)} return true, err default: return false, nil } } func _Oneof_OneofSizer(msg proto.Message) (n int) { m := msg.(*Oneof) // union switch x := m.Union.(type) { case *Oneof_F_Bool: n += proto.SizeVarint(1<<3 | proto.WireVarint) n += 1 case *Oneof_F_Int32: n += proto.SizeVarint(2<<3 | proto.WireVarint) n += proto.SizeVarint(uint64(x.F_Int32)) case *Oneof_F_Int64: n += proto.SizeVarint(3<<3 | proto.WireVarint) n += proto.SizeVarint(uint64(x.F_Int64)) case *Oneof_F_Fixed32: n += proto.SizeVarint(4<<3 | proto.WireFixed32) n += 4 case *Oneof_F_Fixed64: n += proto.SizeVarint(5<<3 | proto.WireFixed64) n += 8 case *Oneof_F_Uint32: n += proto.SizeVarint(6<<3 | proto.WireVarint) n += proto.SizeVarint(uint64(x.F_Uint32)) case *Oneof_F_Uint64: n += proto.SizeVarint(7<<3 | proto.WireVarint) n += proto.SizeVarint(uint64(x.F_Uint64)) case *Oneof_F_Float: n += proto.SizeVarint(8<<3 | proto.WireFixed32) n += 4 case *Oneof_F_Double: n += proto.SizeVarint(9<<3 | proto.WireFixed64) n += 8 case *Oneof_F_String: n += proto.SizeVarint(10<<3 | proto.WireBytes) n += proto.SizeVarint(uint64(len(x.F_String))) n += len(x.F_String) case *Oneof_F_Bytes: n += proto.SizeVarint(11<<3 | proto.WireBytes) n += proto.SizeVarint(uint64(len(x.F_Bytes))) n += len(x.F_Bytes) case *Oneof_F_Sint32: n += proto.SizeVarint(12<<3 | proto.WireVarint) n += proto.SizeVarint(uint64((uint32(x.F_Sint32) << 1) ^ uint32((int32(x.F_Sint32) >> 31)))) case *Oneof_F_Sint64: n += proto.SizeVarint(13<<3 | proto.WireVarint) n += proto.SizeVarint(uint64(uint64(x.F_Sint64<<1) ^ uint64((int64(x.F_Sint64) >> 63)))) case *Oneof_F_Enum: n += proto.SizeVarint(14<<3 | proto.WireVarint) n += proto.SizeVarint(uint64(x.F_Enum)) case *Oneof_F_Message: s := proto.Size(x.F_Message) n += proto.SizeVarint(15<<3 | proto.WireBytes) n += proto.SizeVarint(uint64(s)) n += s case *Oneof_FGroup: n += proto.SizeVarint(16<<3 | proto.WireStartGroup) n += proto.Size(x.FGroup) n += proto.SizeVarint(16<<3 | proto.WireEndGroup) case *Oneof_F_Largest_Tag: n += proto.SizeVarint(536870911<<3 | proto.WireVarint) n += proto.SizeVarint(uint64(x.F_Largest_Tag)) case nil: default: panic(fmt.Sprintf("proto: unexpected type %T in oneof", x)) } // tormato switch x := m.Tormato.(type) { case *Oneof_Value: n += proto.SizeVarint(100<<3 | proto.WireVarint) n += proto.SizeVarint(uint64(x.Value)) case nil: default: panic(fmt.Sprintf("proto: unexpected type %T in oneof", x)) } return n } type Oneof_F_Group struct { X *int32 `protobuf:"varint,17,opt,name=x" json:"x,omitempty"` XXX_unrecognized []byte `json:"-"` } func (m *Oneof_F_Group) Reset() { *m = Oneof_F_Group{} } func (m *Oneof_F_Group) String() string { return proto.CompactTextString(m) } func (*Oneof_F_Group) ProtoMessage() {} func (*Oneof_F_Group) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{27, 0} } func (m *Oneof_F_Group) GetX() int32 { if m != nil && m.X != nil { return *m.X } return 0 } type Communique struct { MakeMeCry *bool `protobuf:"varint,1,opt,name=make_me_cry,json=makeMeCry" json:"make_me_cry,omitempty"` // This is a oneof, called "union". // // Types that are valid to be assigned to Union: // *Communique_Number // *Communique_Name // *Communique_Data // *Communique_TempC // *Communique_Col // *Communique_Msg Union isCommunique_Union `protobuf_oneof:"union"` XXX_unrecognized []byte `json:"-"` } func (m *Communique) Reset() { *m = Communique{} } func (m *Communique) String() string { return proto.CompactTextString(m) } func (*Communique) ProtoMessage() {} func (*Communique) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{28} } type isCommunique_Union interface { isCommunique_Union() } type Communique_Number struct { Number int32 `protobuf:"varint,5,opt,name=number,oneof"` } type Communique_Name struct { Name string `protobuf:"bytes,6,opt,name=name,oneof"` } type Communique_Data struct { Data []byte `protobuf:"bytes,7,opt,name=data,oneof"` } type Communique_TempC struct { TempC float64 `protobuf:"fixed64,8,opt,name=temp_c,json=tempC,oneof"` } type Communique_Col struct { Col MyMessage_Color `protobuf:"varint,9,opt,name=col,enum=testdata.MyMessage_Color,oneof"` } type Communique_Msg struct { Msg *Strings `protobuf:"bytes,10,opt,name=msg,oneof"` } func (*Communique_Number) isCommunique_Union() {} func (*Communique_Name) isCommunique_Union() {} func (*Communique_Data) isCommunique_Union() {} func (*Communique_TempC) isCommunique_Union() {} func (*Communique_Col) isCommunique_Union() {} func (*Communique_Msg) isCommunique_Union() {} func (m *Communique) GetUnion() isCommunique_Union { if m != nil { return m.Union } return nil } func (m *Communique) GetMakeMeCry() bool { if m != nil && m.MakeMeCry != nil { return *m.MakeMeCry } return false } func (m *Communique) GetNumber() int32 { if x, ok := m.GetUnion().(*Communique_Number); ok { return x.Number } return 0 } func (m *Communique) GetName() string { if x, ok := m.GetUnion().(*Communique_Name); ok { return x.Name } return "" } func (m *Communique) GetData() []byte { if x, ok := m.GetUnion().(*Communique_Data); ok { return x.Data } return nil } func (m *Communique) GetTempC() float64 { if x, ok := m.GetUnion().(*Communique_TempC); ok { return x.TempC } return 0 } func (m *Communique) GetCol() MyMessage_Color { if x, ok := m.GetUnion().(*Communique_Col); ok { return x.Col } return MyMessage_RED } func (m *Communique) GetMsg() *Strings { if x, ok := m.GetUnion().(*Communique_Msg); ok { return x.Msg } return nil } // XXX_OneofFuncs is for the internal use of the proto package. func (*Communique) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) { return _Communique_OneofMarshaler, _Communique_OneofUnmarshaler, _Communique_OneofSizer, []interface{}{ (*Communique_Number)(nil), (*Communique_Name)(nil), (*Communique_Data)(nil), (*Communique_TempC)(nil), (*Communique_Col)(nil), (*Communique_Msg)(nil), } } func _Communique_OneofMarshaler(msg proto.Message, b *proto.Buffer) error { m := msg.(*Communique) // union switch x := m.Union.(type) { case *Communique_Number: b.EncodeVarint(5<<3 | proto.WireVarint) b.EncodeVarint(uint64(x.Number)) case *Communique_Name: b.EncodeVarint(6<<3 | proto.WireBytes) b.EncodeStringBytes(x.Name) case *Communique_Data: b.EncodeVarint(7<<3 | proto.WireBytes) b.EncodeRawBytes(x.Data) case *Communique_TempC: b.EncodeVarint(8<<3 | proto.WireFixed64) b.EncodeFixed64(math.Float64bits(x.TempC)) case *Communique_Col: b.EncodeVarint(9<<3 | proto.WireVarint) b.EncodeVarint(uint64(x.Col)) case *Communique_Msg: b.EncodeVarint(10<<3 | proto.WireBytes) if err := b.EncodeMessage(x.Msg); err != nil { return err } case nil: default: return fmt.Errorf("Communique.Union has unexpected type %T", x) } return nil } func _Communique_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) { m := msg.(*Communique) switch tag { case 5: // union.number if wire != proto.WireVarint { return true, proto.ErrInternalBadWireType } x, err := b.DecodeVarint() m.Union = &Communique_Number{int32(x)} return true, err case 6: // union.name if wire != proto.WireBytes { return true, proto.ErrInternalBadWireType } x, err := b.DecodeStringBytes() m.Union = &Communique_Name{x} return true, err case 7: // union.data if wire != proto.WireBytes { return true, proto.ErrInternalBadWireType } x, err := b.DecodeRawBytes(true) m.Union = &Communique_Data{x} return true, err case 8: // union.temp_c if wire != proto.WireFixed64 { return true, proto.ErrInternalBadWireType } x, err := b.DecodeFixed64() m.Union = &Communique_TempC{math.Float64frombits(x)} return true, err case 9: // union.col if wire != proto.WireVarint { return true, proto.ErrInternalBadWireType } x, err := b.DecodeVarint() m.Union = &Communique_Col{MyMessage_Color(x)} return true, err case 10: // union.msg if wire != proto.WireBytes { return true, proto.ErrInternalBadWireType } msg := new(Strings) err := b.DecodeMessage(msg) m.Union = &Communique_Msg{msg} return true, err default: return false, nil } } func _Communique_OneofSizer(msg proto.Message) (n int) { m := msg.(*Communique) // union switch x := m.Union.(type) { case *Communique_Number: n += proto.SizeVarint(5<<3 | proto.WireVarint) n += proto.SizeVarint(uint64(x.Number)) case *Communique_Name: n += proto.SizeVarint(6<<3 | proto.WireBytes) n += proto.SizeVarint(uint64(len(x.Name))) n += len(x.Name) case *Communique_Data: n += proto.SizeVarint(7<<3 | proto.WireBytes) n += proto.SizeVarint(uint64(len(x.Data))) n += len(x.Data) case *Communique_TempC: n += proto.SizeVarint(8<<3 | proto.WireFixed64) n += 8 case *Communique_Col: n += proto.SizeVarint(9<<3 | proto.WireVarint) n += proto.SizeVarint(uint64(x.Col)) case *Communique_Msg: s := proto.Size(x.Msg) n += proto.SizeVarint(10<<3 | proto.WireBytes) n += proto.SizeVarint(uint64(s)) n += s case nil: default: panic(fmt.Sprintf("proto: unexpected type %T in oneof", x)) } return n } var E_Greeting = &proto.ExtensionDesc{ ExtendedType: (*MyMessage)(nil), ExtensionType: ([]string)(nil), Field: 106, Name: "testdata.greeting", Tag: "bytes,106,rep,name=greeting", } var E_Complex = &proto.ExtensionDesc{ ExtendedType: (*OtherMessage)(nil), ExtensionType: (*ComplexExtension)(nil), Field: 200, Name: "testdata.complex", Tag: "bytes,200,opt,name=complex", } var E_RComplex = &proto.ExtensionDesc{ ExtendedType: (*OtherMessage)(nil), ExtensionType: ([]*ComplexExtension)(nil), Field: 201, Name: "testdata.r_complex", Tag: "bytes,201,rep,name=r_complex,json=rComplex", } var E_NoDefaultDouble = &proto.ExtensionDesc{ ExtendedType: (*DefaultsMessage)(nil), ExtensionType: (*float64)(nil), Field: 101, Name: "testdata.no_default_double", Tag: "fixed64,101,opt,name=no_default_double,json=noDefaultDouble", } var E_NoDefaultFloat = &proto.ExtensionDesc{ ExtendedType: (*DefaultsMessage)(nil), ExtensionType: (*float32)(nil), Field: 102, Name: "testdata.no_default_float", Tag: "fixed32,102,opt,name=no_default_float,json=noDefaultFloat", } var E_NoDefaultInt32 = &proto.ExtensionDesc{ ExtendedType: (*DefaultsMessage)(nil), ExtensionType: (*int32)(nil), Field: 103, Name: "testdata.no_default_int32", Tag: "varint,103,opt,name=no_default_int32,json=noDefaultInt32", } var E_NoDefaultInt64 = &proto.ExtensionDesc{ ExtendedType: (*DefaultsMessage)(nil), ExtensionType: (*int64)(nil), Field: 104, Name: "testdata.no_default_int64", Tag: "varint,104,opt,name=no_default_int64,json=noDefaultInt64", } var E_NoDefaultUint32 = &proto.ExtensionDesc{ ExtendedType: (*DefaultsMessage)(nil), ExtensionType: (*uint32)(nil), Field: 105, Name: "testdata.no_default_uint32", Tag: "varint,105,opt,name=no_default_uint32,json=noDefaultUint32", } var E_NoDefaultUint64 = &proto.ExtensionDesc{ ExtendedType: (*DefaultsMessage)(nil), ExtensionType: (*uint64)(nil), Field: 106, Name: "testdata.no_default_uint64", Tag: "varint,106,opt,name=no_default_uint64,json=noDefaultUint64", } var E_NoDefaultSint32 = &proto.ExtensionDesc{ ExtendedType: (*DefaultsMessage)(nil), ExtensionType: (*int32)(nil), Field: 107, Name: "testdata.no_default_sint32", Tag: "zigzag32,107,opt,name=no_default_sint32,json=noDefaultSint32", } var E_NoDefaultSint64 = &proto.ExtensionDesc{ ExtendedType: (*DefaultsMessage)(nil), ExtensionType: (*int64)(nil), Field: 108, Name: "testdata.no_default_sint64", Tag: "zigzag64,108,opt,name=no_default_sint64,json=noDefaultSint64", } var E_NoDefaultFixed32 = &proto.ExtensionDesc{ ExtendedType: (*DefaultsMessage)(nil), ExtensionType: (*uint32)(nil), Field: 109, Name: "testdata.no_default_fixed32", Tag: "fixed32,109,opt,name=no_default_fixed32,json=noDefaultFixed32", } var E_NoDefaultFixed64 = &proto.ExtensionDesc{ ExtendedType: (*DefaultsMessage)(nil), ExtensionType: (*uint64)(nil), Field: 110, Name: "testdata.no_default_fixed64", Tag: "fixed64,110,opt,name=no_default_fixed64,json=noDefaultFixed64", } var E_NoDefaultSfixed32 = &proto.ExtensionDesc{ ExtendedType: (*DefaultsMessage)(nil), ExtensionType: (*int32)(nil), Field: 111, Name: "testdata.no_default_sfixed32", Tag: "fixed32,111,opt,name=no_default_sfixed32,json=noDefaultSfixed32", } var E_NoDefaultSfixed64 = &proto.ExtensionDesc{ ExtendedType: (*DefaultsMessage)(nil), ExtensionType: (*int64)(nil), Field: 112, Name: "testdata.no_default_sfixed64", Tag: "fixed64,112,opt,name=no_default_sfixed64,json=noDefaultSfixed64", } var E_NoDefaultBool = &proto.ExtensionDesc{ ExtendedType: (*DefaultsMessage)(nil), ExtensionType: (*bool)(nil), Field: 113, Name: "testdata.no_default_bool", Tag: "varint,113,opt,name=no_default_bool,json=noDefaultBool", } var E_NoDefaultString = &proto.ExtensionDesc{ ExtendedType: (*DefaultsMessage)(nil), ExtensionType: (*string)(nil), Field: 114, Name: "testdata.no_default_string", Tag: "bytes,114,opt,name=no_default_string,json=noDefaultString", } var E_NoDefaultBytes = &proto.ExtensionDesc{ ExtendedType: (*DefaultsMessage)(nil), ExtensionType: ([]byte)(nil), Field: 115, Name: "testdata.no_default_bytes", Tag: "bytes,115,opt,name=no_default_bytes,json=noDefaultBytes", } var E_NoDefaultEnum = &proto.ExtensionDesc{ ExtendedType: (*DefaultsMessage)(nil), ExtensionType: (*DefaultsMessage_DefaultsEnum)(nil), Field: 116, Name: "testdata.no_default_enum", Tag: "varint,116,opt,name=no_default_enum,json=noDefaultEnum,enum=testdata.DefaultsMessage_DefaultsEnum", } var E_DefaultDouble = &proto.ExtensionDesc{ ExtendedType: (*DefaultsMessage)(nil), ExtensionType: (*float64)(nil), Field: 201, Name: "testdata.default_double", Tag: "fixed64,201,opt,name=default_double,json=defaultDouble,def=3.1415", } var E_DefaultFloat = &proto.ExtensionDesc{ ExtendedType: (*DefaultsMessage)(nil), ExtensionType: (*float32)(nil), Field: 202, Name: "testdata.default_float", Tag: "fixed32,202,opt,name=default_float,json=defaultFloat,def=3.14", } var E_DefaultInt32 = &proto.ExtensionDesc{ ExtendedType: (*DefaultsMessage)(nil), ExtensionType: (*int32)(nil), Field: 203, Name: "testdata.default_int32", Tag: "varint,203,opt,name=default_int32,json=defaultInt32,def=42", } var E_DefaultInt64 = &proto.ExtensionDesc{ ExtendedType: (*DefaultsMessage)(nil), ExtensionType: (*int64)(nil), Field: 204, Name: "testdata.default_int64", Tag: "varint,204,opt,name=default_int64,json=defaultInt64,def=43", } var E_DefaultUint32 = &proto.ExtensionDesc{ ExtendedType: (*DefaultsMessage)(nil), ExtensionType: (*uint32)(nil), Field: 205, Name: "testdata.default_uint32", Tag: "varint,205,opt,name=default_uint32,json=defaultUint32,def=44", } var E_DefaultUint64 = &proto.ExtensionDesc{ ExtendedType: (*DefaultsMessage)(nil), ExtensionType: (*uint64)(nil), Field: 206, Name: "testdata.default_uint64", Tag: "varint,206,opt,name=default_uint64,json=defaultUint64,def=45", } var E_DefaultSint32 = &proto.ExtensionDesc{ ExtendedType: (*DefaultsMessage)(nil), ExtensionType: (*int32)(nil), Field: 207, Name: "testdata.default_sint32", Tag: "zigzag32,207,opt,name=default_sint32,json=defaultSint32,def=46", } var E_DefaultSint64 = &proto.ExtensionDesc{ ExtendedType: (*DefaultsMessage)(nil), ExtensionType: (*int64)(nil), Field: 208, Name: "testdata.default_sint64", Tag: "zigzag64,208,opt,name=default_sint64,json=defaultSint64,def=47", } var E_DefaultFixed32 = &proto.ExtensionDesc{ ExtendedType: (*DefaultsMessage)(nil), ExtensionType: (*uint32)(nil), Field: 209, Name: "testdata.default_fixed32", Tag: "fixed32,209,opt,name=default_fixed32,json=defaultFixed32,def=48", } var E_DefaultFixed64 = &proto.ExtensionDesc{ ExtendedType: (*DefaultsMessage)(nil), ExtensionType: (*uint64)(nil), Field: 210, Name: "testdata.default_fixed64", Tag: "fixed64,210,opt,name=default_fixed64,json=defaultFixed64,def=49", } var E_DefaultSfixed32 = &proto.ExtensionDesc{ ExtendedType: (*DefaultsMessage)(nil), ExtensionType: (*int32)(nil), Field: 211, Name: "testdata.default_sfixed32", Tag: "fixed32,211,opt,name=default_sfixed32,json=defaultSfixed32,def=50", } var E_DefaultSfixed64 = &proto.ExtensionDesc{ ExtendedType: (*DefaultsMessage)(nil), ExtensionType: (*int64)(nil), Field: 212, Name: "testdata.default_sfixed64", Tag: "fixed64,212,opt,name=default_sfixed64,json=defaultSfixed64,def=51", } var E_DefaultBool = &proto.ExtensionDesc{ ExtendedType: (*DefaultsMessage)(nil), ExtensionType: (*bool)(nil), Field: 213, Name: "testdata.default_bool", Tag: "varint,213,opt,name=default_bool,json=defaultBool,def=1", } var E_DefaultString = &proto.ExtensionDesc{ ExtendedType: (*DefaultsMessage)(nil), ExtensionType: (*string)(nil), Field: 214, Name: "testdata.default_string", Tag: "bytes,214,opt,name=default_string,json=defaultString,def=Hello, string", } var E_DefaultBytes = &proto.ExtensionDesc{ ExtendedType: (*DefaultsMessage)(nil), ExtensionType: ([]byte)(nil), Field: 215, Name: "testdata.default_bytes", Tag: "bytes,215,opt,name=default_bytes,json=defaultBytes,def=Hello, bytes", } var E_DefaultEnum = &proto.ExtensionDesc{ ExtendedType: (*DefaultsMessage)(nil), ExtensionType: (*DefaultsMessage_DefaultsEnum)(nil), Field: 216, Name: "testdata.default_enum", Tag: "varint,216,opt,name=default_enum,json=defaultEnum,enum=testdata.DefaultsMessage_DefaultsEnum,def=1", } var E_X201 = &proto.ExtensionDesc{ ExtendedType: (*MyMessageSet)(nil), ExtensionType: (*Empty)(nil), Field: 201, Name: "testdata.x201", Tag: "bytes,201,opt,name=x201", } var E_X202 = &proto.ExtensionDesc{ ExtendedType: (*MyMessageSet)(nil), ExtensionType: (*Empty)(nil), Field: 202, Name: "testdata.x202", Tag: "bytes,202,opt,name=x202", } var E_X203 = &proto.ExtensionDesc{ ExtendedType: (*MyMessageSet)(nil), ExtensionType: (*Empty)(nil), Field: 203, Name: "testdata.x203", Tag: "bytes,203,opt,name=x203", } var E_X204 = &proto.ExtensionDesc{ ExtendedType: (*MyMessageSet)(nil), ExtensionType: (*Empty)(nil), Field: 204, Name: "testdata.x204", Tag: "bytes,204,opt,name=x204", } var E_X205 = &proto.ExtensionDesc{ ExtendedType: (*MyMessageSet)(nil), ExtensionType: (*Empty)(nil), Field: 205, Name: "testdata.x205", Tag: "bytes,205,opt,name=x205", } var E_X206 = &proto.ExtensionDesc{ ExtendedType: (*MyMessageSet)(nil), ExtensionType: (*Empty)(nil), Field: 206, Name: "testdata.x206", Tag: "bytes,206,opt,name=x206", } var E_X207 = &proto.ExtensionDesc{ ExtendedType: (*MyMessageSet)(nil), ExtensionType: (*Empty)(nil), Field: 207, Name: "testdata.x207", Tag: "bytes,207,opt,name=x207", } var E_X208 = &proto.ExtensionDesc{ ExtendedType: (*MyMessageSet)(nil), ExtensionType: (*Empty)(nil), Field: 208, Name: "testdata.x208", Tag: "bytes,208,opt,name=x208", } var E_X209 = &proto.ExtensionDesc{ ExtendedType: (*MyMessageSet)(nil), ExtensionType: (*Empty)(nil), Field: 209, Name: "testdata.x209", Tag: "bytes,209,opt,name=x209", } var E_X210 = &proto.ExtensionDesc{ ExtendedType: (*MyMessageSet)(nil), ExtensionType: (*Empty)(nil), Field: 210, Name: "testdata.x210", Tag: "bytes,210,opt,name=x210", } var E_X211 = &proto.ExtensionDesc{ ExtendedType: (*MyMessageSet)(nil), ExtensionType: (*Empty)(nil), Field: 211, Name: "testdata.x211", Tag: "bytes,211,opt,name=x211", } var E_X212 = &proto.ExtensionDesc{ ExtendedType: (*MyMessageSet)(nil), ExtensionType: (*Empty)(nil), Field: 212, Name: "testdata.x212", Tag: "bytes,212,opt,name=x212", } var E_X213 = &proto.ExtensionDesc{ ExtendedType: (*MyMessageSet)(nil), ExtensionType: (*Empty)(nil), Field: 213, Name: "testdata.x213", Tag: "bytes,213,opt,name=x213", } var E_X214 = &proto.ExtensionDesc{ ExtendedType: (*MyMessageSet)(nil), ExtensionType: (*Empty)(nil), Field: 214, Name: "testdata.x214", Tag: "bytes,214,opt,name=x214", } var E_X215 = &proto.ExtensionDesc{ ExtendedType: (*MyMessageSet)(nil), ExtensionType: (*Empty)(nil), Field: 215, Name: "testdata.x215", Tag: "bytes,215,opt,name=x215", } var E_X216 = &proto.ExtensionDesc{ ExtendedType: (*MyMessageSet)(nil), ExtensionType: (*Empty)(nil), Field: 216, Name: "testdata.x216", Tag: "bytes,216,opt,name=x216", } var E_X217 = &proto.ExtensionDesc{ ExtendedType: (*MyMessageSet)(nil), ExtensionType: (*Empty)(nil), Field: 217, Name: "testdata.x217", Tag: "bytes,217,opt,name=x217", } var E_X218 = &proto.ExtensionDesc{ ExtendedType: (*MyMessageSet)(nil), ExtensionType: (*Empty)(nil), Field: 218, Name: "testdata.x218", Tag: "bytes,218,opt,name=x218", } var E_X219 = &proto.ExtensionDesc{ ExtendedType: (*MyMessageSet)(nil), ExtensionType: (*Empty)(nil), Field: 219, Name: "testdata.x219", Tag: "bytes,219,opt,name=x219", } var E_X220 = &proto.ExtensionDesc{ ExtendedType: (*MyMessageSet)(nil), ExtensionType: (*Empty)(nil), Field: 220, Name: "testdata.x220", Tag: "bytes,220,opt,name=x220", } var E_X221 = &proto.ExtensionDesc{ ExtendedType: (*MyMessageSet)(nil), ExtensionType: (*Empty)(nil), Field: 221, Name: "testdata.x221", Tag: "bytes,221,opt,name=x221", } var E_X222 = &proto.ExtensionDesc{ ExtendedType: (*MyMessageSet)(nil), ExtensionType: (*Empty)(nil), Field: 222, Name: "testdata.x222", Tag: "bytes,222,opt,name=x222", } var E_X223 = &proto.ExtensionDesc{ ExtendedType: (*MyMessageSet)(nil), ExtensionType: (*Empty)(nil), Field: 223, Name: "testdata.x223", Tag: "bytes,223,opt,name=x223", } var E_X224 = &proto.ExtensionDesc{ ExtendedType: (*MyMessageSet)(nil), ExtensionType: (*Empty)(nil), Field: 224, Name: "testdata.x224", Tag: "bytes,224,opt,name=x224", } var E_X225 = &proto.ExtensionDesc{ ExtendedType: (*MyMessageSet)(nil), ExtensionType: (*Empty)(nil), Field: 225, Name: "testdata.x225", Tag: "bytes,225,opt,name=x225", } var E_X226 = &proto.ExtensionDesc{ ExtendedType: (*MyMessageSet)(nil), ExtensionType: (*Empty)(nil), Field: 226, Name: "testdata.x226", Tag: "bytes,226,opt,name=x226", } var E_X227 = &proto.ExtensionDesc{ ExtendedType: (*MyMessageSet)(nil), ExtensionType: (*Empty)(nil), Field: 227, Name: "testdata.x227", Tag: "bytes,227,opt,name=x227", } var E_X228 = &proto.ExtensionDesc{ ExtendedType: (*MyMessageSet)(nil), ExtensionType: (*Empty)(nil), Field: 228, Name: "testdata.x228", Tag: "bytes,228,opt,name=x228", } var E_X229 = &proto.ExtensionDesc{ ExtendedType: (*MyMessageSet)(nil), ExtensionType: (*Empty)(nil), Field: 229, Name: "testdata.x229", Tag: "bytes,229,opt,name=x229", } var E_X230 = &proto.ExtensionDesc{ ExtendedType: (*MyMessageSet)(nil), ExtensionType: (*Empty)(nil), Field: 230, Name: "testdata.x230", Tag: "bytes,230,opt,name=x230", } var E_X231 = &proto.ExtensionDesc{ ExtendedType: (*MyMessageSet)(nil), ExtensionType: (*Empty)(nil), Field: 231, Name: "testdata.x231", Tag: "bytes,231,opt,name=x231", } var E_X232 = &proto.ExtensionDesc{ ExtendedType: (*MyMessageSet)(nil), ExtensionType: (*Empty)(nil), Field: 232, Name: "testdata.x232", Tag: "bytes,232,opt,name=x232", } var E_X233 = &proto.ExtensionDesc{ ExtendedType: (*MyMessageSet)(nil), ExtensionType: (*Empty)(nil), Field: 233, Name: "testdata.x233", Tag: "bytes,233,opt,name=x233", } var E_X234 = &proto.ExtensionDesc{ ExtendedType: (*MyMessageSet)(nil), ExtensionType: (*Empty)(nil), Field: 234, Name: "testdata.x234", Tag: "bytes,234,opt,name=x234", } var E_X235 = &proto.ExtensionDesc{ ExtendedType: (*MyMessageSet)(nil), ExtensionType: (*Empty)(nil), Field: 235, Name: "testdata.x235", Tag: "bytes,235,opt,name=x235", } var E_X236 = &proto.ExtensionDesc{ ExtendedType: (*MyMessageSet)(nil), ExtensionType: (*Empty)(nil), Field: 236, Name: "testdata.x236", Tag: "bytes,236,opt,name=x236", } var E_X237 = &proto.ExtensionDesc{ ExtendedType: (*MyMessageSet)(nil), ExtensionType: (*Empty)(nil), Field: 237, Name: "testdata.x237", Tag: "bytes,237,opt,name=x237", } var E_X238 = &proto.ExtensionDesc{ ExtendedType: (*MyMessageSet)(nil), ExtensionType: (*Empty)(nil), Field: 238, Name: "testdata.x238", Tag: "bytes,238,opt,name=x238", } var E_X239 = &proto.ExtensionDesc{ ExtendedType: (*MyMessageSet)(nil), ExtensionType: (*Empty)(nil), Field: 239, Name: "testdata.x239", Tag: "bytes,239,opt,name=x239", } var E_X240 = &proto.ExtensionDesc{ ExtendedType: (*MyMessageSet)(nil), ExtensionType: (*Empty)(nil), Field: 240, Name: "testdata.x240", Tag: "bytes,240,opt,name=x240", } var E_X241 = &proto.ExtensionDesc{ ExtendedType: (*MyMessageSet)(nil), ExtensionType: (*Empty)(nil), Field: 241, Name: "testdata.x241", Tag: "bytes,241,opt,name=x241", } var E_X242 = &proto.ExtensionDesc{ ExtendedType: (*MyMessageSet)(nil), ExtensionType: (*Empty)(nil), Field: 242, Name: "testdata.x242", Tag: "bytes,242,opt,name=x242", } var E_X243 = &proto.ExtensionDesc{ ExtendedType: (*MyMessageSet)(nil), ExtensionType: (*Empty)(nil), Field: 243, Name: "testdata.x243", Tag: "bytes,243,opt,name=x243", } var E_X244 = &proto.ExtensionDesc{ ExtendedType: (*MyMessageSet)(nil), ExtensionType: (*Empty)(nil), Field: 244, Name: "testdata.x244", Tag: "bytes,244,opt,name=x244", } var E_X245 = &proto.ExtensionDesc{ ExtendedType: (*MyMessageSet)(nil), ExtensionType: (*Empty)(nil), Field: 245, Name: "testdata.x245", Tag: "bytes,245,opt,name=x245", } var E_X246 = &proto.ExtensionDesc{ ExtendedType: (*MyMessageSet)(nil), ExtensionType: (*Empty)(nil), Field: 246, Name: "testdata.x246", Tag: "bytes,246,opt,name=x246", } var E_X247 = &proto.ExtensionDesc{ ExtendedType: (*MyMessageSet)(nil), ExtensionType: (*Empty)(nil), Field: 247, Name: "testdata.x247", Tag: "bytes,247,opt,name=x247", } var E_X248 = &proto.ExtensionDesc{ ExtendedType: (*MyMessageSet)(nil), ExtensionType: (*Empty)(nil), Field: 248, Name: "testdata.x248", Tag: "bytes,248,opt,name=x248", } var E_X249 = &proto.ExtensionDesc{ ExtendedType: (*MyMessageSet)(nil), ExtensionType: (*Empty)(nil), Field: 249, Name: "testdata.x249", Tag: "bytes,249,opt,name=x249", } var E_X250 = &proto.ExtensionDesc{ ExtendedType: (*MyMessageSet)(nil), ExtensionType: (*Empty)(nil), Field: 250, Name: "testdata.x250", Tag: "bytes,250,opt,name=x250", } func init() { proto.RegisterType((*GoEnum)(nil), "testdata.GoEnum") proto.RegisterType((*GoTestField)(nil), "testdata.GoTestField") proto.RegisterType((*GoTest)(nil), "testdata.GoTest") proto.RegisterType((*GoTest_RequiredGroup)(nil), "testdata.GoTest.RequiredGroup") proto.RegisterType((*GoTest_RepeatedGroup)(nil), "testdata.GoTest.RepeatedGroup") proto.RegisterType((*GoTest_OptionalGroup)(nil), "testdata.GoTest.OptionalGroup") proto.RegisterType((*GoSkipTest)(nil), "testdata.GoSkipTest") proto.RegisterType((*GoSkipTest_SkipGroup)(nil), "testdata.GoSkipTest.SkipGroup") proto.RegisterType((*NonPackedTest)(nil), "testdata.NonPackedTest") proto.RegisterType((*PackedTest)(nil), "testdata.PackedTest") proto.RegisterType((*MaxTag)(nil), "testdata.MaxTag") proto.RegisterType((*OldMessage)(nil), "testdata.OldMessage") proto.RegisterType((*OldMessage_Nested)(nil), "testdata.OldMessage.Nested") proto.RegisterType((*NewMessage)(nil), "testdata.NewMessage") proto.RegisterType((*NewMessage_Nested)(nil), "testdata.NewMessage.Nested") proto.RegisterType((*InnerMessage)(nil), "testdata.InnerMessage") proto.RegisterType((*OtherMessage)(nil), "testdata.OtherMessage") proto.RegisterType((*MyMessage)(nil), "testdata.MyMessage") proto.RegisterType((*MyMessage_SomeGroup)(nil), "testdata.MyMessage.SomeGroup") proto.RegisterType((*Ext)(nil), "testdata.Ext") proto.RegisterType((*ComplexExtension)(nil), "testdata.ComplexExtension") proto.RegisterType((*DefaultsMessage)(nil), "testdata.DefaultsMessage") proto.RegisterType((*MyMessageSet)(nil), "testdata.MyMessageSet") proto.RegisterType((*Empty)(nil), "testdata.Empty") proto.RegisterType((*MessageList)(nil), "testdata.MessageList") proto.RegisterType((*MessageList_Message)(nil), "testdata.MessageList.Message") proto.RegisterType((*Strings)(nil), "testdata.Strings") proto.RegisterType((*Defaults)(nil), "testdata.Defaults") proto.RegisterType((*SubDefaults)(nil), "testdata.SubDefaults") proto.RegisterType((*RepeatedEnum)(nil), "testdata.RepeatedEnum") proto.RegisterType((*MoreRepeated)(nil), "testdata.MoreRepeated") proto.RegisterType((*GroupOld)(nil), "testdata.GroupOld") proto.RegisterType((*GroupOld_G)(nil), "testdata.GroupOld.G") proto.RegisterType((*GroupNew)(nil), "testdata.GroupNew") proto.RegisterType((*GroupNew_G)(nil), "testdata.GroupNew.G") proto.RegisterType((*FloatingPoint)(nil), "testdata.FloatingPoint") proto.RegisterType((*MessageWithMap)(nil), "testdata.MessageWithMap") proto.RegisterType((*Oneof)(nil), "testdata.Oneof") proto.RegisterType((*Oneof_F_Group)(nil), "testdata.Oneof.F_Group") proto.RegisterType((*Communique)(nil), "testdata.Communique") proto.RegisterEnum("testdata.FOO", FOO_name, FOO_value) proto.RegisterEnum("testdata.GoTest_KIND", GoTest_KIND_name, GoTest_KIND_value) proto.RegisterEnum("testdata.MyMessage_Color", MyMessage_Color_name, MyMessage_Color_value) proto.RegisterEnum("testdata.DefaultsMessage_DefaultsEnum", DefaultsMessage_DefaultsEnum_name, DefaultsMessage_DefaultsEnum_value) proto.RegisterEnum("testdata.Defaults_Color", Defaults_Color_name, Defaults_Color_value) proto.RegisterEnum("testdata.RepeatedEnum_Color", RepeatedEnum_Color_name, RepeatedEnum_Color_value) proto.RegisterExtension(E_Ext_More) proto.RegisterExtension(E_Ext_Text) proto.RegisterExtension(E_Ext_Number) proto.RegisterExtension(E_Greeting) proto.RegisterExtension(E_Complex) proto.RegisterExtension(E_RComplex) proto.RegisterExtension(E_NoDefaultDouble) proto.RegisterExtension(E_NoDefaultFloat) proto.RegisterExtension(E_NoDefaultInt32) proto.RegisterExtension(E_NoDefaultInt64) proto.RegisterExtension(E_NoDefaultUint32) proto.RegisterExtension(E_NoDefaultUint64) proto.RegisterExtension(E_NoDefaultSint32) proto.RegisterExtension(E_NoDefaultSint64) proto.RegisterExtension(E_NoDefaultFixed32) proto.RegisterExtension(E_NoDefaultFixed64) proto.RegisterExtension(E_NoDefaultSfixed32) proto.RegisterExtension(E_NoDefaultSfixed64) proto.RegisterExtension(E_NoDefaultBool) proto.RegisterExtension(E_NoDefaultString) proto.RegisterExtension(E_NoDefaultBytes) proto.RegisterExtension(E_NoDefaultEnum) proto.RegisterExtension(E_DefaultDouble) proto.RegisterExtension(E_DefaultFloat) proto.RegisterExtension(E_DefaultInt32) proto.RegisterExtension(E_DefaultInt64) proto.RegisterExtension(E_DefaultUint32) proto.RegisterExtension(E_DefaultUint64) proto.RegisterExtension(E_DefaultSint32) proto.RegisterExtension(E_DefaultSint64) proto.RegisterExtension(E_DefaultFixed32) proto.RegisterExtension(E_DefaultFixed64) proto.RegisterExtension(E_DefaultSfixed32) proto.RegisterExtension(E_DefaultSfixed64) proto.RegisterExtension(E_DefaultBool) proto.RegisterExtension(E_DefaultString) proto.RegisterExtension(E_DefaultBytes) proto.RegisterExtension(E_DefaultEnum) proto.RegisterExtension(E_X201) proto.RegisterExtension(E_X202) proto.RegisterExtension(E_X203) proto.RegisterExtension(E_X204) proto.RegisterExtension(E_X205) proto.RegisterExtension(E_X206) proto.RegisterExtension(E_X207) proto.RegisterExtension(E_X208) proto.RegisterExtension(E_X209) proto.RegisterExtension(E_X210) proto.RegisterExtension(E_X211) proto.RegisterExtension(E_X212) proto.RegisterExtension(E_X213) proto.RegisterExtension(E_X214) proto.RegisterExtension(E_X215) proto.RegisterExtension(E_X216) proto.RegisterExtension(E_X217) proto.RegisterExtension(E_X218) proto.RegisterExtension(E_X219) proto.RegisterExtension(E_X220) proto.RegisterExtension(E_X221) proto.RegisterExtension(E_X222) proto.RegisterExtension(E_X223) proto.RegisterExtension(E_X224) proto.RegisterExtension(E_X225) proto.RegisterExtension(E_X226) proto.RegisterExtension(E_X227) proto.RegisterExtension(E_X228) proto.RegisterExtension(E_X229) proto.RegisterExtension(E_X230) proto.RegisterExtension(E_X231) proto.RegisterExtension(E_X232) proto.RegisterExtension(E_X233) proto.RegisterExtension(E_X234) proto.RegisterExtension(E_X235) proto.RegisterExtension(E_X236) proto.RegisterExtension(E_X237) proto.RegisterExtension(E_X238) proto.RegisterExtension(E_X239) proto.RegisterExtension(E_X240) proto.RegisterExtension(E_X241) proto.RegisterExtension(E_X242) proto.RegisterExtension(E_X243) proto.RegisterExtension(E_X244) proto.RegisterExtension(E_X245) proto.RegisterExtension(E_X246) proto.RegisterExtension(E_X247) proto.RegisterExtension(E_X248) proto.RegisterExtension(E_X249) proto.RegisterExtension(E_X250) } var fileDescriptor0 = []byte{ // 4253 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x94, 0x7a, 0xd9, 0x77, 0x1b, 0x47, 0x76, 0xbe, 0x1b, 0x3b, 0x0a, 0x20, 0xd1, 0x6c, 0xc9, 0x12, 0x44, 0x2d, 0x96, 0x31, 0x63, 0x5b, 0x92, 0x6d, 0x0e, 0xd1, 0x00, 0x49, 0x09, 0x9e, 0xdf, 0x9c, 0x23, 0x4a, 0x24, 0x87, 0x67, 0x44, 0x82, 0xbf, 0x26, 0xed, 0x39, 0xe3, 0x3c, 0xe0, 0x80, 0x62, 0x83, 0x84, 0x05, 0xa0, 0x21, 0x00, 0x8c, 0xa5, 0xe4, 0x25, 0x2f, 0xc9, 0x6b, 0xb6, 0x97, 0xbc, 0xe6, 0x29, 0x4f, 0x49, 0xce, 0xc9, 0x5f, 0x11, 0xdb, 0xb3, 0x7a, 0xd6, 0xac, 0x93, 0x7d, 0x99, 0xec, 0xdb, 0x4c, 0x92, 0x93, 0x73, 0x92, 0x7b, 0x6f, 0xdd, 0xee, 0xae, 0x6e, 0xa0, 0x9b, 0x94, 0x1e, 0x4c, 0x74, 0xd5, 0xf7, 0xdd, 0xba, 0x55, 0xfd, 0xd5, 0xbd, 0x75, 0xab, 0x2d, 0xc4, 0xc4, 0x1e, 0x4f, 0x96, 0x86, 0x23, 0x67, 0xe2, 0x18, 0x39, 0xfc, 0x7d, 0xd4, 0x9e, 0xb4, 0x2b, 0xb7, 0x45, 0x66, 0xcb, 0xd9, 0x18, 0x9c, 0xf6, 0x8d, 0x57, 0x44, 0xb2, 0xe3, 0x38, 0x65, 0xed, 0x66, 0xe2, 0xd6, 0xbc, 0x39, 0xb7, 0xe4, 0x22, 0x96, 0x36, 0x9b, 0x4d, 0x0b, 0x7b, 0x2a, 0x6b, 0xa2, 0xb0, 0xe5, 0x1c, 0x40, 0xf3, 0x66, 0xd7, 0xee, 0x1d, 0x19, 0x17, 0x45, 0xfa, 0x51, 0xfb, 0xd0, 0xee, 0x11, 0x23, 0x6f, 0xa5, 0x7b, 0xf8, 0x60, 0x18, 0x22, 0x75, 0xf0, 0x7c, 0x68, 0x97, 0x13, 0xd4, 0x98, 0x9a, 0xc0, 0xef, 0xca, 0x2f, 0xde, 0xc0, 0x41, 0x90, 0x69, 0xdc, 0x16, 0xa9, 0x2f, 0x75, 0x07, 0x47, 0x3c, 0xca, 0xcb, 0xfe, 0x28, 0xb2, 0x7f, 0xe9, 0x4b, 0xdb, 0xbb, 0x0f, 0xad, 0xd4, 0x13, 0x80, 0xa0, 0xfd, 0x83, 0xf6, 0x61, 0x0f, 0x4d, 0x69, 0x68, 0x7f, 0x82, 0x0f, 0xd8, 0xba, 0xd7, 0x1e, 0xb5, 0xfb, 0xe5, 0x24, 0xb4, 0xa6, 0xad, 0xf4, 0x10, 0x1f, 0x8c, 0x77, 0xc4, 0x9c, 0x65, 0x3f, 0x3d, 0xed, 0x8e, 0xec, 0x23, 0x72, 0xae, 0x9c, 0x02, 0xfb, 0x85, 0x69, 0xfb, 0xd4, 0x69, 0xcd, 0x8d, 0x54, 0xac, 0x24, 0x0f, 0xed, 0xf6, 0xc4, 0x25, 0xa7, 0x6f, 0x26, 0x63, 0xc9, 0x0a, 0x16, 0xc9, 0xcd, 0xe1, 0xa4, 0xeb, 0x0c, 0xda, 0x3d, 0x49, 0xce, 0x80, 0x5f, 0xd1, 0x64, 0x47, 0xc5, 0x1a, 0xaf, 0x8b, 0xd2, 0x66, 0x6b, 0xdd, 0x71, 0x7a, 0x2d, 0xd7, 0xa3, 0xb2, 0x00, 0xc7, 0x73, 0xd6, 0x5c, 0x07, 0x5b, 0xdd, 0x29, 0x19, 0xb7, 0x84, 0xbe, 0xd9, 0xda, 0x1e, 0x4c, 0x6a, 0xa6, 0x0f, 0x2c, 0x00, 0x30, 0x6d, 0xcd, 0x77, 0xa8, 0x79, 0x0a, 0xb9, 0x5a, 0xf7, 0x91, 0x45, 0x40, 0x26, 0x25, 0x72, 0xb5, 0xee, 0x21, 0xdf, 0x12, 0xc6, 0x66, 0x6b, 0xb3, 0xfb, 0xcc, 0x3e, 0x52, 0xad, 0xce, 0x01, 0x36, 0x6b, 0xe9, 0x1d, 0xee, 0x98, 0x81, 0x56, 0x2d, 0xcf, 0x03, 0x3a, 0xe3, 0xa2, 0x15, 0xdb, 0x77, 0xc4, 0xc2, 0x66, 0xeb, 0xdd, 0x6e, 0xd0, 0xe1, 0x12, 0x80, 0xe7, 0xac, 0x52, 0x47, 0xb6, 0x4f, 0x63, 0x55, 0xc3, 0x3a, 0x60, 0x53, 0x8c, 0x55, 0xec, 0xd2, 0xec, 0x36, 0x7b, 0x4e, 0x7b, 0xe2, 0x43, 0x17, 0x00, 0x9a, 0x80, 0xd9, 0x51, 0x73, 0xd0, 0xea, 0x43, 0xe7, 0x14, 0x24, 0xe3, 0x43, 0x0d, 0x80, 0x6a, 0x60, 0x55, 0xb6, 0x07, 0xb1, 0xfb, 0x93, 0x51, 0x77, 0x70, 0xec, 0x63, 0x2f, 0x90, 0x7e, 0x4b, 0x1d, 0xd9, 0x1e, 0xf4, 0x60, 0xfd, 0x39, 0xbc, 0x5c, 0x1f, 0x6a, 0x03, 0xb4, 0x08, 0x1e, 0x50, 0x73, 0xc8, 0x6a, 0x68, 0x0d, 0x3a, 0x00, 0x5d, 0x40, 0xab, 0x33, 0xd6, 0x60, 0x3f, 0xb4, 0x06, 0xc7, 0x80, 0x35, 0x18, 0xab, 0xac, 0x81, 0xaa, 0x19, 0x29, 0xc4, 0xf2, 0x45, 0xd0, 0xab, 0xaf, 0x19, 0xd9, 0x18, 0xd4, 0x0c, 0x03, 0x5f, 0x06, 0xa0, 0xa2, 0x99, 0x10, 0x92, 0x06, 0x67, 0xe4, 0x25, 0x40, 0x2a, 0x9a, 0x61, 0x64, 0x48, 0x33, 0x8c, 0xbd, 0x0c, 0xd8, 0x80, 0x66, 0xa6, 0xd0, 0xaa, 0xe5, 0x32, 0xa0, 0x03, 0x9a, 0x61, 0x74, 0x50, 0x33, 0x0c, 0xbe, 0x02, 0x60, 0x55, 0x33, 0x61, 0xac, 0x6a, 0x78, 0x11, 0xb0, 0xaa, 0x66, 0xd4, 0xd9, 0xb9, 0x9a, 0x61, 0xe8, 0x55, 0x80, 0x2a, 0x9a, 0x51, 0xad, 0x7a, 0x9a, 0x61, 0xe8, 0x35, 0x80, 0xaa, 0x9a, 0x51, 0xb1, 0x9e, 0x66, 0x18, 0x7b, 0x1d, 0xb0, 0xaa, 0x66, 0x18, 0x7b, 0x5b, 0xd5, 0x0c, 0x43, 0x3f, 0xd2, 0x00, 0xab, 0x88, 0x86, 0xa1, 0x6f, 0x06, 0x44, 0xc3, 0xd8, 0x8f, 0x11, 0xab, 0xaa, 0x26, 0x0c, 0x56, 0x57, 0xe1, 0x13, 0x04, 0xab, 0xb2, 0x61, 0xb0, 0x2f, 0x1b, 0x37, 0x04, 0x95, 0x6f, 0x40, 0xa4, 0x72, 0x65, 0xe3, 0xc6, 0x30, 0x55, 0x36, 0x1e, 0xf0, 0x15, 0x0a, 0xb5, 0x2c, 0x9b, 0x29, 0x24, 0x8c, 0xee, 0x21, 0x6f, 0x02, 0xd2, 0x93, 0x8d, 0x87, 0x0c, 0xc8, 0xc6, 0xc3, 0xbe, 0x0a, 0x58, 0x45, 0x36, 0x33, 0xd0, 0xaa, 0xe5, 0x0a, 0xa0, 0x15, 0xd9, 0x78, 0x68, 0x55, 0x36, 0x1e, 0xf8, 0x33, 0x00, 0xf6, 0x65, 0x33, 0x8d, 0x55, 0x0d, 0x7f, 0x16, 0xb0, 0xbe, 0x6c, 0x82, 0xb3, 0x93, 0xb2, 0xf1, 0xa0, 0xaf, 0x01, 0xd4, 0x93, 0x4d, 0xd0, 0x2a, 0xcb, 0xc6, 0x83, 0xbe, 0x0e, 0x50, 0x5f, 0x36, 0x41, 0x2c, 0xcb, 0xc6, 0xc3, 0xbe, 0x41, 0xf9, 0xcd, 0x95, 0x8d, 0x87, 0x55, 0x64, 0xe3, 0x41, 0x7f, 0x13, 0x73, 0xa1, 0x27, 0x1b, 0x0f, 0xaa, 0xca, 0xc6, 0xc3, 0xfe, 0x16, 0x62, 0x7d, 0xd9, 0x4c, 0x83, 0xd5, 0x55, 0xf8, 0x6d, 0x04, 0xfb, 0xb2, 0xf1, 0xc0, 0x4b, 0xe4, 0x04, 0xca, 0xe6, 0xc8, 0xee, 0xb4, 0x4f, 0x7b, 0x28, 0xb1, 0x5b, 0xa8, 0x9b, 0x46, 0x6a, 0x32, 0x3a, 0xb5, 0xd1, 0x13, 0xe8, 0x7c, 0xe8, 0xf6, 0x01, 0x7e, 0xc1, 0x95, 0x8f, 0x4f, 0xb8, 0x8d, 0xfa, 0x69, 0x24, 0x40, 0xba, 0x25, 0xa9, 0xa1, 0x69, 0x3c, 0xf8, 0xe2, 0xe3, 0xef, 0xa0, 0x8a, 0x1a, 0x09, 0x50, 0x6f, 0x49, 0x2a, 0xc9, 0xc7, 0xd7, 0xc4, 0x05, 0x5f, 0x4a, 0x3e, 0xe3, 0x4d, 0xd4, 0x52, 0x23, 0x59, 0x33, 0x97, 0xad, 0x05, 0x57, 0x50, 0xb3, 0x48, 0x81, 0x61, 0xde, 0x42, 0x49, 0x35, 0x92, 0xab, 0x75, 0x8f, 0xa4, 0x8e, 0x64, 0xa2, 0x0c, 0x59, 0x58, 0x3e, 0xe7, 0x6d, 0x54, 0x56, 0x23, 0x05, 0x03, 0x2d, 0x83, 0x18, 0x65, 0xf7, 0x0c, 0x4e, 0x60, 0x9c, 0x25, 0x54, 0x58, 0x23, 0x05, 0xe3, 0xb8, 0x9c, 0xe0, 0x38, 0x0b, 0xae, 0xd0, 0x7c, 0xca, 0xe7, 0x50, 0x69, 0x8d, 0x4c, 0xad, 0x5a, 0xaf, 0xae, 0xdc, 0x83, 0x55, 0xa0, 0x7e, 0x9f, 0x53, 0xc7, 0x71, 0x58, 0x72, 0x3e, 0x69, 0x19, 0x35, 0xd7, 0xc8, 0x98, 0x6b, 0xd5, 0xbb, 0xe6, 0x5d, 0x18, 0x49, 0x02, 0x7c, 0xd6, 0x17, 0x90, 0xc5, 0xe2, 0xf3, 0x59, 0x55, 0x54, 0x5f, 0x43, 0x3f, 0xb1, 0x7b, 0x3d, 0xe7, 0xad, 0x9b, 0x95, 0x0f, 0x9d, 0x51, 0xef, 0xe8, 0xd5, 0x8a, 0x00, 0xbe, 0x84, 0xaa, 0xa3, 0x2e, 0xb8, 0x82, 0xf4, 0xe9, 0xbf, 0x8c, 0xe7, 0xb0, 0x62, 0x23, 0xbb, 0xde, 0x3d, 0x1e, 0x38, 0x63, 0x1b, 0x7c, 0x25, 0x44, 0x68, 0x4d, 0xf6, 0xc3, 0xeb, 0xf8, 0x2b, 0x48, 0x5b, 0x68, 0x24, 0xdf, 0x06, 0x51, 0xe8, 0xac, 0xd0, 0x19, 0x9c, 0xc0, 0x3a, 0xfe, 0x2a, 0x72, 0x0c, 0xe0, 0x80, 0x30, 0x74, 0x16, 0xaa, 0xcf, 0x59, 0x13, 0x97, 0x42, 0x79, 0xb1, 0x35, 0x6c, 0x3f, 0x7e, 0x02, 0x3c, 0x13, 0xd3, 0xe3, 0x7a, 0x42, 0xd7, 0xac, 0x0b, 0x81, 0x14, 0xb9, 0x47, 0xdd, 0xc6, 0x3d, 0x71, 0x39, 0x9c, 0x28, 0x5d, 0x66, 0x0d, 0xf3, 0x25, 0x31, 0x2f, 0x06, 0x73, 0x66, 0x88, 0xaa, 0x04, 0x60, 0x97, 0x5a, 0xc7, 0x04, 0xea, 0x53, 0xfd, 0x48, 0xcc, 0xd4, 0xff, 0x27, 0xae, 0x4c, 0xa7, 0x52, 0x97, 0xbc, 0x82, 0x19, 0x95, 0xc8, 0x97, 0xc2, 0x59, 0x75, 0x8a, 0x3e, 0x63, 0xec, 0x55, 0x4c, 0xb1, 0x2a, 0x7d, 0x6a, 0xf4, 0x77, 0x44, 0x79, 0x2a, 0xd9, 0xba, 0xec, 0x35, 0xcc, 0xb9, 0xc4, 0x7e, 0x39, 0x94, 0x77, 0xc3, 0xe4, 0x19, 0x43, 0xdf, 0xc5, 0x24, 0xac, 0x90, 0xa7, 0x46, 0xa6, 0x25, 0x0b, 0xa6, 0x63, 0x97, 0x7b, 0x0f, 0xb3, 0x32, 0x2f, 0x59, 0x20, 0x33, 0xab, 0xe3, 0x86, 0xf2, 0xb3, 0xcb, 0x6d, 0x60, 0x9a, 0xe6, 0x71, 0x83, 0xa9, 0x9a, 0xc9, 0x9f, 0x47, 0xf2, 0xfe, 0xec, 0x19, 0xff, 0x38, 0x89, 0x09, 0x96, 0xd9, 0xfb, 0xb3, 0xa6, 0xec, 0xb1, 0x67, 0x4c, 0xf9, 0x27, 0xc8, 0x36, 0x14, 0xf6, 0xd4, 0x9c, 0x1f, 0x0a, 0xaf, 0xe2, 0x38, 0x1e, 0x39, 0xa7, 0xc3, 0xf2, 0x26, 0x1c, 0xed, 0x84, 0x79, 0x63, 0xaa, 0xfa, 0x71, 0x0f, 0x79, 0x5b, 0x88, 0xb2, 0x82, 0x24, 0x69, 0x45, 0xda, 0x95, 0x56, 0xf6, 0x60, 0xdc, 0xd9, 0x56, 0x24, 0xca, 0xb3, 0xa2, 0x90, 0xd0, 0x8a, 0x1b, 0xf4, 0xa5, 0x95, 0xf7, 0x61, 0x53, 0xcd, 0xb2, 0xe2, 0xa6, 0x00, 0xb6, 0x12, 0x20, 0x2d, 0xae, 0xf8, 0xf5, 0x16, 0xf5, 0x1b, 0x9f, 0x0d, 0x17, 0x60, 0x5b, 0x74, 0x7e, 0x0e, 0x56, 0x5a, 0x92, 0xa6, 0x38, 0x37, 0x4d, 0xfb, 0xff, 0x11, 0xb4, 0x80, 0x37, 0xd3, 0xb4, 0x9f, 0x9a, 0x41, 0xab, 0xfc, 0x9a, 0x06, 0xc5, 0x26, 0xd4, 0x93, 0x46, 0x4e, 0xa4, 0xde, 0x6b, 0x6e, 0x3f, 0xd4, 0x5f, 0xc2, 0x5f, 0xeb, 0xcd, 0xe6, 0x23, 0x5d, 0x33, 0xf2, 0x22, 0xbd, 0xfe, 0x95, 0x83, 0x8d, 0x7d, 0x3d, 0x61, 0x94, 0x44, 0x61, 0x73, 0x7b, 0x77, 0x6b, 0xc3, 0xda, 0xb3, 0xb6, 0x77, 0x0f, 0xf4, 0x24, 0xf6, 0x6d, 0x3e, 0x6a, 0xde, 0x3f, 0xd0, 0x53, 0x46, 0x56, 0x24, 0xb1, 0x2d, 0x6d, 0x08, 0x91, 0xd9, 0x3f, 0x80, 0xfe, 0x2d, 0x3d, 0x83, 0x56, 0x0e, 0xb6, 0x77, 0x36, 0xf4, 0x2c, 0x22, 0x0f, 0xde, 0xdd, 0x7b, 0xb4, 0xa1, 0xe7, 0xf0, 0xe7, 0x7d, 0xcb, 0xba, 0xff, 0x15, 0x3d, 0x8f, 0xa4, 0x9d, 0xfb, 0x7b, 0xba, 0xa0, 0xee, 0xfb, 0xeb, 0xd0, 0x5d, 0x30, 0x8a, 0x22, 0xb7, 0xf9, 0xee, 0xee, 0x83, 0x83, 0xed, 0xe6, 0xae, 0x5e, 0xac, 0xfc, 0x7a, 0x42, 0x88, 0x2d, 0x67, 0xff, 0x49, 0x77, 0x48, 0x55, 0xf1, 0x75, 0x21, 0xc6, 0xf0, 0xbb, 0x45, 0xd2, 0xe3, 0xca, 0x2e, 0x8f, 0x2d, 0x14, 0x74, 0x8c, 0x57, 0x45, 0x91, 0xba, 0x3b, 0x32, 0x14, 0x50, 0x41, 0x97, 0xb5, 0x0a, 0xd8, 0xc6, 0xd1, 0x21, 0x08, 0x59, 0xad, 0x53, 0x1d, 0x97, 0x51, 0x20, 0xab, 0x75, 0xa8, 0xef, 0xe9, 0xb1, 0x35, 0xa6, 0xb0, 0x4e, 0xb5, 0x5b, 0xde, 0xa2, 0x71, 0x65, 0xa0, 0x07, 0x91, 0xd3, 0x98, 0x52, 0x16, 0xa5, 0x69, 0x89, 0xba, 0xee, 0x2e, 0xe1, 0x0f, 0x29, 0x0b, 0x9f, 0xb0, 0xd8, 0x14, 0x79, 0xaf, 0x1d, 0xc7, 0xa2, 0x56, 0x9e, 0x91, 0x4e, 0x33, 0x12, 0xd4, 0xe4, 0x4d, 0x49, 0x02, 0xd8, 0x9b, 0x05, 0xf2, 0x46, 0x92, 0xa4, 0x3b, 0x95, 0xeb, 0x62, 0x6e, 0xd7, 0x19, 0xc8, 0x2d, 0x44, 0xab, 0x54, 0x14, 0x5a, 0xbb, 0xac, 0x51, 0x09, 0xa3, 0xb5, 0x2b, 0x37, 0x84, 0x50, 0xfa, 0x74, 0xa1, 0x1d, 0xca, 0x3e, 0xda, 0x88, 0xda, 0x61, 0xe5, 0x4d, 0x91, 0xd9, 0x69, 0x3f, 0x3b, 0x68, 0x1f, 0xc3, 0x58, 0xa2, 0xd7, 0x1e, 0x4f, 0x60, 0x6d, 0x50, 0x2a, 0xff, 0x0b, 0xff, 0x34, 0x3a, 0x71, 0xe5, 0xb1, 0x55, 0x4a, 0xe5, 0xa9, 0x10, 0xcd, 0xde, 0xd1, 0x8e, 0x3d, 0x1e, 0xb7, 0x8f, 0x6d, 0x38, 0x2f, 0x64, 0x06, 0x60, 0xd4, 0xc6, 0x6b, 0x0a, 0x2c, 0xe6, 0xaf, 0xfa, 0xab, 0xe0, 0xa3, 0x96, 0x76, 0x09, 0x62, 0x31, 0x14, 0x3c, 0x48, 0x0e, 0x4e, 0xfb, 0x74, 0x59, 0x91, 0xb6, 0xf0, 0xe7, 0xe2, 0x35, 0x91, 0x91, 0x18, 0xbc, 0x14, 0x19, 0xb4, 0xfb, 0x76, 0x59, 0x8e, 0x4b, 0xbf, 0x2b, 0xbf, 0xa4, 0x09, 0xb1, 0x6b, 0x7f, 0x78, 0x8e, 0x31, 0x7d, 0x54, 0xcc, 0x98, 0x49, 0x39, 0xe6, 0x3b, 0x71, 0x63, 0xa2, 0xce, 0x3a, 0x8e, 0x73, 0xd4, 0x92, 0xaf, 0x58, 0xde, 0xab, 0xe4, 0xb1, 0x85, 0xde, 0x5a, 0xe5, 0x7d, 0x51, 0xdc, 0x1e, 0x0c, 0xec, 0x91, 0xeb, 0x13, 0x98, 0x38, 0x71, 0xc6, 0x13, 0xbe, 0xe0, 0xa1, 0xdf, 0x46, 0x59, 0xa4, 0x86, 0xce, 0x68, 0x22, 0xe7, 0xd9, 0x48, 0xc1, 0x99, 0x66, 0xd9, 0xa2, 0x16, 0xe3, 0x9a, 0xc8, 0x3f, 0x76, 0x80, 0xfe, 0x18, 0x27, 0x91, 0xa4, 0xda, 0xc2, 0x6f, 0xa8, 0xfc, 0x82, 0x26, 0x8a, 0xcd, 0xc9, 0x89, 0x6f, 0x1c, 0x7c, 0x7f, 0x62, 0x3f, 0x27, 0xf7, 0xc0, 0x77, 0xf8, 0x89, 0x57, 0x3b, 0x3f, 0xdd, 0xee, 0x9d, 0xca, 0x0b, 0x9f, 0xa2, 0x25, 0x1f, 0x8c, 0x4b, 0x22, 0xf3, 0xa1, 0xdd, 0x3d, 0x3e, 0x99, 0x90, 0xcd, 0x84, 0xc5, 0x4f, 0x50, 0x26, 0xa4, 0xbb, 0xe8, 0x6c, 0x39, 0x45, 0xeb, 0x75, 0xc9, 0x5f, 0x2f, 0x75, 0x0e, 0x96, 0x04, 0xdd, 0xc9, 0xe5, 0x8e, 0xf4, 0x9f, 0x83, 0x7f, 0x89, 0xca, 0xff, 0x24, 0x45, 0x7e, 0xe7, 0xb9, 0xeb, 0x05, 0x8c, 0xf9, 0xd8, 0x39, 0x1d, 0xc8, 0x39, 0xa6, 0x2d, 0xf9, 0xe0, 0xad, 0x5d, 0x42, 0x59, 0x3b, 0x40, 0x3e, 0x3d, 0x75, 0x26, 0x36, 0xb9, 0x91, 0xb7, 0xe4, 0x03, 0xce, 0x62, 0x68, 0x4f, 0xc0, 0x07, 0xac, 0xfc, 0xf0, 0xa7, 0xef, 0x57, 0xfa, 0x1c, 0x7e, 0xc1, 0xf9, 0x37, 0xe3, 0xe0, 0xaa, 0x8c, 0xcb, 0x19, 0xba, 0x74, 0x52, 0xe0, 0xea, 0x6a, 0x59, 0x8c, 0x02, 0x99, 0xe4, 0x21, 0x9e, 0xb7, 0xe4, 0x08, 0xc5, 0x30, 0x25, 0x30, 0x42, 0x0e, 0x80, 0xd4, 0x60, 0xac, 0x88, 0xdc, 0x61, 0xf7, 0x89, 0x3d, 0x3e, 0x81, 0x17, 0x93, 0x05, 0xaf, 0xe6, 0xcd, 0x2b, 0x3e, 0xc7, 0x5b, 0x8b, 0xa5, 0x07, 0x4e, 0xcf, 0x19, 0x59, 0x1e, 0x14, 0xf2, 0x6d, 0x7e, 0xec, 0xf4, 0x6d, 0x29, 0x96, 0x1c, 0xa5, 0x89, 0xeb, 0xb3, 0x78, 0xfb, 0x00, 0x72, 0xc3, 0x81, 0x8b, 0x37, 0xae, 0x4a, 0x47, 0x0f, 0xf1, 0x30, 0x58, 0x16, 0x54, 0xec, 0xa2, 0x43, 0x74, 0x38, 0x34, 0x16, 0xd1, 0xa1, 0xe3, 0x0e, 0xe6, 0x78, 0x88, 0x76, 0x58, 0x29, 0x79, 0xcf, 0x8b, 0x6f, 0x41, 0x1c, 0x71, 0x0d, 0xfa, 0x71, 0x44, 0xee, 0xdd, 0x3c, 0x6d, 0x2e, 0x19, 0x47, 0xe4, 0xc6, 0x7d, 0x4d, 0xa4, 0xc9, 0x6d, 0x8c, 0xb9, 0xd6, 0x06, 0x86, 0x78, 0x88, 0xb9, 0x5b, 0xd6, 0xc6, 0xc6, 0x2e, 0xc4, 0x78, 0x8c, 0xf6, 0x8f, 0xde, 0xdd, 0xd0, 0x13, 0xca, 0xeb, 0xff, 0x0d, 0x4d, 0x24, 0x37, 0x9e, 0xd1, 0x2b, 0xc6, 0x69, 0xb8, 0xdb, 0x03, 0x7f, 0x9b, 0xab, 0x22, 0xd5, 0x77, 0x46, 0xb6, 0x71, 0x61, 0xc6, 0x2c, 0xcb, 0xc7, 0xf4, 0x3a, 0x95, 0x7b, 0x51, 0xb0, 0x62, 0x11, 0xde, 0x7c, 0x43, 0xa4, 0x26, 0x36, 0xd8, 0x9c, 0xc9, 0x3b, 0x91, 0x03, 0x20, 0xc0, 0x84, 0x98, 0x04, 0x9b, 0xf4, 0x10, 0x5e, 0xc9, 0x4c, 0x68, 0x97, 0xa6, 0xc7, 0x90, 0xca, 0x7b, 0x42, 0x7f, 0xe0, 0xf4, 0x87, 0x3d, 0xfb, 0x19, 0x8c, 0x64, 0x0f, 0xc6, 0x90, 0xff, 0x50, 0x84, 0x9d, 0xee, 0x88, 0xb6, 0x24, 0xdd, 0x7e, 0xd2, 0x03, 0x6e, 0x91, 0xb1, 0x0d, 0x5b, 0xed, 0x88, 0xa3, 0x0f, 0x3f, 0x21, 0x7a, 0x72, 0xd2, 0x1d, 0xe1, 0x6e, 0xc4, 0xa0, 0x29, 0x1f, 0x2a, 0x5b, 0xa2, 0xc4, 0xa7, 0xe6, 0x31, 0x0f, 0x5c, 0xb9, 0x23, 0x8a, 0x6e, 0x13, 0x5d, 0x05, 0xc3, 0xc2, 0xbd, 0xbf, 0x61, 0x35, 0x61, 0x35, 0x61, 0x59, 0x9b, 0xbb, 0x1b, 0xb0, 0x96, 0xf0, 0xe3, 0xe0, 0xcb, 0xcd, 0xc0, 0x52, 0x5e, 0x13, 0x45, 0xcf, 0xf7, 0x7d, 0x7b, 0x42, 0x3d, 0x18, 0x5d, 0xb3, 0x8d, 0x44, 0x4e, 0xab, 0x64, 0x45, 0x7a, 0xa3, 0x3f, 0x9c, 0x3c, 0xaf, 0xfc, 0xac, 0x28, 0x30, 0xe8, 0x51, 0x17, 0x9c, 0x5d, 0x13, 0xd9, 0x3e, 0xcf, 0x57, 0xa3, 0x03, 0x8c, 0xaa, 0x29, 0x1f, 0xe7, 0xfe, 0xb6, 0x5c, 0xf4, 0x62, 0x4d, 0x64, 0x95, 0xc0, 0xc4, 0xfb, 0x33, 0xa1, 0xee, 0x4f, 0xb9, 0x93, 0x93, 0xca, 0x4e, 0xae, 0xec, 0x88, 0xac, 0x4c, 0x27, 0x63, 0x4a, 0x91, 0xb2, 0xf8, 0x91, 0x62, 0x92, 0x6f, 0xbe, 0x20, 0xdb, 0xe4, 0x7d, 0x2c, 0xc8, 0x8d, 0x04, 0xcb, 0x08, 0x19, 0x87, 0x04, 0x35, 0x49, 0xb9, 0xfd, 0x4e, 0x5a, 0xe4, 0xdc, 0x95, 0x02, 0x89, 0x67, 0x64, 0xc5, 0x41, 0xa6, 0xdc, 0x8a, 0x38, 0x4d, 0x35, 0x06, 0x74, 0x66, 0xb9, 0xaa, 0xe0, 0x50, 0x89, 0xe5, 0x6f, 0x46, 0x56, 0x11, 0x5e, 0x27, 0x24, 0xea, 0xa4, 0x57, 0xeb, 0x66, 0x64, 0x9d, 0x60, 0xdc, 0x14, 0x79, 0xaf, 0x32, 0xa0, 0xe0, 0xc6, 0x85, 0x6d, 0xce, 0x2d, 0x05, 0x14, 0x04, 0x18, 0x48, 0xfb, 0x55, 0x6c, 0xae, 0xe3, 0xe7, 0xfa, 0x9c, 0x7b, 0xbe, 0xa7, 0x0b, 0x69, 0xb7, 0x64, 0xcd, 0xf2, 0x89, 0xde, 0x07, 0x80, 0x85, 0xac, 0x52, 0x9f, 0x66, 0xf9, 0xd4, 0x0e, 0x80, 0x2c, 0x9f, 0xd3, 0x69, 0xeb, 0xfb, 0xc5, 0x68, 0x46, 0x9e, 0xcd, 0x61, 0x39, 0x73, 0xee, 0x69, 0x9c, 0xf6, 0xa5, 0x5f, 0x79, 0x66, 0xf9, 0x04, 0x6e, 0xbc, 0x89, 0x10, 0xb9, 0xfc, 0x10, 0x02, 0x66, 0x97, 0x99, 0x59, 0x2e, 0x33, 0x61, 0x52, 0x59, 0xae, 0x2e, 0x29, 0x24, 0x28, 0x25, 0x65, 0x46, 0x96, 0x94, 0xc6, 0x0d, 0x32, 0x27, 0x27, 0x55, 0xf4, 0xcb, 0xc7, 0x2c, 0x1f, 0xd9, 0xfd, 0x7e, 0x3a, 0xff, 0x78, 0xa5, 0x62, 0x96, 0x0f, 0xe5, 0xc6, 0x2a, 0xbe, 0x2f, 0xd4, 0x37, 0x9c, 0x7d, 0x30, 0x08, 0x96, 0x7d, 0xe1, 0xb9, 0xef, 0x54, 0xc6, 0xc0, 0x86, 0x8c, 0x20, 0xf0, 0x2a, 0x69, 0x37, 0x2c, 0x22, 0x6f, 0xaf, 0x3b, 0xe8, 0xc0, 0xa1, 0x08, 0x57, 0x22, 0x09, 0x3f, 0xa1, 0x0f, 0x5b, 0xa4, 0x06, 0x76, 0xb1, 0x4f, 0xa7, 0xbe, 0xd4, 0xdb, 0xb2, 0x13, 0x9b, 0x20, 0x57, 0xa6, 0xa1, 0xb3, 0x3d, 0x80, 0xd3, 0x0d, 0xf1, 0x06, 0xed, 0x81, 0x95, 0xea, 0x40, 0x83, 0xf1, 0x86, 0x48, 0x8e, 0x4f, 0x0f, 0xcb, 0x46, 0xf8, 0x5b, 0xc1, 0xfe, 0xe9, 0xa1, 0xeb, 0x8a, 0x85, 0x08, 0xb0, 0x9f, 0x03, 0x81, 0xb6, 0x7e, 0xc6, 0x1e, 0x39, 0xe5, 0x0b, 0xb4, 0x84, 0x2f, 0x59, 0x59, 0x68, 0x79, 0x1f, 0x1a, 0xce, 0x19, 0xfc, 0xe0, 0xa4, 0x54, 0x50, 0xec, 0xc2, 0x71, 0x57, 0x1b, 0xc8, 0xb4, 0xdb, 0xd0, 0xd6, 0x2c, 0x6d, 0x50, 0x39, 0x10, 0x45, 0xf7, 0x54, 0x4e, 0xf3, 0x35, 0x71, 0x27, 0x81, 0x59, 0xda, 0x9f, 0xf3, 0xe6, 0x35, 0xdf, 0x3d, 0x15, 0xc6, 0xe9, 0x42, 0x42, 0x2b, 0x7a, 0xc8, 0x15, 0xad, 0xf2, 0x43, 0x48, 0xf8, 0x3b, 0x10, 0x1d, 0xbd, 0x1b, 0x48, 0xd8, 0xa0, 0x87, 0xb0, 0x33, 0xc6, 0x64, 0x36, 0x67, 0xc9, 0x07, 0xe3, 0x35, 0x51, 0xa4, 0x1f, 0x6e, 0x35, 0x95, 0xf0, 0x8a, 0xf5, 0x02, 0xb5, 0x73, 0x09, 0x05, 0x3b, 0x1e, 0x5e, 0xe2, 0x98, 0x23, 0x19, 0xfd, 0x36, 0x3e, 0x23, 0x0a, 0xf8, 0xd7, 0x65, 0xa6, 0xbc, 0xd3, 0x9f, 0xc0, 0x66, 0x26, 0xbe, 0x21, 0xe6, 0xe8, 0xed, 0x7b, 0xb0, 0xac, 0x57, 0x98, 0x17, 0x65, 0x07, 0x03, 0xcb, 0x22, 0x2b, 0x43, 0xc1, 0x98, 0xbe, 0xff, 0xe4, 0x2d, 0xf7, 0x11, 0xc3, 0x2b, 0x1d, 0xab, 0x65, 0x8e, 0xce, 0x5a, 0xfc, 0x54, 0xb9, 0x2f, 0x72, 0x94, 0xa5, 0xe0, 0x4c, 0x68, 0x54, 0x84, 0x76, 0x5c, 0xb6, 0x29, 0x47, 0x5e, 0x54, 0xce, 0xcc, 0xdc, 0xbd, 0xb4, 0x65, 0x69, 0xc7, 0x8b, 0x0b, 0x42, 0xdb, 0xc2, 0x43, 0xec, 0x33, 0x0e, 0xd3, 0xda, 0xb3, 0x4a, 0x93, 0x4d, 0xc0, 0x11, 0x2f, 0xce, 0x04, 0x74, 0x4b, 0x13, 0xaf, 0x4c, 0x99, 0xc0, 0xa7, 0xe7, 0xfc, 0x31, 0x4c, 0x7b, 0x8e, 0x87, 0x66, 0xda, 0x9e, 0xe0, 0xf8, 0x9e, 0x03, 0xf3, 0xc3, 0xee, 0x0e, 0x1d, 0x6e, 0xe0, 0x50, 0xdc, 0xa9, 0x7c, 0x9a, 0x12, 0xf3, 0x1c, 0x44, 0xbf, 0xdc, 0x9d, 0x9c, 0xec, 0xb4, 0x87, 0xc6, 0x23, 0x51, 0xc4, 0xf8, 0xd9, 0xea, 0xb7, 0x87, 0x43, 0xdc, 0xa8, 0x1a, 0x1d, 0x2a, 0x6e, 0x4f, 0x05, 0x65, 0xc6, 0x2f, 0xed, 0x02, 0x78, 0x47, 0x62, 0x37, 0x06, 0x93, 0xd1, 0x73, 0xab, 0x30, 0xf0, 0x5b, 0x8c, 0x6d, 0x51, 0xe8, 0x8f, 0x8f, 0x3d, 0x63, 0x09, 0x32, 0x76, 0x2b, 0xd2, 0xd8, 0xce, 0xf8, 0x38, 0x60, 0x4b, 0xf4, 0xbd, 0x06, 0x74, 0x0c, 0x23, 0xaf, 0x67, 0x2b, 0x79, 0x86, 0x63, 0x18, 0x24, 0x82, 0x8e, 0x1d, 0xfa, 0x2d, 0x50, 0xf7, 0x0a, 0xdc, 0x48, 0x13, 0x07, 0x2b, 0x0e, 0xd2, 0x4a, 0xc1, 0x7c, 0x3d, 0xd2, 0x16, 0xc4, 0xa4, 0x03, 0x07, 0xfe, 0x23, 0x0d, 0xe1, 0x16, 0xa4, 0xc7, 0xc5, 0x2f, 0x08, 0x3d, 0x3c, 0x7f, 0xf5, 0x20, 0x9b, 0x9e, 0x71, 0x90, 0xcd, 0xf3, 0x41, 0xb6, 0x91, 0xb8, 0xab, 0x2d, 0xbe, 0x27, 0x4a, 0xa1, 0x29, 0xab, 0x74, 0x43, 0xd2, 0xdf, 0x56, 0xe9, 0x05, 0xf3, 0xb2, 0xf2, 0x29, 0x56, 0x7d, 0xb5, 0xaa, 0x5d, 0xf0, 0x2b, 0x3c, 0x7d, 0xd5, 0x70, 0x2e, 0xe6, 0x80, 0x4d, 0xfc, 0x77, 0xc4, 0x5c, 0x60, 0xca, 0x2a, 0x39, 0x7f, 0xc6, 0xa4, 0x2a, 0x3f, 0x9f, 0x16, 0xe9, 0xe6, 0xc0, 0x76, 0x3a, 0xc6, 0xe5, 0x60, 0x46, 0xfc, 0xe2, 0x4b, 0x6e, 0x36, 0xbc, 0x12, 0xca, 0x86, 0xd0, 0xe3, 0xe6, 0xc2, 0x2b, 0xa1, 0x5c, 0xe8, 0x76, 0x41, 0xc0, 0xbe, 0x3e, 0x95, 0x09, 0xa1, 0xd3, 0x4f, 0x83, 0xd7, 0xa7, 0xd2, 0xa0, 0xdf, 0x0d, 0xec, 0xab, 0xe1, 0x1c, 0x08, 0xbd, 0x5e, 0xfe, 0xbb, 0x1a, 0xce, 0x7f, 0x5e, 0x27, 0x30, 0xaf, 0x84, 0x72, 0x1f, 0xb9, 0x24, 0xb3, 0xde, 0xd5, 0x70, 0xd6, 0x23, 0x1e, 0xe7, 0xbb, 0xab, 0xe1, 0x7c, 0x47, 0x9d, 0x9c, 0xdf, 0xae, 0x84, 0xf2, 0x1b, 0x19, 0x95, 0x89, 0xed, 0x6a, 0x38, 0xb1, 0x49, 0x9e, 0xe2, 0xa9, 0x9a, 0xd5, 0xbc, 0x4e, 0xf0, 0xd4, 0x0c, 0xa5, 0xb4, 0xe8, 0x73, 0x3d, 0xbd, 0x0b, 0x0a, 0xef, 0x75, 0x5c, 0x36, 0xf7, 0xc8, 0x59, 0x8a, 0xf9, 0x5a, 0x4d, 0xab, 0xe9, 0x1e, 0xb9, 0x4c, 0x91, 0xed, 0x70, 0xdd, 0xa8, 0x53, 0x8c, 0x52, 0x64, 0x49, 0x2f, 0x7f, 0x69, 0xb3, 0x45, 0xb1, 0x8a, 0xe6, 0x25, 0x4f, 0xef, 0xb7, 0x20, 0x18, 0xb5, 0x1e, 0xb5, 0x47, 0xc7, 0x00, 0x6c, 0x41, 0x25, 0xee, 0xd5, 0xde, 0xf8, 0xfe, 0x0b, 0x1d, 0xee, 0xc1, 0x12, 0xfd, 0x92, 0x2b, 0xae, 0x23, 0xea, 0xd5, 0x58, 0x5e, 0x8b, 0x97, 0x71, 0xd1, 0xa4, 0x31, 0x8a, 0x7a, 0x0b, 0x1c, 0xf5, 0xd6, 0xe1, 0x74, 0x79, 0x3a, 0x80, 0x13, 0xf1, 0x7a, 0x5e, 0x64, 0x27, 0xce, 0xa8, 0xdf, 0x9e, 0x38, 0x95, 0x1f, 0x41, 0x45, 0x0d, 0x27, 0xe6, 0x3e, 0x74, 0x3c, 0x85, 0xc2, 0x11, 0xd2, 0x5e, 0xbf, 0xfd, 0x04, 0xe2, 0x87, 0xdd, 0x7a, 0x3c, 0x72, 0xf7, 0x41, 0x1e, 0x9b, 0x76, 0xec, 0x07, 0x20, 0xf1, 0xb2, 0x7b, 0x18, 0x27, 0xed, 0x90, 0x24, 0xf9, 0x70, 0x7e, 0x91, 0x8f, 0x97, 0x19, 0x7e, 0x87, 0xee, 0x01, 0x53, 0x56, 0x0c, 0x59, 0x7e, 0x7b, 0xf4, 0x84, 0x92, 0x9f, 0xd8, 0xfd, 0x61, 0xeb, 0x31, 0x49, 0x05, 0xe5, 0x90, 0xc6, 0xe7, 0x07, 0xb0, 0x8b, 0x93, 0x90, 0x1a, 0x49, 0x24, 0x67, 0xbc, 0x17, 0xc4, 0x41, 0x1e, 0x4c, 0x42, 0xec, 0x23, 0xd9, 0x14, 0xcc, 0x05, 0xe5, 0x44, 0x20, 0x93, 0x10, 0xc2, 0xa0, 0xdf, 0x9b, 0xf7, 0x9d, 0x92, 0x48, 0x6e, 0x36, 0x9b, 0x98, 0xe5, 0xe1, 0x4f, 0x55, 0xd7, 0x1a, 0x9f, 0x13, 0xb9, 0xe3, 0x91, 0x6d, 0x63, 0x78, 0x98, 0x5d, 0x5d, 0x7c, 0x40, 0x59, 0xcd, 0x03, 0x35, 0xe0, 0x68, 0xfc, 0x58, 0xd6, 0x17, 0x46, 0x44, 0xd5, 0x59, 0xfe, 0x5d, 0x79, 0x17, 0xb1, 0xe8, 0x77, 0x87, 0x2b, 0x12, 0xcb, 0xb5, 0xd1, 0xd8, 0x83, 0x82, 0xaf, 0x75, 0x96, 0xc1, 0x8f, 0x64, 0x76, 0x89, 0x33, 0x98, 0x1b, 0x71, 0x53, 0x63, 0x43, 0x2c, 0x0c, 0x1c, 0xf7, 0xfe, 0xbf, 0x75, 0x24, 0xf7, 0xd8, 0x95, 0xe9, 0x43, 0x9b, 0x6b, 0xdc, 0x96, 0xdf, 0xdc, 0x06, 0x0e, 0x77, 0xc8, 0x5d, 0xd9, 0x78, 0x20, 0x74, 0xc5, 0x0c, 0x15, 0x99, 0x71, 0x56, 0x3a, 0xf2, 0x23, 0x9f, 0x67, 0x85, 0xf6, 0x7d, 0xc8, 0x88, 0xdc, 0x99, 0x31, 0x46, 0x8e, 0xe5, 0x17, 0x53, 0xcf, 0x08, 0x85, 0xba, 0x69, 0x23, 0x18, 0x6b, 0xa2, 0x8d, 0x9c, 0xc8, 0x8f, 0xa9, 0xaa, 0x91, 0xd5, 0x7a, 0x68, 0x55, 0x4e, 0xcf, 0x74, 0xa5, 0x2b, 0xbf, 0x85, 0x7a, 0x56, 0x64, 0x00, 0x9c, 0x61, 0x26, 0xde, 0x99, 0x0f, 0xe4, 0x67, 0xd2, 0x80, 0x99, 0x29, 0x6f, 0xc6, 0x67, 0x7a, 0xf3, 0x44, 0x7e, 0x93, 0xf4, 0xcc, 0xec, 0xcf, 0xf2, 0x66, 0x7c, 0xa6, 0x37, 0x3d, 0xf9, 0xb5, 0x32, 0x60, 0x06, 0xbc, 0xd9, 0x12, 0x86, 0xfa, 0xaa, 0x39, 0x4f, 0xc4, 0xd8, 0xe9, 0xcb, 0x6f, 0xd0, 0xfe, 0xcb, 0x96, 0x94, 0x59, 0x86, 0xe2, 0x1d, 0x1a, 0xc8, 0xcf, 0xd3, 0x41, 0x43, 0xe0, 0xd1, 0xb6, 0xb8, 0xa0, 0x4e, 0xec, 0x1c, 0x2e, 0x39, 0x60, 0xa9, 0x64, 0x2d, 0xf8, 0x53, 0x63, 0xce, 0x4c, 0x53, 0xf1, 0x4e, 0x0d, 0xc1, 0x94, 0x3e, 0x65, 0x0a, 0xbc, 0xba, 0x2f, 0x4a, 0x8a, 0xa9, 0x43, 0xca, 0xd0, 0xd1, 0x66, 0x9e, 0xca, 0xff, 0x4f, 0xc0, 0x33, 0x83, 0x19, 0x3d, 0xfc, 0xc6, 0x38, 0xc7, 0x45, 0x1b, 0x19, 0xc9, 0x8f, 0xdc, 0xbe, 0x2f, 0xc4, 0x08, 0x6d, 0x09, 0xaa, 0xb4, 0xe3, 0xac, 0x8c, 0xe5, 0xe7, 0x6f, 0xdf, 0x15, 0x24, 0x34, 0xba, 0x81, 0xe9, 0xd8, 0x98, 0xe4, 0x62, 0x6c, 0x4c, 0x28, 0x22, 0xbf, 0x1e, 0x09, 0x58, 0x52, 0xaf, 0x42, 0x94, 0x69, 0xe3, 0x23, 0xbc, 0x84, 0xf9, 0xf3, 0x07, 0xa4, 0x8f, 0x34, 0x59, 0x17, 0xd7, 0x96, 0xb0, 0x74, 0xb6, 0xe6, 0x8e, 0x02, 0x71, 0x69, 0x43, 0xcc, 0x9d, 0x3b, 0x28, 0x7d, 0xac, 0xc9, 0xea, 0x12, 0x2d, 0x59, 0xc5, 0xa3, 0x60, 0x64, 0x9a, 0x3b, 0x77, 0x58, 0xfa, 0x44, 0x93, 0x57, 0x11, 0x75, 0xd3, 0x33, 0xe2, 0x46, 0xa6, 0xb9, 0x73, 0x87, 0xa5, 0xaf, 0xca, 0xda, 0x31, 0x51, 0xaf, 0xa9, 0x46, 0x28, 0x16, 0xcc, 0x9f, 0x3f, 0x2c, 0x7d, 0x4d, 0xa3, 0x6b, 0x89, 0x44, 0xbd, 0xee, 0xad, 0x8b, 0x17, 0x99, 0xe6, 0xcf, 0x1f, 0x96, 0xbe, 0xae, 0xd1, 0xe5, 0x45, 0xa2, 0xbe, 0x12, 0x30, 0x13, 0xf4, 0xe6, 0xec, 0xb0, 0xf4, 0x0d, 0x8d, 0xee, 0x13, 0x12, 0xf5, 0x55, 0xcf, 0xcc, 0xfe, 0x94, 0x37, 0x67, 0x87, 0xa5, 0x6f, 0xd2, 0x29, 0x1e, 0xcc, 0xac, 0x05, 0xcc, 0x50, 0x64, 0x2a, 0xbd, 0x40, 0x58, 0xfa, 0x96, 0x46, 0xd7, 0x3e, 0x89, 0xfa, 0x5d, 0xcb, 0x1d, 0xdd, 0x8f, 0x4c, 0xa5, 0x17, 0x08, 0x4b, 0x9f, 0x6a, 0x74, 0x3b, 0x94, 0xa8, 0xdf, 0x0b, 0x1a, 0xa2, 0xc8, 0xa4, 0xbf, 0x48, 0x58, 0xfa, 0x36, 0x5a, 0x2a, 0x35, 0x12, 0x2b, 0xcb, 0x96, 0xeb, 0x80, 0x12, 0x99, 0xf4, 0x17, 0x09, 0x4b, 0xdf, 0x41, 0x53, 0x3a, 0x98, 0xaa, 0x86, 0x4c, 0x81, 0x57, 0x0f, 0x44, 0xf1, 0xbc, 0x61, 0xe9, 0xbb, 0xea, 0xad, 0x5b, 0xe1, 0x48, 0x89, 0x4d, 0x7b, 0xca, 0x3b, 0x3b, 0x33, 0x30, 0x7d, 0x8f, 0x6a, 0x9c, 0xc6, 0xdc, 0x17, 0xe5, 0xcd, 0x94, 0x24, 0xf8, 0xaf, 0x4f, 0x86, 0xa9, 0x1d, 0x7f, 0x7f, 0x9c, 0x19, 0xa3, 0xbe, 0xaf, 0xd1, 0xf5, 0x55, 0x91, 0x0d, 0x12, 0xde, 0xdb, 0x29, 0x32, 0x60, 0x7d, 0xe0, 0xcf, 0xf2, 0xac, 0x68, 0xf5, 0x03, 0xed, 0x45, 0xc2, 0x55, 0x03, 0x6f, 0x6b, 0xbd, 0xc5, 0xa0, 0x96, 0xcf, 0x8b, 0xd4, 0x33, 0x73, 0xb9, 0xaa, 0x1e, 0xc9, 0xd4, 0x5b, 0x5b, 0x19, 0xa4, 0x0a, 0x66, 0x49, 0xb9, 0xd8, 0xc6, 0x6b, 0x5b, 0x8b, 0x58, 0xcc, 0x36, 0x23, 0xd9, 0x1f, 0xc7, 0xb0, 0x4d, 0x66, 0xd7, 0x22, 0xd9, 0x9f, 0xc4, 0xb0, 0x6b, 0xcc, 0xae, 0x47, 0xb2, 0xbf, 0x1a, 0xc3, 0xae, 0x33, 0x7b, 0x25, 0x92, 0xfd, 0xb5, 0x18, 0xf6, 0x0a, 0xb3, 0x57, 0x23, 0xd9, 0x5f, 0x8f, 0x61, 0xaf, 0x32, 0x7b, 0x2d, 0x92, 0xfd, 0x8d, 0x18, 0xf6, 0x1a, 0xb3, 0xef, 0x46, 0xb2, 0xbf, 0x19, 0xc3, 0xbe, 0xcb, 0xec, 0x7b, 0x91, 0xec, 0x6f, 0xc5, 0xb0, 0xef, 0x49, 0x76, 0x75, 0x39, 0x92, 0xfd, 0x69, 0x34, 0xbb, 0xba, 0xcc, 0xec, 0x68, 0xad, 0x7d, 0x3b, 0x86, 0xcd, 0x5a, 0xab, 0x46, 0x6b, 0xed, 0x3b, 0x31, 0x6c, 0xd6, 0x5a, 0x35, 0x5a, 0x6b, 0xdf, 0x8d, 0x61, 0xb3, 0xd6, 0xaa, 0xd1, 0x5a, 0xfb, 0x5e, 0x0c, 0x9b, 0xb5, 0x56, 0x8d, 0xd6, 0xda, 0xf7, 0x63, 0xd8, 0xac, 0xb5, 0x6a, 0xb4, 0xd6, 0x7e, 0x10, 0xc3, 0x66, 0xad, 0x55, 0xa3, 0xb5, 0xf6, 0x7b, 0x31, 0x6c, 0xd6, 0x5a, 0x35, 0x5a, 0x6b, 0xbf, 0x1f, 0xc3, 0x66, 0xad, 0x55, 0xa3, 0xb5, 0xf6, 0x07, 0x31, 0x6c, 0xd6, 0x9a, 0x19, 0xad, 0xb5, 0x3f, 0x8c, 0x66, 0x9b, 0xac, 0x35, 0x33, 0x5a, 0x6b, 0x7f, 0x14, 0xc3, 0x66, 0xad, 0x99, 0xd1, 0x5a, 0xfb, 0xe3, 0x18, 0x36, 0x6b, 0xcd, 0x8c, 0xd6, 0xda, 0x0f, 0x63, 0xd8, 0xac, 0x35, 0x33, 0x5a, 0x6b, 0x7f, 0x12, 0xc3, 0x66, 0xad, 0x99, 0xd1, 0x5a, 0xfb, 0xd3, 0x18, 0x36, 0x6b, 0xcd, 0x8c, 0xd6, 0xda, 0x9f, 0xc5, 0xb0, 0x59, 0x6b, 0x66, 0xb4, 0xd6, 0xfe, 0x3c, 0x86, 0xcd, 0x5a, 0x33, 0xa3, 0xb5, 0xf6, 0x17, 0x31, 0x6c, 0xd6, 0x9a, 0x19, 0xad, 0xb5, 0xbf, 0x8c, 0x61, 0xb3, 0xd6, 0x6a, 0xd1, 0x5a, 0xfb, 0xab, 0x68, 0x76, 0x8d, 0xb5, 0x56, 0x8b, 0xd6, 0xda, 0x5f, 0xc7, 0xb0, 0x59, 0x6b, 0xb5, 0x68, 0xad, 0xfd, 0x4d, 0x0c, 0x9b, 0xb5, 0x56, 0x8b, 0xd6, 0xda, 0xdf, 0xc6, 0xb0, 0x59, 0x6b, 0xb5, 0x68, 0xad, 0xfd, 0x28, 0x86, 0xcd, 0x5a, 0xab, 0x45, 0x6b, 0xed, 0xef, 0x62, 0xd8, 0xac, 0xb5, 0x5a, 0xb4, 0xd6, 0xfe, 0x3e, 0x86, 0xcd, 0x5a, 0xab, 0x45, 0x6b, 0xed, 0x1f, 0x62, 0xd8, 0xac, 0xb5, 0x5a, 0xb4, 0xd6, 0xfe, 0x31, 0x86, 0xcd, 0x5a, 0xab, 0x45, 0x6b, 0xed, 0x9f, 0x62, 0xd8, 0xac, 0xb5, 0x7a, 0xb4, 0xd6, 0xfe, 0x39, 0x9a, 0x5d, 0x67, 0xad, 0xd5, 0xa3, 0xb5, 0xf6, 0x2f, 0x31, 0x6c, 0xd6, 0x5a, 0x3d, 0x5a, 0x6b, 0xff, 0x1a, 0xc3, 0x66, 0xad, 0xd5, 0xa3, 0xb5, 0xf6, 0x6f, 0x31, 0x6c, 0xd6, 0x5a, 0x3d, 0x5a, 0x6b, 0xff, 0x1e, 0xc3, 0x66, 0xad, 0xd5, 0xa3, 0xb5, 0xf6, 0x1f, 0x31, 0x6c, 0xd6, 0x5a, 0x3d, 0x5a, 0x6b, 0x3f, 0x8e, 0x61, 0xb3, 0xd6, 0xea, 0xd1, 0x5a, 0xfb, 0x49, 0x0c, 0x9b, 0xb5, 0x56, 0x8f, 0xd6, 0xda, 0x7f, 0xc6, 0xb0, 0x59, 0x6b, 0xf5, 0x68, 0xad, 0xfd, 0x57, 0x0c, 0x9b, 0xb5, 0xb6, 0x12, 0xad, 0xb5, 0xff, 0x8e, 0x66, 0xaf, 0x2c, 0xff, 0x5f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x53, 0x6a, 0x15, 0xef, 0x13, 0x38, 0x00, 0x00, } lxd-2.0.0/dist/src/github.com/golang/protobuf/proto/testdata/Makefile0000644061062106075000000000363012702772352030233 0ustar00stgraberdomain admins00000000000000# Go support for Protocol Buffers - Google's data interchange format # # Copyright 2010 The Go Authors. All rights reserved. # https://github.com/golang/protobuf # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. include ../../Make.protobuf all: regenerate regenerate: rm -f test.pb.go make test.pb.go # The following rules are just aids to development. Not needed for typical testing. diff: regenerate git diff test.pb.go restore: cp test.pb.go.golden test.pb.go preserve: cp test.pb.go test.pb.go.golden lxd-2.0.0/dist/src/github.com/golang/protobuf/proto/testdata/test.proto0000644061062106075000000003602012702772352030636 0ustar00stgraberdomain admins00000000000000// Go support for Protocol Buffers - Google's data interchange format // // Copyright 2010 The Go Authors. All rights reserved. // https://github.com/golang/protobuf // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // A feature-rich test file for the protocol compiler and libraries. syntax = "proto2"; package testdata; enum FOO { FOO1 = 1; }; message GoEnum { required FOO foo = 1; } message GoTestField { required string Label = 1; required string Type = 2; } message GoTest { // An enum, for completeness. enum KIND { VOID = 0; // Basic types BOOL = 1; BYTES = 2; FINGERPRINT = 3; FLOAT = 4; INT = 5; STRING = 6; TIME = 7; // Groupings TUPLE = 8; ARRAY = 9; MAP = 10; // Table types TABLE = 11; // Functions FUNCTION = 12; // last tag }; // Some typical parameters required KIND Kind = 1; optional string Table = 2; optional int32 Param = 3; // Required, repeated and optional foreign fields. required GoTestField RequiredField = 4; repeated GoTestField RepeatedField = 5; optional GoTestField OptionalField = 6; // Required fields of all basic types required bool F_Bool_required = 10; required int32 F_Int32_required = 11; required int64 F_Int64_required = 12; required fixed32 F_Fixed32_required = 13; required fixed64 F_Fixed64_required = 14; required uint32 F_Uint32_required = 15; required uint64 F_Uint64_required = 16; required float F_Float_required = 17; required double F_Double_required = 18; required string F_String_required = 19; required bytes F_Bytes_required = 101; required sint32 F_Sint32_required = 102; required sint64 F_Sint64_required = 103; // Repeated fields of all basic types repeated bool F_Bool_repeated = 20; repeated int32 F_Int32_repeated = 21; repeated int64 F_Int64_repeated = 22; repeated fixed32 F_Fixed32_repeated = 23; repeated fixed64 F_Fixed64_repeated = 24; repeated uint32 F_Uint32_repeated = 25; repeated uint64 F_Uint64_repeated = 26; repeated float F_Float_repeated = 27; repeated double F_Double_repeated = 28; repeated string F_String_repeated = 29; repeated bytes F_Bytes_repeated = 201; repeated sint32 F_Sint32_repeated = 202; repeated sint64 F_Sint64_repeated = 203; // Optional fields of all basic types optional bool F_Bool_optional = 30; optional int32 F_Int32_optional = 31; optional int64 F_Int64_optional = 32; optional fixed32 F_Fixed32_optional = 33; optional fixed64 F_Fixed64_optional = 34; optional uint32 F_Uint32_optional = 35; optional uint64 F_Uint64_optional = 36; optional float F_Float_optional = 37; optional double F_Double_optional = 38; optional string F_String_optional = 39; optional bytes F_Bytes_optional = 301; optional sint32 F_Sint32_optional = 302; optional sint64 F_Sint64_optional = 303; // Default-valued fields of all basic types optional bool F_Bool_defaulted = 40 [default=true]; optional int32 F_Int32_defaulted = 41 [default=32]; optional int64 F_Int64_defaulted = 42 [default=64]; optional fixed32 F_Fixed32_defaulted = 43 [default=320]; optional fixed64 F_Fixed64_defaulted = 44 [default=640]; optional uint32 F_Uint32_defaulted = 45 [default=3200]; optional uint64 F_Uint64_defaulted = 46 [default=6400]; optional float F_Float_defaulted = 47 [default=314159.]; optional double F_Double_defaulted = 48 [default=271828.]; optional string F_String_defaulted = 49 [default="hello, \"world!\"\n"]; optional bytes F_Bytes_defaulted = 401 [default="Bignose"]; optional sint32 F_Sint32_defaulted = 402 [default = -32]; optional sint64 F_Sint64_defaulted = 403 [default = -64]; // Packed repeated fields (no string or bytes). repeated bool F_Bool_repeated_packed = 50 [packed=true]; repeated int32 F_Int32_repeated_packed = 51 [packed=true]; repeated int64 F_Int64_repeated_packed = 52 [packed=true]; repeated fixed32 F_Fixed32_repeated_packed = 53 [packed=true]; repeated fixed64 F_Fixed64_repeated_packed = 54 [packed=true]; repeated uint32 F_Uint32_repeated_packed = 55 [packed=true]; repeated uint64 F_Uint64_repeated_packed = 56 [packed=true]; repeated float F_Float_repeated_packed = 57 [packed=true]; repeated double F_Double_repeated_packed = 58 [packed=true]; repeated sint32 F_Sint32_repeated_packed = 502 [packed=true]; repeated sint64 F_Sint64_repeated_packed = 503 [packed=true]; // Required, repeated, and optional groups. required group RequiredGroup = 70 { required string RequiredField = 71; }; repeated group RepeatedGroup = 80 { required string RequiredField = 81; }; optional group OptionalGroup = 90 { required string RequiredField = 91; }; } // For testing skipping of unrecognized fields. // Numbers are all big, larger than tag numbers in GoTestField, // the message used in the corresponding test. message GoSkipTest { required int32 skip_int32 = 11; required fixed32 skip_fixed32 = 12; required fixed64 skip_fixed64 = 13; required string skip_string = 14; required group SkipGroup = 15 { required int32 group_int32 = 16; required string group_string = 17; } } // For testing packed/non-packed decoder switching. // A serialized instance of one should be deserializable as the other. message NonPackedTest { repeated int32 a = 1; } message PackedTest { repeated int32 b = 1 [packed=true]; } message MaxTag { // Maximum possible tag number. optional string last_field = 536870911; } message OldMessage { message Nested { optional string name = 1; } optional Nested nested = 1; optional int32 num = 2; } // NewMessage is wire compatible with OldMessage; // imagine it as a future version. message NewMessage { message Nested { optional string name = 1; optional string food_group = 2; } optional Nested nested = 1; // This is an int32 in OldMessage. optional int64 num = 2; } // Smaller tests for ASCII formatting. message InnerMessage { required string host = 1; optional int32 port = 2 [default=4000]; optional bool connected = 3; } message OtherMessage { optional int64 key = 1; optional bytes value = 2; optional float weight = 3; optional InnerMessage inner = 4; extensions 100 to max; } message MyMessage { required int32 count = 1; optional string name = 2; optional string quote = 3; repeated string pet = 4; optional InnerMessage inner = 5; repeated OtherMessage others = 6; repeated InnerMessage rep_inner = 12; enum Color { RED = 0; GREEN = 1; BLUE = 2; }; optional Color bikeshed = 7; optional group SomeGroup = 8 { optional int32 group_field = 9; } // This field becomes [][]byte in the generated code. repeated bytes rep_bytes = 10; optional double bigfloat = 11; extensions 100 to max; } message Ext { extend MyMessage { optional Ext more = 103; optional string text = 104; optional int32 number = 105; } optional string data = 1; } extend MyMessage { repeated string greeting = 106; } message ComplexExtension { optional int32 first = 1; optional int32 second = 2; repeated int32 third = 3; } extend OtherMessage { optional ComplexExtension complex = 200; repeated ComplexExtension r_complex = 201; } message DefaultsMessage { enum DefaultsEnum { ZERO = 0; ONE = 1; TWO = 2; }; extensions 100 to max; } extend DefaultsMessage { optional double no_default_double = 101; optional float no_default_float = 102; optional int32 no_default_int32 = 103; optional int64 no_default_int64 = 104; optional uint32 no_default_uint32 = 105; optional uint64 no_default_uint64 = 106; optional sint32 no_default_sint32 = 107; optional sint64 no_default_sint64 = 108; optional fixed32 no_default_fixed32 = 109; optional fixed64 no_default_fixed64 = 110; optional sfixed32 no_default_sfixed32 = 111; optional sfixed64 no_default_sfixed64 = 112; optional bool no_default_bool = 113; optional string no_default_string = 114; optional bytes no_default_bytes = 115; optional DefaultsMessage.DefaultsEnum no_default_enum = 116; optional double default_double = 201 [default = 3.1415]; optional float default_float = 202 [default = 3.14]; optional int32 default_int32 = 203 [default = 42]; optional int64 default_int64 = 204 [default = 43]; optional uint32 default_uint32 = 205 [default = 44]; optional uint64 default_uint64 = 206 [default = 45]; optional sint32 default_sint32 = 207 [default = 46]; optional sint64 default_sint64 = 208 [default = 47]; optional fixed32 default_fixed32 = 209 [default = 48]; optional fixed64 default_fixed64 = 210 [default = 49]; optional sfixed32 default_sfixed32 = 211 [default = 50]; optional sfixed64 default_sfixed64 = 212 [default = 51]; optional bool default_bool = 213 [default = true]; optional string default_string = 214 [default = "Hello, string"]; optional bytes default_bytes = 215 [default = "Hello, bytes"]; optional DefaultsMessage.DefaultsEnum default_enum = 216 [default = ONE]; } message MyMessageSet { option message_set_wire_format = true; extensions 100 to max; } message Empty { } extend MyMessageSet { optional Empty x201 = 201; optional Empty x202 = 202; optional Empty x203 = 203; optional Empty x204 = 204; optional Empty x205 = 205; optional Empty x206 = 206; optional Empty x207 = 207; optional Empty x208 = 208; optional Empty x209 = 209; optional Empty x210 = 210; optional Empty x211 = 211; optional Empty x212 = 212; optional Empty x213 = 213; optional Empty x214 = 214; optional Empty x215 = 215; optional Empty x216 = 216; optional Empty x217 = 217; optional Empty x218 = 218; optional Empty x219 = 219; optional Empty x220 = 220; optional Empty x221 = 221; optional Empty x222 = 222; optional Empty x223 = 223; optional Empty x224 = 224; optional Empty x225 = 225; optional Empty x226 = 226; optional Empty x227 = 227; optional Empty x228 = 228; optional Empty x229 = 229; optional Empty x230 = 230; optional Empty x231 = 231; optional Empty x232 = 232; optional Empty x233 = 233; optional Empty x234 = 234; optional Empty x235 = 235; optional Empty x236 = 236; optional Empty x237 = 237; optional Empty x238 = 238; optional Empty x239 = 239; optional Empty x240 = 240; optional Empty x241 = 241; optional Empty x242 = 242; optional Empty x243 = 243; optional Empty x244 = 244; optional Empty x245 = 245; optional Empty x246 = 246; optional Empty x247 = 247; optional Empty x248 = 248; optional Empty x249 = 249; optional Empty x250 = 250; } message MessageList { repeated group Message = 1 { required string name = 2; required int32 count = 3; } } message Strings { optional string string_field = 1; optional bytes bytes_field = 2; } message Defaults { enum Color { RED = 0; GREEN = 1; BLUE = 2; } // Default-valued fields of all basic types. // Same as GoTest, but copied here to make testing easier. optional bool F_Bool = 1 [default=true]; optional int32 F_Int32 = 2 [default=32]; optional int64 F_Int64 = 3 [default=64]; optional fixed32 F_Fixed32 = 4 [default=320]; optional fixed64 F_Fixed64 = 5 [default=640]; optional uint32 F_Uint32 = 6 [default=3200]; optional uint64 F_Uint64 = 7 [default=6400]; optional float F_Float = 8 [default=314159.]; optional double F_Double = 9 [default=271828.]; optional string F_String = 10 [default="hello, \"world!\"\n"]; optional bytes F_Bytes = 11 [default="Bignose"]; optional sint32 F_Sint32 = 12 [default=-32]; optional sint64 F_Sint64 = 13 [default=-64]; optional Color F_Enum = 14 [default=GREEN]; // More fields with crazy defaults. optional float F_Pinf = 15 [default=inf]; optional float F_Ninf = 16 [default=-inf]; optional float F_Nan = 17 [default=nan]; // Sub-message. optional SubDefaults sub = 18; // Redundant but explicit defaults. optional string str_zero = 19 [default=""]; } message SubDefaults { optional int64 n = 1 [default=7]; } message RepeatedEnum { enum Color { RED = 1; } repeated Color color = 1; } message MoreRepeated { repeated bool bools = 1; repeated bool bools_packed = 2 [packed=true]; repeated int32 ints = 3; repeated int32 ints_packed = 4 [packed=true]; repeated int64 int64s_packed = 7 [packed=true]; repeated string strings = 5; repeated fixed32 fixeds = 6; } // GroupOld and GroupNew have the same wire format. // GroupNew has a new field inside a group. message GroupOld { optional group G = 101 { optional int32 x = 2; } } message GroupNew { optional group G = 101 { optional int32 x = 2; optional int32 y = 3; } } message FloatingPoint { required double f = 1; } message MessageWithMap { map name_mapping = 1; map msg_mapping = 2; map byte_mapping = 3; map str_to_str = 4; } message Oneof { oneof union { bool F_Bool = 1; int32 F_Int32 = 2; int64 F_Int64 = 3; fixed32 F_Fixed32 = 4; fixed64 F_Fixed64 = 5; uint32 F_Uint32 = 6; uint64 F_Uint64 = 7; float F_Float = 8; double F_Double = 9; string F_String = 10; bytes F_Bytes = 11; sint32 F_Sint32 = 12; sint64 F_Sint64 = 13; MyMessage.Color F_Enum = 14; GoTestField F_Message = 15; group F_Group = 16 { optional int32 x = 17; } int32 F_Largest_Tag = 536870911; } oneof tormato { int32 value = 100; } } message Communique { optional bool make_me_cry = 1; // This is a oneof, called "union". oneof union { int32 number = 5; string name = 6; bytes data = 7; double temp_c = 8; MyMessage.Color col = 9; Strings msg = 10; } } lxd-2.0.0/dist/src/github.com/golang/protobuf/CONTRIBUTORS0000644061062106075000000000025212702772352025474 0ustar00stgraberdomain admins00000000000000# This source code was written by the Go contributors. # The master list of contributors is in the main Go distribution, # visible at http://tip.golang.org/CONTRIBUTORS. lxd-2.0.0/dist/src/github.com/golang/protobuf/LICENSE0000644061062106075000000000305712702772352024627 0ustar00stgraberdomain admins00000000000000Go support for Protocol Buffers - Google's data interchange format Copyright 2010 The Go Authors. All rights reserved. https://github.com/golang/protobuf Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Google Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. lxd-2.0.0/dist/src/github.com/golang/protobuf/README.md0000644061062106075000000001575512702772352025111 0ustar00stgraberdomain admins00000000000000# Go support for Protocol Buffers Google's data interchange format. Copyright 2010 The Go Authors. https://github.com/golang/protobuf This package and the code it generates requires at least Go 1.4. This software implements Go bindings for protocol buffers. For information about protocol buffers themselves, see https://developers.google.com/protocol-buffers/ ## Installation ## To use this software, you must: - Install the standard C++ implementation of protocol buffers from https://developers.google.com/protocol-buffers/ - Of course, install the Go compiler and tools from https://golang.org/ See https://golang.org/doc/install for details or, if you are using gccgo, follow the instructions at https://golang.org/doc/install/gccgo - Grab the code from the repository and install the proto package. The simplest way is to run `go get -u github.com/golang/protobuf/{proto,protoc-gen-go}`. The compiler plugin, protoc-gen-go, will be installed in $GOBIN, defaulting to $GOPATH/bin. It must be in your $PATH for the protocol compiler, protoc, to find it. This software has two parts: a 'protocol compiler plugin' that generates Go source files that, once compiled, can access and manage protocol buffers; and a library that implements run-time support for encoding (marshaling), decoding (unmarshaling), and accessing protocol buffers. There is support for gRPC in Go using protocol buffers. See the note at the bottom of this file for details. There are no insertion points in the plugin. ## Using protocol buffers with Go ## Once the software is installed, there are two steps to using it. First you must compile the protocol buffer definitions and then import them, with the support library, into your program. To compile the protocol buffer definition, run protoc with the --go_out parameter set to the directory you want to output the Go code to. protoc --go_out=. *.proto The generated files will be suffixed .pb.go. See the Test code below for an example using such a file. The package comment for the proto library contains text describing the interface provided in Go for protocol buffers. Here is an edited version. ========== The proto package converts data structures to and from the wire format of protocol buffers. It works in concert with the Go source code generated for .proto files by the protocol compiler. A summary of the properties of the protocol buffer interface for a protocol buffer variable v: - Names are turned from camel_case to CamelCase for export. - There are no methods on v to set fields; just treat them as structure fields. - There are getters that return a field's value if set, and return the field's default value if unset. The getters work even if the receiver is a nil message. - The zero value for a struct is its correct initialization state. All desired fields must be set before marshaling. - A Reset() method will restore a protobuf struct to its zero state. - Non-repeated fields are pointers to the values; nil means unset. That is, optional or required field int32 f becomes F *int32. - Repeated fields are slices. - Helper functions are available to aid the setting of fields. Helpers for getting values are superseded by the GetFoo methods and their use is deprecated. msg.Foo = proto.String("hello") // set field - Constants are defined to hold the default values of all fields that have them. They have the form Default_StructName_FieldName. Because the getter methods handle defaulted values, direct use of these constants should be rare. - Enums are given type names and maps from names to values. Enum values are prefixed with the enum's type name. Enum types have a String method, and a Enum method to assist in message construction. - Nested groups and enums have type names prefixed with the name of the surrounding message type. - Extensions are given descriptor names that start with E_, followed by an underscore-delimited list of the nested messages that contain it (if any) followed by the CamelCased name of the extension field itself. HasExtension, ClearExtension, GetExtension and SetExtension are functions for manipulating extensions. - Oneof field sets are given a single field in their message, with distinguished wrapper types for each possible field value. - Marshal and Unmarshal are functions to encode and decode the wire format. When the .proto file specifies `syntax="proto3"`, there are some differences: - Non-repeated fields of non-message type are values instead of pointers. - Getters are only generated for message and oneof fields. - Enum types do not get an Enum method. Consider file test.proto, containing ```proto package example; enum FOO { X = 17; }; message Test { required string label = 1; optional int32 type = 2 [default=77]; repeated int64 reps = 3; optional group OptionalGroup = 4 { required string RequiredField = 5; } } ``` To create and play with a Test object from the example package, ```go package main import ( "log" "github.com/golang/protobuf/proto" "path/to/example" ) func main() { test := &example.Test { Label: proto.String("hello"), Type: proto.Int32(17), Reps: []int64{1, 2, 3}, Optionalgroup: &example.Test_OptionalGroup { RequiredField: proto.String("good bye"), }, } data, err := proto.Marshal(test) if err != nil { log.Fatal("marshaling error: ", err) } newTest := &example.Test{} err = proto.Unmarshal(data, newTest) if err != nil { log.Fatal("unmarshaling error: ", err) } // Now test and newTest contain the same data. if test.GetLabel() != newTest.GetLabel() { log.Fatalf("data mismatch %q != %q", test.GetLabel(), newTest.GetLabel()) } // etc. } ``` ## Parameters ## To pass extra parameters to the plugin, use a comma-separated parameter list separated from the output directory by a colon: protoc --go_out=plugins=grpc,import_path=mypackage:. *.proto - `import_prefix=xxx` - a prefix that is added onto the beginning of all imports. Useful for things like generating protos in a subdirectory, or regenerating vendored protobufs in-place. - `import_path=foo/bar` - used as the package if no input files declare `go_package`. If it contains slashes, everything up to the rightmost slash is ignored. - `plugins=plugin1+plugin2` - specifies the list of sub-plugins to load. The only plugin in this repo is `grpc`. - `Mfoo/bar.proto=quux/shme` - declares that foo/bar.proto is associated with Go package quux/shme. This is subject to the import_prefix parameter. ## gRPC Support ## If a proto file specifies RPC services, protoc-gen-go can be instructed to generate code compatible with gRPC (http://www.grpc.io/). To do this, pass the `plugins` parameter to protoc-gen-go; the usual way is to insert it into the --go_out argument to protoc: protoc --go_out=plugins=grpc:. *.proto ## Plugins ## The `protoc-gen-go/generator` package exposes a plugin interface, which is used by the gRPC code generation. This interface is not supported and is subject to incompatible changes without notice. lxd-2.0.0/dist/src/github.com/golang/protobuf/AUTHORS0000644061062106075000000000025512702772352024667 0ustar00stgraberdomain admins00000000000000# This source code refers to The Go Authors for copyright purposes. # The master list of authors is in the main Go distribution, # visible at http://tip.golang.org/AUTHORS. lxd-2.0.0/dist/src/github.com/golang/protobuf/Makefile0000644061062106075000000000404012702772352025253 0ustar00stgraberdomain admins00000000000000# Go support for Protocol Buffers - Google's data interchange format # # Copyright 2010 The Go Authors. All rights reserved. # https://github.com/golang/protobuf # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. all: install install: go install ./proto ./jsonpb ./ptypes go install ./protoc-gen-go test: go test ./proto ./jsonpb ./ptypes make -C protoc-gen-go/testdata test clean: go clean ./... nuke: go clean -i ./... regenerate: make -C protoc-gen-go/descriptor regenerate make -C protoc-gen-go/plugin regenerate make -C protoc-gen-go/testdata regenerate make -C proto/testdata regenerate make -C jsonpb/jsonpb_test_proto regenerate lxd-2.0.0/dist/src/github.com/golang/protobuf/Make.protobuf0000644061062106075000000000364312702772352026262 0ustar00stgraberdomain admins00000000000000# Go support for Protocol Buffers - Google's data interchange format # # Copyright 2010 The Go Authors. All rights reserved. # https://github.com/golang/protobuf # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # Includable Makefile to add a rule for generating .pb.go files from .proto files # (Google protocol buffer descriptions). # Typical use if myproto.proto is a file in package mypackage in this directory: # # include $(GOROOT)/src/pkg/github.com/golang/protobuf/Make.protobuf %.pb.go: %.proto protoc --go_out=. $< lxd-2.0.0/dist/src/github.com/golang/protobuf/protoc-gen-go/0000755061062106075000000000000012702772352026275 5ustar00stgraberdomain admins00000000000000lxd-2.0.0/dist/src/github.com/golang/protobuf/protoc-gen-go/doc.go0000644061062106075000000000456412702772352027402 0ustar00stgraberdomain admins00000000000000// Go support for Protocol Buffers - Google's data interchange format // // Copyright 2010 The Go Authors. All rights reserved. // https://github.com/golang/protobuf // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /* A plugin for the Google protocol buffer compiler to generate Go code. Run it by building this program and putting it in your path with the name protoc-gen-go That word 'go' at the end becomes part of the option string set for the protocol compiler, so once the protocol compiler (protoc) is installed you can run protoc --go_out=output_directory input_directory/file.proto to generate Go bindings for the protocol defined by file.proto. With that input, the output will be written to output_directory/file.pb.go The generated code is documented in the package comment for the library. See the README and documentation for protocol buffers to learn more: https://developers.google.com/protocol-buffers/ */ package documentation lxd-2.0.0/dist/src/github.com/golang/protobuf/protoc-gen-go/plugin/0000755061062106075000000000000012702772352027573 5ustar00stgraberdomain admins00000000000000lxd-2.0.0/dist/src/github.com/golang/protobuf/protoc-gen-go/plugin/plugin.pb.go0000644061062106075000000002522212702772352032023 0ustar00stgraberdomain admins00000000000000// Code generated by protoc-gen-go. // source: google/protobuf/compiler/plugin.proto // DO NOT EDIT! /* Package plugin_go is a generated protocol buffer package. It is generated from these files: google/protobuf/compiler/plugin.proto It has these top-level messages: CodeGeneratorRequest CodeGeneratorResponse */ package plugin_go import proto "github.com/golang/protobuf/proto" import fmt "fmt" import math "math" import google_protobuf "github.com/golang/protobuf/protoc-gen-go/descriptor" // Reference imports to suppress errors if they are not otherwise used. var _ = proto.Marshal var _ = fmt.Errorf var _ = math.Inf // This is a compile-time assertion to ensure that this generated file // is compatible with the proto package it is being compiled against. const _ = proto.ProtoPackageIsVersion1 // An encoded CodeGeneratorRequest is written to the plugin's stdin. type CodeGeneratorRequest struct { // The .proto files that were explicitly listed on the command-line. The // code generator should generate code only for these files. Each file's // descriptor will be included in proto_file, below. FileToGenerate []string `protobuf:"bytes,1,rep,name=file_to_generate,json=fileToGenerate" json:"file_to_generate,omitempty"` // The generator parameter passed on the command-line. Parameter *string `protobuf:"bytes,2,opt,name=parameter" json:"parameter,omitempty"` // FileDescriptorProtos for all files in files_to_generate and everything // they import. The files will appear in topological order, so each file // appears before any file that imports it. // // protoc guarantees that all proto_files will be written after // the fields above, even though this is not technically guaranteed by the // protobuf wire format. This theoretically could allow a plugin to stream // in the FileDescriptorProtos and handle them one by one rather than read // the entire set into memory at once. However, as of this writing, this // is not similarly optimized on protoc's end -- it will store all fields in // memory at once before sending them to the plugin. ProtoFile []*google_protobuf.FileDescriptorProto `protobuf:"bytes,15,rep,name=proto_file,json=protoFile" json:"proto_file,omitempty"` XXX_unrecognized []byte `json:"-"` } func (m *CodeGeneratorRequest) Reset() { *m = CodeGeneratorRequest{} } func (m *CodeGeneratorRequest) String() string { return proto.CompactTextString(m) } func (*CodeGeneratorRequest) ProtoMessage() {} func (*CodeGeneratorRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } func (m *CodeGeneratorRequest) GetFileToGenerate() []string { if m != nil { return m.FileToGenerate } return nil } func (m *CodeGeneratorRequest) GetParameter() string { if m != nil && m.Parameter != nil { return *m.Parameter } return "" } func (m *CodeGeneratorRequest) GetProtoFile() []*google_protobuf.FileDescriptorProto { if m != nil { return m.ProtoFile } return nil } // The plugin writes an encoded CodeGeneratorResponse to stdout. type CodeGeneratorResponse struct { // Error message. If non-empty, code generation failed. The plugin process // should exit with status code zero even if it reports an error in this way. // // This should be used to indicate errors in .proto files which prevent the // code generator from generating correct code. Errors which indicate a // problem in protoc itself -- such as the input CodeGeneratorRequest being // unparseable -- should be reported by writing a message to stderr and // exiting with a non-zero status code. Error *string `protobuf:"bytes,1,opt,name=error" json:"error,omitempty"` File []*CodeGeneratorResponse_File `protobuf:"bytes,15,rep,name=file" json:"file,omitempty"` XXX_unrecognized []byte `json:"-"` } func (m *CodeGeneratorResponse) Reset() { *m = CodeGeneratorResponse{} } func (m *CodeGeneratorResponse) String() string { return proto.CompactTextString(m) } func (*CodeGeneratorResponse) ProtoMessage() {} func (*CodeGeneratorResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } func (m *CodeGeneratorResponse) GetError() string { if m != nil && m.Error != nil { return *m.Error } return "" } func (m *CodeGeneratorResponse) GetFile() []*CodeGeneratorResponse_File { if m != nil { return m.File } return nil } // Represents a single generated file. type CodeGeneratorResponse_File struct { // The file name, relative to the output directory. The name must not // contain "." or ".." components and must be relative, not be absolute (so, // the file cannot lie outside the output directory). "/" must be used as // the path separator, not "\". // // If the name is omitted, the content will be appended to the previous // file. This allows the generator to break large files into small chunks, // and allows the generated text to be streamed back to protoc so that large // files need not reside completely in memory at one time. Note that as of // this writing protoc does not optimize for this -- it will read the entire // CodeGeneratorResponse before writing files to disk. Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` // If non-empty, indicates that the named file should already exist, and the // content here is to be inserted into that file at a defined insertion // point. This feature allows a code generator to extend the output // produced by another code generator. The original generator may provide // insertion points by placing special annotations in the file that look // like: // @@protoc_insertion_point(NAME) // The annotation can have arbitrary text before and after it on the line, // which allows it to be placed in a comment. NAME should be replaced with // an identifier naming the point -- this is what other generators will use // as the insertion_point. Code inserted at this point will be placed // immediately above the line containing the insertion point (thus multiple // insertions to the same point will come out in the order they were added). // The double-@ is intended to make it unlikely that the generated code // could contain things that look like insertion points by accident. // // For example, the C++ code generator places the following line in the // .pb.h files that it generates: // // @@protoc_insertion_point(namespace_scope) // This line appears within the scope of the file's package namespace, but // outside of any particular class. Another plugin can then specify the // insertion_point "namespace_scope" to generate additional classes or // other declarations that should be placed in this scope. // // Note that if the line containing the insertion point begins with // whitespace, the same whitespace will be added to every line of the // inserted text. This is useful for languages like Python, where // indentation matters. In these languages, the insertion point comment // should be indented the same amount as any inserted code will need to be // in order to work correctly in that context. // // The code generator that generates the initial file and the one which // inserts into it must both run as part of a single invocation of protoc. // Code generators are executed in the order in which they appear on the // command line. // // If |insertion_point| is present, |name| must also be present. InsertionPoint *string `protobuf:"bytes,2,opt,name=insertion_point,json=insertionPoint" json:"insertion_point,omitempty"` // The file contents. Content *string `protobuf:"bytes,15,opt,name=content" json:"content,omitempty"` XXX_unrecognized []byte `json:"-"` } func (m *CodeGeneratorResponse_File) Reset() { *m = CodeGeneratorResponse_File{} } func (m *CodeGeneratorResponse_File) String() string { return proto.CompactTextString(m) } func (*CodeGeneratorResponse_File) ProtoMessage() {} func (*CodeGeneratorResponse_File) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1, 0} } func (m *CodeGeneratorResponse_File) GetName() string { if m != nil && m.Name != nil { return *m.Name } return "" } func (m *CodeGeneratorResponse_File) GetInsertionPoint() string { if m != nil && m.InsertionPoint != nil { return *m.InsertionPoint } return "" } func (m *CodeGeneratorResponse_File) GetContent() string { if m != nil && m.Content != nil { return *m.Content } return "" } func init() { proto.RegisterType((*CodeGeneratorRequest)(nil), "google.protobuf.compiler.CodeGeneratorRequest") proto.RegisterType((*CodeGeneratorResponse)(nil), "google.protobuf.compiler.CodeGeneratorResponse") proto.RegisterType((*CodeGeneratorResponse_File)(nil), "google.protobuf.compiler.CodeGeneratorResponse.File") } var fileDescriptor0 = []byte{ // 311 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x74, 0x91, 0xd1, 0x4a, 0xfb, 0x30, 0x14, 0xc6, 0xe9, 0xff, 0x3f, 0x91, 0x1d, 0x65, 0x93, 0x30, 0xa1, 0x8c, 0x5d, 0x94, 0xa1, 0xb8, 0xab, 0x14, 0x44, 0xf0, 0x7e, 0x13, 0xf5, 0xb2, 0x14, 0xaf, 0x04, 0x29, 0xb5, 0x3b, 0x2b, 0x81, 0x2e, 0x27, 0xa6, 0xe9, 0x13, 0xf9, 0x4e, 0x3e, 0x8f, 0x49, 0xda, 0x4e, 0x29, 0xee, 0xaa, 0x3d, 0xdf, 0xf9, 0xe5, 0x3b, 0x5f, 0x72, 0xe0, 0xba, 0x24, 0x2a, 0x2b, 0x8c, 0x95, 0x26, 0x43, 0xef, 0xcd, 0x2e, 0x2e, 0x68, 0xaf, 0x44, 0x85, 0x3a, 0x56, 0x55, 0x53, 0x0a, 0xc9, 0x7d, 0x83, 0x85, 0x2d, 0xc6, 0x7b, 0x8c, 0xf7, 0xd8, 0x3c, 0x1a, 0x1a, 0x6c, 0xb1, 0x2e, 0xb4, 0x50, 0x86, 0x74, 0x4b, 0x2f, 0x3f, 0x03, 0x98, 0x6d, 0x68, 0x8b, 0x4f, 0x28, 0x51, 0xe7, 0x56, 0x4f, 0xf1, 0xa3, 0xc1, 0xda, 0xb0, 0x15, 0x5c, 0xec, 0xac, 0x47, 0x66, 0x28, 0x2b, 0xdb, 0x1e, 0x86, 0x41, 0xf4, 0x7f, 0x35, 0x4e, 0x27, 0x4e, 0x7f, 0xa1, 0xee, 0x04, 0xb2, 0x05, 0x8c, 0x55, 0xae, 0xf3, 0x3d, 0x1a, 0xd4, 0xe1, 0xbf, 0x28, 0xb0, 0xc8, 0x8f, 0xc0, 0x36, 0x00, 0x7e, 0x52, 0xe6, 0x4e, 0x85, 0x53, 0xeb, 0x70, 0x76, 0x7b, 0xc5, 0x87, 0x89, 0x1f, 0x6d, 0xf3, 0xe1, 0x90, 0x2d, 0x71, 0xb2, 0x35, 0x71, 0x1f, 0xd7, 0x59, 0x7e, 0x05, 0x70, 0x39, 0x48, 0x59, 0x2b, 0x92, 0x35, 0xb2, 0x19, 0x9c, 0xa0, 0xd6, 0xa4, 0x6d, 0x36, 0x37, 0xb8, 0x2d, 0xd8, 0x33, 0x8c, 0x7e, 0x8d, 0xbb, 0xe3, 0xc7, 0x1e, 0x88, 0xff, 0x69, 0xea, 0xd3, 0xa4, 0xde, 0x61, 0xfe, 0x06, 0x23, 0x57, 0x31, 0x06, 0x23, 0x69, 0x6f, 0xd4, 0x8d, 0xf1, 0xff, 0xec, 0x06, 0xa6, 0xc2, 0xe2, 0xda, 0x08, 0x92, 0x99, 0x22, 0x21, 0x4d, 0x77, 0xfd, 0xc9, 0x41, 0x4e, 0x9c, 0xca, 0x42, 0x38, 0x2d, 0x48, 0x1a, 0xb4, 0xc0, 0xd4, 0x03, 0x7d, 0xb9, 0xbe, 0x87, 0x85, 0xcd, 0x72, 0x34, 0xdf, 0xfa, 0x3c, 0xf1, 0x8b, 0xf6, 0x0f, 0x52, 0xbf, 0x8e, 0xdb, 0xb5, 0x67, 0x25, 0x7d, 0x07, 0x00, 0x00, 0xff, 0xff, 0x83, 0x7b, 0x5c, 0x7c, 0x1b, 0x02, 0x00, 0x00, } lxd-2.0.0/dist/src/github.com/golang/protobuf/protoc-gen-go/plugin/Makefile0000644061062106075000000000434412702772352031240 0ustar00stgraberdomain admins00000000000000# Go support for Protocol Buffers - Google's data interchange format # # Copyright 2010 The Go Authors. All rights reserved. # https://github.com/golang/protobuf # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # Not stored here, but plugin.proto is in https://github.com/google/protobuf/ # at src/google/protobuf/compiler/plugin.proto # Also we need to fix an import. regenerate: echo WARNING! THIS RULE IS PROBABLY NOT RIGHT FOR YOUR INSTALLATION protoc --go_out=Mgoogle/protobuf/descriptor.proto=github.com/golang/protobuf/protoc-gen-go/descriptor:. \ -I$(HOME)/src/protobuf/src $(HOME)/src/protobuf/src/google/protobuf/compiler/plugin.proto && \ mv google/protobuf/compiler/plugin.pb.go $(GOPATH)/src/github.com/golang/protobuf/protoc-gen-go/plugin restore: cp plugin.pb.golden plugin.pb.go preserve: cp plugin.pb.go plugin.pb.golden lxd-2.0.0/dist/src/github.com/golang/protobuf/protoc-gen-go/plugin/plugin.pb.golden0000644061062106075000000000571312702772352032671 0ustar00stgraberdomain admins00000000000000// Code generated by protoc-gen-go. // source: google/protobuf/compiler/plugin.proto // DO NOT EDIT! package google_protobuf_compiler import proto "github.com/golang/protobuf/proto" import "math" import google_protobuf "github.com/golang/protobuf/protoc-gen-go/descriptor" // Reference proto and math imports to suppress error if they are not otherwise used. var _ = proto.GetString var _ = math.Inf type CodeGeneratorRequest struct { FileToGenerate []string `protobuf:"bytes,1,rep,name=file_to_generate" json:"file_to_generate,omitempty"` Parameter *string `protobuf:"bytes,2,opt,name=parameter" json:"parameter,omitempty"` ProtoFile []*google_protobuf.FileDescriptorProto `protobuf:"bytes,15,rep,name=proto_file" json:"proto_file,omitempty"` XXX_unrecognized []byte `json:"-"` } func (this *CodeGeneratorRequest) Reset() { *this = CodeGeneratorRequest{} } func (this *CodeGeneratorRequest) String() string { return proto.CompactTextString(this) } func (*CodeGeneratorRequest) ProtoMessage() {} func (this *CodeGeneratorRequest) GetParameter() string { if this != nil && this.Parameter != nil { return *this.Parameter } return "" } type CodeGeneratorResponse struct { Error *string `protobuf:"bytes,1,opt,name=error" json:"error,omitempty"` File []*CodeGeneratorResponse_File `protobuf:"bytes,15,rep,name=file" json:"file,omitempty"` XXX_unrecognized []byte `json:"-"` } func (this *CodeGeneratorResponse) Reset() { *this = CodeGeneratorResponse{} } func (this *CodeGeneratorResponse) String() string { return proto.CompactTextString(this) } func (*CodeGeneratorResponse) ProtoMessage() {} func (this *CodeGeneratorResponse) GetError() string { if this != nil && this.Error != nil { return *this.Error } return "" } type CodeGeneratorResponse_File struct { Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` InsertionPoint *string `protobuf:"bytes,2,opt,name=insertion_point" json:"insertion_point,omitempty"` Content *string `protobuf:"bytes,15,opt,name=content" json:"content,omitempty"` XXX_unrecognized []byte `json:"-"` } func (this *CodeGeneratorResponse_File) Reset() { *this = CodeGeneratorResponse_File{} } func (this *CodeGeneratorResponse_File) String() string { return proto.CompactTextString(this) } func (*CodeGeneratorResponse_File) ProtoMessage() {} func (this *CodeGeneratorResponse_File) GetName() string { if this != nil && this.Name != nil { return *this.Name } return "" } func (this *CodeGeneratorResponse_File) GetInsertionPoint() string { if this != nil && this.InsertionPoint != nil { return *this.InsertionPoint } return "" } func (this *CodeGeneratorResponse_File) GetContent() string { if this != nil && this.Content != nil { return *this.Content } return "" } func init() { } lxd-2.0.0/dist/src/github.com/golang/protobuf/protoc-gen-go/link_grpc.go0000644061062106075000000000331412702772352030575 0ustar00stgraberdomain admins00000000000000// Go support for Protocol Buffers - Google's data interchange format // // Copyright 2015 The Go Authors. All rights reserved. // https://github.com/golang/protobuf // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package main import _ "github.com/golang/protobuf/protoc-gen-go/grpc" lxd-2.0.0/dist/src/github.com/golang/protobuf/protoc-gen-go/grpc/0000755061062106075000000000000012702772352027230 5ustar00stgraberdomain admins00000000000000lxd-2.0.0/dist/src/github.com/golang/protobuf/protoc-gen-go/grpc/grpc.go0000644061062106075000000003525212702772352030521 0ustar00stgraberdomain admins00000000000000// Go support for Protocol Buffers - Google's data interchange format // // Copyright 2015 The Go Authors. All rights reserved. // https://github.com/golang/protobuf // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Package grpc outputs gRPC service descriptions in Go code. // It runs as a plugin for the Go protocol buffer compiler plugin. // It is linked in to protoc-gen-go. package grpc import ( "fmt" "path" "strconv" "strings" pb "github.com/golang/protobuf/protoc-gen-go/descriptor" "github.com/golang/protobuf/protoc-gen-go/generator" ) // generatedCodeVersion indicates a version of the generated code. // It is incremented whenever an incompatibility between the generated code and // the grpc package is introduced; the generated code references // a constant, grpc.SupportPackageIsVersionN (where N is generatedCodeVersion). const generatedCodeVersion = 1 // Paths for packages used by code generated in this file, // relative to the import_prefix of the generator.Generator. const ( contextPkgPath = "golang.org/x/net/context" grpcPkgPath = "google.golang.org/grpc" ) func init() { generator.RegisterPlugin(new(grpc)) } // grpc is an implementation of the Go protocol buffer compiler's // plugin architecture. It generates bindings for gRPC support. type grpc struct { gen *generator.Generator } // Name returns the name of this plugin, "grpc". func (g *grpc) Name() string { return "grpc" } // The names for packages imported in the generated code. // They may vary from the final path component of the import path // if the name is used by other packages. var ( contextPkg string grpcPkg string ) // Init initializes the plugin. func (g *grpc) Init(gen *generator.Generator) { g.gen = gen contextPkg = generator.RegisterUniquePackageName("context", nil) grpcPkg = generator.RegisterUniquePackageName("grpc", nil) } // Given a type name defined in a .proto, return its object. // Also record that we're using it, to guarantee the associated import. func (g *grpc) objectNamed(name string) generator.Object { g.gen.RecordTypeUse(name) return g.gen.ObjectNamed(name) } // Given a type name defined in a .proto, return its name as we will print it. func (g *grpc) typeName(str string) string { return g.gen.TypeName(g.objectNamed(str)) } // P forwards to g.gen.P. func (g *grpc) P(args ...interface{}) { g.gen.P(args...) } // Generate generates code for the services in the given file. func (g *grpc) Generate(file *generator.FileDescriptor) { if len(file.FileDescriptorProto.Service) == 0 { return } g.P("// Reference imports to suppress errors if they are not otherwise used.") g.P("var _ ", contextPkg, ".Context") g.P("var _ ", grpcPkg, ".ClientConn") g.P() // Assert version compatibility. g.P("// This is a compile-time assertion to ensure that this generated file") g.P("// is compatible with the grpc package it is being compiled against.") g.P("const _ = ", grpcPkg, ".SupportPackageIsVersion", generatedCodeVersion) g.P() for i, service := range file.FileDescriptorProto.Service { g.generateService(file, service, i) } } // GenerateImports generates the import declaration for this file. func (g *grpc) GenerateImports(file *generator.FileDescriptor) { if len(file.FileDescriptorProto.Service) == 0 { return } g.P("import (") g.P(contextPkg, " ", strconv.Quote(path.Join(g.gen.ImportPrefix, contextPkgPath))) g.P(grpcPkg, " ", strconv.Quote(path.Join(g.gen.ImportPrefix, grpcPkgPath))) g.P(")") g.P() } // reservedClientName records whether a client name is reserved on the client side. var reservedClientName = map[string]bool{ // TODO: do we need any in gRPC? } func unexport(s string) string { return strings.ToLower(s[:1]) + s[1:] } // generateService generates all the code for the named service. func (g *grpc) generateService(file *generator.FileDescriptor, service *pb.ServiceDescriptorProto, index int) { path := fmt.Sprintf("6,%d", index) // 6 means service. origServName := service.GetName() fullServName := origServName if pkg := file.GetPackage(); pkg != "" { fullServName = pkg + "." + fullServName } servName := generator.CamelCase(origServName) g.P() g.P("// Client API for ", servName, " service") g.P() // Client interface. g.P("type ", servName, "Client interface {") for i, method := range service.Method { g.gen.PrintComments(fmt.Sprintf("%s,2,%d", path, i)) // 2 means method in a service. g.P(g.generateClientSignature(servName, method)) } g.P("}") g.P() // Client structure. g.P("type ", unexport(servName), "Client struct {") g.P("cc *", grpcPkg, ".ClientConn") g.P("}") g.P() // NewClient factory. g.P("func New", servName, "Client (cc *", grpcPkg, ".ClientConn) ", servName, "Client {") g.P("return &", unexport(servName), "Client{cc}") g.P("}") g.P() var methodIndex, streamIndex int serviceDescVar := "_" + servName + "_serviceDesc" // Client method implementations. for _, method := range service.Method { var descExpr string if !method.GetServerStreaming() && !method.GetClientStreaming() { // Unary RPC method descExpr = fmt.Sprintf("&%s.Methods[%d]", serviceDescVar, methodIndex) methodIndex++ } else { // Streaming RPC method descExpr = fmt.Sprintf("&%s.Streams[%d]", serviceDescVar, streamIndex) streamIndex++ } g.generateClientMethod(servName, fullServName, serviceDescVar, method, descExpr) } g.P("// Server API for ", servName, " service") g.P() // Server interface. serverType := servName + "Server" g.P("type ", serverType, " interface {") for i, method := range service.Method { g.gen.PrintComments(fmt.Sprintf("%s,2,%d", path, i)) // 2 means method in a service. g.P(g.generateServerSignature(servName, method)) } g.P("}") g.P() // Server registration. g.P("func Register", servName, "Server(s *", grpcPkg, ".Server, srv ", serverType, ") {") g.P("s.RegisterService(&", serviceDescVar, `, srv)`) g.P("}") g.P() // Server handler implementations. var handlerNames []string for _, method := range service.Method { hname := g.generateServerMethod(servName, method) handlerNames = append(handlerNames, hname) } // Service descriptor. g.P("var ", serviceDescVar, " = ", grpcPkg, ".ServiceDesc {") g.P("ServiceName: ", strconv.Quote(fullServName), ",") g.P("HandlerType: (*", serverType, ")(nil),") g.P("Methods: []", grpcPkg, ".MethodDesc{") for i, method := range service.Method { if method.GetServerStreaming() || method.GetClientStreaming() { continue } g.P("{") g.P("MethodName: ", strconv.Quote(method.GetName()), ",") g.P("Handler: ", handlerNames[i], ",") g.P("},") } g.P("},") g.P("Streams: []", grpcPkg, ".StreamDesc{") for i, method := range service.Method { if !method.GetServerStreaming() && !method.GetClientStreaming() { continue } g.P("{") g.P("StreamName: ", strconv.Quote(method.GetName()), ",") g.P("Handler: ", handlerNames[i], ",") if method.GetServerStreaming() { g.P("ServerStreams: true,") } if method.GetClientStreaming() { g.P("ClientStreams: true,") } g.P("},") } g.P("},") g.P("}") g.P() } // generateClientSignature returns the client-side signature for a method. func (g *grpc) generateClientSignature(servName string, method *pb.MethodDescriptorProto) string { origMethName := method.GetName() methName := generator.CamelCase(origMethName) if reservedClientName[methName] { methName += "_" } reqArg := ", in *" + g.typeName(method.GetInputType()) if method.GetClientStreaming() { reqArg = "" } respName := "*" + g.typeName(method.GetOutputType()) if method.GetServerStreaming() || method.GetClientStreaming() { respName = servName + "_" + generator.CamelCase(origMethName) + "Client" } return fmt.Sprintf("%s(ctx %s.Context%s, opts ...%s.CallOption) (%s, error)", methName, contextPkg, reqArg, grpcPkg, respName) } func (g *grpc) generateClientMethod(servName, fullServName, serviceDescVar string, method *pb.MethodDescriptorProto, descExpr string) { sname := fmt.Sprintf("/%s/%s", fullServName, method.GetName()) methName := generator.CamelCase(method.GetName()) inType := g.typeName(method.GetInputType()) outType := g.typeName(method.GetOutputType()) g.P("func (c *", unexport(servName), "Client) ", g.generateClientSignature(servName, method), "{") if !method.GetServerStreaming() && !method.GetClientStreaming() { g.P("out := new(", outType, ")") // TODO: Pass descExpr to Invoke. g.P("err := ", grpcPkg, `.Invoke(ctx, "`, sname, `", in, out, c.cc, opts...)`) g.P("if err != nil { return nil, err }") g.P("return out, nil") g.P("}") g.P() return } streamType := unexport(servName) + methName + "Client" g.P("stream, err := ", grpcPkg, ".NewClientStream(ctx, ", descExpr, `, c.cc, "`, sname, `", opts...)`) g.P("if err != nil { return nil, err }") g.P("x := &", streamType, "{stream}") if !method.GetClientStreaming() { g.P("if err := x.ClientStream.SendMsg(in); err != nil { return nil, err }") g.P("if err := x.ClientStream.CloseSend(); err != nil { return nil, err }") } g.P("return x, nil") g.P("}") g.P() genSend := method.GetClientStreaming() genRecv := method.GetServerStreaming() genCloseAndRecv := !method.GetServerStreaming() // Stream auxiliary types and methods. g.P("type ", servName, "_", methName, "Client interface {") if genSend { g.P("Send(*", inType, ") error") } if genRecv { g.P("Recv() (*", outType, ", error)") } if genCloseAndRecv { g.P("CloseAndRecv() (*", outType, ", error)") } g.P(grpcPkg, ".ClientStream") g.P("}") g.P() g.P("type ", streamType, " struct {") g.P(grpcPkg, ".ClientStream") g.P("}") g.P() if genSend { g.P("func (x *", streamType, ") Send(m *", inType, ") error {") g.P("return x.ClientStream.SendMsg(m)") g.P("}") g.P() } if genRecv { g.P("func (x *", streamType, ") Recv() (*", outType, ", error) {") g.P("m := new(", outType, ")") g.P("if err := x.ClientStream.RecvMsg(m); err != nil { return nil, err }") g.P("return m, nil") g.P("}") g.P() } if genCloseAndRecv { g.P("func (x *", streamType, ") CloseAndRecv() (*", outType, ", error) {") g.P("if err := x.ClientStream.CloseSend(); err != nil { return nil, err }") g.P("m := new(", outType, ")") g.P("if err := x.ClientStream.RecvMsg(m); err != nil { return nil, err }") g.P("return m, nil") g.P("}") g.P() } } // generateServerSignature returns the server-side signature for a method. func (g *grpc) generateServerSignature(servName string, method *pb.MethodDescriptorProto) string { origMethName := method.GetName() methName := generator.CamelCase(origMethName) if reservedClientName[methName] { methName += "_" } var reqArgs []string ret := "error" if !method.GetServerStreaming() && !method.GetClientStreaming() { reqArgs = append(reqArgs, contextPkg+".Context") ret = "(*" + g.typeName(method.GetOutputType()) + ", error)" } if !method.GetClientStreaming() { reqArgs = append(reqArgs, "*"+g.typeName(method.GetInputType())) } if method.GetServerStreaming() || method.GetClientStreaming() { reqArgs = append(reqArgs, servName+"_"+generator.CamelCase(origMethName)+"Server") } return methName + "(" + strings.Join(reqArgs, ", ") + ") " + ret } func (g *grpc) generateServerMethod(servName string, method *pb.MethodDescriptorProto) string { methName := generator.CamelCase(method.GetName()) hname := fmt.Sprintf("_%s_%s_Handler", servName, methName) inType := g.typeName(method.GetInputType()) outType := g.typeName(method.GetOutputType()) if !method.GetServerStreaming() && !method.GetClientStreaming() { g.P("func ", hname, "(srv interface{}, ctx ", contextPkg, ".Context, dec func(interface{}) error) (interface{}, error) {") g.P("in := new(", inType, ")") g.P("if err := dec(in); err != nil { return nil, err }") g.P("out, err := srv.(", servName, "Server).", methName, "(ctx, in)") g.P("if err != nil { return nil, err }") g.P("return out, nil") g.P("}") g.P() return hname } streamType := unexport(servName) + methName + "Server" g.P("func ", hname, "(srv interface{}, stream ", grpcPkg, ".ServerStream) error {") if !method.GetClientStreaming() { g.P("m := new(", inType, ")") g.P("if err := stream.RecvMsg(m); err != nil { return err }") g.P("return srv.(", servName, "Server).", methName, "(m, &", streamType, "{stream})") } else { g.P("return srv.(", servName, "Server).", methName, "(&", streamType, "{stream})") } g.P("}") g.P() genSend := method.GetServerStreaming() genSendAndClose := !method.GetServerStreaming() genRecv := method.GetClientStreaming() // Stream auxiliary types and methods. g.P("type ", servName, "_", methName, "Server interface {") if genSend { g.P("Send(*", outType, ") error") } if genSendAndClose { g.P("SendAndClose(*", outType, ") error") } if genRecv { g.P("Recv() (*", inType, ", error)") } g.P(grpcPkg, ".ServerStream") g.P("}") g.P() g.P("type ", streamType, " struct {") g.P(grpcPkg, ".ServerStream") g.P("}") g.P() if genSend { g.P("func (x *", streamType, ") Send(m *", outType, ") error {") g.P("return x.ServerStream.SendMsg(m)") g.P("}") g.P() } if genSendAndClose { g.P("func (x *", streamType, ") SendAndClose(m *", outType, ") error {") g.P("return x.ServerStream.SendMsg(m)") g.P("}") g.P() } if genRecv { g.P("func (x *", streamType, ") Recv() (*", inType, ", error) {") g.P("m := new(", inType, ")") g.P("if err := x.ServerStream.RecvMsg(m); err != nil { return nil, err }") g.P("return m, nil") g.P("}") g.P() } return hname } lxd-2.0.0/dist/src/github.com/golang/protobuf/protoc-gen-go/Makefile0000644061062106075000000000320712702772352027737 0ustar00stgraberdomain admins00000000000000# Go support for Protocol Buffers - Google's data interchange format # # Copyright 2010 The Go Authors. All rights reserved. # https://github.com/golang/protobuf # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. test: cd testdata && make test lxd-2.0.0/dist/src/github.com/golang/protobuf/protoc-gen-go/testdata/0000755061062106075000000000000012702772352030106 5ustar00stgraberdomain admins00000000000000lxd-2.0.0/dist/src/github.com/golang/protobuf/protoc-gen-go/testdata/imp3.proto0000644061062106075000000000334712702772352032052 0ustar00stgraberdomain admins00000000000000// Go support for Protocol Buffers - Google's data interchange format // // Copyright 2012 The Go Authors. All rights reserved. // https://github.com/golang/protobuf // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. syntax = "proto2"; package imp; message ForeignImportedMessage { optional string tuber = 1; } lxd-2.0.0/dist/src/github.com/golang/protobuf/protoc-gen-go/testdata/extension_extra.proto0000644061062106075000000000335012702772352034413 0ustar00stgraberdomain admins00000000000000// Go support for Protocol Buffers - Google's data interchange format // // Copyright 2011 The Go Authors. All rights reserved. // https://github.com/golang/protobuf // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. syntax = "proto2"; package extension_extra; message ExtraMessage { optional int32 width = 1; } lxd-2.0.0/dist/src/github.com/golang/protobuf/protoc-gen-go/testdata/extension_test.go0000644061062106075000000001510012702772352033505 0ustar00stgraberdomain admins00000000000000// Go support for Protocol Buffers - Google's data interchange format // // Copyright 2010 The Go Authors. All rights reserved. // https://github.com/golang/protobuf // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Test that we can use protocol buffers that use extensions. package testdata /* import ( "bytes" "regexp" "testing" "github.com/golang/protobuf/proto" base "extension_base.pb" user "extension_user.pb" ) func TestSingleFieldExtension(t *testing.T) { bm := &base.BaseMessage{ Height: proto.Int32(178), } // Use extension within scope of another type. vol := proto.Uint32(11) err := proto.SetExtension(bm, user.E_LoudMessage_Volume, vol) if err != nil { t.Fatal("Failed setting extension:", err) } buf, err := proto.Marshal(bm) if err != nil { t.Fatal("Failed encoding message with extension:", err) } bm_new := new(base.BaseMessage) if err := proto.Unmarshal(buf, bm_new); err != nil { t.Fatal("Failed decoding message with extension:", err) } if !proto.HasExtension(bm_new, user.E_LoudMessage_Volume) { t.Fatal("Decoded message didn't contain extension.") } vol_out, err := proto.GetExtension(bm_new, user.E_LoudMessage_Volume) if err != nil { t.Fatal("Failed getting extension:", err) } if v := vol_out.(*uint32); *v != *vol { t.Errorf("vol_out = %v, expected %v", *v, *vol) } proto.ClearExtension(bm_new, user.E_LoudMessage_Volume) if proto.HasExtension(bm_new, user.E_LoudMessage_Volume) { t.Fatal("Failed clearing extension.") } } func TestMessageExtension(t *testing.T) { bm := &base.BaseMessage{ Height: proto.Int32(179), } // Use extension that is itself a message. um := &user.UserMessage{ Name: proto.String("Dave"), Rank: proto.String("Major"), } err := proto.SetExtension(bm, user.E_LoginMessage_UserMessage, um) if err != nil { t.Fatal("Failed setting extension:", err) } buf, err := proto.Marshal(bm) if err != nil { t.Fatal("Failed encoding message with extension:", err) } bm_new := new(base.BaseMessage) if err := proto.Unmarshal(buf, bm_new); err != nil { t.Fatal("Failed decoding message with extension:", err) } if !proto.HasExtension(bm_new, user.E_LoginMessage_UserMessage) { t.Fatal("Decoded message didn't contain extension.") } um_out, err := proto.GetExtension(bm_new, user.E_LoginMessage_UserMessage) if err != nil { t.Fatal("Failed getting extension:", err) } if n := um_out.(*user.UserMessage).Name; *n != *um.Name { t.Errorf("um_out.Name = %q, expected %q", *n, *um.Name) } if r := um_out.(*user.UserMessage).Rank; *r != *um.Rank { t.Errorf("um_out.Rank = %q, expected %q", *r, *um.Rank) } proto.ClearExtension(bm_new, user.E_LoginMessage_UserMessage) if proto.HasExtension(bm_new, user.E_LoginMessage_UserMessage) { t.Fatal("Failed clearing extension.") } } func TestTopLevelExtension(t *testing.T) { bm := &base.BaseMessage{ Height: proto.Int32(179), } width := proto.Int32(17) err := proto.SetExtension(bm, user.E_Width, width) if err != nil { t.Fatal("Failed setting extension:", err) } buf, err := proto.Marshal(bm) if err != nil { t.Fatal("Failed encoding message with extension:", err) } bm_new := new(base.BaseMessage) if err := proto.Unmarshal(buf, bm_new); err != nil { t.Fatal("Failed decoding message with extension:", err) } if !proto.HasExtension(bm_new, user.E_Width) { t.Fatal("Decoded message didn't contain extension.") } width_out, err := proto.GetExtension(bm_new, user.E_Width) if err != nil { t.Fatal("Failed getting extension:", err) } if w := width_out.(*int32); *w != *width { t.Errorf("width_out = %v, expected %v", *w, *width) } proto.ClearExtension(bm_new, user.E_Width) if proto.HasExtension(bm_new, user.E_Width) { t.Fatal("Failed clearing extension.") } } func TestMessageSetWireFormat(t *testing.T) { osm := new(base.OldStyleMessage) osp := &user.OldStyleParcel{ Name: proto.String("Dave"), Height: proto.Int32(178), } err := proto.SetExtension(osm, user.E_OldStyleParcel_MessageSetExtension, osp) if err != nil { t.Fatal("Failed setting extension:", err) } buf, err := proto.Marshal(osm) if err != nil { t.Fatal("Failed encoding message:", err) } // Data generated from Python implementation. expected := []byte{ 11, 16, 209, 15, 26, 9, 10, 4, 68, 97, 118, 101, 16, 178, 1, 12, } if !bytes.Equal(expected, buf) { t.Errorf("Encoding mismatch.\nwant %+v\n got %+v", expected, buf) } // Check that it is restored correctly. osm = new(base.OldStyleMessage) if err := proto.Unmarshal(buf, osm); err != nil { t.Fatal("Failed decoding message:", err) } osp_out, err := proto.GetExtension(osm, user.E_OldStyleParcel_MessageSetExtension) if err != nil { t.Fatal("Failed getting extension:", err) } osp = osp_out.(*user.OldStyleParcel) if *osp.Name != "Dave" || *osp.Height != 178 { t.Errorf("Retrieved extension from decoded message is not correct: %+v", osp) } } func main() { // simpler than rigging up gotest testing.Main(regexp.MatchString, []testing.InternalTest{ {"TestSingleFieldExtension", TestSingleFieldExtension}, {"TestMessageExtension", TestMessageExtension}, {"TestTopLevelExtension", TestTopLevelExtension}, }, []testing.InternalBenchmark{}, []testing.InternalExample{}) } */ lxd-2.0.0/dist/src/github.com/golang/protobuf/protoc-gen-go/testdata/multi/0000755061062106075000000000000012702772352031240 5ustar00stgraberdomain admins00000000000000lxd-2.0.0/dist/src/github.com/golang/protobuf/protoc-gen-go/testdata/multi/multi3.proto0000644061062106075000000000342512702772352033546 0ustar00stgraberdomain admins00000000000000// Go support for Protocol Buffers - Google's data interchange format // // Copyright 2010 The Go Authors. All rights reserved. // https://github.com/golang/protobuf // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. syntax = "proto2"; package multitest; message Multi3 { enum HatType { FEDORA = 1; FEZ = 2; }; optional HatType hat_type = 1; } lxd-2.0.0/dist/src/github.com/golang/protobuf/protoc-gen-go/testdata/multi/multi2.proto0000644061062106075000000000350112702772352033540 0ustar00stgraberdomain admins00000000000000// Go support for Protocol Buffers - Google's data interchange format // // Copyright 2010 The Go Authors. All rights reserved. // https://github.com/golang/protobuf // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. syntax = "proto2"; package multitest; message Multi2 { required int32 required_value = 1; enum Color { BLUE = 1; GREEN = 2; RED = 3; }; optional Color color = 2; } lxd-2.0.0/dist/src/github.com/golang/protobuf/protoc-gen-go/testdata/multi/multi1.proto0000644061062106075000000000354512702772352033547 0ustar00stgraberdomain admins00000000000000// Go support for Protocol Buffers - Google's data interchange format // // Copyright 2010 The Go Authors. All rights reserved. // https://github.com/golang/protobuf // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. syntax = "proto2"; import "multi/multi2.proto"; import "multi/multi3.proto"; package multitest; message Multi1 { required Multi2 multi2 = 1; optional Multi2.Color color = 2; optional Multi3.HatType hat_type = 3; } lxd-2.0.0/dist/src/github.com/golang/protobuf/protoc-gen-go/testdata/imp2.proto0000644061062106075000000000344112702772352032044 0ustar00stgraberdomain admins00000000000000// Go support for Protocol Buffers - Google's data interchange format // // Copyright 2011 The Go Authors. All rights reserved. // https://github.com/golang/protobuf // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. syntax = "proto2"; package imp; message PubliclyImportedMessage { optional int64 field = 1; } enum PubliclyImportedEnum { GLASSES = 1; HAIR = 2; } lxd-2.0.0/dist/src/github.com/golang/protobuf/protoc-gen-go/testdata/my_test/0000755061062106075000000000000012702772352031572 5ustar00stgraberdomain admins00000000000000lxd-2.0.0/dist/src/github.com/golang/protobuf/protoc-gen-go/testdata/my_test/test.pb.go.golden0000644061062106075000000005775512702772352034772 0ustar00stgraberdomain admins00000000000000// Code generated by protoc-gen-go. // source: my_test/test.proto // DO NOT EDIT! /* Package my_test is a generated protocol buffer package. This package holds interesting messages. It is generated from these files: my_test/test.proto It has these top-level messages: Request Reply OtherBase ReplyExtensions OtherReplyExtensions OldReply Communique */ package my_test import proto "github.com/golang/protobuf/proto" import fmt "fmt" import math "math" import _ "github.com/golang/protobuf/protoc-gen-go/testdata/multi" // Reference imports to suppress errors if they are not otherwise used. var _ = proto.Marshal var _ = fmt.Errorf var _ = math.Inf // This is a compile-time assertion to ensure that this generated file // is compatible with the proto package it is being compiled against. const _ = proto.ProtoPackageIsVersion1 type HatType int32 const ( // deliberately skipping 0 HatType_FEDORA HatType = 1 HatType_FEZ HatType = 2 ) var HatType_name = map[int32]string{ 1: "FEDORA", 2: "FEZ", } var HatType_value = map[string]int32{ "FEDORA": 1, "FEZ": 2, } func (x HatType) Enum() *HatType { p := new(HatType) *p = x return p } func (x HatType) String() string { return proto.EnumName(HatType_name, int32(x)) } func (x *HatType) UnmarshalJSON(data []byte) error { value, err := proto.UnmarshalJSONEnum(HatType_value, data, "HatType") if err != nil { return err } *x = HatType(value) return nil } // This enum represents days of the week. type Days int32 const ( Days_MONDAY Days = 1 Days_TUESDAY Days = 2 Days_LUNDI Days = 1 ) var Days_name = map[int32]string{ 1: "MONDAY", 2: "TUESDAY", // Duplicate value: 1: "LUNDI", } var Days_value = map[string]int32{ "MONDAY": 1, "TUESDAY": 2, "LUNDI": 1, } func (x Days) Enum() *Days { p := new(Days) *p = x return p } func (x Days) String() string { return proto.EnumName(Days_name, int32(x)) } func (x *Days) UnmarshalJSON(data []byte) error { value, err := proto.UnmarshalJSONEnum(Days_value, data, "Days") if err != nil { return err } *x = Days(value) return nil } type Request_Color int32 const ( Request_RED Request_Color = 0 Request_GREEN Request_Color = 1 Request_BLUE Request_Color = 2 ) var Request_Color_name = map[int32]string{ 0: "RED", 1: "GREEN", 2: "BLUE", } var Request_Color_value = map[string]int32{ "RED": 0, "GREEN": 1, "BLUE": 2, } func (x Request_Color) Enum() *Request_Color { p := new(Request_Color) *p = x return p } func (x Request_Color) String() string { return proto.EnumName(Request_Color_name, int32(x)) } func (x *Request_Color) UnmarshalJSON(data []byte) error { value, err := proto.UnmarshalJSONEnum(Request_Color_value, data, "Request_Color") if err != nil { return err } *x = Request_Color(value) return nil } type Reply_Entry_Game int32 const ( Reply_Entry_FOOTBALL Reply_Entry_Game = 1 Reply_Entry_TENNIS Reply_Entry_Game = 2 ) var Reply_Entry_Game_name = map[int32]string{ 1: "FOOTBALL", 2: "TENNIS", } var Reply_Entry_Game_value = map[string]int32{ "FOOTBALL": 1, "TENNIS": 2, } func (x Reply_Entry_Game) Enum() *Reply_Entry_Game { p := new(Reply_Entry_Game) *p = x return p } func (x Reply_Entry_Game) String() string { return proto.EnumName(Reply_Entry_Game_name, int32(x)) } func (x *Reply_Entry_Game) UnmarshalJSON(data []byte) error { value, err := proto.UnmarshalJSONEnum(Reply_Entry_Game_value, data, "Reply_Entry_Game") if err != nil { return err } *x = Reply_Entry_Game(value) return nil } // This is a message that might be sent somewhere. type Request struct { Key []int64 `protobuf:"varint,1,rep,name=key" json:"key,omitempty"` // optional imp.ImportedMessage imported_message = 2; Hue *Request_Color `protobuf:"varint,3,opt,name=hue,enum=my.test.Request_Color" json:"hue,omitempty"` Hat *HatType `protobuf:"varint,4,opt,name=hat,enum=my.test.HatType,def=1" json:"hat,omitempty"` // optional imp.ImportedMessage.Owner owner = 6; Deadline *float32 `protobuf:"fixed32,7,opt,name=deadline,def=inf" json:"deadline,omitempty"` Somegroup *Request_SomeGroup `protobuf:"group,8,opt,name=SomeGroup,json=somegroup" json:"somegroup,omitempty"` // This is a map field. It will generate map[int32]string. NameMapping map[int32]string `protobuf:"bytes,14,rep,name=name_mapping,json=nameMapping" json:"name_mapping,omitempty" protobuf_key:"varint,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` // This is a map field whose value type is a message. MsgMapping map[int64]*Reply `protobuf:"bytes,15,rep,name=msg_mapping,json=msgMapping" json:"msg_mapping,omitempty" protobuf_key:"zigzag64,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` Reset_ *int32 `protobuf:"varint,12,opt,name=reset" json:"reset,omitempty"` // This field should not conflict with any getters. GetKey_ *string `protobuf:"bytes,16,opt,name=get_key,json=getKey" json:"get_key,omitempty"` XXX_unrecognized []byte `json:"-"` } func (m *Request) Reset() { *m = Request{} } func (m *Request) String() string { return proto.CompactTextString(m) } func (*Request) ProtoMessage() {} const Default_Request_Hat HatType = HatType_FEDORA var Default_Request_Deadline float32 = float32(math.Inf(1)) func (m *Request) GetKey() []int64 { if m != nil { return m.Key } return nil } func (m *Request) GetHue() Request_Color { if m != nil && m.Hue != nil { return *m.Hue } return Request_RED } func (m *Request) GetHat() HatType { if m != nil && m.Hat != nil { return *m.Hat } return Default_Request_Hat } func (m *Request) GetDeadline() float32 { if m != nil && m.Deadline != nil { return *m.Deadline } return Default_Request_Deadline } func (m *Request) GetSomegroup() *Request_SomeGroup { if m != nil { return m.Somegroup } return nil } func (m *Request) GetNameMapping() map[int32]string { if m != nil { return m.NameMapping } return nil } func (m *Request) GetMsgMapping() map[int64]*Reply { if m != nil { return m.MsgMapping } return nil } func (m *Request) GetReset_() int32 { if m != nil && m.Reset_ != nil { return *m.Reset_ } return 0 } func (m *Request) GetGetKey_() string { if m != nil && m.GetKey_ != nil { return *m.GetKey_ } return "" } type Request_SomeGroup struct { GroupField *int32 `protobuf:"varint,9,opt,name=group_field,json=groupField" json:"group_field,omitempty"` XXX_unrecognized []byte `json:"-"` } func (m *Request_SomeGroup) Reset() { *m = Request_SomeGroup{} } func (m *Request_SomeGroup) String() string { return proto.CompactTextString(m) } func (*Request_SomeGroup) ProtoMessage() {} func (m *Request_SomeGroup) GetGroupField() int32 { if m != nil && m.GroupField != nil { return *m.GroupField } return 0 } type Reply struct { Found []*Reply_Entry `protobuf:"bytes,1,rep,name=found" json:"found,omitempty"` CompactKeys []int32 `protobuf:"varint,2,rep,packed,name=compact_keys,json=compactKeys" json:"compact_keys,omitempty"` XXX_extensions map[int32]proto.Extension `json:"-"` XXX_unrecognized []byte `json:"-"` } func (m *Reply) Reset() { *m = Reply{} } func (m *Reply) String() string { return proto.CompactTextString(m) } func (*Reply) ProtoMessage() {} var extRange_Reply = []proto.ExtensionRange{ {100, 536870911}, } func (*Reply) ExtensionRangeArray() []proto.ExtensionRange { return extRange_Reply } func (m *Reply) ExtensionMap() map[int32]proto.Extension { if m.XXX_extensions == nil { m.XXX_extensions = make(map[int32]proto.Extension) } return m.XXX_extensions } func (m *Reply) GetFound() []*Reply_Entry { if m != nil { return m.Found } return nil } func (m *Reply) GetCompactKeys() []int32 { if m != nil { return m.CompactKeys } return nil } type Reply_Entry struct { KeyThatNeeds_1234Camel_CasIng *int64 `protobuf:"varint,1,req,name=key_that_needs_1234camel_CasIng,json=keyThatNeeds1234camelCasIng" json:"key_that_needs_1234camel_CasIng,omitempty"` Value *int64 `protobuf:"varint,2,opt,name=value,def=7" json:"value,omitempty"` XMyFieldName_2 *int64 `protobuf:"varint,3,opt,name=_my_field_name_2,json=myFieldName2" json:"_my_field_name_2,omitempty"` XXX_unrecognized []byte `json:"-"` } func (m *Reply_Entry) Reset() { *m = Reply_Entry{} } func (m *Reply_Entry) String() string { return proto.CompactTextString(m) } func (*Reply_Entry) ProtoMessage() {} const Default_Reply_Entry_Value int64 = 7 func (m *Reply_Entry) GetKeyThatNeeds_1234Camel_CasIng() int64 { if m != nil && m.KeyThatNeeds_1234Camel_CasIng != nil { return *m.KeyThatNeeds_1234Camel_CasIng } return 0 } func (m *Reply_Entry) GetValue() int64 { if m != nil && m.Value != nil { return *m.Value } return Default_Reply_Entry_Value } func (m *Reply_Entry) GetXMyFieldName_2() int64 { if m != nil && m.XMyFieldName_2 != nil { return *m.XMyFieldName_2 } return 0 } type OtherBase struct { Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` XXX_extensions map[int32]proto.Extension `json:"-"` XXX_unrecognized []byte `json:"-"` } func (m *OtherBase) Reset() { *m = OtherBase{} } func (m *OtherBase) String() string { return proto.CompactTextString(m) } func (*OtherBase) ProtoMessage() {} var extRange_OtherBase = []proto.ExtensionRange{ {100, 536870911}, } func (*OtherBase) ExtensionRangeArray() []proto.ExtensionRange { return extRange_OtherBase } func (m *OtherBase) ExtensionMap() map[int32]proto.Extension { if m.XXX_extensions == nil { m.XXX_extensions = make(map[int32]proto.Extension) } return m.XXX_extensions } func (m *OtherBase) GetName() string { if m != nil && m.Name != nil { return *m.Name } return "" } type ReplyExtensions struct { XXX_unrecognized []byte `json:"-"` } func (m *ReplyExtensions) Reset() { *m = ReplyExtensions{} } func (m *ReplyExtensions) String() string { return proto.CompactTextString(m) } func (*ReplyExtensions) ProtoMessage() {} var E_ReplyExtensions_Time = &proto.ExtensionDesc{ ExtendedType: (*Reply)(nil), ExtensionType: (*float64)(nil), Field: 101, Name: "my.test.ReplyExtensions.time", Tag: "fixed64,101,opt,name=time", } var E_ReplyExtensions_Carrot = &proto.ExtensionDesc{ ExtendedType: (*Reply)(nil), ExtensionType: (*ReplyExtensions)(nil), Field: 105, Name: "my.test.ReplyExtensions.carrot", Tag: "bytes,105,opt,name=carrot", } var E_ReplyExtensions_Donut = &proto.ExtensionDesc{ ExtendedType: (*OtherBase)(nil), ExtensionType: (*ReplyExtensions)(nil), Field: 101, Name: "my.test.ReplyExtensions.donut", Tag: "bytes,101,opt,name=donut", } type OtherReplyExtensions struct { Key *int32 `protobuf:"varint,1,opt,name=key" json:"key,omitempty"` XXX_unrecognized []byte `json:"-"` } func (m *OtherReplyExtensions) Reset() { *m = OtherReplyExtensions{} } func (m *OtherReplyExtensions) String() string { return proto.CompactTextString(m) } func (*OtherReplyExtensions) ProtoMessage() {} func (m *OtherReplyExtensions) GetKey() int32 { if m != nil && m.Key != nil { return *m.Key } return 0 } type OldReply struct { XXX_extensions map[int32]proto.Extension `json:"-"` XXX_unrecognized []byte `json:"-"` } func (m *OldReply) Reset() { *m = OldReply{} } func (m *OldReply) String() string { return proto.CompactTextString(m) } func (*OldReply) ProtoMessage() {} func (m *OldReply) Marshal() ([]byte, error) { return proto.MarshalMessageSet(m.ExtensionMap()) } func (m *OldReply) Unmarshal(buf []byte) error { return proto.UnmarshalMessageSet(buf, m.ExtensionMap()) } func (m *OldReply) MarshalJSON() ([]byte, error) { return proto.MarshalMessageSetJSON(m.XXX_extensions) } func (m *OldReply) UnmarshalJSON(buf []byte) error { return proto.UnmarshalMessageSetJSON(buf, m.XXX_extensions) } // ensure OldReply satisfies proto.Marshaler and proto.Unmarshaler var _ proto.Marshaler = (*OldReply)(nil) var _ proto.Unmarshaler = (*OldReply)(nil) var extRange_OldReply = []proto.ExtensionRange{ {100, 2147483646}, } func (*OldReply) ExtensionRangeArray() []proto.ExtensionRange { return extRange_OldReply } func (m *OldReply) ExtensionMap() map[int32]proto.Extension { if m.XXX_extensions == nil { m.XXX_extensions = make(map[int32]proto.Extension) } return m.XXX_extensions } type Communique struct { MakeMeCry *bool `protobuf:"varint,1,opt,name=make_me_cry,json=makeMeCry" json:"make_me_cry,omitempty"` // This is a oneof, called "union". // // Types that are valid to be assigned to Union: // *Communique_Number // *Communique_Name // *Communique_Data // *Communique_TempC // *Communique_Height // *Communique_Today // *Communique_Maybe // *Communique_Delta_ // *Communique_Msg // *Communique_Somegroup Union isCommunique_Union `protobuf_oneof:"union"` XXX_unrecognized []byte `json:"-"` } func (m *Communique) Reset() { *m = Communique{} } func (m *Communique) String() string { return proto.CompactTextString(m) } func (*Communique) ProtoMessage() {} type isCommunique_Union interface { isCommunique_Union() } type Communique_Number struct { Number int32 `protobuf:"varint,5,opt,name=number,oneof"` } type Communique_Name struct { Name string `protobuf:"bytes,6,opt,name=name,oneof"` } type Communique_Data struct { Data []byte `protobuf:"bytes,7,opt,name=data,oneof"` } type Communique_TempC struct { TempC float64 `protobuf:"fixed64,8,opt,name=temp_c,json=tempC,oneof"` } type Communique_Height struct { Height float32 `protobuf:"fixed32,9,opt,name=height,oneof"` } type Communique_Today struct { Today Days `protobuf:"varint,10,opt,name=today,enum=my.test.Days,oneof"` } type Communique_Maybe struct { Maybe bool `protobuf:"varint,11,opt,name=maybe,oneof"` } type Communique_Delta_ struct { Delta int32 `protobuf:"zigzag32,12,opt,name=delta,oneof"` } type Communique_Msg struct { Msg *Reply `protobuf:"bytes,13,opt,name=msg,oneof"` } type Communique_Somegroup struct { Somegroup *Communique_SomeGroup `protobuf:"group,14,opt,name=SomeGroup,json=somegroup,oneof"` } func (*Communique_Number) isCommunique_Union() {} func (*Communique_Name) isCommunique_Union() {} func (*Communique_Data) isCommunique_Union() {} func (*Communique_TempC) isCommunique_Union() {} func (*Communique_Height) isCommunique_Union() {} func (*Communique_Today) isCommunique_Union() {} func (*Communique_Maybe) isCommunique_Union() {} func (*Communique_Delta_) isCommunique_Union() {} func (*Communique_Msg) isCommunique_Union() {} func (*Communique_Somegroup) isCommunique_Union() {} func (m *Communique) GetUnion() isCommunique_Union { if m != nil { return m.Union } return nil } func (m *Communique) GetMakeMeCry() bool { if m != nil && m.MakeMeCry != nil { return *m.MakeMeCry } return false } func (m *Communique) GetNumber() int32 { if x, ok := m.GetUnion().(*Communique_Number); ok { return x.Number } return 0 } func (m *Communique) GetName() string { if x, ok := m.GetUnion().(*Communique_Name); ok { return x.Name } return "" } func (m *Communique) GetData() []byte { if x, ok := m.GetUnion().(*Communique_Data); ok { return x.Data } return nil } func (m *Communique) GetTempC() float64 { if x, ok := m.GetUnion().(*Communique_TempC); ok { return x.TempC } return 0 } func (m *Communique) GetHeight() float32 { if x, ok := m.GetUnion().(*Communique_Height); ok { return x.Height } return 0 } func (m *Communique) GetToday() Days { if x, ok := m.GetUnion().(*Communique_Today); ok { return x.Today } return Days_MONDAY } func (m *Communique) GetMaybe() bool { if x, ok := m.GetUnion().(*Communique_Maybe); ok { return x.Maybe } return false } func (m *Communique) GetDelta() int32 { if x, ok := m.GetUnion().(*Communique_Delta_); ok { return x.Delta } return 0 } func (m *Communique) GetMsg() *Reply { if x, ok := m.GetUnion().(*Communique_Msg); ok { return x.Msg } return nil } func (m *Communique) GetSomegroup() *Communique_SomeGroup { if x, ok := m.GetUnion().(*Communique_Somegroup); ok { return x.Somegroup } return nil } // XXX_OneofFuncs is for the internal use of the proto package. func (*Communique) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) { return _Communique_OneofMarshaler, _Communique_OneofUnmarshaler, _Communique_OneofSizer, []interface{}{ (*Communique_Number)(nil), (*Communique_Name)(nil), (*Communique_Data)(nil), (*Communique_TempC)(nil), (*Communique_Height)(nil), (*Communique_Today)(nil), (*Communique_Maybe)(nil), (*Communique_Delta_)(nil), (*Communique_Msg)(nil), (*Communique_Somegroup)(nil), } } func _Communique_OneofMarshaler(msg proto.Message, b *proto.Buffer) error { m := msg.(*Communique) // union switch x := m.Union.(type) { case *Communique_Number: b.EncodeVarint(5<<3 | proto.WireVarint) b.EncodeVarint(uint64(x.Number)) case *Communique_Name: b.EncodeVarint(6<<3 | proto.WireBytes) b.EncodeStringBytes(x.Name) case *Communique_Data: b.EncodeVarint(7<<3 | proto.WireBytes) b.EncodeRawBytes(x.Data) case *Communique_TempC: b.EncodeVarint(8<<3 | proto.WireFixed64) b.EncodeFixed64(math.Float64bits(x.TempC)) case *Communique_Height: b.EncodeVarint(9<<3 | proto.WireFixed32) b.EncodeFixed32(uint64(math.Float32bits(x.Height))) case *Communique_Today: b.EncodeVarint(10<<3 | proto.WireVarint) b.EncodeVarint(uint64(x.Today)) case *Communique_Maybe: t := uint64(0) if x.Maybe { t = 1 } b.EncodeVarint(11<<3 | proto.WireVarint) b.EncodeVarint(t) case *Communique_Delta_: b.EncodeVarint(12<<3 | proto.WireVarint) b.EncodeZigzag32(uint64(x.Delta)) case *Communique_Msg: b.EncodeVarint(13<<3 | proto.WireBytes) if err := b.EncodeMessage(x.Msg); err != nil { return err } case *Communique_Somegroup: b.EncodeVarint(14<<3 | proto.WireStartGroup) if err := b.Marshal(x.Somegroup); err != nil { return err } b.EncodeVarint(14<<3 | proto.WireEndGroup) case nil: default: return fmt.Errorf("Communique.Union has unexpected type %T", x) } return nil } func _Communique_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) { m := msg.(*Communique) switch tag { case 5: // union.number if wire != proto.WireVarint { return true, proto.ErrInternalBadWireType } x, err := b.DecodeVarint() m.Union = &Communique_Number{int32(x)} return true, err case 6: // union.name if wire != proto.WireBytes { return true, proto.ErrInternalBadWireType } x, err := b.DecodeStringBytes() m.Union = &Communique_Name{x} return true, err case 7: // union.data if wire != proto.WireBytes { return true, proto.ErrInternalBadWireType } x, err := b.DecodeRawBytes(true) m.Union = &Communique_Data{x} return true, err case 8: // union.temp_c if wire != proto.WireFixed64 { return true, proto.ErrInternalBadWireType } x, err := b.DecodeFixed64() m.Union = &Communique_TempC{math.Float64frombits(x)} return true, err case 9: // union.height if wire != proto.WireFixed32 { return true, proto.ErrInternalBadWireType } x, err := b.DecodeFixed32() m.Union = &Communique_Height{math.Float32frombits(uint32(x))} return true, err case 10: // union.today if wire != proto.WireVarint { return true, proto.ErrInternalBadWireType } x, err := b.DecodeVarint() m.Union = &Communique_Today{Days(x)} return true, err case 11: // union.maybe if wire != proto.WireVarint { return true, proto.ErrInternalBadWireType } x, err := b.DecodeVarint() m.Union = &Communique_Maybe{x != 0} return true, err case 12: // union.delta if wire != proto.WireVarint { return true, proto.ErrInternalBadWireType } x, err := b.DecodeZigzag32() m.Union = &Communique_Delta_{int32(x)} return true, err case 13: // union.msg if wire != proto.WireBytes { return true, proto.ErrInternalBadWireType } msg := new(Reply) err := b.DecodeMessage(msg) m.Union = &Communique_Msg{msg} return true, err case 14: // union.somegroup if wire != proto.WireStartGroup { return true, proto.ErrInternalBadWireType } msg := new(Communique_SomeGroup) err := b.DecodeGroup(msg) m.Union = &Communique_Somegroup{msg} return true, err default: return false, nil } } func _Communique_OneofSizer(msg proto.Message) (n int) { m := msg.(*Communique) // union switch x := m.Union.(type) { case *Communique_Number: n += proto.SizeVarint(5<<3 | proto.WireVarint) n += proto.SizeVarint(uint64(x.Number)) case *Communique_Name: n += proto.SizeVarint(6<<3 | proto.WireBytes) n += proto.SizeVarint(uint64(len(x.Name))) n += len(x.Name) case *Communique_Data: n += proto.SizeVarint(7<<3 | proto.WireBytes) n += proto.SizeVarint(uint64(len(x.Data))) n += len(x.Data) case *Communique_TempC: n += proto.SizeVarint(8<<3 | proto.WireFixed64) n += 8 case *Communique_Height: n += proto.SizeVarint(9<<3 | proto.WireFixed32) n += 4 case *Communique_Today: n += proto.SizeVarint(10<<3 | proto.WireVarint) n += proto.SizeVarint(uint64(x.Today)) case *Communique_Maybe: n += proto.SizeVarint(11<<3 | proto.WireVarint) n += 1 case *Communique_Delta_: n += proto.SizeVarint(12<<3 | proto.WireVarint) n += proto.SizeVarint(uint64((uint32(x.Delta) << 1) ^ uint32((int32(x.Delta) >> 31)))) case *Communique_Msg: s := proto.Size(x.Msg) n += proto.SizeVarint(13<<3 | proto.WireBytes) n += proto.SizeVarint(uint64(s)) n += s case *Communique_Somegroup: n += proto.SizeVarint(14<<3 | proto.WireStartGroup) n += proto.Size(x.Somegroup) n += proto.SizeVarint(14<<3 | proto.WireEndGroup) case nil: default: panic(fmt.Sprintf("proto: unexpected type %T in oneof", x)) } return n } type Communique_SomeGroup struct { Member *string `protobuf:"bytes,15,opt,name=member" json:"member,omitempty"` XXX_unrecognized []byte `json:"-"` } func (m *Communique_SomeGroup) Reset() { *m = Communique_SomeGroup{} } func (m *Communique_SomeGroup) String() string { return proto.CompactTextString(m) } func (*Communique_SomeGroup) ProtoMessage() {} func (m *Communique_SomeGroup) GetMember() string { if m != nil && m.Member != nil { return *m.Member } return "" } type Communique_Delta struct { XXX_unrecognized []byte `json:"-"` } func (m *Communique_Delta) Reset() { *m = Communique_Delta{} } func (m *Communique_Delta) String() string { return proto.CompactTextString(m) } func (*Communique_Delta) ProtoMessage() {} var E_Tag = &proto.ExtensionDesc{ ExtendedType: (*Reply)(nil), ExtensionType: (*string)(nil), Field: 103, Name: "my.test.tag", Tag: "bytes,103,opt,name=tag", } var E_Donut = &proto.ExtensionDesc{ ExtendedType: (*Reply)(nil), ExtensionType: (*OtherReplyExtensions)(nil), Field: 106, Name: "my.test.donut", Tag: "bytes,106,opt,name=donut", } func init() { proto.RegisterType((*Request)(nil), "my.test.Request") proto.RegisterType((*Request_SomeGroup)(nil), "my.test.Request.SomeGroup") proto.RegisterType((*Reply)(nil), "my.test.Reply") proto.RegisterType((*Reply_Entry)(nil), "my.test.Reply.Entry") proto.RegisterType((*OtherBase)(nil), "my.test.OtherBase") proto.RegisterType((*ReplyExtensions)(nil), "my.test.ReplyExtensions") proto.RegisterType((*OtherReplyExtensions)(nil), "my.test.OtherReplyExtensions") proto.RegisterType((*OldReply)(nil), "my.test.OldReply") proto.RegisterType((*Communique)(nil), "my.test.Communique") proto.RegisterType((*Communique_SomeGroup)(nil), "my.test.Communique.SomeGroup") proto.RegisterType((*Communique_Delta)(nil), "my.test.Communique.Delta") proto.RegisterEnum("my.test.HatType", HatType_name, HatType_value) proto.RegisterEnum("my.test.Days", Days_name, Days_value) proto.RegisterEnum("my.test.Request_Color", Request_Color_name, Request_Color_value) proto.RegisterEnum("my.test.Reply_Entry_Game", Reply_Entry_Game_name, Reply_Entry_Game_value) proto.RegisterExtension(E_ReplyExtensions_Time) proto.RegisterExtension(E_ReplyExtensions_Carrot) proto.RegisterExtension(E_ReplyExtensions_Donut) proto.RegisterExtension(E_Tag) proto.RegisterExtension(E_Donut) } lxd-2.0.0/dist/src/github.com/golang/protobuf/protoc-gen-go/testdata/my_test/test.pb.go0000644061062106075000000005775512702772352033523 0ustar00stgraberdomain admins00000000000000// Code generated by protoc-gen-go. // source: my_test/test.proto // DO NOT EDIT! /* Package my_test is a generated protocol buffer package. This package holds interesting messages. It is generated from these files: my_test/test.proto It has these top-level messages: Request Reply OtherBase ReplyExtensions OtherReplyExtensions OldReply Communique */ package my_test import proto "github.com/golang/protobuf/proto" import fmt "fmt" import math "math" import _ "github.com/golang/protobuf/protoc-gen-go/testdata/multi" // Reference imports to suppress errors if they are not otherwise used. var _ = proto.Marshal var _ = fmt.Errorf var _ = math.Inf // This is a compile-time assertion to ensure that this generated file // is compatible with the proto package it is being compiled against. const _ = proto.ProtoPackageIsVersion1 type HatType int32 const ( // deliberately skipping 0 HatType_FEDORA HatType = 1 HatType_FEZ HatType = 2 ) var HatType_name = map[int32]string{ 1: "FEDORA", 2: "FEZ", } var HatType_value = map[string]int32{ "FEDORA": 1, "FEZ": 2, } func (x HatType) Enum() *HatType { p := new(HatType) *p = x return p } func (x HatType) String() string { return proto.EnumName(HatType_name, int32(x)) } func (x *HatType) UnmarshalJSON(data []byte) error { value, err := proto.UnmarshalJSONEnum(HatType_value, data, "HatType") if err != nil { return err } *x = HatType(value) return nil } // This enum represents days of the week. type Days int32 const ( Days_MONDAY Days = 1 Days_TUESDAY Days = 2 Days_LUNDI Days = 1 ) var Days_name = map[int32]string{ 1: "MONDAY", 2: "TUESDAY", // Duplicate value: 1: "LUNDI", } var Days_value = map[string]int32{ "MONDAY": 1, "TUESDAY": 2, "LUNDI": 1, } func (x Days) Enum() *Days { p := new(Days) *p = x return p } func (x Days) String() string { return proto.EnumName(Days_name, int32(x)) } func (x *Days) UnmarshalJSON(data []byte) error { value, err := proto.UnmarshalJSONEnum(Days_value, data, "Days") if err != nil { return err } *x = Days(value) return nil } type Request_Color int32 const ( Request_RED Request_Color = 0 Request_GREEN Request_Color = 1 Request_BLUE Request_Color = 2 ) var Request_Color_name = map[int32]string{ 0: "RED", 1: "GREEN", 2: "BLUE", } var Request_Color_value = map[string]int32{ "RED": 0, "GREEN": 1, "BLUE": 2, } func (x Request_Color) Enum() *Request_Color { p := new(Request_Color) *p = x return p } func (x Request_Color) String() string { return proto.EnumName(Request_Color_name, int32(x)) } func (x *Request_Color) UnmarshalJSON(data []byte) error { value, err := proto.UnmarshalJSONEnum(Request_Color_value, data, "Request_Color") if err != nil { return err } *x = Request_Color(value) return nil } type Reply_Entry_Game int32 const ( Reply_Entry_FOOTBALL Reply_Entry_Game = 1 Reply_Entry_TENNIS Reply_Entry_Game = 2 ) var Reply_Entry_Game_name = map[int32]string{ 1: "FOOTBALL", 2: "TENNIS", } var Reply_Entry_Game_value = map[string]int32{ "FOOTBALL": 1, "TENNIS": 2, } func (x Reply_Entry_Game) Enum() *Reply_Entry_Game { p := new(Reply_Entry_Game) *p = x return p } func (x Reply_Entry_Game) String() string { return proto.EnumName(Reply_Entry_Game_name, int32(x)) } func (x *Reply_Entry_Game) UnmarshalJSON(data []byte) error { value, err := proto.UnmarshalJSONEnum(Reply_Entry_Game_value, data, "Reply_Entry_Game") if err != nil { return err } *x = Reply_Entry_Game(value) return nil } // This is a message that might be sent somewhere. type Request struct { Key []int64 `protobuf:"varint,1,rep,name=key" json:"key,omitempty"` // optional imp.ImportedMessage imported_message = 2; Hue *Request_Color `protobuf:"varint,3,opt,name=hue,enum=my.test.Request_Color" json:"hue,omitempty"` Hat *HatType `protobuf:"varint,4,opt,name=hat,enum=my.test.HatType,def=1" json:"hat,omitempty"` // optional imp.ImportedMessage.Owner owner = 6; Deadline *float32 `protobuf:"fixed32,7,opt,name=deadline,def=inf" json:"deadline,omitempty"` Somegroup *Request_SomeGroup `protobuf:"group,8,opt,name=SomeGroup,json=somegroup" json:"somegroup,omitempty"` // This is a map field. It will generate map[int32]string. NameMapping map[int32]string `protobuf:"bytes,14,rep,name=name_mapping,json=nameMapping" json:"name_mapping,omitempty" protobuf_key:"varint,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` // This is a map field whose value type is a message. MsgMapping map[int64]*Reply `protobuf:"bytes,15,rep,name=msg_mapping,json=msgMapping" json:"msg_mapping,omitempty" protobuf_key:"zigzag64,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` Reset_ *int32 `protobuf:"varint,12,opt,name=reset" json:"reset,omitempty"` // This field should not conflict with any getters. GetKey_ *string `protobuf:"bytes,16,opt,name=get_key,json=getKey" json:"get_key,omitempty"` XXX_unrecognized []byte `json:"-"` } func (m *Request) Reset() { *m = Request{} } func (m *Request) String() string { return proto.CompactTextString(m) } func (*Request) ProtoMessage() {} const Default_Request_Hat HatType = HatType_FEDORA var Default_Request_Deadline float32 = float32(math.Inf(1)) func (m *Request) GetKey() []int64 { if m != nil { return m.Key } return nil } func (m *Request) GetHue() Request_Color { if m != nil && m.Hue != nil { return *m.Hue } return Request_RED } func (m *Request) GetHat() HatType { if m != nil && m.Hat != nil { return *m.Hat } return Default_Request_Hat } func (m *Request) GetDeadline() float32 { if m != nil && m.Deadline != nil { return *m.Deadline } return Default_Request_Deadline } func (m *Request) GetSomegroup() *Request_SomeGroup { if m != nil { return m.Somegroup } return nil } func (m *Request) GetNameMapping() map[int32]string { if m != nil { return m.NameMapping } return nil } func (m *Request) GetMsgMapping() map[int64]*Reply { if m != nil { return m.MsgMapping } return nil } func (m *Request) GetReset_() int32 { if m != nil && m.Reset_ != nil { return *m.Reset_ } return 0 } func (m *Request) GetGetKey_() string { if m != nil && m.GetKey_ != nil { return *m.GetKey_ } return "" } type Request_SomeGroup struct { GroupField *int32 `protobuf:"varint,9,opt,name=group_field,json=groupField" json:"group_field,omitempty"` XXX_unrecognized []byte `json:"-"` } func (m *Request_SomeGroup) Reset() { *m = Request_SomeGroup{} } func (m *Request_SomeGroup) String() string { return proto.CompactTextString(m) } func (*Request_SomeGroup) ProtoMessage() {} func (m *Request_SomeGroup) GetGroupField() int32 { if m != nil && m.GroupField != nil { return *m.GroupField } return 0 } type Reply struct { Found []*Reply_Entry `protobuf:"bytes,1,rep,name=found" json:"found,omitempty"` CompactKeys []int32 `protobuf:"varint,2,rep,packed,name=compact_keys,json=compactKeys" json:"compact_keys,omitempty"` XXX_extensions map[int32]proto.Extension `json:"-"` XXX_unrecognized []byte `json:"-"` } func (m *Reply) Reset() { *m = Reply{} } func (m *Reply) String() string { return proto.CompactTextString(m) } func (*Reply) ProtoMessage() {} var extRange_Reply = []proto.ExtensionRange{ {100, 536870911}, } func (*Reply) ExtensionRangeArray() []proto.ExtensionRange { return extRange_Reply } func (m *Reply) ExtensionMap() map[int32]proto.Extension { if m.XXX_extensions == nil { m.XXX_extensions = make(map[int32]proto.Extension) } return m.XXX_extensions } func (m *Reply) GetFound() []*Reply_Entry { if m != nil { return m.Found } return nil } func (m *Reply) GetCompactKeys() []int32 { if m != nil { return m.CompactKeys } return nil } type Reply_Entry struct { KeyThatNeeds_1234Camel_CasIng *int64 `protobuf:"varint,1,req,name=key_that_needs_1234camel_CasIng,json=keyThatNeeds1234camelCasIng" json:"key_that_needs_1234camel_CasIng,omitempty"` Value *int64 `protobuf:"varint,2,opt,name=value,def=7" json:"value,omitempty"` XMyFieldName_2 *int64 `protobuf:"varint,3,opt,name=_my_field_name_2,json=myFieldName2" json:"_my_field_name_2,omitempty"` XXX_unrecognized []byte `json:"-"` } func (m *Reply_Entry) Reset() { *m = Reply_Entry{} } func (m *Reply_Entry) String() string { return proto.CompactTextString(m) } func (*Reply_Entry) ProtoMessage() {} const Default_Reply_Entry_Value int64 = 7 func (m *Reply_Entry) GetKeyThatNeeds_1234Camel_CasIng() int64 { if m != nil && m.KeyThatNeeds_1234Camel_CasIng != nil { return *m.KeyThatNeeds_1234Camel_CasIng } return 0 } func (m *Reply_Entry) GetValue() int64 { if m != nil && m.Value != nil { return *m.Value } return Default_Reply_Entry_Value } func (m *Reply_Entry) GetXMyFieldName_2() int64 { if m != nil && m.XMyFieldName_2 != nil { return *m.XMyFieldName_2 } return 0 } type OtherBase struct { Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` XXX_extensions map[int32]proto.Extension `json:"-"` XXX_unrecognized []byte `json:"-"` } func (m *OtherBase) Reset() { *m = OtherBase{} } func (m *OtherBase) String() string { return proto.CompactTextString(m) } func (*OtherBase) ProtoMessage() {} var extRange_OtherBase = []proto.ExtensionRange{ {100, 536870911}, } func (*OtherBase) ExtensionRangeArray() []proto.ExtensionRange { return extRange_OtherBase } func (m *OtherBase) ExtensionMap() map[int32]proto.Extension { if m.XXX_extensions == nil { m.XXX_extensions = make(map[int32]proto.Extension) } return m.XXX_extensions } func (m *OtherBase) GetName() string { if m != nil && m.Name != nil { return *m.Name } return "" } type ReplyExtensions struct { XXX_unrecognized []byte `json:"-"` } func (m *ReplyExtensions) Reset() { *m = ReplyExtensions{} } func (m *ReplyExtensions) String() string { return proto.CompactTextString(m) } func (*ReplyExtensions) ProtoMessage() {} var E_ReplyExtensions_Time = &proto.ExtensionDesc{ ExtendedType: (*Reply)(nil), ExtensionType: (*float64)(nil), Field: 101, Name: "my.test.ReplyExtensions.time", Tag: "fixed64,101,opt,name=time", } var E_ReplyExtensions_Carrot = &proto.ExtensionDesc{ ExtendedType: (*Reply)(nil), ExtensionType: (*ReplyExtensions)(nil), Field: 105, Name: "my.test.ReplyExtensions.carrot", Tag: "bytes,105,opt,name=carrot", } var E_ReplyExtensions_Donut = &proto.ExtensionDesc{ ExtendedType: (*OtherBase)(nil), ExtensionType: (*ReplyExtensions)(nil), Field: 101, Name: "my.test.ReplyExtensions.donut", Tag: "bytes,101,opt,name=donut", } type OtherReplyExtensions struct { Key *int32 `protobuf:"varint,1,opt,name=key" json:"key,omitempty"` XXX_unrecognized []byte `json:"-"` } func (m *OtherReplyExtensions) Reset() { *m = OtherReplyExtensions{} } func (m *OtherReplyExtensions) String() string { return proto.CompactTextString(m) } func (*OtherReplyExtensions) ProtoMessage() {} func (m *OtherReplyExtensions) GetKey() int32 { if m != nil && m.Key != nil { return *m.Key } return 0 } type OldReply struct { XXX_extensions map[int32]proto.Extension `json:"-"` XXX_unrecognized []byte `json:"-"` } func (m *OldReply) Reset() { *m = OldReply{} } func (m *OldReply) String() string { return proto.CompactTextString(m) } func (*OldReply) ProtoMessage() {} func (m *OldReply) Marshal() ([]byte, error) { return proto.MarshalMessageSet(m.ExtensionMap()) } func (m *OldReply) Unmarshal(buf []byte) error { return proto.UnmarshalMessageSet(buf, m.ExtensionMap()) } func (m *OldReply) MarshalJSON() ([]byte, error) { return proto.MarshalMessageSetJSON(m.XXX_extensions) } func (m *OldReply) UnmarshalJSON(buf []byte) error { return proto.UnmarshalMessageSetJSON(buf, m.XXX_extensions) } // ensure OldReply satisfies proto.Marshaler and proto.Unmarshaler var _ proto.Marshaler = (*OldReply)(nil) var _ proto.Unmarshaler = (*OldReply)(nil) var extRange_OldReply = []proto.ExtensionRange{ {100, 2147483646}, } func (*OldReply) ExtensionRangeArray() []proto.ExtensionRange { return extRange_OldReply } func (m *OldReply) ExtensionMap() map[int32]proto.Extension { if m.XXX_extensions == nil { m.XXX_extensions = make(map[int32]proto.Extension) } return m.XXX_extensions } type Communique struct { MakeMeCry *bool `protobuf:"varint,1,opt,name=make_me_cry,json=makeMeCry" json:"make_me_cry,omitempty"` // This is a oneof, called "union". // // Types that are valid to be assigned to Union: // *Communique_Number // *Communique_Name // *Communique_Data // *Communique_TempC // *Communique_Height // *Communique_Today // *Communique_Maybe // *Communique_Delta_ // *Communique_Msg // *Communique_Somegroup Union isCommunique_Union `protobuf_oneof:"union"` XXX_unrecognized []byte `json:"-"` } func (m *Communique) Reset() { *m = Communique{} } func (m *Communique) String() string { return proto.CompactTextString(m) } func (*Communique) ProtoMessage() {} type isCommunique_Union interface { isCommunique_Union() } type Communique_Number struct { Number int32 `protobuf:"varint,5,opt,name=number,oneof"` } type Communique_Name struct { Name string `protobuf:"bytes,6,opt,name=name,oneof"` } type Communique_Data struct { Data []byte `protobuf:"bytes,7,opt,name=data,oneof"` } type Communique_TempC struct { TempC float64 `protobuf:"fixed64,8,opt,name=temp_c,json=tempC,oneof"` } type Communique_Height struct { Height float32 `protobuf:"fixed32,9,opt,name=height,oneof"` } type Communique_Today struct { Today Days `protobuf:"varint,10,opt,name=today,enum=my.test.Days,oneof"` } type Communique_Maybe struct { Maybe bool `protobuf:"varint,11,opt,name=maybe,oneof"` } type Communique_Delta_ struct { Delta int32 `protobuf:"zigzag32,12,opt,name=delta,oneof"` } type Communique_Msg struct { Msg *Reply `protobuf:"bytes,13,opt,name=msg,oneof"` } type Communique_Somegroup struct { Somegroup *Communique_SomeGroup `protobuf:"group,14,opt,name=SomeGroup,json=somegroup,oneof"` } func (*Communique_Number) isCommunique_Union() {} func (*Communique_Name) isCommunique_Union() {} func (*Communique_Data) isCommunique_Union() {} func (*Communique_TempC) isCommunique_Union() {} func (*Communique_Height) isCommunique_Union() {} func (*Communique_Today) isCommunique_Union() {} func (*Communique_Maybe) isCommunique_Union() {} func (*Communique_Delta_) isCommunique_Union() {} func (*Communique_Msg) isCommunique_Union() {} func (*Communique_Somegroup) isCommunique_Union() {} func (m *Communique) GetUnion() isCommunique_Union { if m != nil { return m.Union } return nil } func (m *Communique) GetMakeMeCry() bool { if m != nil && m.MakeMeCry != nil { return *m.MakeMeCry } return false } func (m *Communique) GetNumber() int32 { if x, ok := m.GetUnion().(*Communique_Number); ok { return x.Number } return 0 } func (m *Communique) GetName() string { if x, ok := m.GetUnion().(*Communique_Name); ok { return x.Name } return "" } func (m *Communique) GetData() []byte { if x, ok := m.GetUnion().(*Communique_Data); ok { return x.Data } return nil } func (m *Communique) GetTempC() float64 { if x, ok := m.GetUnion().(*Communique_TempC); ok { return x.TempC } return 0 } func (m *Communique) GetHeight() float32 { if x, ok := m.GetUnion().(*Communique_Height); ok { return x.Height } return 0 } func (m *Communique) GetToday() Days { if x, ok := m.GetUnion().(*Communique_Today); ok { return x.Today } return Days_MONDAY } func (m *Communique) GetMaybe() bool { if x, ok := m.GetUnion().(*Communique_Maybe); ok { return x.Maybe } return false } func (m *Communique) GetDelta() int32 { if x, ok := m.GetUnion().(*Communique_Delta_); ok { return x.Delta } return 0 } func (m *Communique) GetMsg() *Reply { if x, ok := m.GetUnion().(*Communique_Msg); ok { return x.Msg } return nil } func (m *Communique) GetSomegroup() *Communique_SomeGroup { if x, ok := m.GetUnion().(*Communique_Somegroup); ok { return x.Somegroup } return nil } // XXX_OneofFuncs is for the internal use of the proto package. func (*Communique) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) { return _Communique_OneofMarshaler, _Communique_OneofUnmarshaler, _Communique_OneofSizer, []interface{}{ (*Communique_Number)(nil), (*Communique_Name)(nil), (*Communique_Data)(nil), (*Communique_TempC)(nil), (*Communique_Height)(nil), (*Communique_Today)(nil), (*Communique_Maybe)(nil), (*Communique_Delta_)(nil), (*Communique_Msg)(nil), (*Communique_Somegroup)(nil), } } func _Communique_OneofMarshaler(msg proto.Message, b *proto.Buffer) error { m := msg.(*Communique) // union switch x := m.Union.(type) { case *Communique_Number: b.EncodeVarint(5<<3 | proto.WireVarint) b.EncodeVarint(uint64(x.Number)) case *Communique_Name: b.EncodeVarint(6<<3 | proto.WireBytes) b.EncodeStringBytes(x.Name) case *Communique_Data: b.EncodeVarint(7<<3 | proto.WireBytes) b.EncodeRawBytes(x.Data) case *Communique_TempC: b.EncodeVarint(8<<3 | proto.WireFixed64) b.EncodeFixed64(math.Float64bits(x.TempC)) case *Communique_Height: b.EncodeVarint(9<<3 | proto.WireFixed32) b.EncodeFixed32(uint64(math.Float32bits(x.Height))) case *Communique_Today: b.EncodeVarint(10<<3 | proto.WireVarint) b.EncodeVarint(uint64(x.Today)) case *Communique_Maybe: t := uint64(0) if x.Maybe { t = 1 } b.EncodeVarint(11<<3 | proto.WireVarint) b.EncodeVarint(t) case *Communique_Delta_: b.EncodeVarint(12<<3 | proto.WireVarint) b.EncodeZigzag32(uint64(x.Delta)) case *Communique_Msg: b.EncodeVarint(13<<3 | proto.WireBytes) if err := b.EncodeMessage(x.Msg); err != nil { return err } case *Communique_Somegroup: b.EncodeVarint(14<<3 | proto.WireStartGroup) if err := b.Marshal(x.Somegroup); err != nil { return err } b.EncodeVarint(14<<3 | proto.WireEndGroup) case nil: default: return fmt.Errorf("Communique.Union has unexpected type %T", x) } return nil } func _Communique_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) { m := msg.(*Communique) switch tag { case 5: // union.number if wire != proto.WireVarint { return true, proto.ErrInternalBadWireType } x, err := b.DecodeVarint() m.Union = &Communique_Number{int32(x)} return true, err case 6: // union.name if wire != proto.WireBytes { return true, proto.ErrInternalBadWireType } x, err := b.DecodeStringBytes() m.Union = &Communique_Name{x} return true, err case 7: // union.data if wire != proto.WireBytes { return true, proto.ErrInternalBadWireType } x, err := b.DecodeRawBytes(true) m.Union = &Communique_Data{x} return true, err case 8: // union.temp_c if wire != proto.WireFixed64 { return true, proto.ErrInternalBadWireType } x, err := b.DecodeFixed64() m.Union = &Communique_TempC{math.Float64frombits(x)} return true, err case 9: // union.height if wire != proto.WireFixed32 { return true, proto.ErrInternalBadWireType } x, err := b.DecodeFixed32() m.Union = &Communique_Height{math.Float32frombits(uint32(x))} return true, err case 10: // union.today if wire != proto.WireVarint { return true, proto.ErrInternalBadWireType } x, err := b.DecodeVarint() m.Union = &Communique_Today{Days(x)} return true, err case 11: // union.maybe if wire != proto.WireVarint { return true, proto.ErrInternalBadWireType } x, err := b.DecodeVarint() m.Union = &Communique_Maybe{x != 0} return true, err case 12: // union.delta if wire != proto.WireVarint { return true, proto.ErrInternalBadWireType } x, err := b.DecodeZigzag32() m.Union = &Communique_Delta_{int32(x)} return true, err case 13: // union.msg if wire != proto.WireBytes { return true, proto.ErrInternalBadWireType } msg := new(Reply) err := b.DecodeMessage(msg) m.Union = &Communique_Msg{msg} return true, err case 14: // union.somegroup if wire != proto.WireStartGroup { return true, proto.ErrInternalBadWireType } msg := new(Communique_SomeGroup) err := b.DecodeGroup(msg) m.Union = &Communique_Somegroup{msg} return true, err default: return false, nil } } func _Communique_OneofSizer(msg proto.Message) (n int) { m := msg.(*Communique) // union switch x := m.Union.(type) { case *Communique_Number: n += proto.SizeVarint(5<<3 | proto.WireVarint) n += proto.SizeVarint(uint64(x.Number)) case *Communique_Name: n += proto.SizeVarint(6<<3 | proto.WireBytes) n += proto.SizeVarint(uint64(len(x.Name))) n += len(x.Name) case *Communique_Data: n += proto.SizeVarint(7<<3 | proto.WireBytes) n += proto.SizeVarint(uint64(len(x.Data))) n += len(x.Data) case *Communique_TempC: n += proto.SizeVarint(8<<3 | proto.WireFixed64) n += 8 case *Communique_Height: n += proto.SizeVarint(9<<3 | proto.WireFixed32) n += 4 case *Communique_Today: n += proto.SizeVarint(10<<3 | proto.WireVarint) n += proto.SizeVarint(uint64(x.Today)) case *Communique_Maybe: n += proto.SizeVarint(11<<3 | proto.WireVarint) n += 1 case *Communique_Delta_: n += proto.SizeVarint(12<<3 | proto.WireVarint) n += proto.SizeVarint(uint64((uint32(x.Delta) << 1) ^ uint32((int32(x.Delta) >> 31)))) case *Communique_Msg: s := proto.Size(x.Msg) n += proto.SizeVarint(13<<3 | proto.WireBytes) n += proto.SizeVarint(uint64(s)) n += s case *Communique_Somegroup: n += proto.SizeVarint(14<<3 | proto.WireStartGroup) n += proto.Size(x.Somegroup) n += proto.SizeVarint(14<<3 | proto.WireEndGroup) case nil: default: panic(fmt.Sprintf("proto: unexpected type %T in oneof", x)) } return n } type Communique_SomeGroup struct { Member *string `protobuf:"bytes,15,opt,name=member" json:"member,omitempty"` XXX_unrecognized []byte `json:"-"` } func (m *Communique_SomeGroup) Reset() { *m = Communique_SomeGroup{} } func (m *Communique_SomeGroup) String() string { return proto.CompactTextString(m) } func (*Communique_SomeGroup) ProtoMessage() {} func (m *Communique_SomeGroup) GetMember() string { if m != nil && m.Member != nil { return *m.Member } return "" } type Communique_Delta struct { XXX_unrecognized []byte `json:"-"` } func (m *Communique_Delta) Reset() { *m = Communique_Delta{} } func (m *Communique_Delta) String() string { return proto.CompactTextString(m) } func (*Communique_Delta) ProtoMessage() {} var E_Tag = &proto.ExtensionDesc{ ExtendedType: (*Reply)(nil), ExtensionType: (*string)(nil), Field: 103, Name: "my.test.tag", Tag: "bytes,103,opt,name=tag", } var E_Donut = &proto.ExtensionDesc{ ExtendedType: (*Reply)(nil), ExtensionType: (*OtherReplyExtensions)(nil), Field: 106, Name: "my.test.donut", Tag: "bytes,106,opt,name=donut", } func init() { proto.RegisterType((*Request)(nil), "my.test.Request") proto.RegisterType((*Request_SomeGroup)(nil), "my.test.Request.SomeGroup") proto.RegisterType((*Reply)(nil), "my.test.Reply") proto.RegisterType((*Reply_Entry)(nil), "my.test.Reply.Entry") proto.RegisterType((*OtherBase)(nil), "my.test.OtherBase") proto.RegisterType((*ReplyExtensions)(nil), "my.test.ReplyExtensions") proto.RegisterType((*OtherReplyExtensions)(nil), "my.test.OtherReplyExtensions") proto.RegisterType((*OldReply)(nil), "my.test.OldReply") proto.RegisterType((*Communique)(nil), "my.test.Communique") proto.RegisterType((*Communique_SomeGroup)(nil), "my.test.Communique.SomeGroup") proto.RegisterType((*Communique_Delta)(nil), "my.test.Communique.Delta") proto.RegisterEnum("my.test.HatType", HatType_name, HatType_value) proto.RegisterEnum("my.test.Days", Days_name, Days_value) proto.RegisterEnum("my.test.Request_Color", Request_Color_name, Request_Color_value) proto.RegisterEnum("my.test.Reply_Entry_Game", Reply_Entry_Game_name, Reply_Entry_Game_value) proto.RegisterExtension(E_ReplyExtensions_Time) proto.RegisterExtension(E_ReplyExtensions_Carrot) proto.RegisterExtension(E_ReplyExtensions_Donut) proto.RegisterExtension(E_Tag) proto.RegisterExtension(E_Donut) } lxd-2.0.0/dist/src/github.com/golang/protobuf/protoc-gen-go/testdata/my_test/test.proto0000644061062106075000000001065312702772352033643 0ustar00stgraberdomain admins00000000000000// Go support for Protocol Buffers - Google's data interchange format // // Copyright 2010 The Go Authors. All rights reserved. // https://github.com/golang/protobuf // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. syntax = "proto2"; // This package holds interesting messages. package my.test; // dotted package name //import "imp.proto"; import "multi/multi1.proto"; // unused import enum HatType { // deliberately skipping 0 FEDORA = 1; FEZ = 2; } // This enum represents days of the week. enum Days { option allow_alias = true; MONDAY = 1; TUESDAY = 2; LUNDI = 1; // same value as MONDAY } // This is a message that might be sent somewhere. message Request { enum Color { RED = 0; GREEN = 1; BLUE = 2; } repeated int64 key = 1; // optional imp.ImportedMessage imported_message = 2; optional Color hue = 3; // no default optional HatType hat = 4 [default=FEDORA]; // optional imp.ImportedMessage.Owner owner = 6; optional float deadline = 7 [default=inf]; optional group SomeGroup = 8 { optional int32 group_field = 9; } // These foreign types are in imp2.proto, // which is publicly imported by imp.proto. // optional imp.PubliclyImportedMessage pub = 10; // optional imp.PubliclyImportedEnum pub_enum = 13 [default=HAIR]; // This is a map field. It will generate map[int32]string. map name_mapping = 14; // This is a map field whose value type is a message. map msg_mapping = 15; optional int32 reset = 12; // This field should not conflict with any getters. optional string get_key = 16; } message Reply { message Entry { required int64 key_that_needs_1234camel_CasIng = 1; optional int64 value = 2 [default=7]; optional int64 _my_field_name_2 = 3; enum Game { FOOTBALL = 1; TENNIS = 2; } } repeated Entry found = 1; repeated int32 compact_keys = 2 [packed=true]; extensions 100 to max; } message OtherBase { optional string name = 1; extensions 100 to max; } message ReplyExtensions { extend Reply { optional double time = 101; optional ReplyExtensions carrot = 105; } extend OtherBase { optional ReplyExtensions donut = 101; } } message OtherReplyExtensions { optional int32 key = 1; } // top-level extension extend Reply { optional string tag = 103; optional OtherReplyExtensions donut = 106; // optional imp.ImportedMessage elephant = 107; // extend with message from another file. } message OldReply { // Extensions will be encoded in MessageSet wire format. option message_set_wire_format = true; extensions 100 to max; } message Communique { optional bool make_me_cry = 1; // This is a oneof, called "union". oneof union { int32 number = 5; string name = 6; bytes data = 7; double temp_c = 8; float height = 9; Days today = 10; bool maybe = 11; sint32 delta = 12; // name will conflict with Delta below Reply msg = 13; group SomeGroup = 14 { optional string member = 15; } } message Delta {} } lxd-2.0.0/dist/src/github.com/golang/protobuf/protoc-gen-go/testdata/imp.pb.go.golden0000644061062106075000000000652512702772352033101 0ustar00stgraberdomain admins00000000000000// Code generated by protoc-gen-go. // source: imp.proto // DO NOT EDIT! package imp import proto "github.com/golang/protobuf/proto" import "math" import "os" import imp1 "imp2.pb" // Reference proto & math imports to suppress error if they are not otherwise used. var _ = proto.GetString var _ = math.Inf // Types from public import imp2.proto type PubliclyImportedMessage imp1.PubliclyImportedMessage func (this *PubliclyImportedMessage) Reset() { (*imp1.PubliclyImportedMessage)(this).Reset() } func (this *PubliclyImportedMessage) String() string { return (*imp1.PubliclyImportedMessage)(this).String() } // PubliclyImportedMessage from public import imp.proto type ImportedMessage_Owner int32 const ( ImportedMessage_DAVE ImportedMessage_Owner = 1 ImportedMessage_MIKE ImportedMessage_Owner = 2 ) var ImportedMessage_Owner_name = map[int32]string{ 1: "DAVE", 2: "MIKE", } var ImportedMessage_Owner_value = map[string]int32{ "DAVE": 1, "MIKE": 2, } // NewImportedMessage_Owner is deprecated. Use x.Enum() instead. func NewImportedMessage_Owner(x ImportedMessage_Owner) *ImportedMessage_Owner { e := ImportedMessage_Owner(x) return &e } func (x ImportedMessage_Owner) Enum() *ImportedMessage_Owner { p := new(ImportedMessage_Owner) *p = x return p } func (x ImportedMessage_Owner) String() string { return proto.EnumName(ImportedMessage_Owner_name, int32(x)) } type ImportedMessage struct { Field *int64 `protobuf:"varint,1,req,name=field" json:"field,omitempty"` XXX_extensions map[int32][]byte `json:",omitempty"` XXX_unrecognized []byte `json:",omitempty"` } func (this *ImportedMessage) Reset() { *this = ImportedMessage{} } func (this *ImportedMessage) String() string { return proto.CompactTextString(this) } var extRange_ImportedMessage = []proto.ExtensionRange{ proto.ExtensionRange{90, 100}, } func (*ImportedMessage) ExtensionRangeArray() []proto.ExtensionRange { return extRange_ImportedMessage } func (this *ImportedMessage) ExtensionMap() map[int32][]byte { if this.XXX_extensions == nil { this.XXX_extensions = make(map[int32][]byte) } return this.XXX_extensions } type ImportedExtendable struct { XXX_extensions map[int32][]byte `json:",omitempty"` XXX_unrecognized []byte `json:",omitempty"` } func (this *ImportedExtendable) Reset() { *this = ImportedExtendable{} } func (this *ImportedExtendable) String() string { return proto.CompactTextString(this) } func (this *ImportedExtendable) Marshal() ([]byte, error) { return proto.MarshalMessageSet(this.ExtensionMap()) } func (this *ImportedExtendable) Unmarshal(buf []byte) error { return proto.UnmarshalMessageSet(buf, this.ExtensionMap()) } // ensure ImportedExtendable satisfies proto.Marshaler and proto.Unmarshaler var _ proto.Marshaler = (*ImportedExtendable)(nil) var _ proto.Unmarshaler = (*ImportedExtendable)(nil) var extRange_ImportedExtendable = []proto.ExtensionRange{ proto.ExtensionRange{100, 536870911}, } func (*ImportedExtendable) ExtensionRangeArray() []proto.ExtensionRange { return extRange_ImportedExtendable } func (this *ImportedExtendable) ExtensionMap() map[int32][]byte { if this.XXX_extensions == nil { this.XXX_extensions = make(map[int32][]byte) } return this.XXX_extensions } func init() { proto.RegisterEnum("imp.ImportedMessage_Owner", ImportedMessage_Owner_name, ImportedMessage_Owner_value) } lxd-2.0.0/dist/src/github.com/golang/protobuf/protoc-gen-go/testdata/imp.proto0000644061062106075000000000453712702772352031771 0ustar00stgraberdomain admins00000000000000// Go support for Protocol Buffers - Google's data interchange format // // Copyright 2010 The Go Authors. All rights reserved. // https://github.com/golang/protobuf // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. syntax = "proto2"; package imp; import "imp2.proto"; import "imp3.proto"; message ImportedMessage { required int64 field = 1; // The forwarded getters for these fields are fiddly to get right. optional ImportedMessage2 local_msg = 2; optional ForeignImportedMessage foreign_msg = 3; // in imp3.proto optional Owner enum_field = 4; oneof union { int32 state = 9; } repeated string name = 5; repeated Owner boss = 6; repeated ImportedMessage2 memo = 7; map msg_map = 8; enum Owner { DAVE = 1; MIKE = 2; } extensions 90 to 100; } message ImportedMessage2 { } message ImportedExtendable { option message_set_wire_format = true; extensions 100 to max; } lxd-2.0.0/dist/src/github.com/golang/protobuf/protoc-gen-go/testdata/extension_base.proto0000644061062106075000000000367312702772352034212 0ustar00stgraberdomain admins00000000000000// Go support for Protocol Buffers - Google's data interchange format // // Copyright 2010 The Go Authors. All rights reserved. // https://github.com/golang/protobuf // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. syntax = "proto2"; package extension_base; message BaseMessage { optional int32 height = 1; extensions 4 to 9; extensions 16 to max; } // Another message that may be extended, using message_set_wire_format. message OldStyleMessage { option message_set_wire_format = true; extensions 100 to max; } lxd-2.0.0/dist/src/github.com/golang/protobuf/protoc-gen-go/testdata/extension_user.proto0000644061062106075000000000604412702772352034251 0ustar00stgraberdomain admins00000000000000// Go support for Protocol Buffers - Google's data interchange format // // Copyright 2010 The Go Authors. All rights reserved. // https://github.com/golang/protobuf // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. syntax = "proto2"; import "extension_base.proto"; import "extension_extra.proto"; package extension_user; message UserMessage { optional string name = 1; optional string rank = 2; } // Extend with a message extend extension_base.BaseMessage { optional UserMessage user_message = 5; } // Extend with a foreign message extend extension_base.BaseMessage { optional extension_extra.ExtraMessage extra_message = 9; } // Extend with some primitive types extend extension_base.BaseMessage { optional int32 width = 6; optional int64 area = 7; } // Extend inside the scope of another type message LoudMessage { extend extension_base.BaseMessage { optional uint32 volume = 8; } extensions 100 to max; } // Extend inside the scope of another type, using a message. message LoginMessage { extend extension_base.BaseMessage { optional UserMessage user_message = 16; } } // Extend with a repeated field extend extension_base.BaseMessage { repeated Detail detail = 17; } message Detail { optional string color = 1; } // An extension of an extension message Announcement { optional string words = 1; extend LoudMessage { optional Announcement loud_ext = 100; } } // Something that can be put in a message set. message OldStyleParcel { extend extension_base.OldStyleMessage { optional OldStyleParcel message_set_extension = 2001; } required string name = 1; optional int32 height = 2; } lxd-2.0.0/dist/src/github.com/golang/protobuf/protoc-gen-go/testdata/Makefile0000644061062106075000000000520612702772352031551 0ustar00stgraberdomain admins00000000000000# Go support for Protocol Buffers - Google's data interchange format # # Copyright 2010 The Go Authors. All rights reserved. # https://github.com/golang/protobuf # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. all: @echo run make test include ../../Make.protobuf test: golden testbuild #test: golden testbuild extension_test # ./extension_test # @echo PASS my_test/test.pb.go: my_test/test.proto protoc --go_out=Mmulti/multi1.proto=github.com/golang/protobuf/protoc-gen-go/testdata/multi:. $< golden: make -B my_test/test.pb.go sed -i '/return.*fileDescriptor/d' my_test/test.pb.go sed -i '/^var fileDescriptor/,/^}/d' my_test/test.pb.go gofmt -w my_test/test.pb.go diff -w my_test/test.pb.go my_test/test.pb.go.golden nuke: clean testbuild: regenerate go test regenerate: # Invoke protoc once to generate three independent .pb.go files in the same package. protoc --go_out=. multi/multi{1,2,3}.proto #extension_test: extension_test.$O # $(LD) -L. -o $@ $< #multi.a: multi3.pb.$O multi2.pb.$O multi1.pb.$O # rm -f multi.a # $(QUOTED_GOBIN)/gopack grc $@ $< #test.pb.go: imp.pb.go #multi1.pb.go: multi2.pb.go multi3.pb.go #main.$O: imp.pb.$O test.pb.$O multi.a #extension_test.$O: extension_base.pb.$O extension_extra.pb.$O extension_user.pb.$O lxd-2.0.0/dist/src/github.com/golang/protobuf/protoc-gen-go/testdata/grpc.proto0000644061062106075000000000422112702772352032125 0ustar00stgraberdomain admins00000000000000// Go support for Protocol Buffers - Google's data interchange format // // Copyright 2015 The Go Authors. All rights reserved. // https://github.com/golang/protobuf // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. syntax = "proto3"; package grpc.testing; message SimpleRequest { } message SimpleResponse { } message StreamMsg { } message StreamMsg2 { } service Test { rpc UnaryCall(SimpleRequest) returns (SimpleResponse); // This RPC streams from the server only. rpc Downstream(SimpleRequest) returns (stream StreamMsg); // This RPC streams from the client. rpc Upstream(stream StreamMsg) returns (SimpleResponse); // This one streams in both directions. rpc Bidi(stream StreamMsg) returns (stream StreamMsg2); } lxd-2.0.0/dist/src/github.com/golang/protobuf/protoc-gen-go/testdata/main_test.go0000644061062106075000000000364012702772352032423 0ustar00stgraberdomain admins00000000000000// Go support for Protocol Buffers - Google's data interchange format // // Copyright 2010 The Go Authors. All rights reserved. // https://github.com/golang/protobuf // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // A simple binary to link together the protocol buffers in this test. package testdata import ( "testing" mytestpb "./my_test" multipb "github.com/golang/protobuf/protoc-gen-go/testdata/multi" ) func TestLink(t *testing.T) { _ = &multipb.Multi1{} _ = &mytestpb.Request{} } lxd-2.0.0/dist/src/github.com/golang/protobuf/protoc-gen-go/testdata/proto3.proto0000644061062106075000000000364512702772352032431 0ustar00stgraberdomain admins00000000000000// Go support for Protocol Buffers - Google's data interchange format // // Copyright 2014 The Go Authors. All rights reserved. // https://github.com/golang/protobuf // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. syntax = "proto3"; package proto3; message Request { enum Flavour { SWEET = 0; SOUR = 1; UMAMI = 2; GOPHERLICIOUS = 3; } string name = 1; repeated int64 key = 2; Flavour taste = 3; Book book = 4; } message Book { string title = 1; bytes raw_data = 2; } lxd-2.0.0/dist/src/github.com/golang/protobuf/protoc-gen-go/descriptor/0000755061062106075000000000000012702772352030453 5ustar00stgraberdomain admins00000000000000lxd-2.0.0/dist/src/github.com/golang/protobuf/protoc-gen-go/descriptor/descriptor.pb.go0000644061062106075000000024431212702772352033566 0ustar00stgraberdomain admins00000000000000// Code generated by protoc-gen-go. // source: google/protobuf/descriptor.proto // DO NOT EDIT! /* Package descriptor is a generated protocol buffer package. It is generated from these files: google/protobuf/descriptor.proto It has these top-level messages: FileDescriptorSet FileDescriptorProto DescriptorProto FieldDescriptorProto OneofDescriptorProto EnumDescriptorProto EnumValueDescriptorProto ServiceDescriptorProto MethodDescriptorProto FileOptions MessageOptions FieldOptions EnumOptions EnumValueOptions ServiceOptions MethodOptions UninterpretedOption SourceCodeInfo */ package descriptor import proto "github.com/golang/protobuf/proto" import fmt "fmt" import math "math" // Reference imports to suppress errors if they are not otherwise used. var _ = proto.Marshal var _ = fmt.Errorf var _ = math.Inf // This is a compile-time assertion to ensure that this generated file // is compatible with the proto package it is being compiled against. const _ = proto.ProtoPackageIsVersion1 type FieldDescriptorProto_Type int32 const ( // 0 is reserved for errors. // Order is weird for historical reasons. FieldDescriptorProto_TYPE_DOUBLE FieldDescriptorProto_Type = 1 FieldDescriptorProto_TYPE_FLOAT FieldDescriptorProto_Type = 2 // Not ZigZag encoded. Negative numbers take 10 bytes. Use TYPE_SINT64 if // negative values are likely. FieldDescriptorProto_TYPE_INT64 FieldDescriptorProto_Type = 3 FieldDescriptorProto_TYPE_UINT64 FieldDescriptorProto_Type = 4 // Not ZigZag encoded. Negative numbers take 10 bytes. Use TYPE_SINT32 if // negative values are likely. FieldDescriptorProto_TYPE_INT32 FieldDescriptorProto_Type = 5 FieldDescriptorProto_TYPE_FIXED64 FieldDescriptorProto_Type = 6 FieldDescriptorProto_TYPE_FIXED32 FieldDescriptorProto_Type = 7 FieldDescriptorProto_TYPE_BOOL FieldDescriptorProto_Type = 8 FieldDescriptorProto_TYPE_STRING FieldDescriptorProto_Type = 9 FieldDescriptorProto_TYPE_GROUP FieldDescriptorProto_Type = 10 FieldDescriptorProto_TYPE_MESSAGE FieldDescriptorProto_Type = 11 // New in version 2. FieldDescriptorProto_TYPE_BYTES FieldDescriptorProto_Type = 12 FieldDescriptorProto_TYPE_UINT32 FieldDescriptorProto_Type = 13 FieldDescriptorProto_TYPE_ENUM FieldDescriptorProto_Type = 14 FieldDescriptorProto_TYPE_SFIXED32 FieldDescriptorProto_Type = 15 FieldDescriptorProto_TYPE_SFIXED64 FieldDescriptorProto_Type = 16 FieldDescriptorProto_TYPE_SINT32 FieldDescriptorProto_Type = 17 FieldDescriptorProto_TYPE_SINT64 FieldDescriptorProto_Type = 18 ) var FieldDescriptorProto_Type_name = map[int32]string{ 1: "TYPE_DOUBLE", 2: "TYPE_FLOAT", 3: "TYPE_INT64", 4: "TYPE_UINT64", 5: "TYPE_INT32", 6: "TYPE_FIXED64", 7: "TYPE_FIXED32", 8: "TYPE_BOOL", 9: "TYPE_STRING", 10: "TYPE_GROUP", 11: "TYPE_MESSAGE", 12: "TYPE_BYTES", 13: "TYPE_UINT32", 14: "TYPE_ENUM", 15: "TYPE_SFIXED32", 16: "TYPE_SFIXED64", 17: "TYPE_SINT32", 18: "TYPE_SINT64", } var FieldDescriptorProto_Type_value = map[string]int32{ "TYPE_DOUBLE": 1, "TYPE_FLOAT": 2, "TYPE_INT64": 3, "TYPE_UINT64": 4, "TYPE_INT32": 5, "TYPE_FIXED64": 6, "TYPE_FIXED32": 7, "TYPE_BOOL": 8, "TYPE_STRING": 9, "TYPE_GROUP": 10, "TYPE_MESSAGE": 11, "TYPE_BYTES": 12, "TYPE_UINT32": 13, "TYPE_ENUM": 14, "TYPE_SFIXED32": 15, "TYPE_SFIXED64": 16, "TYPE_SINT32": 17, "TYPE_SINT64": 18, } func (x FieldDescriptorProto_Type) Enum() *FieldDescriptorProto_Type { p := new(FieldDescriptorProto_Type) *p = x return p } func (x FieldDescriptorProto_Type) String() string { return proto.EnumName(FieldDescriptorProto_Type_name, int32(x)) } func (x *FieldDescriptorProto_Type) UnmarshalJSON(data []byte) error { value, err := proto.UnmarshalJSONEnum(FieldDescriptorProto_Type_value, data, "FieldDescriptorProto_Type") if err != nil { return err } *x = FieldDescriptorProto_Type(value) return nil } func (FieldDescriptorProto_Type) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{3, 0} } type FieldDescriptorProto_Label int32 const ( // 0 is reserved for errors FieldDescriptorProto_LABEL_OPTIONAL FieldDescriptorProto_Label = 1 FieldDescriptorProto_LABEL_REQUIRED FieldDescriptorProto_Label = 2 FieldDescriptorProto_LABEL_REPEATED FieldDescriptorProto_Label = 3 ) var FieldDescriptorProto_Label_name = map[int32]string{ 1: "LABEL_OPTIONAL", 2: "LABEL_REQUIRED", 3: "LABEL_REPEATED", } var FieldDescriptorProto_Label_value = map[string]int32{ "LABEL_OPTIONAL": 1, "LABEL_REQUIRED": 2, "LABEL_REPEATED": 3, } func (x FieldDescriptorProto_Label) Enum() *FieldDescriptorProto_Label { p := new(FieldDescriptorProto_Label) *p = x return p } func (x FieldDescriptorProto_Label) String() string { return proto.EnumName(FieldDescriptorProto_Label_name, int32(x)) } func (x *FieldDescriptorProto_Label) UnmarshalJSON(data []byte) error { value, err := proto.UnmarshalJSONEnum(FieldDescriptorProto_Label_value, data, "FieldDescriptorProto_Label") if err != nil { return err } *x = FieldDescriptorProto_Label(value) return nil } func (FieldDescriptorProto_Label) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{3, 1} } // Generated classes can be optimized for speed or code size. type FileOptions_OptimizeMode int32 const ( FileOptions_SPEED FileOptions_OptimizeMode = 1 // etc. FileOptions_CODE_SIZE FileOptions_OptimizeMode = 2 FileOptions_LITE_RUNTIME FileOptions_OptimizeMode = 3 ) var FileOptions_OptimizeMode_name = map[int32]string{ 1: "SPEED", 2: "CODE_SIZE", 3: "LITE_RUNTIME", } var FileOptions_OptimizeMode_value = map[string]int32{ "SPEED": 1, "CODE_SIZE": 2, "LITE_RUNTIME": 3, } func (x FileOptions_OptimizeMode) Enum() *FileOptions_OptimizeMode { p := new(FileOptions_OptimizeMode) *p = x return p } func (x FileOptions_OptimizeMode) String() string { return proto.EnumName(FileOptions_OptimizeMode_name, int32(x)) } func (x *FileOptions_OptimizeMode) UnmarshalJSON(data []byte) error { value, err := proto.UnmarshalJSONEnum(FileOptions_OptimizeMode_value, data, "FileOptions_OptimizeMode") if err != nil { return err } *x = FileOptions_OptimizeMode(value) return nil } func (FileOptions_OptimizeMode) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{9, 0} } type FieldOptions_CType int32 const ( // Default mode. FieldOptions_STRING FieldOptions_CType = 0 FieldOptions_CORD FieldOptions_CType = 1 FieldOptions_STRING_PIECE FieldOptions_CType = 2 ) var FieldOptions_CType_name = map[int32]string{ 0: "STRING", 1: "CORD", 2: "STRING_PIECE", } var FieldOptions_CType_value = map[string]int32{ "STRING": 0, "CORD": 1, "STRING_PIECE": 2, } func (x FieldOptions_CType) Enum() *FieldOptions_CType { p := new(FieldOptions_CType) *p = x return p } func (x FieldOptions_CType) String() string { return proto.EnumName(FieldOptions_CType_name, int32(x)) } func (x *FieldOptions_CType) UnmarshalJSON(data []byte) error { value, err := proto.UnmarshalJSONEnum(FieldOptions_CType_value, data, "FieldOptions_CType") if err != nil { return err } *x = FieldOptions_CType(value) return nil } func (FieldOptions_CType) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{11, 0} } type FieldOptions_JSType int32 const ( // Use the default type. FieldOptions_JS_NORMAL FieldOptions_JSType = 0 // Use JavaScript strings. FieldOptions_JS_STRING FieldOptions_JSType = 1 // Use JavaScript numbers. FieldOptions_JS_NUMBER FieldOptions_JSType = 2 ) var FieldOptions_JSType_name = map[int32]string{ 0: "JS_NORMAL", 1: "JS_STRING", 2: "JS_NUMBER", } var FieldOptions_JSType_value = map[string]int32{ "JS_NORMAL": 0, "JS_STRING": 1, "JS_NUMBER": 2, } func (x FieldOptions_JSType) Enum() *FieldOptions_JSType { p := new(FieldOptions_JSType) *p = x return p } func (x FieldOptions_JSType) String() string { return proto.EnumName(FieldOptions_JSType_name, int32(x)) } func (x *FieldOptions_JSType) UnmarshalJSON(data []byte) error { value, err := proto.UnmarshalJSONEnum(FieldOptions_JSType_value, data, "FieldOptions_JSType") if err != nil { return err } *x = FieldOptions_JSType(value) return nil } func (FieldOptions_JSType) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{11, 1} } // The protocol compiler can output a FileDescriptorSet containing the .proto // files it parses. type FileDescriptorSet struct { File []*FileDescriptorProto `protobuf:"bytes,1,rep,name=file" json:"file,omitempty"` XXX_unrecognized []byte `json:"-"` } func (m *FileDescriptorSet) Reset() { *m = FileDescriptorSet{} } func (m *FileDescriptorSet) String() string { return proto.CompactTextString(m) } func (*FileDescriptorSet) ProtoMessage() {} func (*FileDescriptorSet) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } func (m *FileDescriptorSet) GetFile() []*FileDescriptorProto { if m != nil { return m.File } return nil } // Describes a complete .proto file. type FileDescriptorProto struct { Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` Package *string `protobuf:"bytes,2,opt,name=package" json:"package,omitempty"` // Names of files imported by this file. Dependency []string `protobuf:"bytes,3,rep,name=dependency" json:"dependency,omitempty"` // Indexes of the public imported files in the dependency list above. PublicDependency []int32 `protobuf:"varint,10,rep,name=public_dependency,json=publicDependency" json:"public_dependency,omitempty"` // Indexes of the weak imported files in the dependency list. // For Google-internal migration only. Do not use. WeakDependency []int32 `protobuf:"varint,11,rep,name=weak_dependency,json=weakDependency" json:"weak_dependency,omitempty"` // All top-level definitions in this file. MessageType []*DescriptorProto `protobuf:"bytes,4,rep,name=message_type,json=messageType" json:"message_type,omitempty"` EnumType []*EnumDescriptorProto `protobuf:"bytes,5,rep,name=enum_type,json=enumType" json:"enum_type,omitempty"` Service []*ServiceDescriptorProto `protobuf:"bytes,6,rep,name=service" json:"service,omitempty"` Extension []*FieldDescriptorProto `protobuf:"bytes,7,rep,name=extension" json:"extension,omitempty"` Options *FileOptions `protobuf:"bytes,8,opt,name=options" json:"options,omitempty"` // This field contains optional information about the original source code. // You may safely remove this entire field without harming runtime // functionality of the descriptors -- the information is needed only by // development tools. SourceCodeInfo *SourceCodeInfo `protobuf:"bytes,9,opt,name=source_code_info,json=sourceCodeInfo" json:"source_code_info,omitempty"` // The syntax of the proto file. // The supported values are "proto2" and "proto3". Syntax *string `protobuf:"bytes,12,opt,name=syntax" json:"syntax,omitempty"` XXX_unrecognized []byte `json:"-"` } func (m *FileDescriptorProto) Reset() { *m = FileDescriptorProto{} } func (m *FileDescriptorProto) String() string { return proto.CompactTextString(m) } func (*FileDescriptorProto) ProtoMessage() {} func (*FileDescriptorProto) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } func (m *FileDescriptorProto) GetName() string { if m != nil && m.Name != nil { return *m.Name } return "" } func (m *FileDescriptorProto) GetPackage() string { if m != nil && m.Package != nil { return *m.Package } return "" } func (m *FileDescriptorProto) GetDependency() []string { if m != nil { return m.Dependency } return nil } func (m *FileDescriptorProto) GetPublicDependency() []int32 { if m != nil { return m.PublicDependency } return nil } func (m *FileDescriptorProto) GetWeakDependency() []int32 { if m != nil { return m.WeakDependency } return nil } func (m *FileDescriptorProto) GetMessageType() []*DescriptorProto { if m != nil { return m.MessageType } return nil } func (m *FileDescriptorProto) GetEnumType() []*EnumDescriptorProto { if m != nil { return m.EnumType } return nil } func (m *FileDescriptorProto) GetService() []*ServiceDescriptorProto { if m != nil { return m.Service } return nil } func (m *FileDescriptorProto) GetExtension() []*FieldDescriptorProto { if m != nil { return m.Extension } return nil } func (m *FileDescriptorProto) GetOptions() *FileOptions { if m != nil { return m.Options } return nil } func (m *FileDescriptorProto) GetSourceCodeInfo() *SourceCodeInfo { if m != nil { return m.SourceCodeInfo } return nil } func (m *FileDescriptorProto) GetSyntax() string { if m != nil && m.Syntax != nil { return *m.Syntax } return "" } // Describes a message type. type DescriptorProto struct { Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` Field []*FieldDescriptorProto `protobuf:"bytes,2,rep,name=field" json:"field,omitempty"` Extension []*FieldDescriptorProto `protobuf:"bytes,6,rep,name=extension" json:"extension,omitempty"` NestedType []*DescriptorProto `protobuf:"bytes,3,rep,name=nested_type,json=nestedType" json:"nested_type,omitempty"` EnumType []*EnumDescriptorProto `protobuf:"bytes,4,rep,name=enum_type,json=enumType" json:"enum_type,omitempty"` ExtensionRange []*DescriptorProto_ExtensionRange `protobuf:"bytes,5,rep,name=extension_range,json=extensionRange" json:"extension_range,omitempty"` OneofDecl []*OneofDescriptorProto `protobuf:"bytes,8,rep,name=oneof_decl,json=oneofDecl" json:"oneof_decl,omitempty"` Options *MessageOptions `protobuf:"bytes,7,opt,name=options" json:"options,omitempty"` ReservedRange []*DescriptorProto_ReservedRange `protobuf:"bytes,9,rep,name=reserved_range,json=reservedRange" json:"reserved_range,omitempty"` // Reserved field names, which may not be used by fields in the same message. // A given name may only be reserved once. ReservedName []string `protobuf:"bytes,10,rep,name=reserved_name,json=reservedName" json:"reserved_name,omitempty"` XXX_unrecognized []byte `json:"-"` } func (m *DescriptorProto) Reset() { *m = DescriptorProto{} } func (m *DescriptorProto) String() string { return proto.CompactTextString(m) } func (*DescriptorProto) ProtoMessage() {} func (*DescriptorProto) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} } func (m *DescriptorProto) GetName() string { if m != nil && m.Name != nil { return *m.Name } return "" } func (m *DescriptorProto) GetField() []*FieldDescriptorProto { if m != nil { return m.Field } return nil } func (m *DescriptorProto) GetExtension() []*FieldDescriptorProto { if m != nil { return m.Extension } return nil } func (m *DescriptorProto) GetNestedType() []*DescriptorProto { if m != nil { return m.NestedType } return nil } func (m *DescriptorProto) GetEnumType() []*EnumDescriptorProto { if m != nil { return m.EnumType } return nil } func (m *DescriptorProto) GetExtensionRange() []*DescriptorProto_ExtensionRange { if m != nil { return m.ExtensionRange } return nil } func (m *DescriptorProto) GetOneofDecl() []*OneofDescriptorProto { if m != nil { return m.OneofDecl } return nil } func (m *DescriptorProto) GetOptions() *MessageOptions { if m != nil { return m.Options } return nil } func (m *DescriptorProto) GetReservedRange() []*DescriptorProto_ReservedRange { if m != nil { return m.ReservedRange } return nil } func (m *DescriptorProto) GetReservedName() []string { if m != nil { return m.ReservedName } return nil } type DescriptorProto_ExtensionRange struct { Start *int32 `protobuf:"varint,1,opt,name=start" json:"start,omitempty"` End *int32 `protobuf:"varint,2,opt,name=end" json:"end,omitempty"` XXX_unrecognized []byte `json:"-"` } func (m *DescriptorProto_ExtensionRange) Reset() { *m = DescriptorProto_ExtensionRange{} } func (m *DescriptorProto_ExtensionRange) String() string { return proto.CompactTextString(m) } func (*DescriptorProto_ExtensionRange) ProtoMessage() {} func (*DescriptorProto_ExtensionRange) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2, 0} } func (m *DescriptorProto_ExtensionRange) GetStart() int32 { if m != nil && m.Start != nil { return *m.Start } return 0 } func (m *DescriptorProto_ExtensionRange) GetEnd() int32 { if m != nil && m.End != nil { return *m.End } return 0 } // Range of reserved tag numbers. Reserved tag numbers may not be used by // fields or extension ranges in the same message. Reserved ranges may // not overlap. type DescriptorProto_ReservedRange struct { Start *int32 `protobuf:"varint,1,opt,name=start" json:"start,omitempty"` End *int32 `protobuf:"varint,2,opt,name=end" json:"end,omitempty"` XXX_unrecognized []byte `json:"-"` } func (m *DescriptorProto_ReservedRange) Reset() { *m = DescriptorProto_ReservedRange{} } func (m *DescriptorProto_ReservedRange) String() string { return proto.CompactTextString(m) } func (*DescriptorProto_ReservedRange) ProtoMessage() {} func (*DescriptorProto_ReservedRange) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2, 1} } func (m *DescriptorProto_ReservedRange) GetStart() int32 { if m != nil && m.Start != nil { return *m.Start } return 0 } func (m *DescriptorProto_ReservedRange) GetEnd() int32 { if m != nil && m.End != nil { return *m.End } return 0 } // Describes a field within a message. type FieldDescriptorProto struct { Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` Number *int32 `protobuf:"varint,3,opt,name=number" json:"number,omitempty"` Label *FieldDescriptorProto_Label `protobuf:"varint,4,opt,name=label,enum=google.protobuf.FieldDescriptorProto_Label" json:"label,omitempty"` // If type_name is set, this need not be set. If both this and type_name // are set, this must be one of TYPE_ENUM, TYPE_MESSAGE or TYPE_GROUP. Type *FieldDescriptorProto_Type `protobuf:"varint,5,opt,name=type,enum=google.protobuf.FieldDescriptorProto_Type" json:"type,omitempty"` // For message and enum types, this is the name of the type. If the name // starts with a '.', it is fully-qualified. Otherwise, C++-like scoping // rules are used to find the type (i.e. first the nested types within this // message are searched, then within the parent, on up to the root // namespace). TypeName *string `protobuf:"bytes,6,opt,name=type_name,json=typeName" json:"type_name,omitempty"` // For extensions, this is the name of the type being extended. It is // resolved in the same manner as type_name. Extendee *string `protobuf:"bytes,2,opt,name=extendee" json:"extendee,omitempty"` // For numeric types, contains the original text representation of the value. // For booleans, "true" or "false". // For strings, contains the default text contents (not escaped in any way). // For bytes, contains the C escaped value. All bytes >= 128 are escaped. // TODO(kenton): Base-64 encode? DefaultValue *string `protobuf:"bytes,7,opt,name=default_value,json=defaultValue" json:"default_value,omitempty"` // If set, gives the index of a oneof in the containing type's oneof_decl // list. This field is a member of that oneof. OneofIndex *int32 `protobuf:"varint,9,opt,name=oneof_index,json=oneofIndex" json:"oneof_index,omitempty"` // JSON name of this field. The value is set by protocol compiler. If the // user has set a "json_name" option on this field, that option's value // will be used. Otherwise, it's deduced from the field's name by converting // it to camelCase. JsonName *string `protobuf:"bytes,10,opt,name=json_name,json=jsonName" json:"json_name,omitempty"` Options *FieldOptions `protobuf:"bytes,8,opt,name=options" json:"options,omitempty"` XXX_unrecognized []byte `json:"-"` } func (m *FieldDescriptorProto) Reset() { *m = FieldDescriptorProto{} } func (m *FieldDescriptorProto) String() string { return proto.CompactTextString(m) } func (*FieldDescriptorProto) ProtoMessage() {} func (*FieldDescriptorProto) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} } func (m *FieldDescriptorProto) GetName() string { if m != nil && m.Name != nil { return *m.Name } return "" } func (m *FieldDescriptorProto) GetNumber() int32 { if m != nil && m.Number != nil { return *m.Number } return 0 } func (m *FieldDescriptorProto) GetLabel() FieldDescriptorProto_Label { if m != nil && m.Label != nil { return *m.Label } return FieldDescriptorProto_LABEL_OPTIONAL } func (m *FieldDescriptorProto) GetType() FieldDescriptorProto_Type { if m != nil && m.Type != nil { return *m.Type } return FieldDescriptorProto_TYPE_DOUBLE } func (m *FieldDescriptorProto) GetTypeName() string { if m != nil && m.TypeName != nil { return *m.TypeName } return "" } func (m *FieldDescriptorProto) GetExtendee() string { if m != nil && m.Extendee != nil { return *m.Extendee } return "" } func (m *FieldDescriptorProto) GetDefaultValue() string { if m != nil && m.DefaultValue != nil { return *m.DefaultValue } return "" } func (m *FieldDescriptorProto) GetOneofIndex() int32 { if m != nil && m.OneofIndex != nil { return *m.OneofIndex } return 0 } func (m *FieldDescriptorProto) GetJsonName() string { if m != nil && m.JsonName != nil { return *m.JsonName } return "" } func (m *FieldDescriptorProto) GetOptions() *FieldOptions { if m != nil { return m.Options } return nil } // Describes a oneof. type OneofDescriptorProto struct { Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` XXX_unrecognized []byte `json:"-"` } func (m *OneofDescriptorProto) Reset() { *m = OneofDescriptorProto{} } func (m *OneofDescriptorProto) String() string { return proto.CompactTextString(m) } func (*OneofDescriptorProto) ProtoMessage() {} func (*OneofDescriptorProto) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} } func (m *OneofDescriptorProto) GetName() string { if m != nil && m.Name != nil { return *m.Name } return "" } // Describes an enum type. type EnumDescriptorProto struct { Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` Value []*EnumValueDescriptorProto `protobuf:"bytes,2,rep,name=value" json:"value,omitempty"` Options *EnumOptions `protobuf:"bytes,3,opt,name=options" json:"options,omitempty"` XXX_unrecognized []byte `json:"-"` } func (m *EnumDescriptorProto) Reset() { *m = EnumDescriptorProto{} } func (m *EnumDescriptorProto) String() string { return proto.CompactTextString(m) } func (*EnumDescriptorProto) ProtoMessage() {} func (*EnumDescriptorProto) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} } func (m *EnumDescriptorProto) GetName() string { if m != nil && m.Name != nil { return *m.Name } return "" } func (m *EnumDescriptorProto) GetValue() []*EnumValueDescriptorProto { if m != nil { return m.Value } return nil } func (m *EnumDescriptorProto) GetOptions() *EnumOptions { if m != nil { return m.Options } return nil } // Describes a value within an enum. type EnumValueDescriptorProto struct { Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` Number *int32 `protobuf:"varint,2,opt,name=number" json:"number,omitempty"` Options *EnumValueOptions `protobuf:"bytes,3,opt,name=options" json:"options,omitempty"` XXX_unrecognized []byte `json:"-"` } func (m *EnumValueDescriptorProto) Reset() { *m = EnumValueDescriptorProto{} } func (m *EnumValueDescriptorProto) String() string { return proto.CompactTextString(m) } func (*EnumValueDescriptorProto) ProtoMessage() {} func (*EnumValueDescriptorProto) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{6} } func (m *EnumValueDescriptorProto) GetName() string { if m != nil && m.Name != nil { return *m.Name } return "" } func (m *EnumValueDescriptorProto) GetNumber() int32 { if m != nil && m.Number != nil { return *m.Number } return 0 } func (m *EnumValueDescriptorProto) GetOptions() *EnumValueOptions { if m != nil { return m.Options } return nil } // Describes a service. type ServiceDescriptorProto struct { Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` Method []*MethodDescriptorProto `protobuf:"bytes,2,rep,name=method" json:"method,omitempty"` Options *ServiceOptions `protobuf:"bytes,3,opt,name=options" json:"options,omitempty"` XXX_unrecognized []byte `json:"-"` } func (m *ServiceDescriptorProto) Reset() { *m = ServiceDescriptorProto{} } func (m *ServiceDescriptorProto) String() string { return proto.CompactTextString(m) } func (*ServiceDescriptorProto) ProtoMessage() {} func (*ServiceDescriptorProto) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{7} } func (m *ServiceDescriptorProto) GetName() string { if m != nil && m.Name != nil { return *m.Name } return "" } func (m *ServiceDescriptorProto) GetMethod() []*MethodDescriptorProto { if m != nil { return m.Method } return nil } func (m *ServiceDescriptorProto) GetOptions() *ServiceOptions { if m != nil { return m.Options } return nil } // Describes a method of a service. type MethodDescriptorProto struct { Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` // Input and output type names. These are resolved in the same way as // FieldDescriptorProto.type_name, but must refer to a message type. InputType *string `protobuf:"bytes,2,opt,name=input_type,json=inputType" json:"input_type,omitempty"` OutputType *string `protobuf:"bytes,3,opt,name=output_type,json=outputType" json:"output_type,omitempty"` Options *MethodOptions `protobuf:"bytes,4,opt,name=options" json:"options,omitempty"` // Identifies if client streams multiple client messages ClientStreaming *bool `protobuf:"varint,5,opt,name=client_streaming,json=clientStreaming,def=0" json:"client_streaming,omitempty"` // Identifies if server streams multiple server messages ServerStreaming *bool `protobuf:"varint,6,opt,name=server_streaming,json=serverStreaming,def=0" json:"server_streaming,omitempty"` XXX_unrecognized []byte `json:"-"` } func (m *MethodDescriptorProto) Reset() { *m = MethodDescriptorProto{} } func (m *MethodDescriptorProto) String() string { return proto.CompactTextString(m) } func (*MethodDescriptorProto) ProtoMessage() {} func (*MethodDescriptorProto) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{8} } const Default_MethodDescriptorProto_ClientStreaming bool = false const Default_MethodDescriptorProto_ServerStreaming bool = false func (m *MethodDescriptorProto) GetName() string { if m != nil && m.Name != nil { return *m.Name } return "" } func (m *MethodDescriptorProto) GetInputType() string { if m != nil && m.InputType != nil { return *m.InputType } return "" } func (m *MethodDescriptorProto) GetOutputType() string { if m != nil && m.OutputType != nil { return *m.OutputType } return "" } func (m *MethodDescriptorProto) GetOptions() *MethodOptions { if m != nil { return m.Options } return nil } func (m *MethodDescriptorProto) GetClientStreaming() bool { if m != nil && m.ClientStreaming != nil { return *m.ClientStreaming } return Default_MethodDescriptorProto_ClientStreaming } func (m *MethodDescriptorProto) GetServerStreaming() bool { if m != nil && m.ServerStreaming != nil { return *m.ServerStreaming } return Default_MethodDescriptorProto_ServerStreaming } type FileOptions struct { // Sets the Java package where classes generated from this .proto will be // placed. By default, the proto package is used, but this is often // inappropriate because proto packages do not normally start with backwards // domain names. JavaPackage *string `protobuf:"bytes,1,opt,name=java_package,json=javaPackage" json:"java_package,omitempty"` // If set, all the classes from the .proto file are wrapped in a single // outer class with the given name. This applies to both Proto1 // (equivalent to the old "--one_java_file" option) and Proto2 (where // a .proto always translates to a single class, but you may want to // explicitly choose the class name). JavaOuterClassname *string `protobuf:"bytes,8,opt,name=java_outer_classname,json=javaOuterClassname" json:"java_outer_classname,omitempty"` // If set true, then the Java code generator will generate a separate .java // file for each top-level message, enum, and service defined in the .proto // file. Thus, these types will *not* be nested inside the outer class // named by java_outer_classname. However, the outer class will still be // generated to contain the file's getDescriptor() method as well as any // top-level extensions defined in the file. JavaMultipleFiles *bool `protobuf:"varint,10,opt,name=java_multiple_files,json=javaMultipleFiles,def=0" json:"java_multiple_files,omitempty"` // If set true, then the Java code generator will generate equals() and // hashCode() methods for all messages defined in the .proto file. // This increases generated code size, potentially substantially for large // protos, which may harm a memory-constrained application. // - In the full runtime this is a speed optimization, as the // AbstractMessage base class includes reflection-based implementations of // these methods. // - In the lite runtime, setting this option changes the semantics of // equals() and hashCode() to more closely match those of the full runtime; // the generated methods compute their results based on field values rather // than object identity. (Implementations should not assume that hashcodes // will be consistent across runtimes or versions of the protocol compiler.) JavaGenerateEqualsAndHash *bool `protobuf:"varint,20,opt,name=java_generate_equals_and_hash,json=javaGenerateEqualsAndHash,def=0" json:"java_generate_equals_and_hash,omitempty"` // If set true, then the Java2 code generator will generate code that // throws an exception whenever an attempt is made to assign a non-UTF-8 // byte sequence to a string field. // Message reflection will do the same. // However, an extension field still accepts non-UTF-8 byte sequences. // This option has no effect on when used with the lite runtime. JavaStringCheckUtf8 *bool `protobuf:"varint,27,opt,name=java_string_check_utf8,json=javaStringCheckUtf8,def=0" json:"java_string_check_utf8,omitempty"` OptimizeFor *FileOptions_OptimizeMode `protobuf:"varint,9,opt,name=optimize_for,json=optimizeFor,enum=google.protobuf.FileOptions_OptimizeMode,def=1" json:"optimize_for,omitempty"` // Sets the Go package where structs generated from this .proto will be // placed. If omitted, the Go package will be derived from the following: // - The basename of the package import path, if provided. // - Otherwise, the package statement in the .proto file, if present. // - Otherwise, the basename of the .proto file, without extension. GoPackage *string `protobuf:"bytes,11,opt,name=go_package,json=goPackage" json:"go_package,omitempty"` // Should generic services be generated in each language? "Generic" services // are not specific to any particular RPC system. They are generated by the // main code generators in each language (without additional plugins). // Generic services were the only kind of service generation supported by // early versions of google.protobuf. // // Generic services are now considered deprecated in favor of using plugins // that generate code specific to your particular RPC system. Therefore, // these default to false. Old code which depends on generic services should // explicitly set them to true. CcGenericServices *bool `protobuf:"varint,16,opt,name=cc_generic_services,json=ccGenericServices,def=0" json:"cc_generic_services,omitempty"` JavaGenericServices *bool `protobuf:"varint,17,opt,name=java_generic_services,json=javaGenericServices,def=0" json:"java_generic_services,omitempty"` PyGenericServices *bool `protobuf:"varint,18,opt,name=py_generic_services,json=pyGenericServices,def=0" json:"py_generic_services,omitempty"` // Is this file deprecated? // Depending on the target platform, this can emit Deprecated annotations // for everything in the file, or it will be completely ignored; in the very // least, this is a formalization for deprecating files. Deprecated *bool `protobuf:"varint,23,opt,name=deprecated,def=0" json:"deprecated,omitempty"` // Enables the use of arenas for the proto messages in this file. This applies // only to generated classes for C++. CcEnableArenas *bool `protobuf:"varint,31,opt,name=cc_enable_arenas,json=ccEnableArenas,def=0" json:"cc_enable_arenas,omitempty"` // Sets the objective c class prefix which is prepended to all objective c // generated classes from this .proto. There is no default. ObjcClassPrefix *string `protobuf:"bytes,36,opt,name=objc_class_prefix,json=objcClassPrefix" json:"objc_class_prefix,omitempty"` // Namespace for generated classes; defaults to the package. CsharpNamespace *string `protobuf:"bytes,37,opt,name=csharp_namespace,json=csharpNamespace" json:"csharp_namespace,omitempty"` // Whether the nano proto compiler should generate in the deprecated non-nano // suffixed package. JavananoUseDeprecatedPackage *bool `protobuf:"varint,38,opt,name=javanano_use_deprecated_package,json=javananoUseDeprecatedPackage" json:"javanano_use_deprecated_package,omitempty"` // The parser stores options it doesn't recognize here. See above. UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"` XXX_extensions map[int32]proto.Extension `json:"-"` XXX_unrecognized []byte `json:"-"` } func (m *FileOptions) Reset() { *m = FileOptions{} } func (m *FileOptions) String() string { return proto.CompactTextString(m) } func (*FileOptions) ProtoMessage() {} func (*FileOptions) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{9} } var extRange_FileOptions = []proto.ExtensionRange{ {1000, 536870911}, } func (*FileOptions) ExtensionRangeArray() []proto.ExtensionRange { return extRange_FileOptions } func (m *FileOptions) ExtensionMap() map[int32]proto.Extension { if m.XXX_extensions == nil { m.XXX_extensions = make(map[int32]proto.Extension) } return m.XXX_extensions } const Default_FileOptions_JavaMultipleFiles bool = false const Default_FileOptions_JavaGenerateEqualsAndHash bool = false const Default_FileOptions_JavaStringCheckUtf8 bool = false const Default_FileOptions_OptimizeFor FileOptions_OptimizeMode = FileOptions_SPEED const Default_FileOptions_CcGenericServices bool = false const Default_FileOptions_JavaGenericServices bool = false const Default_FileOptions_PyGenericServices bool = false const Default_FileOptions_Deprecated bool = false const Default_FileOptions_CcEnableArenas bool = false func (m *FileOptions) GetJavaPackage() string { if m != nil && m.JavaPackage != nil { return *m.JavaPackage } return "" } func (m *FileOptions) GetJavaOuterClassname() string { if m != nil && m.JavaOuterClassname != nil { return *m.JavaOuterClassname } return "" } func (m *FileOptions) GetJavaMultipleFiles() bool { if m != nil && m.JavaMultipleFiles != nil { return *m.JavaMultipleFiles } return Default_FileOptions_JavaMultipleFiles } func (m *FileOptions) GetJavaGenerateEqualsAndHash() bool { if m != nil && m.JavaGenerateEqualsAndHash != nil { return *m.JavaGenerateEqualsAndHash } return Default_FileOptions_JavaGenerateEqualsAndHash } func (m *FileOptions) GetJavaStringCheckUtf8() bool { if m != nil && m.JavaStringCheckUtf8 != nil { return *m.JavaStringCheckUtf8 } return Default_FileOptions_JavaStringCheckUtf8 } func (m *FileOptions) GetOptimizeFor() FileOptions_OptimizeMode { if m != nil && m.OptimizeFor != nil { return *m.OptimizeFor } return Default_FileOptions_OptimizeFor } func (m *FileOptions) GetGoPackage() string { if m != nil && m.GoPackage != nil { return *m.GoPackage } return "" } func (m *FileOptions) GetCcGenericServices() bool { if m != nil && m.CcGenericServices != nil { return *m.CcGenericServices } return Default_FileOptions_CcGenericServices } func (m *FileOptions) GetJavaGenericServices() bool { if m != nil && m.JavaGenericServices != nil { return *m.JavaGenericServices } return Default_FileOptions_JavaGenericServices } func (m *FileOptions) GetPyGenericServices() bool { if m != nil && m.PyGenericServices != nil { return *m.PyGenericServices } return Default_FileOptions_PyGenericServices } func (m *FileOptions) GetDeprecated() bool { if m != nil && m.Deprecated != nil { return *m.Deprecated } return Default_FileOptions_Deprecated } func (m *FileOptions) GetCcEnableArenas() bool { if m != nil && m.CcEnableArenas != nil { return *m.CcEnableArenas } return Default_FileOptions_CcEnableArenas } func (m *FileOptions) GetObjcClassPrefix() string { if m != nil && m.ObjcClassPrefix != nil { return *m.ObjcClassPrefix } return "" } func (m *FileOptions) GetCsharpNamespace() string { if m != nil && m.CsharpNamespace != nil { return *m.CsharpNamespace } return "" } func (m *FileOptions) GetJavananoUseDeprecatedPackage() bool { if m != nil && m.JavananoUseDeprecatedPackage != nil { return *m.JavananoUseDeprecatedPackage } return false } func (m *FileOptions) GetUninterpretedOption() []*UninterpretedOption { if m != nil { return m.UninterpretedOption } return nil } type MessageOptions struct { // Set true to use the old proto1 MessageSet wire format for extensions. // This is provided for backwards-compatibility with the MessageSet wire // format. You should not use this for any other reason: It's less // efficient, has fewer features, and is more complicated. // // The message must be defined exactly as follows: // message Foo { // option message_set_wire_format = true; // extensions 4 to max; // } // Note that the message cannot have any defined fields; MessageSets only // have extensions. // // All extensions of your type must be singular messages; e.g. they cannot // be int32s, enums, or repeated messages. // // Because this is an option, the above two restrictions are not enforced by // the protocol compiler. MessageSetWireFormat *bool `protobuf:"varint,1,opt,name=message_set_wire_format,json=messageSetWireFormat,def=0" json:"message_set_wire_format,omitempty"` // Disables the generation of the standard "descriptor()" accessor, which can // conflict with a field of the same name. This is meant to make migration // from proto1 easier; new code should avoid fields named "descriptor". NoStandardDescriptorAccessor *bool `protobuf:"varint,2,opt,name=no_standard_descriptor_accessor,json=noStandardDescriptorAccessor,def=0" json:"no_standard_descriptor_accessor,omitempty"` // Is this message deprecated? // Depending on the target platform, this can emit Deprecated annotations // for the message, or it will be completely ignored; in the very least, // this is a formalization for deprecating messages. Deprecated *bool `protobuf:"varint,3,opt,name=deprecated,def=0" json:"deprecated,omitempty"` // Whether the message is an automatically generated map entry type for the // maps field. // // For maps fields: // map map_field = 1; // The parsed descriptor looks like: // message MapFieldEntry { // option map_entry = true; // optional KeyType key = 1; // optional ValueType value = 2; // } // repeated MapFieldEntry map_field = 1; // // Implementations may choose not to generate the map_entry=true message, but // use a native map in the target language to hold the keys and values. // The reflection APIs in such implementions still need to work as // if the field is a repeated message field. // // NOTE: Do not set the option in .proto files. Always use the maps syntax // instead. The option should only be implicitly set by the proto compiler // parser. MapEntry *bool `protobuf:"varint,7,opt,name=map_entry,json=mapEntry" json:"map_entry,omitempty"` // The parser stores options it doesn't recognize here. See above. UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"` XXX_extensions map[int32]proto.Extension `json:"-"` XXX_unrecognized []byte `json:"-"` } func (m *MessageOptions) Reset() { *m = MessageOptions{} } func (m *MessageOptions) String() string { return proto.CompactTextString(m) } func (*MessageOptions) ProtoMessage() {} func (*MessageOptions) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{10} } var extRange_MessageOptions = []proto.ExtensionRange{ {1000, 536870911}, } func (*MessageOptions) ExtensionRangeArray() []proto.ExtensionRange { return extRange_MessageOptions } func (m *MessageOptions) ExtensionMap() map[int32]proto.Extension { if m.XXX_extensions == nil { m.XXX_extensions = make(map[int32]proto.Extension) } return m.XXX_extensions } const Default_MessageOptions_MessageSetWireFormat bool = false const Default_MessageOptions_NoStandardDescriptorAccessor bool = false const Default_MessageOptions_Deprecated bool = false func (m *MessageOptions) GetMessageSetWireFormat() bool { if m != nil && m.MessageSetWireFormat != nil { return *m.MessageSetWireFormat } return Default_MessageOptions_MessageSetWireFormat } func (m *MessageOptions) GetNoStandardDescriptorAccessor() bool { if m != nil && m.NoStandardDescriptorAccessor != nil { return *m.NoStandardDescriptorAccessor } return Default_MessageOptions_NoStandardDescriptorAccessor } func (m *MessageOptions) GetDeprecated() bool { if m != nil && m.Deprecated != nil { return *m.Deprecated } return Default_MessageOptions_Deprecated } func (m *MessageOptions) GetMapEntry() bool { if m != nil && m.MapEntry != nil { return *m.MapEntry } return false } func (m *MessageOptions) GetUninterpretedOption() []*UninterpretedOption { if m != nil { return m.UninterpretedOption } return nil } type FieldOptions struct { // The ctype option instructs the C++ code generator to use a different // representation of the field than it normally would. See the specific // options below. This option is not yet implemented in the open source // release -- sorry, we'll try to include it in a future version! Ctype *FieldOptions_CType `protobuf:"varint,1,opt,name=ctype,enum=google.protobuf.FieldOptions_CType,def=0" json:"ctype,omitempty"` // The packed option can be enabled for repeated primitive fields to enable // a more efficient representation on the wire. Rather than repeatedly // writing the tag and type for each element, the entire array is encoded as // a single length-delimited blob. In proto3, only explicit setting it to // false will avoid using packed encoding. Packed *bool `protobuf:"varint,2,opt,name=packed" json:"packed,omitempty"` // The jstype option determines the JavaScript type used for values of the // field. The option is permitted only for 64 bit integral and fixed types // (int64, uint64, sint64, fixed64, sfixed64). By default these types are // represented as JavaScript strings. This avoids loss of precision that can // happen when a large value is converted to a floating point JavaScript // numbers. Specifying JS_NUMBER for the jstype causes the generated // JavaScript code to use the JavaScript "number" type instead of strings. // This option is an enum to permit additional types to be added, // e.g. goog.math.Integer. Jstype *FieldOptions_JSType `protobuf:"varint,6,opt,name=jstype,enum=google.protobuf.FieldOptions_JSType,def=0" json:"jstype,omitempty"` // Should this field be parsed lazily? Lazy applies only to message-type // fields. It means that when the outer message is initially parsed, the // inner message's contents will not be parsed but instead stored in encoded // form. The inner message will actually be parsed when it is first accessed. // // This is only a hint. Implementations are free to choose whether to use // eager or lazy parsing regardless of the value of this option. However, // setting this option true suggests that the protocol author believes that // using lazy parsing on this field is worth the additional bookkeeping // overhead typically needed to implement it. // // This option does not affect the public interface of any generated code; // all method signatures remain the same. Furthermore, thread-safety of the // interface is not affected by this option; const methods remain safe to // call from multiple threads concurrently, while non-const methods continue // to require exclusive access. // // // Note that implementations may choose not to check required fields within // a lazy sub-message. That is, calling IsInitialized() on the outher message // may return true even if the inner message has missing required fields. // This is necessary because otherwise the inner message would have to be // parsed in order to perform the check, defeating the purpose of lazy // parsing. An implementation which chooses not to check required fields // must be consistent about it. That is, for any particular sub-message, the // implementation must either *always* check its required fields, or *never* // check its required fields, regardless of whether or not the message has // been parsed. Lazy *bool `protobuf:"varint,5,opt,name=lazy,def=0" json:"lazy,omitempty"` // Is this field deprecated? // Depending on the target platform, this can emit Deprecated annotations // for accessors, or it will be completely ignored; in the very least, this // is a formalization for deprecating fields. Deprecated *bool `protobuf:"varint,3,opt,name=deprecated,def=0" json:"deprecated,omitempty"` // For Google-internal migration only. Do not use. Weak *bool `protobuf:"varint,10,opt,name=weak,def=0" json:"weak,omitempty"` // The parser stores options it doesn't recognize here. See above. UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"` XXX_extensions map[int32]proto.Extension `json:"-"` XXX_unrecognized []byte `json:"-"` } func (m *FieldOptions) Reset() { *m = FieldOptions{} } func (m *FieldOptions) String() string { return proto.CompactTextString(m) } func (*FieldOptions) ProtoMessage() {} func (*FieldOptions) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{11} } var extRange_FieldOptions = []proto.ExtensionRange{ {1000, 536870911}, } func (*FieldOptions) ExtensionRangeArray() []proto.ExtensionRange { return extRange_FieldOptions } func (m *FieldOptions) ExtensionMap() map[int32]proto.Extension { if m.XXX_extensions == nil { m.XXX_extensions = make(map[int32]proto.Extension) } return m.XXX_extensions } const Default_FieldOptions_Ctype FieldOptions_CType = FieldOptions_STRING const Default_FieldOptions_Jstype FieldOptions_JSType = FieldOptions_JS_NORMAL const Default_FieldOptions_Lazy bool = false const Default_FieldOptions_Deprecated bool = false const Default_FieldOptions_Weak bool = false func (m *FieldOptions) GetCtype() FieldOptions_CType { if m != nil && m.Ctype != nil { return *m.Ctype } return Default_FieldOptions_Ctype } func (m *FieldOptions) GetPacked() bool { if m != nil && m.Packed != nil { return *m.Packed } return false } func (m *FieldOptions) GetJstype() FieldOptions_JSType { if m != nil && m.Jstype != nil { return *m.Jstype } return Default_FieldOptions_Jstype } func (m *FieldOptions) GetLazy() bool { if m != nil && m.Lazy != nil { return *m.Lazy } return Default_FieldOptions_Lazy } func (m *FieldOptions) GetDeprecated() bool { if m != nil && m.Deprecated != nil { return *m.Deprecated } return Default_FieldOptions_Deprecated } func (m *FieldOptions) GetWeak() bool { if m != nil && m.Weak != nil { return *m.Weak } return Default_FieldOptions_Weak } func (m *FieldOptions) GetUninterpretedOption() []*UninterpretedOption { if m != nil { return m.UninterpretedOption } return nil } type EnumOptions struct { // Set this option to true to allow mapping different tag names to the same // value. AllowAlias *bool `protobuf:"varint,2,opt,name=allow_alias,json=allowAlias" json:"allow_alias,omitempty"` // Is this enum deprecated? // Depending on the target platform, this can emit Deprecated annotations // for the enum, or it will be completely ignored; in the very least, this // is a formalization for deprecating enums. Deprecated *bool `protobuf:"varint,3,opt,name=deprecated,def=0" json:"deprecated,omitempty"` // The parser stores options it doesn't recognize here. See above. UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"` XXX_extensions map[int32]proto.Extension `json:"-"` XXX_unrecognized []byte `json:"-"` } func (m *EnumOptions) Reset() { *m = EnumOptions{} } func (m *EnumOptions) String() string { return proto.CompactTextString(m) } func (*EnumOptions) ProtoMessage() {} func (*EnumOptions) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{12} } var extRange_EnumOptions = []proto.ExtensionRange{ {1000, 536870911}, } func (*EnumOptions) ExtensionRangeArray() []proto.ExtensionRange { return extRange_EnumOptions } func (m *EnumOptions) ExtensionMap() map[int32]proto.Extension { if m.XXX_extensions == nil { m.XXX_extensions = make(map[int32]proto.Extension) } return m.XXX_extensions } const Default_EnumOptions_Deprecated bool = false func (m *EnumOptions) GetAllowAlias() bool { if m != nil && m.AllowAlias != nil { return *m.AllowAlias } return false } func (m *EnumOptions) GetDeprecated() bool { if m != nil && m.Deprecated != nil { return *m.Deprecated } return Default_EnumOptions_Deprecated } func (m *EnumOptions) GetUninterpretedOption() []*UninterpretedOption { if m != nil { return m.UninterpretedOption } return nil } type EnumValueOptions struct { // Is this enum value deprecated? // Depending on the target platform, this can emit Deprecated annotations // for the enum value, or it will be completely ignored; in the very least, // this is a formalization for deprecating enum values. Deprecated *bool `protobuf:"varint,1,opt,name=deprecated,def=0" json:"deprecated,omitempty"` // The parser stores options it doesn't recognize here. See above. UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"` XXX_extensions map[int32]proto.Extension `json:"-"` XXX_unrecognized []byte `json:"-"` } func (m *EnumValueOptions) Reset() { *m = EnumValueOptions{} } func (m *EnumValueOptions) String() string { return proto.CompactTextString(m) } func (*EnumValueOptions) ProtoMessage() {} func (*EnumValueOptions) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{13} } var extRange_EnumValueOptions = []proto.ExtensionRange{ {1000, 536870911}, } func (*EnumValueOptions) ExtensionRangeArray() []proto.ExtensionRange { return extRange_EnumValueOptions } func (m *EnumValueOptions) ExtensionMap() map[int32]proto.Extension { if m.XXX_extensions == nil { m.XXX_extensions = make(map[int32]proto.Extension) } return m.XXX_extensions } const Default_EnumValueOptions_Deprecated bool = false func (m *EnumValueOptions) GetDeprecated() bool { if m != nil && m.Deprecated != nil { return *m.Deprecated } return Default_EnumValueOptions_Deprecated } func (m *EnumValueOptions) GetUninterpretedOption() []*UninterpretedOption { if m != nil { return m.UninterpretedOption } return nil } type ServiceOptions struct { // Is this service deprecated? // Depending on the target platform, this can emit Deprecated annotations // for the service, or it will be completely ignored; in the very least, // this is a formalization for deprecating services. Deprecated *bool `protobuf:"varint,33,opt,name=deprecated,def=0" json:"deprecated,omitempty"` // The parser stores options it doesn't recognize here. See above. UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"` XXX_extensions map[int32]proto.Extension `json:"-"` XXX_unrecognized []byte `json:"-"` } func (m *ServiceOptions) Reset() { *m = ServiceOptions{} } func (m *ServiceOptions) String() string { return proto.CompactTextString(m) } func (*ServiceOptions) ProtoMessage() {} func (*ServiceOptions) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{14} } var extRange_ServiceOptions = []proto.ExtensionRange{ {1000, 536870911}, } func (*ServiceOptions) ExtensionRangeArray() []proto.ExtensionRange { return extRange_ServiceOptions } func (m *ServiceOptions) ExtensionMap() map[int32]proto.Extension { if m.XXX_extensions == nil { m.XXX_extensions = make(map[int32]proto.Extension) } return m.XXX_extensions } const Default_ServiceOptions_Deprecated bool = false func (m *ServiceOptions) GetDeprecated() bool { if m != nil && m.Deprecated != nil { return *m.Deprecated } return Default_ServiceOptions_Deprecated } func (m *ServiceOptions) GetUninterpretedOption() []*UninterpretedOption { if m != nil { return m.UninterpretedOption } return nil } type MethodOptions struct { // Is this method deprecated? // Depending on the target platform, this can emit Deprecated annotations // for the method, or it will be completely ignored; in the very least, // this is a formalization for deprecating methods. Deprecated *bool `protobuf:"varint,33,opt,name=deprecated,def=0" json:"deprecated,omitempty"` // The parser stores options it doesn't recognize here. See above. UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"` XXX_extensions map[int32]proto.Extension `json:"-"` XXX_unrecognized []byte `json:"-"` } func (m *MethodOptions) Reset() { *m = MethodOptions{} } func (m *MethodOptions) String() string { return proto.CompactTextString(m) } func (*MethodOptions) ProtoMessage() {} func (*MethodOptions) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{15} } var extRange_MethodOptions = []proto.ExtensionRange{ {1000, 536870911}, } func (*MethodOptions) ExtensionRangeArray() []proto.ExtensionRange { return extRange_MethodOptions } func (m *MethodOptions) ExtensionMap() map[int32]proto.Extension { if m.XXX_extensions == nil { m.XXX_extensions = make(map[int32]proto.Extension) } return m.XXX_extensions } const Default_MethodOptions_Deprecated bool = false func (m *MethodOptions) GetDeprecated() bool { if m != nil && m.Deprecated != nil { return *m.Deprecated } return Default_MethodOptions_Deprecated } func (m *MethodOptions) GetUninterpretedOption() []*UninterpretedOption { if m != nil { return m.UninterpretedOption } return nil } // A message representing a option the parser does not recognize. This only // appears in options protos created by the compiler::Parser class. // DescriptorPool resolves these when building Descriptor objects. Therefore, // options protos in descriptor objects (e.g. returned by Descriptor::options(), // or produced by Descriptor::CopyTo()) will never have UninterpretedOptions // in them. type UninterpretedOption struct { Name []*UninterpretedOption_NamePart `protobuf:"bytes,2,rep,name=name" json:"name,omitempty"` // The value of the uninterpreted option, in whatever type the tokenizer // identified it as during parsing. Exactly one of these should be set. IdentifierValue *string `protobuf:"bytes,3,opt,name=identifier_value,json=identifierValue" json:"identifier_value,omitempty"` PositiveIntValue *uint64 `protobuf:"varint,4,opt,name=positive_int_value,json=positiveIntValue" json:"positive_int_value,omitempty"` NegativeIntValue *int64 `protobuf:"varint,5,opt,name=negative_int_value,json=negativeIntValue" json:"negative_int_value,omitempty"` DoubleValue *float64 `protobuf:"fixed64,6,opt,name=double_value,json=doubleValue" json:"double_value,omitempty"` StringValue []byte `protobuf:"bytes,7,opt,name=string_value,json=stringValue" json:"string_value,omitempty"` AggregateValue *string `protobuf:"bytes,8,opt,name=aggregate_value,json=aggregateValue" json:"aggregate_value,omitempty"` XXX_unrecognized []byte `json:"-"` } func (m *UninterpretedOption) Reset() { *m = UninterpretedOption{} } func (m *UninterpretedOption) String() string { return proto.CompactTextString(m) } func (*UninterpretedOption) ProtoMessage() {} func (*UninterpretedOption) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{16} } func (m *UninterpretedOption) GetName() []*UninterpretedOption_NamePart { if m != nil { return m.Name } return nil } func (m *UninterpretedOption) GetIdentifierValue() string { if m != nil && m.IdentifierValue != nil { return *m.IdentifierValue } return "" } func (m *UninterpretedOption) GetPositiveIntValue() uint64 { if m != nil && m.PositiveIntValue != nil { return *m.PositiveIntValue } return 0 } func (m *UninterpretedOption) GetNegativeIntValue() int64 { if m != nil && m.NegativeIntValue != nil { return *m.NegativeIntValue } return 0 } func (m *UninterpretedOption) GetDoubleValue() float64 { if m != nil && m.DoubleValue != nil { return *m.DoubleValue } return 0 } func (m *UninterpretedOption) GetStringValue() []byte { if m != nil { return m.StringValue } return nil } func (m *UninterpretedOption) GetAggregateValue() string { if m != nil && m.AggregateValue != nil { return *m.AggregateValue } return "" } // The name of the uninterpreted option. Each string represents a segment in // a dot-separated name. is_extension is true iff a segment represents an // extension (denoted with parentheses in options specs in .proto files). // E.g.,{ ["foo", false], ["bar.baz", true], ["qux", false] } represents // "foo.(bar.baz).qux". type UninterpretedOption_NamePart struct { NamePart *string `protobuf:"bytes,1,req,name=name_part,json=namePart" json:"name_part,omitempty"` IsExtension *bool `protobuf:"varint,2,req,name=is_extension,json=isExtension" json:"is_extension,omitempty"` XXX_unrecognized []byte `json:"-"` } func (m *UninterpretedOption_NamePart) Reset() { *m = UninterpretedOption_NamePart{} } func (m *UninterpretedOption_NamePart) String() string { return proto.CompactTextString(m) } func (*UninterpretedOption_NamePart) ProtoMessage() {} func (*UninterpretedOption_NamePart) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{16, 0} } func (m *UninterpretedOption_NamePart) GetNamePart() string { if m != nil && m.NamePart != nil { return *m.NamePart } return "" } func (m *UninterpretedOption_NamePart) GetIsExtension() bool { if m != nil && m.IsExtension != nil { return *m.IsExtension } return false } // Encapsulates information about the original source file from which a // FileDescriptorProto was generated. type SourceCodeInfo struct { // A Location identifies a piece of source code in a .proto file which // corresponds to a particular definition. This information is intended // to be useful to IDEs, code indexers, documentation generators, and similar // tools. // // For example, say we have a file like: // message Foo { // optional string foo = 1; // } // Let's look at just the field definition: // optional string foo = 1; // ^ ^^ ^^ ^ ^^^ // a bc de f ghi // We have the following locations: // span path represents // [a,i) [ 4, 0, 2, 0 ] The whole field definition. // [a,b) [ 4, 0, 2, 0, 4 ] The label (optional). // [c,d) [ 4, 0, 2, 0, 5 ] The type (string). // [e,f) [ 4, 0, 2, 0, 1 ] The name (foo). // [g,h) [ 4, 0, 2, 0, 3 ] The number (1). // // Notes: // - A location may refer to a repeated field itself (i.e. not to any // particular index within it). This is used whenever a set of elements are // logically enclosed in a single code segment. For example, an entire // extend block (possibly containing multiple extension definitions) will // have an outer location whose path refers to the "extensions" repeated // field without an index. // - Multiple locations may have the same path. This happens when a single // logical declaration is spread out across multiple places. The most // obvious example is the "extend" block again -- there may be multiple // extend blocks in the same scope, each of which will have the same path. // - A location's span is not always a subset of its parent's span. For // example, the "extendee" of an extension declaration appears at the // beginning of the "extend" block and is shared by all extensions within // the block. // - Just because a location's span is a subset of some other location's span // does not mean that it is a descendent. For example, a "group" defines // both a type and a field in a single declaration. Thus, the locations // corresponding to the type and field and their components will overlap. // - Code which tries to interpret locations should probably be designed to // ignore those that it doesn't understand, as more types of locations could // be recorded in the future. Location []*SourceCodeInfo_Location `protobuf:"bytes,1,rep,name=location" json:"location,omitempty"` XXX_unrecognized []byte `json:"-"` } func (m *SourceCodeInfo) Reset() { *m = SourceCodeInfo{} } func (m *SourceCodeInfo) String() string { return proto.CompactTextString(m) } func (*SourceCodeInfo) ProtoMessage() {} func (*SourceCodeInfo) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{17} } func (m *SourceCodeInfo) GetLocation() []*SourceCodeInfo_Location { if m != nil { return m.Location } return nil } type SourceCodeInfo_Location struct { // Identifies which part of the FileDescriptorProto was defined at this // location. // // Each element is a field number or an index. They form a path from // the root FileDescriptorProto to the place where the definition. For // example, this path: // [ 4, 3, 2, 7, 1 ] // refers to: // file.message_type(3) // 4, 3 // .field(7) // 2, 7 // .name() // 1 // This is because FileDescriptorProto.message_type has field number 4: // repeated DescriptorProto message_type = 4; // and DescriptorProto.field has field number 2: // repeated FieldDescriptorProto field = 2; // and FieldDescriptorProto.name has field number 1: // optional string name = 1; // // Thus, the above path gives the location of a field name. If we removed // the last element: // [ 4, 3, 2, 7 ] // this path refers to the whole field declaration (from the beginning // of the label to the terminating semicolon). Path []int32 `protobuf:"varint,1,rep,packed,name=path" json:"path,omitempty"` // Always has exactly three or four elements: start line, start column, // end line (optional, otherwise assumed same as start line), end column. // These are packed into a single field for efficiency. Note that line // and column numbers are zero-based -- typically you will want to add // 1 to each before displaying to a user. Span []int32 `protobuf:"varint,2,rep,packed,name=span" json:"span,omitempty"` // If this SourceCodeInfo represents a complete declaration, these are any // comments appearing before and after the declaration which appear to be // attached to the declaration. // // A series of line comments appearing on consecutive lines, with no other // tokens appearing on those lines, will be treated as a single comment. // // leading_detached_comments will keep paragraphs of comments that appear // before (but not connected to) the current element. Each paragraph, // separated by empty lines, will be one comment element in the repeated // field. // // Only the comment content is provided; comment markers (e.g. //) are // stripped out. For block comments, leading whitespace and an asterisk // will be stripped from the beginning of each line other than the first. // Newlines are included in the output. // // Examples: // // optional int32 foo = 1; // Comment attached to foo. // // Comment attached to bar. // optional int32 bar = 2; // // optional string baz = 3; // // Comment attached to baz. // // Another line attached to baz. // // // Comment attached to qux. // // // // Another line attached to qux. // optional double qux = 4; // // // Detached comment for corge. This is not leading or trailing comments // // to qux or corge because there are blank lines separating it from // // both. // // // Detached comment for corge paragraph 2. // // optional string corge = 5; // /* Block comment attached // * to corge. Leading asterisks // * will be removed. */ // /* Block comment attached to // * grault. */ // optional int32 grault = 6; // // // ignored detached comments. LeadingComments *string `protobuf:"bytes,3,opt,name=leading_comments,json=leadingComments" json:"leading_comments,omitempty"` TrailingComments *string `protobuf:"bytes,4,opt,name=trailing_comments,json=trailingComments" json:"trailing_comments,omitempty"` LeadingDetachedComments []string `protobuf:"bytes,6,rep,name=leading_detached_comments,json=leadingDetachedComments" json:"leading_detached_comments,omitempty"` XXX_unrecognized []byte `json:"-"` } func (m *SourceCodeInfo_Location) Reset() { *m = SourceCodeInfo_Location{} } func (m *SourceCodeInfo_Location) String() string { return proto.CompactTextString(m) } func (*SourceCodeInfo_Location) ProtoMessage() {} func (*SourceCodeInfo_Location) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{17, 0} } func (m *SourceCodeInfo_Location) GetPath() []int32 { if m != nil { return m.Path } return nil } func (m *SourceCodeInfo_Location) GetSpan() []int32 { if m != nil { return m.Span } return nil } func (m *SourceCodeInfo_Location) GetLeadingComments() string { if m != nil && m.LeadingComments != nil { return *m.LeadingComments } return "" } func (m *SourceCodeInfo_Location) GetTrailingComments() string { if m != nil && m.TrailingComments != nil { return *m.TrailingComments } return "" } func (m *SourceCodeInfo_Location) GetLeadingDetachedComments() []string { if m != nil { return m.LeadingDetachedComments } return nil } func init() { proto.RegisterType((*FileDescriptorSet)(nil), "google.protobuf.FileDescriptorSet") proto.RegisterType((*FileDescriptorProto)(nil), "google.protobuf.FileDescriptorProto") proto.RegisterType((*DescriptorProto)(nil), "google.protobuf.DescriptorProto") proto.RegisterType((*DescriptorProto_ExtensionRange)(nil), "google.protobuf.DescriptorProto.ExtensionRange") proto.RegisterType((*DescriptorProto_ReservedRange)(nil), "google.protobuf.DescriptorProto.ReservedRange") proto.RegisterType((*FieldDescriptorProto)(nil), "google.protobuf.FieldDescriptorProto") proto.RegisterType((*OneofDescriptorProto)(nil), "google.protobuf.OneofDescriptorProto") proto.RegisterType((*EnumDescriptorProto)(nil), "google.protobuf.EnumDescriptorProto") proto.RegisterType((*EnumValueDescriptorProto)(nil), "google.protobuf.EnumValueDescriptorProto") proto.RegisterType((*ServiceDescriptorProto)(nil), "google.protobuf.ServiceDescriptorProto") proto.RegisterType((*MethodDescriptorProto)(nil), "google.protobuf.MethodDescriptorProto") proto.RegisterType((*FileOptions)(nil), "google.protobuf.FileOptions") proto.RegisterType((*MessageOptions)(nil), "google.protobuf.MessageOptions") proto.RegisterType((*FieldOptions)(nil), "google.protobuf.FieldOptions") proto.RegisterType((*EnumOptions)(nil), "google.protobuf.EnumOptions") proto.RegisterType((*EnumValueOptions)(nil), "google.protobuf.EnumValueOptions") proto.RegisterType((*ServiceOptions)(nil), "google.protobuf.ServiceOptions") proto.RegisterType((*MethodOptions)(nil), "google.protobuf.MethodOptions") proto.RegisterType((*UninterpretedOption)(nil), "google.protobuf.UninterpretedOption") proto.RegisterType((*UninterpretedOption_NamePart)(nil), "google.protobuf.UninterpretedOption.NamePart") proto.RegisterType((*SourceCodeInfo)(nil), "google.protobuf.SourceCodeInfo") proto.RegisterType((*SourceCodeInfo_Location)(nil), "google.protobuf.SourceCodeInfo.Location") proto.RegisterEnum("google.protobuf.FieldDescriptorProto_Type", FieldDescriptorProto_Type_name, FieldDescriptorProto_Type_value) proto.RegisterEnum("google.protobuf.FieldDescriptorProto_Label", FieldDescriptorProto_Label_name, FieldDescriptorProto_Label_value) proto.RegisterEnum("google.protobuf.FileOptions_OptimizeMode", FileOptions_OptimizeMode_name, FileOptions_OptimizeMode_value) proto.RegisterEnum("google.protobuf.FieldOptions_CType", FieldOptions_CType_name, FieldOptions_CType_value) proto.RegisterEnum("google.protobuf.FieldOptions_JSType", FieldOptions_JSType_name, FieldOptions_JSType_value) } var fileDescriptor0 = []byte{ // 2199 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xcc, 0x58, 0x4f, 0x73, 0xdb, 0xd6, 0x11, 0x2f, 0xff, 0x8a, 0x5c, 0x52, 0x24, 0xf4, 0xa4, 0xd8, 0xb4, 0x62, 0x47, 0x36, 0x63, 0xc7, 0x8e, 0xd3, 0x52, 0x19, 0xb7, 0x49, 0x5c, 0xa5, 0x93, 0x0e, 0x45, 0xc2, 0x0a, 0x3d, 0x94, 0xc8, 0x82, 0x64, 0xeb, 0xe4, 0x82, 0x81, 0xc0, 0x47, 0x0a, 0x36, 0x08, 0xb0, 0x00, 0x68, 0x5b, 0x39, 0x75, 0xa6, 0xa7, 0x7e, 0x83, 0x4e, 0xdb, 0xe9, 0x21, 0x97, 0xcc, 0xf4, 0x03, 0xf4, 0xd0, 0x7b, 0xaf, 0x3d, 0xf4, 0xdc, 0x63, 0x67, 0xda, 0x6f, 0xd0, 0x6b, 0xf7, 0xbd, 0x07, 0x80, 0x00, 0x09, 0xc5, 0x6a, 0x66, 0x52, 0x47, 0x17, 0xf1, 0xed, 0xfe, 0x76, 0xb1, 0x6f, 0xdf, 0xef, 0xed, 0x2e, 0x00, 0x37, 0xa7, 0xb6, 0x3d, 0x35, 0xe9, 0xfe, 0xdc, 0xb1, 0x3d, 0xfb, 0x74, 0x31, 0xd9, 0x1f, 0x53, 0x57, 0x77, 0x8c, 0xb9, 0x67, 0x3b, 0x0d, 0x2e, 0x23, 0x55, 0x81, 0x68, 0x04, 0x88, 0xfa, 0x31, 0x6c, 0x3d, 0x32, 0x4c, 0xda, 0x0e, 0x81, 0x03, 0xea, 0x91, 0x87, 0x90, 0x9d, 0xa0, 0xb0, 0x96, 0xba, 0x99, 0xb9, 0x57, 0x7a, 0x70, 0xbb, 0xb1, 0x62, 0xd4, 0x88, 0x5b, 0xf4, 0x99, 0x58, 0xe1, 0x16, 0xf5, 0x7f, 0x66, 0x61, 0x3b, 0x41, 0x4b, 0x08, 0x64, 0x2d, 0x6d, 0xc6, 0x3c, 0xa6, 0xee, 0x15, 0x15, 0xfe, 0x9b, 0xd4, 0x60, 0x63, 0xae, 0xe9, 0xcf, 0xb4, 0x29, 0xad, 0xa5, 0xb9, 0x38, 0x58, 0x92, 0xb7, 0x00, 0xc6, 0x74, 0x4e, 0xad, 0x31, 0xb5, 0xf4, 0xf3, 0x5a, 0x06, 0xa3, 0x28, 0x2a, 0x11, 0x09, 0x79, 0x0f, 0xb6, 0xe6, 0x8b, 0x53, 0xd3, 0xd0, 0xd5, 0x08, 0x0c, 0x10, 0x96, 0x53, 0x24, 0xa1, 0x68, 0x2f, 0xc1, 0x77, 0xa1, 0xfa, 0x82, 0x6a, 0xcf, 0xa2, 0xd0, 0x12, 0x87, 0x56, 0x98, 0x38, 0x02, 0x6c, 0x41, 0x79, 0x46, 0x5d, 0x17, 0x03, 0x50, 0xbd, 0xf3, 0x39, 0xad, 0x65, 0xf9, 0xee, 0x6f, 0xae, 0xed, 0x7e, 0x75, 0xe7, 0x25, 0xdf, 0x6a, 0x88, 0x46, 0xa4, 0x09, 0x45, 0x6a, 0x2d, 0x66, 0xc2, 0x43, 0xee, 0x82, 0xfc, 0xc9, 0x88, 0x58, 0xf5, 0x52, 0x60, 0x66, 0xbe, 0x8b, 0x0d, 0x97, 0x3a, 0xcf, 0x0d, 0x9d, 0xd6, 0xf2, 0xdc, 0xc1, 0xdd, 0x35, 0x07, 0x03, 0xa1, 0x5f, 0xf5, 0x11, 0xd8, 0xe1, 0x56, 0x8a, 0xf4, 0xa5, 0x47, 0x2d, 0xd7, 0xb0, 0xad, 0xda, 0x06, 0x77, 0x72, 0x27, 0xe1, 0x14, 0xa9, 0x39, 0x5e, 0x75, 0xb1, 0xb4, 0x23, 0x1f, 0xc2, 0x86, 0x3d, 0xf7, 0xf0, 0x97, 0x5b, 0x2b, 0xe0, 0xf9, 0x94, 0x1e, 0x5c, 0x4f, 0x24, 0x42, 0x4f, 0x60, 0x94, 0x00, 0x4c, 0x3a, 0x20, 0xb9, 0xf6, 0xc2, 0xd1, 0xa9, 0xaa, 0xdb, 0x63, 0xaa, 0x1a, 0xd6, 0xc4, 0xae, 0x15, 0xb9, 0x83, 0xbd, 0xf5, 0x8d, 0x70, 0x60, 0x0b, 0x71, 0x1d, 0x84, 0x29, 0x15, 0x37, 0xb6, 0x26, 0x57, 0x20, 0xef, 0x9e, 0x5b, 0x9e, 0xf6, 0xb2, 0x56, 0xe6, 0x0c, 0xf1, 0x57, 0xf5, 0xff, 0xe4, 0xa0, 0x7a, 0x19, 0x8a, 0x7d, 0x0c, 0xb9, 0x09, 0xdb, 0x25, 0x12, 0xec, 0x7f, 0xc8, 0x81, 0xb0, 0x89, 0x27, 0x31, 0xff, 0x0d, 0x93, 0xd8, 0x84, 0x92, 0x45, 0x5d, 0x8f, 0x8e, 0x05, 0x23, 0x32, 0x97, 0xe4, 0x14, 0x08, 0xa3, 0x75, 0x4a, 0x65, 0xbf, 0x11, 0xa5, 0x9e, 0x40, 0x35, 0x0c, 0x49, 0x75, 0x34, 0x6b, 0x1a, 0x70, 0x73, 0xff, 0x55, 0x91, 0x34, 0xe4, 0xc0, 0x4e, 0x61, 0x66, 0x4a, 0x85, 0xc6, 0xd6, 0xa4, 0x0d, 0x60, 0x5b, 0xd4, 0x9e, 0xe0, 0xf5, 0xd2, 0x4d, 0xe4, 0x49, 0x72, 0x96, 0x7a, 0x0c, 0xb2, 0x96, 0x25, 0x5b, 0x48, 0x75, 0x93, 0xfc, 0x78, 0x49, 0xb5, 0x8d, 0x0b, 0x98, 0x72, 0x2c, 0x2e, 0xd9, 0x1a, 0xdb, 0x46, 0x50, 0x71, 0x28, 0xe3, 0x3d, 0xa6, 0x58, 0xec, 0xac, 0xc8, 0x83, 0x68, 0xbc, 0x72, 0x67, 0x8a, 0x6f, 0x26, 0x36, 0xb6, 0xe9, 0x44, 0x97, 0xe4, 0x6d, 0x08, 0x05, 0x2a, 0xa7, 0x15, 0xf0, 0x2a, 0x54, 0x0e, 0x84, 0x27, 0x28, 0xdb, 0x7d, 0x08, 0x95, 0x78, 0x7a, 0xc8, 0x0e, 0xe4, 0x5c, 0x4f, 0x73, 0x3c, 0xce, 0xc2, 0x9c, 0x22, 0x16, 0x44, 0x82, 0x0c, 0x16, 0x19, 0x5e, 0xe5, 0x72, 0x0a, 0xfb, 0xb9, 0xfb, 0x11, 0x6c, 0xc6, 0x1e, 0x7f, 0x59, 0xc3, 0xfa, 0x6f, 0xf3, 0xb0, 0x93, 0xc4, 0xb9, 0x44, 0xfa, 0xe3, 0xf5, 0x41, 0x06, 0x9c, 0x52, 0x07, 0x79, 0xc7, 0x3c, 0xf8, 0x2b, 0x64, 0x54, 0xce, 0xd4, 0x4e, 0xa9, 0x89, 0x6c, 0x4a, 0xdd, 0xab, 0x3c, 0x78, 0xef, 0x52, 0xac, 0x6e, 0x74, 0x99, 0x89, 0x22, 0x2c, 0xc9, 0x27, 0x90, 0xf5, 0x4b, 0x1c, 0xf3, 0x70, 0xff, 0x72, 0x1e, 0x18, 0x17, 0x15, 0x6e, 0x47, 0xde, 0x84, 0x22, 0xfb, 0x2f, 0x72, 0x9b, 0xe7, 0x31, 0x17, 0x98, 0x80, 0xe5, 0x95, 0xec, 0x42, 0x81, 0xd3, 0x6c, 0x4c, 0x83, 0xd6, 0x10, 0xae, 0xd9, 0xc1, 0x8c, 0xe9, 0x44, 0x5b, 0x98, 0x9e, 0xfa, 0x5c, 0x33, 0x17, 0x94, 0x13, 0x06, 0x0f, 0xc6, 0x17, 0xfe, 0x9c, 0xc9, 0xc8, 0x1e, 0x94, 0x04, 0x2b, 0x0d, 0xb4, 0x79, 0xc9, 0xab, 0x4f, 0x4e, 0x11, 0x44, 0xed, 0x30, 0x09, 0x7b, 0xfc, 0x53, 0x17, 0xef, 0x82, 0x7f, 0xb4, 0xfc, 0x11, 0x4c, 0xc0, 0x1f, 0xff, 0xd1, 0x6a, 0xe1, 0xbb, 0x91, 0xbc, 0xbd, 0x55, 0x2e, 0xd6, 0xff, 0x9c, 0x86, 0x2c, 0xbf, 0x6f, 0x55, 0x28, 0x0d, 0x3f, 0xeb, 0xcb, 0x6a, 0xbb, 0x37, 0x3a, 0xec, 0xca, 0x52, 0x8a, 0x54, 0x00, 0xb8, 0xe0, 0x51, 0xb7, 0xd7, 0x1c, 0x4a, 0xe9, 0x70, 0xdd, 0x39, 0x19, 0x7e, 0xf8, 0x23, 0x29, 0x13, 0x1a, 0x8c, 0x84, 0x20, 0x1b, 0x05, 0xfc, 0xf0, 0x81, 0x94, 0x43, 0x26, 0x94, 0x85, 0x83, 0xce, 0x13, 0xb9, 0x8d, 0x88, 0x7c, 0x5c, 0x82, 0x98, 0x0d, 0xb2, 0x09, 0x45, 0x2e, 0x39, 0xec, 0xf5, 0xba, 0x52, 0x21, 0xf4, 0x39, 0x18, 0x2a, 0x9d, 0x93, 0x23, 0xa9, 0x18, 0xfa, 0x3c, 0x52, 0x7a, 0xa3, 0xbe, 0x04, 0xa1, 0x87, 0x63, 0x79, 0x30, 0x68, 0x1e, 0xc9, 0x52, 0x29, 0x44, 0x1c, 0x7e, 0x36, 0x94, 0x07, 0x52, 0x39, 0x16, 0x16, 0x3e, 0x62, 0x33, 0x7c, 0x84, 0x7c, 0x32, 0x3a, 0x96, 0x2a, 0x64, 0x0b, 0x36, 0xc5, 0x23, 0x82, 0x20, 0xaa, 0x2b, 0x22, 0x8c, 0x54, 0x5a, 0x06, 0x22, 0xbc, 0x6c, 0xc5, 0x04, 0x88, 0x20, 0xf5, 0x16, 0xe4, 0x38, 0xbb, 0x90, 0xc5, 0x95, 0x6e, 0xf3, 0x50, 0xee, 0xaa, 0xbd, 0xfe, 0xb0, 0xd3, 0x3b, 0x69, 0x76, 0x31, 0x77, 0xa1, 0x4c, 0x91, 0x7f, 0x36, 0xea, 0x28, 0x72, 0x1b, 0xf3, 0x17, 0x91, 0xf5, 0xe5, 0xe6, 0x10, 0x65, 0x99, 0xfa, 0x7d, 0xd8, 0x49, 0xaa, 0x33, 0x49, 0x37, 0xa3, 0xfe, 0x65, 0x0a, 0xb6, 0x13, 0x4a, 0x66, 0xe2, 0x2d, 0xfa, 0x29, 0xe4, 0x04, 0xd3, 0x44, 0x13, 0x79, 0x37, 0xb1, 0xf6, 0x72, 0xde, 0xad, 0x35, 0x12, 0x6e, 0x17, 0x6d, 0xa4, 0x99, 0x0b, 0x1a, 0x29, 0x73, 0xb1, 0x46, 0xa7, 0x5f, 0xa7, 0xa0, 0x76, 0x91, 0xef, 0x57, 0xdc, 0xf7, 0x74, 0xec, 0xbe, 0x7f, 0xbc, 0x1a, 0xc0, 0xad, 0x8b, 0xf7, 0xb0, 0x16, 0xc5, 0x57, 0x29, 0xb8, 0x92, 0x3c, 0x6f, 0x24, 0xc6, 0xf0, 0x09, 0xe4, 0x67, 0xd4, 0x3b, 0xb3, 0x83, 0x9e, 0xfb, 0x4e, 0x42, 0x25, 0x67, 0xea, 0xd5, 0x5c, 0xf9, 0x56, 0xd1, 0x56, 0x90, 0xb9, 0x68, 0x68, 0x10, 0xd1, 0xac, 0x45, 0xfa, 0x9b, 0x34, 0xbc, 0x91, 0xe8, 0x3c, 0x31, 0xd0, 0x1b, 0x00, 0x86, 0x35, 0x5f, 0x78, 0xa2, 0xaf, 0x8a, 0x32, 0x53, 0xe4, 0x12, 0x7e, 0x85, 0x59, 0x09, 0x59, 0x78, 0xa1, 0x3e, 0xc3, 0xf5, 0x20, 0x44, 0x1c, 0xf0, 0x70, 0x19, 0x68, 0x96, 0x07, 0xfa, 0xd6, 0x05, 0x3b, 0x5d, 0x6b, 0x59, 0xef, 0x83, 0xa4, 0x9b, 0x06, 0xb5, 0x3c, 0xd5, 0xf5, 0x1c, 0xaa, 0xcd, 0x0c, 0x6b, 0xca, 0xeb, 0x68, 0xe1, 0x20, 0x37, 0xd1, 0x4c, 0x97, 0x2a, 0x55, 0xa1, 0x1e, 0x04, 0x5a, 0x66, 0xc1, 0x9b, 0x85, 0x13, 0xb1, 0xc8, 0xc7, 0x2c, 0x84, 0x3a, 0xb4, 0xa8, 0xff, 0x7d, 0x03, 0x4a, 0x91, 0xe9, 0x8c, 0xdc, 0x82, 0xf2, 0x53, 0xed, 0xb9, 0xa6, 0x06, 0x13, 0xb7, 0xc8, 0x44, 0x89, 0xc9, 0xfa, 0xfe, 0xd4, 0xfd, 0x3e, 0xec, 0x70, 0x08, 0xee, 0x11, 0x1f, 0xa4, 0x9b, 0x9a, 0xeb, 0xf2, 0xa4, 0x15, 0x38, 0x94, 0x30, 0x5d, 0x8f, 0xa9, 0x5a, 0x81, 0x86, 0x7c, 0x00, 0xdb, 0xdc, 0x62, 0x86, 0x85, 0xd7, 0x98, 0x9b, 0x54, 0x65, 0xef, 0x00, 0x2e, 0xaf, 0xa7, 0x61, 0x64, 0x5b, 0x0c, 0x71, 0xec, 0x03, 0x58, 0x44, 0x2e, 0x39, 0x82, 0x1b, 0xdc, 0x6c, 0x4a, 0x2d, 0xea, 0x68, 0x1e, 0x55, 0xe9, 0x2f, 0x17, 0x88, 0x55, 0x35, 0x6b, 0xac, 0x9e, 0x69, 0xee, 0x59, 0x6d, 0x27, 0xea, 0xe0, 0x1a, 0xc3, 0x1e, 0xf9, 0x50, 0x99, 0x23, 0x9b, 0xd6, 0xf8, 0x53, 0xc4, 0x91, 0x03, 0xb8, 0xc2, 0x1d, 0x61, 0x52, 0x70, 0xcf, 0xaa, 0x7e, 0x46, 0xf5, 0x67, 0xea, 0xc2, 0x9b, 0x3c, 0xac, 0xbd, 0x19, 0xf5, 0xc0, 0x83, 0x1c, 0x70, 0x4c, 0x8b, 0x41, 0x46, 0x88, 0x20, 0x03, 0x28, 0xb3, 0xf3, 0x98, 0x19, 0x5f, 0x60, 0xd8, 0xb6, 0xc3, 0x7b, 0x44, 0x25, 0xe1, 0x72, 0x47, 0x92, 0xd8, 0xe8, 0xf9, 0x06, 0xc7, 0x38, 0x9f, 0x1e, 0xe4, 0x06, 0x7d, 0x59, 0x6e, 0x2b, 0xa5, 0xc0, 0xcb, 0x23, 0xdb, 0x61, 0x9c, 0x9a, 0xda, 0x61, 0x8e, 0x4b, 0x82, 0x53, 0x53, 0x3b, 0xc8, 0x30, 0xe6, 0x4b, 0xd7, 0xc5, 0xb6, 0xf1, 0xdd, 0xc5, 0x1f, 0xd6, 0xdd, 0x9a, 0x14, 0xcb, 0x97, 0xae, 0x1f, 0x09, 0x80, 0x4f, 0x73, 0x17, 0xaf, 0xc4, 0x1b, 0xcb, 0x7c, 0x45, 0x0d, 0xb7, 0xd6, 0x76, 0xb9, 0x6a, 0x8a, 0x4f, 0x9c, 0x9f, 0xaf, 0x1b, 0x92, 0xd8, 0x13, 0xe7, 0xe7, 0xab, 0x66, 0x77, 0xf8, 0x0b, 0x98, 0x43, 0x75, 0x4c, 0xf9, 0xb8, 0x76, 0x35, 0x8a, 0x8e, 0x28, 0xc8, 0x3e, 0x12, 0x59, 0x57, 0xa9, 0xa5, 0x9d, 0xe2, 0xd9, 0x6b, 0x0e, 0xfe, 0x70, 0x6b, 0x7b, 0x51, 0x70, 0x45, 0xd7, 0x65, 0xae, 0x6d, 0x72, 0x25, 0xb9, 0x0f, 0x5b, 0xf6, 0xe9, 0x53, 0x5d, 0x90, 0x4b, 0x45, 0x3f, 0x13, 0xe3, 0x65, 0xed, 0x36, 0x4f, 0x53, 0x95, 0x29, 0x38, 0xb5, 0xfa, 0x5c, 0x4c, 0xde, 0x45, 0xe7, 0xee, 0x99, 0xe6, 0xcc, 0x79, 0x93, 0x76, 0x31, 0xa9, 0xb4, 0x76, 0x47, 0x40, 0x85, 0xfc, 0x24, 0x10, 0x13, 0x19, 0xf6, 0xd8, 0xe6, 0x2d, 0xcd, 0xb2, 0xd5, 0x85, 0x4b, 0xd5, 0x65, 0x88, 0xe1, 0x59, 0xbc, 0xc3, 0xc2, 0x52, 0xae, 0x07, 0xb0, 0x91, 0x8b, 0xc5, 0x2c, 0x00, 0x05, 0xc7, 0xf3, 0x04, 0x76, 0x16, 0x96, 0x61, 0x21, 0xc5, 0x51, 0xc3, 0x8c, 0xc5, 0x85, 0xad, 0xfd, 0x6b, 0xe3, 0x82, 0xa1, 0x7b, 0x14, 0x45, 0x0b, 0x92, 0x28, 0xdb, 0x8b, 0x75, 0x61, 0xfd, 0x00, 0xca, 0x51, 0xee, 0x90, 0x22, 0x08, 0xf6, 0x60, 0x77, 0xc3, 0x8e, 0xda, 0xea, 0xb5, 0x59, 0x2f, 0xfc, 0x5c, 0xc6, 0xc6, 0x86, 0x3d, 0xb9, 0xdb, 0x19, 0xca, 0xaa, 0x32, 0x3a, 0x19, 0x76, 0x8e, 0x65, 0x29, 0x73, 0xbf, 0x58, 0xf8, 0xf7, 0x86, 0xf4, 0x2b, 0xfc, 0x4b, 0xd7, 0xff, 0x9a, 0x86, 0x4a, 0x7c, 0x0e, 0x26, 0x3f, 0x81, 0xab, 0xc1, 0x4b, 0xab, 0x4b, 0x3d, 0xf5, 0x85, 0xe1, 0x70, 0x3a, 0xcf, 0x34, 0x31, 0x49, 0x86, 0x27, 0xb1, 0xe3, 0xa3, 0xf0, 0xf5, 0xfe, 0x17, 0x88, 0x79, 0xc4, 0x21, 0xa4, 0x0b, 0x7b, 0x98, 0x32, 0x9c, 0x35, 0xad, 0xb1, 0xe6, 0x8c, 0xd5, 0xe5, 0xe7, 0x02, 0x55, 0xd3, 0x91, 0x07, 0xae, 0x2d, 0x3a, 0x49, 0xe8, 0xe5, 0xba, 0x65, 0x0f, 0x7c, 0xf0, 0xb2, 0xc4, 0x36, 0x7d, 0xe8, 0x0a, 0x6b, 0x32, 0x17, 0xb1, 0x06, 0x67, 0xaf, 0x99, 0x36, 0x47, 0xda, 0x78, 0xce, 0x39, 0x9f, 0xde, 0x0a, 0x4a, 0x01, 0x05, 0x32, 0x5b, 0x7f, 0x7b, 0x67, 0x10, 0xcd, 0xe3, 0x3f, 0x32, 0x50, 0x8e, 0x4e, 0x70, 0x6c, 0x20, 0xd6, 0x79, 0x99, 0x4f, 0xf1, 0x2a, 0xf0, 0xf6, 0xd7, 0xce, 0x7b, 0x8d, 0x16, 0xab, 0xff, 0x07, 0x79, 0x31, 0x57, 0x29, 0xc2, 0x92, 0xf5, 0x5e, 0xc6, 0x35, 0x2a, 0xa6, 0xf5, 0x82, 0xe2, 0xaf, 0xb0, 0xd8, 0xe5, 0x9f, 0xba, 0xdc, 0x77, 0x9e, 0xfb, 0xbe, 0xfd, 0xf5, 0xbe, 0x1f, 0x0f, 0xb8, 0xf3, 0xe2, 0xe3, 0x81, 0x7a, 0xd2, 0x53, 0x8e, 0x9b, 0x5d, 0xc5, 0x37, 0x27, 0xd7, 0x20, 0x6b, 0x6a, 0x5f, 0x9c, 0xc7, 0x3b, 0x05, 0x17, 0x5d, 0x36, 0xf1, 0xe8, 0x81, 0x7d, 0xf2, 0x88, 0xd7, 0x67, 0x2e, 0xfa, 0x16, 0xa9, 0xbf, 0x0f, 0x39, 0x9e, 0x2f, 0x02, 0xe0, 0x67, 0x4c, 0xfa, 0x1e, 0x29, 0x40, 0xb6, 0xd5, 0x53, 0x18, 0xfd, 0x91, 0xef, 0x42, 0xaa, 0xf6, 0x3b, 0x72, 0x0b, 0x6f, 0x40, 0xfd, 0x03, 0xc8, 0x8b, 0x24, 0xb0, 0xab, 0x11, 0xa6, 0x01, 0x8d, 0xc4, 0xd2, 0xf7, 0x91, 0x0a, 0xb4, 0xa3, 0xe3, 0x43, 0x59, 0x91, 0xd2, 0xd1, 0xe3, 0xfd, 0x4b, 0x0a, 0x4a, 0x91, 0x81, 0x8a, 0xb5, 0x72, 0xcd, 0x34, 0xed, 0x17, 0xaa, 0x66, 0x1a, 0x58, 0xa1, 0xc4, 0xf9, 0x00, 0x17, 0x35, 0x99, 0xe4, 0xb2, 0xf9, 0xfb, 0xbf, 0x70, 0xf3, 0x8f, 0x29, 0x90, 0x56, 0x87, 0xb1, 0x95, 0x00, 0x53, 0xaf, 0x35, 0xc0, 0x3f, 0xa4, 0xa0, 0x12, 0x9f, 0xc0, 0x56, 0xc2, 0xbb, 0xf5, 0x5a, 0xc3, 0xfb, 0x7d, 0x0a, 0x36, 0x63, 0x73, 0xd7, 0x77, 0x2a, 0xba, 0xdf, 0x65, 0x60, 0x3b, 0xc1, 0x0e, 0x0b, 0x90, 0x18, 0x50, 0xc5, 0xcc, 0xfc, 0x83, 0xcb, 0x3c, 0xab, 0xc1, 0xfa, 0x5f, 0x5f, 0x73, 0x3c, 0x7f, 0x9e, 0xc5, 0x7e, 0x69, 0x8c, 0xb1, 0xa8, 0x1a, 0x13, 0x03, 0xc7, 0x37, 0xf1, 0xc6, 0x22, 0xa6, 0xd6, 0xea, 0x52, 0x2e, 0x5e, 0x8f, 0xbf, 0x0f, 0x64, 0x6e, 0xbb, 0x86, 0x67, 0x3c, 0x67, 0x9f, 0xe7, 0x82, 0x17, 0x69, 0x36, 0xc5, 0x66, 0x15, 0x29, 0xd0, 0x74, 0x2c, 0x2f, 0x44, 0x5b, 0x74, 0xaa, 0xad, 0xa0, 0x59, 0x19, 0xca, 0x28, 0x52, 0xa0, 0x09, 0xd1, 0x38, 0x68, 0x8e, 0xed, 0x05, 0x1b, 0x08, 0x04, 0x8e, 0x55, 0xbd, 0x94, 0x52, 0x12, 0xb2, 0x10, 0xe2, 0x4f, 0x6c, 0xcb, 0x37, 0xf8, 0xb2, 0x52, 0x12, 0x32, 0x01, 0xb9, 0x0b, 0x55, 0x6d, 0x3a, 0x75, 0x98, 0xf3, 0xc0, 0x91, 0x18, 0x43, 0x2b, 0xa1, 0x98, 0x03, 0x77, 0x1f, 0x43, 0x21, 0xc8, 0x03, 0x6b, 0x2c, 0x2c, 0x13, 0xd8, 0xf3, 0xf9, 0x77, 0x94, 0x34, 0x7b, 0xa9, 0xb7, 0x02, 0x25, 0x3e, 0xd4, 0x70, 0xd5, 0xe5, 0x07, 0xbd, 0x34, 0xea, 0x0b, 0x4a, 0xc9, 0x70, 0xc3, 0x2f, 0x38, 0xf5, 0xaf, 0xb0, 0xbd, 0xc6, 0x3f, 0x48, 0x92, 0x36, 0x14, 0x4c, 0x1b, 0xf9, 0xc1, 0x2c, 0xc4, 0xd7, 0xf0, 0x7b, 0xaf, 0xf8, 0x86, 0xd9, 0xe8, 0xfa, 0x78, 0x25, 0xb4, 0xdc, 0xfd, 0x5b, 0x0a, 0x0a, 0x81, 0x18, 0x1b, 0x45, 0x76, 0xae, 0x79, 0x67, 0xdc, 0x5d, 0xee, 0x30, 0x2d, 0xa5, 0x14, 0xbe, 0x66, 0x72, 0x9c, 0x66, 0x2c, 0x4e, 0x01, 0x5f, 0xce, 0xd6, 0xec, 0x5c, 0x4d, 0xaa, 0x8d, 0xf9, 0x80, 0x6b, 0xcf, 0x66, 0x78, 0x92, 0x6e, 0x70, 0xae, 0xbe, 0xbc, 0xe5, 0x8b, 0xd9, 0x77, 0x71, 0xcf, 0xd1, 0x0c, 0x33, 0x86, 0xcd, 0x72, 0xac, 0x14, 0x28, 0x42, 0xf0, 0x01, 0x5c, 0x0b, 0xfc, 0x8e, 0xa9, 0xa7, 0xe1, 0xf0, 0x3c, 0x5e, 0x1a, 0xe5, 0xf9, 0xd7, 0xae, 0xab, 0x3e, 0xa0, 0xed, 0xeb, 0x03, 0xdb, 0xc3, 0x27, 0x38, 0xc8, 0xda, 0xb3, 0xd5, 0x4c, 0x1c, 0x4a, 0x2b, 0xef, 0x5d, 0xee, 0xa7, 0xa9, 0xcf, 0x61, 0x39, 0x54, 0x7c, 0x99, 0xce, 0x1c, 0xf5, 0x0f, 0xff, 0x94, 0xde, 0x3d, 0x12, 0x76, 0xfd, 0x20, 0x83, 0x0a, 0x9d, 0x98, 0x54, 0x67, 0xd9, 0xf9, 0x6f, 0x00, 0x00, 0x00, 0xff, 0xff, 0xc3, 0xe8, 0xdf, 0x9c, 0xc3, 0x18, 0x00, 0x00, } lxd-2.0.0/dist/src/github.com/golang/protobuf/protoc-gen-go/descriptor/Makefile0000644061062106075000000000420012702772352032107 0ustar00stgraberdomain admins00000000000000# Go support for Protocol Buffers - Google's data interchange format # # Copyright 2010 The Go Authors. All rights reserved. # https://github.com/golang/protobuf # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # Not stored here, but descriptor.proto is in https://github.com/google/protobuf/ # at src/google/protobuf/descriptor.proto regenerate: echo WARNING! THIS RULE IS PROBABLY NOT RIGHT FOR YOUR INSTALLATION protoc --go_out=. -I$(HOME)/src/protobuf/src $(HOME)/src/protobuf/src/google/protobuf/descriptor.proto && \ sed 's,^package google_protobuf,package descriptor,' google/protobuf/descriptor.pb.go > \ $(GOPATH)/src/github.com/golang/protobuf/protoc-gen-go/descriptor/descriptor.pb.go && \ rm -f google/protobuf/descriptor.pb.go lxd-2.0.0/dist/src/github.com/golang/protobuf/protoc-gen-go/main.go0000644061062106075000000000676012702772352027561 0ustar00stgraberdomain admins00000000000000// Go support for Protocol Buffers - Google's data interchange format // // Copyright 2010 The Go Authors. All rights reserved. // https://github.com/golang/protobuf // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // protoc-gen-go is a plugin for the Google protocol buffer compiler to generate // Go code. Run it by building this program and putting it in your path with // the name // protoc-gen-go // That word 'go' at the end becomes part of the option string set for the // protocol compiler, so once the protocol compiler (protoc) is installed // you can run // protoc --go_out=output_directory input_directory/file.proto // to generate Go bindings for the protocol defined by file.proto. // With that input, the output will be written to // output_directory/file.pb.go // // The generated code is documented in the package comment for // the library. // // See the README and documentation for protocol buffers to learn more: // https://developers.google.com/protocol-buffers/ package main import ( "io/ioutil" "os" "github.com/golang/protobuf/proto" "github.com/golang/protobuf/protoc-gen-go/generator" ) func main() { // Begin by allocating a generator. The request and response structures are stored there // so we can do error handling easily - the response structure contains the field to // report failure. g := generator.New() data, err := ioutil.ReadAll(os.Stdin) if err != nil { g.Error(err, "reading input") } if err := proto.Unmarshal(data, g.Request); err != nil { g.Error(err, "parsing input proto") } if len(g.Request.FileToGenerate) == 0 { g.Fail("no files to generate") } g.CommandLineParameters(g.Request.GetParameter()) // Create a wrapped version of the Descriptors and EnumDescriptors that // point to the file that defines them. g.WrapTypes() g.SetPackageNames() g.BuildTypeNameMap() g.GenerateAllFiles() // Send back the results. data, err = proto.Marshal(g.Response) if err != nil { g.Error(err, "failed to marshal output proto") } _, err = os.Stdout.Write(data) if err != nil { g.Error(err, "failed to write output proto") } } lxd-2.0.0/dist/src/github.com/golang/protobuf/protoc-gen-go/generator/0000755061062106075000000000000012702772352030263 5ustar00stgraberdomain admins00000000000000lxd-2.0.0/dist/src/github.com/golang/protobuf/protoc-gen-go/generator/generator.go0000644061062106075000000025726612702772352032622 0ustar00stgraberdomain admins00000000000000// Go support for Protocol Buffers - Google's data interchange format // // Copyright 2010 The Go Authors. All rights reserved. // https://github.com/golang/protobuf // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /* The code generator for the plugin for the Google protocol buffer compiler. It generates Go code from the protocol buffer description files read by the main routine. */ package generator import ( "bufio" "bytes" "compress/gzip" "fmt" "go/parser" "go/printer" "go/token" "log" "os" "path" "strconv" "strings" "unicode" "unicode/utf8" "github.com/golang/protobuf/proto" "github.com/golang/protobuf/protoc-gen-go/descriptor" plugin "github.com/golang/protobuf/protoc-gen-go/plugin" ) // generatedCodeVersion indicates a version of the generated code. // It is incremented whenever an incompatibility between the generated code and // proto package is introduced; the generated code references // a constant, proto.ProtoPackageIsVersionN (where N is generatedCodeVersion). const generatedCodeVersion = 1 // A Plugin provides functionality to add to the output during Go code generation, // such as to produce RPC stubs. type Plugin interface { // Name identifies the plugin. Name() string // Init is called once after data structures are built but before // code generation begins. Init(g *Generator) // Generate produces the code generated by the plugin for this file, // except for the imports, by calling the generator's methods P, In, and Out. Generate(file *FileDescriptor) // GenerateImports produces the import declarations for this file. // It is called after Generate. GenerateImports(file *FileDescriptor) } var plugins []Plugin // RegisterPlugin installs a (second-order) plugin to be run when the Go output is generated. // It is typically called during initialization. func RegisterPlugin(p Plugin) { plugins = append(plugins, p) } // Each type we import as a protocol buffer (other than FileDescriptorProto) needs // a pointer to the FileDescriptorProto that represents it. These types achieve that // wrapping by placing each Proto inside a struct with the pointer to its File. The // structs have the same names as their contents, with "Proto" removed. // FileDescriptor is used to store the things that it points to. // The file and package name method are common to messages and enums. type common struct { file *descriptor.FileDescriptorProto // File this object comes from. } // PackageName is name in the package clause in the generated file. func (c *common) PackageName() string { return uniquePackageOf(c.file) } func (c *common) File() *descriptor.FileDescriptorProto { return c.file } func fileIsProto3(file *descriptor.FileDescriptorProto) bool { return file.GetSyntax() == "proto3" } func (c *common) proto3() bool { return fileIsProto3(c.file) } // Descriptor represents a protocol buffer message. type Descriptor struct { common *descriptor.DescriptorProto parent *Descriptor // The containing message, if any. nested []*Descriptor // Inner messages, if any. enums []*EnumDescriptor // Inner enums, if any. ext []*ExtensionDescriptor // Extensions, if any. typename []string // Cached typename vector. index int // The index into the container, whether the file or another message. path string // The SourceCodeInfo path as comma-separated integers. group bool } // TypeName returns the elements of the dotted type name. // The package name is not part of this name. func (d *Descriptor) TypeName() []string { if d.typename != nil { return d.typename } n := 0 for parent := d; parent != nil; parent = parent.parent { n++ } s := make([]string, n, n) for parent := d; parent != nil; parent = parent.parent { n-- s[n] = parent.GetName() } d.typename = s return s } // EnumDescriptor describes an enum. If it's at top level, its parent will be nil. // Otherwise it will be the descriptor of the message in which it is defined. type EnumDescriptor struct { common *descriptor.EnumDescriptorProto parent *Descriptor // The containing message, if any. typename []string // Cached typename vector. index int // The index into the container, whether the file or a message. path string // The SourceCodeInfo path as comma-separated integers. } // TypeName returns the elements of the dotted type name. // The package name is not part of this name. func (e *EnumDescriptor) TypeName() (s []string) { if e.typename != nil { return e.typename } name := e.GetName() if e.parent == nil { s = make([]string, 1) } else { pname := e.parent.TypeName() s = make([]string, len(pname)+1) copy(s, pname) } s[len(s)-1] = name e.typename = s return s } // Everything but the last element of the full type name, CamelCased. // The values of type Foo.Bar are call Foo_value1... not Foo_Bar_value1... . func (e *EnumDescriptor) prefix() string { if e.parent == nil { // If the enum is not part of a message, the prefix is just the type name. return CamelCase(*e.Name) + "_" } typeName := e.TypeName() return CamelCaseSlice(typeName[0:len(typeName)-1]) + "_" } // The integer value of the named constant in this enumerated type. func (e *EnumDescriptor) integerValueAsString(name string) string { for _, c := range e.Value { if c.GetName() == name { return fmt.Sprint(c.GetNumber()) } } log.Fatal("cannot find value for enum constant") return "" } // ExtensionDescriptor describes an extension. If it's at top level, its parent will be nil. // Otherwise it will be the descriptor of the message in which it is defined. type ExtensionDescriptor struct { common *descriptor.FieldDescriptorProto parent *Descriptor // The containing message, if any. } // TypeName returns the elements of the dotted type name. // The package name is not part of this name. func (e *ExtensionDescriptor) TypeName() (s []string) { name := e.GetName() if e.parent == nil { // top-level extension s = make([]string, 1) } else { pname := e.parent.TypeName() s = make([]string, len(pname)+1) copy(s, pname) } s[len(s)-1] = name return s } // DescName returns the variable name used for the generated descriptor. func (e *ExtensionDescriptor) DescName() string { // The full type name. typeName := e.TypeName() // Each scope of the extension is individually CamelCased, and all are joined with "_" with an "E_" prefix. for i, s := range typeName { typeName[i] = CamelCase(s) } return "E_" + strings.Join(typeName, "_") } // ImportedDescriptor describes a type that has been publicly imported from another file. type ImportedDescriptor struct { common o Object } func (id *ImportedDescriptor) TypeName() []string { return id.o.TypeName() } // FileDescriptor describes an protocol buffer descriptor file (.proto). // It includes slices of all the messages and enums defined within it. // Those slices are constructed by WrapTypes. type FileDescriptor struct { *descriptor.FileDescriptorProto desc []*Descriptor // All the messages defined in this file. enum []*EnumDescriptor // All the enums defined in this file. ext []*ExtensionDescriptor // All the top-level extensions defined in this file. imp []*ImportedDescriptor // All types defined in files publicly imported by this file. // Comments, stored as a map of path (comma-separated integers) to the comment. comments map[string]*descriptor.SourceCodeInfo_Location // The full list of symbols that are exported, // as a map from the exported object to its symbols. // This is used for supporting public imports. exported map[Object][]symbol index int // The index of this file in the list of files to generate code for proto3 bool // whether to generate proto3 code for this file } // PackageName is the package name we'll use in the generated code to refer to this file. func (d *FileDescriptor) PackageName() string { return uniquePackageOf(d.FileDescriptorProto) } // goPackageOption interprets the file's go_package option. // If there is no go_package, it returns ("", "", false). // If there's a simple name, it returns ("", pkg, true). // If the option implies an import path, it returns (impPath, pkg, true). func (d *FileDescriptor) goPackageOption() (impPath, pkg string, ok bool) { pkg = d.GetOptions().GetGoPackage() if pkg == "" { return } ok = true // The presence of a slash implies there's an import path. slash := strings.LastIndex(pkg, "/") if slash < 0 { return } impPath, pkg = pkg, pkg[slash+1:] // A semicolon-delimited suffix overrides the package name. sc := strings.IndexByte(impPath, ';') if sc < 0 { return } impPath, pkg = impPath[:sc], impPath[sc+1:] return } // goPackageName returns the Go package name to use in the // generated Go file. The result explicit reports whether the name // came from an option go_package statement. If explicit is false, // the name was derived from the protocol buffer's package statement // or the input file name. func (d *FileDescriptor) goPackageName() (name string, explicit bool) { // Does the file have a "go_package" option? if _, pkg, ok := d.goPackageOption(); ok { return pkg, true } // Does the file have a package clause? if pkg := d.GetPackage(); pkg != "" { return pkg, false } // Use the file base name. return baseName(d.GetName()), false } // goFileName returns the output name for the generated Go file. func (d *FileDescriptor) goFileName() string { name := *d.Name if ext := path.Ext(name); ext == ".proto" || ext == ".protodevel" { name = name[:len(name)-len(ext)] } name += ".pb.go" // Does the file have a "go_package" option? // If it does, it may override the filename. if impPath, _, ok := d.goPackageOption(); ok && impPath != "" { // Replace the existing dirname with the declared import path. _, name = path.Split(name) name = path.Join(impPath, name) return name } return name } func (d *FileDescriptor) addExport(obj Object, sym symbol) { d.exported[obj] = append(d.exported[obj], sym) } // symbol is an interface representing an exported Go symbol. type symbol interface { // GenerateAlias should generate an appropriate alias // for the symbol from the named package. GenerateAlias(g *Generator, pkg string) } type messageSymbol struct { sym string hasExtensions, isMessageSet bool hasOneof bool getters []getterSymbol } type getterSymbol struct { name string typ string typeName string // canonical name in proto world; empty for proto.Message and similar genType bool // whether typ contains a generated type (message/group/enum) } func (ms *messageSymbol) GenerateAlias(g *Generator, pkg string) { remoteSym := pkg + "." + ms.sym g.P("type ", ms.sym, " ", remoteSym) g.P("func (m *", ms.sym, ") Reset() { (*", remoteSym, ")(m).Reset() }") g.P("func (m *", ms.sym, ") String() string { return (*", remoteSym, ")(m).String() }") g.P("func (*", ms.sym, ") ProtoMessage() {}") if ms.hasExtensions { g.P("func (*", ms.sym, ") ExtensionRangeArray() []", g.Pkg["proto"], ".ExtensionRange ", "{ return (*", remoteSym, ")(nil).ExtensionRangeArray() }") g.P("func (m *", ms.sym, ") ExtensionMap() map[int32]", g.Pkg["proto"], ".Extension ", "{ return (*", remoteSym, ")(m).ExtensionMap() }") if ms.isMessageSet { g.P("func (m *", ms.sym, ") Marshal() ([]byte, error) ", "{ return (*", remoteSym, ")(m).Marshal() }") g.P("func (m *", ms.sym, ") Unmarshal(buf []byte) error ", "{ return (*", remoteSym, ")(m).Unmarshal(buf) }") } } if ms.hasOneof { // Oneofs and public imports do not mix well. // We can make them work okay for the binary format, // but they're going to break weirdly for text/JSON. enc := "_" + ms.sym + "_OneofMarshaler" dec := "_" + ms.sym + "_OneofUnmarshaler" size := "_" + ms.sym + "_OneofSizer" encSig := "(msg " + g.Pkg["proto"] + ".Message, b *" + g.Pkg["proto"] + ".Buffer) error" decSig := "(msg " + g.Pkg["proto"] + ".Message, tag, wire int, b *" + g.Pkg["proto"] + ".Buffer) (bool, error)" sizeSig := "(msg " + g.Pkg["proto"] + ".Message) int" g.P("func (m *", ms.sym, ") XXX_OneofFuncs() (func", encSig, ", func", decSig, ", func", sizeSig, ", []interface{}) {") g.P("return ", enc, ", ", dec, ", ", size, ", nil") g.P("}") g.P("func ", enc, encSig, " {") g.P("m := msg.(*", ms.sym, ")") g.P("m0 := (*", remoteSym, ")(m)") g.P("enc, _, _, _ := m0.XXX_OneofFuncs()") g.P("return enc(m0, b)") g.P("}") g.P("func ", dec, decSig, " {") g.P("m := msg.(*", ms.sym, ")") g.P("m0 := (*", remoteSym, ")(m)") g.P("_, dec, _, _ := m0.XXX_OneofFuncs()") g.P("return dec(m0, tag, wire, b)") g.P("}") g.P("func ", size, sizeSig, " {") g.P("m := msg.(*", ms.sym, ")") g.P("m0 := (*", remoteSym, ")(m)") g.P("_, _, size, _ := m0.XXX_OneofFuncs()") g.P("return size(m0)") g.P("}") } for _, get := range ms.getters { if get.typeName != "" { g.RecordTypeUse(get.typeName) } typ := get.typ val := "(*" + remoteSym + ")(m)." + get.name + "()" if get.genType { // typ will be "*pkg.T" (message/group) or "pkg.T" (enum) // or "map[t]*pkg.T" (map to message/enum). // The first two of those might have a "[]" prefix if it is repeated. // Drop any package qualifier since we have hoisted the type into this package. rep := strings.HasPrefix(typ, "[]") if rep { typ = typ[2:] } isMap := strings.HasPrefix(typ, "map[") star := typ[0] == '*' if !isMap { // map types handled lower down typ = typ[strings.Index(typ, ".")+1:] } if star { typ = "*" + typ } if rep { // Go does not permit conversion between slice types where both // element types are named. That means we need to generate a bit // of code in this situation. // typ is the element type. // val is the expression to get the slice from the imported type. ctyp := typ // conversion type expression; "Foo" or "(*Foo)" if star { ctyp = "(" + typ + ")" } g.P("func (m *", ms.sym, ") ", get.name, "() []", typ, " {") g.In() g.P("o := ", val) g.P("if o == nil {") g.In() g.P("return nil") g.Out() g.P("}") g.P("s := make([]", typ, ", len(o))") g.P("for i, x := range o {") g.In() g.P("s[i] = ", ctyp, "(x)") g.Out() g.P("}") g.P("return s") g.Out() g.P("}") continue } if isMap { // Split map[keyTyp]valTyp. bra, ket := strings.Index(typ, "["), strings.Index(typ, "]") keyTyp, valTyp := typ[bra+1:ket], typ[ket+1:] // Drop any package qualifier. // Only the value type may be foreign. star := valTyp[0] == '*' valTyp = valTyp[strings.Index(valTyp, ".")+1:] if star { valTyp = "*" + valTyp } typ := "map[" + keyTyp + "]" + valTyp g.P("func (m *", ms.sym, ") ", get.name, "() ", typ, " {") g.P("o := ", val) g.P("if o == nil { return nil }") g.P("s := make(", typ, ", len(o))") g.P("for k, v := range o {") g.P("s[k] = (", valTyp, ")(v)") g.P("}") g.P("return s") g.P("}") continue } // Convert imported type into the forwarding type. val = "(" + typ + ")(" + val + ")" } g.P("func (m *", ms.sym, ") ", get.name, "() ", typ, " { return ", val, " }") } } type enumSymbol struct { name string proto3 bool // Whether this came from a proto3 file. } func (es enumSymbol) GenerateAlias(g *Generator, pkg string) { s := es.name g.P("type ", s, " ", pkg, ".", s) g.P("var ", s, "_name = ", pkg, ".", s, "_name") g.P("var ", s, "_value = ", pkg, ".", s, "_value") g.P("func (x ", s, ") String() string { return (", pkg, ".", s, ")(x).String() }") if !es.proto3 { g.P("func (x ", s, ") Enum() *", s, "{ return (*", s, ")((", pkg, ".", s, ")(x).Enum()) }") g.P("func (x *", s, ") UnmarshalJSON(data []byte) error { return (*", pkg, ".", s, ")(x).UnmarshalJSON(data) }") } } type constOrVarSymbol struct { sym string typ string // either "const" or "var" cast string // if non-empty, a type cast is required (used for enums) } func (cs constOrVarSymbol) GenerateAlias(g *Generator, pkg string) { v := pkg + "." + cs.sym if cs.cast != "" { v = cs.cast + "(" + v + ")" } g.P(cs.typ, " ", cs.sym, " = ", v) } // Object is an interface abstracting the abilities shared by enums, messages, extensions and imported objects. type Object interface { PackageName() string // The name we use in our output (a_b_c), possibly renamed for uniqueness. TypeName() []string File() *descriptor.FileDescriptorProto } // Each package name we generate must be unique. The package we're generating // gets its own name but every other package must have a unique name that does // not conflict in the code we generate. These names are chosen globally (although // they don't have to be, it simplifies things to do them globally). func uniquePackageOf(fd *descriptor.FileDescriptorProto) string { s, ok := uniquePackageName[fd] if !ok { log.Fatal("internal error: no package name defined for " + fd.GetName()) } return s } // Generator is the type whose methods generate the output, stored in the associated response structure. type Generator struct { *bytes.Buffer Request *plugin.CodeGeneratorRequest // The input. Response *plugin.CodeGeneratorResponse // The output. Param map[string]string // Command-line parameters. PackageImportPath string // Go import path of the package we're generating code for ImportPrefix string // String to prefix to imported package file names. ImportMap map[string]string // Mapping from .proto file name to import path Pkg map[string]string // The names under which we import support packages packageName string // What we're calling ourselves. allFiles []*FileDescriptor // All files in the tree allFilesByName map[string]*FileDescriptor // All files by filename. genFiles []*FileDescriptor // Those files we will generate output for. file *FileDescriptor // The file we are compiling now. usedPackages map[string]bool // Names of packages used in current file. typeNameToObject map[string]Object // Key is a fully-qualified name in input syntax. init []string // Lines to emit in the init function. indent string writeOutput bool } // New creates a new generator and allocates the request and response protobufs. func New() *Generator { g := new(Generator) g.Buffer = new(bytes.Buffer) g.Request = new(plugin.CodeGeneratorRequest) g.Response = new(plugin.CodeGeneratorResponse) return g } // Error reports a problem, including an error, and exits the program. func (g *Generator) Error(err error, msgs ...string) { s := strings.Join(msgs, " ") + ":" + err.Error() log.Print("protoc-gen-go: error:", s) os.Exit(1) } // Fail reports a problem and exits the program. func (g *Generator) Fail(msgs ...string) { s := strings.Join(msgs, " ") log.Print("protoc-gen-go: error:", s) os.Exit(1) } // CommandLineParameters breaks the comma-separated list of key=value pairs // in the parameter (a member of the request protobuf) into a key/value map. // It then sets file name mappings defined by those entries. func (g *Generator) CommandLineParameters(parameter string) { g.Param = make(map[string]string) for _, p := range strings.Split(parameter, ",") { if i := strings.Index(p, "="); i < 0 { g.Param[p] = "" } else { g.Param[p[0:i]] = p[i+1:] } } g.ImportMap = make(map[string]string) pluginList := "none" // Default list of plugin names to enable (empty means all). for k, v := range g.Param { switch k { case "import_prefix": g.ImportPrefix = v case "import_path": g.PackageImportPath = v case "plugins": pluginList = v default: if len(k) > 0 && k[0] == 'M' { g.ImportMap[k[1:]] = v } } } if pluginList != "" { // Amend the set of plugins. enabled := make(map[string]bool) for _, name := range strings.Split(pluginList, "+") { enabled[name] = true } var nplugins []Plugin for _, p := range plugins { if enabled[p.Name()] { nplugins = append(nplugins, p) } } plugins = nplugins } } // DefaultPackageName returns the package name printed for the object. // If its file is in a different package, it returns the package name we're using for this file, plus ".". // Otherwise it returns the empty string. func (g *Generator) DefaultPackageName(obj Object) string { pkg := obj.PackageName() if pkg == g.packageName { return "" } return pkg + "." } // For each input file, the unique package name to use, underscored. var uniquePackageName = make(map[*descriptor.FileDescriptorProto]string) // Package names already registered. Key is the name from the .proto file; // value is the name that appears in the generated code. var pkgNamesInUse = make(map[string]bool) // Create and remember a guaranteed unique package name for this file descriptor. // Pkg is the candidate name. If f is nil, it's a builtin package like "proto" and // has no file descriptor. func RegisterUniquePackageName(pkg string, f *FileDescriptor) string { // Convert dots to underscores before finding a unique alias. pkg = strings.Map(badToUnderscore, pkg) for i, orig := 1, pkg; pkgNamesInUse[pkg]; i++ { // It's a duplicate; must rename. pkg = orig + strconv.Itoa(i) } // Install it. pkgNamesInUse[pkg] = true if f != nil { uniquePackageName[f.FileDescriptorProto] = pkg } return pkg } var isGoKeyword = map[string]bool{ "break": true, "case": true, "chan": true, "const": true, "continue": true, "default": true, "else": true, "defer": true, "fallthrough": true, "for": true, "func": true, "go": true, "goto": true, "if": true, "import": true, "interface": true, "map": true, "package": true, "range": true, "return": true, "select": true, "struct": true, "switch": true, "type": true, "var": true, } // defaultGoPackage returns the package name to use, // derived from the import path of the package we're building code for. func (g *Generator) defaultGoPackage() string { p := g.PackageImportPath if i := strings.LastIndex(p, "/"); i >= 0 { p = p[i+1:] } if p == "" { return "" } p = strings.Map(badToUnderscore, p) // Identifier must not be keyword: insert _. if isGoKeyword[p] { p = "_" + p } // Identifier must not begin with digit: insert _. if r, _ := utf8.DecodeRuneInString(p); unicode.IsDigit(r) { p = "_" + p } return p } // SetPackageNames sets the package name for this run. // The package name must agree across all files being generated. // It also defines unique package names for all imported files. func (g *Generator) SetPackageNames() { // Register the name for this package. It will be the first name // registered so is guaranteed to be unmodified. pkg, explicit := g.genFiles[0].goPackageName() // Check all files for an explicit go_package option. for _, f := range g.genFiles { thisPkg, thisExplicit := f.goPackageName() if thisExplicit { if !explicit { // Let this file's go_package option serve for all input files. pkg, explicit = thisPkg, true } else if thisPkg != pkg { g.Fail("inconsistent package names:", thisPkg, pkg) } } } // If we don't have an explicit go_package option but we have an // import path, use that. if !explicit { p := g.defaultGoPackage() if p != "" { pkg, explicit = p, true } } // If there was no go_package and no import path to use, // double-check that all the inputs have the same implicit // Go package name. if !explicit { for _, f := range g.genFiles { thisPkg, _ := f.goPackageName() if thisPkg != pkg { g.Fail("inconsistent package names:", thisPkg, pkg) } } } g.packageName = RegisterUniquePackageName(pkg, g.genFiles[0]) // Register the support package names. They might collide with the // name of a package we import. g.Pkg = map[string]string{ "fmt": RegisterUniquePackageName("fmt", nil), "math": RegisterUniquePackageName("math", nil), "proto": RegisterUniquePackageName("proto", nil), } AllFiles: for _, f := range g.allFiles { for _, genf := range g.genFiles { if f == genf { // In this package already. uniquePackageName[f.FileDescriptorProto] = g.packageName continue AllFiles } } // The file is a dependency, so we want to ignore its go_package option // because that is only relevant for its specific generated output. pkg := f.GetPackage() if pkg == "" { pkg = baseName(*f.Name) } RegisterUniquePackageName(pkg, f) } } // WrapTypes walks the incoming data, wrapping DescriptorProtos, EnumDescriptorProtos // and FileDescriptorProtos into file-referenced objects within the Generator. // It also creates the list of files to generate and so should be called before GenerateAllFiles. func (g *Generator) WrapTypes() { g.allFiles = make([]*FileDescriptor, 0, len(g.Request.ProtoFile)) g.allFilesByName = make(map[string]*FileDescriptor, len(g.allFiles)) for _, f := range g.Request.ProtoFile { // We must wrap the descriptors before we wrap the enums descs := wrapDescriptors(f) g.buildNestedDescriptors(descs) enums := wrapEnumDescriptors(f, descs) g.buildNestedEnums(descs, enums) exts := wrapExtensions(f) fd := &FileDescriptor{ FileDescriptorProto: f, desc: descs, enum: enums, ext: exts, exported: make(map[Object][]symbol), proto3: fileIsProto3(f), } extractComments(fd) g.allFiles = append(g.allFiles, fd) g.allFilesByName[f.GetName()] = fd } for _, fd := range g.allFiles { fd.imp = wrapImported(fd.FileDescriptorProto, g) } g.genFiles = make([]*FileDescriptor, 0, len(g.Request.FileToGenerate)) for _, fileName := range g.Request.FileToGenerate { fd := g.allFilesByName[fileName] if fd == nil { g.Fail("could not find file named", fileName) } fd.index = len(g.genFiles) g.genFiles = append(g.genFiles, fd) } } // Scan the descriptors in this file. For each one, build the slice of nested descriptors func (g *Generator) buildNestedDescriptors(descs []*Descriptor) { for _, desc := range descs { if len(desc.NestedType) != 0 { for _, nest := range descs { if nest.parent == desc { desc.nested = append(desc.nested, nest) } } if len(desc.nested) != len(desc.NestedType) { g.Fail("internal error: nesting failure for", desc.GetName()) } } } } func (g *Generator) buildNestedEnums(descs []*Descriptor, enums []*EnumDescriptor) { for _, desc := range descs { if len(desc.EnumType) != 0 { for _, enum := range enums { if enum.parent == desc { desc.enums = append(desc.enums, enum) } } if len(desc.enums) != len(desc.EnumType) { g.Fail("internal error: enum nesting failure for", desc.GetName()) } } } } // Construct the Descriptor func newDescriptor(desc *descriptor.DescriptorProto, parent *Descriptor, file *descriptor.FileDescriptorProto, index int) *Descriptor { d := &Descriptor{ common: common{file}, DescriptorProto: desc, parent: parent, index: index, } if parent == nil { d.path = fmt.Sprintf("%d,%d", messagePath, index) } else { d.path = fmt.Sprintf("%s,%d,%d", parent.path, messageMessagePath, index) } // The only way to distinguish a group from a message is whether // the containing message has a TYPE_GROUP field that matches. if parent != nil { parts := d.TypeName() if file.Package != nil { parts = append([]string{*file.Package}, parts...) } exp := "." + strings.Join(parts, ".") for _, field := range parent.Field { if field.GetType() == descriptor.FieldDescriptorProto_TYPE_GROUP && field.GetTypeName() == exp { d.group = true break } } } for _, field := range desc.Extension { d.ext = append(d.ext, &ExtensionDescriptor{common{file}, field, d}) } return d } // Return a slice of all the Descriptors defined within this file func wrapDescriptors(file *descriptor.FileDescriptorProto) []*Descriptor { sl := make([]*Descriptor, 0, len(file.MessageType)+10) for i, desc := range file.MessageType { sl = wrapThisDescriptor(sl, desc, nil, file, i) } return sl } // Wrap this Descriptor, recursively func wrapThisDescriptor(sl []*Descriptor, desc *descriptor.DescriptorProto, parent *Descriptor, file *descriptor.FileDescriptorProto, index int) []*Descriptor { sl = append(sl, newDescriptor(desc, parent, file, index)) me := sl[len(sl)-1] for i, nested := range desc.NestedType { sl = wrapThisDescriptor(sl, nested, me, file, i) } return sl } // Construct the EnumDescriptor func newEnumDescriptor(desc *descriptor.EnumDescriptorProto, parent *Descriptor, file *descriptor.FileDescriptorProto, index int) *EnumDescriptor { ed := &EnumDescriptor{ common: common{file}, EnumDescriptorProto: desc, parent: parent, index: index, } if parent == nil { ed.path = fmt.Sprintf("%d,%d", enumPath, index) } else { ed.path = fmt.Sprintf("%s,%d,%d", parent.path, messageEnumPath, index) } return ed } // Return a slice of all the EnumDescriptors defined within this file func wrapEnumDescriptors(file *descriptor.FileDescriptorProto, descs []*Descriptor) []*EnumDescriptor { sl := make([]*EnumDescriptor, 0, len(file.EnumType)+10) // Top-level enums. for i, enum := range file.EnumType { sl = append(sl, newEnumDescriptor(enum, nil, file, i)) } // Enums within messages. Enums within embedded messages appear in the outer-most message. for _, nested := range descs { for i, enum := range nested.EnumType { sl = append(sl, newEnumDescriptor(enum, nested, file, i)) } } return sl } // Return a slice of all the top-level ExtensionDescriptors defined within this file. func wrapExtensions(file *descriptor.FileDescriptorProto) []*ExtensionDescriptor { var sl []*ExtensionDescriptor for _, field := range file.Extension { sl = append(sl, &ExtensionDescriptor{common{file}, field, nil}) } return sl } // Return a slice of all the types that are publicly imported into this file. func wrapImported(file *descriptor.FileDescriptorProto, g *Generator) (sl []*ImportedDescriptor) { for _, index := range file.PublicDependency { df := g.fileByName(file.Dependency[index]) for _, d := range df.desc { if d.GetOptions().GetMapEntry() { continue } sl = append(sl, &ImportedDescriptor{common{file}, d}) } for _, e := range df.enum { sl = append(sl, &ImportedDescriptor{common{file}, e}) } for _, ext := range df.ext { sl = append(sl, &ImportedDescriptor{common{file}, ext}) } } return } func extractComments(file *FileDescriptor) { file.comments = make(map[string]*descriptor.SourceCodeInfo_Location) for _, loc := range file.GetSourceCodeInfo().GetLocation() { if loc.LeadingComments == nil { continue } var p []string for _, n := range loc.Path { p = append(p, strconv.Itoa(int(n))) } file.comments[strings.Join(p, ",")] = loc } } // BuildTypeNameMap builds the map from fully qualified type names to objects. // The key names for the map come from the input data, which puts a period at the beginning. // It should be called after SetPackageNames and before GenerateAllFiles. func (g *Generator) BuildTypeNameMap() { g.typeNameToObject = make(map[string]Object) for _, f := range g.allFiles { // The names in this loop are defined by the proto world, not us, so the // package name may be empty. If so, the dotted package name of X will // be ".X"; otherwise it will be ".pkg.X". dottedPkg := "." + f.GetPackage() if dottedPkg != "." { dottedPkg += "." } for _, enum := range f.enum { name := dottedPkg + dottedSlice(enum.TypeName()) g.typeNameToObject[name] = enum } for _, desc := range f.desc { name := dottedPkg + dottedSlice(desc.TypeName()) g.typeNameToObject[name] = desc } } } // ObjectNamed, given a fully-qualified input type name as it appears in the input data, // returns the descriptor for the message or enum with that name. func (g *Generator) ObjectNamed(typeName string) Object { o, ok := g.typeNameToObject[typeName] if !ok { g.Fail("can't find object with type", typeName) } // If the file of this object isn't a direct dependency of the current file, // or in the current file, then this object has been publicly imported into // a dependency of the current file. // We should return the ImportedDescriptor object for it instead. direct := *o.File().Name == *g.file.Name if !direct { for _, dep := range g.file.Dependency { if *g.fileByName(dep).Name == *o.File().Name { direct = true break } } } if !direct { found := false Loop: for _, dep := range g.file.Dependency { df := g.fileByName(*g.fileByName(dep).Name) for _, td := range df.imp { if td.o == o { // Found it! o = td found = true break Loop } } } if !found { log.Printf("protoc-gen-go: WARNING: failed finding publicly imported dependency for %v, used in %v", typeName, *g.file.Name) } } return o } // P prints the arguments to the generated output. It handles strings and int32s, plus // handling indirections because they may be *string, etc. func (g *Generator) P(str ...interface{}) { if !g.writeOutput { return } g.WriteString(g.indent) for _, v := range str { switch s := v.(type) { case string: g.WriteString(s) case *string: g.WriteString(*s) case bool: fmt.Fprintf(g, "%t", s) case *bool: fmt.Fprintf(g, "%t", *s) case int: fmt.Fprintf(g, "%d", s) case *int32: fmt.Fprintf(g, "%d", *s) case *int64: fmt.Fprintf(g, "%d", *s) case float64: fmt.Fprintf(g, "%g", s) case *float64: fmt.Fprintf(g, "%g", *s) default: g.Fail(fmt.Sprintf("unknown type in printer: %T", v)) } } g.WriteByte('\n') } // addInitf stores the given statement to be printed inside the file's init function. // The statement is given as a format specifier and arguments. func (g *Generator) addInitf(stmt string, a ...interface{}) { g.init = append(g.init, fmt.Sprintf(stmt, a...)) } // In Indents the output one tab stop. func (g *Generator) In() { g.indent += "\t" } // Out unindents the output one tab stop. func (g *Generator) Out() { if len(g.indent) > 0 { g.indent = g.indent[1:] } } // GenerateAllFiles generates the output for all the files we're outputting. func (g *Generator) GenerateAllFiles() { // Initialize the plugins for _, p := range plugins { p.Init(g) } // Generate the output. The generator runs for every file, even the files // that we don't generate output for, so that we can collate the full list // of exported symbols to support public imports. genFileMap := make(map[*FileDescriptor]bool, len(g.genFiles)) for _, file := range g.genFiles { genFileMap[file] = true } for _, file := range g.allFiles { g.Reset() g.writeOutput = genFileMap[file] g.generate(file) if !g.writeOutput { continue } g.Response.File = append(g.Response.File, &plugin.CodeGeneratorResponse_File{ Name: proto.String(file.goFileName()), Content: proto.String(g.String()), }) } } // Run all the plugins associated with the file. func (g *Generator) runPlugins(file *FileDescriptor) { for _, p := range plugins { p.Generate(file) } } // FileOf return the FileDescriptor for this FileDescriptorProto. func (g *Generator) FileOf(fd *descriptor.FileDescriptorProto) *FileDescriptor { for _, file := range g.allFiles { if file.FileDescriptorProto == fd { return file } } g.Fail("could not find file in table:", fd.GetName()) return nil } // Fill the response protocol buffer with the generated output for all the files we're // supposed to generate. func (g *Generator) generate(file *FileDescriptor) { g.file = g.FileOf(file.FileDescriptorProto) g.usedPackages = make(map[string]bool) if g.file.index == 0 { // For one file in the package, assert version compatibility. g.P("// This is a compile-time assertion to ensure that this generated file") g.P("// is compatible with the proto package it is being compiled against.") g.P("const _ = ", g.Pkg["proto"], ".ProtoPackageIsVersion", generatedCodeVersion) g.P() } for _, td := range g.file.imp { g.generateImported(td) } for _, enum := range g.file.enum { g.generateEnum(enum) } for _, desc := range g.file.desc { // Don't generate virtual messages for maps. if desc.GetOptions().GetMapEntry() { continue } g.generateMessage(desc) } for _, ext := range g.file.ext { g.generateExtension(ext) } g.generateInitFunction() // Run the plugins before the imports so we know which imports are necessary. g.runPlugins(file) g.generateFileDescriptor(file) // Generate header and imports last, though they appear first in the output. rem := g.Buffer g.Buffer = new(bytes.Buffer) g.generateHeader() g.generateImports() if !g.writeOutput { return } g.Write(rem.Bytes()) // Reformat generated code. fset := token.NewFileSet() raw := g.Bytes() ast, err := parser.ParseFile(fset, "", g, parser.ParseComments) if err != nil { // Print out the bad code with line numbers. // This should never happen in practice, but it can while changing generated code, // so consider this a debugging aid. var src bytes.Buffer s := bufio.NewScanner(bytes.NewReader(raw)) for line := 1; s.Scan(); line++ { fmt.Fprintf(&src, "%5d\t%s\n", line, s.Bytes()) } g.Fail("bad Go source code was generated:", err.Error(), "\n"+src.String()) } g.Reset() err = (&printer.Config{Mode: printer.TabIndent | printer.UseSpaces, Tabwidth: 8}).Fprint(g, fset, ast) if err != nil { g.Fail("generated Go source code could not be reformatted:", err.Error()) } } // Generate the header, including package definition func (g *Generator) generateHeader() { g.P("// Code generated by protoc-gen-go.") g.P("// source: ", g.file.Name) g.P("// DO NOT EDIT!") g.P() name := g.file.PackageName() if g.file.index == 0 { // Generate package docs for the first file in the package. g.P("/*") g.P("Package ", name, " is a generated protocol buffer package.") g.P() if loc, ok := g.file.comments[strconv.Itoa(packagePath)]; ok { // not using g.PrintComments because this is a /* */ comment block. text := strings.TrimSuffix(loc.GetLeadingComments(), "\n") for _, line := range strings.Split(text, "\n") { line = strings.TrimPrefix(line, " ") // ensure we don't escape from the block comment line = strings.Replace(line, "*/", "* /", -1) g.P(line) } g.P() } var topMsgs []string g.P("It is generated from these files:") for _, f := range g.genFiles { g.P("\t", f.Name) for _, msg := range f.desc { if msg.parent != nil { continue } topMsgs = append(topMsgs, CamelCaseSlice(msg.TypeName())) } } g.P() g.P("It has these top-level messages:") for _, msg := range topMsgs { g.P("\t", msg) } g.P("*/") } g.P("package ", name) g.P() } // PrintComments prints any comments from the source .proto file. // The path is a comma-separated list of integers. // It returns an indication of whether any comments were printed. // See descriptor.proto for its format. func (g *Generator) PrintComments(path string) bool { if !g.writeOutput { return false } if loc, ok := g.file.comments[path]; ok { text := strings.TrimSuffix(loc.GetLeadingComments(), "\n") for _, line := range strings.Split(text, "\n") { g.P("// ", strings.TrimPrefix(line, " ")) } return true } return false } func (g *Generator) fileByName(filename string) *FileDescriptor { return g.allFilesByName[filename] } // weak returns whether the ith import of the current file is a weak import. func (g *Generator) weak(i int32) bool { for _, j := range g.file.WeakDependency { if j == i { return true } } return false } // Generate the imports func (g *Generator) generateImports() { // We almost always need a proto import. Rather than computing when we // do, which is tricky when there's a plugin, just import it and // reference it later. The same argument applies to the fmt and math packages. g.P("import " + g.Pkg["proto"] + " " + strconv.Quote(g.ImportPrefix+"github.com/golang/protobuf/proto")) g.P("import " + g.Pkg["fmt"] + ` "fmt"`) g.P("import " + g.Pkg["math"] + ` "math"`) for i, s := range g.file.Dependency { fd := g.fileByName(s) // Do not import our own package. if fd.PackageName() == g.packageName { continue } filename := fd.goFileName() // By default, import path is the dirname of the Go filename. importPath := path.Dir(filename) if substitution, ok := g.ImportMap[s]; ok { importPath = substitution } importPath = g.ImportPrefix + importPath // Skip weak imports. if g.weak(int32(i)) { g.P("// skipping weak import ", fd.PackageName(), " ", strconv.Quote(importPath)) continue } // We need to import all the dependencies, even if we don't reference them, // because other code and tools depend on having the full transitive closure // of protocol buffer types in the binary. pname := fd.PackageName() if _, ok := g.usedPackages[pname]; !ok { pname = "_" } g.P("import ", pname, " ", strconv.Quote(importPath)) } g.P() // TODO: may need to worry about uniqueness across plugins for _, p := range plugins { p.GenerateImports(g.file) g.P() } g.P("// Reference imports to suppress errors if they are not otherwise used.") g.P("var _ = ", g.Pkg["proto"], ".Marshal") g.P("var _ = ", g.Pkg["fmt"], ".Errorf") g.P("var _ = ", g.Pkg["math"], ".Inf") g.P() } func (g *Generator) generateImported(id *ImportedDescriptor) { // Don't generate public import symbols for files that we are generating // code for, since those symbols will already be in this package. // We can't simply avoid creating the ImportedDescriptor objects, // because g.genFiles isn't populated at that stage. tn := id.TypeName() sn := tn[len(tn)-1] df := g.FileOf(id.o.File()) filename := *df.Name for _, fd := range g.genFiles { if *fd.Name == filename { g.P("// Ignoring public import of ", sn, " from ", filename) g.P() return } } g.P("// ", sn, " from public import ", filename) g.usedPackages[df.PackageName()] = true for _, sym := range df.exported[id.o] { sym.GenerateAlias(g, df.PackageName()) } g.P() } // Generate the enum definitions for this EnumDescriptor. func (g *Generator) generateEnum(enum *EnumDescriptor) { // The full type name typeName := enum.TypeName() // The full type name, CamelCased. ccTypeName := CamelCaseSlice(typeName) ccPrefix := enum.prefix() g.PrintComments(enum.path) g.P("type ", ccTypeName, " int32") g.file.addExport(enum, enumSymbol{ccTypeName, enum.proto3()}) g.P("const (") g.In() for i, e := range enum.Value { g.PrintComments(fmt.Sprintf("%s,%d,%d", enum.path, enumValuePath, i)) name := ccPrefix + *e.Name g.P(name, " ", ccTypeName, " = ", e.Number) g.file.addExport(enum, constOrVarSymbol{name, "const", ccTypeName}) } g.Out() g.P(")") g.P("var ", ccTypeName, "_name = map[int32]string{") g.In() generated := make(map[int32]bool) // avoid duplicate values for _, e := range enum.Value { duplicate := "" if _, present := generated[*e.Number]; present { duplicate = "// Duplicate value: " } g.P(duplicate, e.Number, ": ", strconv.Quote(*e.Name), ",") generated[*e.Number] = true } g.Out() g.P("}") g.P("var ", ccTypeName, "_value = map[string]int32{") g.In() for _, e := range enum.Value { g.P(strconv.Quote(*e.Name), ": ", e.Number, ",") } g.Out() g.P("}") if !enum.proto3() { g.P("func (x ", ccTypeName, ") Enum() *", ccTypeName, " {") g.In() g.P("p := new(", ccTypeName, ")") g.P("*p = x") g.P("return p") g.Out() g.P("}") } g.P("func (x ", ccTypeName, ") String() string {") g.In() g.P("return ", g.Pkg["proto"], ".EnumName(", ccTypeName, "_name, int32(x))") g.Out() g.P("}") if !enum.proto3() { g.P("func (x *", ccTypeName, ") UnmarshalJSON(data []byte) error {") g.In() g.P("value, err := ", g.Pkg["proto"], ".UnmarshalJSONEnum(", ccTypeName, `_value, data, "`, ccTypeName, `")`) g.P("if err != nil {") g.In() g.P("return err") g.Out() g.P("}") g.P("*x = ", ccTypeName, "(value)") g.P("return nil") g.Out() g.P("}") } var indexes []string for m := enum.parent; m != nil; m = m.parent { // XXX: skip groups? indexes = append([]string{strconv.Itoa(m.index)}, indexes...) } indexes = append(indexes, strconv.Itoa(enum.index)) g.P("func (", ccTypeName, ") EnumDescriptor() ([]byte, []int) { return fileDescriptor", g.file.index, ", []int{", strings.Join(indexes, ", "), "} }") if enum.file.GetPackage() == "google.protobuf" && enum.GetName() == "NullValue" { g.P("func (", ccTypeName, `) XXX_WellKnownType() string { return "`, enum.GetName(), `" }`) } g.P() } // The tag is a string like "varint,2,opt,name=fieldname,def=7" that // identifies details of the field for the protocol buffer marshaling and unmarshaling // code. The fields are: // wire encoding // protocol tag number // opt,req,rep for optional, required, or repeated // packed whether the encoding is "packed" (optional; repeated primitives only) // name= the original declared name // enum= the name of the enum type if it is an enum-typed field. // proto3 if this field is in a proto3 message // def= string representation of the default value, if any. // The default value must be in a representation that can be used at run-time // to generate the default value. Thus bools become 0 and 1, for instance. func (g *Generator) goTag(message *Descriptor, field *descriptor.FieldDescriptorProto, wiretype string) string { optrepreq := "" switch { case isOptional(field): optrepreq = "opt" case isRequired(field): optrepreq = "req" case isRepeated(field): optrepreq = "rep" } var defaultValue string if dv := field.DefaultValue; dv != nil { // set means an explicit default defaultValue = *dv // Some types need tweaking. switch *field.Type { case descriptor.FieldDescriptorProto_TYPE_BOOL: if defaultValue == "true" { defaultValue = "1" } else { defaultValue = "0" } case descriptor.FieldDescriptorProto_TYPE_STRING, descriptor.FieldDescriptorProto_TYPE_BYTES: // Nothing to do. Quoting is done for the whole tag. case descriptor.FieldDescriptorProto_TYPE_ENUM: // For enums we need to provide the integer constant. obj := g.ObjectNamed(field.GetTypeName()) if id, ok := obj.(*ImportedDescriptor); ok { // It is an enum that was publicly imported. // We need the underlying type. obj = id.o } enum, ok := obj.(*EnumDescriptor) if !ok { log.Printf("obj is a %T", obj) if id, ok := obj.(*ImportedDescriptor); ok { log.Printf("id.o is a %T", id.o) } g.Fail("unknown enum type", CamelCaseSlice(obj.TypeName())) } defaultValue = enum.integerValueAsString(defaultValue) } defaultValue = ",def=" + defaultValue } enum := "" if *field.Type == descriptor.FieldDescriptorProto_TYPE_ENUM { // We avoid using obj.PackageName(), because we want to use the // original (proto-world) package name. obj := g.ObjectNamed(field.GetTypeName()) if id, ok := obj.(*ImportedDescriptor); ok { obj = id.o } enum = ",enum=" if pkg := obj.File().GetPackage(); pkg != "" { enum += pkg + "." } enum += CamelCaseSlice(obj.TypeName()) } packed := "" if field.Options != nil && field.Options.GetPacked() { packed = ",packed" } fieldName := field.GetName() name := fieldName if *field.Type == descriptor.FieldDescriptorProto_TYPE_GROUP { // We must use the type name for groups instead of // the field name to preserve capitalization. // type_name in FieldDescriptorProto is fully-qualified, // but we only want the local part. name = *field.TypeName if i := strings.LastIndex(name, "."); i >= 0 { name = name[i+1:] } } if json := field.GetJsonName(); json != "" && json != name { // TODO: escaping might be needed, in which case // perhaps this should be in its own "json" tag. name += ",json=" + json } name = ",name=" + name if message.proto3() { // We only need the extra tag for []byte fields; // no need to add noise for the others. if *field.Type == descriptor.FieldDescriptorProto_TYPE_BYTES { name += ",proto3" } } oneof := "" if field.OneofIndex != nil { oneof = ",oneof" } return strconv.Quote(fmt.Sprintf("%s,%d,%s%s%s%s%s%s", wiretype, field.GetNumber(), optrepreq, packed, name, enum, oneof, defaultValue)) } func needsStar(typ descriptor.FieldDescriptorProto_Type) bool { switch typ { case descriptor.FieldDescriptorProto_TYPE_GROUP: return false case descriptor.FieldDescriptorProto_TYPE_MESSAGE: return false case descriptor.FieldDescriptorProto_TYPE_BYTES: return false } return true } // TypeName is the printed name appropriate for an item. If the object is in the current file, // TypeName drops the package name and underscores the rest. // Otherwise the object is from another package; and the result is the underscored // package name followed by the item name. // The result always has an initial capital. func (g *Generator) TypeName(obj Object) string { return g.DefaultPackageName(obj) + CamelCaseSlice(obj.TypeName()) } // TypeNameWithPackage is like TypeName, but always includes the package // name even if the object is in our own package. func (g *Generator) TypeNameWithPackage(obj Object) string { return obj.PackageName() + CamelCaseSlice(obj.TypeName()) } // GoType returns a string representing the type name, and the wire type func (g *Generator) GoType(message *Descriptor, field *descriptor.FieldDescriptorProto) (typ string, wire string) { // TODO: Options. switch *field.Type { case descriptor.FieldDescriptorProto_TYPE_DOUBLE: typ, wire = "float64", "fixed64" case descriptor.FieldDescriptorProto_TYPE_FLOAT: typ, wire = "float32", "fixed32" case descriptor.FieldDescriptorProto_TYPE_INT64: typ, wire = "int64", "varint" case descriptor.FieldDescriptorProto_TYPE_UINT64: typ, wire = "uint64", "varint" case descriptor.FieldDescriptorProto_TYPE_INT32: typ, wire = "int32", "varint" case descriptor.FieldDescriptorProto_TYPE_UINT32: typ, wire = "uint32", "varint" case descriptor.FieldDescriptorProto_TYPE_FIXED64: typ, wire = "uint64", "fixed64" case descriptor.FieldDescriptorProto_TYPE_FIXED32: typ, wire = "uint32", "fixed32" case descriptor.FieldDescriptorProto_TYPE_BOOL: typ, wire = "bool", "varint" case descriptor.FieldDescriptorProto_TYPE_STRING: typ, wire = "string", "bytes" case descriptor.FieldDescriptorProto_TYPE_GROUP: desc := g.ObjectNamed(field.GetTypeName()) typ, wire = "*"+g.TypeName(desc), "group" case descriptor.FieldDescriptorProto_TYPE_MESSAGE: desc := g.ObjectNamed(field.GetTypeName()) typ, wire = "*"+g.TypeName(desc), "bytes" case descriptor.FieldDescriptorProto_TYPE_BYTES: typ, wire = "[]byte", "bytes" case descriptor.FieldDescriptorProto_TYPE_ENUM: desc := g.ObjectNamed(field.GetTypeName()) typ, wire = g.TypeName(desc), "varint" case descriptor.FieldDescriptorProto_TYPE_SFIXED32: typ, wire = "int32", "fixed32" case descriptor.FieldDescriptorProto_TYPE_SFIXED64: typ, wire = "int64", "fixed64" case descriptor.FieldDescriptorProto_TYPE_SINT32: typ, wire = "int32", "zigzag32" case descriptor.FieldDescriptorProto_TYPE_SINT64: typ, wire = "int64", "zigzag64" default: g.Fail("unknown type for", field.GetName()) } if isRepeated(field) { typ = "[]" + typ } else if message != nil && message.proto3() { return } else if field.OneofIndex != nil && message != nil { return } else if needsStar(*field.Type) { typ = "*" + typ } return } func (g *Generator) RecordTypeUse(t string) { if obj, ok := g.typeNameToObject[t]; ok { // Call ObjectNamed to get the true object to record the use. obj = g.ObjectNamed(t) g.usedPackages[obj.PackageName()] = true } } // Method names that may be generated. Fields with these names get an // underscore appended. var methodNames = [...]string{ "Reset", "String", "ProtoMessage", "Marshal", "Unmarshal", "ExtensionRangeArray", "ExtensionMap", "Descriptor", } // Names of messages in the `google.protobuf` package for which // we will generate XXX_WellKnownType methods. var wellKnownTypes = map[string]bool{ "Any": true, "Duration": true, "Empty": true, "Struct": true, "Timestamp": true, "Value": true, "ListValue": true, "DoubleValue": true, "FloatValue": true, "Int64Value": true, "UInt64Value": true, "Int32Value": true, "UInt32Value": true, "BoolValue": true, "StringValue": true, "BytesValue": true, } // Generate the type and default constant definitions for this Descriptor. func (g *Generator) generateMessage(message *Descriptor) { // The full type name typeName := message.TypeName() // The full type name, CamelCased. ccTypeName := CamelCaseSlice(typeName) usedNames := make(map[string]bool) for _, n := range methodNames { usedNames[n] = true } fieldNames := make(map[*descriptor.FieldDescriptorProto]string) fieldGetterNames := make(map[*descriptor.FieldDescriptorProto]string) fieldTypes := make(map[*descriptor.FieldDescriptorProto]string) mapFieldTypes := make(map[*descriptor.FieldDescriptorProto]string) oneofFieldName := make(map[int32]string) // indexed by oneof_index field of FieldDescriptorProto oneofDisc := make(map[int32]string) // name of discriminator method oneofTypeName := make(map[*descriptor.FieldDescriptorProto]string) // without star oneofInsertPoints := make(map[int32]int) // oneof_index => offset of g.Buffer g.PrintComments(message.path) g.P("type ", ccTypeName, " struct {") g.In() // allocNames finds a conflict-free variation of the given strings, // consistently mutating their suffixes. // It returns the same number of strings. allocNames := func(ns ...string) []string { Loop: for { for _, n := range ns { if usedNames[n] { for i := range ns { ns[i] += "_" } continue Loop } } for _, n := range ns { usedNames[n] = true } return ns } } for i, field := range message.Field { // Allocate the getter and the field at the same time so name // collisions create field/method consistent names. // TODO: This allocation occurs based on the order of the fields // in the proto file, meaning that a change in the field // ordering can change generated Method/Field names. base := CamelCase(*field.Name) ns := allocNames(base, "Get"+base) fieldName, fieldGetterName := ns[0], ns[1] typename, wiretype := g.GoType(message, field) jsonName := *field.Name tag := fmt.Sprintf("protobuf:%s json:%q", g.goTag(message, field, wiretype), jsonName+",omitempty") fieldNames[field] = fieldName fieldGetterNames[field] = fieldGetterName oneof := field.OneofIndex != nil if oneof && oneofFieldName[*field.OneofIndex] == "" { odp := message.OneofDecl[int(*field.OneofIndex)] fname := allocNames(CamelCase(odp.GetName()))[0] // This is the first field of a oneof we haven't seen before. // Generate the union field. com := g.PrintComments(fmt.Sprintf("%s,%d,%d", message.path, messageOneofPath, *field.OneofIndex)) if com { g.P("//") } g.P("// Types that are valid to be assigned to ", fname, ":") // Generate the rest of this comment later, // when we've computed any disambiguation. oneofInsertPoints[*field.OneofIndex] = g.Buffer.Len() dname := "is" + ccTypeName + "_" + fname oneofFieldName[*field.OneofIndex] = fname oneofDisc[*field.OneofIndex] = dname tag := `protobuf_oneof:"` + odp.GetName() + `"` g.P(fname, " ", dname, " `", tag, "`") } if *field.Type == descriptor.FieldDescriptorProto_TYPE_MESSAGE { desc := g.ObjectNamed(field.GetTypeName()) if d, ok := desc.(*Descriptor); ok && d.GetOptions().GetMapEntry() { // Figure out the Go types and tags for the key and value types. keyField, valField := d.Field[0], d.Field[1] keyType, keyWire := g.GoType(d, keyField) valType, valWire := g.GoType(d, valField) keyTag, valTag := g.goTag(d, keyField, keyWire), g.goTag(d, valField, valWire) // We don't use stars, except for message-typed values. // Message and enum types are the only two possibly foreign types used in maps, // so record their use. They are not permitted as map keys. keyType = strings.TrimPrefix(keyType, "*") switch *valField.Type { case descriptor.FieldDescriptorProto_TYPE_ENUM: valType = strings.TrimPrefix(valType, "*") g.RecordTypeUse(valField.GetTypeName()) case descriptor.FieldDescriptorProto_TYPE_MESSAGE: g.RecordTypeUse(valField.GetTypeName()) default: valType = strings.TrimPrefix(valType, "*") } typename = fmt.Sprintf("map[%s]%s", keyType, valType) mapFieldTypes[field] = typename // record for the getter generation tag += fmt.Sprintf(" protobuf_key:%s protobuf_val:%s", keyTag, valTag) } } fieldTypes[field] = typename if oneof { tname := ccTypeName + "_" + fieldName // It is possible for this to collide with a message or enum // nested in this message. Check for collisions. for { ok := true for _, desc := range message.nested { if CamelCaseSlice(desc.TypeName()) == tname { ok = false break } } for _, enum := range message.enums { if CamelCaseSlice(enum.TypeName()) == tname { ok = false break } } if !ok { tname += "_" continue } break } oneofTypeName[field] = tname continue } g.PrintComments(fmt.Sprintf("%s,%d,%d", message.path, messageFieldPath, i)) g.P(fieldName, "\t", typename, "\t`", tag, "`") g.RecordTypeUse(field.GetTypeName()) } if len(message.ExtensionRange) > 0 { g.P("XXX_extensions\t\tmap[int32]", g.Pkg["proto"], ".Extension `json:\"-\"`") } if !message.proto3() { g.P("XXX_unrecognized\t[]byte `json:\"-\"`") } g.Out() g.P("}") // Update g.Buffer to list valid oneof types. // We do this down here, after we've disambiguated the oneof type names. // We go in reverse order of insertion point to avoid invalidating offsets. for oi := int32(len(message.OneofDecl)); oi >= 0; oi-- { ip := oneofInsertPoints[oi] all := g.Buffer.Bytes() rem := all[ip:] g.Buffer = bytes.NewBuffer(all[:ip:ip]) // set cap so we don't scribble on rem for _, field := range message.Field { if field.OneofIndex == nil || *field.OneofIndex != oi { continue } g.P("//\t*", oneofTypeName[field]) } g.Buffer.Write(rem) } // Reset, String and ProtoMessage methods. g.P("func (m *", ccTypeName, ") Reset() { *m = ", ccTypeName, "{} }") g.P("func (m *", ccTypeName, ") String() string { return ", g.Pkg["proto"], ".CompactTextString(m) }") g.P("func (*", ccTypeName, ") ProtoMessage() {}") var indexes []string for m := message; m != nil; m = m.parent { indexes = append([]string{strconv.Itoa(m.index)}, indexes...) } g.P("func (*", ccTypeName, ") Descriptor() ([]byte, []int) { return fileDescriptor", g.file.index, ", []int{", strings.Join(indexes, ", "), "} }") // TODO: Revisit the decision to use a XXX_WellKnownType method // if we change proto.MessageName to work with multiple equivalents. if message.file.GetPackage() == "google.protobuf" && wellKnownTypes[message.GetName()] { g.P("func (*", ccTypeName, `) XXX_WellKnownType() string { return "`, message.GetName(), `" }`) } // Extension support methods var hasExtensions, isMessageSet bool if len(message.ExtensionRange) > 0 { hasExtensions = true // message_set_wire_format only makes sense when extensions are defined. if opts := message.Options; opts != nil && opts.GetMessageSetWireFormat() { isMessageSet = true g.P() g.P("func (m *", ccTypeName, ") Marshal() ([]byte, error) {") g.In() g.P("return ", g.Pkg["proto"], ".MarshalMessageSet(m.ExtensionMap())") g.Out() g.P("}") g.P("func (m *", ccTypeName, ") Unmarshal(buf []byte) error {") g.In() g.P("return ", g.Pkg["proto"], ".UnmarshalMessageSet(buf, m.ExtensionMap())") g.Out() g.P("}") g.P("func (m *", ccTypeName, ") MarshalJSON() ([]byte, error) {") g.In() g.P("return ", g.Pkg["proto"], ".MarshalMessageSetJSON(m.XXX_extensions)") g.Out() g.P("}") g.P("func (m *", ccTypeName, ") UnmarshalJSON(buf []byte) error {") g.In() g.P("return ", g.Pkg["proto"], ".UnmarshalMessageSetJSON(buf, m.XXX_extensions)") g.Out() g.P("}") g.P("// ensure ", ccTypeName, " satisfies proto.Marshaler and proto.Unmarshaler") g.P("var _ ", g.Pkg["proto"], ".Marshaler = (*", ccTypeName, ")(nil)") g.P("var _ ", g.Pkg["proto"], ".Unmarshaler = (*", ccTypeName, ")(nil)") } g.P() g.P("var extRange_", ccTypeName, " = []", g.Pkg["proto"], ".ExtensionRange{") g.In() for _, r := range message.ExtensionRange { end := fmt.Sprint(*r.End - 1) // make range inclusive on both ends g.P("{", r.Start, ", ", end, "},") } g.Out() g.P("}") g.P("func (*", ccTypeName, ") ExtensionRangeArray() []", g.Pkg["proto"], ".ExtensionRange {") g.In() g.P("return extRange_", ccTypeName) g.Out() g.P("}") g.P("func (m *", ccTypeName, ") ExtensionMap() map[int32]", g.Pkg["proto"], ".Extension {") g.In() g.P("if m.XXX_extensions == nil {") g.In() g.P("m.XXX_extensions = make(map[int32]", g.Pkg["proto"], ".Extension)") g.Out() g.P("}") g.P("return m.XXX_extensions") g.Out() g.P("}") } // Default constants defNames := make(map[*descriptor.FieldDescriptorProto]string) for _, field := range message.Field { def := field.GetDefaultValue() if def == "" { continue } fieldname := "Default_" + ccTypeName + "_" + CamelCase(*field.Name) defNames[field] = fieldname typename, _ := g.GoType(message, field) if typename[0] == '*' { typename = typename[1:] } kind := "const " switch { case typename == "bool": case typename == "string": def = strconv.Quote(def) case typename == "[]byte": def = "[]byte(" + strconv.Quote(def) + ")" kind = "var " case def == "inf", def == "-inf", def == "nan": // These names are known to, and defined by, the protocol language. switch def { case "inf": def = "math.Inf(1)" case "-inf": def = "math.Inf(-1)" case "nan": def = "math.NaN()" } if *field.Type == descriptor.FieldDescriptorProto_TYPE_FLOAT { def = "float32(" + def + ")" } kind = "var " case *field.Type == descriptor.FieldDescriptorProto_TYPE_ENUM: // Must be an enum. Need to construct the prefixed name. obj := g.ObjectNamed(field.GetTypeName()) var enum *EnumDescriptor if id, ok := obj.(*ImportedDescriptor); ok { // The enum type has been publicly imported. enum, _ = id.o.(*EnumDescriptor) } else { enum, _ = obj.(*EnumDescriptor) } if enum == nil { log.Printf("don't know how to generate constant for %s", fieldname) continue } def = g.DefaultPackageName(obj) + enum.prefix() + def } g.P(kind, fieldname, " ", typename, " = ", def) g.file.addExport(message, constOrVarSymbol{fieldname, kind, ""}) } g.P() // Oneof per-field types, discriminants and getters. // // Generate unexported named types for the discriminant interfaces. // We shouldn't have to do this, but there was (~19 Aug 2015) a compiler/linker bug // that was triggered by using anonymous interfaces here. // TODO: Revisit this and consider reverting back to anonymous interfaces. for oi := range message.OneofDecl { dname := oneofDisc[int32(oi)] g.P("type ", dname, " interface { ", dname, "() }") } g.P() for _, field := range message.Field { if field.OneofIndex == nil { continue } _, wiretype := g.GoType(message, field) tag := "protobuf:" + g.goTag(message, field, wiretype) g.P("type ", oneofTypeName[field], " struct{ ", fieldNames[field], " ", fieldTypes[field], " `", tag, "` }") g.RecordTypeUse(field.GetTypeName()) } g.P() for _, field := range message.Field { if field.OneofIndex == nil { continue } g.P("func (*", oneofTypeName[field], ") ", oneofDisc[*field.OneofIndex], "() {}") } g.P() for oi := range message.OneofDecl { fname := oneofFieldName[int32(oi)] g.P("func (m *", ccTypeName, ") Get", fname, "() ", oneofDisc[int32(oi)], " {") g.P("if m != nil { return m.", fname, " }") g.P("return nil") g.P("}") } g.P() // Field getters var getters []getterSymbol for _, field := range message.Field { oneof := field.OneofIndex != nil fname := fieldNames[field] typename, _ := g.GoType(message, field) if t, ok := mapFieldTypes[field]; ok { typename = t } mname := fieldGetterNames[field] star := "" if needsStar(*field.Type) && typename[0] == '*' { typename = typename[1:] star = "*" } // In proto3, only generate getters for message fields and oneof fields. if message.proto3() && *field.Type != descriptor.FieldDescriptorProto_TYPE_MESSAGE && !oneof { continue } // Only export getter symbols for basic types, // and for messages and enums in the same package. // Groups are not exported. // Foreign types can't be hoisted through a public import because // the importer may not already be importing the defining .proto. // As an example, imagine we have an import tree like this: // A.proto -> B.proto -> C.proto // If A publicly imports B, we need to generate the getters from B in A's output, // but if one such getter returns something from C then we cannot do that // because A is not importing C already. var getter, genType bool switch *field.Type { case descriptor.FieldDescriptorProto_TYPE_GROUP: getter = false case descriptor.FieldDescriptorProto_TYPE_MESSAGE, descriptor.FieldDescriptorProto_TYPE_ENUM: // Only export getter if its return type is in this package. getter = g.ObjectNamed(field.GetTypeName()).PackageName() == message.PackageName() genType = true default: getter = true } if getter { getters = append(getters, getterSymbol{ name: mname, typ: typename, typeName: field.GetTypeName(), genType: genType, }) } g.P("func (m *", ccTypeName, ") "+mname+"() "+typename+" {") g.In() def, hasDef := defNames[field] typeDefaultIsNil := false // whether this field type's default value is a literal nil unless specified switch *field.Type { case descriptor.FieldDescriptorProto_TYPE_BYTES: typeDefaultIsNil = !hasDef case descriptor.FieldDescriptorProto_TYPE_GROUP, descriptor.FieldDescriptorProto_TYPE_MESSAGE: typeDefaultIsNil = true } if isRepeated(field) { typeDefaultIsNil = true } if typeDefaultIsNil && !oneof { // A bytes field with no explicit default needs less generated code, // as does a message or group field, or a repeated field. g.P("if m != nil {") g.In() g.P("return m." + fname) g.Out() g.P("}") g.P("return nil") g.Out() g.P("}") g.P() continue } if !oneof { g.P("if m != nil && m." + fname + " != nil {") g.In() g.P("return " + star + "m." + fname) g.Out() g.P("}") } else { uname := oneofFieldName[*field.OneofIndex] tname := oneofTypeName[field] g.P("if x, ok := m.Get", uname, "().(*", tname, "); ok {") g.P("return x.", fname) g.P("}") } if hasDef { if *field.Type != descriptor.FieldDescriptorProto_TYPE_BYTES { g.P("return " + def) } else { // The default is a []byte var. // Make a copy when returning it to be safe. g.P("return append([]byte(nil), ", def, "...)") } } else { switch *field.Type { case descriptor.FieldDescriptorProto_TYPE_BOOL: g.P("return false") case descriptor.FieldDescriptorProto_TYPE_STRING: g.P(`return ""`) case descriptor.FieldDescriptorProto_TYPE_GROUP, descriptor.FieldDescriptorProto_TYPE_MESSAGE, descriptor.FieldDescriptorProto_TYPE_BYTES: // This is only possible for oneof fields. g.P("return nil") case descriptor.FieldDescriptorProto_TYPE_ENUM: // The default default for an enum is the first value in the enum, // not zero. obj := g.ObjectNamed(field.GetTypeName()) var enum *EnumDescriptor if id, ok := obj.(*ImportedDescriptor); ok { // The enum type has been publicly imported. enum, _ = id.o.(*EnumDescriptor) } else { enum, _ = obj.(*EnumDescriptor) } if enum == nil { log.Printf("don't know how to generate getter for %s", field.GetName()) continue } if len(enum.Value) == 0 { g.P("return 0 // empty enum") } else { first := enum.Value[0].GetName() g.P("return ", g.DefaultPackageName(obj)+enum.prefix()+first) } default: g.P("return 0") } } g.Out() g.P("}") g.P() } if !message.group { ms := &messageSymbol{ sym: ccTypeName, hasExtensions: hasExtensions, isMessageSet: isMessageSet, hasOneof: len(message.OneofDecl) > 0, getters: getters, } g.file.addExport(message, ms) } // Oneof functions if len(message.OneofDecl) > 0 { fieldWire := make(map[*descriptor.FieldDescriptorProto]string) // method enc := "_" + ccTypeName + "_OneofMarshaler" dec := "_" + ccTypeName + "_OneofUnmarshaler" size := "_" + ccTypeName + "_OneofSizer" encSig := "(msg " + g.Pkg["proto"] + ".Message, b *" + g.Pkg["proto"] + ".Buffer) error" decSig := "(msg " + g.Pkg["proto"] + ".Message, tag, wire int, b *" + g.Pkg["proto"] + ".Buffer) (bool, error)" sizeSig := "(msg " + g.Pkg["proto"] + ".Message) (n int)" g.P("// XXX_OneofFuncs is for the internal use of the proto package.") g.P("func (*", ccTypeName, ") XXX_OneofFuncs() (func", encSig, ", func", decSig, ", func", sizeSig, ", []interface{}) {") g.P("return ", enc, ", ", dec, ", ", size, ", []interface{}{") for _, field := range message.Field { if field.OneofIndex == nil { continue } g.P("(*", oneofTypeName[field], ")(nil),") } g.P("}") g.P("}") g.P() // marshaler g.P("func ", enc, encSig, " {") g.P("m := msg.(*", ccTypeName, ")") for oi, odp := range message.OneofDecl { g.P("// ", odp.GetName()) fname := oneofFieldName[int32(oi)] g.P("switch x := m.", fname, ".(type) {") for _, field := range message.Field { if field.OneofIndex == nil || int(*field.OneofIndex) != oi { continue } g.P("case *", oneofTypeName[field], ":") var wire, pre, post string val := "x." + fieldNames[field] // overridden for TYPE_BOOL canFail := false // only TYPE_MESSAGE and TYPE_GROUP can fail switch *field.Type { case descriptor.FieldDescriptorProto_TYPE_DOUBLE: wire = "WireFixed64" pre = "b.EncodeFixed64(" + g.Pkg["math"] + ".Float64bits(" post = "))" case descriptor.FieldDescriptorProto_TYPE_FLOAT: wire = "WireFixed32" pre = "b.EncodeFixed32(uint64(" + g.Pkg["math"] + ".Float32bits(" post = ")))" case descriptor.FieldDescriptorProto_TYPE_INT64, descriptor.FieldDescriptorProto_TYPE_UINT64: wire = "WireVarint" pre, post = "b.EncodeVarint(uint64(", "))" case descriptor.FieldDescriptorProto_TYPE_INT32, descriptor.FieldDescriptorProto_TYPE_UINT32, descriptor.FieldDescriptorProto_TYPE_ENUM: wire = "WireVarint" pre, post = "b.EncodeVarint(uint64(", "))" case descriptor.FieldDescriptorProto_TYPE_FIXED64, descriptor.FieldDescriptorProto_TYPE_SFIXED64: wire = "WireFixed64" pre, post = "b.EncodeFixed64(uint64(", "))" case descriptor.FieldDescriptorProto_TYPE_FIXED32, descriptor.FieldDescriptorProto_TYPE_SFIXED32: wire = "WireFixed32" pre, post = "b.EncodeFixed32(uint64(", "))" case descriptor.FieldDescriptorProto_TYPE_BOOL: // bool needs special handling. g.P("t := uint64(0)") g.P("if ", val, " { t = 1 }") val = "t" wire = "WireVarint" pre, post = "b.EncodeVarint(", ")" case descriptor.FieldDescriptorProto_TYPE_STRING: wire = "WireBytes" pre, post = "b.EncodeStringBytes(", ")" case descriptor.FieldDescriptorProto_TYPE_GROUP: wire = "WireStartGroup" pre, post = "b.Marshal(", ")" canFail = true case descriptor.FieldDescriptorProto_TYPE_MESSAGE: wire = "WireBytes" pre, post = "b.EncodeMessage(", ")" canFail = true case descriptor.FieldDescriptorProto_TYPE_BYTES: wire = "WireBytes" pre, post = "b.EncodeRawBytes(", ")" case descriptor.FieldDescriptorProto_TYPE_SINT32: wire = "WireVarint" pre, post = "b.EncodeZigzag32(uint64(", "))" case descriptor.FieldDescriptorProto_TYPE_SINT64: wire = "WireVarint" pre, post = "b.EncodeZigzag64(uint64(", "))" default: g.Fail("unhandled oneof field type ", field.Type.String()) } fieldWire[field] = wire g.P("b.EncodeVarint(", field.Number, "<<3|", g.Pkg["proto"], ".", wire, ")") if !canFail { g.P(pre, val, post) } else { g.P("if err := ", pre, val, post, "; err != nil {") g.P("return err") g.P("}") } if *field.Type == descriptor.FieldDescriptorProto_TYPE_GROUP { g.P("b.EncodeVarint(", field.Number, "<<3|", g.Pkg["proto"], ".WireEndGroup)") } } g.P("case nil:") g.P("default: return ", g.Pkg["fmt"], `.Errorf("`, ccTypeName, ".", fname, ` has unexpected type %T", x)`) g.P("}") } g.P("return nil") g.P("}") g.P() // unmarshaler g.P("func ", dec, decSig, " {") g.P("m := msg.(*", ccTypeName, ")") g.P("switch tag {") for _, field := range message.Field { if field.OneofIndex == nil { continue } odp := message.OneofDecl[int(*field.OneofIndex)] g.P("case ", field.Number, ": // ", odp.GetName(), ".", *field.Name) g.P("if wire != ", g.Pkg["proto"], ".", fieldWire[field], " {") g.P("return true, ", g.Pkg["proto"], ".ErrInternalBadWireType") g.P("}") lhs := "x, err" // overridden for TYPE_MESSAGE and TYPE_GROUP var dec, cast, cast2 string switch *field.Type { case descriptor.FieldDescriptorProto_TYPE_DOUBLE: dec, cast = "b.DecodeFixed64()", g.Pkg["math"]+".Float64frombits" case descriptor.FieldDescriptorProto_TYPE_FLOAT: dec, cast, cast2 = "b.DecodeFixed32()", "uint32", g.Pkg["math"]+".Float32frombits" case descriptor.FieldDescriptorProto_TYPE_INT64: dec, cast = "b.DecodeVarint()", "int64" case descriptor.FieldDescriptorProto_TYPE_UINT64: dec = "b.DecodeVarint()" case descriptor.FieldDescriptorProto_TYPE_INT32: dec, cast = "b.DecodeVarint()", "int32" case descriptor.FieldDescriptorProto_TYPE_FIXED64: dec = "b.DecodeFixed64()" case descriptor.FieldDescriptorProto_TYPE_FIXED32: dec, cast = "b.DecodeFixed32()", "uint32" case descriptor.FieldDescriptorProto_TYPE_BOOL: dec = "b.DecodeVarint()" // handled specially below case descriptor.FieldDescriptorProto_TYPE_STRING: dec = "b.DecodeStringBytes()" case descriptor.FieldDescriptorProto_TYPE_GROUP: g.P("msg := new(", fieldTypes[field][1:], ")") // drop star lhs = "err" dec = "b.DecodeGroup(msg)" // handled specially below case descriptor.FieldDescriptorProto_TYPE_MESSAGE: g.P("msg := new(", fieldTypes[field][1:], ")") // drop star lhs = "err" dec = "b.DecodeMessage(msg)" // handled specially below case descriptor.FieldDescriptorProto_TYPE_BYTES: dec = "b.DecodeRawBytes(true)" case descriptor.FieldDescriptorProto_TYPE_UINT32: dec, cast = "b.DecodeVarint()", "uint32" case descriptor.FieldDescriptorProto_TYPE_ENUM: dec, cast = "b.DecodeVarint()", fieldTypes[field] case descriptor.FieldDescriptorProto_TYPE_SFIXED32: dec, cast = "b.DecodeFixed32()", "int32" case descriptor.FieldDescriptorProto_TYPE_SFIXED64: dec, cast = "b.DecodeFixed64()", "int64" case descriptor.FieldDescriptorProto_TYPE_SINT32: dec, cast = "b.DecodeZigzag32()", "int32" case descriptor.FieldDescriptorProto_TYPE_SINT64: dec, cast = "b.DecodeZigzag64()", "int64" default: g.Fail("unhandled oneof field type ", field.Type.String()) } g.P(lhs, " := ", dec) val := "x" if cast != "" { val = cast + "(" + val + ")" } if cast2 != "" { val = cast2 + "(" + val + ")" } switch *field.Type { case descriptor.FieldDescriptorProto_TYPE_BOOL: val += " != 0" case descriptor.FieldDescriptorProto_TYPE_GROUP, descriptor.FieldDescriptorProto_TYPE_MESSAGE: val = "msg" } g.P("m.", oneofFieldName[*field.OneofIndex], " = &", oneofTypeName[field], "{", val, "}") g.P("return true, err") } g.P("default: return false, nil") g.P("}") g.P("}") g.P() // sizer g.P("func ", size, sizeSig, " {") g.P("m := msg.(*", ccTypeName, ")") for oi, odp := range message.OneofDecl { g.P("// ", odp.GetName()) fname := oneofFieldName[int32(oi)] g.P("switch x := m.", fname, ".(type) {") for _, field := range message.Field { if field.OneofIndex == nil || int(*field.OneofIndex) != oi { continue } g.P("case *", oneofTypeName[field], ":") val := "x." + fieldNames[field] var wire, varint, fixed string switch *field.Type { case descriptor.FieldDescriptorProto_TYPE_DOUBLE: wire = "WireFixed64" fixed = "8" case descriptor.FieldDescriptorProto_TYPE_FLOAT: wire = "WireFixed32" fixed = "4" case descriptor.FieldDescriptorProto_TYPE_INT64, descriptor.FieldDescriptorProto_TYPE_UINT64, descriptor.FieldDescriptorProto_TYPE_INT32, descriptor.FieldDescriptorProto_TYPE_UINT32, descriptor.FieldDescriptorProto_TYPE_ENUM: wire = "WireVarint" varint = val case descriptor.FieldDescriptorProto_TYPE_FIXED64, descriptor.FieldDescriptorProto_TYPE_SFIXED64: wire = "WireFixed64" fixed = "8" case descriptor.FieldDescriptorProto_TYPE_FIXED32, descriptor.FieldDescriptorProto_TYPE_SFIXED32: wire = "WireFixed32" fixed = "4" case descriptor.FieldDescriptorProto_TYPE_BOOL: wire = "WireVarint" fixed = "1" case descriptor.FieldDescriptorProto_TYPE_STRING: wire = "WireBytes" fixed = "len(" + val + ")" varint = fixed case descriptor.FieldDescriptorProto_TYPE_GROUP: wire = "WireStartGroup" fixed = g.Pkg["proto"] + ".Size(" + val + ")" case descriptor.FieldDescriptorProto_TYPE_MESSAGE: wire = "WireBytes" g.P("s := ", g.Pkg["proto"], ".Size(", val, ")") fixed = "s" varint = fixed case descriptor.FieldDescriptorProto_TYPE_BYTES: wire = "WireBytes" fixed = "len(" + val + ")" varint = fixed case descriptor.FieldDescriptorProto_TYPE_SINT32: wire = "WireVarint" varint = "(uint32(" + val + ") << 1) ^ uint32((int32(" + val + ") >> 31))" case descriptor.FieldDescriptorProto_TYPE_SINT64: wire = "WireVarint" varint = "uint64(" + val + " << 1) ^ uint64((int64(" + val + ") >> 63))" default: g.Fail("unhandled oneof field type ", field.Type.String()) } g.P("n += ", g.Pkg["proto"], ".SizeVarint(", field.Number, "<<3|", g.Pkg["proto"], ".", wire, ")") if varint != "" { g.P("n += ", g.Pkg["proto"], ".SizeVarint(uint64(", varint, "))") } if fixed != "" { g.P("n += ", fixed) } if *field.Type == descriptor.FieldDescriptorProto_TYPE_GROUP { g.P("n += ", g.Pkg["proto"], ".SizeVarint(", field.Number, "<<3|", g.Pkg["proto"], ".WireEndGroup)") } } g.P("case nil:") g.P("default:") g.P("panic(", g.Pkg["fmt"], ".Sprintf(\"proto: unexpected type %T in oneof\", x))") g.P("}") } g.P("return n") g.P("}") g.P() } for _, ext := range message.ext { g.generateExtension(ext) } fullName := strings.Join(message.TypeName(), ".") if g.file.Package != nil { fullName = *g.file.Package + "." + fullName } g.addInitf("%s.RegisterType((*%s)(nil), %q)", g.Pkg["proto"], ccTypeName, fullName) } func (g *Generator) generateExtension(ext *ExtensionDescriptor) { ccTypeName := ext.DescName() extObj := g.ObjectNamed(*ext.Extendee) var extDesc *Descriptor if id, ok := extObj.(*ImportedDescriptor); ok { // This is extending a publicly imported message. // We need the underlying type for goTag. extDesc = id.o.(*Descriptor) } else { extDesc = extObj.(*Descriptor) } extendedType := "*" + g.TypeName(extObj) // always use the original field := ext.FieldDescriptorProto fieldType, wireType := g.GoType(ext.parent, field) tag := g.goTag(extDesc, field, wireType) g.RecordTypeUse(*ext.Extendee) if n := ext.FieldDescriptorProto.TypeName; n != nil { // foreign extension type g.RecordTypeUse(*n) } typeName := ext.TypeName() // Special case for proto2 message sets: If this extension is extending // proto2_bridge.MessageSet, and its final name component is "message_set_extension", // then drop that last component. mset := false if extendedType == "*proto2_bridge.MessageSet" && typeName[len(typeName)-1] == "message_set_extension" { typeName = typeName[:len(typeName)-1] mset = true } // For text formatting, the package must be exactly what the .proto file declares, // ignoring overrides such as the go_package option, and with no dot/underscore mapping. extName := strings.Join(typeName, ".") if g.file.Package != nil { extName = *g.file.Package + "." + extName } g.P("var ", ccTypeName, " = &", g.Pkg["proto"], ".ExtensionDesc{") g.In() g.P("ExtendedType: (", extendedType, ")(nil),") g.P("ExtensionType: (", fieldType, ")(nil),") g.P("Field: ", field.Number, ",") g.P(`Name: "`, extName, `",`) g.P("Tag: ", tag, ",") g.Out() g.P("}") g.P() if mset { // Generate a bit more code to register with message_set.go. g.addInitf("%s.RegisterMessageSetType((%s)(nil), %d, %q)", g.Pkg["proto"], fieldType, *field.Number, extName) } g.file.addExport(ext, constOrVarSymbol{ccTypeName, "var", ""}) } func (g *Generator) generateInitFunction() { for _, enum := range g.file.enum { g.generateEnumRegistration(enum) } for _, d := range g.file.desc { for _, ext := range d.ext { g.generateExtensionRegistration(ext) } } for _, ext := range g.file.ext { g.generateExtensionRegistration(ext) } if len(g.init) == 0 { return } g.P("func init() {") g.In() for _, l := range g.init { g.P(l) } g.Out() g.P("}") g.init = nil } func (g *Generator) generateFileDescriptor(file *FileDescriptor) { // Make a copy and trim source_code_info data. // TODO: Trim this more when we know exactly what we need. pb := proto.Clone(file.FileDescriptorProto).(*descriptor.FileDescriptorProto) pb.SourceCodeInfo = nil b, err := proto.Marshal(pb) if err != nil { g.Fail(err.Error()) } var buf bytes.Buffer w, _ := gzip.NewWriterLevel(&buf, gzip.BestCompression) w.Write(b) w.Close() b = buf.Bytes() v := fmt.Sprintf("fileDescriptor%d", file.index) g.P() g.P("var ", v, " = []byte{") g.In() g.P("// ", len(b), " bytes of a gzipped FileDescriptorProto") for len(b) > 0 { n := 16 if n > len(b) { n = len(b) } s := "" for _, c := range b[:n] { s += fmt.Sprintf("0x%02x,", c) } g.P(s) b = b[n:] } g.Out() g.P("}") } func (g *Generator) generateEnumRegistration(enum *EnumDescriptor) { // // We always print the full (proto-world) package name here. pkg := enum.File().GetPackage() if pkg != "" { pkg += "." } // The full type name typeName := enum.TypeName() // The full type name, CamelCased. ccTypeName := CamelCaseSlice(typeName) g.addInitf("%s.RegisterEnum(%q, %[3]s_name, %[3]s_value)", g.Pkg["proto"], pkg+ccTypeName, ccTypeName) } func (g *Generator) generateExtensionRegistration(ext *ExtensionDescriptor) { g.addInitf("%s.RegisterExtension(%s)", g.Pkg["proto"], ext.DescName()) } // And now lots of helper functions. // Is c an ASCII lower-case letter? func isASCIILower(c byte) bool { return 'a' <= c && c <= 'z' } // Is c an ASCII digit? func isASCIIDigit(c byte) bool { return '0' <= c && c <= '9' } // CamelCase returns the CamelCased name. // If there is an interior underscore followed by a lower case letter, // drop the underscore and convert the letter to upper case. // There is a remote possibility of this rewrite causing a name collision, // but it's so remote we're prepared to pretend it's nonexistent - since the // C++ generator lowercases names, it's extremely unlikely to have two fields // with different capitalizations. // In short, _my_field_name_2 becomes XMyFieldName_2. func CamelCase(s string) string { if s == "" { return "" } t := make([]byte, 0, 32) i := 0 if s[0] == '_' { // Need a capital letter; drop the '_'. t = append(t, 'X') i++ } // Invariant: if the next letter is lower case, it must be converted // to upper case. // That is, we process a word at a time, where words are marked by _ or // upper case letter. Digits are treated as words. for ; i < len(s); i++ { c := s[i] if c == '_' && i+1 < len(s) && isASCIILower(s[i+1]) { continue // Skip the underscore in s. } if isASCIIDigit(c) { t = append(t, c) continue } // Assume we have a letter now - if not, it's a bogus identifier. // The next word is a sequence of characters that must start upper case. if isASCIILower(c) { c ^= ' ' // Make it a capital letter. } t = append(t, c) // Guaranteed not lower case. // Accept lower case sequence that follows. for i+1 < len(s) && isASCIILower(s[i+1]) { i++ t = append(t, s[i]) } } return string(t) } // CamelCaseSlice is like CamelCase, but the argument is a slice of strings to // be joined with "_". func CamelCaseSlice(elem []string) string { return CamelCase(strings.Join(elem, "_")) } // dottedSlice turns a sliced name into a dotted name. func dottedSlice(elem []string) string { return strings.Join(elem, ".") } // Is this field optional? func isOptional(field *descriptor.FieldDescriptorProto) bool { return field.Label != nil && *field.Label == descriptor.FieldDescriptorProto_LABEL_OPTIONAL } // Is this field required? func isRequired(field *descriptor.FieldDescriptorProto) bool { return field.Label != nil && *field.Label == descriptor.FieldDescriptorProto_LABEL_REQUIRED } // Is this field repeated? func isRepeated(field *descriptor.FieldDescriptorProto) bool { return field.Label != nil && *field.Label == descriptor.FieldDescriptorProto_LABEL_REPEATED } // badToUnderscore is the mapping function used to generate Go names from package names, // which can be dotted in the input .proto file. It replaces non-identifier characters such as // dot or dash with underscore. func badToUnderscore(r rune) rune { if unicode.IsLetter(r) || unicode.IsDigit(r) || r == '_' { return r } return '_' } // baseName returns the last path element of the name, with the last dotted suffix removed. func baseName(name string) string { // First, find the last element if i := strings.LastIndex(name, "/"); i >= 0 { name = name[i+1:] } // Now drop the suffix if i := strings.LastIndex(name, "."); i >= 0 { name = name[0:i] } return name } // The SourceCodeInfo message describes the location of elements of a parsed // .proto file by way of a "path", which is a sequence of integers that // describe the route from a FileDescriptorProto to the relevant submessage. // The path alternates between a field number of a repeated field, and an index // into that repeated field. The constants below define the field numbers that // are used. // // See descriptor.proto for more information about this. const ( // tag numbers in FileDescriptorProto packagePath = 2 // package messagePath = 4 // message_type enumPath = 5 // enum_type // tag numbers in DescriptorProto messageFieldPath = 2 // field messageMessagePath = 3 // nested_type messageEnumPath = 4 // enum_type messageOneofPath = 8 // oneof_decl // tag numbers in EnumDescriptorProto enumValuePath = 2 // value ) lxd-2.0.0/dist/src/github.com/golang/protobuf/protoc-gen-go/generator/name_test.go0000644061062106075000000000561012702772352032573 0ustar00stgraberdomain admins00000000000000// Go support for Protocol Buffers - Google's data interchange format // // Copyright 2013 The Go Authors. All rights reserved. // https://github.com/golang/protobuf // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package generator import ( "testing" "github.com/golang/protobuf/protoc-gen-go/descriptor" ) func TestCamelCase(t *testing.T) { tests := []struct { in, want string }{ {"one", "One"}, {"one_two", "OneTwo"}, {"_my_field_name_2", "XMyFieldName_2"}, {"Something_Capped", "Something_Capped"}, {"my_Name", "My_Name"}, {"OneTwo", "OneTwo"}, {"_", "X"}, {"_a_", "XA_"}, } for _, tc := range tests { if got := CamelCase(tc.in); got != tc.want { t.Errorf("CamelCase(%q) = %q, want %q", tc.in, got, tc.want) } } } func TestGoPackageOption(t *testing.T) { tests := []struct { in string impPath, pkg string ok bool }{ {"", "", "", false}, {"foo", "", "foo", true}, {"github.com/golang/bar", "github.com/golang/bar", "bar", true}, {"github.com/golang/bar;baz", "github.com/golang/bar", "baz", true}, } for _, tc := range tests { d := &FileDescriptor{ FileDescriptorProto: &descriptor.FileDescriptorProto{ Options: &descriptor.FileOptions{ GoPackage: &tc.in, }, }, } impPath, pkg, ok := d.goPackageOption() if impPath != tc.impPath || pkg != tc.pkg || ok != tc.ok { t.Errorf("go_package = %q => (%q, %q, %t), want (%q, %q, %t)", tc.in, impPath, pkg, ok, tc.impPath, tc.pkg, tc.ok) } } } lxd-2.0.0/dist/src/github.com/golang/protobuf/protoc-gen-go/generator/Makefile0000644061062106075000000000343512702772352031730 0ustar00stgraberdomain admins00000000000000# Go support for Protocol Buffers - Google's data interchange format # # Copyright 2010 The Go Authors. All rights reserved. # https://github.com/golang/protobuf # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. include $(GOROOT)/src/Make.inc TARG=github.com/golang/protobuf/compiler/generator GOFILES=\ generator.go\ DEPS=../descriptor ../plugin ../../proto include $(GOROOT)/src/Make.pkg lxd-2.0.0/dist/src/github.com/golang/protobuf/ptypes/0000755061062106075000000000000012702772352025141 5ustar00stgraberdomain admins00000000000000lxd-2.0.0/dist/src/github.com/golang/protobuf/ptypes/duration.go0000644061062106075000000000744312702772352027325 0ustar00stgraberdomain admins00000000000000// Go support for Protocol Buffers - Google's data interchange format // // Copyright 2016 The Go Authors. All rights reserved. // https://github.com/golang/protobuf // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package ptypes // This file implements conversions between google.protobuf.Duration // and time.Duration. import ( "errors" "fmt" "time" durpb "github.com/golang/protobuf/ptypes/duration" ) const ( // Range of a durpb.Duration in seconds, as specified in // google/protobuf/duration.proto. This is about 10,000 years in seconds. maxSeconds = int64(10000 * 365.25 * 24 * 60 * 60) minSeconds = -maxSeconds ) // validateDuration determines whether the durpb.Duration is valid according to the // definition in google/protobuf/duration.proto. A valid durpb.Duration // may still be too large to fit into a time.Duration (the range of durpb.Duration // is about 10,000 years, and the range of time.Duration is about 290). func validateDuration(d *durpb.Duration) error { if d == nil { return errors.New("duration: nil Duration") } if d.Seconds < minSeconds || d.Seconds > maxSeconds { return fmt.Errorf("duration: %v: seconds out of range", d) } if d.Nanos <= -1e9 || d.Nanos >= 1e9 { return fmt.Errorf("duration: %v: nanos out of range", d) } // Seconds and Nanos must have the same sign, unless d.Nanos is zero. if (d.Seconds < 0 && d.Nanos > 0) || (d.Seconds > 0 && d.Nanos < 0) { return fmt.Errorf("duration: %v: seconds and nanos have different signs", d) } return nil } // Duration converts a durpb.Duration to a time.Duration. Duration // returns an error if the durpb.Duration is invalid or is too large to be // represented in a time.Duration. func Duration(p *durpb.Duration) (time.Duration, error) { if err := validateDuration(p); err != nil { return 0, err } d := time.Duration(p.Seconds) * time.Second if int64(d/time.Second) != p.Seconds { return 0, fmt.Errorf("duration: %v is out of range for time.Duration", p) } if p.Nanos != 0 { d += time.Duration(p.Nanos) if (d < 0) != (p.Nanos < 0) { return 0, fmt.Errorf("duration: %v is out of range for time.Duration", p) } } return d, nil } // DurationProto converts a time.Duration to a durpb.Duration. func DurationProto(d time.Duration) *durpb.Duration { nanos := d.Nanoseconds() secs := nanos / 1e9 nanos -= secs * 1e9 return &durpb.Duration{ Seconds: secs, Nanos: int32(nanos), } } lxd-2.0.0/dist/src/github.com/golang/protobuf/ptypes/any_test.go0000644061062106075000000000740112702772352027320 0ustar00stgraberdomain admins00000000000000// Go support for Protocol Buffers - Google's data interchange format // // Copyright 2016 The Go Authors. All rights reserved. // https://github.com/golang/protobuf // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package ptypes import ( "testing" "github.com/golang/protobuf/proto" pb "github.com/golang/protobuf/protoc-gen-go/descriptor" "github.com/golang/protobuf/ptypes/any" ) func TestMarshalUnmarshal(t *testing.T) { orig := &any.Any{Value: []byte("test")} packed, err := MarshalAny(orig) if err != nil { t.Errorf("MarshalAny(%+v): got: _, %v exp: _, nil", orig, err) } unpacked := &any.Any{} err = UnmarshalAny(packed, unpacked) if err != nil || !proto.Equal(unpacked, orig) { t.Errorf("got: %v, %+v; want nil, %+v", err, unpacked, orig) } } func TestIs(t *testing.T) { a, err := MarshalAny(&pb.FileDescriptorProto{}) if err != nil { t.Fatal(err) } if Is(a, &pb.DescriptorProto{}) { t.Error("FileDescriptorProto is not a DescriptorProto, but Is says it is") } if !Is(a, &pb.FileDescriptorProto{}) { t.Error("FileDescriptorProto is indeed a FileDescriptorProto, but Is says it is not") } } func TestIsDifferentUrlPrefixes(t *testing.T) { m := &pb.FileDescriptorProto{} a := &any.Any{TypeUrl: "foo/bar/" + proto.MessageName(m)} if !Is(a, m) { t.Errorf("message with type url %q didn't satisfy Is for type %q", a.TypeUrl, proto.MessageName(m)) } } func TestUnmarshalDynamic(t *testing.T) { want := &pb.FileDescriptorProto{Name: proto.String("foo")} a, err := MarshalAny(want) if err != nil { t.Fatal(err) } var got DynamicAny if err := UnmarshalAny(a, &got); err != nil { t.Fatal(err) } if !proto.Equal(got.Message, want) { t.Errorf("invalid result from UnmarshalAny, got %q want %q", got.Message, want) } } func TestEmpty(t *testing.T) { want := &pb.FileDescriptorProto{} a, err := MarshalAny(want) if err != nil { t.Fatal(err) } got, err := Empty(a) if err != nil { t.Fatal(err) } if !proto.Equal(got, want) { t.Errorf("unequal empty message, got %q, want %q", got, want) } // that's a valid type_url for a message which shouldn't be linked into this // test binary. We want an error. a.TypeUrl = "type.googleapis.com/google.protobuf.FieldMask" if _, err := Empty(a); err == nil { t.Errorf("got no error for an attempt to create a message of type %q, which shouldn't be linked in", a.TypeUrl) } } lxd-2.0.0/dist/src/github.com/golang/protobuf/ptypes/empty/0000755061062106075000000000000012702772352026277 5ustar00stgraberdomain admins00000000000000lxd-2.0.0/dist/src/github.com/golang/protobuf/ptypes/empty/empty.proto0000644061062106075000000000464312702772352030531 0ustar00stgraberdomain admins00000000000000// Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. // https://developers.google.com/protocol-buffers/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. syntax = "proto3"; package google.protobuf; option go_package = "github.com/golang/protobuf/ptypes/empty"; option csharp_namespace = "Google.Protobuf.WellKnownTypes"; option java_package = "com.google.protobuf"; option java_outer_classname = "EmptyProto"; option java_multiple_files = true; option java_generate_equals_and_hash = true; option objc_class_prefix = "GPB"; option cc_enable_arenas = true; // A generic empty message that you can re-use to avoid defining duplicated // empty messages in your APIs. A typical example is to use it as the request // or the response type of an API method. For instance: // // service Foo { // rpc Bar(google.protobuf.Empty) returns (google.protobuf.Empty); // } // // The JSON representation for `Empty` is empty JSON object `{}`. message Empty {} lxd-2.0.0/dist/src/github.com/golang/protobuf/ptypes/empty/empty.pb.go0000644061062106075000000000471512702772352030373 0ustar00stgraberdomain admins00000000000000// Code generated by protoc-gen-go. // source: github.com/golang/protobuf/ptypes/empty/empty.proto // DO NOT EDIT! /* Package empty is a generated protocol buffer package. It is generated from these files: github.com/golang/protobuf/ptypes/empty/empty.proto It has these top-level messages: Empty */ package empty import proto "github.com/golang/protobuf/proto" import fmt "fmt" import math "math" // Reference imports to suppress errors if they are not otherwise used. var _ = proto.Marshal var _ = fmt.Errorf var _ = math.Inf // This is a compile-time assertion to ensure that this generated file // is compatible with the proto package it is being compiled against. const _ = proto.ProtoPackageIsVersion1 // A generic empty message that you can re-use to avoid defining duplicated // empty messages in your APIs. A typical example is to use it as the request // or the response type of an API method. For instance: // // service Foo { // rpc Bar(google.protobuf.Empty) returns (google.protobuf.Empty); // } // // The JSON representation for `Empty` is empty JSON object `{}`. type Empty struct { } func (m *Empty) Reset() { *m = Empty{} } func (m *Empty) String() string { return proto.CompactTextString(m) } func (*Empty) ProtoMessage() {} func (*Empty) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } func (*Empty) XXX_WellKnownType() string { return "Empty" } func init() { proto.RegisterType((*Empty)(nil), "google.protobuf.Empty") } var fileDescriptor0 = []byte{ // 148 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0x32, 0x4e, 0xcf, 0x2c, 0xc9, 0x28, 0x4d, 0xd2, 0x4b, 0xce, 0xcf, 0xd5, 0x4f, 0xcf, 0xcf, 0x49, 0xcc, 0x4b, 0xd7, 0x2f, 0x28, 0xca, 0x2f, 0xc9, 0x4f, 0x2a, 0x4d, 0xd3, 0x2f, 0x28, 0xa9, 0x2c, 0x48, 0x2d, 0xd6, 0x4f, 0xcd, 0x05, 0x32, 0x20, 0xa4, 0x1e, 0x58, 0x4e, 0x88, 0x3f, 0x3d, 0x3f, 0x3f, 0x3d, 0x27, 0x55, 0x0f, 0xa6, 0x52, 0x89, 0x9d, 0x8b, 0xd5, 0x15, 0x24, 0xef, 0x54, 0xc9, 0x25, 0x0c, 0x34, 0x49, 0x0f, 0x4d, 0xde, 0x89, 0x0b, 0x2c, 0x1b, 0x00, 0xe2, 0x06, 0x30, 0x46, 0xa9, 0x13, 0x69, 0xe7, 0x02, 0x46, 0xc6, 0x1f, 0x8c, 0x8c, 0x8b, 0x98, 0x98, 0xdd, 0x03, 0x9c, 0x56, 0x31, 0xc9, 0xb9, 0x43, 0x0c, 0x0d, 0x80, 0x2a, 0xd5, 0x0b, 0x4f, 0xcd, 0xc9, 0xf1, 0xce, 0xcb, 0x2f, 0xcf, 0x0b, 0x01, 0x69, 0x49, 0x62, 0x03, 0x9b, 0x61, 0x0c, 0x08, 0x00, 0x00, 0xff, 0xff, 0x7f, 0xbb, 0xf4, 0x0e, 0xd2, 0x00, 0x00, 0x00, } lxd-2.0.0/dist/src/github.com/golang/protobuf/ptypes/doc.go0000644061062106075000000000333612702772352026242 0ustar00stgraberdomain admins00000000000000// Go support for Protocol Buffers - Google's data interchange format // // Copyright 2016 The Go Authors. All rights reserved. // https://github.com/golang/protobuf // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /* Package ptypes contains code for interacting with well-known types. */ package ptypes lxd-2.0.0/dist/src/github.com/golang/protobuf/ptypes/timestamp/0000755061062106075000000000000012702772352027144 5ustar00stgraberdomain admins00000000000000lxd-2.0.0/dist/src/github.com/golang/protobuf/ptypes/timestamp/timestamp.proto0000644061062106075000000001111412702772352032232 0ustar00stgraberdomain admins00000000000000// Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. // https://developers.google.com/protocol-buffers/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. syntax = "proto3"; package google.protobuf; option go_package = "github.com/golang/protobuf/ptypes/timestamp"; option csharp_namespace = "Google.Protobuf.WellKnownTypes"; option cc_enable_arenas = true; option java_package = "com.google.protobuf"; option java_outer_classname = "TimestampProto"; option java_multiple_files = true; option java_generate_equals_and_hash = true; option objc_class_prefix = "GPB"; // A Timestamp represents a point in time independent of any time zone // or calendar, represented as seconds and fractions of seconds at // nanosecond resolution in UTC Epoch time. It is encoded using the // Proleptic Gregorian Calendar which extends the Gregorian calendar // backwards to year one. It is encoded assuming all minutes are 60 // seconds long, i.e. leap seconds are "smeared" so that no leap second // table is needed for interpretation. Range is from // 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z. // By restricting to that range, we ensure that we can convert to // and from RFC 3339 date strings. // See [https://www.ietf.org/rfc/rfc3339.txt](https://www.ietf.org/rfc/rfc3339.txt). // // Example 1: Compute Timestamp from POSIX `time()`. // // Timestamp timestamp; // timestamp.set_seconds(time(NULL)); // timestamp.set_nanos(0); // // Example 2: Compute Timestamp from POSIX `gettimeofday()`. // // struct timeval tv; // gettimeofday(&tv, NULL); // // Timestamp timestamp; // timestamp.set_seconds(tv.tv_sec); // timestamp.set_nanos(tv.tv_usec * 1000); // // Example 3: Compute Timestamp from Win32 `GetSystemTimeAsFileTime()`. // // FILETIME ft; // GetSystemTimeAsFileTime(&ft); // UINT64 ticks = (((UINT64)ft.dwHighDateTime) << 32) | ft.dwLowDateTime; // // // A Windows tick is 100 nanoseconds. Windows epoch 1601-01-01T00:00:00Z // // is 11644473600 seconds before Unix epoch 1970-01-01T00:00:00Z. // Timestamp timestamp; // timestamp.set_seconds((INT64) ((ticks / 10000000) - 11644473600LL)); // timestamp.set_nanos((INT32) ((ticks % 10000000) * 100)); // // Example 4: Compute Timestamp from Java `System.currentTimeMillis()`. // // long millis = System.currentTimeMillis(); // // Timestamp timestamp = Timestamp.newBuilder().setSeconds(millis / 1000) // .setNanos((int) ((millis % 1000) * 1000000)).build(); // // // Example 5: Compute Timestamp from current time in Python. // // now = time.time() // seconds = int(now) // nanos = int((now - seconds) * 10**9) // timestamp = Timestamp(seconds=seconds, nanos=nanos) // // message Timestamp { // Represents seconds of UTC time since Unix epoch // 1970-01-01T00:00:00Z. Must be from from 0001-01-01T00:00:00Z to // 9999-12-31T23:59:59Z inclusive. int64 seconds = 1; // Non-negative fractions of a second at nanosecond resolution. Negative // second values with fractions must still have non-negative nanos values // that count forward in time. Must be from 0 to 999,999,999 // inclusive. int32 nanos = 2; } lxd-2.0.0/dist/src/github.com/golang/protobuf/ptypes/timestamp/timestamp.pb.go0000644061062106075000000001203612702772352032100 0ustar00stgraberdomain admins00000000000000// Code generated by protoc-gen-go. // source: github.com/golang/protobuf/ptypes/timestamp/timestamp.proto // DO NOT EDIT! /* Package timestamp is a generated protocol buffer package. It is generated from these files: github.com/golang/protobuf/ptypes/timestamp/timestamp.proto It has these top-level messages: Timestamp */ package timestamp import proto "github.com/golang/protobuf/proto" import fmt "fmt" import math "math" // Reference imports to suppress errors if they are not otherwise used. var _ = proto.Marshal var _ = fmt.Errorf var _ = math.Inf // This is a compile-time assertion to ensure that this generated file // is compatible with the proto package it is being compiled against. const _ = proto.ProtoPackageIsVersion1 // A Timestamp represents a point in time independent of any time zone // or calendar, represented as seconds and fractions of seconds at // nanosecond resolution in UTC Epoch time. It is encoded using the // Proleptic Gregorian Calendar which extends the Gregorian calendar // backwards to year one. It is encoded assuming all minutes are 60 // seconds long, i.e. leap seconds are "smeared" so that no leap second // table is needed for interpretation. Range is from // 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z. // By restricting to that range, we ensure that we can convert to // and from RFC 3339 date strings. // See [https://www.ietf.org/rfc/rfc3339.txt](https://www.ietf.org/rfc/rfc3339.txt). // // Example 1: Compute Timestamp from POSIX `time()`. // // Timestamp timestamp; // timestamp.set_seconds(time(NULL)); // timestamp.set_nanos(0); // // Example 2: Compute Timestamp from POSIX `gettimeofday()`. // // struct timeval tv; // gettimeofday(&tv, NULL); // // Timestamp timestamp; // timestamp.set_seconds(tv.tv_sec); // timestamp.set_nanos(tv.tv_usec * 1000); // // Example 3: Compute Timestamp from Win32 `GetSystemTimeAsFileTime()`. // // FILETIME ft; // GetSystemTimeAsFileTime(&ft); // UINT64 ticks = (((UINT64)ft.dwHighDateTime) << 32) | ft.dwLowDateTime; // // // A Windows tick is 100 nanoseconds. Windows epoch 1601-01-01T00:00:00Z // // is 11644473600 seconds before Unix epoch 1970-01-01T00:00:00Z. // Timestamp timestamp; // timestamp.set_seconds((INT64) ((ticks / 10000000) - 11644473600LL)); // timestamp.set_nanos((INT32) ((ticks % 10000000) * 100)); // // Example 4: Compute Timestamp from Java `System.currentTimeMillis()`. // // long millis = System.currentTimeMillis(); // // Timestamp timestamp = Timestamp.newBuilder().setSeconds(millis / 1000) // .setNanos((int) ((millis % 1000) * 1000000)).build(); // // // Example 5: Compute Timestamp from current time in Python. // // now = time.time() // seconds = int(now) // nanos = int((now - seconds) * 10**9) // timestamp = Timestamp(seconds=seconds, nanos=nanos) // // type Timestamp struct { // Represents seconds of UTC time since Unix epoch // 1970-01-01T00:00:00Z. Must be from from 0001-01-01T00:00:00Z to // 9999-12-31T23:59:59Z inclusive. Seconds int64 `protobuf:"varint,1,opt,name=seconds" json:"seconds,omitempty"` // Non-negative fractions of a second at nanosecond resolution. Negative // second values with fractions must still have non-negative nanos values // that count forward in time. Must be from 0 to 999,999,999 // inclusive. Nanos int32 `protobuf:"varint,2,opt,name=nanos" json:"nanos,omitempty"` } func (m *Timestamp) Reset() { *m = Timestamp{} } func (m *Timestamp) String() string { return proto.CompactTextString(m) } func (*Timestamp) ProtoMessage() {} func (*Timestamp) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } func (*Timestamp) XXX_WellKnownType() string { return "Timestamp" } func init() { proto.RegisterType((*Timestamp)(nil), "google.protobuf.Timestamp") } var fileDescriptor0 = []byte{ // 192 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0xb2, 0x4e, 0xcf, 0x2c, 0xc9, 0x28, 0x4d, 0xd2, 0x4b, 0xce, 0xcf, 0xd5, 0x4f, 0xcf, 0xcf, 0x49, 0xcc, 0x4b, 0xd7, 0x2f, 0x28, 0xca, 0x2f, 0xc9, 0x4f, 0x2a, 0x4d, 0xd3, 0x2f, 0x28, 0xa9, 0x2c, 0x48, 0x2d, 0xd6, 0x2f, 0xc9, 0xcc, 0x4d, 0x2d, 0x2e, 0x49, 0xcc, 0x2d, 0x40, 0xb0, 0xf4, 0xc0, 0x6a, 0x84, 0xf8, 0xd3, 0xf3, 0xf3, 0xd3, 0x73, 0x52, 0xf5, 0x60, 0x3a, 0x94, 0xac, 0xb9, 0x38, 0x43, 0x60, 0x6a, 0x84, 0x24, 0xb8, 0xd8, 0x8b, 0x53, 0x93, 0xf3, 0xf3, 0x52, 0x8a, 0x25, 0x18, 0x15, 0x18, 0x35, 0x98, 0x83, 0x60, 0x5c, 0x21, 0x11, 0x2e, 0xd6, 0xbc, 0xc4, 0xbc, 0xfc, 0x62, 0x09, 0x26, 0xa0, 0x38, 0x6b, 0x10, 0x84, 0xe3, 0xd4, 0xc8, 0xc8, 0x25, 0x0c, 0x74, 0x86, 0x1e, 0x9a, 0xa1, 0x4e, 0x7c, 0x70, 0x23, 0x03, 0x40, 0x42, 0x01, 0x8c, 0x51, 0xda, 0x24, 0x38, 0x7a, 0x01, 0x23, 0xe3, 0x0f, 0x46, 0xc6, 0x45, 0x4c, 0xcc, 0xee, 0x01, 0x4e, 0xab, 0x98, 0xe4, 0xdc, 0x21, 0x86, 0x07, 0x40, 0x95, 0xeb, 0x85, 0xa7, 0xe6, 0xe4, 0x78, 0xe7, 0xe5, 0x97, 0xe7, 0x85, 0x80, 0xb4, 0x25, 0xb1, 0x81, 0xcd, 0x31, 0x06, 0x04, 0x00, 0x00, 0xff, 0xff, 0x17, 0x5f, 0xb7, 0xdc, 0x17, 0x01, 0x00, 0x00, } lxd-2.0.0/dist/src/github.com/golang/protobuf/ptypes/duration/0000755061062106075000000000000012702772352026766 5ustar00stgraberdomain admins00000000000000lxd-2.0.0/dist/src/github.com/golang/protobuf/ptypes/duration/duration.pb.go0000644061062106075000000001063312702772352031545 0ustar00stgraberdomain admins00000000000000// Code generated by protoc-gen-go. // source: github.com/golang/protobuf/ptypes/duration/duration.proto // DO NOT EDIT! /* Package duration is a generated protocol buffer package. It is generated from these files: github.com/golang/protobuf/ptypes/duration/duration.proto It has these top-level messages: Duration */ package duration import proto "github.com/golang/protobuf/proto" import fmt "fmt" import math "math" // Reference imports to suppress errors if they are not otherwise used. var _ = proto.Marshal var _ = fmt.Errorf var _ = math.Inf // This is a compile-time assertion to ensure that this generated file // is compatible with the proto package it is being compiled against. const _ = proto.ProtoPackageIsVersion1 // A Duration represents a signed, fixed-length span of time represented // as a count of seconds and fractions of seconds at nanosecond // resolution. It is independent of any calendar and concepts like "day" // or "month". It is related to Timestamp in that the difference between // two Timestamp values is a Duration and it can be added or subtracted // from a Timestamp. Range is approximately +-10,000 years. // // Example 1: Compute Duration from two Timestamps in pseudo code. // // Timestamp start = ...; // Timestamp end = ...; // Duration duration = ...; // // duration.seconds = end.seconds - start.seconds; // duration.nanos = end.nanos - start.nanos; // // if (duration.seconds < 0 && duration.nanos > 0) { // duration.seconds += 1; // duration.nanos -= 1000000000; // } else if (durations.seconds > 0 && duration.nanos < 0) { // duration.seconds -= 1; // duration.nanos += 1000000000; // } // // Example 2: Compute Timestamp from Timestamp + Duration in pseudo code. // // Timestamp start = ...; // Duration duration = ...; // Timestamp end = ...; // // end.seconds = start.seconds + duration.seconds; // end.nanos = start.nanos + duration.nanos; // // if (end.nanos < 0) { // end.seconds -= 1; // end.nanos += 1000000000; // } else if (end.nanos >= 1000000000) { // end.seconds += 1; // end.nanos -= 1000000000; // } // type Duration struct { // Signed seconds of the span of time. Must be from -315,576,000,000 // to +315,576,000,000 inclusive. Seconds int64 `protobuf:"varint,1,opt,name=seconds" json:"seconds,omitempty"` // Signed fractions of a second at nanosecond resolution of the span // of time. Durations less than one second are represented with a 0 // `seconds` field and a positive or negative `nanos` field. For durations // of one second or more, a non-zero value for the `nanos` field must be // of the same sign as the `seconds` field. Must be from -999,999,999 // to +999,999,999 inclusive. Nanos int32 `protobuf:"varint,2,opt,name=nanos" json:"nanos,omitempty"` } func (m *Duration) Reset() { *m = Duration{} } func (m *Duration) String() string { return proto.CompactTextString(m) } func (*Duration) ProtoMessage() {} func (*Duration) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } func (*Duration) XXX_WellKnownType() string { return "Duration" } func init() { proto.RegisterType((*Duration)(nil), "google.protobuf.Duration") } var fileDescriptor0 = []byte{ // 187 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0xb2, 0x4c, 0xcf, 0x2c, 0xc9, 0x28, 0x4d, 0xd2, 0x4b, 0xce, 0xcf, 0xd5, 0x4f, 0xcf, 0xcf, 0x49, 0xcc, 0x4b, 0xd7, 0x2f, 0x28, 0xca, 0x2f, 0xc9, 0x4f, 0x2a, 0x4d, 0xd3, 0x2f, 0x28, 0xa9, 0x2c, 0x48, 0x2d, 0xd6, 0x4f, 0x29, 0x2d, 0x4a, 0x2c, 0xc9, 0xcc, 0xcf, 0x83, 0x33, 0xf4, 0xc0, 0x2a, 0x84, 0xf8, 0xd3, 0xf3, 0xf3, 0xd3, 0x73, 0x52, 0xf5, 0x60, 0xea, 0x95, 0xac, 0xb8, 0x38, 0x5c, 0xa0, 0x4a, 0x84, 0x24, 0xb8, 0xd8, 0x8b, 0x53, 0x93, 0xf3, 0xf3, 0x52, 0x8a, 0x25, 0x18, 0x15, 0x18, 0x35, 0x98, 0x83, 0x60, 0x5c, 0x21, 0x11, 0x2e, 0xd6, 0xbc, 0xc4, 0xbc, 0xfc, 0x62, 0x09, 0x26, 0xa0, 0x38, 0x6b, 0x10, 0x84, 0xe3, 0x54, 0xc3, 0x25, 0x0c, 0x74, 0x82, 0x1e, 0x9a, 0x91, 0x4e, 0xbc, 0x30, 0x03, 0x03, 0x40, 0x22, 0x01, 0x8c, 0x51, 0x5a, 0xc4, 0xbb, 0x77, 0x01, 0x23, 0xe3, 0x22, 0x26, 0x66, 0xf7, 0x00, 0xa7, 0x55, 0x4c, 0x72, 0xee, 0x10, 0x73, 0x03, 0xa0, 0x4a, 0xf5, 0xc2, 0x53, 0x73, 0x72, 0xbc, 0xf3, 0xf2, 0xcb, 0xf3, 0x42, 0x40, 0x5a, 0x92, 0xd8, 0xc0, 0x66, 0x18, 0x03, 0x02, 0x00, 0x00, 0xff, 0xff, 0x62, 0xfb, 0xb1, 0x51, 0x0e, 0x01, 0x00, 0x00, } lxd-2.0.0/dist/src/github.com/golang/protobuf/ptypes/duration/duration.proto0000644061062106075000000000772612702772352031714 0ustar00stgraberdomain admins00000000000000// Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. // https://developers.google.com/protocol-buffers/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. syntax = "proto3"; package google.protobuf; option go_package = "github.com/golang/protobuf/ptypes/duration"; option csharp_namespace = "Google.Protobuf.WellKnownTypes"; option java_package = "com.google.protobuf"; option java_outer_classname = "DurationProto"; option java_multiple_files = true; option java_generate_equals_and_hash = true; option objc_class_prefix = "GPB"; // A Duration represents a signed, fixed-length span of time represented // as a count of seconds and fractions of seconds at nanosecond // resolution. It is independent of any calendar and concepts like "day" // or "month". It is related to Timestamp in that the difference between // two Timestamp values is a Duration and it can be added or subtracted // from a Timestamp. Range is approximately +-10,000 years. // // Example 1: Compute Duration from two Timestamps in pseudo code. // // Timestamp start = ...; // Timestamp end = ...; // Duration duration = ...; // // duration.seconds = end.seconds - start.seconds; // duration.nanos = end.nanos - start.nanos; // // if (duration.seconds < 0 && duration.nanos > 0) { // duration.seconds += 1; // duration.nanos -= 1000000000; // } else if (durations.seconds > 0 && duration.nanos < 0) { // duration.seconds -= 1; // duration.nanos += 1000000000; // } // // Example 2: Compute Timestamp from Timestamp + Duration in pseudo code. // // Timestamp start = ...; // Duration duration = ...; // Timestamp end = ...; // // end.seconds = start.seconds + duration.seconds; // end.nanos = start.nanos + duration.nanos; // // if (end.nanos < 0) { // end.seconds -= 1; // end.nanos += 1000000000; // } else if (end.nanos >= 1000000000) { // end.seconds += 1; // end.nanos -= 1000000000; // } // message Duration { // Signed seconds of the span of time. Must be from -315,576,000,000 // to +315,576,000,000 inclusive. int64 seconds = 1; // Signed fractions of a second at nanosecond resolution of the span // of time. Durations less than one second are represented with a 0 // `seconds` field and a positive or negative `nanos` field. For durations // of one second or more, a non-zero value for the `nanos` field must be // of the same sign as the `seconds` field. Must be from -999,999,999 // to +999,999,999 inclusive. int32 nanos = 2; } lxd-2.0.0/dist/src/github.com/golang/protobuf/ptypes/struct/0000755061062106075000000000000012702772352026465 5ustar00stgraberdomain admins00000000000000lxd-2.0.0/dist/src/github.com/golang/protobuf/ptypes/struct/struct.pb.go0000644061062106075000000003075412702772352030751 0ustar00stgraberdomain admins00000000000000// Code generated by protoc-gen-go. // source: github.com/golang/protobuf/ptypes/struct/struct.proto // DO NOT EDIT! /* Package structpb is a generated protocol buffer package. It is generated from these files: github.com/golang/protobuf/ptypes/struct/struct.proto It has these top-level messages: Struct Value ListValue */ package structpb import proto "github.com/golang/protobuf/proto" import fmt "fmt" import math "math" // Reference imports to suppress errors if they are not otherwise used. var _ = proto.Marshal var _ = fmt.Errorf var _ = math.Inf // This is a compile-time assertion to ensure that this generated file // is compatible with the proto package it is being compiled against. const _ = proto.ProtoPackageIsVersion1 // `NullValue` is a singleton enumeration to represent the null value for the // `Value` type union. // // The JSON representation for `NullValue` is JSON `null`. type NullValue int32 const ( // Null value. NullValue_NULL_VALUE NullValue = 0 ) var NullValue_name = map[int32]string{ 0: "NULL_VALUE", } var NullValue_value = map[string]int32{ "NULL_VALUE": 0, } func (x NullValue) String() string { return proto.EnumName(NullValue_name, int32(x)) } func (NullValue) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } func (NullValue) XXX_WellKnownType() string { return "NullValue" } // `Struct` represents a structured data value, consisting of fields // which map to dynamically typed values. In some languages, `Struct` // might be supported by a native representation. For example, in // scripting languages like JS a struct is represented as an // object. The details of that representation are described together // with the proto support for the language. // // The JSON representation for `Struct` is JSON object. type Struct struct { // Map of dynamically typed values. Fields map[string]*Value `protobuf:"bytes,1,rep,name=fields" json:"fields,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` } func (m *Struct) Reset() { *m = Struct{} } func (m *Struct) String() string { return proto.CompactTextString(m) } func (*Struct) ProtoMessage() {} func (*Struct) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } func (*Struct) XXX_WellKnownType() string { return "Struct" } func (m *Struct) GetFields() map[string]*Value { if m != nil { return m.Fields } return nil } // `Value` represents a dynamically typed value which can be either // null, a number, a string, a boolean, a recursive struct value, or a // list of values. A producer of value is expected to set one of that // variants, absence of any variant indicates an error. // // The JSON representation for `Value` is JSON value. type Value struct { // The kind of value. // // Types that are valid to be assigned to Kind: // *Value_NullValue // *Value_NumberValue // *Value_StringValue // *Value_BoolValue // *Value_StructValue // *Value_ListValue Kind isValue_Kind `protobuf_oneof:"kind"` } func (m *Value) Reset() { *m = Value{} } func (m *Value) String() string { return proto.CompactTextString(m) } func (*Value) ProtoMessage() {} func (*Value) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } func (*Value) XXX_WellKnownType() string { return "Value" } type isValue_Kind interface { isValue_Kind() } type Value_NullValue struct { NullValue NullValue `protobuf:"varint,1,opt,name=null_value,json=nullValue,enum=google.protobuf.NullValue,oneof"` } type Value_NumberValue struct { NumberValue float64 `protobuf:"fixed64,2,opt,name=number_value,json=numberValue,oneof"` } type Value_StringValue struct { StringValue string `protobuf:"bytes,3,opt,name=string_value,json=stringValue,oneof"` } type Value_BoolValue struct { BoolValue bool `protobuf:"varint,4,opt,name=bool_value,json=boolValue,oneof"` } type Value_StructValue struct { StructValue *Struct `protobuf:"bytes,5,opt,name=struct_value,json=structValue,oneof"` } type Value_ListValue struct { ListValue *ListValue `protobuf:"bytes,6,opt,name=list_value,json=listValue,oneof"` } func (*Value_NullValue) isValue_Kind() {} func (*Value_NumberValue) isValue_Kind() {} func (*Value_StringValue) isValue_Kind() {} func (*Value_BoolValue) isValue_Kind() {} func (*Value_StructValue) isValue_Kind() {} func (*Value_ListValue) isValue_Kind() {} func (m *Value) GetKind() isValue_Kind { if m != nil { return m.Kind } return nil } func (m *Value) GetNullValue() NullValue { if x, ok := m.GetKind().(*Value_NullValue); ok { return x.NullValue } return NullValue_NULL_VALUE } func (m *Value) GetNumberValue() float64 { if x, ok := m.GetKind().(*Value_NumberValue); ok { return x.NumberValue } return 0 } func (m *Value) GetStringValue() string { if x, ok := m.GetKind().(*Value_StringValue); ok { return x.StringValue } return "" } func (m *Value) GetBoolValue() bool { if x, ok := m.GetKind().(*Value_BoolValue); ok { return x.BoolValue } return false } func (m *Value) GetStructValue() *Struct { if x, ok := m.GetKind().(*Value_StructValue); ok { return x.StructValue } return nil } func (m *Value) GetListValue() *ListValue { if x, ok := m.GetKind().(*Value_ListValue); ok { return x.ListValue } return nil } // XXX_OneofFuncs is for the internal use of the proto package. func (*Value) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) { return _Value_OneofMarshaler, _Value_OneofUnmarshaler, _Value_OneofSizer, []interface{}{ (*Value_NullValue)(nil), (*Value_NumberValue)(nil), (*Value_StringValue)(nil), (*Value_BoolValue)(nil), (*Value_StructValue)(nil), (*Value_ListValue)(nil), } } func _Value_OneofMarshaler(msg proto.Message, b *proto.Buffer) error { m := msg.(*Value) // kind switch x := m.Kind.(type) { case *Value_NullValue: b.EncodeVarint(1<<3 | proto.WireVarint) b.EncodeVarint(uint64(x.NullValue)) case *Value_NumberValue: b.EncodeVarint(2<<3 | proto.WireFixed64) b.EncodeFixed64(math.Float64bits(x.NumberValue)) case *Value_StringValue: b.EncodeVarint(3<<3 | proto.WireBytes) b.EncodeStringBytes(x.StringValue) case *Value_BoolValue: t := uint64(0) if x.BoolValue { t = 1 } b.EncodeVarint(4<<3 | proto.WireVarint) b.EncodeVarint(t) case *Value_StructValue: b.EncodeVarint(5<<3 | proto.WireBytes) if err := b.EncodeMessage(x.StructValue); err != nil { return err } case *Value_ListValue: b.EncodeVarint(6<<3 | proto.WireBytes) if err := b.EncodeMessage(x.ListValue); err != nil { return err } case nil: default: return fmt.Errorf("Value.Kind has unexpected type %T", x) } return nil } func _Value_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) { m := msg.(*Value) switch tag { case 1: // kind.null_value if wire != proto.WireVarint { return true, proto.ErrInternalBadWireType } x, err := b.DecodeVarint() m.Kind = &Value_NullValue{NullValue(x)} return true, err case 2: // kind.number_value if wire != proto.WireFixed64 { return true, proto.ErrInternalBadWireType } x, err := b.DecodeFixed64() m.Kind = &Value_NumberValue{math.Float64frombits(x)} return true, err case 3: // kind.string_value if wire != proto.WireBytes { return true, proto.ErrInternalBadWireType } x, err := b.DecodeStringBytes() m.Kind = &Value_StringValue{x} return true, err case 4: // kind.bool_value if wire != proto.WireVarint { return true, proto.ErrInternalBadWireType } x, err := b.DecodeVarint() m.Kind = &Value_BoolValue{x != 0} return true, err case 5: // kind.struct_value if wire != proto.WireBytes { return true, proto.ErrInternalBadWireType } msg := new(Struct) err := b.DecodeMessage(msg) m.Kind = &Value_StructValue{msg} return true, err case 6: // kind.list_value if wire != proto.WireBytes { return true, proto.ErrInternalBadWireType } msg := new(ListValue) err := b.DecodeMessage(msg) m.Kind = &Value_ListValue{msg} return true, err default: return false, nil } } func _Value_OneofSizer(msg proto.Message) (n int) { m := msg.(*Value) // kind switch x := m.Kind.(type) { case *Value_NullValue: n += proto.SizeVarint(1<<3 | proto.WireVarint) n += proto.SizeVarint(uint64(x.NullValue)) case *Value_NumberValue: n += proto.SizeVarint(2<<3 | proto.WireFixed64) n += 8 case *Value_StringValue: n += proto.SizeVarint(3<<3 | proto.WireBytes) n += proto.SizeVarint(uint64(len(x.StringValue))) n += len(x.StringValue) case *Value_BoolValue: n += proto.SizeVarint(4<<3 | proto.WireVarint) n += 1 case *Value_StructValue: s := proto.Size(x.StructValue) n += proto.SizeVarint(5<<3 | proto.WireBytes) n += proto.SizeVarint(uint64(s)) n += s case *Value_ListValue: s := proto.Size(x.ListValue) n += proto.SizeVarint(6<<3 | proto.WireBytes) n += proto.SizeVarint(uint64(s)) n += s case nil: default: panic(fmt.Sprintf("proto: unexpected type %T in oneof", x)) } return n } // `ListValue` is a wrapper around a repeated field of values. // // The JSON representation for `ListValue` is JSON array. type ListValue struct { // Repeated field of dynamically typed values. Values []*Value `protobuf:"bytes,1,rep,name=values" json:"values,omitempty"` } func (m *ListValue) Reset() { *m = ListValue{} } func (m *ListValue) String() string { return proto.CompactTextString(m) } func (*ListValue) ProtoMessage() {} func (*ListValue) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} } func (*ListValue) XXX_WellKnownType() string { return "ListValue" } func (m *ListValue) GetValues() []*Value { if m != nil { return m.Values } return nil } func init() { proto.RegisterType((*Struct)(nil), "google.protobuf.Struct") proto.RegisterType((*Value)(nil), "google.protobuf.Value") proto.RegisterType((*ListValue)(nil), "google.protobuf.ListValue") proto.RegisterEnum("google.protobuf.NullValue", NullValue_name, NullValue_value) } var fileDescriptor0 = []byte{ // 412 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x8c, 0x92, 0xcf, 0x8b, 0xd3, 0x40, 0x14, 0xc7, 0x3b, 0x49, 0x1b, 0xcc, 0x8b, 0xd4, 0x12, 0x41, 0x4b, 0x05, 0x95, 0xf6, 0x52, 0x44, 0x12, 0xac, 0x08, 0x62, 0xbd, 0x18, 0xa8, 0x15, 0x0c, 0x25, 0x46, 0x5b, 0xc1, 0x4b, 0x69, 0xda, 0x34, 0x86, 0x4e, 0x67, 0x42, 0x7e, 0x28, 0x3d, 0xfa, 0x5f, 0x78, 0x5c, 0xf6, 0xb8, 0xc7, 0xfd, 0x0b, 0x77, 0x7e, 0x24, 0xd9, 0xa5, 0xa5, 0xb0, 0xa7, 0x99, 0xf7, 0x9d, 0xcf, 0xfb, 0xce, 0x7b, 0x6f, 0x06, 0xde, 0x45, 0x71, 0xfe, 0xbb, 0x08, 0xac, 0x35, 0xdd, 0xdb, 0x11, 0xc5, 0x2b, 0x12, 0xd9, 0x49, 0x4a, 0x73, 0x1a, 0x14, 0x5b, 0x3b, 0xc9, 0x0f, 0x49, 0x98, 0xd9, 0x59, 0x9e, 0x16, 0xeb, 0xbc, 0x5c, 0x2c, 0x71, 0x6a, 0x3e, 0x8a, 0x28, 0x8d, 0x70, 0x68, 0x55, 0x6c, 0xff, 0x3f, 0x02, 0xed, 0xbb, 0x20, 0xcc, 0x31, 0x68, 0xdb, 0x38, 0xc4, 0x9b, 0xac, 0x8b, 0x5e, 0xaa, 0x43, 0x63, 0x34, 0xb0, 0x8e, 0x60, 0x4b, 0x82, 0xd6, 0x67, 0x41, 0x4d, 0x48, 0x9e, 0x1e, 0xfc, 0x32, 0xa5, 0xf7, 0x0d, 0x8c, 0x3b, 0xb2, 0xd9, 0x01, 0x75, 0x17, 0x1e, 0x98, 0x11, 0x1a, 0xea, 0x3e, 0xdf, 0x9a, 0xaf, 0xa1, 0xf5, 0x67, 0x85, 0x8b, 0xb0, 0xab, 0x30, 0xcd, 0x18, 0x3d, 0x39, 0x31, 0x5f, 0xf0, 0x53, 0x5f, 0x42, 0x1f, 0x94, 0xf7, 0xa8, 0x7f, 0xad, 0x40, 0x4b, 0x88, 0xac, 0x32, 0x20, 0x05, 0xc6, 0x4b, 0x69, 0xc0, 0x4d, 0xdb, 0xa3, 0xde, 0x89, 0xc1, 0x8c, 0x21, 0x82, 0xff, 0xd2, 0xf0, 0x75, 0x52, 0x05, 0xe6, 0x00, 0x1e, 0x92, 0x62, 0x1f, 0x84, 0xe9, 0xf2, 0xf6, 0x7e, 0xc4, 0x10, 0x43, 0xaa, 0x35, 0xc4, 0xe6, 0x14, 0x93, 0xa8, 0x84, 0x54, 0x5e, 0x38, 0x87, 0xa4, 0x2a, 0xa1, 0x17, 0x00, 0x01, 0xa5, 0x55, 0x19, 0x4d, 0x86, 0x3c, 0xe0, 0x57, 0x71, 0x4d, 0x02, 0x1f, 0x85, 0x0b, 0x1b, 0x51, 0x89, 0xb4, 0x44, 0xab, 0x4f, 0xcf, 0xcc, 0xb1, 0xb4, 0x67, 0xbb, 0xba, 0x4b, 0x1c, 0x67, 0x55, 0xae, 0x26, 0x72, 0x4f, 0xbb, 0x74, 0x19, 0x52, 0x77, 0x89, 0xab, 0xc0, 0xd1, 0xa0, 0xb9, 0x8b, 0xc9, 0xa6, 0x3f, 0x06, 0xbd, 0x26, 0x4c, 0x0b, 0x34, 0x61, 0x56, 0xbd, 0xe8, 0xb9, 0xa1, 0x97, 0xd4, 0xab, 0x67, 0xa0, 0xd7, 0x43, 0x34, 0xdb, 0x00, 0xb3, 0xb9, 0xeb, 0x2e, 0x17, 0x9f, 0xdc, 0xf9, 0xa4, 0xd3, 0x70, 0xfe, 0x21, 0x78, 0xcc, 0x7e, 0xdb, 0xb1, 0x85, 0x63, 0xc8, 0x6e, 0x3c, 0x1e, 0x7b, 0xe8, 0xd7, 0x9b, 0xfb, 0x7e, 0xcc, 0xb1, 0x5c, 0x92, 0xe0, 0x02, 0xa1, 0x4b, 0x45, 0x9d, 0x7a, 0xce, 0x95, 0xf2, 0x7c, 0x2a, 0xcd, 0xbd, 0xaa, 0xbe, 0x9f, 0x21, 0xc6, 0x5f, 0x09, 0xfd, 0x4b, 0x7e, 0xf0, 0xcc, 0x40, 0x13, 0x56, 0x6f, 0x6f, 0x02, 0x00, 0x00, 0xff, 0xff, 0xbc, 0xcf, 0x6d, 0x50, 0xfe, 0x02, 0x00, 0x00, } lxd-2.0.0/dist/src/github.com/golang/protobuf/ptypes/struct/struct.proto0000644061062106075000000000731012702772352031077 0ustar00stgraberdomain admins00000000000000// Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. // https://developers.google.com/protocol-buffers/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. syntax = "proto3"; package google.protobuf; option go_package = "github.com/golang/protobuf/ptypes/struct;structpb"; option csharp_namespace = "Google.Protobuf.WellKnownTypes"; option java_package = "com.google.protobuf"; option java_outer_classname = "StructProto"; option java_multiple_files = true; option java_generate_equals_and_hash = true; option objc_class_prefix = "GPB"; // `Struct` represents a structured data value, consisting of fields // which map to dynamically typed values. In some languages, `Struct` // might be supported by a native representation. For example, in // scripting languages like JS a struct is represented as an // object. The details of that representation are described together // with the proto support for the language. // // The JSON representation for `Struct` is JSON object. message Struct { // Map of dynamically typed values. map fields = 1; } // `Value` represents a dynamically typed value which can be either // null, a number, a string, a boolean, a recursive struct value, or a // list of values. A producer of value is expected to set one of that // variants, absence of any variant indicates an error. // // The JSON representation for `Value` is JSON value. message Value { // The kind of value. oneof kind { // Represents a null value. NullValue null_value = 1; // Represents a double value. double number_value = 2; // Represents a string value. string string_value = 3; // Represents a boolean value. bool bool_value = 4; // Represents a structured value. Struct struct_value = 5; // Represents a repeated `Value`. ListValue list_value = 6; } } // `NullValue` is a singleton enumeration to represent the null value for the // `Value` type union. // // The JSON representation for `NullValue` is JSON `null`. enum NullValue { // Null value. NULL_VALUE = 0; } // `ListValue` is a wrapper around a repeated field of values. // // The JSON representation for `ListValue` is JSON array. message ListValue { // Repeated field of dynamically typed values. repeated Value values = 1; } lxd-2.0.0/dist/src/github.com/golang/protobuf/ptypes/timestamp_test.go0000644061062106075000000001211212702772352030527 0ustar00stgraberdomain admins00000000000000// Go support for Protocol Buffers - Google's data interchange format // // Copyright 2016 The Go Authors. All rights reserved. // https://github.com/golang/protobuf // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package ptypes import ( "math" "testing" "time" "github.com/golang/protobuf/proto" tspb "github.com/golang/protobuf/ptypes/timestamp" ) var tests = []struct { ts *tspb.Timestamp valid bool t time.Time }{ // The timestamp representing the Unix epoch date. {&tspb.Timestamp{0, 0}, true, utcDate(1970, 1, 1)}, // The smallest representable timestamp. {&tspb.Timestamp{math.MinInt64, math.MinInt32}, false, time.Unix(math.MinInt64, math.MinInt32).UTC()}, // The smallest representable timestamp with non-negative nanos. {&tspb.Timestamp{math.MinInt64, 0}, false, time.Unix(math.MinInt64, 0).UTC()}, // The earliest valid timestamp. {&tspb.Timestamp{minValidSeconds, 0}, true, utcDate(1, 1, 1)}, //"0001-01-01T00:00:00Z"}, // The largest representable timestamp. {&tspb.Timestamp{math.MaxInt64, math.MaxInt32}, false, time.Unix(math.MaxInt64, math.MaxInt32).UTC()}, // The largest representable timestamp with nanos in range. {&tspb.Timestamp{math.MaxInt64, 1e9 - 1}, false, time.Unix(math.MaxInt64, 1e9-1).UTC()}, // The largest valid timestamp. {&tspb.Timestamp{maxValidSeconds - 1, 1e9 - 1}, true, time.Date(9999, 12, 31, 23, 59, 59, 1e9-1, time.UTC)}, // The smallest invalid timestamp that is larger than the valid range. {&tspb.Timestamp{maxValidSeconds, 0}, false, time.Unix(maxValidSeconds, 0).UTC()}, // A date before the epoch. {&tspb.Timestamp{-281836800, 0}, true, utcDate(1961, 1, 26)}, // A date after the epoch. {&tspb.Timestamp{1296000000, 0}, true, utcDate(2011, 1, 26)}, // A date after the epoch, in the middle of the day. {&tspb.Timestamp{1296012345, 940483}, true, time.Date(2011, 1, 26, 3, 25, 45, 940483, time.UTC)}, } func TestValidateTimestamp(t *testing.T) { for _, s := range tests { got := validateTimestamp(s.ts) if (got == nil) != s.valid { t.Errorf("validateTimestamp(%v) = %v, want %v", s.ts, got, s.valid) } } } func TestTimestamp(t *testing.T) { for _, s := range tests { got, err := Timestamp(s.ts) if (err == nil) != s.valid { t.Errorf("Timestamp(%v) error = %v, but valid = %t", s.ts, err, s.valid) } else if s.valid && got != s.t { t.Errorf("Timestamp(%v) = %v, want %v", s.ts, got, s.t) } } // Special case: a nil Timestamp is an error, but returns the 0 Unix time. got, err := Timestamp(nil) want := time.Unix(0, 0).UTC() if got != want { t.Errorf("Timestamp(nil) = %v, want %v", got, want) } if err == nil { t.Errorf("Timestamp(nil) error = nil, expected error") } } func TestTimestampProto(t *testing.T) { for _, s := range tests { got, err := TimestampProto(s.t) if (err == nil) != s.valid { t.Errorf("TimestampProto(%v) error = %v, but valid = %t", s.t, err, s.valid) } else if s.valid && !proto.Equal(got, s.ts) { t.Errorf("TimestampProto(%v) = %v, want %v", s.t, got, s.ts) } } // No corresponding special case here: no time.Time results in a nil Timestamp. } func TestTimestampString(t *testing.T) { for _, test := range []struct { ts *tspb.Timestamp want string }{ // Not much testing needed because presumably time.Format is // well-tested. {&tspb.Timestamp{0, 0}, "1970-01-01T00:00:00Z"}, {&tspb.Timestamp{minValidSeconds - 1, 0}, "(timestamp: seconds:-62135596801 before 0001-01-01)"}, } { got := TimestampString(test.ts) if got != test.want { t.Errorf("TimestampString(%v) = %q, want %q", test.ts, got, test.want) } } } func utcDate(year, month, day int) time.Time { return time.Date(year, time.Month(month), day, 0, 0, 0, 0, time.UTC) } lxd-2.0.0/dist/src/github.com/golang/protobuf/ptypes/timestamp.go0000644061062106075000000001110212702772352027466 0ustar00stgraberdomain admins00000000000000// Go support for Protocol Buffers - Google's data interchange format // // Copyright 2016 The Go Authors. All rights reserved. // https://github.com/golang/protobuf // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package ptypes // This file implements operations on google.protobuf.Timestamp. import ( "errors" "fmt" "time" tspb "github.com/golang/protobuf/ptypes/timestamp" ) const ( // Seconds field of the earliest valid Timestamp. // This is time.Date(1, 1, 1, 0, 0, 0, 0, time.UTC).Unix(). minValidSeconds = -62135596800 // Seconds field just after the latest valid Timestamp. // This is time.Date(10000, 1, 1, 0, 0, 0, 0, time.UTC).Unix(). maxValidSeconds = 253402300800 ) // validateTimestamp determines whether a Timestamp is valid. // A valid timestamp represents a time in the range // [0001-01-01, 10000-01-01) and has a Nanos field // in the range [0, 1e9). // // If the Timestamp is valid, validateTimestamp returns nil. // Otherwise, it returns an error that describes // the problem. // // Every valid Timestamp can be represented by a time.Time, but the converse is not true. func validateTimestamp(ts *tspb.Timestamp) error { if ts == nil { return errors.New("timestamp: nil Timestamp") } if ts.Seconds < minValidSeconds { return fmt.Errorf("timestamp: %v before 0001-01-01", ts) } if ts.Seconds >= maxValidSeconds { return fmt.Errorf("timestamp: %v after 10000-01-01", ts) } if ts.Nanos < 0 || ts.Nanos >= 1e9 { return fmt.Errorf("timestamp: %v: nanos not in range [0, 1e9)", ts) } return nil } // Timestamp converts a google.protobuf.Timestamp proto to a time.Time. // It returns an error if the argument is invalid. // // Unlike most Go functions, if Timestamp returns an error, the first return value // is not the zero time.Time. Instead, it is the value obtained from the // time.Unix function when passed the contents of the Timestamp, in the UTC // locale. This may or may not be a meaningful time; many invalid Timestamps // do map to valid time.Times. // // A nil Timestamp returns an error. The first return value in that case is // undefined. func Timestamp(ts *tspb.Timestamp) (time.Time, error) { // Don't return the zero value on error, because corresponds to a valid // timestamp. Instead return whatever time.Unix gives us. var t time.Time if ts == nil { t = time.Unix(0, 0).UTC() // treat nil like the empty Timestamp } else { t = time.Unix(ts.Seconds, int64(ts.Nanos)).UTC() } return t, validateTimestamp(ts) } // TimestampProto converts the time.Time to a google.protobuf.Timestamp proto. // It returns an error if the resulting Timestamp is invalid. func TimestampProto(t time.Time) (*tspb.Timestamp, error) { seconds := t.Unix() nanos := int32(t.Sub(time.Unix(seconds, 0))) ts := &tspb.Timestamp{ Seconds: seconds, Nanos: nanos, } if err := validateTimestamp(ts); err != nil { return nil, err } return ts, nil } // TimestampString returns the RFC 3339 string for valid Timestamps. For invalid // Timestamps, it returns an error message in parentheses. func TimestampString(ts *tspb.Timestamp) string { t, err := Timestamp(ts) if err != nil { return fmt.Sprintf("(%v)", err) } return t.Format(time.RFC3339Nano) } lxd-2.0.0/dist/src/github.com/golang/protobuf/ptypes/any/0000755061062106075000000000000012702772352025730 5ustar00stgraberdomain admins00000000000000lxd-2.0.0/dist/src/github.com/golang/protobuf/ptypes/any/any.pb.go0000644061062106075000000001060712702772352027452 0ustar00stgraberdomain admins00000000000000// Code generated by protoc-gen-go. // source: github.com/golang/protobuf/ptypes/any/any.proto // DO NOT EDIT! /* Package any is a generated protocol buffer package. It is generated from these files: github.com/golang/protobuf/ptypes/any/any.proto It has these top-level messages: Any */ package any import proto "github.com/golang/protobuf/proto" import fmt "fmt" import math "math" // Reference imports to suppress errors if they are not otherwise used. var _ = proto.Marshal var _ = fmt.Errorf var _ = math.Inf // This is a compile-time assertion to ensure that this generated file // is compatible with the proto package it is being compiled against. const _ = proto.ProtoPackageIsVersion1 // `Any` contains an arbitrary serialized message along with a URL // that describes the type of the serialized message. // // // JSON // ==== // The JSON representation of an `Any` value uses the regular // representation of the deserialized, embedded message, with an // additional field `@type` which contains the type URL. Example: // // package google.profile; // message Person { // string first_name = 1; // string last_name = 2; // } // // { // "@type": "type.googleapis.com/google.profile.Person", // "firstName": , // "lastName": // } // // If the embedded message type is well-known and has a custom JSON // representation, that representation will be embedded adding a field // `value` which holds the custom JSON in addition to the `@type` // field. Example (for message [google.protobuf.Duration][]): // // { // "@type": "type.googleapis.com/google.protobuf.Duration", // "value": "1.212s" // } // type Any struct { // A URL/resource name whose content describes the type of the // serialized message. // // For URLs which use the schema `http`, `https`, or no schema, the // following restrictions and interpretations apply: // // * If no schema is provided, `https` is assumed. // * The last segment of the URL's path must represent the fully // qualified name of the type (as in `path/google.protobuf.Duration`). // * An HTTP GET on the URL must yield a [google.protobuf.Type][] // value in binary format, or produce an error. // * Applications are allowed to cache lookup results based on the // URL, or have them precompiled into a binary to avoid any // lookup. Therefore, binary compatibility needs to be preserved // on changes to types. (Use versioned type names to manage // breaking changes.) // // Schemas other than `http`, `https` (or the empty schema) might be // used with implementation specific semantics. // TypeUrl string `protobuf:"bytes,1,opt,name=type_url,json=typeUrl" json:"type_url,omitempty"` // Must be valid serialized data of the above specified type. Value []byte `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` } func (m *Any) Reset() { *m = Any{} } func (m *Any) String() string { return proto.CompactTextString(m) } func (*Any) ProtoMessage() {} func (*Any) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } func (*Any) XXX_WellKnownType() string { return "Any" } func init() { proto.RegisterType((*Any)(nil), "google.protobuf.Any") } var fileDescriptor0 = []byte{ // 184 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0xd2, 0x4f, 0xcf, 0x2c, 0xc9, 0x28, 0x4d, 0xd2, 0x4b, 0xce, 0xcf, 0xd5, 0x4f, 0xcf, 0xcf, 0x49, 0xcc, 0x4b, 0xd7, 0x2f, 0x28, 0xca, 0x2f, 0xc9, 0x4f, 0x2a, 0x4d, 0xd3, 0x2f, 0x28, 0xa9, 0x2c, 0x48, 0x2d, 0xd6, 0x4f, 0xcc, 0xab, 0x04, 0x61, 0x3d, 0xb0, 0xb8, 0x10, 0x7f, 0x7a, 0x7e, 0x7e, 0x7a, 0x4e, 0xaa, 0x1e, 0x4c, 0x95, 0x92, 0x19, 0x17, 0xb3, 0x63, 0x5e, 0xa5, 0x90, 0x24, 0x17, 0x07, 0x48, 0x79, 0x7c, 0x69, 0x51, 0x8e, 0x04, 0xa3, 0x02, 0xa3, 0x06, 0x67, 0x10, 0x3b, 0x88, 0x1f, 0x5a, 0x94, 0x23, 0x24, 0xc2, 0xc5, 0x5a, 0x96, 0x98, 0x53, 0x9a, 0x2a, 0xc1, 0x04, 0x14, 0xe7, 0x09, 0x82, 0x70, 0x9c, 0x8a, 0xb8, 0x84, 0x81, 0x96, 0xea, 0xa1, 0x19, 0xe7, 0xc4, 0x01, 0x34, 0x2c, 0x00, 0xc4, 0x09, 0x60, 0x8c, 0x52, 0x25, 0xca, 0x71, 0x0b, 0x18, 0x19, 0x17, 0x31, 0x31, 0xbb, 0x07, 0x38, 0xad, 0x62, 0x92, 0x73, 0x87, 0x98, 0x16, 0x00, 0x55, 0xa5, 0x17, 0x9e, 0x9a, 0x93, 0xe3, 0x9d, 0x97, 0x5f, 0x9e, 0x17, 0x02, 0x52, 0x9d, 0xc4, 0x06, 0xd6, 0x6e, 0x0c, 0x08, 0x00, 0x00, 0xff, 0xff, 0xc6, 0x4d, 0x03, 0x23, 0xf6, 0x00, 0x00, 0x00, } lxd-2.0.0/dist/src/github.com/golang/protobuf/ptypes/any/any.proto0000644061062106075000000001002212702772352027577 0ustar00stgraberdomain admins00000000000000// Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. // https://developers.google.com/protocol-buffers/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. syntax = "proto3"; package google.protobuf; option go_package = "github.com/golang/protobuf/ptypes/any"; option csharp_namespace = "Google.Protobuf.WellKnownTypes"; option java_package = "com.google.protobuf"; option java_outer_classname = "AnyProto"; option java_multiple_files = true; option java_generate_equals_and_hash = true; option objc_class_prefix = "GPB"; // `Any` contains an arbitrary serialized message along with a URL // that describes the type of the serialized message. // // // JSON // ==== // The JSON representation of an `Any` value uses the regular // representation of the deserialized, embedded message, with an // additional field `@type` which contains the type URL. Example: // // package google.profile; // message Person { // string first_name = 1; // string last_name = 2; // } // // { // "@type": "type.googleapis.com/google.profile.Person", // "firstName": , // "lastName": // } // // If the embedded message type is well-known and has a custom JSON // representation, that representation will be embedded adding a field // `value` which holds the custom JSON in addition to the `@type` // field. Example (for message [google.protobuf.Duration][]): // // { // "@type": "type.googleapis.com/google.protobuf.Duration", // "value": "1.212s" // } // message Any { // A URL/resource name whose content describes the type of the // serialized message. // // For URLs which use the schema `http`, `https`, or no schema, the // following restrictions and interpretations apply: // // * If no schema is provided, `https` is assumed. // * The last segment of the URL's path must represent the fully // qualified name of the type (as in `path/google.protobuf.Duration`). // * An HTTP GET on the URL must yield a [google.protobuf.Type][] // value in binary format, or produce an error. // * Applications are allowed to cache lookup results based on the // URL, or have them precompiled into a binary to avoid any // lookup. Therefore, binary compatibility needs to be preserved // on changes to types. (Use versioned type names to manage // breaking changes.) // // Schemas other than `http`, `https` (or the empty schema) might be // used with implementation specific semantics. // string type_url = 1; // Must be valid serialized data of the above specified type. bytes value = 2; } lxd-2.0.0/dist/src/github.com/golang/protobuf/ptypes/regen.sh0000755061062106075000000000414012702772352026577 0ustar00stgraberdomain admins00000000000000#!/bin/bash -e # # This script fetches and rebuilds the "well-known types" protocol buffers. # To run this you will need protoc and goprotobuf installed; # see https://github.com/golang/protobuf for instructions. # You also need Go and Git installed. PKG=github.com/golang/protobuf/ptypes UPSTREAM=https://github.com/google/protobuf UPSTREAM_SUBDIR=src/google/protobuf PROTO_FILES=' any.proto duration.proto empty.proto struct.proto timestamp.proto wrappers.proto ' function die() { echo 1>&2 $* exit 1 } # Sanity check that the right tools are accessible. for tool in go git protoc protoc-gen-go; do q=$(which $tool) || die "didn't find $tool" echo 1>&2 "$tool: $q" done tmpdir=$(mktemp -d -t regen-wkt.XXXXXX) trap 'rm -rf $tmpdir' EXIT echo -n 1>&2 "finding package dir... " pkgdir=$(go list -f '{{.Dir}}' $PKG) echo 1>&2 $pkgdir base=$(echo $pkgdir | sed "s,/$PKG\$,,") echo 1>&2 "base: $base" cd $base echo 1>&2 "fetching latest protos... " git clone -q $UPSTREAM $tmpdir # Pass 1: build mapping from upstream filename to our filename. declare -A filename_map for f in $(cd $PKG && find * -name '*.proto'); do echo -n 1>&2 "looking for latest version of $f... " up=$(cd $tmpdir/$UPSTREAM_SUBDIR && find * -name $(basename $f) | grep -v /testdata/) echo 1>&2 $up if [ $(echo $up | wc -w) != "1" ]; then die "not exactly one match" fi filename_map[$up]=$f done # Pass 2: copy files, making necessary adjustments. for up in "${!filename_map[@]}"; do f=${filename_map[$up]} shortname=$(basename $f | sed 's,\.proto$,,') cat $tmpdir/$UPSTREAM_SUBDIR/$up | # Adjust proto package. # TODO(dsymonds): Remove when the right go_package options are upstream. sed '/^package /a option go_package = "github.com\/golang\/protobuf\/ptypes\/'${shortname}'";' | # Unfortunately "package struct" and "package type" don't work. sed '/option go_package/s,struct",struct;structpb",' | cat > $PKG/$f done # Run protoc once per package. for dir in $(find $PKG -name '*.proto' | xargs dirname | sort | uniq); do echo 1>&2 "* $dir" protoc --go_out=. $dir/*.proto done echo 1>&2 "All OK" lxd-2.0.0/dist/src/github.com/golang/protobuf/ptypes/wrappers/0000755061062106075000000000000012702772352027004 5ustar00stgraberdomain admins00000000000000lxd-2.0.0/dist/src/github.com/golang/protobuf/ptypes/wrappers/wrappers.proto0000644061062106075000000000731612702772352031743 0ustar00stgraberdomain admins00000000000000// Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. // https://developers.google.com/protocol-buffers/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Wrappers for primitive (non-message) types. These types are useful // for embedding primitives in the `google.protobuf.Any` type and for places // where we need to distinguish between the absence of a primitive // typed field and its default value. syntax = "proto3"; package google.protobuf; option go_package = "github.com/golang/protobuf/ptypes/wrappers"; option csharp_namespace = "Google.Protobuf.WellKnownTypes"; option cc_enable_arenas = true; option java_package = "com.google.protobuf"; option java_outer_classname = "WrappersProto"; option java_multiple_files = true; option java_generate_equals_and_hash = true; option objc_class_prefix = "GPB"; // Wrapper message for `double`. // // The JSON representation for `DoubleValue` is JSON number. message DoubleValue { // The double value. double value = 1; } // Wrapper message for `float`. // // The JSON representation for `FloatValue` is JSON number. message FloatValue { // The float value. float value = 1; } // Wrapper message for `int64`. // // The JSON representation for `Int64Value` is JSON string. message Int64Value { // The int64 value. int64 value = 1; } // Wrapper message for `uint64`. // // The JSON representation for `UInt64Value` is JSON string. message UInt64Value { // The uint64 value. uint64 value = 1; } // Wrapper message for `int32`. // // The JSON representation for `Int32Value` is JSON number. message Int32Value { // The int32 value. int32 value = 1; } // Wrapper message for `uint32`. // // The JSON representation for `UInt32Value` is JSON number. message UInt32Value { // The uint32 value. uint32 value = 1; } // Wrapper message for `bool`. // // The JSON representation for `BoolValue` is JSON `true` and `false`. message BoolValue { // The bool value. bool value = 1; } // Wrapper message for `string`. // // The JSON representation for `StringValue` is JSON string. message StringValue { // The string value. string value = 1; } // Wrapper message for `bytes`. // // The JSON representation for `BytesValue` is JSON string. message BytesValue { // The bytes value. bytes value = 1; } lxd-2.0.0/dist/src/github.com/golang/protobuf/ptypes/wrappers/wrappers.pb.go0000644061062106075000000002036112702772352031600 0ustar00stgraberdomain admins00000000000000// Code generated by protoc-gen-go. // source: github.com/golang/protobuf/ptypes/wrappers/wrappers.proto // DO NOT EDIT! /* Package wrappers is a generated protocol buffer package. It is generated from these files: github.com/golang/protobuf/ptypes/wrappers/wrappers.proto It has these top-level messages: DoubleValue FloatValue Int64Value UInt64Value Int32Value UInt32Value BoolValue StringValue BytesValue */ package wrappers import proto "github.com/golang/protobuf/proto" import fmt "fmt" import math "math" // Reference imports to suppress errors if they are not otherwise used. var _ = proto.Marshal var _ = fmt.Errorf var _ = math.Inf // This is a compile-time assertion to ensure that this generated file // is compatible with the proto package it is being compiled against. const _ = proto.ProtoPackageIsVersion1 // Wrapper message for `double`. // // The JSON representation for `DoubleValue` is JSON number. type DoubleValue struct { // The double value. Value float64 `protobuf:"fixed64,1,opt,name=value" json:"value,omitempty"` } func (m *DoubleValue) Reset() { *m = DoubleValue{} } func (m *DoubleValue) String() string { return proto.CompactTextString(m) } func (*DoubleValue) ProtoMessage() {} func (*DoubleValue) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } func (*DoubleValue) XXX_WellKnownType() string { return "DoubleValue" } // Wrapper message for `float`. // // The JSON representation for `FloatValue` is JSON number. type FloatValue struct { // The float value. Value float32 `protobuf:"fixed32,1,opt,name=value" json:"value,omitempty"` } func (m *FloatValue) Reset() { *m = FloatValue{} } func (m *FloatValue) String() string { return proto.CompactTextString(m) } func (*FloatValue) ProtoMessage() {} func (*FloatValue) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } func (*FloatValue) XXX_WellKnownType() string { return "FloatValue" } // Wrapper message for `int64`. // // The JSON representation for `Int64Value` is JSON string. type Int64Value struct { // The int64 value. Value int64 `protobuf:"varint,1,opt,name=value" json:"value,omitempty"` } func (m *Int64Value) Reset() { *m = Int64Value{} } func (m *Int64Value) String() string { return proto.CompactTextString(m) } func (*Int64Value) ProtoMessage() {} func (*Int64Value) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} } func (*Int64Value) XXX_WellKnownType() string { return "Int64Value" } // Wrapper message for `uint64`. // // The JSON representation for `UInt64Value` is JSON string. type UInt64Value struct { // The uint64 value. Value uint64 `protobuf:"varint,1,opt,name=value" json:"value,omitempty"` } func (m *UInt64Value) Reset() { *m = UInt64Value{} } func (m *UInt64Value) String() string { return proto.CompactTextString(m) } func (*UInt64Value) ProtoMessage() {} func (*UInt64Value) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} } func (*UInt64Value) XXX_WellKnownType() string { return "UInt64Value" } // Wrapper message for `int32`. // // The JSON representation for `Int32Value` is JSON number. type Int32Value struct { // The int32 value. Value int32 `protobuf:"varint,1,opt,name=value" json:"value,omitempty"` } func (m *Int32Value) Reset() { *m = Int32Value{} } func (m *Int32Value) String() string { return proto.CompactTextString(m) } func (*Int32Value) ProtoMessage() {} func (*Int32Value) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} } func (*Int32Value) XXX_WellKnownType() string { return "Int32Value" } // Wrapper message for `uint32`. // // The JSON representation for `UInt32Value` is JSON number. type UInt32Value struct { // The uint32 value. Value uint32 `protobuf:"varint,1,opt,name=value" json:"value,omitempty"` } func (m *UInt32Value) Reset() { *m = UInt32Value{} } func (m *UInt32Value) String() string { return proto.CompactTextString(m) } func (*UInt32Value) ProtoMessage() {} func (*UInt32Value) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} } func (*UInt32Value) XXX_WellKnownType() string { return "UInt32Value" } // Wrapper message for `bool`. // // The JSON representation for `BoolValue` is JSON `true` and `false`. type BoolValue struct { // The bool value. Value bool `protobuf:"varint,1,opt,name=value" json:"value,omitempty"` } func (m *BoolValue) Reset() { *m = BoolValue{} } func (m *BoolValue) String() string { return proto.CompactTextString(m) } func (*BoolValue) ProtoMessage() {} func (*BoolValue) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{6} } func (*BoolValue) XXX_WellKnownType() string { return "BoolValue" } // Wrapper message for `string`. // // The JSON representation for `StringValue` is JSON string. type StringValue struct { // The string value. Value string `protobuf:"bytes,1,opt,name=value" json:"value,omitempty"` } func (m *StringValue) Reset() { *m = StringValue{} } func (m *StringValue) String() string { return proto.CompactTextString(m) } func (*StringValue) ProtoMessage() {} func (*StringValue) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{7} } func (*StringValue) XXX_WellKnownType() string { return "StringValue" } // Wrapper message for `bytes`. // // The JSON representation for `BytesValue` is JSON string. type BytesValue struct { // The bytes value. Value []byte `protobuf:"bytes,1,opt,name=value,proto3" json:"value,omitempty"` } func (m *BytesValue) Reset() { *m = BytesValue{} } func (m *BytesValue) String() string { return proto.CompactTextString(m) } func (*BytesValue) ProtoMessage() {} func (*BytesValue) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{8} } func (*BytesValue) XXX_WellKnownType() string { return "BytesValue" } func init() { proto.RegisterType((*DoubleValue)(nil), "google.protobuf.DoubleValue") proto.RegisterType((*FloatValue)(nil), "google.protobuf.FloatValue") proto.RegisterType((*Int64Value)(nil), "google.protobuf.Int64Value") proto.RegisterType((*UInt64Value)(nil), "google.protobuf.UInt64Value") proto.RegisterType((*Int32Value)(nil), "google.protobuf.Int32Value") proto.RegisterType((*UInt32Value)(nil), "google.protobuf.UInt32Value") proto.RegisterType((*BoolValue)(nil), "google.protobuf.BoolValue") proto.RegisterType((*StringValue)(nil), "google.protobuf.StringValue") proto.RegisterType((*BytesValue)(nil), "google.protobuf.BytesValue") } var fileDescriptor0 = []byte{ // 258 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0xb2, 0x4c, 0xcf, 0x2c, 0xc9, 0x28, 0x4d, 0xd2, 0x4b, 0xce, 0xcf, 0xd5, 0x4f, 0xcf, 0xcf, 0x49, 0xcc, 0x4b, 0xd7, 0x2f, 0x28, 0xca, 0x2f, 0xc9, 0x4f, 0x2a, 0x4d, 0xd3, 0x2f, 0x28, 0xa9, 0x2c, 0x48, 0x2d, 0xd6, 0x2f, 0x2f, 0x4a, 0x2c, 0x28, 0x48, 0x2d, 0x42, 0x30, 0xf4, 0xc0, 0x2a, 0x84, 0xf8, 0xd3, 0xf3, 0xf3, 0xd3, 0x73, 0x52, 0xf5, 0x60, 0xea, 0x95, 0x94, 0xb9, 0xb8, 0x5d, 0xf2, 0x4b, 0x93, 0x72, 0x52, 0xc3, 0x12, 0x73, 0x4a, 0x53, 0x85, 0x44, 0xb8, 0x58, 0xcb, 0x40, 0x0c, 0x09, 0x46, 0x05, 0x46, 0x0d, 0xc6, 0x20, 0x08, 0x47, 0x49, 0x89, 0x8b, 0xcb, 0x2d, 0x27, 0x3f, 0xb1, 0x04, 0x8b, 0x1a, 0x26, 0x24, 0x35, 0x9e, 0x79, 0x25, 0x66, 0x26, 0x58, 0xd4, 0x30, 0xc3, 0xd4, 0x00, 0x2d, 0x0b, 0xc5, 0xa5, 0x88, 0x05, 0xd5, 0x20, 0x63, 0x23, 0x2c, 0x6a, 0x58, 0xd1, 0x0c, 0xc2, 0xaa, 0x88, 0x17, 0xa6, 0x48, 0x91, 0x8b, 0xd3, 0x29, 0x3f, 0x3f, 0x07, 0x8b, 0x12, 0x0e, 0x24, 0x73, 0x82, 0x4b, 0x8a, 0x32, 0xf3, 0xd2, 0xb1, 0x28, 0xe2, 0x44, 0x72, 0x90, 0x53, 0x65, 0x49, 0x6a, 0x31, 0x16, 0x35, 0x3c, 0x50, 0x35, 0x4e, 0xf5, 0x5c, 0xc2, 0xc0, 0xd8, 0xd0, 0x43, 0x0b, 0x5d, 0x27, 0xde, 0x70, 0x68, 0xf0, 0x07, 0x80, 0x44, 0x02, 0x18, 0xa3, 0xb4, 0x88, 0x8f, 0xba, 0x05, 0x8c, 0x8c, 0x3f, 0x18, 0x19, 0x17, 0x31, 0x31, 0xbb, 0x07, 0x38, 0xad, 0x62, 0x92, 0x73, 0x87, 0x18, 0x1d, 0x00, 0x55, 0xad, 0x17, 0x9e, 0x9a, 0x93, 0xe3, 0x9d, 0x97, 0x5f, 0x9e, 0x17, 0x02, 0xd2, 0x95, 0xc4, 0x06, 0x36, 0xc6, 0x18, 0x10, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xdf, 0x64, 0x4b, 0x1c, 0x02, 0x00, 0x00, } lxd-2.0.0/dist/src/github.com/golang/protobuf/ptypes/duration_test.go0000644061062106075000000001143412702772352030357 0ustar00stgraberdomain admins00000000000000// Go support for Protocol Buffers - Google's data interchange format // // Copyright 2016 The Go Authors. All rights reserved. // https://github.com/golang/protobuf // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package ptypes import ( "math" "testing" "time" "github.com/golang/protobuf/proto" durpb "github.com/golang/protobuf/ptypes/duration" ) const ( minGoSeconds = math.MinInt64 / int64(1e9) maxGoSeconds = math.MaxInt64 / int64(1e9) ) var durationTests = []struct { proto *durpb.Duration isValid bool inRange bool dur time.Duration }{ // The zero duration. {&durpb.Duration{0, 0}, true, true, 0}, // Some ordinary non-zero durations. {&durpb.Duration{100, 0}, true, true, 100 * time.Second}, {&durpb.Duration{-100, 0}, true, true, -100 * time.Second}, {&durpb.Duration{100, 987}, true, true, 100*time.Second + 987}, {&durpb.Duration{-100, -987}, true, true, -(100*time.Second + 987)}, // The largest duration representable in Go. {&durpb.Duration{maxGoSeconds, int32(math.MaxInt64 - 1e9*maxGoSeconds)}, true, true, math.MaxInt64}, // The smallest duration representable in Go. {&durpb.Duration{minGoSeconds, int32(math.MinInt64 - 1e9*minGoSeconds)}, true, true, math.MinInt64}, {nil, false, false, 0}, {&durpb.Duration{-100, 987}, false, false, 0}, {&durpb.Duration{100, -987}, false, false, 0}, {&durpb.Duration{math.MinInt64, 0}, false, false, 0}, {&durpb.Duration{math.MaxInt64, 0}, false, false, 0}, // The largest valid duration. {&durpb.Duration{maxSeconds, 1e9 - 1}, true, false, 0}, // The smallest valid duration. {&durpb.Duration{minSeconds, -(1e9 - 1)}, true, false, 0}, // The smallest invalid duration above the valid range. {&durpb.Duration{maxSeconds + 1, 0}, false, false, 0}, // The largest invalid duration below the valid range. {&durpb.Duration{minSeconds - 1, -(1e9 - 1)}, false, false, 0}, // One nanosecond past the largest duration representable in Go. {&durpb.Duration{maxGoSeconds, int32(math.MaxInt64-1e9*maxGoSeconds) + 1}, true, false, 0}, // One nanosecond past the smallest duration representable in Go. {&durpb.Duration{minGoSeconds, int32(math.MinInt64-1e9*minGoSeconds) - 1}, true, false, 0}, // One second past the largest duration representable in Go. {&durpb.Duration{maxGoSeconds + 1, int32(math.MaxInt64 - 1e9*maxGoSeconds)}, true, false, 0}, // One second past the smallest duration representable in Go. {&durpb.Duration{minGoSeconds - 1, int32(math.MinInt64 - 1e9*minGoSeconds)}, true, false, 0}, } func TestValidateDuration(t *testing.T) { for _, test := range durationTests { err := validateDuration(test.proto) gotValid := (err == nil) if gotValid != test.isValid { t.Errorf("validateDuration(%v) = %t, want %t", test.proto, gotValid, test.isValid) } } } func TestDuration(t *testing.T) { for _, test := range durationTests { got, err := Duration(test.proto) gotOK := (err == nil) wantOK := test.isValid && test.inRange if gotOK != wantOK { t.Errorf("Duration(%v) ok = %t, want %t", test.proto, gotOK, wantOK) } if err == nil && got != test.dur { t.Errorf("Duration(%v) = %v, want %v", test.proto, got, test.dur) } } } func TestDurationProto(t *testing.T) { for _, test := range durationTests { if test.isValid && test.inRange { got := DurationProto(test.dur) if !proto.Equal(got, test.proto) { t.Errorf("DurationProto(%v) = %v, want %v", test.dur, got, test.proto) } } } } lxd-2.0.0/dist/src/github.com/golang/protobuf/ptypes/any.go0000644061062106075000000001111512702772352026256 0ustar00stgraberdomain admins00000000000000// Go support for Protocol Buffers - Google's data interchange format // // Copyright 2016 The Go Authors. All rights reserved. // https://github.com/golang/protobuf // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package ptypes // This file implements functions to marshal proto.Message to/from // google.protobuf.Any message. import ( "fmt" "reflect" "strings" "github.com/golang/protobuf/proto" "github.com/golang/protobuf/ptypes/any" ) const googleApis = "type.googleapis.com/" // AnyMessageName returns the name of the message contained in a google.protobuf.Any message. // // Note that regular type assertions should be done using the Is // function. AnyMessageName is provided for less common use cases like filtering a // sequence of Any messages based on a set of allowed message type names. func AnyMessageName(any *any.Any) (string, error) { slash := strings.LastIndex(any.TypeUrl, "/") if slash < 0 { return "", fmt.Errorf("message type url %q is invalid", any.TypeUrl) } return any.TypeUrl[slash+1:], nil } // MarshalAny takes the protocol buffer and encodes it into google.protobuf.Any. func MarshalAny(pb proto.Message) (*any.Any, error) { value, err := proto.Marshal(pb) if err != nil { return nil, err } return &any.Any{TypeUrl: googleApis + proto.MessageName(pb), Value: value}, nil } // DynamicAny is a value that can be passed to UnmarshalAny to automatically // allocate a proto.Message for the type specified in a google.protobuf.Any // message. The allocated message is stored in the embedded proto.Message. // // Example: // // var x ptypes.DynamicAny // if err := ptypes.UnmarshalAny(a, &x); err != nil { ... } // fmt.Printf("unmarshaled message: %v", x.Message) type DynamicAny struct { proto.Message } // Empty returns a new proto.Message of the type specified in a // google.protobuf.Any message. It returns an error if corresponding message // type isn't linked in. func Empty(any *any.Any) (proto.Message, error) { aname, err := AnyMessageName(any) if err != nil { return nil, err } t := proto.MessageType(aname) if t == nil { return nil, fmt.Errorf("any: message type %q isn't linked in", aname) } return reflect.New(t.Elem()).Interface().(proto.Message), nil } // UnmarshalAny parses the protocol buffer representation in a google.protobuf.Any // message and places the decoded result in pb. It returns an error if type of // contents of Any message does not match type of pb message. // // pb can be a proto.Message, or a *DynamicAny. func UnmarshalAny(any *any.Any, pb proto.Message) error { if d, ok := pb.(*DynamicAny); ok { if d.Message == nil { var err error d.Message, err = Empty(any) if err != nil { return err } } return UnmarshalAny(any, d.Message) } aname, err := AnyMessageName(any) if err != nil { return err } mname := proto.MessageName(pb) if aname != mname { return fmt.Errorf("mismatched message type: got %q want %q", aname, mname) } return proto.Unmarshal(any.Value, pb) } // Is returns true if any value contains a given message type. func Is(any *any.Any, pb proto.Message) bool { aname, err := AnyMessageName(any) if err != nil { return false } return aname == proto.MessageName(pb) } lxd-2.0.0/dist/src/github.com/godbus/0000755061062106075000000000000012702772372021773 5ustar00stgraberdomain admins00000000000000lxd-2.0.0/dist/src/github.com/godbus/dbus/0000755061062106075000000000000012702772372022730 5ustar00stgraberdomain admins00000000000000lxd-2.0.0/dist/src/github.com/godbus/dbus/prop/0000755061062106075000000000000012702772372023710 5ustar00stgraberdomain admins00000000000000lxd-2.0.0/dist/src/github.com/godbus/dbus/prop/prop.go0000644061062106075000000001701212702772372025220 0ustar00stgraberdomain admins00000000000000// Package prop provides the Properties struct which can be used to implement // org.freedesktop.DBus.Properties. package prop import ( "github.com/godbus/dbus" "github.com/godbus/dbus/introspect" "sync" ) // EmitType controls how org.freedesktop.DBus.Properties.PropertiesChanged is // emitted for a property. If it is EmitTrue, the signal is emitted. If it is // EmitInvalidates, the signal is also emitted, but the new value of the property // is not disclosed. type EmitType byte const ( EmitFalse EmitType = iota EmitTrue EmitInvalidates ) // ErrIfaceNotFound is the error returned to peers who try to access properties // on interfaces that aren't found. var ErrIfaceNotFound = dbus.NewError("org.freedesktop.DBus.Properties.Error.InterfaceNotFound", nil) // ErrPropNotFound is the error returned to peers trying to access properties // that aren't found. var ErrPropNotFound = dbus.NewError("org.freedesktop.DBus.Properties.Error.PropertyNotFound", nil) // ErrReadOnly is the error returned to peers trying to set a read-only // property. var ErrReadOnly = dbus.NewError("org.freedesktop.DBus.Properties.Error.ReadOnly", nil) // ErrInvalidArg is returned to peers if the type of the property that is being // changed and the argument don't match. var ErrInvalidArg = dbus.NewError("org.freedesktop.DBus.Properties.Error.InvalidArg", nil) // The introspection data for the org.freedesktop.DBus.Properties interface. var IntrospectData = introspect.Interface{ Name: "org.freedesktop.DBus.Properties", Methods: []introspect.Method{ { Name: "Get", Args: []introspect.Arg{ {"interface", "s", "in"}, {"property", "s", "in"}, {"value", "v", "out"}, }, }, { Name: "GetAll", Args: []introspect.Arg{ {"interface", "s", "in"}, {"props", "a{sv}", "out"}, }, }, { Name: "Set", Args: []introspect.Arg{ {"interface", "s", "in"}, {"property", "s", "in"}, {"value", "v", "in"}, }, }, }, Signals: []introspect.Signal{ { Name: "PropertiesChanged", Args: []introspect.Arg{ {"interface", "s", "out"}, {"changed_properties", "a{sv}", "out"}, {"invalidates_properties", "as", "out"}, }, }, }, } // The introspection data for the org.freedesktop.DBus.Properties interface, as // a string. const IntrospectDataString = ` ` // Prop represents a single property. It is used for creating a Properties // value. type Prop struct { // Initial value. Must be a DBus-representable type. Value interface{} // If true, the value can be modified by calls to Set. Writable bool // Controls how org.freedesktop.DBus.Properties.PropertiesChanged is // emitted if this property changes. Emit EmitType // If not nil, anytime this property is changed by Set, this function is // called with an appropiate Change as its argument. If the returned error // is not nil, it is sent back to the caller of Set and the property is not // changed. Callback func(*Change) *dbus.Error } // Change represents a change of a property by a call to Set. type Change struct { Props *Properties Iface string Name string Value interface{} } // Properties is a set of values that can be made available to the message bus // using the org.freedesktop.DBus.Properties interface. It is safe for // concurrent use by multiple goroutines. type Properties struct { m map[string]map[string]*Prop mut sync.RWMutex conn *dbus.Conn path dbus.ObjectPath } // New returns a new Properties structure that manages the given properties. // The key for the first-level map of props is the name of the interface; the // second-level key is the name of the property. The returned structure will be // exported as org.freedesktop.DBus.Properties on path. func New(conn *dbus.Conn, path dbus.ObjectPath, props map[string]map[string]*Prop) *Properties { p := &Properties{m: props, conn: conn, path: path} conn.Export(p, path, "org.freedesktop.DBus.Properties") return p } // Get implements org.freedesktop.DBus.Properties.Get. func (p *Properties) Get(iface, property string) (dbus.Variant, *dbus.Error) { p.mut.RLock() defer p.mut.RUnlock() m, ok := p.m[iface] if !ok { return dbus.Variant{}, ErrIfaceNotFound } prop, ok := m[property] if !ok { return dbus.Variant{}, ErrPropNotFound } return dbus.MakeVariant(prop.Value), nil } // GetAll implements org.freedesktop.DBus.Properties.GetAll. func (p *Properties) GetAll(iface string) (map[string]dbus.Variant, *dbus.Error) { p.mut.RLock() defer p.mut.RUnlock() m, ok := p.m[iface] if !ok { return nil, ErrIfaceNotFound } rm := make(map[string]dbus.Variant, len(m)) for k, v := range m { rm[k] = dbus.MakeVariant(v.Value) } return rm, nil } // GetMust returns the value of the given property and panics if either the // interface or the property name are invalid. func (p *Properties) GetMust(iface, property string) interface{} { p.mut.RLock() defer p.mut.RUnlock() return p.m[iface][property].Value } // Introspection returns the introspection data that represents the properties // of iface. func (p *Properties) Introspection(iface string) []introspect.Property { p.mut.RLock() defer p.mut.RUnlock() m := p.m[iface] s := make([]introspect.Property, 0, len(m)) for k, v := range m { p := introspect.Property{Name: k, Type: dbus.SignatureOf(v.Value).String()} if v.Writable { p.Access = "readwrite" } else { p.Access = "read" } s = append(s, p) } return s } // set sets the given property and emits PropertyChanged if appropiate. p.mut // must already be locked. func (p *Properties) set(iface, property string, v interface{}) { prop := p.m[iface][property] prop.Value = v switch prop.Emit { case EmitFalse: // do nothing case EmitInvalidates: p.conn.Emit(p.path, "org.freedesktop.DBus.Properties.PropertiesChanged", iface, map[string]dbus.Variant{}, []string{property}) case EmitTrue: p.conn.Emit(p.path, "org.freedesktop.DBus.Properties.PropertiesChanged", iface, map[string]dbus.Variant{property: dbus.MakeVariant(v)}, []string{}) default: panic("invalid value for EmitType") } } // Set implements org.freedesktop.Properties.Set. func (p *Properties) Set(iface, property string, newv dbus.Variant) *dbus.Error { p.mut.Lock() defer p.mut.Unlock() m, ok := p.m[iface] if !ok { return ErrIfaceNotFound } prop, ok := m[property] if !ok { return ErrPropNotFound } if !prop.Writable { return ErrReadOnly } if newv.Signature() != dbus.SignatureOf(prop.Value) { return ErrInvalidArg } if prop.Callback != nil { err := prop.Callback(&Change{p, iface, property, newv.Value()}) if err != nil { return err } } p.set(iface, property, newv.Value()) return nil } // SetMust sets the value of the given property and panics if the interface or // the property name are invalid. func (p *Properties) SetMust(iface, property string, v interface{}) { p.mut.Lock() p.set(iface, property, v) p.mut.Unlock() } lxd-2.0.0/dist/src/github.com/godbus/dbus/homedir_static.go0000644061062106075000000000115112702772372026253 0ustar00stgraberdomain admins00000000000000// +build static_build package dbus import ( "bufio" "os" "strconv" "strings" ) func lookupHomeDir() string { myUid := os.Getuid() f, err := os.Open("/etc/passwd") if err != nil { return "/" } defer f.Close() s := bufio.NewScanner(f) for s.Scan() { if err := s.Err(); err != nil { break } line := strings.TrimSpace(s.Text()) if line == "" { continue } parts := strings.Split(line, ":") if len(parts) >= 6 { uid, err := strconv.Atoi(parts[2]) if err == nil && uid == myUid { return parts[5] } } } // Default to / if we can't get a better value return "/" } lxd-2.0.0/dist/src/github.com/godbus/dbus/transport_generic.go0000644061062106075000000000120412702772372027004 0ustar00stgraberdomain admins00000000000000package dbus import ( "encoding/binary" "errors" "io" ) type genericTransport struct { io.ReadWriteCloser } func (t genericTransport) SendNullByte() error { _, err := t.Write([]byte{0}) return err } func (t genericTransport) SupportsUnixFDs() bool { return false } func (t genericTransport) EnableUnixFDs() {} func (t genericTransport) ReadMessage() (*Message, error) { return DecodeMessage(t) } func (t genericTransport) SendMessage(msg *Message) error { for _, v := range msg.Body { if _, ok := v.(UnixFD); ok { return errors.New("dbus: unix fd passing not enabled") } } return msg.EncodeTo(t, binary.LittleEndian) } lxd-2.0.0/dist/src/github.com/godbus/dbus/transport_unix_test.go0000644061062106075000000000205012702772372027412 0ustar00stgraberdomain admins00000000000000package dbus import ( "os" "testing" ) const testString = `This is a test! This text should be read from the file that is created by this test.` type unixFDTest struct{} func (t unixFDTest) Test(fd UnixFD) (string, *Error) { var b [4096]byte file := os.NewFile(uintptr(fd), "testfile") defer file.Close() n, err := file.Read(b[:]) if err != nil { return "", &Error{"com.github.guelfey.test.Error", nil} } return string(b[:n]), nil } func TestUnixFDs(t *testing.T) { conn, err := SessionBus() if err != nil { t.Fatal(err) } r, w, err := os.Pipe() if err != nil { t.Fatal(err) } defer w.Close() if _, err := w.Write([]byte(testString)); err != nil { t.Fatal(err) } name := conn.Names()[0] test := unixFDTest{} conn.Export(test, "/com/github/guelfey/test", "com.github.guelfey.test") var s string obj := conn.Object(name, "/com/github/guelfey/test") err = obj.Call("com.github.guelfey.test.Test", 0, UnixFD(r.Fd())).Store(&s) if err != nil { t.Fatal(err) } if s != testString { t.Fatal("got", s, "wanted", testString) } } lxd-2.0.0/dist/src/github.com/godbus/dbus/auth_sha1.go0000644061062106075000000000461412702772372025141 0ustar00stgraberdomain admins00000000000000package dbus import ( "bufio" "bytes" "crypto/rand" "crypto/sha1" "encoding/hex" "os" ) // AuthCookieSha1 returns an Auth that authenticates as the given user with the // DBUS_COOKIE_SHA1 mechanism. The home parameter should specify the home // directory of the user. func AuthCookieSha1(user, home string) Auth { return authCookieSha1{user, home} } type authCookieSha1 struct { user, home string } func (a authCookieSha1) FirstData() ([]byte, []byte, AuthStatus) { b := make([]byte, 2*len(a.user)) hex.Encode(b, []byte(a.user)) return []byte("DBUS_COOKIE_SHA1"), b, AuthContinue } func (a authCookieSha1) HandleData(data []byte) ([]byte, AuthStatus) { challenge := make([]byte, len(data)/2) _, err := hex.Decode(challenge, data) if err != nil { return nil, AuthError } b := bytes.Split(challenge, []byte{' '}) if len(b) != 3 { return nil, AuthError } context := b[0] id := b[1] svchallenge := b[2] cookie := a.getCookie(context, id) if cookie == nil { return nil, AuthError } clchallenge := a.generateChallenge() if clchallenge == nil { return nil, AuthError } hash := sha1.New() hash.Write(bytes.Join([][]byte{svchallenge, clchallenge, cookie}, []byte{':'})) hexhash := make([]byte, 2*hash.Size()) hex.Encode(hexhash, hash.Sum(nil)) data = append(clchallenge, ' ') data = append(data, hexhash...) resp := make([]byte, 2*len(data)) hex.Encode(resp, data) return resp, AuthOk } // getCookie searches for the cookie identified by id in context and returns // the cookie content or nil. (Since HandleData can't return a specific error, // but only whether an error occured, this function also doesn't bother to // return an error.) func (a authCookieSha1) getCookie(context, id []byte) []byte { file, err := os.Open(a.home + "/.dbus-keyrings/" + string(context)) if err != nil { return nil } defer file.Close() rd := bufio.NewReader(file) for { line, err := rd.ReadBytes('\n') if err != nil { return nil } line = line[:len(line)-1] b := bytes.Split(line, []byte{' '}) if len(b) != 3 { return nil } if bytes.Equal(b[0], id) { return b[2] } } } // generateChallenge returns a random, hex-encoded challenge, or nil on error // (see above). func (a authCookieSha1) generateChallenge() []byte { b := make([]byte, 16) n, err := rand.Read(b) if err != nil { return nil } if n != 16 { return nil } enc := make([]byte, 32) hex.Encode(enc, b) return enc } lxd-2.0.0/dist/src/github.com/godbus/dbus/conn_other.go0000644061062106075000000000075212702772372025421 0ustar00stgraberdomain admins00000000000000// +build !darwin package dbus import ( "bytes" "errors" "os" "os/exec" ) func sessionBusPlatform() (*Conn, error) { cmd := exec.Command("dbus-launch") b, err := cmd.CombinedOutput() if err != nil { return nil, err } i := bytes.IndexByte(b, '=') j := bytes.IndexByte(b, '\n') if i == -1 || j == -1 { return nil, errors.New("dbus: couldn't determine address of session bus") } env, addr := string(b[0:i]), string(b[i+1:j]) os.Setenv(env, addr) return Dial(addr) } lxd-2.0.0/dist/src/github.com/godbus/dbus/CONTRIBUTING.md0000644061062106075000000000271412702772372025165 0ustar00stgraberdomain admins00000000000000# How to Contribute ## Getting Started - Fork the repository on GitHub - Read the [README](README.markdown) for build and test instructions - Play with the project, submit bugs, submit patches! ## Contribution Flow This is a rough outline of what a contributor's workflow looks like: - Create a topic branch from where you want to base your work (usually master). - Make commits of logical units. - Make sure your commit messages are in the proper format (see below). - Push your changes to a topic branch in your fork of the repository. - Make sure the tests pass, and add any new tests as appropriate. - Submit a pull request to the original repository. Thanks for your contributions! ### Format of the Commit Message We follow a rough convention for commit messages that is designed to answer two questions: what changed and why. The subject line should feature the what and the body of the commit should describe the why. ``` scripts: add the test-cluster command this uses tmux to setup a test cluster that you can easily kill and start for debugging. Fixes #38 ``` The format can be described more formally as follows: ``` :