Compare commits
402 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
cd1994b007 | ||
|
1fd780befc | ||
|
8847a471c5 | ||
|
c0c144bd56 | ||
|
1d962916b9 | ||
|
bda6668f00 | ||
|
0f828db9a3 | ||
|
5970000589 | ||
|
7870fa8c9d | ||
|
b4d45306b2 | ||
|
3c2b5e6636 | ||
|
bf743b3060 | ||
|
3b98be7788 | ||
|
746685023f | ||
|
a0fcbb16d6 | ||
|
f63fa39a2d | ||
|
0ae90f3b22 | ||
|
dee67b964a | ||
|
05062188f1 | ||
|
5405fc9d0d | ||
|
c7f327bb89 | ||
|
71e2b2bddb | ||
|
8fac253214 | ||
|
e19fd09664 | ||
|
4a25948b53 | ||
|
f5cc75299a | ||
|
f816819c6d | ||
|
5f688a0a21 | ||
|
f92dcb7968 | ||
|
bb71f5e072 | ||
|
ed512c1cac | ||
|
94f8e00054 | ||
|
b5cb942acb | ||
|
de38ac5c98 | ||
|
dfc5f2627f | ||
|
057e8094d5 | ||
|
15b50d4712 | ||
|
dda5032296 | ||
|
d675638776 | ||
|
61e3595520 | ||
|
4f76283917 | ||
|
9c4aca6c9a | ||
|
13dc11abf3 | ||
|
9ba25550a1 | ||
|
81ffa056bd | ||
|
8c804a1124 | ||
|
0a46b32c88 | ||
|
fac805dc11 | ||
|
94ea0b99ea | ||
|
56a80d84cf | ||
|
00c9174da4 | ||
|
ec8742c9ba | ||
|
b3b09aeb19 | ||
|
481d98c0b5 | ||
|
f30727a675 | ||
|
fc4efb086b | ||
|
5383bd1f07 | ||
|
e1305937e6 | ||
|
20c4653ecf | ||
|
43c6da06a5 | ||
|
7ab84601c3 | ||
|
a24b23663c | ||
|
91fe744bd2 | ||
|
eb8fc045ee | ||
|
ba83b2871f | ||
|
f36821f7ce | ||
|
97fe210760 | ||
|
c6400f7751 | ||
|
f6647634f0 | ||
|
837d3d3622 | ||
|
1063a4b9ee | ||
|
081f77a102 | ||
|
41289286ca | ||
|
d50a4069a6 | ||
|
be0c9c56e4 | ||
|
6467f06656 | ||
|
7a05e63fcc | ||
|
ca6f97d050 | ||
|
d086bca9e4 | ||
|
d25f18776f | ||
|
c583b77cdb | ||
|
ed4d5fac4c | ||
|
40429204ba | ||
|
d72d54be59 | ||
|
373c7ecbd9 | ||
|
31c46c7051 | ||
|
66ec7d805c | ||
|
2563896f89 | ||
|
94a242cc58 | ||
|
5b159fcf56 | ||
|
a9e8940132 | ||
|
cf194ab85e | ||
|
33bc5fc63d | ||
|
09f6a279ef | ||
|
e8c8b811fe | ||
|
f5ecc05d62 | ||
|
66a2f00679 | ||
|
14cad6f7c3 | ||
|
6f188bd5d4 | ||
|
41832ab19e | ||
|
672e4c07af | ||
|
be53013431 | ||
|
c30fc51b03 | ||
|
b429eaab84 | ||
|
e0104e6d93 | ||
|
7bf9712724 | ||
|
78b0f82918 | ||
|
987aa21883 | ||
|
47ac4f6931 | ||
|
f8aa7a43b8 | ||
|
2fe0b0b2a8 | ||
|
19ce7ac849 | ||
|
477053ffde | ||
|
eb0d2dbfa3 | ||
|
18caa5bf07 | ||
|
a27bbb912f | ||
|
3b2af743bd | ||
|
995bc63abe | ||
|
a28f870302 | ||
|
a3357c273c | ||
|
080c698ec2 | ||
|
afbf1dbb3a | ||
|
a275e18533 | ||
|
cf3baa8805 | ||
|
ed84bcef04 | ||
|
7d8b29e597 | ||
|
4eaaa5c927 | ||
|
536f8acf2a | ||
|
9605b5edf2 | ||
|
42153edbbc | ||
|
650a239fdb | ||
|
3e47c09b41 | ||
|
d4c617fc23 | ||
|
9441586229 | ||
|
be62a1df66 | ||
|
c093e44049 | ||
|
be68a8e5cc | ||
|
58b4de8093 | ||
|
ae3676096c | ||
|
a548b557ed | ||
|
a9c132a706 | ||
|
c3c4b86a3b | ||
|
44142ff8af | ||
|
e9529ede44 | ||
|
4b5b801171 | ||
|
551cbb1e5d | ||
|
3c93938f8a | ||
|
f61c08c246 | ||
|
571903cec6 | ||
|
bdbd1930ed | ||
|
cc75a943ba | ||
|
fc77ba6355 | ||
|
7cfa0df7c4 | ||
|
58f0dadaf9 | ||
|
1ab530f157 | ||
|
13e4b77130 | ||
|
54c62cbb70 | ||
|
c8e864fef5 | ||
|
60a3377e7c | ||
|
5527f09778 | ||
|
54a64454b9 | ||
|
0e70d4f01f | ||
|
af8e590575 | ||
|
40d943fb7a | ||
|
248536a5cd | ||
|
4ed1d03c97 | ||
|
057ab37364 | ||
|
182241c8d3 | ||
|
edced59fa6 | ||
|
9be836df31 | ||
|
4e54447b8e | ||
|
999c38b09b | ||
|
06d13de5c3 | ||
|
5b0903d162 | ||
|
10669be7c0 | ||
|
2edae741e1 | ||
|
ea90e553d1 | ||
|
b0cfd86902 | ||
|
565a9540c9 | ||
|
fd10e27b99 | ||
|
39763d772c | ||
|
ee69b77bfb | ||
|
353444e56d | ||
|
112ba1e31f | ||
|
9c3cd9e69c | ||
|
685d8317bc | ||
|
f42d102b26 | ||
|
c944e9ef94 | ||
|
f10d6e8bef | ||
|
f3f3af79fd | ||
|
0e63aa0f6b | ||
|
b254e17e89 | ||
|
5c059b66f0 | ||
|
c628bef666 | ||
|
2270db3f7a | ||
|
d0d467813d | ||
|
123f111efe | ||
|
521ecfdab5 | ||
|
6d0fdf1a47 | ||
|
ffc54b028c | ||
|
420f7cf202 | ||
|
624df676d0 | ||
|
75ed8dacf9 | ||
|
dcaabe4d4a | ||
|
92c57423ba | ||
|
7447e133c9 | ||
|
4e466c12da | ||
|
333468dba3 | ||
|
55c3a793ad | ||
|
eca51031c8 | ||
|
19522bcb82 | ||
|
62248ea33d | ||
|
d2a19cc86d | ||
|
08131ffab1 | ||
|
4a0019c669 | ||
|
3275ead1ec | ||
|
32b6a55724 | ||
|
6c43644369 | ||
|
e6593d49e6 | ||
|
ab752b239f | ||
|
0742e4d357 | ||
|
78f586ec9e | ||
|
6f91b76d79 | ||
|
5c80ccacc4 | ||
|
44fdf95d99 | ||
|
0a62614eec | ||
|
97758b343b | ||
|
fb6f52b360 | ||
|
786cd2a539 | ||
|
45793f1254 | ||
|
b621756d92 | ||
|
a5b5c700a6 | ||
|
ea95920f31 | ||
|
d7602f3c08 | ||
|
a20addd05e | ||
|
d9d89a6fa0 | ||
|
3c26376326 | ||
|
d3294bcb86 | ||
|
dda314b518 | ||
|
055a3c339a | ||
|
51f37100a1 | ||
|
88e8265cd6 | ||
|
6e2db882e6 | ||
|
3e2823df1b | ||
|
46cb51cf91 | ||
|
1a6cee5305 | ||
|
d02aa18839 | ||
|
e9bda98b54 | ||
|
badc874b74 | ||
|
c9e8c887b8 | ||
|
8be307de49 | ||
|
562c474275 | ||
|
b6062f0644 | ||
|
c5fada6e69 | ||
|
5c5834863b | ||
|
44f0a949c5 | ||
|
106c4e7a2c | ||
|
6c1ba590aa | ||
|
45da664c59 | ||
|
2a71551ef2 | ||
|
84e1cb3242 | ||
|
5214ead926 | ||
|
e2c24c4cef | ||
|
75e288c553 | ||
|
0785840fe3 | ||
|
c10bfc2f56 | ||
|
2f954dcdc2 | ||
|
cdfc94f4e9 | ||
|
18e2f98414 | ||
|
4b472795c4 | ||
|
85b8d804c8 | ||
|
1fbbaaec19 | ||
|
667dbd8fb7 | ||
|
6730cb7227 | ||
|
9454522033 | ||
|
c255739a93 | ||
|
2051cd3e1c | ||
|
b52cb3fea3 | ||
|
da5f85b3fb | ||
|
9999178538 | ||
|
8f766e4666 | ||
|
2d28d16c92 | ||
|
e9cd09dd7b | ||
|
8370b30aa2 | ||
|
3e015cc3a1 | ||
|
a0fe6d0884 | ||
|
585ce5fcd9 | ||
|
72445796ca | ||
|
7342d91a85 | ||
|
db1bc51c98 | ||
|
c1f373e648 | ||
|
db49a16002 | ||
|
a4a6c281d9 | ||
|
17f8733121 | ||
|
7dec922618 | ||
|
54d3ae27af | ||
|
ee2416af64 | ||
|
cda037f9a5 | ||
|
549806cf64 | ||
|
56815a6756 | ||
|
24a6f7c49c | ||
|
98484be434 | ||
|
9024659296 | ||
|
fc6940f7ba | ||
|
f2fd95699b | ||
|
65db96cc7c | ||
|
c17b93b5c0 | ||
|
d352f8ce6a | ||
|
78aa2c56ec | ||
|
c5b3788282 | ||
|
5e98970bb5 | ||
|
cbdd446c55 | ||
|
316cadcf44 | ||
|
5a939be21b | ||
|
8d76c64386 | ||
|
1b854eb51e | ||
|
9fcf338bf3 | ||
|
fda72bdb5c | ||
|
685a38c6c8 | ||
|
9d15f2cfaf | ||
|
2134fce791 | ||
|
3abd6b2225 | ||
|
2a8e6c9566 | ||
|
abe43537da | ||
|
3a550af651 | ||
|
61c3a0eb2d | ||
|
480176bc11 | ||
|
01b18eb551 | ||
|
970ef435b6 | ||
|
e8d0021140 | ||
|
e9ec78ac6f | ||
|
4a2e417781 | ||
|
604ef7ecb4 | ||
|
c39dd5cc67 | ||
|
a923161f4a | ||
|
e59e2f6cd5 | ||
|
e90fe3eba8 | ||
|
fb0187b197 | ||
|
6babe74716 | ||
|
b1e88284ca | ||
|
18a65f7dac | ||
|
0c212c72c9 | ||
|
6a800d8cc0 | ||
|
5e112147bb | ||
|
7e78b1563f | ||
|
ecbe81f103 | ||
|
45c20c1dd3 | ||
|
8ce925a060 | ||
|
eadb6ef42c | ||
|
7518f0ec93 | ||
|
f0b9eaf2fe | ||
|
7320a2cbf2 | ||
|
57950b3ed9 | ||
|
85c6a2a16a | ||
|
24b44e86a6 | ||
|
2f52ad4ef8 | ||
|
735d6c6161 | ||
|
1cf275bad6 | ||
|
f1c97cb4d5 | ||
|
d143904aa9 | ||
|
c428ce2cc5 | ||
|
dfb5b4fc3a | ||
|
97d5538533 | ||
|
6b8f82b5d3 | ||
|
facde6609f | ||
|
d68ae84b37 | ||
|
54aa39543b | ||
|
8566a2c118 | ||
|
49ac083af5 | ||
|
5d65ca230a | ||
|
38b3e1213a | ||
|
4eedca26e9 | ||
|
f2b342c8be | ||
|
c19d8f6b61 | ||
|
7913f74351 | ||
|
5593408be8 | ||
|
7fc67c2acf | ||
|
b093094292 | ||
|
9a80fd714a | ||
|
fef5473881 | ||
|
bf5a2b208f | ||
|
364507fb75 | ||
|
08d4842502 | ||
|
21e32e44f8 | ||
|
7a06dee16f | ||
|
ff9cf5743d | ||
|
1b10a3a187 | ||
|
10838e001d | ||
|
96370ac5b9 | ||
|
0b82cd074d | ||
|
a974e85103 | ||
|
f0450662b0 | ||
|
03e29d1291 | ||
|
98ae5d88aa | ||
|
bf5d3539c9 | ||
|
5e4cbcd909 | ||
|
a270c4c737 | ||
|
f356a8a690 | ||
|
be51f4eba0 | ||
|
e3037f18a6 | ||
|
fe388a3ab6 | ||
|
c820f2b1cf |
14
.travis.yml
14
.travis.yml
@@ -1,8 +1,12 @@
|
||||
language: go
|
||||
go: 1.2
|
||||
|
||||
install:
|
||||
- go get code.google.com/p/go.tools/cmd/cover
|
||||
sudo: false
|
||||
matrix:
|
||||
include:
|
||||
- go: 1.4
|
||||
install:
|
||||
- go get golang.org/x/tools/cmd/cover
|
||||
- go get golang.org/x/tools/cmd/vet
|
||||
- go: 1.5
|
||||
|
||||
script:
|
||||
- ./test
|
||||
- ./test
|
||||
|
@@ -39,22 +39,25 @@ Thanks for your contributions!
|
||||
|
||||
### Format of the Commit Message
|
||||
|
||||
We follow a rough convention for commit messages borrowed from AngularJS. This
|
||||
is an example of a commit:
|
||||
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.
|
||||
|
||||
```
|
||||
feat(scripts/test-cluster): add a cluster test command
|
||||
environment: write new keys in consistent order
|
||||
|
||||
this uses tmux to setup a test cluster that you can easily kill and
|
||||
start for debugging.
|
||||
Go 1.3 randomizes the ordering of keys when iterating over a map.
|
||||
Sort the keys to make this ordering consistent.
|
||||
|
||||
Fixes #38
|
||||
```
|
||||
|
||||
The format can be described more formally as follows:
|
||||
|
||||
```
|
||||
<type>(<scope>): <subject>
|
||||
<subsystem>: <what changed>
|
||||
<BLANK LINE>
|
||||
<body>
|
||||
<why this change was made>
|
||||
<BLANK LINE>
|
||||
<footer>
|
||||
```
|
||||
@@ -63,25 +66,3 @@ The first line is the subject and should be no longer than 70 characters, the
|
||||
second line is always blank, and other lines should be wrapped at 80 characters.
|
||||
This allows the message to be easier to read on GitHub as well as in various
|
||||
git tools.
|
||||
|
||||
#### Subject Line
|
||||
|
||||
The subject line contains a succinct description of the change.
|
||||
|
||||
#### Allowed `<type>`s
|
||||
- *feat* (feature)
|
||||
- *fix* (bug fix)
|
||||
- *docs* (documentation)
|
||||
- *style* (formatting, missing semi colons, …)
|
||||
- *refactor*
|
||||
- *test* (when adding missing tests)
|
||||
- *chore* (maintain)
|
||||
|
||||
#### Allowed `<scope>`s
|
||||
|
||||
Scopes can anything specifying the place of the commit change in the code base -
|
||||
for example, "api", "store", etc.
|
||||
|
||||
|
||||
For more details on the commit format, see the [AngularJS commit style
|
||||
guide](https://docs.google.com/a/coreos.com/document/d/1QrDFcIiPjSLDn3EL15IJygNPiHORgU1_OOAqWjiDU5Y/edit#).
|
||||
|
38
Documentation/cloud-config-deprecated.md
Normal file
38
Documentation/cloud-config-deprecated.md
Normal file
@@ -0,0 +1,38 @@
|
||||
# Deprecated Cloud-Config Features
|
||||
|
||||
## Retrieving SSH Authorized Keys
|
||||
|
||||
### From a GitHub User
|
||||
|
||||
Using the `coreos-ssh-import-github` field, we can import public SSH keys from a GitHub user to use as authorized keys to a server.
|
||||
|
||||
```yaml
|
||||
#cloud-config
|
||||
|
||||
users:
|
||||
- name: elroy
|
||||
coreos-ssh-import-github: elroy
|
||||
```
|
||||
|
||||
### From an HTTP Endpoint
|
||||
|
||||
We can also pull public SSH keys from any HTTP endpoint which matches [GitHub's API response format](https://developer.github.com/v3/users/keys/#list-public-keys-for-a-user).
|
||||
For example, if you have an installation of GitHub Enterprise, you can provide a complete URL with an authentication token:
|
||||
|
||||
```yaml
|
||||
#cloud-config
|
||||
|
||||
users:
|
||||
- name: elroy
|
||||
coreos-ssh-import-url: https://github-enterprise.example.com/api/v3/users/elroy/keys?access_token=<TOKEN>
|
||||
```
|
||||
|
||||
You can also specify any URL whose response matches the JSON format for public keys:
|
||||
|
||||
```yaml
|
||||
#cloud-config
|
||||
|
||||
users:
|
||||
- name: elroy
|
||||
coreos-ssh-import-url: https://example.com/public-keys
|
||||
```
|
26
Documentation/cloud-config-locations.md
Normal file
26
Documentation/cloud-config-locations.md
Normal file
@@ -0,0 +1,26 @@
|
||||
# Cloud-Config Locations
|
||||
|
||||
On every boot, coreos-cloudinit looks for a config file to configure your host. Here is a list of locations which are used by the Cloud-Config utility, depending on your CoreOS platform:
|
||||
|
||||
Location | Description
|
||||
--- | --- | ---
|
||||
|`/media/configvirtfs/openstack/latest/user_data`|`/media/configvirtfs` mount point with [config-2](/os/docs/latest/config-drive.html#contents-and-format) label. It should contain a `openstack/latest/user_data` relative path. Usually used by cloud providers or in VM installations.|
|
||||
|`/media/configdrive/openstack/latest/user_data`|FAT or ISO9660 filesystem with [config-2](/os/docs/latest/config-drive.html#qemu-virtfs) label and `/media/configdrive/` mount point. It should also contain a `openstack/latest/user_data` relative path. Usually used in installations which are configured by USB Flash sticks or CDROM media.|
|
||||
|Kernel command line: `cloud-config-url=http://example.com/user_data`.| You can find this string using this command `cat /proc/cmdline`. Usually used in [PXE](/os/docs/latest/booting-with-pxe.html) or [iPXE](/os/docs/latest/booting-with-ipxe.html) boots.|
|
||||
|`/var/lib/coreos-install/user_data`| When you install CoreOS manually using the [coreos-install](/os/docs/latest/installing-to-disk.html) tool. Usually used in bare metal installations.|
|
||||
|`/usr/share/oem/cloud-config.yml`| Path for OEM images.|
|
||||
|`/var/lib/coreos-vagrant/vagrantfile-user-data`| Vagrant OEM scripts automatically store Cloud-Config into this path. |
|
||||
|`/var/lib/waagent/CustomData`| Azure platform uses OEM path for first Cloud-Config initialization and then `/var/lib/waagent/CustomData` to apply your settings.|
|
||||
|`http://169.254.169.254/metadata/v1/user-data` `http://169.254.169.254/2009-04-04/user-data` `https://metadata.packet.net/userdata`|DigitalOcean, EC2 and Packet cloud providers correspondingly use these URLs to download Cloud-Config.|
|
||||
|`/usr/share/oem/bin/vmtoolsd --cmd "info-get guestinfo.coreos.config.data"`|Cloud-Config provided by [VMware Backdoor][VMware Backdoor]|
|
||||
|`/usr/share/oem/bin/vmtoolsd --cmd "info-get guestinfo.coreos.config.url"`|Cloud-Config URL provided by [VMware Backdoor][VMware Backdoor]|
|
||||
|
||||
[VMware Backdoor]: vmware-backdoor.md
|
||||
|
||||
You can also run the `coreos-cloudinit` tool manually and provide a path to your custom Cloud-Config file:
|
||||
|
||||
```sh
|
||||
sudo coreos-cloudinit --from-file=/home/core/cloud-config.yaml
|
||||
```
|
||||
|
||||
This command will apply your custom cloud-config.
|
@@ -13,20 +13,20 @@ If no **id** field is provided, coreos-cloudinit will ignore this section.
|
||||
|
||||
For example, the following cloud-config document...
|
||||
|
||||
```
|
||||
```yaml
|
||||
#cloud-config
|
||||
coreos:
|
||||
oem:
|
||||
id: rackspace
|
||||
name: Rackspace Cloud Servers
|
||||
version-id: 168.0.0
|
||||
home-url: https://www.rackspace.com/cloud/servers/
|
||||
bug-report-url: https://github.com/coreos/coreos-overlay
|
||||
id: "rackspace"
|
||||
name: "Rackspace Cloud Servers"
|
||||
version-id: "168.0.0"
|
||||
home-url: "https://www.rackspace.com/cloud/servers/"
|
||||
bug-report-url: "https://github.com/coreos/coreos-overlay"
|
||||
```
|
||||
|
||||
...would be rendered to the following `/etc/oem-release`:
|
||||
|
||||
```
|
||||
```yaml
|
||||
ID=rackspace
|
||||
NAME="Rackspace Cloud Servers"
|
||||
VERSION_ID=168.0.0
|
||||
|
@@ -1,10 +1,20 @@
|
||||
# Using Cloud-Config
|
||||
|
||||
CoreOS allows you to declaratively customize various OS-level items, such as network configuration, user accounts, and systemd units. This document describes the full list of items we can configure. The `coreos-cloudinit` program uses these files as it configures the OS after startup or during runtime.
|
||||
CoreOS allows you to declaratively customize various OS-level items, such as network configuration, user accounts, and systemd units. This document describes the full list of items we can configure. The `coreos-cloudinit` program uses these files as it configures the OS after startup or during runtime.
|
||||
|
||||
Your cloud-config is processed during each boot. Invalid cloud-config won't be processed but will be logged in the journal. You can validate your cloud-config with the [CoreOS validator]({{site.url}}/validate) or by running `coreos-cloudinit -validate`.
|
||||
|
||||
In addition to `coreos-cloudinit -validate` command and https://coreos.com/validate/ online service you can debug `coreos-cloudinit` system output through the `journalctl` tool:
|
||||
|
||||
```sh
|
||||
journalctl _EXE=/usr/bin/coreos-cloudinit
|
||||
```
|
||||
|
||||
It will show `coreos-cloudinit` run output which was triggered by system boot.
|
||||
|
||||
## Configuration File
|
||||
|
||||
The file used by this system initialization program is called a "cloud-config" file. It is inspired by the [cloud-init][cloud-init] project's [cloud-config][cloud-config] file. which is "the defacto multi-distribution package that handles early initialization of a cloud instance" ([cloud-init docs][cloud-init-docs]). Because the cloud-init project includes tools which aren't used by CoreOS, only the relevant subset of its configuration items will be implemented in our cloud-config file. In addition to those, we added a few CoreOS-specific items, such as etcd configuration, OEM definition, and systemd units.
|
||||
The file used by this system initialization program is called a "cloud-config" file. It is inspired by the [cloud-init][cloud-init] project's [cloud-config][cloud-config] file, which is "the defacto multi-distribution package that handles early initialization of a cloud instance" ([cloud-init docs][cloud-init-docs]). Because the cloud-init project includes tools which aren't used by CoreOS, only the relevant subset of its configuration items will be implemented in our cloud-config file. In addition to those, we added a few CoreOS-specific items, such as etcd configuration, OEM definition, and systemd units.
|
||||
|
||||
We've designed our implementation to allow the same cloud-config file to work across all of our supported platforms.
|
||||
|
||||
@@ -16,7 +26,7 @@ We've designed our implementation to allow the same cloud-config file to work ac
|
||||
|
||||
The cloud-config file uses the [YAML][yaml] file format, which uses whitespace and new-lines to delimit lists, associative arrays, and values.
|
||||
|
||||
A cloud-config file should contain `#cloud-config`, followed by an associative array which has zero or more of the following keys:
|
||||
A cloud-config file must contain a header: either `#cloud-config` for processing as cloud-config (suggested) or `#!` for processing as a shell script (advanced). If cloud-config has #cloud-config header, it should followed by an associative array which has zero or more of the following keys:
|
||||
|
||||
- `coreos`
|
||||
- `ssh_authorized_keys`
|
||||
@@ -27,6 +37,8 @@ A cloud-config file should contain `#cloud-config`, followed by an associative a
|
||||
|
||||
The expected values for these keys are defined in the rest of this document.
|
||||
|
||||
If cloud-config header starts on `#!` then coreos-cloudinit will recognize it as shell script which is interpreted by bash and run it as transient systemd service.
|
||||
|
||||
[yaml]: https://en.wikipedia.org/wiki/YAML
|
||||
|
||||
### Providing Cloud-Config with Config-Drive
|
||||
@@ -37,27 +49,27 @@ CoreOS tries to conform to each platform's native method to provide user data. E
|
||||
|
||||
### coreos
|
||||
|
||||
#### etcd
|
||||
#### etcd (deprecated. see etcd2)
|
||||
|
||||
The `coreos.etcd.*` parameters will be translated to a partial systemd unit acting as an etcd configuration file.
|
||||
We can use the templating feature of coreos-cloudinit to automate etcd configuration with the `$private_ipv4` and `$public_ipv4` fields. For example, the following cloud-config document...
|
||||
If the platform environment supports the templating feature of coreos-cloudinit it is possible to automate etcd configuration with the `$private_ipv4` and `$public_ipv4` fields. For example, the following cloud-config document...
|
||||
|
||||
```
|
||||
```yaml
|
||||
#cloud-config
|
||||
|
||||
coreos:
|
||||
etcd:
|
||||
name: node001
|
||||
# generate a new token for each unique cluster from https://discovery.etcd.io/new
|
||||
discovery: https://discovery.etcd.io/<token>
|
||||
# multi-region and multi-cloud deployments need to use $public_ipv4
|
||||
addr: $public_ipv4:4001
|
||||
peer-addr: $private_ipv4:7001
|
||||
etcd:
|
||||
name: "node001"
|
||||
# generate a new token for each unique cluster from https://discovery.etcd.io/new
|
||||
discovery: "https://discovery.etcd.io/<token>"
|
||||
# multi-region and multi-cloud deployments need to use $public_ipv4
|
||||
addr: "$public_ipv4:4001"
|
||||
peer-addr: "$private_ipv4:7001"
|
||||
```
|
||||
|
||||
...will generate a systemd unit drop-in like this:
|
||||
...will generate a systemd unit drop-in for etcd.service with the following contents:
|
||||
|
||||
```
|
||||
```yaml
|
||||
[Service]
|
||||
Environment="ETCD_NAME=node001"
|
||||
Environment="ETCD_DISCOVERY=https://discovery.etcd.io/<token>"
|
||||
@@ -66,34 +78,157 @@ Environment="ETCD_PEER_ADDR=192.0.2.13:7001"
|
||||
```
|
||||
|
||||
For more information about the available configuration parameters, see the [etcd documentation][etcd-config].
|
||||
Note that hyphens in the coreos.etcd.* keys are mapped to underscores.
|
||||
|
||||
[etcd-config]: https://github.com/coreos/etcd/blob/master/Documentation/configuration.md
|
||||
_Note: The `$private_ipv4` and `$public_ipv4` substitution variables referenced in other documents are only supported on Amazon EC2, Google Compute Engine, OpenStack, Rackspace, DigitalOcean, and Vagrant._
|
||||
|
||||
#### fleet
|
||||
[etcd-config]: https://github.com/coreos/etcd/blob/9fa3bea5a22265151f0d5063ce38a79c5b5d0271/Documentation/configuration.md
|
||||
|
||||
The `coreos.fleet.*` parameters work very similarly to `coreos.etcd.*`, and allow for the configuration of fleet through environment variables. For example, the following cloud-config document...
|
||||
#### etcd2
|
||||
|
||||
```
|
||||
The `coreos.etcd2.*` parameters will be translated to a partial systemd unit acting as an etcd configuration file.
|
||||
If the platform environment supports the templating feature of coreos-cloudinit it is possible to automate etcd configuration with the `$private_ipv4` and `$public_ipv4` fields. When generating a [discovery token](https://discovery.etcd.io/new?size=3), set the `size` parameter, since etcd uses this to determine if all members have joined the cluster. After the cluster is bootstrapped, it can grow or shrink from this configured size.
|
||||
|
||||
For example, the following cloud-config document...
|
||||
|
||||
```yaml
|
||||
#cloud-config
|
||||
|
||||
coreos:
|
||||
fleet:
|
||||
public-ip: $public_ipv4
|
||||
metadata: region=us-west
|
||||
etcd2:
|
||||
# generate a new token for each unique cluster from https://discovery.etcd.io/new?size=3
|
||||
discovery: "https://discovery.etcd.io/<token>"
|
||||
# multi-region and multi-cloud deployments need to use $public_ipv4
|
||||
advertise-client-urls: "http://$public_ipv4:2379"
|
||||
initial-advertise-peer-urls: "http://$private_ipv4:2380"
|
||||
# listen on both the official ports and the legacy ports
|
||||
# legacy ports can be omitted if your application doesn't depend on them
|
||||
listen-client-urls: "http://0.0.0.0:2379,http://0.0.0.0:4001"
|
||||
listen-peer-urls: "http://$private_ipv4:2380,http://$private_ipv4:7001"
|
||||
```
|
||||
|
||||
...will generate a systemd unit drop-in for etcd2.service with the following contents:
|
||||
|
||||
```yaml
|
||||
[Service]
|
||||
Environment="ETCD_DISCOVERY=https://discovery.etcd.io/<token>"
|
||||
Environment="ETCD_ADVERTISE_CLIENT_URLS=http://203.0.113.29:2379"
|
||||
Environment="ETCD_INITIAL_ADVERTISE_PEER_URLS=http://192.0.2.13:2380"
|
||||
Environment="ETCD_LISTEN_CLIENT_URLS=http://0.0.0.0:2379,http://0.0.0.0:4001"
|
||||
Environment="ETCD_LISTEN_PEER_URLS=http://192.0.2.13:2380,http://192.0.2.13:7001"
|
||||
```
|
||||
|
||||
For more information about the available configuration parameters, see the [etcd documentation][etcd-config].
|
||||
|
||||
_Note: The `$private_ipv4` and `$public_ipv4` substitution variables referenced in other documents are only supported on Amazon EC2, Google Compute Engine, OpenStack, Rackspace, DigitalOcean, and Vagrant._
|
||||
|
||||
[etcd-config]: https://github.com/coreos/etcd/blob/86e616c6e974828fc9119c1eb0f6439577a9ce0b/Documentation/configuration.md
|
||||
|
||||
#### fleet
|
||||
|
||||
The `coreos.fleet.*` parameters work very similarly to `coreos.etcd2.*`, and allow for the configuration of fleet through environment variables. For example, the following cloud-config document...
|
||||
|
||||
```yaml
|
||||
#cloud-config
|
||||
|
||||
coreos:
|
||||
fleet:
|
||||
public-ip: "$public_ipv4"
|
||||
metadata: "region=us-west"
|
||||
```
|
||||
|
||||
...will generate a systemd unit drop-in like this:
|
||||
|
||||
```
|
||||
```yaml
|
||||
[Service]
|
||||
Environment="FLEET_PUBLIC_IP=203.0.113.29"
|
||||
Environment="FLEET_METADATA=region=us-west"
|
||||
```
|
||||
|
||||
List of fleet configuration parameters:
|
||||
|
||||
- **agent_ttl**: An Agent will be considered dead if it exceeds this amount of time to communicate with the Registry
|
||||
- **engine_reconcile_interval**: Interval in seconds at which the engine should reconcile the cluster schedule in etcd
|
||||
- **etcd_cafile**: Path to CA file used for TLS communication with etcd
|
||||
- **etcd_certfile**: Provide TLS configuration when SSL certificate authentication is enabled in etcd endpoints
|
||||
- **etcd_keyfile**: Path to private key file used for TLS communication with etcd
|
||||
- **etcd_key_prefix**: etcd prefix path to be used for fleet keys
|
||||
- **etcd_request_timeout**: Amount of time in seconds to allow a single etcd request before considering it failed
|
||||
- **etcd_servers**: Comma separated list of etcd endpoints
|
||||
- **metadata**: Comma separated key/value pairs that are published with the local to the fleet registry
|
||||
- **public_ip**: IP accessible by other nodes for inter-host communication
|
||||
- **verbosity**: Enable debug logging by setting this to an integer value greater than zero
|
||||
|
||||
For more information on fleet configuration, see the [fleet documentation][fleet-config].
|
||||
|
||||
[fleet-config]: https://github.com/coreos/fleet/blob/master/Documentation/configuration.md
|
||||
[fleet-config]: https://github.com/coreos/fleet/blob/master/Documentation/deployment-and-configuration.md#configuration
|
||||
|
||||
#### flannel
|
||||
|
||||
The `coreos.flannel.*` parameters also work very similarly to `coreos.etcd2.*`
|
||||
and `coreos.fleet.*`. They can be used to set environment variables for
|
||||
flanneld. For example, the following cloud-config...
|
||||
|
||||
```yaml
|
||||
#cloud-config
|
||||
|
||||
coreos:
|
||||
flannel:
|
||||
etcd_prefix: "/coreos.com/network2"
|
||||
```
|
||||
|
||||
...will generate a systemd unit drop-in like so:
|
||||
|
||||
```
|
||||
[Service]
|
||||
Environment="FLANNELD_ETCD_PREFIX=/coreos.com/network2"
|
||||
```
|
||||
|
||||
List of flannel configuration parameters:
|
||||
|
||||
- **etcd_endpoints**: Comma separated list of etcd endpoints
|
||||
- **etcd_cafile**: Path to CA file used for TLS communication with etcd
|
||||
- **etcd_certfile**: Path to certificate file used for TLS communication with etcd
|
||||
- **etcd_keyfile**: Path to private key file used for TLS communication with etcd
|
||||
- **etcd_prefix**: etcd prefix path to be used for flannel keys
|
||||
- **ip_masq**: Install IP masquerade rules for traffic outside of flannel subnet
|
||||
- **subnet_file**: Path to flannel subnet file to write out
|
||||
- **interface**: Interface (name or IP) that should be used for inter-host communication
|
||||
- **public_ip**: IP accessible by other nodes for inter-host communication
|
||||
|
||||
For more information on flannel configuration, see the [flannel documentation][flannel-readme].
|
||||
|
||||
[flannel-readme]: https://github.com/coreos/flannel/blob/master/README.md
|
||||
|
||||
#### locksmith
|
||||
|
||||
The `coreos.locksmith.*` parameters can be used to set environment variables
|
||||
for locksmith. For example, the following cloud-config...
|
||||
|
||||
```yaml
|
||||
#cloud-config
|
||||
|
||||
coreos:
|
||||
locksmith:
|
||||
endpoint: "http://example.com:2379"
|
||||
```
|
||||
|
||||
...will generate a systemd unit drop-in like so:
|
||||
|
||||
```
|
||||
[Service]
|
||||
Environment="LOCKSMITHD_ENDPOINT=http://example.com:2379"
|
||||
```
|
||||
|
||||
List of locksmith configuration parameters:
|
||||
|
||||
- **endpoint**: Comma separated list of etcd endpoints
|
||||
- **etcd_cafile**: Path to CA file used for TLS communication with etcd
|
||||
- **etcd_certfile**: Path to certificate file used for TLS communication with etcd
|
||||
- **etcd_keyfile**: Path to private key file used for TLS communication with etcd
|
||||
|
||||
For the complete list of locksmith configuration parameters, see the [locksmith documentation][locksmith-readme].
|
||||
|
||||
[locksmith-readme]: https://github.com/coreos/locksmith/blob/master/README.md
|
||||
|
||||
#### update
|
||||
|
||||
@@ -107,30 +242,39 @@ The `reboot-strategy` parameter also affects the behaviour of [locksmith](https:
|
||||
- _etcd-lock_: Reboot after first taking a distributed lock in etcd, this guarantees that only one host will reboot concurrently and that the cluster will remain available during the update.
|
||||
- _best-effort_ - If etcd is running, "etcd-lock", otherwise simply "reboot".
|
||||
- _off_ - Disable rebooting after updates are applied (not recommended).
|
||||
- **server**: is the omaha endpoint URL which will be queried for updates.
|
||||
- **server**: The location of the [CoreUpdate][coreupdate] server which will be queried for updates. Also known as the [omaha][omaha-docs] server endpoint.
|
||||
- **group**: signifies the channel which should be used for automatic updates. This value defaults to the version of the image initially downloaded. (one of "master", "alpha", "beta", "stable")
|
||||
|
||||
[coreupdate]: https://coreos.com/products/coreupdate
|
||||
[omaha-docs]: https://coreos.com/docs/coreupdate/custom-apps/coreupdate-protocol/
|
||||
|
||||
*Note: cloudinit will only manipulate the locksmith unit file in the systemd runtime directory (`/run/systemd/system/locksmithd.service`). If any manual modifications are made to an overriding unit configuration file (e.g. `/etc/systemd/system/locksmithd.service`), cloudinit will no longer be able to control the locksmith service unit.*
|
||||
|
||||
##### Example
|
||||
|
||||
```
|
||||
```yaml
|
||||
#cloud-config
|
||||
coreos:
|
||||
update:
|
||||
reboot-strategy: etcd-lock
|
||||
reboot-strategy: "etcd-lock"
|
||||
```
|
||||
|
||||
#### units
|
||||
|
||||
The `coreos.units.*` parameters define a list of arbitrary systemd units to start. Each item is an object with the following fields:
|
||||
The `coreos.units.*` parameters define a list of arbitrary systemd units to start after booting. This feature is intended to help you start essential services required to mount storage and configure networking in order to join the CoreOS cluster. It is not intended to be a Chef/Puppet replacement.
|
||||
|
||||
Each item is an object with the following fields:
|
||||
|
||||
- **name**: String representing unit's name. Required.
|
||||
- **runtime**: Boolean indicating whether or not to persist the unit across reboots. This is analogous to the `--runtime` argument to `systemctl enable`. Default value is false.
|
||||
- **enable**: Boolean indicating whether or not to handle the [Install] section of the unit file. This is similar to running `systemctl enable <name>`. Default value is false.
|
||||
- **runtime**: Boolean indicating whether or not to persist the unit across reboots. This is analogous to the `--runtime` argument to `systemctl enable`. The default value is false.
|
||||
- **enable**: Boolean indicating whether or not to handle the [Install] section of the unit file. This is similar to running `systemctl enable <name>`. The default value is false.
|
||||
- **content**: Plaintext string representing entire unit file. If no value is provided, the unit is assumed to exist already.
|
||||
- **command**: Command to execute on unit: start, stop, reload, restart, try-restart, reload-or-restart, reload-or-try-restart. Default value is restart.
|
||||
- **mask**: Whether to mask the unit file by symlinking it to `/dev/null` (analogous to `systemctl mask <name>`). Note that unlike `systemctl mask`, **this will destructively remove any existing unit file** located at `/etc/systemd/system/<unit>`, to ensure that the mask succeeds. Default value is false.
|
||||
- **command**: Command to execute on unit: start, stop, reload, restart, try-restart, reload-or-restart, reload-or-try-restart. The default behavior is to not execute any commands.
|
||||
- **mask**: Whether to mask the unit file by symlinking it to `/dev/null` (analogous to `systemctl mask <name>`). Note that unlike `systemctl mask`, **this will destructively remove any existing unit file** located at `/etc/systemd/system/<unit>`, to ensure that the mask succeeds. The default value is false.
|
||||
- **drop-ins**: A list of unit drop-ins with the following fields:
|
||||
- **name**: String representing unit's name. Required.
|
||||
- **content**: Plaintext string representing entire file. Required.
|
||||
|
||||
|
||||
**NOTE:** The command field is ignored for all network, netdev, and link units. The systemd-networkd.service unit will be restarted in their place.
|
||||
|
||||
@@ -138,36 +282,51 @@ The `coreos.units.*` parameters define a list of arbitrary systemd units to star
|
||||
|
||||
Write a unit to disk, automatically starting it.
|
||||
|
||||
```
|
||||
```yaml
|
||||
#cloud-config
|
||||
|
||||
coreos:
|
||||
units:
|
||||
- name: docker-redis.service
|
||||
command: start
|
||||
content: |
|
||||
[Unit]
|
||||
Description=Redis container
|
||||
Author=Me
|
||||
After=docker.service
|
||||
units:
|
||||
- name: "docker-redis.service"
|
||||
command: "start"
|
||||
content: |
|
||||
[Unit]
|
||||
Description=Redis container
|
||||
Author=Me
|
||||
After=docker.service
|
||||
|
||||
[Service]
|
||||
Restart=always
|
||||
ExecStart=/usr/bin/docker start -a redis_server
|
||||
ExecStop=/usr/bin/docker stop -t 2 redis_server
|
||||
[Service]
|
||||
Restart=always
|
||||
ExecStart=/usr/bin/docker start -a redis_server
|
||||
ExecStop=/usr/bin/docker stop -t 2 redis_server
|
||||
```
|
||||
|
||||
Start the built-in `etcd` and `fleet` services:
|
||||
Add the DOCKER_OPTS environment variable to docker.service.
|
||||
|
||||
```
|
||||
```yaml
|
||||
#cloud-config
|
||||
|
||||
coreos:
|
||||
units:
|
||||
- name: etcd.service
|
||||
command: start
|
||||
- name: fleet.service
|
||||
command: start
|
||||
units:
|
||||
- name: "docker.service"
|
||||
drop-ins:
|
||||
- name: "50-insecure-registry.conf"
|
||||
content: |
|
||||
[Service]
|
||||
Environment=DOCKER_OPTS='--insecure-registry="10.0.1.0/24"'
|
||||
```
|
||||
|
||||
Start the built-in `etcd2` and `fleet` services:
|
||||
|
||||
```yaml
|
||||
#cloud-config
|
||||
|
||||
coreos:
|
||||
units:
|
||||
- name: "etcd2.service"
|
||||
command: "start"
|
||||
- name: "fleet.service"
|
||||
command: "start"
|
||||
```
|
||||
|
||||
### ssh_authorized_keys
|
||||
@@ -177,11 +336,11 @@ The `ssh_authorized_keys` parameter adds public SSH keys which will be authorize
|
||||
The keys will be named "coreos-cloudinit" by default.
|
||||
Override this by using the `--ssh-key-name` flag when calling `coreos-cloudinit`.
|
||||
|
||||
```
|
||||
```yaml
|
||||
#cloud-config
|
||||
|
||||
ssh_authorized_keys:
|
||||
- ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC0g+ZTxC7weoIJLUafOgrm+h...
|
||||
- "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC0g+ZTxC7weoIJLUafOgrm+h..."
|
||||
```
|
||||
|
||||
### hostname
|
||||
@@ -189,10 +348,10 @@ ssh_authorized_keys:
|
||||
The `hostname` parameter defines the system's hostname.
|
||||
This is the local part of a fully-qualified domain name (i.e. `foo` in `foo.example.com`).
|
||||
|
||||
```
|
||||
```yaml
|
||||
#cloud-config
|
||||
|
||||
hostname: coreos1
|
||||
hostname: "coreos1"
|
||||
```
|
||||
|
||||
### users
|
||||
@@ -203,16 +362,18 @@ All but the `passwd` and `ssh-authorized-keys` fields will be ignored if the use
|
||||
- **name**: Required. Login name of user
|
||||
- **gecos**: GECOS comment of user
|
||||
- **passwd**: Hash of the password to use for this user
|
||||
- **homedir**: User's home directory. Defaults to /home/<name>
|
||||
- **homedir**: User's home directory. Defaults to /home/\<name\>
|
||||
- **no-create-home**: Boolean. Skip home directory creation.
|
||||
- **primary-group**: Default group for the user. Defaults to a new group created named after the user.
|
||||
- **groups**: Add user to these additional groups
|
||||
- **no-user-group**: Boolean. Skip default group creation.
|
||||
- **ssh-authorized-keys**: List of public SSH keys to authorize for this user
|
||||
- **coreos-ssh-import-github**: Authorize SSH keys from Github user
|
||||
- **coreos-ssh-import-url**: Authorize SSH keys imported from a url endpoint.
|
||||
- **coreos-ssh-import-github** [DEPRECATED]: Authorize SSH keys from GitHub user
|
||||
- **coreos-ssh-import-github-users** [DEPRECATED]: Authorize SSH keys from a list of GitHub users
|
||||
- **coreos-ssh-import-url** [DEPRECATED]: Authorize SSH keys imported from a url endpoint.
|
||||
- **system**: Create the user as a system user. No home directory will be created.
|
||||
- **no-log-init**: Boolean. Skip initialization of lastlog and faillog databases.
|
||||
- **shell**: User's login shell.
|
||||
|
||||
The following fields are not yet implemented:
|
||||
|
||||
@@ -222,17 +383,17 @@ The following fields are not yet implemented:
|
||||
- **selinux-user**: Corresponding SELinux user
|
||||
- **ssh-import-id**: Import SSH keys by ID from Launchpad.
|
||||
|
||||
```
|
||||
```yaml
|
||||
#cloud-config
|
||||
|
||||
users:
|
||||
- name: elroy
|
||||
passwd: $6$5s2u6/jR$un0AvWnqilcgaNB3Mkxd5yYv6mTlWfOoCYHZmfi3LDKVltj.E8XNKEcwWm...
|
||||
- name: "elroy"
|
||||
passwd: "$6$5s2u6/jR$un0AvWnqilcgaNB3Mkxd5yYv6mTlWfOoCYHZmfi3LDKVltj.E8XNKEcwWm..."
|
||||
groups:
|
||||
- sudo
|
||||
- docker
|
||||
- "sudo"
|
||||
- "docker"
|
||||
ssh-authorized-keys:
|
||||
- ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC0g+ZTxC7weoIJLUafOgrm+h...
|
||||
- "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC0g+ZTxC7weoIJLUafOgrm+h..."
|
||||
```
|
||||
|
||||
#### Generating a password hash
|
||||
@@ -255,63 +416,52 @@ perl -e 'print crypt("password","\$6\$SALT\$") . "\n"'
|
||||
|
||||
Using a higher number of rounds will help create more secure passwords, but given enough time, password hashes can be reversed. On most RPM based distributions there is a tool called mkpasswd available in the `expect` package, but this does not handle "rounds" nor advanced hashing algorithms.
|
||||
|
||||
#### Retrieving SSH Authorized Keys
|
||||
|
||||
##### From a GitHub User
|
||||
|
||||
Using the `coreos-ssh-import-github` field, we can import public SSH keys from a GitHub user to use as authorized keys to a server.
|
||||
|
||||
```
|
||||
#cloud-config
|
||||
|
||||
users:
|
||||
- name: elroy
|
||||
coreos-ssh-import-github: elroy
|
||||
```
|
||||
|
||||
##### From an HTTP Endpoint
|
||||
|
||||
We can also pull public SSH keys from any HTTP endpoint which matches [GitHub's API response format](https://developer.github.com/v3/users/keys/#list-public-keys-for-a-user).
|
||||
For example, if you have an installation of GitHub Enterprise, you can provide a complete URL with an authentication token:
|
||||
|
||||
```
|
||||
#cloud-config
|
||||
|
||||
users:
|
||||
- name: elroy
|
||||
coreos-ssh-import-url: https://github-enterprise.example.com/api/v3/users/elroy/keys?access_token=<TOKEN>
|
||||
```
|
||||
|
||||
You can also specify any URL whose response matches the JSON format for public keys:
|
||||
|
||||
```
|
||||
#cloud-config
|
||||
|
||||
users:
|
||||
- name: elroy
|
||||
coreos-ssh-import-url: https://example.com/public-keys
|
||||
```
|
||||
|
||||
### write_files
|
||||
|
||||
The `write-file` parameter defines a list of files to create on the local filesystem. Each file is represented as an associative array which has the following keys:
|
||||
The `write_files` directive defines a set of files to create on the local filesystem.
|
||||
Each item in the list may have the following keys:
|
||||
|
||||
- **path**: Absolute location on disk where contents should be written
|
||||
- **content**: Data to write at the provided `path`
|
||||
- **permissions**: String representing file permissions in octal notation (i.e. '0644')
|
||||
- **permissions**: Integer representing file permissions, typically in octal notation (i.e. 0644)
|
||||
- **owner**: User and group that should own the file written to disk. This is equivalent to the `<user>:<group>` argument to `chown <user>:<group> <path>`.
|
||||
- **encoding**: Optional. The encoding of the data in content. If not specified this defaults to the yaml document encoding (usually utf-8). Supported encoding types are:
|
||||
- **b64, base64**: Base64 encoded content
|
||||
- **gz, gzip**: gzip encoded content, for use with the !!binary tag
|
||||
- **gz+b64, gz+base64, gzip+b64, gzip+base64**: Base64 encoded gzip content
|
||||
|
||||
Explicitly not implemented is the **encoding** attribute.
|
||||
The **content** field must represent exactly what should be written to disk.
|
||||
|
||||
```
|
||||
```yaml
|
||||
#cloud-config
|
||||
write_files:
|
||||
- path: /etc/fleet/fleet.conf
|
||||
permissions: 0644
|
||||
- path: "/etc/resolv.conf"
|
||||
permissions: "0644"
|
||||
owner: "root"
|
||||
content: |
|
||||
verbosity=1
|
||||
metadata="region=us-west,type=ssd"
|
||||
nameserver 8.8.8.8
|
||||
- path: "/etc/motd"
|
||||
permissions: "0644"
|
||||
owner: "root"
|
||||
content: |
|
||||
Good news, everyone!
|
||||
- path: "/tmp/like_this"
|
||||
permissions: "0644"
|
||||
owner: "root"
|
||||
encoding: "gzip"
|
||||
content: !!binary |
|
||||
H4sIAKgdh1QAAwtITM5WyK1USMqvUCjPLMlQSMssS1VIya9KzVPIySwszS9SyCpNLwYARQFQ5CcAAAA=
|
||||
- path: "/tmp/or_like_this"
|
||||
permissions: "0644"
|
||||
owner: "root"
|
||||
encoding: "gzip+base64"
|
||||
content: |
|
||||
H4sIAKgdh1QAAwtITM5WyK1USMqvUCjPLMlQSMssS1VIya9KzVPIySwszS9SyCpNLwYARQFQ5CcAAAA=
|
||||
- path: "/tmp/todolist"
|
||||
permissions: "0644"
|
||||
owner: "root"
|
||||
encoding: "base64"
|
||||
content: |
|
||||
UGFjayBteSBib3ggd2l0aCBmaXZlIGRvemVuIGxpcXVvciBqdWdz
|
||||
```
|
||||
|
||||
### manage_etc_hosts
|
||||
@@ -321,8 +471,8 @@ Currently, the only supported value is "localhost" which will cause your system'
|
||||
to resolve to "127.0.0.1". This is helpful when the host does not have DNS
|
||||
infrastructure in place to resolve its own hostname, for example, when using Vagrant.
|
||||
|
||||
```
|
||||
```yaml
|
||||
#cloud-config
|
||||
|
||||
manage_etc_hosts: localhost
|
||||
manage_etc_hosts: "localhost"
|
||||
```
|
||||
|
@@ -4,7 +4,7 @@ CoreOS supports providing configuration data via [config drive][config-drive]
|
||||
disk images. Currently only providing a single script or cloud config file is
|
||||
supported.
|
||||
|
||||
[config-drive]: http://docs.openstack.org/user-guide/content/enable_config_drive.html#config_drive_contents
|
||||
[config-drive]: http://docs.openstack.org/user-guide/cli_config_drive.html
|
||||
|
||||
## Contents and Format
|
||||
|
||||
@@ -14,17 +14,27 @@ The image should be a single FAT or ISO9660 file system with the label
|
||||
|
||||
For example, to wrap up a config named `user_data` in a config drive image:
|
||||
|
||||
mkdir -p /tmp/new-drive/openstack/latest
|
||||
cp user_data /tmp/new-drive/openstack/latest/user_data
|
||||
mkisofs -R -V config-2 -o configdrive.iso /tmp/new-drive
|
||||
rm -r /tmp/new-drive
|
||||
```sh
|
||||
mkdir -p /tmp/new-drive/openstack/latest
|
||||
cp user_data /tmp/new-drive/openstack/latest/user_data
|
||||
mkisofs -R -V config-2 -o configdrive.iso /tmp/new-drive
|
||||
rm -r /tmp/new-drive
|
||||
```
|
||||
|
||||
If on OS X, replace the `mkisofs` invocation with:
|
||||
|
||||
```sh
|
||||
hdiutil makehybrid -iso -joliet -default-volume-name config-2 -o configdrive.iso /tmp/new-drive
|
||||
```
|
||||
|
||||
## QEMU virtfs
|
||||
|
||||
One exception to the above, when using QEMU it is possible to skip creating an
|
||||
image and use a plain directory containing the same contents:
|
||||
|
||||
qemu-system-x86_64 \
|
||||
-fsdev local,id=conf,security_model=none,readonly,path=/tmp/new-drive \
|
||||
-device virtio-9p-pci,fsdev=conf,mount_tag=config-2 \
|
||||
[usual qemu options here...]
|
||||
```sh
|
||||
qemu-system-x86_64 \
|
||||
-fsdev local,id=conf,security_model=none,readonly,path=/tmp/new-drive \
|
||||
-device virtio-9p-pci,fsdev=conf,mount_tag=config-2 \
|
||||
[usual qemu options here...]
|
||||
```
|
||||
|
32
Documentation/vmware-backdoor.md
Normal file
32
Documentation/vmware-backdoor.md
Normal file
@@ -0,0 +1,32 @@
|
||||
# VMware Backdoor
|
||||
|
||||
## Cloud-Config Options List
|
||||
|
||||
coreos-cloudinit is capable of reading userdata and metadata from the VMware
|
||||
backdoor. This datasource can be enabled with the `--from-vmware-backdoor` flag.
|
||||
Userdata and metadata are passed from the hypervisor to the virtual machine
|
||||
through guest variables. The following guest variables and their expected types
|
||||
are supported by coreos-cloudinit:
|
||||
|
||||
| guest variable | type |
|
||||
|:--------------------------------------|:--------------------------------|
|
||||
| `hostname` | `hostname` |
|
||||
| `interface.<n>.name` | `string` |
|
||||
| `interface.<n>.mac` | `MAC address` |
|
||||
| `interface.<n>.dhcp` | `{"yes", "no"}` |
|
||||
| `interface.<n>.role` | `{"public", "private"}` |
|
||||
| `interface.<n>.ip.<m>.address` | `CIDR IP address` |
|
||||
| `interface.<n>.route.<l>.gateway` | `IP address` |
|
||||
| `interface.<n>.route.<l>.destination` | `CIDR IP address` |
|
||||
| `dns.server.<x>` | `IP address` |
|
||||
| `coreos.config.data` | `string` |
|
||||
| `coreos.config.data.encoding` | `{"", "base64", "gzip+base64"}` |
|
||||
| `coreos.config.url` | `URL` |
|
||||
|
||||
Note: "n", "m", "l", and "x" are 0-indexed, incrementing integers. The
|
||||
identifier for the interfaces does not correspond to anything outside of this
|
||||
configuration; it is merely for mapping configuration values to each interface.
|
||||
|
||||
Please refer to [link][vmware] to know more how to run CoreOS on VMware.
|
||||
|
||||
[vmware]: https://github.com/coreos/docs/blob/master/os/booting-on-vmware.md
|
38
Godeps/Godeps.json
generated
Normal file
38
Godeps/Godeps.json
generated
Normal file
@@ -0,0 +1,38 @@
|
||||
{
|
||||
"ImportPath": "github.com/coreos/coreos-cloudinit",
|
||||
"GoVersion": "go1.3.3",
|
||||
"Packages": [
|
||||
"./..."
|
||||
],
|
||||
"Deps": [
|
||||
{
|
||||
"ImportPath": "github.com/cloudsigma/cepgo",
|
||||
"Rev": "1bfc4895bf5c4d3b599f3f6ee142299488c8739b"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/go-systemd/dbus",
|
||||
"Rev": "4fbc5060a317b142e6c7bfbedb65596d5f0ab99b"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/yaml",
|
||||
"Rev": "6b16a5714269b2f70720a45406b1babd947a17ef"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/dotcloud/docker/pkg/netlink",
|
||||
"Comment": "v0.11.1-359-g55d41c3e21e1",
|
||||
"Rev": "55d41c3e21e1593b944c06196ffb2ac57ab7f653"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/guelfey/go.dbus",
|
||||
"Rev": "f6a3a2366cc39b8479cadc499d3c735fb10fbdda"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/tarm/goserial",
|
||||
"Rev": "cdabc8d44e8e84f58f18074ae44337e1f2f375b9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/sigma/vmw-guestinfo",
|
||||
"Rev": "de573afc542e0268fe8478d46e237fad9d6f7aec"
|
||||
}
|
||||
]
|
||||
}
|
5
Godeps/Readme
generated
Normal file
5
Godeps/Readme
generated
Normal file
@@ -0,0 +1,5 @@
|
||||
This directory tree is generated automatically by godep.
|
||||
|
||||
Please do not edit.
|
||||
|
||||
See https://github.com/tools/godep for more information.
|
2
Godeps/_workspace/.gitignore
generated
vendored
Normal file
2
Godeps/_workspace/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
/pkg
|
||||
/bin
|
23
Godeps/_workspace/src/github.com/cloudsigma/cepgo/.gitignore
generated
vendored
Normal file
23
Godeps/_workspace/src/github.com/cloudsigma/cepgo/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
# Compiled Object files, Static and Dynamic libs (Shared Objects)
|
||||
*.o
|
||||
*.a
|
||||
*.so
|
||||
|
||||
# Folders
|
||||
_obj
|
||||
_test
|
||||
|
||||
# Architecture specific extensions/prefixes
|
||||
*.[568vq]
|
||||
[568vq].out
|
||||
|
||||
*.cgo1.go
|
||||
*.cgo2.c
|
||||
_cgo_defun.c
|
||||
_cgo_gotypes.go
|
||||
_cgo_export.*
|
||||
|
||||
_testmain.go
|
||||
|
||||
*.exe
|
||||
*.test
|
202
Godeps/_workspace/src/github.com/cloudsigma/cepgo/LICENSE
generated
vendored
Normal file
202
Godeps/_workspace/src/github.com/cloudsigma/cepgo/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,202 @@
|
||||
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.
|
||||
|
43
Godeps/_workspace/src/github.com/cloudsigma/cepgo/README.md
generated
vendored
Normal file
43
Godeps/_workspace/src/github.com/cloudsigma/cepgo/README.md
generated
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
cepgo
|
||||
=====
|
||||
|
||||
Cepko implements easy-to-use communication with CloudSigma's VMs through a
|
||||
virtual serial port without bothering with formatting the messages properly nor
|
||||
parsing the output with the specific and sometimes confusing shell tools for
|
||||
that purpose.
|
||||
|
||||
Having the server definition accessible by the VM can be useful in various
|
||||
ways. For example it is possible to easily determine from within the VM, which
|
||||
network interfaces are connected to public and which to private network.
|
||||
Another use is to pass some data to initial VM setup scripts, like setting the
|
||||
hostname to the VM name or passing ssh public keys through server meta.
|
||||
|
||||
Example usage:
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/cloudsigma/cepgo"
|
||||
)
|
||||
|
||||
func main() {
|
||||
c := cepgo.NewCepgo()
|
||||
result, err := c.Meta()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fmt.Printf("%#v", result)
|
||||
}
|
||||
|
||||
Output:
|
||||
|
||||
map[string]interface {}{
|
||||
"optimize_for":"custom",
|
||||
"ssh_public_key":"ssh-rsa AAA...",
|
||||
"description":"[...]",
|
||||
}
|
||||
|
||||
For more information take a look at the Server Context section of CloudSigma
|
||||
API Docs: http://cloudsigma-docs.readthedocs.org/en/latest/server_context.html
|
186
Godeps/_workspace/src/github.com/cloudsigma/cepgo/cepgo.go
generated
vendored
Normal file
186
Godeps/_workspace/src/github.com/cloudsigma/cepgo/cepgo.go
generated
vendored
Normal file
@@ -0,0 +1,186 @@
|
||||
// Cepko implements easy-to-use communication with CloudSigma's VMs through a
|
||||
// virtual serial port without bothering with formatting the messages properly
|
||||
// nor parsing the output with the specific and sometimes confusing shell tools
|
||||
// for that purpose.
|
||||
//
|
||||
// Having the server definition accessible by the VM can be useful in various
|
||||
// ways. For example it is possible to easily determine from within the VM,
|
||||
// which network interfaces are connected to public and which to private
|
||||
// network. Another use is to pass some data to initial VM setup scripts, like
|
||||
// setting the hostname to the VM name or passing ssh public keys through
|
||||
// server meta.
|
||||
//
|
||||
// Example usage:
|
||||
//
|
||||
// package main
|
||||
//
|
||||
// import (
|
||||
// "fmt"
|
||||
//
|
||||
// "github.com/cloudsigma/cepgo"
|
||||
// )
|
||||
//
|
||||
// func main() {
|
||||
// c := cepgo.NewCepgo()
|
||||
// result, err := c.Meta()
|
||||
// if err != nil {
|
||||
// panic(err)
|
||||
// }
|
||||
// fmt.Printf("%#v", result)
|
||||
// }
|
||||
//
|
||||
// Output:
|
||||
//
|
||||
// map[string]string{
|
||||
// "optimize_for":"custom",
|
||||
// "ssh_public_key":"ssh-rsa AAA...",
|
||||
// "description":"[...]",
|
||||
// }
|
||||
//
|
||||
// For more information take a look at the Server Context section API Docs:
|
||||
// http://cloudsigma-docs.readthedocs.org/en/latest/server_context.html
|
||||
package cepgo
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"runtime"
|
||||
|
||||
"github.com/coreos/coreos-cloudinit/Godeps/_workspace/src/github.com/tarm/goserial"
|
||||
)
|
||||
|
||||
const (
|
||||
requestPattern = "<\n%s\n>"
|
||||
EOT = '\x04' // End Of Transmission
|
||||
)
|
||||
|
||||
var (
|
||||
SerialPort string = "/dev/ttyS1"
|
||||
Baud int = 115200
|
||||
)
|
||||
|
||||
// Sets the serial port. If the operating system is windows CloudSigma's server
|
||||
// context is at COM2 port, otherwise (linux, freebsd, darwin) the port is
|
||||
// being left to the default /dev/ttyS1.
|
||||
func init() {
|
||||
if runtime.GOOS == "windows" {
|
||||
SerialPort = "COM2"
|
||||
}
|
||||
}
|
||||
|
||||
// The default fetcher makes the connection to the serial port,
|
||||
// writes given query and reads until the EOT symbol.
|
||||
func fetchViaSerialPort(key string) ([]byte, error) {
|
||||
config := &serial.Config{Name: SerialPort, Baud: Baud}
|
||||
connection, err := serial.OpenPort(config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
query := fmt.Sprintf(requestPattern, key)
|
||||
if _, err := connection.Write([]byte(query)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
reader := bufio.NewReader(connection)
|
||||
answer, err := reader.ReadBytes(EOT)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return answer[0 : len(answer)-1], nil
|
||||
}
|
||||
|
||||
// Queries to the serial port can be executed only from instance of this type.
|
||||
// The result from each of them can be either interface{}, map[string]string or
|
||||
// a single in case of single value is returned. There is also a public metod
|
||||
// who directly calls the fetcher and returns raw []byte from the serial port.
|
||||
type Cepgo struct {
|
||||
fetcher func(string) ([]byte, error)
|
||||
}
|
||||
|
||||
// Creates a Cepgo instance with the default serial port fetcher.
|
||||
func NewCepgo() *Cepgo {
|
||||
cepgo := new(Cepgo)
|
||||
cepgo.fetcher = fetchViaSerialPort
|
||||
return cepgo
|
||||
}
|
||||
|
||||
// Creates a Cepgo instance with custom fetcher.
|
||||
func NewCepgoFetcher(fetcher func(string) ([]byte, error)) *Cepgo {
|
||||
cepgo := new(Cepgo)
|
||||
cepgo.fetcher = fetcher
|
||||
return cepgo
|
||||
}
|
||||
|
||||
// Fetches raw []byte from the serial port using directly the fetcher member.
|
||||
func (c *Cepgo) FetchRaw(key string) ([]byte, error) {
|
||||
return c.fetcher(key)
|
||||
}
|
||||
|
||||
// Fetches a single key and tries to unmarshal the result to json and returns
|
||||
// it. If the unmarshalling fails it's safe to assume the result it's just a
|
||||
// string and returns it.
|
||||
func (c *Cepgo) Key(key string) (interface{}, error) {
|
||||
var result interface{}
|
||||
|
||||
fetched, err := c.FetchRaw(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = json.Unmarshal(fetched, &result)
|
||||
if err != nil {
|
||||
return string(fetched), nil
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// Fetches all the server context. Equivalent of c.Key("")
|
||||
func (c *Cepgo) All() (interface{}, error) {
|
||||
return c.Key("")
|
||||
}
|
||||
|
||||
// Fetches only the object meta field and makes sure to return a proper
|
||||
// map[string]string
|
||||
func (c *Cepgo) Meta() (map[string]string, error) {
|
||||
rawMeta, err := c.Key("/meta/")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return typeAssertToMapOfStrings(rawMeta)
|
||||
}
|
||||
|
||||
// Fetches only the global context and makes sure to return a proper
|
||||
// map[string]string
|
||||
func (c *Cepgo) GlobalContext() (map[string]string, error) {
|
||||
rawContext, err := c.Key("/global_context/")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return typeAssertToMapOfStrings(rawContext)
|
||||
}
|
||||
|
||||
// Just a little helper function that uses type assertions in order to convert
|
||||
// a interface{} to map[string]string if this is possible.
|
||||
func typeAssertToMapOfStrings(raw interface{}) (map[string]string, error) {
|
||||
result := make(map[string]string)
|
||||
|
||||
dictionary, ok := raw.(map[string]interface{})
|
||||
if !ok {
|
||||
return nil, errors.New("Received bytes are formatted badly")
|
||||
}
|
||||
|
||||
for key, rawValue := range dictionary {
|
||||
if value, ok := rawValue.(string); ok {
|
||||
result[key] = value
|
||||
} else {
|
||||
return nil, errors.New("Server context metadata is formatted badly")
|
||||
}
|
||||
}
|
||||
return result, nil
|
||||
}
|
122
Godeps/_workspace/src/github.com/cloudsigma/cepgo/cepgo_test.go
generated
vendored
Normal file
122
Godeps/_workspace/src/github.com/cloudsigma/cepgo/cepgo_test.go
generated
vendored
Normal file
@@ -0,0 +1,122 @@
|
||||
package cepgo
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func fetchMock(key string) ([]byte, error) {
|
||||
context := []byte(`{
|
||||
"context": true,
|
||||
"cpu": 4000,
|
||||
"cpu_model": null,
|
||||
"cpus_instead_of_cores": false,
|
||||
"enable_numa": false,
|
||||
"global_context": {
|
||||
"some_global_key": "some_global_val"
|
||||
},
|
||||
"grantees": [],
|
||||
"hv_relaxed": false,
|
||||
"hv_tsc": false,
|
||||
"jobs": [],
|
||||
"mem": 4294967296,
|
||||
"meta": {
|
||||
"base64_fields": "cloudinit-user-data",
|
||||
"cloudinit-user-data": "I2Nsb3VkLWNvbmZpZwoKaG9zdG5hbWU6IGNvcmVvczE=",
|
||||
"ssh_public_key": "ssh-rsa AAAAB2NzaC1yc2E.../hQ5D5 john@doe"
|
||||
},
|
||||
"name": "coreos",
|
||||
"nics": [
|
||||
{
|
||||
"runtime": {
|
||||
"interface_type": "public",
|
||||
"ip_v4": {
|
||||
"uuid": "31.171.251.74"
|
||||
},
|
||||
"ip_v6": null
|
||||
},
|
||||
"vlan": null
|
||||
}
|
||||
],
|
||||
"smp": 2,
|
||||
"status": "running",
|
||||
"uuid": "20a0059b-041e-4d0c-bcc6-9b2852de48b3"
|
||||
}`)
|
||||
|
||||
if key == "" {
|
||||
return context, nil
|
||||
}
|
||||
|
||||
var marshalledContext map[string]interface{}
|
||||
|
||||
err := json.Unmarshal(context, &marshalledContext)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if key[0] == '/' {
|
||||
key = key[1:]
|
||||
}
|
||||
if key[len(key)-1] == '/' {
|
||||
key = key[:len(key)-1]
|
||||
}
|
||||
|
||||
return json.Marshal(marshalledContext[key])
|
||||
}
|
||||
|
||||
func TestAll(t *testing.T) {
|
||||
cepgo := NewCepgoFetcher(fetchMock)
|
||||
|
||||
result, err := cepgo.All()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
for _, key := range []string{"meta", "name", "uuid", "global_context"} {
|
||||
if _, ok := result.(map[string]interface{})[key]; !ok {
|
||||
t.Errorf("%s not in all keys", key)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestKey(t *testing.T) {
|
||||
cepgo := NewCepgoFetcher(fetchMock)
|
||||
|
||||
result, err := cepgo.Key("uuid")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if _, ok := result.(string); !ok {
|
||||
t.Errorf("%#v\n", result)
|
||||
|
||||
t.Error("Fetching the uuid did not return a string")
|
||||
}
|
||||
}
|
||||
|
||||
func TestMeta(t *testing.T) {
|
||||
cepgo := NewCepgoFetcher(fetchMock)
|
||||
|
||||
meta, err := cepgo.Meta()
|
||||
if err != nil {
|
||||
t.Errorf("%#v\n", meta)
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if _, ok := meta["ssh_public_key"]; !ok {
|
||||
t.Error("ssh_public_key is not in the meta")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGlobalContext(t *testing.T) {
|
||||
cepgo := NewCepgoFetcher(fetchMock)
|
||||
|
||||
result, err := cepgo.GlobalContext()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if _, ok := result["some_global_key"]; !ok {
|
||||
t.Error("some_global_key is not in the global context")
|
||||
}
|
||||
}
|
@@ -23,7 +23,7 @@ import (
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/coreos/coreos-cloudinit/third_party/github.com/guelfey/go.dbus"
|
||||
"github.com/coreos/coreos-cloudinit/Godeps/_workspace/src/github.com/guelfey/go.dbus"
|
||||
)
|
||||
|
||||
const signalBuffer = 100
|
@@ -18,7 +18,7 @@ package dbus
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"github.com/coreos/coreos-cloudinit/third_party/github.com/guelfey/go.dbus"
|
||||
"github.com/coreos/coreos-cloudinit/Godeps/_workspace/src/github.com/guelfey/go.dbus"
|
||||
)
|
||||
|
||||
func (c *Conn) initJobs() {
|
||||
@@ -208,7 +208,7 @@ func (c *Conn) SetUnitProperties(name string, runtime bool, properties ...Proper
|
||||
}
|
||||
|
||||
func (c *Conn) GetUnitTypeProperty(unit string, unitType string, propertyName string) (*Property, error) {
|
||||
return c.getProperty(unit, "org.freedesktop.systemd1." + unitType, propertyName)
|
||||
return c.getProperty(unit, "org.freedesktop.systemd1."+unitType, propertyName)
|
||||
}
|
||||
|
||||
// ListUnits returns an array with all currently loaded units. Note that
|
@@ -18,7 +18,7 @@ package dbus
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/coreos/coreos-cloudinit/third_party/github.com/guelfey/go.dbus"
|
||||
"github.com/coreos/coreos-cloudinit/Godeps/_workspace/src/github.com/guelfey/go.dbus"
|
||||
"math/rand"
|
||||
"os"
|
||||
"path/filepath"
|
@@ -17,7 +17,7 @@ limitations under the License.
|
||||
package dbus
|
||||
|
||||
import (
|
||||
"github.com/coreos/coreos-cloudinit/third_party/github.com/guelfey/go.dbus"
|
||||
"github.com/coreos/coreos-cloudinit/Godeps/_workspace/src/github.com/guelfey/go.dbus"
|
||||
)
|
||||
|
||||
// From the systemd docs:
|
@@ -20,7 +20,7 @@ import (
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"github.com/coreos/coreos-cloudinit/third_party/github.com/guelfey/go.dbus"
|
||||
"github.com/coreos/coreos-cloudinit/Godeps/_workspace/src/github.com/guelfey/go.dbus"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -101,7 +101,7 @@ func (c *Conn) SubscribeUnits(interval time.Duration) (<-chan map[string]*UnitSt
|
||||
// SubscribeUnitsCustom is like SubscribeUnits but lets you specify the buffer
|
||||
// size of the channels, the comparison function for detecting changes and a filter
|
||||
// function for cutting down on the noise that your channel receives.
|
||||
func (c *Conn) SubscribeUnitsCustom(interval time.Duration, buffer int, isChanged func(*UnitStatus, *UnitStatus) bool, filterUnit func (string) bool) (<-chan map[string]*UnitStatus, <-chan error) {
|
||||
func (c *Conn) SubscribeUnitsCustom(interval time.Duration, buffer int, isChanged func(*UnitStatus, *UnitStatus) bool, filterUnit func(string) bool) (<-chan map[string]*UnitStatus, <-chan error) {
|
||||
old := make(map[string]*UnitStatus)
|
||||
statusChan := make(chan map[string]*UnitStatus, buffer)
|
||||
errChan := make(chan error, buffer)
|
@@ -1,3 +1,6 @@
|
||||
|
||||
Copyright (c) 2011-2014 - Canonical Inc.
|
||||
|
||||
This software is licensed under the LGPLv3, included below.
|
||||
|
||||
As a special exception to the GNU Lesser General Public License version 3
|
@@ -1,3 +1,15 @@
|
||||
The following files were ported to Go from C files of libyaml, and thus
|
||||
are still covered by their original copyright and license:
|
||||
|
||||
apic.go
|
||||
emitterc.go
|
||||
parserc.go
|
||||
readerc.go
|
||||
scannerc.go
|
||||
writerc.go
|
||||
yamlh.go
|
||||
yamlprivateh.go
|
||||
|
||||
Copyright (c) 2006 Kirill Simonov
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
131
Godeps/_workspace/src/github.com/coreos/yaml/README.md
generated
vendored
Normal file
131
Godeps/_workspace/src/github.com/coreos/yaml/README.md
generated
vendored
Normal file
@@ -0,0 +1,131 @@
|
||||
Note: This is a fork of https://github.com/go-yaml/yaml. The following README
|
||||
doesn't necessarily apply to this fork.
|
||||
|
||||
# YAML support for the Go language
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
||||
The yaml package enables Go programs to comfortably encode and decode YAML
|
||||
values. It was developed within [Canonical](https://www.canonical.com) as
|
||||
part of the [juju](https://juju.ubuntu.com) project, and is based on a
|
||||
pure Go port of the well-known [libyaml](http://pyyaml.org/wiki/LibYAML)
|
||||
C library to parse and generate YAML data quickly and reliably.
|
||||
|
||||
Compatibility
|
||||
-------------
|
||||
|
||||
The yaml package supports most of YAML 1.1 and 1.2, including support for
|
||||
anchors, tags, map merging, etc. Multi-document unmarshalling is not yet
|
||||
implemented, and base-60 floats from YAML 1.1 are purposefully not
|
||||
supported since they're a poor design and are gone in YAML 1.2.
|
||||
|
||||
Installation and usage
|
||||
----------------------
|
||||
|
||||
The import path for the package is *gopkg.in/yaml.v1*.
|
||||
|
||||
To install it, run:
|
||||
|
||||
go get gopkg.in/yaml.v1
|
||||
|
||||
API documentation
|
||||
-----------------
|
||||
|
||||
If opened in a browser, the import path itself leads to the API documentation:
|
||||
|
||||
* [https://gopkg.in/yaml.v1](https://gopkg.in/yaml.v1)
|
||||
|
||||
API stability
|
||||
-------------
|
||||
|
||||
The package API for yaml v1 will remain stable as described in [gopkg.in](https://gopkg.in).
|
||||
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
The yaml package is licensed under the LGPL with an exception that allows it to be linked statically. Please see the LICENSE file for details.
|
||||
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
```Go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"gopkg.in/yaml.v1"
|
||||
)
|
||||
|
||||
var data = `
|
||||
a: Easy!
|
||||
b:
|
||||
c: 2
|
||||
d: [3, 4]
|
||||
`
|
||||
|
||||
type T struct {
|
||||
A string
|
||||
B struct{C int; D []int ",flow"}
|
||||
}
|
||||
|
||||
func main() {
|
||||
t := T{}
|
||||
|
||||
err := yaml.Unmarshal([]byte(data), &t)
|
||||
if err != nil {
|
||||
log.Fatalf("error: %v", err)
|
||||
}
|
||||
fmt.Printf("--- t:\n%v\n\n", t)
|
||||
|
||||
d, err := yaml.Marshal(&t)
|
||||
if err != nil {
|
||||
log.Fatalf("error: %v", err)
|
||||
}
|
||||
fmt.Printf("--- t dump:\n%s\n\n", string(d))
|
||||
|
||||
m := make(map[interface{}]interface{})
|
||||
|
||||
err = yaml.Unmarshal([]byte(data), &m)
|
||||
if err != nil {
|
||||
log.Fatalf("error: %v", err)
|
||||
}
|
||||
fmt.Printf("--- m:\n%v\n\n", m)
|
||||
|
||||
d, err = yaml.Marshal(&m)
|
||||
if err != nil {
|
||||
log.Fatalf("error: %v", err)
|
||||
}
|
||||
fmt.Printf("--- m dump:\n%s\n\n", string(d))
|
||||
}
|
||||
```
|
||||
|
||||
This example will generate the following output:
|
||||
|
||||
```
|
||||
--- t:
|
||||
{Easy! {2 [3 4]}}
|
||||
|
||||
--- t dump:
|
||||
a: Easy!
|
||||
b:
|
||||
c: 2
|
||||
d: [3, 4]
|
||||
|
||||
|
||||
--- m:
|
||||
map[a:Easy! b:map[c:2 d:[3 4]]]
|
||||
|
||||
--- m dump:
|
||||
a: Easy!
|
||||
b:
|
||||
c: 2
|
||||
d:
|
||||
- 3
|
||||
- 4
|
||||
```
|
||||
|
@@ -1,4 +1,4 @@
|
||||
package goyaml
|
||||
package yaml
|
||||
|
||||
import (
|
||||
"io"
|
@@ -1,8 +1,11 @@
|
||||
package goyaml
|
||||
package yaml
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -27,13 +30,15 @@ type node struct {
|
||||
// Parser, produces a node tree out of a libyaml event stream.
|
||||
|
||||
type parser struct {
|
||||
parser yaml_parser_t
|
||||
event yaml_event_t
|
||||
doc *node
|
||||
parser yaml_parser_t
|
||||
event yaml_event_t
|
||||
doc *node
|
||||
transform transformString
|
||||
}
|
||||
|
||||
func newParser(b []byte) *parser {
|
||||
p := parser{}
|
||||
func newParser(b []byte, t transformString) *parser {
|
||||
p := parser{transform: t}
|
||||
|
||||
if !yaml_parser_initialize(&p.parser) {
|
||||
panic("Failed to initialize YAML emitter")
|
||||
}
|
||||
@@ -62,7 +67,7 @@ func (p *parser) destroy() {
|
||||
func (p *parser) skip() {
|
||||
if p.event.typ != yaml_NO_EVENT {
|
||||
if p.event.typ == yaml_STREAM_END_EVENT {
|
||||
panic("Attempted to go past the end of stream. Corrupted value?")
|
||||
fail("Attempted to go past the end of stream. Corrupted value?")
|
||||
}
|
||||
yaml_event_delete(&p.event)
|
||||
}
|
||||
@@ -88,7 +93,7 @@ func (p *parser) fail() {
|
||||
} else {
|
||||
msg = "Unknown problem parsing YAML content"
|
||||
}
|
||||
panic(where + msg)
|
||||
fail(where + msg)
|
||||
}
|
||||
|
||||
func (p *parser) anchor(n *node, anchor []byte) {
|
||||
@@ -113,10 +118,9 @@ func (p *parser) parse() *node {
|
||||
// Happens when attempting to decode an empty buffer.
|
||||
return nil
|
||||
default:
|
||||
panic("Attempted to parse unknown event: " +
|
||||
strconv.Itoa(int(p.event.typ)))
|
||||
panic("Attempted to parse unknown event: " + strconv.Itoa(int(p.event.typ)))
|
||||
}
|
||||
panic("Unreachable")
|
||||
panic("unreachable")
|
||||
}
|
||||
|
||||
func (p *parser) node(kind int) *node {
|
||||
@@ -134,8 +138,7 @@ func (p *parser) document() *node {
|
||||
p.skip()
|
||||
n.children = append(n.children, p.parse())
|
||||
if p.event.typ != yaml_DOCUMENT_END_EVENT {
|
||||
panic("Expected end of document event but got " +
|
||||
strconv.Itoa(int(p.event.typ)))
|
||||
panic("Expected end of document event but got " + strconv.Itoa(int(p.event.typ)))
|
||||
}
|
||||
p.skip()
|
||||
return n
|
||||
@@ -174,7 +177,10 @@ func (p *parser) mapping() *node {
|
||||
p.anchor(n, p.event.anchor)
|
||||
p.skip()
|
||||
for p.event.typ != yaml_MAPPING_END_EVENT {
|
||||
n.children = append(n.children, p.parse(), p.parse())
|
||||
key := p.parse()
|
||||
key.value = p.transform(key.value)
|
||||
value := p.parse()
|
||||
n.children = append(n.children, key, value)
|
||||
}
|
||||
p.skip()
|
||||
return n
|
||||
@@ -211,11 +217,21 @@ func newDecoder() *decoder {
|
||||
// returned to call SetYAML() with the value of *out once it's defined.
|
||||
//
|
||||
func (d *decoder) setter(tag string, out *reflect.Value, good *bool) (set func()) {
|
||||
if (*out).Kind() != reflect.Ptr && (*out).CanAddr() {
|
||||
setter, _ := (*out).Addr().Interface().(Setter)
|
||||
if setter != nil {
|
||||
var arg interface{}
|
||||
*out = reflect.ValueOf(&arg).Elem()
|
||||
return func() {
|
||||
*good = setter.SetYAML(shortTag(tag), arg)
|
||||
}
|
||||
}
|
||||
}
|
||||
again := true
|
||||
for again {
|
||||
again = false
|
||||
setter, _ := (*out).Interface().(Setter)
|
||||
if tag != "!!null" || setter != nil {
|
||||
if tag != yaml_NULL_TAG || setter != nil {
|
||||
if pv := (*out); pv.Kind() == reflect.Ptr {
|
||||
if pv.IsNil() {
|
||||
*out = reflect.New(pv.Type().Elem()).Elem()
|
||||
@@ -231,7 +247,7 @@ func (d *decoder) setter(tag string, out *reflect.Value, good *bool) (set func()
|
||||
var arg interface{}
|
||||
*out = reflect.ValueOf(&arg).Elem()
|
||||
return func() {
|
||||
*good = setter.SetYAML(tag, arg)
|
||||
*good = setter.SetYAML(shortTag(tag), arg)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -268,10 +284,10 @@ func (d *decoder) document(n *node, out reflect.Value) (good bool) {
|
||||
func (d *decoder) alias(n *node, out reflect.Value) (good bool) {
|
||||
an, ok := d.doc.anchors[n.value]
|
||||
if !ok {
|
||||
panic("Unknown anchor '" + n.value + "' referenced")
|
||||
fail("Unknown anchor '" + n.value + "' referenced")
|
||||
}
|
||||
if d.aliases[n.value] {
|
||||
panic("Anchor '" + n.value + "' value contains itself")
|
||||
fail("Anchor '" + n.value + "' value contains itself")
|
||||
}
|
||||
d.aliases[n.value] = true
|
||||
good = d.unmarshal(an, out)
|
||||
@@ -279,20 +295,50 @@ func (d *decoder) alias(n *node, out reflect.Value) (good bool) {
|
||||
return good
|
||||
}
|
||||
|
||||
var zeroValue reflect.Value
|
||||
|
||||
func resetMap(out reflect.Value) {
|
||||
for _, k := range out.MapKeys() {
|
||||
out.SetMapIndex(k, zeroValue)
|
||||
}
|
||||
}
|
||||
|
||||
var durationType = reflect.TypeOf(time.Duration(0))
|
||||
|
||||
func (d *decoder) scalar(n *node, out reflect.Value) (good bool) {
|
||||
var tag string
|
||||
var resolved interface{}
|
||||
if n.tag == "" && !n.implicit {
|
||||
tag = yaml_STR_TAG
|
||||
resolved = n.value
|
||||
} else {
|
||||
tag, resolved = resolve(n.tag, n.value)
|
||||
if set := d.setter(tag, &out, &good); set != nil {
|
||||
defer set()
|
||||
if tag == yaml_BINARY_TAG {
|
||||
data, err := base64.StdEncoding.DecodeString(resolved.(string))
|
||||
if err != nil {
|
||||
fail("!!binary value contains invalid base64 data")
|
||||
}
|
||||
resolved = string(data)
|
||||
}
|
||||
}
|
||||
if set := d.setter(tag, &out, &good); set != nil {
|
||||
defer set()
|
||||
}
|
||||
if resolved == nil {
|
||||
if out.Kind() == reflect.Map && !out.CanAddr() {
|
||||
resetMap(out)
|
||||
} else {
|
||||
out.Set(reflect.Zero(out.Type()))
|
||||
}
|
||||
good = true
|
||||
return
|
||||
}
|
||||
switch out.Kind() {
|
||||
case reflect.String:
|
||||
if resolved != nil {
|
||||
if tag == yaml_BINARY_TAG {
|
||||
out.SetString(resolved.(string))
|
||||
good = true
|
||||
} else if resolved != nil {
|
||||
out.SetString(n.value)
|
||||
good = true
|
||||
}
|
||||
@@ -320,6 +366,14 @@ func (d *decoder) scalar(n *node, out reflect.Value) (good bool) {
|
||||
out.SetInt(int64(resolved))
|
||||
good = true
|
||||
}
|
||||
case string:
|
||||
if out.Type() == durationType {
|
||||
d, err := time.ParseDuration(resolved)
|
||||
if err == nil {
|
||||
out.SetInt(int64(d))
|
||||
good = true
|
||||
}
|
||||
}
|
||||
}
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||
switch resolved := resolved.(type) {
|
||||
@@ -358,17 +412,11 @@ func (d *decoder) scalar(n *node, out reflect.Value) (good bool) {
|
||||
good = true
|
||||
}
|
||||
case reflect.Ptr:
|
||||
switch resolved.(type) {
|
||||
case nil:
|
||||
out.Set(reflect.Zero(out.Type()))
|
||||
if out.Type().Elem() == reflect.TypeOf(resolved) {
|
||||
elem := reflect.New(out.Type().Elem())
|
||||
elem.Elem().Set(reflect.ValueOf(resolved))
|
||||
out.Set(elem)
|
||||
good = true
|
||||
default:
|
||||
if out.Type().Elem() == reflect.TypeOf(resolved) {
|
||||
elem := reflect.New(out.Type().Elem())
|
||||
elem.Elem().Set(reflect.ValueOf(resolved))
|
||||
out.Set(elem)
|
||||
good = true
|
||||
}
|
||||
}
|
||||
}
|
||||
return good
|
||||
@@ -382,7 +430,7 @@ func settableValueOf(i interface{}) reflect.Value {
|
||||
}
|
||||
|
||||
func (d *decoder) sequence(n *node, out reflect.Value) (good bool) {
|
||||
if set := d.setter("!!seq", &out, &good); set != nil {
|
||||
if set := d.setter(yaml_SEQ_TAG, &out, &good); set != nil {
|
||||
defer set()
|
||||
}
|
||||
var iface reflect.Value
|
||||
@@ -411,7 +459,7 @@ func (d *decoder) sequence(n *node, out reflect.Value) (good bool) {
|
||||
}
|
||||
|
||||
func (d *decoder) mapping(n *node, out reflect.Value) (good bool) {
|
||||
if set := d.setter("!!map", &out, &good); set != nil {
|
||||
if set := d.setter(yaml_MAP_TAG, &out, &good); set != nil {
|
||||
defer set()
|
||||
}
|
||||
if out.Kind() == reflect.Struct {
|
||||
@@ -437,8 +485,19 @@ func (d *decoder) mapping(n *node, out reflect.Value) (good bool) {
|
||||
}
|
||||
l := len(n.children)
|
||||
for i := 0; i < l; i += 2 {
|
||||
if isMerge(n.children[i]) {
|
||||
d.merge(n.children[i+1], out)
|
||||
continue
|
||||
}
|
||||
k := reflect.New(kt).Elem()
|
||||
if d.unmarshal(n.children[i], k) {
|
||||
kkind := k.Kind()
|
||||
if kkind == reflect.Interface {
|
||||
kkind = k.Elem().Kind()
|
||||
}
|
||||
if kkind == reflect.Map || kkind == reflect.Slice {
|
||||
fail(fmt.Sprintf("invalid map key: %#v", k.Interface()))
|
||||
}
|
||||
e := reflect.New(et).Elem()
|
||||
if d.unmarshal(n.children[i+1], e) {
|
||||
out.SetMapIndex(k, e)
|
||||
@@ -456,7 +515,12 @@ func (d *decoder) mappingStruct(n *node, out reflect.Value) (good bool) {
|
||||
name := settableValueOf("")
|
||||
l := len(n.children)
|
||||
for i := 0; i < l; i += 2 {
|
||||
if !d.unmarshal(n.children[i], name) {
|
||||
ni := n.children[i]
|
||||
if isMerge(ni) {
|
||||
d.merge(n.children[i+1], out)
|
||||
continue
|
||||
}
|
||||
if !d.unmarshal(ni, name) {
|
||||
continue
|
||||
}
|
||||
if info, ok := sinfo.FieldsMap[name.String()]; ok {
|
||||
@@ -471,3 +535,37 @@ func (d *decoder) mappingStruct(n *node, out reflect.Value) (good bool) {
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (d *decoder) merge(n *node, out reflect.Value) {
|
||||
const wantMap = "map merge requires map or sequence of maps as the value"
|
||||
switch n.kind {
|
||||
case mappingNode:
|
||||
d.unmarshal(n, out)
|
||||
case aliasNode:
|
||||
an, ok := d.doc.anchors[n.value]
|
||||
if ok && an.kind != mappingNode {
|
||||
fail(wantMap)
|
||||
}
|
||||
d.unmarshal(n, out)
|
||||
case sequenceNode:
|
||||
// Step backwards as earlier nodes take precedence.
|
||||
for i := len(n.children) - 1; i >= 0; i-- {
|
||||
ni := n.children[i]
|
||||
if ni.kind == aliasNode {
|
||||
an, ok := d.doc.anchors[ni.value]
|
||||
if ok && an.kind != mappingNode {
|
||||
fail(wantMap)
|
||||
}
|
||||
} else if ni.kind != mappingNode {
|
||||
fail(wantMap)
|
||||
}
|
||||
d.unmarshal(ni, out)
|
||||
}
|
||||
default:
|
||||
fail(wantMap)
|
||||
}
|
||||
}
|
||||
|
||||
func isMerge(n *node) bool {
|
||||
return n.kind == scalarNode && n.value == "<<" && (n.implicit == true || n.tag == yaml_MERGE_TAG)
|
||||
}
|
@@ -1,10 +1,12 @@
|
||||
package goyaml_test
|
||||
package yaml_test
|
||||
|
||||
import (
|
||||
. "launchpad.net/gocheck"
|
||||
"github.com/coreos/coreos-cloudinit/third_party/launchpad.net/goyaml"
|
||||
"github.com/coreos/yaml"
|
||||
. "gopkg.in/check.v1"
|
||||
"math"
|
||||
"reflect"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
var unmarshalIntTest = 123
|
||||
@@ -315,7 +317,10 @@ var unmarshalTests = []struct {
|
||||
map[string]*string{"foo": new(string)},
|
||||
}, {
|
||||
"foo: null",
|
||||
map[string]string{},
|
||||
map[string]string{"foo": ""},
|
||||
}, {
|
||||
"foo: null",
|
||||
map[string]interface{}{"foo": nil},
|
||||
},
|
||||
|
||||
// Ignored field
|
||||
@@ -350,6 +355,50 @@ var unmarshalTests = []struct {
|
||||
C inlineB `yaml:",inline"`
|
||||
}{1, inlineB{2, inlineC{3}}},
|
||||
},
|
||||
|
||||
// bug 1243827
|
||||
{
|
||||
"a: -b_c",
|
||||
map[string]interface{}{"a": "-b_c"},
|
||||
},
|
||||
{
|
||||
"a: +b_c",
|
||||
map[string]interface{}{"a": "+b_c"},
|
||||
},
|
||||
{
|
||||
"a: 50cent_of_dollar",
|
||||
map[string]interface{}{"a": "50cent_of_dollar"},
|
||||
},
|
||||
|
||||
// Duration
|
||||
{
|
||||
"a: 3s",
|
||||
map[string]time.Duration{"a": 3 * time.Second},
|
||||
},
|
||||
|
||||
// Issue #24.
|
||||
{
|
||||
"a: <foo>",
|
||||
map[string]string{"a": "<foo>"},
|
||||
},
|
||||
|
||||
// Base 60 floats are obsolete and unsupported.
|
||||
{
|
||||
"a: 1:1\n",
|
||||
map[string]string{"a": "1:1"},
|
||||
},
|
||||
|
||||
// Binary data.
|
||||
{
|
||||
"a: !!binary gIGC\n",
|
||||
map[string]string{"a": "\x80\x81\x82"},
|
||||
}, {
|
||||
"a: !!binary |\n " + strings.Repeat("kJCQ", 17) + "kJ\n CQ\n",
|
||||
map[string]string{"a": strings.Repeat("\x90", 54)},
|
||||
}, {
|
||||
"a: !!binary |\n " + strings.Repeat("A", 70) + "\n ==\n",
|
||||
map[string]string{"a": strings.Repeat("\x00", 52)},
|
||||
},
|
||||
}
|
||||
|
||||
type inlineB struct {
|
||||
@@ -377,7 +426,7 @@ func (s *S) TestUnmarshal(c *C) {
|
||||
pv := reflect.New(pt.Elem())
|
||||
value = pv.Interface()
|
||||
}
|
||||
err := goyaml.Unmarshal([]byte(item.data), value)
|
||||
err := yaml.Unmarshal([]byte(item.data), value)
|
||||
c.Assert(err, IsNil, Commentf("Item #%d", i))
|
||||
if t.Kind() == reflect.String {
|
||||
c.Assert(*value.(*string), Equals, item.value, Commentf("Item #%d", i))
|
||||
@@ -389,7 +438,7 @@ func (s *S) TestUnmarshal(c *C) {
|
||||
|
||||
func (s *S) TestUnmarshalNaN(c *C) {
|
||||
value := map[string]interface{}{}
|
||||
err := goyaml.Unmarshal([]byte("notanum: .NaN"), &value)
|
||||
err := yaml.Unmarshal([]byte("notanum: .NaN"), &value)
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(math.IsNaN(value["notanum"].(float64)), Equals, true)
|
||||
}
|
||||
@@ -397,18 +446,21 @@ func (s *S) TestUnmarshalNaN(c *C) {
|
||||
var unmarshalErrorTests = []struct {
|
||||
data, error string
|
||||
}{
|
||||
{"v: !!float 'error'", "YAML error: Can't decode !!str 'error' as a !!float"},
|
||||
{"v: !!float 'error'", "YAML error: cannot decode !!str `error` as a !!float"},
|
||||
{"v: [A,", "YAML error: line 1: did not find expected node content"},
|
||||
{"v:\n- [A,", "YAML error: line 2: did not find expected node content"},
|
||||
{"a: *b\n", "YAML error: Unknown anchor 'b' referenced"},
|
||||
{"a: &a\n b: *a\n", "YAML error: Anchor 'a' value contains itself"},
|
||||
{"value: -", "YAML error: block sequence entries are not allowed in this context"},
|
||||
{"a: !!binary ==", "YAML error: !!binary value contains invalid base64 data"},
|
||||
{"{[.]}", `YAML error: invalid map key: \[\]interface \{\}\{"\."\}`},
|
||||
{"{{.}}", `YAML error: invalid map key: map\[interface\ \{\}\]interface \{\}\{".":interface \{\}\(nil\)\}`},
|
||||
}
|
||||
|
||||
func (s *S) TestUnmarshalErrors(c *C) {
|
||||
for _, item := range unmarshalErrorTests {
|
||||
var value interface{}
|
||||
err := goyaml.Unmarshal([]byte(item.data), &value)
|
||||
err := yaml.Unmarshal([]byte(item.data), &value)
|
||||
c.Assert(err, ErrorMatches, item.error, Commentf("Partial unmarshal: %#v", value))
|
||||
}
|
||||
}
|
||||
@@ -421,6 +473,8 @@ var setterTests = []struct {
|
||||
{"_: [1,A]", "!!seq", []interface{}{1, "A"}},
|
||||
{"_: 10", "!!int", 10},
|
||||
{"_: null", "!!null", nil},
|
||||
{`_: BAR!`, "!!str", "BAR!"},
|
||||
{`_: "BAR!"`, "!!str", "BAR!"},
|
||||
{"_: !!foo 'BAR!'", "!!foo", "BAR!"},
|
||||
}
|
||||
|
||||
@@ -442,17 +496,31 @@ func (o *typeWithSetter) SetYAML(tag string, value interface{}) (ok bool) {
|
||||
return true
|
||||
}
|
||||
|
||||
type typeWithSetterField struct {
|
||||
type setterPointerType struct {
|
||||
Field *typeWithSetter "_"
|
||||
}
|
||||
|
||||
func (s *S) TestUnmarshalWithSetter(c *C) {
|
||||
type setterValueType struct {
|
||||
Field typeWithSetter "_"
|
||||
}
|
||||
|
||||
func (s *S) TestUnmarshalWithPointerSetter(c *C) {
|
||||
for _, item := range setterTests {
|
||||
obj := &typeWithSetterField{}
|
||||
err := goyaml.Unmarshal([]byte(item.data), obj)
|
||||
obj := &setterPointerType{}
|
||||
err := yaml.Unmarshal([]byte(item.data), obj)
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(obj.Field, NotNil,
|
||||
Commentf("Pointer not initialized (%#v)", item.value))
|
||||
c.Assert(obj.Field, NotNil, Commentf("Pointer not initialized (%#v)", item.value))
|
||||
c.Assert(obj.Field.tag, Equals, item.tag)
|
||||
c.Assert(obj.Field.value, DeepEquals, item.value)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *S) TestUnmarshalWithValueSetter(c *C) {
|
||||
for _, item := range setterTests {
|
||||
obj := &setterValueType{}
|
||||
err := yaml.Unmarshal([]byte(item.data), obj)
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(obj.Field, NotNil, Commentf("Pointer not initialized (%#v)", item.value))
|
||||
c.Assert(obj.Field.tag, Equals, item.tag)
|
||||
c.Assert(obj.Field.value, DeepEquals, item.value)
|
||||
}
|
||||
@@ -460,7 +528,7 @@ func (s *S) TestUnmarshalWithSetter(c *C) {
|
||||
|
||||
func (s *S) TestUnmarshalWholeDocumentWithSetter(c *C) {
|
||||
obj := &typeWithSetter{}
|
||||
err := goyaml.Unmarshal([]byte(setterTests[0].data), obj)
|
||||
err := yaml.Unmarshal([]byte(setterTests[0].data), obj)
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(obj.tag, Equals, setterTests[0].tag)
|
||||
value, ok := obj.value.(map[interface{}]interface{})
|
||||
@@ -477,8 +545,8 @@ func (s *S) TestUnmarshalWithFalseSetterIgnoresValue(c *C) {
|
||||
}()
|
||||
|
||||
m := map[string]*typeWithSetter{}
|
||||
data := "{abc: 1, def: 2, ghi: 3, jkl: 4}"
|
||||
err := goyaml.Unmarshal([]byte(data), m)
|
||||
data := `{abc: 1, def: 2, ghi: 3, jkl: 4}`
|
||||
err := yaml.Unmarshal([]byte(data), m)
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(m["abc"], NotNil)
|
||||
c.Assert(m["def"], IsNil)
|
||||
@@ -489,6 +557,139 @@ func (s *S) TestUnmarshalWithFalseSetterIgnoresValue(c *C) {
|
||||
c.Assert(m["ghi"].value, Equals, 3)
|
||||
}
|
||||
|
||||
func (s *S) TestUnmarshalWithTransform(c *C) {
|
||||
data := `{a_b: 1, c-d: 2, e-f_g: 3, h_i-j: 4}`
|
||||
expect := map[string]int{
|
||||
"a_b": 1,
|
||||
"c_d": 2,
|
||||
"e_f_g": 3,
|
||||
"h_i_j": 4,
|
||||
}
|
||||
m := map[string]int{}
|
||||
yaml.UnmarshalMappingKeyTransform = func(i string) string {
|
||||
return strings.Replace(i, "-", "_", -1)
|
||||
}
|
||||
err := yaml.Unmarshal([]byte(data), m)
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(m, DeepEquals, expect)
|
||||
}
|
||||
|
||||
// From http://yaml.org/type/merge.html
|
||||
var mergeTests = `
|
||||
anchors:
|
||||
- &CENTER { "x": 1, "y": 2 }
|
||||
- &LEFT { "x": 0, "y": 2 }
|
||||
- &BIG { "r": 10 }
|
||||
- &SMALL { "r": 1 }
|
||||
|
||||
# All the following maps are equal:
|
||||
|
||||
plain:
|
||||
# Explicit keys
|
||||
"x": 1
|
||||
"y": 2
|
||||
"r": 10
|
||||
label: center/big
|
||||
|
||||
mergeOne:
|
||||
# Merge one map
|
||||
<< : *CENTER
|
||||
"r": 10
|
||||
label: center/big
|
||||
|
||||
mergeMultiple:
|
||||
# Merge multiple maps
|
||||
<< : [ *CENTER, *BIG ]
|
||||
label: center/big
|
||||
|
||||
override:
|
||||
# Override
|
||||
<< : [ *BIG, *LEFT, *SMALL ]
|
||||
"x": 1
|
||||
label: center/big
|
||||
|
||||
shortTag:
|
||||
# Explicit short merge tag
|
||||
!!merge "<<" : [ *CENTER, *BIG ]
|
||||
label: center/big
|
||||
|
||||
longTag:
|
||||
# Explicit merge long tag
|
||||
!<tag:yaml.org,2002:merge> "<<" : [ *CENTER, *BIG ]
|
||||
label: center/big
|
||||
|
||||
inlineMap:
|
||||
# Inlined map
|
||||
<< : {"x": 1, "y": 2, "r": 10}
|
||||
label: center/big
|
||||
|
||||
inlineSequenceMap:
|
||||
# Inlined map in sequence
|
||||
<< : [ *CENTER, {"r": 10} ]
|
||||
label: center/big
|
||||
`
|
||||
|
||||
func (s *S) TestMerge(c *C) {
|
||||
var want = map[interface{}]interface{}{
|
||||
"x": 1,
|
||||
"y": 2,
|
||||
"r": 10,
|
||||
"label": "center/big",
|
||||
}
|
||||
|
||||
var m map[string]interface{}
|
||||
err := yaml.Unmarshal([]byte(mergeTests), &m)
|
||||
c.Assert(err, IsNil)
|
||||
for name, test := range m {
|
||||
if name == "anchors" {
|
||||
continue
|
||||
}
|
||||
c.Assert(test, DeepEquals, want, Commentf("test %q failed", name))
|
||||
}
|
||||
}
|
||||
|
||||
func (s *S) TestMergeStruct(c *C) {
|
||||
type Data struct {
|
||||
X, Y, R int
|
||||
Label string
|
||||
}
|
||||
want := Data{1, 2, 10, "center/big"}
|
||||
|
||||
var m map[string]Data
|
||||
err := yaml.Unmarshal([]byte(mergeTests), &m)
|
||||
c.Assert(err, IsNil)
|
||||
for name, test := range m {
|
||||
if name == "anchors" {
|
||||
continue
|
||||
}
|
||||
c.Assert(test, Equals, want, Commentf("test %q failed", name))
|
||||
}
|
||||
}
|
||||
|
||||
var unmarshalNullTests = []func() interface{}{
|
||||
func() interface{} { var v interface{}; v = "v"; return &v },
|
||||
func() interface{} { var s = "s"; return &s },
|
||||
func() interface{} { var s = "s"; sptr := &s; return &sptr },
|
||||
func() interface{} { var i = 1; return &i },
|
||||
func() interface{} { var i = 1; iptr := &i; return &iptr },
|
||||
func() interface{} { m := map[string]int{"s": 1}; return &m },
|
||||
func() interface{} { m := map[string]int{"s": 1}; return m },
|
||||
}
|
||||
|
||||
func (s *S) TestUnmarshalNull(c *C) {
|
||||
for _, test := range unmarshalNullTests {
|
||||
item := test()
|
||||
zero := reflect.Zero(reflect.TypeOf(item).Elem()).Interface()
|
||||
err := yaml.Unmarshal([]byte("null"), item)
|
||||
c.Assert(err, IsNil)
|
||||
if reflect.TypeOf(item).Kind() == reflect.Map {
|
||||
c.Assert(reflect.ValueOf(item).Interface(), DeepEquals, reflect.MakeMap(reflect.TypeOf(item)).Interface())
|
||||
} else {
|
||||
c.Assert(reflect.ValueOf(item).Elem().Interface(), DeepEquals, zero)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//var data []byte
|
||||
//func init() {
|
||||
// var err error
|
||||
@@ -502,7 +703,7 @@ func (s *S) TestUnmarshalWithFalseSetterIgnoresValue(c *C) {
|
||||
// var err error
|
||||
// for i := 0; i < c.N; i++ {
|
||||
// var v map[string]interface{}
|
||||
// err = goyaml.Unmarshal(data, &v)
|
||||
// err = yaml.Unmarshal(data, &v)
|
||||
// }
|
||||
// if err != nil {
|
||||
// panic(err)
|
||||
@@ -511,9 +712,9 @@ func (s *S) TestUnmarshalWithFalseSetterIgnoresValue(c *C) {
|
||||
//
|
||||
//func (s *S) BenchmarkMarshal(c *C) {
|
||||
// var v map[string]interface{}
|
||||
// goyaml.Unmarshal(data, &v)
|
||||
// yaml.Unmarshal(data, &v)
|
||||
// c.ResetTimer()
|
||||
// for i := 0; i < c.N; i++ {
|
||||
// goyaml.Marshal(&v)
|
||||
// yaml.Marshal(&v)
|
||||
// }
|
||||
//}
|
@@ -1,4 +1,4 @@
|
||||
package goyaml
|
||||
package yaml
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@@ -973,8 +973,8 @@ func yaml_emitter_analyze_tag(emitter *yaml_emitter_t, tag []byte) bool {
|
||||
if bytes.HasPrefix(tag, tag_directive.prefix) {
|
||||
emitter.tag_data.handle = tag_directive.handle
|
||||
emitter.tag_data.suffix = tag[len(tag_directive.prefix):]
|
||||
return true
|
||||
}
|
||||
return true
|
||||
}
|
||||
emitter.tag_data.suffix = tag
|
||||
return true
|
||||
@@ -1279,6 +1279,9 @@ func yaml_emitter_write_tag_content(emitter *yaml_emitter_t, value []byte, need_
|
||||
for k := 0; k < w; k++ {
|
||||
octet := value[i]
|
||||
i++
|
||||
if !put(emitter, '%') {
|
||||
return false
|
||||
}
|
||||
|
||||
c := octet >> 4
|
||||
if c < 10 {
|
@@ -1,9 +1,12 @@
|
||||
package goyaml
|
||||
package yaml
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
type encoder struct {
|
||||
@@ -49,14 +52,19 @@ func (e *encoder) must(ok bool) {
|
||||
if msg == "" {
|
||||
msg = "Unknown problem generating YAML content"
|
||||
}
|
||||
panic(msg)
|
||||
fail(msg)
|
||||
}
|
||||
}
|
||||
|
||||
func (e *encoder) marshal(tag string, in reflect.Value) {
|
||||
if !in.IsValid() {
|
||||
e.nilv()
|
||||
return
|
||||
}
|
||||
var value interface{}
|
||||
if getter, ok := in.Interface().(Getter); ok {
|
||||
tag, value = getter.GetYAML()
|
||||
tag = longTag(tag)
|
||||
if value == nil {
|
||||
e.nilv()
|
||||
return
|
||||
@@ -85,7 +93,11 @@ func (e *encoder) marshal(tag string, in reflect.Value) {
|
||||
case reflect.String:
|
||||
e.stringv(tag, in)
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
e.intv(tag, in)
|
||||
if in.Type() == durationType {
|
||||
e.stringv(tag, reflect.ValueOf(in.Interface().(time.Duration).String()))
|
||||
} else {
|
||||
e.intv(tag, in)
|
||||
}
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||
e.uintv(tag, in)
|
||||
case reflect.Float32, reflect.Float64:
|
||||
@@ -93,7 +105,7 @@ func (e *encoder) marshal(tag string, in reflect.Value) {
|
||||
case reflect.Bool:
|
||||
e.boolv(tag, in)
|
||||
default:
|
||||
panic("Can't marshal type yet: " + in.Type().String())
|
||||
panic("Can't marshal type: " + in.Type().String())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -162,11 +174,46 @@ func (e *encoder) slicev(tag string, in reflect.Value) {
|
||||
e.emit()
|
||||
}
|
||||
|
||||
// isBase60 returns whether s is in base 60 notation as defined in YAML 1.1.
|
||||
//
|
||||
// The base 60 float notation in YAML 1.1 is a terrible idea and is unsupported
|
||||
// in YAML 1.2 and by this package, but these should be marshalled quoted for
|
||||
// the time being for compatibility with other parsers.
|
||||
func isBase60Float(s string) (result bool) {
|
||||
// Fast path.
|
||||
if s == "" {
|
||||
return false
|
||||
}
|
||||
c := s[0]
|
||||
if !(c == '+' || c == '-' || c >= '0' && c <= '9') || strings.IndexByte(s, ':') < 0 {
|
||||
return false
|
||||
}
|
||||
// Do the full match.
|
||||
return base60float.MatchString(s)
|
||||
}
|
||||
|
||||
// From http://yaml.org/type/float.html, except the regular expression there
|
||||
// is bogus. In practice parsers do not enforce the "\.[0-9_]*" suffix.
|
||||
var base60float = regexp.MustCompile(`^[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+(?:\.[0-9_]*)?$`)
|
||||
|
||||
func (e *encoder) stringv(tag string, in reflect.Value) {
|
||||
var style yaml_scalar_style_t
|
||||
s := in.String()
|
||||
if rtag, _ := resolve("", s); rtag != "!!str" {
|
||||
rtag, rs := resolve("", s)
|
||||
if rtag == yaml_BINARY_TAG {
|
||||
if tag == "" || tag == yaml_STR_TAG {
|
||||
tag = rtag
|
||||
s = rs.(string)
|
||||
} else if tag == yaml_BINARY_TAG {
|
||||
fail("explicitly tagged !!binary data must be base64-encoded")
|
||||
} else {
|
||||
fail("cannot marshal invalid UTF-8 data as " + shortTag(tag))
|
||||
}
|
||||
}
|
||||
if tag == "" && (rtag != yaml_STR_TAG || isBase60Float(s)) {
|
||||
style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
|
||||
} else if strings.Contains(s, "\n") {
|
||||
style = yaml_LITERAL_SCALAR_STYLE
|
||||
} else {
|
||||
style = yaml_PLAIN_SCALAR_STYLE
|
||||
}
|
||||
@@ -213,9 +260,6 @@ func (e *encoder) nilv() {
|
||||
|
||||
func (e *encoder) emitScalar(value, anchor, tag string, style yaml_scalar_style_t) {
|
||||
implicit := tag == ""
|
||||
if !implicit {
|
||||
style = yaml_PLAIN_SCALAR_STYLE
|
||||
}
|
||||
e.must(yaml_scalar_event_initialize(&e.event, []byte(anchor), []byte(tag), []byte(value), implicit, implicit, style))
|
||||
e.emit()
|
||||
}
|
@@ -1,12 +1,14 @@
|
||||
package goyaml_test
|
||||
package yaml_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
. "launchpad.net/gocheck"
|
||||
"github.com/coreos/coreos-cloudinit/third_party/launchpad.net/goyaml"
|
||||
"math"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/coreos/yaml"
|
||||
. "gopkg.in/check.v1"
|
||||
)
|
||||
|
||||
var marshalIntTest = 123
|
||||
@@ -16,6 +18,9 @@ var marshalTests = []struct {
|
||||
data string
|
||||
}{
|
||||
{
|
||||
nil,
|
||||
"null\n",
|
||||
}, {
|
||||
&struct{}{},
|
||||
"{}\n",
|
||||
}, {
|
||||
@@ -86,7 +91,7 @@ var marshalTests = []struct {
|
||||
"v:\n- A\n- B\n",
|
||||
}, {
|
||||
map[string][]string{"v": []string{"A", "B\nC"}},
|
||||
"v:\n- A\n- 'B\n\n C'\n",
|
||||
"v:\n- A\n- |-\n B\n C\n",
|
||||
}, {
|
||||
map[string][]interface{}{"v": []interface{}{"A", 1, map[string][]int{"B": []int{2, 3}}}},
|
||||
"v:\n- A\n- 1\n- B:\n - 2\n - 3\n",
|
||||
@@ -212,11 +217,51 @@ var marshalTests = []struct {
|
||||
}{1, inlineB{2, inlineC{3}}},
|
||||
"a: 1\nb: 2\nc: 3\n",
|
||||
},
|
||||
|
||||
// Duration
|
||||
{
|
||||
map[string]time.Duration{"a": 3 * time.Second},
|
||||
"a: 3s\n",
|
||||
},
|
||||
|
||||
// Issue #24: bug in map merging logic.
|
||||
{
|
||||
map[string]string{"a": "<foo>"},
|
||||
"a: <foo>\n",
|
||||
},
|
||||
|
||||
// Issue #34: marshal unsupported base 60 floats quoted for compatibility
|
||||
// with old YAML 1.1 parsers.
|
||||
{
|
||||
map[string]string{"a": "1:1"},
|
||||
"a: \"1:1\"\n",
|
||||
},
|
||||
|
||||
// Binary data.
|
||||
{
|
||||
map[string]string{"a": "\x00"},
|
||||
"a: \"\\0\"\n",
|
||||
}, {
|
||||
map[string]string{"a": "\x80\x81\x82"},
|
||||
"a: !!binary gIGC\n",
|
||||
}, {
|
||||
map[string]string{"a": strings.Repeat("\x90", 54)},
|
||||
"a: !!binary |\n " + strings.Repeat("kJCQ", 17) + "kJ\n CQ\n",
|
||||
}, {
|
||||
map[string]interface{}{"a": typeWithGetter{"!!str", "\x80\x81\x82"}},
|
||||
"a: !!binary gIGC\n",
|
||||
},
|
||||
|
||||
// Escaping of tags.
|
||||
{
|
||||
map[string]interface{}{"a": typeWithGetter{"foo!bar", 1}},
|
||||
"a: !<foo%21bar> 1\n",
|
||||
},
|
||||
}
|
||||
|
||||
func (s *S) TestMarshal(c *C) {
|
||||
for _, item := range marshalTests {
|
||||
data, err := goyaml.Marshal(item.value)
|
||||
data, err := yaml.Marshal(item.value)
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(string(data), Equals, item.data)
|
||||
}
|
||||
@@ -225,20 +270,29 @@ func (s *S) TestMarshal(c *C) {
|
||||
var marshalErrorTests = []struct {
|
||||
value interface{}
|
||||
error string
|
||||
}{
|
||||
{
|
||||
&struct {
|
||||
B int
|
||||
inlineB ",inline"
|
||||
}{1, inlineB{2, inlineC{3}}},
|
||||
`Duplicated key 'b' in struct struct \{ B int; .*`,
|
||||
},
|
||||
}
|
||||
panic string
|
||||
}{{
|
||||
value: &struct {
|
||||
B int
|
||||
inlineB ",inline"
|
||||
}{1, inlineB{2, inlineC{3}}},
|
||||
panic: `Duplicated key 'b' in struct struct \{ B int; .*`,
|
||||
}, {
|
||||
value: typeWithGetter{"!!binary", "\x80"},
|
||||
error: "YAML error: explicitly tagged !!binary data must be base64-encoded",
|
||||
}, {
|
||||
value: typeWithGetter{"!!float", "\x80"},
|
||||
error: `YAML error: cannot marshal invalid UTF-8 data as !!float`,
|
||||
}}
|
||||
|
||||
func (s *S) TestMarshalErrors(c *C) {
|
||||
for _, item := range marshalErrorTests {
|
||||
_, err := goyaml.Marshal(item.value)
|
||||
c.Assert(err, ErrorMatches, item.error)
|
||||
if item.panic != "" {
|
||||
c.Assert(func() { yaml.Marshal(item.value) }, PanicMatches, item.panic)
|
||||
} else {
|
||||
_, err := yaml.Marshal(item.value)
|
||||
c.Assert(err, ErrorMatches, item.error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -269,12 +323,12 @@ func (s *S) TestMarshalTypeCache(c *C) {
|
||||
var err error
|
||||
func() {
|
||||
type T struct{ A int }
|
||||
data, err = goyaml.Marshal(&T{})
|
||||
data, err = yaml.Marshal(&T{})
|
||||
c.Assert(err, IsNil)
|
||||
}()
|
||||
func() {
|
||||
type T struct{ B int }
|
||||
data, err = goyaml.Marshal(&T{})
|
||||
data, err = yaml.Marshal(&T{})
|
||||
c.Assert(err, IsNil)
|
||||
}()
|
||||
c.Assert(string(data), Equals, "b: 0\n")
|
||||
@@ -298,7 +352,7 @@ func (s *S) TestMashalWithGetter(c *C) {
|
||||
obj := &typeWithGetterField{}
|
||||
obj.Field.tag = item.tag
|
||||
obj.Field.value = item.value
|
||||
data, err := goyaml.Marshal(obj)
|
||||
data, err := yaml.Marshal(obj)
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(string(data), Equals, string(item.data))
|
||||
}
|
||||
@@ -308,7 +362,7 @@ func (s *S) TestUnmarshalWholeDocumentWithGetter(c *C) {
|
||||
obj := &typeWithGetter{}
|
||||
obj.tag = ""
|
||||
obj.value = map[string]string{"hello": "world!"}
|
||||
data, err := goyaml.Marshal(obj)
|
||||
data, err := yaml.Marshal(obj)
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(string(data), Equals, "hello: world!\n")
|
||||
}
|
||||
@@ -356,7 +410,7 @@ func (s *S) TestSortedOutput(c *C) {
|
||||
for _, k := range order {
|
||||
m[k] = 1
|
||||
}
|
||||
data, err := goyaml.Marshal(m)
|
||||
data, err := yaml.Marshal(m)
|
||||
c.Assert(err, IsNil)
|
||||
out := "\n" + string(data)
|
||||
last := 0
|
@@ -1,4 +1,4 @@
|
||||
package goyaml
|
||||
package yaml
|
||||
|
||||
import (
|
||||
"bytes"
|
@@ -1,4 +1,4 @@
|
||||
package goyaml
|
||||
package yaml
|
||||
|
||||
import (
|
||||
"io"
|
190
Godeps/_workspace/src/github.com/coreos/yaml/resolve.go
generated
vendored
Normal file
190
Godeps/_workspace/src/github.com/coreos/yaml/resolve.go
generated
vendored
Normal file
@@ -0,0 +1,190 @@
|
||||
package yaml
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"math"
|
||||
"strconv"
|
||||
"strings"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
// TODO: merge, timestamps, base 60 floats, omap.
|
||||
|
||||
type resolveMapItem struct {
|
||||
value interface{}
|
||||
tag string
|
||||
}
|
||||
|
||||
var resolveTable = make([]byte, 256)
|
||||
var resolveMap = make(map[string]resolveMapItem)
|
||||
|
||||
func init() {
|
||||
t := resolveTable
|
||||
t[int('+')] = 'S' // Sign
|
||||
t[int('-')] = 'S'
|
||||
for _, c := range "0123456789" {
|
||||
t[int(c)] = 'D' // Digit
|
||||
}
|
||||
for _, c := range "yYnNtTfFoO~" {
|
||||
t[int(c)] = 'M' // In map
|
||||
}
|
||||
t[int('.')] = '.' // Float (potentially in map)
|
||||
|
||||
var resolveMapList = []struct {
|
||||
v interface{}
|
||||
tag string
|
||||
l []string
|
||||
}{
|
||||
{true, yaml_BOOL_TAG, []string{"y", "Y", "yes", "Yes", "YES"}},
|
||||
{true, yaml_BOOL_TAG, []string{"true", "True", "TRUE"}},
|
||||
{true, yaml_BOOL_TAG, []string{"on", "On", "ON"}},
|
||||
{false, yaml_BOOL_TAG, []string{"n", "N", "no", "No", "NO"}},
|
||||
{false, yaml_BOOL_TAG, []string{"false", "False", "FALSE"}},
|
||||
{false, yaml_BOOL_TAG, []string{"off", "Off", "OFF"}},
|
||||
{nil, yaml_NULL_TAG, []string{"", "~", "null", "Null", "NULL"}},
|
||||
{math.NaN(), yaml_FLOAT_TAG, []string{".nan", ".NaN", ".NAN"}},
|
||||
{math.Inf(+1), yaml_FLOAT_TAG, []string{".inf", ".Inf", ".INF"}},
|
||||
{math.Inf(+1), yaml_FLOAT_TAG, []string{"+.inf", "+.Inf", "+.INF"}},
|
||||
{math.Inf(-1), yaml_FLOAT_TAG, []string{"-.inf", "-.Inf", "-.INF"}},
|
||||
{"<<", yaml_MERGE_TAG, []string{"<<"}},
|
||||
}
|
||||
|
||||
m := resolveMap
|
||||
for _, item := range resolveMapList {
|
||||
for _, s := range item.l {
|
||||
m[s] = resolveMapItem{item.v, item.tag}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const longTagPrefix = "tag:yaml.org,2002:"
|
||||
|
||||
func shortTag(tag string) string {
|
||||
// TODO This can easily be made faster and produce less garbage.
|
||||
if strings.HasPrefix(tag, longTagPrefix) {
|
||||
return "!!" + tag[len(longTagPrefix):]
|
||||
}
|
||||
return tag
|
||||
}
|
||||
|
||||
func longTag(tag string) string {
|
||||
if strings.HasPrefix(tag, "!!") {
|
||||
return longTagPrefix + tag[2:]
|
||||
}
|
||||
return tag
|
||||
}
|
||||
|
||||
func resolvableTag(tag string) bool {
|
||||
switch tag {
|
||||
case "", yaml_STR_TAG, yaml_BOOL_TAG, yaml_INT_TAG, yaml_FLOAT_TAG, yaml_NULL_TAG:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func resolve(tag string, in string) (rtag string, out interface{}) {
|
||||
if !resolvableTag(tag) {
|
||||
return tag, in
|
||||
}
|
||||
|
||||
defer func() {
|
||||
switch tag {
|
||||
case "", rtag, yaml_STR_TAG, yaml_BINARY_TAG:
|
||||
return
|
||||
}
|
||||
fail(fmt.Sprintf("cannot decode %s `%s` as a %s", shortTag(rtag), in, shortTag(tag)))
|
||||
}()
|
||||
|
||||
// Any data is accepted as a !!str or !!binary.
|
||||
// Otherwise, the prefix is enough of a hint about what it might be.
|
||||
hint := byte('N')
|
||||
if in != "" {
|
||||
hint = resolveTable[in[0]]
|
||||
}
|
||||
if hint != 0 && tag != yaml_STR_TAG && tag != yaml_BINARY_TAG {
|
||||
// Handle things we can lookup in a map.
|
||||
if item, ok := resolveMap[in]; ok {
|
||||
return item.tag, item.value
|
||||
}
|
||||
|
||||
// Base 60 floats are a bad idea, were dropped in YAML 1.2, and
|
||||
// are purposefully unsupported here. They're still quoted on
|
||||
// the way out for compatibility with other parser, though.
|
||||
|
||||
switch hint {
|
||||
case 'M':
|
||||
// We've already checked the map above.
|
||||
|
||||
case '.':
|
||||
// Not in the map, so maybe a normal float.
|
||||
floatv, err := strconv.ParseFloat(in, 64)
|
||||
if err == nil {
|
||||
return yaml_FLOAT_TAG, floatv
|
||||
}
|
||||
|
||||
case 'D', 'S':
|
||||
// Int, float, or timestamp.
|
||||
plain := strings.Replace(in, "_", "", -1)
|
||||
intv, err := strconv.ParseInt(plain, 0, 64)
|
||||
if err == nil {
|
||||
if intv == int64(int(intv)) {
|
||||
return yaml_INT_TAG, int(intv)
|
||||
} else {
|
||||
return yaml_INT_TAG, intv
|
||||
}
|
||||
}
|
||||
floatv, err := strconv.ParseFloat(plain, 64)
|
||||
if err == nil {
|
||||
return yaml_FLOAT_TAG, floatv
|
||||
}
|
||||
if strings.HasPrefix(plain, "0b") {
|
||||
intv, err := strconv.ParseInt(plain[2:], 2, 64)
|
||||
if err == nil {
|
||||
return yaml_INT_TAG, int(intv)
|
||||
}
|
||||
} else if strings.HasPrefix(plain, "-0b") {
|
||||
intv, err := strconv.ParseInt(plain[3:], 2, 64)
|
||||
if err == nil {
|
||||
return yaml_INT_TAG, -int(intv)
|
||||
}
|
||||
}
|
||||
// XXX Handle timestamps here.
|
||||
|
||||
default:
|
||||
panic("resolveTable item not yet handled: " + string(rune(hint)) + " (with " + in + ")")
|
||||
}
|
||||
}
|
||||
if tag == yaml_BINARY_TAG {
|
||||
return yaml_BINARY_TAG, in
|
||||
}
|
||||
if utf8.ValidString(in) {
|
||||
return yaml_STR_TAG, in
|
||||
}
|
||||
return yaml_BINARY_TAG, encodeBase64(in)
|
||||
}
|
||||
|
||||
// encodeBase64 encodes s as base64 that is broken up into multiple lines
|
||||
// as appropriate for the resulting length.
|
||||
func encodeBase64(s string) string {
|
||||
const lineLen = 70
|
||||
encLen := base64.StdEncoding.EncodedLen(len(s))
|
||||
lines := encLen/lineLen + 1
|
||||
buf := make([]byte, encLen*2+lines)
|
||||
in := buf[0:encLen]
|
||||
out := buf[encLen:]
|
||||
base64.StdEncoding.Encode(in, []byte(s))
|
||||
k := 0
|
||||
for i := 0; i < len(in); i += lineLen {
|
||||
j := i + lineLen
|
||||
if j > len(in) {
|
||||
j = len(in)
|
||||
}
|
||||
k += copy(out[k:], in[i:j])
|
||||
if lines > 1 {
|
||||
out[k] = '\n'
|
||||
k++
|
||||
}
|
||||
}
|
||||
return string(out[:k])
|
||||
}
|
@@ -1,4 +1,4 @@
|
||||
package goyaml
|
||||
package yaml
|
||||
|
||||
import (
|
||||
"bytes"
|
@@ -1,4 +1,4 @@
|
||||
package goyaml
|
||||
package yaml
|
||||
|
||||
import (
|
||||
"reflect"
|
@@ -1,7 +1,7 @@
|
||||
package goyaml_test
|
||||
package yaml_test
|
||||
|
||||
import (
|
||||
. "launchpad.net/gocheck"
|
||||
. "gopkg.in/check.v1"
|
||||
"testing"
|
||||
)
|
||||
|
@@ -1,4 +1,4 @@
|
||||
package goyaml
|
||||
package yaml
|
||||
|
||||
// Set the writer error and return false.
|
||||
func yaml_emitter_set_writer_error(emitter *yaml_emitter_t, problem string) bool {
|
@@ -1,59 +1,60 @@
|
||||
// Package goyaml implements YAML support for the Go language.
|
||||
package goyaml
|
||||
// Package yaml implements YAML support for the Go language.
|
||||
//
|
||||
// Source code and other details for the project are available at GitHub:
|
||||
//
|
||||
// https://github.com/go-yaml/yaml
|
||||
//
|
||||
package yaml
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
type yamlError string
|
||||
|
||||
func fail(msg string) {
|
||||
panic(yamlError(msg))
|
||||
}
|
||||
|
||||
func handleErr(err *error) {
|
||||
if r := recover(); r != nil {
|
||||
if _, ok := r.(runtime.Error); ok {
|
||||
panic(r)
|
||||
} else if _, ok := r.(*reflect.ValueError); ok {
|
||||
panic(r)
|
||||
} else if _, ok := r.(externalPanic); ok {
|
||||
panic(r)
|
||||
} else if s, ok := r.(string); ok {
|
||||
*err = errors.New("YAML error: " + s)
|
||||
} else if e, ok := r.(error); ok {
|
||||
*err = e
|
||||
if e, ok := r.(yamlError); ok {
|
||||
*err = errors.New("YAML error: " + string(e))
|
||||
} else {
|
||||
panic(r)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Objects implementing the goyaml.Setter interface will receive the YAML
|
||||
// tag and value via the SetYAML method during unmarshaling, rather than
|
||||
// being implicitly assigned by the goyaml machinery. If setting the value
|
||||
// works, the method should return true. If it returns false, the given
|
||||
// value will be omitted from maps and slices.
|
||||
// The Setter interface may be implemented by types to do their own custom
|
||||
// unmarshalling of YAML values, rather than being implicitly assigned by
|
||||
// the yaml package machinery. If setting the value works, the method should
|
||||
// return true. If it returns false, the value is considered unsupported
|
||||
// and is omitted from maps and slices.
|
||||
type Setter interface {
|
||||
SetYAML(tag string, value interface{}) bool
|
||||
}
|
||||
|
||||
// Objects implementing the goyaml.Getter interface will get the GetYAML()
|
||||
// method called when goyaml is requested to marshal the given value, and
|
||||
// the result of this method will be marshaled in place of the actual object.
|
||||
// The Getter interface is implemented by types to do their own custom
|
||||
// marshalling into a YAML tag and value.
|
||||
type Getter interface {
|
||||
GetYAML() (tag string, value interface{})
|
||||
}
|
||||
|
||||
// Unmarshal decodes the first document found within the in byte slice
|
||||
// and assigns decoded values into the object pointed by out.
|
||||
// and assigns decoded values into the out value.
|
||||
//
|
||||
// Maps, pointers to structs and ints, etc, may all be used as out values.
|
||||
// If an internal pointer within a struct is not initialized, goyaml
|
||||
// will initialize it if necessary for unmarshalling the provided data,
|
||||
// but the struct provided as out must not be a nil pointer.
|
||||
// Maps and pointers (to a struct, string, int, etc) are accepted as out
|
||||
// values. If an internal pointer within a struct is not initialized,
|
||||
// the yaml package will initialize it if necessary for unmarshalling
|
||||
// the provided data. The out parameter must not be nil.
|
||||
//
|
||||
// The type of the decoded values and the type of out will be considered,
|
||||
// and Unmarshal() will do the best possible job to unmarshal values
|
||||
// and Unmarshal will do the best possible job to unmarshal values
|
||||
// appropriately. It is NOT considered an error, though, to skip values
|
||||
// because they are not available in the decoded YAML, or if they are not
|
||||
// compatible with the out value. To ensure something was properly
|
||||
@@ -61,11 +62,11 @@ type Getter interface {
|
||||
// field (usually the zero value).
|
||||
//
|
||||
// Struct fields are only unmarshalled if they are exported (have an
|
||||
// upper case first letter), and will be unmarshalled using the field
|
||||
// name lowercased by default. When custom field names are desired, the
|
||||
// tag value may be used to tweak the name. Everything before the first
|
||||
// comma in the field tag will be used as the name. The values following
|
||||
// the comma are used to tweak the marshalling process (see Marshal).
|
||||
// upper case first letter), and are unmarshalled using the field name
|
||||
// lowercased as the default key. Custom keys may be defined via the
|
||||
// "yaml" name in the field tag: the content preceding the first comma
|
||||
// is used as the key, and the following comma-separated options are
|
||||
// used to tweak the marshalling process (see Marshal).
|
||||
// Conflicting names result in a runtime error.
|
||||
//
|
||||
// For example:
|
||||
@@ -74,8 +75,8 @@ type Getter interface {
|
||||
// F int `yaml:"a,omitempty"`
|
||||
// B int
|
||||
// }
|
||||
// var T t
|
||||
// goyaml.Unmarshal([]byte("a: 1\nb: 2"), &t)
|
||||
// var t T
|
||||
// yaml.Unmarshal([]byte("a: 1\nb: 2"), &t)
|
||||
//
|
||||
// See the documentation of Marshal for the format of tags and a list of
|
||||
// supported tag options.
|
||||
@@ -83,25 +84,31 @@ type Getter interface {
|
||||
func Unmarshal(in []byte, out interface{}) (err error) {
|
||||
defer handleErr(&err)
|
||||
d := newDecoder()
|
||||
p := newParser(in)
|
||||
p := newParser(in, UnmarshalMappingKeyTransform)
|
||||
defer p.destroy()
|
||||
node := p.parse()
|
||||
if node != nil {
|
||||
d.unmarshal(node, reflect.ValueOf(out))
|
||||
v := reflect.ValueOf(out)
|
||||
if v.Kind() == reflect.Ptr && !v.IsNil() {
|
||||
v = v.Elem()
|
||||
}
|
||||
d.unmarshal(node, v)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Marshal serializes the value provided into a YAML document. The structure
|
||||
// of the generated document will reflect the structure of the value itself.
|
||||
// Maps, pointers to structs and ints, etc, may all be used as the in value.
|
||||
// Maps and pointers (to struct, string, int, etc) are accepted as the in value.
|
||||
//
|
||||
// In the case of struct values, only exported fields will be serialized.
|
||||
// The lowercased field name is used as the key for each exported field,
|
||||
// but this behavior may be changed using the respective field tag.
|
||||
// The tag may also contain flags to tweak the marshalling behavior for
|
||||
// the field. Conflicting names result in a runtime error. The tag format
|
||||
// accepted is:
|
||||
// Struct fields are only unmarshalled if they are exported (have an upper case
|
||||
// first letter), and are unmarshalled using the field name lowercased as the
|
||||
// default key. Custom keys may be defined via the "yaml" name in the field
|
||||
// tag: the content preceding the first comma is used as the key, and the
|
||||
// following comma-separated options are used to tweak the marshalling process.
|
||||
// Conflicting names result in a runtime error.
|
||||
//
|
||||
// The field tag format accepted is:
|
||||
//
|
||||
// `(...) yaml:"[<key>][,<flag1>[,<flag2>]]" (...)`
|
||||
//
|
||||
@@ -126,8 +133,8 @@ func Unmarshal(in []byte, out interface{}) (err error) {
|
||||
// F int "a,omitempty"
|
||||
// B int
|
||||
// }
|
||||
// goyaml.Marshal(&T{B: 2}) // Returns "b: 2\n"
|
||||
// goyaml.Marshal(&T{F: 1}} // Returns "a: 1\nb: 0\n"
|
||||
// yaml.Marshal(&T{B: 2}) // Returns "b: 2\n"
|
||||
// yaml.Marshal(&T{F: 1}} // Returns "a: 1\nb: 0\n"
|
||||
//
|
||||
func Marshal(in interface{}) (out []byte, err error) {
|
||||
defer handleErr(&err)
|
||||
@@ -139,10 +146,21 @@ func Marshal(in interface{}) (out []byte, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
// UnmarshalMappingKeyTransform is a string transformation that is applied to
|
||||
// each mapping key in a YAML document before it is unmarshalled. By default,
|
||||
// UnmarshalMappingKeyTransform is an identity transform (no modification).
|
||||
var UnmarshalMappingKeyTransform transformString = identityTransform
|
||||
|
||||
type transformString func(in string) (out string)
|
||||
|
||||
func identityTransform(in string) (out string) {
|
||||
return in
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// Maintain a mapping of keys to structure field indexes
|
||||
|
||||
// The code in this section was copied from gobson.
|
||||
// The code in this section was copied from mgo/bson.
|
||||
|
||||
// structInfo holds details for the serialization of fields of
|
||||
// a given struct.
|
||||
@@ -168,12 +186,6 @@ type fieldInfo struct {
|
||||
var structMap = make(map[reflect.Type]*structInfo)
|
||||
var fieldMapMutex sync.RWMutex
|
||||
|
||||
type externalPanic string
|
||||
|
||||
func (e externalPanic) String() string {
|
||||
return string(e)
|
||||
}
|
||||
|
||||
func getStructInfo(st reflect.Type) (*structInfo, error) {
|
||||
fieldMapMutex.RLock()
|
||||
sinfo, found := structMap[st]
|
||||
@@ -214,8 +226,7 @@ func getStructInfo(st reflect.Type) (*structInfo, error) {
|
||||
case "inline":
|
||||
inline = true
|
||||
default:
|
||||
msg := fmt.Sprintf("Unsupported flag %q in tag %q of type %s", flag, tag, st)
|
||||
panic(externalPanic(msg))
|
||||
return nil, errors.New(fmt.Sprintf("Unsupported flag %q in tag %q of type %s", flag, tag, st))
|
||||
}
|
||||
}
|
||||
tag = fields[0]
|
||||
@@ -223,6 +234,7 @@ func getStructInfo(st reflect.Type) (*structInfo, error) {
|
||||
|
||||
if inline {
|
||||
switch field.Type.Kind() {
|
||||
// TODO: Implement support for inline maps.
|
||||
//case reflect.Map:
|
||||
// if inlineMap >= 0 {
|
||||
// return nil, errors.New("Multiple ,inline maps in struct " + st.String())
|
||||
@@ -250,8 +262,8 @@ func getStructInfo(st reflect.Type) (*structInfo, error) {
|
||||
fieldsList = append(fieldsList, finfo)
|
||||
}
|
||||
default:
|
||||
//panic("Option ,inline needs a struct value or map field")
|
||||
panic("Option ,inline needs a struct value field")
|
||||
//return nil, errors.New("Option ,inline needs a struct value or map field")
|
||||
return nil, errors.New("Option ,inline needs a struct value field")
|
||||
}
|
||||
continue
|
||||
}
|
@@ -1,4 +1,4 @@
|
||||
package goyaml
|
||||
package yaml
|
||||
|
||||
import (
|
||||
"io"
|
||||
@@ -294,6 +294,10 @@ const (
|
||||
yaml_SEQ_TAG = "tag:yaml.org,2002:seq" // The tag !!seq is used to denote sequences.
|
||||
yaml_MAP_TAG = "tag:yaml.org,2002:map" // The tag !!map is used to denote mapping.
|
||||
|
||||
// Not in original libyaml.
|
||||
yaml_BINARY_TAG = "tag:yaml.org,2002:binary"
|
||||
yaml_MERGE_TAG = "tag:yaml.org,2002:merge"
|
||||
|
||||
yaml_DEFAULT_SCALAR_TAG = yaml_STR_TAG // The default scalar tag is !!str.
|
||||
yaml_DEFAULT_SEQUENCE_TAG = yaml_SEQ_TAG // The default sequence tag is !!seq.
|
||||
yaml_DEFAULT_MAPPING_TAG = yaml_MAP_TAG // The default mapping tag is !!map.
|
@@ -1,4 +1,4 @@
|
||||
package goyaml
|
||||
package yaml
|
||||
|
||||
const (
|
||||
// The size of the input raw buffer.
|
@@ -2,7 +2,7 @@ package introspect
|
||||
|
||||
import (
|
||||
"encoding/xml"
|
||||
"github.com/coreos/coreos-cloudinit/third_party/github.com/guelfey/go.dbus"
|
||||
"github.com/coreos/coreos-cloudinit/Godeps/_workspace/src/github.com/guelfey/go.dbus"
|
||||
"strings"
|
||||
)
|
||||
|
@@ -2,7 +2,7 @@ package introspect
|
||||
|
||||
import (
|
||||
"encoding/xml"
|
||||
"github.com/coreos/coreos-cloudinit/third_party/github.com/guelfey/go.dbus"
|
||||
"github.com/coreos/coreos-cloudinit/Godeps/_workspace/src/github.com/guelfey/go.dbus"
|
||||
"reflect"
|
||||
)
|
||||
|
@@ -3,8 +3,8 @@
|
||||
package prop
|
||||
|
||||
import (
|
||||
"github.com/coreos/coreos-cloudinit/third_party/github.com/guelfey/go.dbus"
|
||||
"github.com/coreos/coreos-cloudinit/third_party/github.com/guelfey/go.dbus/introspect"
|
||||
"github.com/coreos/coreos-cloudinit/Godeps/_workspace/src/github.com/guelfey/go.dbus"
|
||||
"github.com/coreos/coreos-cloudinit/Godeps/_workspace/src/github.com/guelfey/go.dbus/introspect"
|
||||
"sync"
|
||||
)
|
||||
|
502
Godeps/_workspace/src/github.com/sigma/vmw-guestinfo/COPYING
generated
vendored
Normal file
502
Godeps/_workspace/src/github.com/sigma/vmw-guestinfo/COPYING
generated
vendored
Normal file
@@ -0,0 +1,502 @@
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 2.1, February 1999
|
||||
|
||||
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
[This is the first released version of the Lesser GPL. It also counts
|
||||
as the successor of the GNU Library Public License, version 2, hence
|
||||
the version number 2.1.]
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
Licenses are intended to guarantee your freedom to share and change
|
||||
free software--to make sure the software is free for all its users.
|
||||
|
||||
This license, the Lesser General Public License, applies to some
|
||||
specially designated software packages--typically libraries--of the
|
||||
Free Software Foundation and other authors who decide to use it. You
|
||||
can use it too, but we suggest you first think carefully about whether
|
||||
this license or the ordinary General Public License is the better
|
||||
strategy to use in any particular case, based on the explanations below.
|
||||
|
||||
When we speak of free software, we are referring to freedom of use,
|
||||
not price. Our General Public Licenses are designed to make sure that
|
||||
you have the freedom to distribute copies of free software (and charge
|
||||
for this service if you wish); that you receive source code or can get
|
||||
it if you want it; that you can change the software and use pieces of
|
||||
it in new free programs; and that you are informed that you can do
|
||||
these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
distributors to deny you these rights or to ask you to surrender these
|
||||
rights. These restrictions translate to certain responsibilities for
|
||||
you if you distribute copies of the library or if you modify it.
|
||||
|
||||
For example, if you distribute copies of the library, whether gratis
|
||||
or for a fee, you must give the recipients all the rights that we gave
|
||||
you. You must make sure that they, too, receive or can get the source
|
||||
code. If you link other code with the library, you must provide
|
||||
complete object files to the recipients, so that they can relink them
|
||||
with the library after making changes to the library and recompiling
|
||||
it. And you must show them these terms so they know their rights.
|
||||
|
||||
We protect your rights with a two-step method: (1) we copyright the
|
||||
library, and (2) we offer you this license, which gives you legal
|
||||
permission to copy, distribute and/or modify the library.
|
||||
|
||||
To protect each distributor, we want to make it very clear that
|
||||
there is no warranty for the free library. Also, if the library is
|
||||
modified by someone else and passed on, the recipients should know
|
||||
that what they have is not the original version, so that the original
|
||||
author's reputation will not be affected by problems that might be
|
||||
introduced by others.
|
||||
|
||||
Finally, software patents pose a constant threat to the existence of
|
||||
any free program. We wish to make sure that a company cannot
|
||||
effectively restrict the users of a free program by obtaining a
|
||||
restrictive license from a patent holder. Therefore, we insist that
|
||||
any patent license obtained for a version of the library must be
|
||||
consistent with the full freedom of use specified in this license.
|
||||
|
||||
Most GNU software, including some libraries, is covered by the
|
||||
ordinary GNU General Public License. This license, the GNU Lesser
|
||||
General Public License, applies to certain designated libraries, and
|
||||
is quite different from the ordinary General Public License. We use
|
||||
this license for certain libraries in order to permit linking those
|
||||
libraries into non-free programs.
|
||||
|
||||
When a program is linked with a library, whether statically or using
|
||||
a shared library, the combination of the two is legally speaking a
|
||||
combined work, a derivative of the original library. The ordinary
|
||||
General Public License therefore permits such linking only if the
|
||||
entire combination fits its criteria of freedom. The Lesser General
|
||||
Public License permits more lax criteria for linking other code with
|
||||
the library.
|
||||
|
||||
We call this license the "Lesser" General Public License because it
|
||||
does Less to protect the user's freedom than the ordinary General
|
||||
Public License. It also provides other free software developers Less
|
||||
of an advantage over competing non-free programs. These disadvantages
|
||||
are the reason we use the ordinary General Public License for many
|
||||
libraries. However, the Lesser license provides advantages in certain
|
||||
special circumstances.
|
||||
|
||||
For example, on rare occasions, there may be a special need to
|
||||
encourage the widest possible use of a certain library, so that it becomes
|
||||
a de-facto standard. To achieve this, non-free programs must be
|
||||
allowed to use the library. A more frequent case is that a free
|
||||
library does the same job as widely used non-free libraries. In this
|
||||
case, there is little to gain by limiting the free library to free
|
||||
software only, so we use the Lesser General Public License.
|
||||
|
||||
In other cases, permission to use a particular library in non-free
|
||||
programs enables a greater number of people to use a large body of
|
||||
free software. For example, permission to use the GNU C Library in
|
||||
non-free programs enables many more people to use the whole GNU
|
||||
operating system, as well as its variant, the GNU/Linux operating
|
||||
system.
|
||||
|
||||
Although the Lesser General Public License is Less protective of the
|
||||
users' freedom, it does ensure that the user of a program that is
|
||||
linked with the Library has the freedom and the wherewithal to run
|
||||
that program using a modified version of the Library.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow. Pay close attention to the difference between a
|
||||
"work based on the library" and a "work that uses the library". The
|
||||
former contains code derived from the library, whereas the latter must
|
||||
be combined with the library in order to run.
|
||||
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License Agreement applies to any software library or other
|
||||
program which contains a notice placed by the copyright holder or
|
||||
other authorized party saying it may be distributed under the terms of
|
||||
this Lesser General Public License (also called "this License").
|
||||
Each licensee is addressed as "you".
|
||||
|
||||
A "library" means a collection of software functions and/or data
|
||||
prepared so as to be conveniently linked with application programs
|
||||
(which use some of those functions and data) to form executables.
|
||||
|
||||
The "Library", below, refers to any such software library or work
|
||||
which has been distributed under these terms. A "work based on the
|
||||
Library" means either the Library or any derivative work under
|
||||
copyright law: that is to say, a work containing the Library or a
|
||||
portion of it, either verbatim or with modifications and/or translated
|
||||
straightforwardly into another language. (Hereinafter, translation is
|
||||
included without limitation in the term "modification".)
|
||||
|
||||
"Source code" for a work means the preferred form of the work for
|
||||
making modifications to it. For a library, complete source code means
|
||||
all the source code for all modules it contains, plus any associated
|
||||
interface definition files, plus the scripts used to control compilation
|
||||
and installation of the library.
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running a program using the Library is not restricted, and output from
|
||||
such a program is covered only if its contents constitute a work based
|
||||
on the Library (independent of the use of the Library in a tool for
|
||||
writing it). Whether that is true depends on what the Library does
|
||||
and what the program that uses the Library does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Library's
|
||||
complete source code as you receive it, in any medium, provided that
|
||||
you conspicuously and appropriately publish on each copy an
|
||||
appropriate copyright notice and disclaimer of warranty; keep intact
|
||||
all the notices that refer to this License and to the absence of any
|
||||
warranty; and distribute a copy of this License along with the
|
||||
Library.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy,
|
||||
and you may at your option offer warranty protection in exchange for a
|
||||
fee.
|
||||
|
||||
2. You may modify your copy or copies of the Library or any portion
|
||||
of it, thus forming a work based on the Library, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) The modified work must itself be a software library.
|
||||
|
||||
b) You must cause the files modified to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
c) You must cause the whole of the work to be licensed at no
|
||||
charge to all third parties under the terms of this License.
|
||||
|
||||
d) If a facility in the modified Library refers to a function or a
|
||||
table of data to be supplied by an application program that uses
|
||||
the facility, other than as an argument passed when the facility
|
||||
is invoked, then you must make a good faith effort to ensure that,
|
||||
in the event an application does not supply such function or
|
||||
table, the facility still operates, and performs whatever part of
|
||||
its purpose remains meaningful.
|
||||
|
||||
(For example, a function in a library to compute square roots has
|
||||
a purpose that is entirely well-defined independent of the
|
||||
application. Therefore, Subsection 2d requires that any
|
||||
application-supplied function or table used by this function must
|
||||
be optional: if the application does not supply it, the square
|
||||
root function must still compute square roots.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Library,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Library, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote
|
||||
it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Library.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Library
|
||||
with the Library (or with a work based on the Library) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may opt to apply the terms of the ordinary GNU General Public
|
||||
License instead of this License to a given copy of the Library. To do
|
||||
this, you must alter all the notices that refer to this License, so
|
||||
that they refer to the ordinary GNU General Public License, version 2,
|
||||
instead of to this License. (If a newer version than version 2 of the
|
||||
ordinary GNU General Public License has appeared, then you can specify
|
||||
that version instead if you wish.) Do not make any other change in
|
||||
these notices.
|
||||
|
||||
Once this change is made in a given copy, it is irreversible for
|
||||
that copy, so the ordinary GNU General Public License applies to all
|
||||
subsequent copies and derivative works made from that copy.
|
||||
|
||||
This option is useful when you wish to copy part of the code of
|
||||
the Library into a program that is not a library.
|
||||
|
||||
4. You may copy and distribute the Library (or a portion or
|
||||
derivative of it, under Section 2) in object code or executable form
|
||||
under the terms of Sections 1 and 2 above provided that you accompany
|
||||
it with the complete corresponding machine-readable source code, which
|
||||
must be distributed under the terms of Sections 1 and 2 above on a
|
||||
medium customarily used for software interchange.
|
||||
|
||||
If distribution of object code is made by offering access to copy
|
||||
from a designated place, then offering equivalent access to copy the
|
||||
source code from the same place satisfies the requirement to
|
||||
distribute the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
5. A program that contains no derivative of any portion of the
|
||||
Library, but is designed to work with the Library by being compiled or
|
||||
linked with it, is called a "work that uses the Library". Such a
|
||||
work, in isolation, is not a derivative work of the Library, and
|
||||
therefore falls outside the scope of this License.
|
||||
|
||||
However, linking a "work that uses the Library" with the Library
|
||||
creates an executable that is a derivative of the Library (because it
|
||||
contains portions of the Library), rather than a "work that uses the
|
||||
library". The executable is therefore covered by this License.
|
||||
Section 6 states terms for distribution of such executables.
|
||||
|
||||
When a "work that uses the Library" uses material from a header file
|
||||
that is part of the Library, the object code for the work may be a
|
||||
derivative work of the Library even though the source code is not.
|
||||
Whether this is true is especially significant if the work can be
|
||||
linked without the Library, or if the work is itself a library. The
|
||||
threshold for this to be true is not precisely defined by law.
|
||||
|
||||
If such an object file uses only numerical parameters, data
|
||||
structure layouts and accessors, and small macros and small inline
|
||||
functions (ten lines or less in length), then the use of the object
|
||||
file is unrestricted, regardless of whether it is legally a derivative
|
||||
work. (Executables containing this object code plus portions of the
|
||||
Library will still fall under Section 6.)
|
||||
|
||||
Otherwise, if the work is a derivative of the Library, you may
|
||||
distribute the object code for the work under the terms of Section 6.
|
||||
Any executables containing that work also fall under Section 6,
|
||||
whether or not they are linked directly with the Library itself.
|
||||
|
||||
6. As an exception to the Sections above, you may also combine or
|
||||
link a "work that uses the Library" with the Library to produce a
|
||||
work containing portions of the Library, and distribute that work
|
||||
under terms of your choice, provided that the terms permit
|
||||
modification of the work for the customer's own use and reverse
|
||||
engineering for debugging such modifications.
|
||||
|
||||
You must give prominent notice with each copy of the work that the
|
||||
Library is used in it and that the Library and its use are covered by
|
||||
this License. You must supply a copy of this License. If the work
|
||||
during execution displays copyright notices, you must include the
|
||||
copyright notice for the Library among them, as well as a reference
|
||||
directing the user to the copy of this License. Also, you must do one
|
||||
of these things:
|
||||
|
||||
a) Accompany the work with the complete corresponding
|
||||
machine-readable source code for the Library including whatever
|
||||
changes were used in the work (which must be distributed under
|
||||
Sections 1 and 2 above); and, if the work is an executable linked
|
||||
with the Library, with the complete machine-readable "work that
|
||||
uses the Library", as object code and/or source code, so that the
|
||||
user can modify the Library and then relink to produce a modified
|
||||
executable containing the modified Library. (It is understood
|
||||
that the user who changes the contents of definitions files in the
|
||||
Library will not necessarily be able to recompile the application
|
||||
to use the modified definitions.)
|
||||
|
||||
b) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (1) uses at run time a
|
||||
copy of the library already present on the user's computer system,
|
||||
rather than copying library functions into the executable, and (2)
|
||||
will operate properly with a modified version of the library, if
|
||||
the user installs one, as long as the modified version is
|
||||
interface-compatible with the version that the work was made with.
|
||||
|
||||
c) Accompany the work with a written offer, valid for at
|
||||
least three years, to give the same user the materials
|
||||
specified in Subsection 6a, above, for a charge no more
|
||||
than the cost of performing this distribution.
|
||||
|
||||
d) If distribution of the work is made by offering access to copy
|
||||
from a designated place, offer equivalent access to copy the above
|
||||
specified materials from the same place.
|
||||
|
||||
e) Verify that the user has already received a copy of these
|
||||
materials or that you have already sent this user a copy.
|
||||
|
||||
For an executable, the required form of the "work that uses the
|
||||
Library" must include any data and utility programs needed for
|
||||
reproducing the executable from it. However, as a special exception,
|
||||
the materials to be distributed need not include anything that is
|
||||
normally distributed (in either source or binary form) with the major
|
||||
components (compiler, kernel, and so on) of the operating system on
|
||||
which the executable runs, unless that component itself accompanies
|
||||
the executable.
|
||||
|
||||
It may happen that this requirement contradicts the license
|
||||
restrictions of other proprietary libraries that do not normally
|
||||
accompany the operating system. Such a contradiction means you cannot
|
||||
use both them and the Library together in an executable that you
|
||||
distribute.
|
||||
|
||||
7. You may place library facilities that are a work based on the
|
||||
Library side-by-side in a single library together with other library
|
||||
facilities not covered by this License, and distribute such a combined
|
||||
library, provided that the separate distribution of the work based on
|
||||
the Library and of the other library facilities is otherwise
|
||||
permitted, and provided that you do these two things:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work
|
||||
based on the Library, uncombined with any other library
|
||||
facilities. This must be distributed under the terms of the
|
||||
Sections above.
|
||||
|
||||
b) Give prominent notice with the combined library of the fact
|
||||
that part of it is a work based on the Library, and explaining
|
||||
where to find the accompanying uncombined form of the same work.
|
||||
|
||||
8. You may not copy, modify, sublicense, link with, or distribute
|
||||
the Library except as expressly provided under this License. Any
|
||||
attempt otherwise to copy, modify, sublicense, link with, or
|
||||
distribute the Library is void, and will automatically terminate your
|
||||
rights under this License. However, parties who have received copies,
|
||||
or rights, from you under this License will not have their licenses
|
||||
terminated so long as such parties remain in full compliance.
|
||||
|
||||
9. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Library or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Library (or any work based on the
|
||||
Library), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Library or works based on it.
|
||||
|
||||
10. Each time you redistribute the Library (or any work based on the
|
||||
Library), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute, link with or modify the Library
|
||||
subject to these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties with
|
||||
this License.
|
||||
|
||||
11. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Library at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Library by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Library.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under any
|
||||
particular circumstance, the balance of the section is intended to apply,
|
||||
and the section as a whole is intended to apply in other circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
12. If the distribution and/or use of the Library is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Library under this License may add
|
||||
an explicit geographical distribution limitation excluding those countries,
|
||||
so that distribution is permitted only in or among countries not thus
|
||||
excluded. In such case, this License incorporates the limitation as if
|
||||
written in the body of this License.
|
||||
|
||||
13. The Free Software Foundation may publish revised and/or new
|
||||
versions of the Lesser General Public License from time to time.
|
||||
Such new versions will be similar in spirit to the present version,
|
||||
but may differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Library
|
||||
specifies a version number of this License which applies to it and
|
||||
"any later version", you have the option of following the terms and
|
||||
conditions either of that version or of any later version published by
|
||||
the Free Software Foundation. If the Library does not specify a
|
||||
license version number, you may choose any version ever published by
|
||||
the Free Software Foundation.
|
||||
|
||||
14. If you wish to incorporate parts of the Library into other free
|
||||
programs whose distribution conditions are incompatible with these,
|
||||
write to the author to ask for permission. For software which is
|
||||
copyrighted by the Free Software Foundation, write to the Free
|
||||
Software Foundation; we sometimes make exceptions for this. Our
|
||||
decision will be guided by the two goals of preserving the free status
|
||||
of all derivatives of our free software and of promoting the sharing
|
||||
and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
|
||||
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
|
||||
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
|
||||
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
|
||||
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
|
||||
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
|
||||
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
|
||||
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
|
||||
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
|
||||
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
|
||||
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
|
||||
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
|
||||
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
|
||||
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
|
||||
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Libraries
|
||||
|
||||
If you develop a new library, and you want it to be of the greatest
|
||||
possible use to the public, we recommend making it free software that
|
||||
everyone can redistribute and change. You can do so by permitting
|
||||
redistribution under these terms (or, alternatively, under the terms of the
|
||||
ordinary General Public License).
|
||||
|
||||
To apply these terms, attach the following notices to the library. It is
|
||||
safest to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least the
|
||||
"copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the library's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the library, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the
|
||||
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1990
|
||||
Ty Coon, President of Vice
|
||||
|
||||
That's all there is to it!
|
272
Godeps/_workspace/src/github.com/sigma/vmw-guestinfo/bridge/backdoor.c
generated
vendored
Normal file
272
Godeps/_workspace/src/github.com/sigma/vmw-guestinfo/bridge/backdoor.c
generated
vendored
Normal file
@@ -0,0 +1,272 @@
|
||||
/*********************************************************
|
||||
* Copyright (C) 1999-2015 VMware, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published
|
||||
* by the Free Software Foundation version 2.1 and no later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
*********************************************************/
|
||||
|
||||
/*********************************************************
|
||||
* The contents of this file are subject to the terms of the Common
|
||||
* Development and Distribution License (the "License") version 1.0
|
||||
* and no later version. You may not use this file except in
|
||||
* compliance with the License.
|
||||
*
|
||||
* You can obtain a copy of the License at
|
||||
* http://www.opensource.org/licenses/cddl1.php
|
||||
*
|
||||
* See the License for the specific language governing permissions
|
||||
* and limitations under the License.
|
||||
*
|
||||
*********************************************************/
|
||||
|
||||
/*
|
||||
* backdoor.c --
|
||||
*
|
||||
* First layer of the internal communication channel between guest
|
||||
* applications and vmware
|
||||
*
|
||||
* This is the backdoor. By using special ports of the virtual I/O space,
|
||||
* and the virtual CPU registers, a guest application can send a
|
||||
* synchroneous basic request to vmware, and vmware can reply to it.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "backdoor_def.h"
|
||||
#include "backdoor.h"
|
||||
#include "backdoorInt.h"
|
||||
|
||||
#if defined(BACKDOOR_DEBUG) && defined(USERLEVEL)
|
||||
#if defined(__KERNEL__) || defined(_KERNEL)
|
||||
#else
|
||||
# include "debug.h"
|
||||
#endif
|
||||
# include <stdio.h>
|
||||
# define BACKDOOR_LOG(args) Debug args
|
||||
# define BACKDOOR_LOG_PROTO_STRUCT(x) BackdoorPrintProtoStruct((x))
|
||||
# define BACKDOOR_LOG_HB_PROTO_STRUCT(x) BackdoorPrintHbProtoStruct((x))
|
||||
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------------
|
||||
*
|
||||
* BackdoorPrintProtoStruct --
|
||||
* BackdoorPrintHbProtoStruct --
|
||||
*
|
||||
* Print the contents of the specified backdoor protocol structure via
|
||||
* printf.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
*
|
||||
* Side effects:
|
||||
* Output to stdout.
|
||||
*
|
||||
*----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void
|
||||
BackdoorPrintProtoStruct(Backdoor_proto *myBp)
|
||||
{
|
||||
Debug("magic 0x%08x, command %d, size %"FMTSZ"u, port %d\n",
|
||||
myBp->in.ax.word, myBp->in.cx.halfs.low,
|
||||
myBp->in.size, myBp->in.dx.halfs.low);
|
||||
|
||||
#ifndef VM_X86_64
|
||||
Debug("ax %#x, "
|
||||
"bx %#x, "
|
||||
"cx %#x, "
|
||||
"dx %#x, "
|
||||
"si %#x, "
|
||||
"di %#x\n",
|
||||
myBp->out.ax.word,
|
||||
myBp->out.bx.word,
|
||||
myBp->out.cx.word,
|
||||
myBp->out.dx.word,
|
||||
myBp->out.si.word,
|
||||
myBp->out.di.word);
|
||||
#else
|
||||
Debug("ax %#"FMT64"x, "
|
||||
"bx %#"FMT64"x, "
|
||||
"cx %#"FMT64"x, "
|
||||
"dx %#"FMT64"x, "
|
||||
"si %#"FMT64"x, "
|
||||
"di %#"FMT64"x\n",
|
||||
myBp->out.ax.quad,
|
||||
myBp->out.bx.quad,
|
||||
myBp->out.cx.quad,
|
||||
myBp->out.dx.quad,
|
||||
myBp->out.si.quad,
|
||||
myBp->out.di.quad);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BackdoorPrintHbProtoStruct(Backdoor_proto_hb *myBp)
|
||||
{
|
||||
Debug("magic 0x%08x, command %d, size %"FMTSZ"u, port %d, "
|
||||
"srcAddr %"FMTSZ"u, dstAddr %"FMTSZ"u\n",
|
||||
myBp->in.ax.word, myBp->in.bx.halfs.low, myBp->in.size,
|
||||
myBp->in.dx.halfs.low, myBp->in.srcAddr, myBp->in.dstAddr);
|
||||
|
||||
#ifndef VM_X86_64
|
||||
Debug("ax %#x, "
|
||||
"bx %#x, "
|
||||
"cx %#x, "
|
||||
"dx %#x, "
|
||||
"si %#x, "
|
||||
"di %#x, "
|
||||
"bp %#x\n",
|
||||
myBp->out.ax.word,
|
||||
myBp->out.bx.word,
|
||||
myBp->out.cx.word,
|
||||
myBp->out.dx.word,
|
||||
myBp->out.si.word,
|
||||
myBp->out.di.word,
|
||||
myBp->out.bp.word);
|
||||
#else
|
||||
Debug("ax %#"FMT64"x, "
|
||||
"bx %#"FMT64"x, "
|
||||
"cx %#"FMT64"x, "
|
||||
"dx %#"FMT64"x, "
|
||||
"si %#"FMT64"x, "
|
||||
"di %#"FMT64"x, "
|
||||
"bp %#"FMT64"x\n",
|
||||
myBp->out.ax.quad,
|
||||
myBp->out.bx.quad,
|
||||
myBp->out.cx.quad,
|
||||
myBp->out.dx.quad,
|
||||
myBp->out.si.quad,
|
||||
myBp->out.di.quad,
|
||||
myBp->out.bp.quad);
|
||||
#endif
|
||||
}
|
||||
|
||||
#else
|
||||
# define BACKDOOR_LOG(args)
|
||||
# define BACKDOOR_LOG_PROTO_STRUCT(x)
|
||||
# define BACKDOOR_LOG_HB_PROTO_STRUCT(x)
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
*-----------------------------------------------------------------------------
|
||||
*
|
||||
* Backdoor --
|
||||
*
|
||||
* Send a low-bandwidth basic request (16 bytes) to vmware, and return its
|
||||
* reply (24 bytes).
|
||||
*
|
||||
* Result:
|
||||
* None
|
||||
*
|
||||
* Side-effects:
|
||||
* None
|
||||
*
|
||||
*-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void
|
||||
Backdoor(Backdoor_proto *myBp) // IN/OUT
|
||||
{
|
||||
ASSERT(myBp);
|
||||
|
||||
myBp->in.ax.word = BDOOR_MAGIC;
|
||||
myBp->in.dx.halfs.low = BDOOR_PORT;
|
||||
|
||||
BACKDOOR_LOG(("Backdoor: before "));
|
||||
BACKDOOR_LOG_PROTO_STRUCT(myBp);
|
||||
|
||||
Backdoor_InOut(myBp);
|
||||
|
||||
BACKDOOR_LOG(("Backdoor: after "));
|
||||
BACKDOOR_LOG_PROTO_STRUCT(myBp);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*-----------------------------------------------------------------------------
|
||||
*
|
||||
* Backdoor_HbOut --
|
||||
*
|
||||
* Send a high-bandwidth basic request to vmware, and return its
|
||||
* reply.
|
||||
*
|
||||
* Result:
|
||||
* The host-side response is returned via the IN/OUT parameter.
|
||||
*
|
||||
* Side-effects:
|
||||
* Pokes the high-bandwidth backdoor.
|
||||
*
|
||||
*-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void
|
||||
Backdoor_HbOut(Backdoor_proto_hb *myBp) // IN/OUT
|
||||
{
|
||||
ASSERT(myBp);
|
||||
|
||||
myBp->in.ax.word = BDOOR_MAGIC;
|
||||
myBp->in.dx.halfs.low = BDOORHB_PORT;
|
||||
|
||||
BACKDOOR_LOG(("Backdoor_HbOut: before "));
|
||||
BACKDOOR_LOG_HB_PROTO_STRUCT(myBp);
|
||||
|
||||
BackdoorHbOut(myBp);
|
||||
|
||||
BACKDOOR_LOG(("Backdoor_HbOut: after "));
|
||||
BACKDOOR_LOG_HB_PROTO_STRUCT(myBp);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*-----------------------------------------------------------------------------
|
||||
*
|
||||
* Backdoor_HbIn --
|
||||
*
|
||||
* Send a basic request to vmware, and return its high-bandwidth
|
||||
* reply
|
||||
*
|
||||
* Result:
|
||||
* Host-side response returned via the IN/OUT parameter.
|
||||
*
|
||||
* Side-effects:
|
||||
* Pokes the high-bandwidth backdoor.
|
||||
*
|
||||
*-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void
|
||||
Backdoor_HbIn(Backdoor_proto_hb *myBp) // IN/OUT
|
||||
{
|
||||
ASSERT(myBp);
|
||||
|
||||
myBp->in.ax.word = BDOOR_MAGIC;
|
||||
myBp->in.dx.halfs.low = BDOORHB_PORT;
|
||||
|
||||
BACKDOOR_LOG(("Backdoor_HbIn: before "));
|
||||
BACKDOOR_LOG_HB_PROTO_STRUCT(myBp);
|
||||
|
||||
BackdoorHbIn(myBp);
|
||||
|
||||
BACKDOOR_LOG(("Backdoor_HbIn: after "));
|
||||
BACKDOOR_LOG_HB_PROTO_STRUCT(myBp);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
235
Godeps/_workspace/src/github.com/sigma/vmw-guestinfo/bridge/backdoor_386.c
generated
vendored
Normal file
235
Godeps/_workspace/src/github.com/sigma/vmw-guestinfo/bridge/backdoor_386.c
generated
vendored
Normal file
@@ -0,0 +1,235 @@
|
||||
/*********************************************************
|
||||
* Copyright (C) 2005-2015 VMware, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published
|
||||
* by the Free Software Foundation version 2.1 and no later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
*********************************************************/
|
||||
|
||||
/*********************************************************
|
||||
* The contents of this file are subject to the terms of the Common
|
||||
* Development and Distribution License (the "License") version 1.0
|
||||
* and no later version. You may not use this file except in
|
||||
* compliance with the License.
|
||||
*
|
||||
* You can obtain a copy of the License at
|
||||
* http://www.opensource.org/licenses/cddl1.php
|
||||
*
|
||||
* See the License for the specific language governing permissions
|
||||
* and limitations under the License.
|
||||
*
|
||||
*********************************************************/
|
||||
|
||||
/*
|
||||
* backdoorGcc32.c --
|
||||
*
|
||||
* Implements the real work for guest-side backdoor for GCC, 32-bit
|
||||
* target (supports inline ASM, GAS syntax). The asm sections are marked
|
||||
* volatile since vmware can change the registers content without the
|
||||
* compiler knowing it.
|
||||
*
|
||||
* XXX
|
||||
* I tried to write this more cleanly, but:
|
||||
* - There is no way to specify an "ebp" constraint
|
||||
* - "ebp" is ignored when specified as cloberred register
|
||||
* - gas barfs when there is more than 10 operands
|
||||
* - gas 2.7.2.3, depending on the order of the operands, can
|
||||
* mis-assemble without any warning
|
||||
* --hpreg
|
||||
*
|
||||
* Note that the problems with gas noted above might longer be relevant
|
||||
* now that we've upgraded most of our compiler versions.
|
||||
* --rrdharan
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "backdoor.h"
|
||||
#include "backdoorInt.h"
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------------
|
||||
*
|
||||
* Backdoor_InOut --
|
||||
*
|
||||
* Send a low-bandwidth basic request (16 bytes) to vmware, and return its
|
||||
* reply (24 bytes).
|
||||
*
|
||||
* Results:
|
||||
* Host-side response returned in bp IN/OUT parameter.
|
||||
*
|
||||
* Side effects:
|
||||
* Pokes the backdoor.
|
||||
*
|
||||
*----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void
|
||||
Backdoor_InOut(Backdoor_proto *myBp) // IN/OUT
|
||||
{
|
||||
uint32 dummy;
|
||||
|
||||
__asm__ __volatile__(
|
||||
#ifdef __PIC__
|
||||
"pushl %%ebx" "\n\t"
|
||||
#endif
|
||||
"pushl %%eax" "\n\t"
|
||||
"movl 20(%%eax), %%edi" "\n\t"
|
||||
"movl 16(%%eax), %%esi" "\n\t"
|
||||
"movl 12(%%eax), %%edx" "\n\t"
|
||||
"movl 8(%%eax), %%ecx" "\n\t"
|
||||
"movl 4(%%eax), %%ebx" "\n\t"
|
||||
"movl (%%eax), %%eax" "\n\t"
|
||||
"inl %%dx, %%eax" "\n\t"
|
||||
"xchgl %%eax, (%%esp)" "\n\t"
|
||||
"movl %%edi, 20(%%eax)" "\n\t"
|
||||
"movl %%esi, 16(%%eax)" "\n\t"
|
||||
"movl %%edx, 12(%%eax)" "\n\t"
|
||||
"movl %%ecx, 8(%%eax)" "\n\t"
|
||||
"movl %%ebx, 4(%%eax)" "\n\t"
|
||||
"popl (%%eax)" "\n\t"
|
||||
#ifdef __PIC__
|
||||
"popl %%ebx" "\n\t"
|
||||
#endif
|
||||
: "=a" (dummy)
|
||||
: "0" (myBp)
|
||||
/*
|
||||
* vmware can modify the whole VM state without the compiler knowing
|
||||
* it. So far it does not modify EFLAGS. --hpreg
|
||||
*/
|
||||
:
|
||||
#ifndef __PIC__
|
||||
"ebx",
|
||||
#endif
|
||||
"ecx", "edx", "esi", "edi", "memory"
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*-----------------------------------------------------------------------------
|
||||
*
|
||||
* BackdoorHbIn --
|
||||
* BackdoorHbOut --
|
||||
*
|
||||
* Send a high-bandwidth basic request to vmware, and return its
|
||||
* reply.
|
||||
*
|
||||
* Results:
|
||||
* Host-side response returned in bp IN/OUT parameter.
|
||||
*
|
||||
* Side-effects:
|
||||
* Pokes the high-bandwidth backdoor port.
|
||||
*
|
||||
*-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void
|
||||
BackdoorHbIn(Backdoor_proto_hb *myBp) // IN/OUT
|
||||
{
|
||||
uint32 dummy;
|
||||
|
||||
__asm__ __volatile__(
|
||||
#ifdef __PIC__
|
||||
"pushl %%ebx" "\n\t"
|
||||
#endif
|
||||
"pushl %%ebp" "\n\t"
|
||||
|
||||
"pushl %%eax" "\n\t"
|
||||
"movl 24(%%eax), %%ebp" "\n\t"
|
||||
"movl 20(%%eax), %%edi" "\n\t"
|
||||
"movl 16(%%eax), %%esi" "\n\t"
|
||||
"movl 12(%%eax), %%edx" "\n\t"
|
||||
"movl 8(%%eax), %%ecx" "\n\t"
|
||||
"movl 4(%%eax), %%ebx" "\n\t"
|
||||
"movl (%%eax), %%eax" "\n\t"
|
||||
"cld" "\n\t"
|
||||
"rep; insb" "\n\t"
|
||||
"xchgl %%eax, (%%esp)" "\n\t"
|
||||
"movl %%ebp, 24(%%eax)" "\n\t"
|
||||
"movl %%edi, 20(%%eax)" "\n\t"
|
||||
"movl %%esi, 16(%%eax)" "\n\t"
|
||||
"movl %%edx, 12(%%eax)" "\n\t"
|
||||
"movl %%ecx, 8(%%eax)" "\n\t"
|
||||
"movl %%ebx, 4(%%eax)" "\n\t"
|
||||
"popl (%%eax)" "\n\t"
|
||||
|
||||
"popl %%ebp" "\n\t"
|
||||
#ifdef __PIC__
|
||||
"popl %%ebx" "\n\t"
|
||||
#endif
|
||||
: "=a" (dummy)
|
||||
: "0" (myBp)
|
||||
/*
|
||||
* vmware can modify the whole VM state without the compiler knowing
|
||||
* it. --hpreg
|
||||
*/
|
||||
:
|
||||
#ifndef __PIC__
|
||||
"ebx",
|
||||
#endif
|
||||
"ecx", "edx", "esi", "edi", "memory", "cc"
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BackdoorHbOut(Backdoor_proto_hb *myBp) // IN/OUT
|
||||
{
|
||||
uint32 dummy;
|
||||
|
||||
__asm__ __volatile__(
|
||||
#ifdef __PIC__
|
||||
"pushl %%ebx" "\n\t"
|
||||
#endif
|
||||
"pushl %%ebp" "\n\t"
|
||||
|
||||
"pushl %%eax" "\n\t"
|
||||
"movl 24(%%eax), %%ebp" "\n\t"
|
||||
"movl 20(%%eax), %%edi" "\n\t"
|
||||
"movl 16(%%eax), %%esi" "\n\t"
|
||||
"movl 12(%%eax), %%edx" "\n\t"
|
||||
"movl 8(%%eax), %%ecx" "\n\t"
|
||||
"movl 4(%%eax), %%ebx" "\n\t"
|
||||
"movl (%%eax), %%eax" "\n\t"
|
||||
"cld" "\n\t"
|
||||
"rep; outsb" "\n\t"
|
||||
"xchgl %%eax, (%%esp)" "\n\t"
|
||||
"movl %%ebp, 24(%%eax)" "\n\t"
|
||||
"movl %%edi, 20(%%eax)" "\n\t"
|
||||
"movl %%esi, 16(%%eax)" "\n\t"
|
||||
"movl %%edx, 12(%%eax)" "\n\t"
|
||||
"movl %%ecx, 8(%%eax)" "\n\t"
|
||||
"movl %%ebx, 4(%%eax)" "\n\t"
|
||||
"popl (%%eax)" "\n\t"
|
||||
|
||||
"popl %%ebp" "\n\t"
|
||||
#ifdef __PIC__
|
||||
"popl %%ebx" "\n\t"
|
||||
#endif
|
||||
: "=a" (dummy)
|
||||
: "0" (myBp)
|
||||
:
|
||||
#ifndef __PIC__
|
||||
"ebx",
|
||||
#endif
|
||||
"ecx", "edx", "esi", "edi", "memory", "cc"
|
||||
);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
243
Godeps/_workspace/src/github.com/sigma/vmw-guestinfo/bridge/backdoor_amd64.c
generated
vendored
Normal file
243
Godeps/_workspace/src/github.com/sigma/vmw-guestinfo/bridge/backdoor_amd64.c
generated
vendored
Normal file
@@ -0,0 +1,243 @@
|
||||
/*********************************************************
|
||||
* Copyright (C) 2005-2015 VMware, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published
|
||||
* by the Free Software Foundation version 2.1 and no later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
*********************************************************/
|
||||
|
||||
/*********************************************************
|
||||
* The contents of this file are subject to the terms of the Common
|
||||
* Development and Distribution License (the "License") version 1.0
|
||||
* and no later version. You may not use this file except in
|
||||
* compliance with the License.
|
||||
*
|
||||
* You can obtain a copy of the License at
|
||||
* http://www.opensource.org/licenses/cddl1.php
|
||||
*
|
||||
* See the License for the specific language governing permissions
|
||||
* and limitations under the License.
|
||||
*
|
||||
*********************************************************/
|
||||
|
||||
/*
|
||||
* backdoorGcc64.c --
|
||||
*
|
||||
* Implements the real work for guest-side backdoor for GCC, 64-bit
|
||||
* target (supports inline ASM, GAS syntax). The asm sections are marked
|
||||
* volatile since vmware can change the registers content without the
|
||||
* compiler knowing it.
|
||||
*
|
||||
* See backdoorGCC32.c (from which this code was mostly copied) for
|
||||
* details on why the ASM is written this way. Also note that it might be
|
||||
* possible to write the asm blocks using the symbolic operand specifiers
|
||||
* in such a way that the same asm would generate correct code for both
|
||||
* 32-bit and 64-bit targets, but I'm too lazy to figure it all out.
|
||||
* --rrdharan
|
||||
*/
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "backdoor.h"
|
||||
#include "backdoorInt.h"
|
||||
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------------
|
||||
*
|
||||
* Backdoor_InOut --
|
||||
*
|
||||
* Send a low-bandwidth basic request (16 bytes) to vmware, and return its
|
||||
* reply (24 bytes).
|
||||
*
|
||||
* Results:
|
||||
* Host-side response returned in bp IN/OUT parameter.
|
||||
*
|
||||
* Side effects:
|
||||
* Pokes the backdoor.
|
||||
*
|
||||
*----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void
|
||||
Backdoor_InOut(Backdoor_proto *myBp) // IN/OUT
|
||||
{
|
||||
uint64 dummy;
|
||||
|
||||
__asm__ __volatile__(
|
||||
#ifdef __APPLE__
|
||||
/*
|
||||
* Save %rbx on the stack because the Mac OS GCC doesn't want us to
|
||||
* clobber it - it erroneously thinks %rbx is the PIC register.
|
||||
* (Radar bug 7304232)
|
||||
*/
|
||||
"pushq %%rbx" "\n\t"
|
||||
#endif
|
||||
"pushq %%rax" "\n\t"
|
||||
"movq 40(%%rax), %%rdi" "\n\t"
|
||||
"movq 32(%%rax), %%rsi" "\n\t"
|
||||
"movq 24(%%rax), %%rdx" "\n\t"
|
||||
"movq 16(%%rax), %%rcx" "\n\t"
|
||||
"movq 8(%%rax), %%rbx" "\n\t"
|
||||
"movq (%%rax), %%rax" "\n\t"
|
||||
"inl %%dx, %%eax" "\n\t" /* NB: There is no inq instruction */
|
||||
"xchgq %%rax, (%%rsp)" "\n\t"
|
||||
"movq %%rdi, 40(%%rax)" "\n\t"
|
||||
"movq %%rsi, 32(%%rax)" "\n\t"
|
||||
"movq %%rdx, 24(%%rax)" "\n\t"
|
||||
"movq %%rcx, 16(%%rax)" "\n\t"
|
||||
"movq %%rbx, 8(%%rax)" "\n\t"
|
||||
"popq (%%rax)" "\n\t"
|
||||
#ifdef __APPLE__
|
||||
"popq %%rbx" "\n\t"
|
||||
#endif
|
||||
: "=a" (dummy)
|
||||
: "0" (myBp)
|
||||
/*
|
||||
* vmware can modify the whole VM state without the compiler knowing
|
||||
* it. So far it does not modify EFLAGS. --hpreg
|
||||
*/
|
||||
:
|
||||
#ifndef __APPLE__
|
||||
/* %rbx is unchanged at the end of the function on Mac OS. */
|
||||
"rbx",
|
||||
#endif
|
||||
"rcx", "rdx", "rsi", "rdi", "memory"
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*-----------------------------------------------------------------------------
|
||||
*
|
||||
* BackdoorHbIn --
|
||||
* BackdoorHbOut --
|
||||
*
|
||||
* Send a high-bandwidth basic request to vmware, and return its
|
||||
* reply.
|
||||
*
|
||||
* Results:
|
||||
* Host-side response returned in bp IN/OUT parameter.
|
||||
*
|
||||
* Side-effects:
|
||||
* Pokes the high-bandwidth backdoor port.
|
||||
*
|
||||
*-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void
|
||||
BackdoorHbIn(Backdoor_proto_hb *myBp) // IN/OUT
|
||||
{
|
||||
uint64 dummy;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"pushq %%rbp" "\n\t"
|
||||
#ifdef __APPLE__
|
||||
/*
|
||||
* Save %rbx on the stack because the Mac OS GCC doesn't want us to
|
||||
* clobber it - it erroneously thinks %rbx is the PIC register.
|
||||
* (Radar bug 7304232)
|
||||
*/
|
||||
"pushq %%rbx" "\n\t"
|
||||
#endif
|
||||
"pushq %%rax" "\n\t"
|
||||
"movq 48(%%rax), %%rbp" "\n\t"
|
||||
"movq 40(%%rax), %%rdi" "\n\t"
|
||||
"movq 32(%%rax), %%rsi" "\n\t"
|
||||
"movq 24(%%rax), %%rdx" "\n\t"
|
||||
"movq 16(%%rax), %%rcx" "\n\t"
|
||||
"movq 8(%%rax), %%rbx" "\n\t"
|
||||
"movq (%%rax), %%rax" "\n\t"
|
||||
"cld" "\n\t"
|
||||
"rep; insb" "\n\t"
|
||||
"xchgq %%rax, (%%rsp)" "\n\t"
|
||||
"movq %%rbp, 48(%%rax)" "\n\t"
|
||||
"movq %%rdi, 40(%%rax)" "\n\t"
|
||||
"movq %%rsi, 32(%%rax)" "\n\t"
|
||||
"movq %%rdx, 24(%%rax)" "\n\t"
|
||||
"movq %%rcx, 16(%%rax)" "\n\t"
|
||||
"movq %%rbx, 8(%%rax)" "\n\t"
|
||||
"popq (%%rax)" "\n\t"
|
||||
#ifdef __APPLE__
|
||||
"popq %%rbx" "\n\t"
|
||||
#endif
|
||||
"popq %%rbp"
|
||||
: "=a" (dummy)
|
||||
: "0" (myBp)
|
||||
/*
|
||||
* vmware can modify the whole VM state without the compiler knowing
|
||||
* it. --hpreg
|
||||
*/
|
||||
:
|
||||
#ifndef __APPLE__
|
||||
/* %rbx is unchanged at the end of the function on Mac OS. */
|
||||
"rbx",
|
||||
#endif
|
||||
"rcx", "rdx", "rsi", "rdi", "memory", "cc"
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BackdoorHbOut(Backdoor_proto_hb *myBp) // IN/OUT
|
||||
{
|
||||
uint64 dummy;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"pushq %%rbp" "\n\t"
|
||||
#ifdef __APPLE__
|
||||
/*
|
||||
* Save %rbx on the stack because the Mac OS GCC doesn't want us to
|
||||
* clobber it - it erroneously thinks %rbx is the PIC register.
|
||||
* (Radar bug 7304232)
|
||||
*/
|
||||
"pushq %%rbx" "\n\t"
|
||||
#endif
|
||||
"pushq %%rax" "\n\t"
|
||||
"movq 48(%%rax), %%rbp" "\n\t"
|
||||
"movq 40(%%rax), %%rdi" "\n\t"
|
||||
"movq 32(%%rax), %%rsi" "\n\t"
|
||||
"movq 24(%%rax), %%rdx" "\n\t"
|
||||
"movq 16(%%rax), %%rcx" "\n\t"
|
||||
"movq 8(%%rax), %%rbx" "\n\t"
|
||||
"movq (%%rax), %%rax" "\n\t"
|
||||
"cld" "\n\t"
|
||||
"rep; outsb" "\n\t"
|
||||
"xchgq %%rax, (%%rsp)" "\n\t"
|
||||
"movq %%rbp, 48(%%rax)" "\n\t"
|
||||
"movq %%rdi, 40(%%rax)" "\n\t"
|
||||
"movq %%rsi, 32(%%rax)" "\n\t"
|
||||
"movq %%rdx, 24(%%rax)" "\n\t"
|
||||
"movq %%rcx, 16(%%rax)" "\n\t"
|
||||
"movq %%rbx, 8(%%rax)" "\n\t"
|
||||
"popq (%%rax)" "\n\t"
|
||||
#ifdef __APPLE__
|
||||
"popq %%rbx" "\n\t"
|
||||
#endif
|
||||
"popq %%rbp"
|
||||
: "=a" (dummy)
|
||||
: "0" (myBp)
|
||||
:
|
||||
#ifndef __APPLE__
|
||||
/* %rbx is unchanged at the end of the function on Mac OS. */
|
||||
"rbx",
|
||||
#endif
|
||||
"rcx", "rdx", "rsi", "rdi", "memory", "cc"
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
60
Godeps/_workspace/src/github.com/sigma/vmw-guestinfo/bridge/bridge.go
generated
vendored
Normal file
60
Godeps/_workspace/src/github.com/sigma/vmw-guestinfo/bridge/bridge.go
generated
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
package bridge
|
||||
|
||||
/*
|
||||
#cgo CFLAGS: -I../include
|
||||
#include <stdlib.h>
|
||||
#include "message.h"
|
||||
#include "vmcheck.h"
|
||||
void Warning(const char *fmt, ...) {}
|
||||
void Debug(const char *fmt, ...) {}
|
||||
void Panic(const char *fmt, ...) {}
|
||||
void Log(const char *fmt, ...) {}
|
||||
*/
|
||||
import "C"
|
||||
import "unsafe"
|
||||
|
||||
// MessageChannel provides a channel to pass information from/to the hypervisor
|
||||
type MessageChannel *C.struct_Message_Channel
|
||||
|
||||
// MessageOpen creates a new MessageChannel
|
||||
func MessageOpen(proto uint32) MessageChannel {
|
||||
return C.Message_Open(C.uint32(proto))
|
||||
}
|
||||
|
||||
// MessageClose closes a MessageChannel
|
||||
func MessageClose(c MessageChannel) bool {
|
||||
status := C.Message_Close(c)
|
||||
return status != 0
|
||||
}
|
||||
|
||||
// MessageSend sends a request through a MessageChannel
|
||||
func MessageSend(c MessageChannel, request []byte) bool {
|
||||
buffer := (*C.uchar)(unsafe.Pointer(&request[0]))
|
||||
status := C.Message_Send(c, buffer, (C.size_t)(C.int(len(request))))
|
||||
return status != 0
|
||||
}
|
||||
|
||||
// MessageReceive receives a response through a MessageChannel
|
||||
func MessageReceive(c MessageChannel) ([]byte, bool) {
|
||||
var reply *C.uchar
|
||||
var replyLen C.size_t
|
||||
defer C.free(unsafe.Pointer(reply))
|
||||
|
||||
status := C.Message_Receive(c, &reply, &replyLen)
|
||||
|
||||
res := C.GoBytes(unsafe.Pointer(reply), (C.int)(replyLen))
|
||||
return res, status != 0
|
||||
}
|
||||
|
||||
// VMCheckIsVirtualWorld checks if current code is running in a VMware virtual machine
|
||||
func VMCheckIsVirtualWorld() bool {
|
||||
return C.VmCheck_IsVirtualWorld() != 0
|
||||
}
|
||||
|
||||
// VMCheckGetVersion returns the identifiers of the current hypervisor
|
||||
func VMCheckGetVersion() (uint32, uint32) {
|
||||
var version C.uint32
|
||||
var typ C.uint32
|
||||
C.VmCheck_GetVersion(&version, &typ)
|
||||
return uint32(version), uint32(typ)
|
||||
}
|
439
Godeps/_workspace/src/github.com/sigma/vmw-guestinfo/bridge/dynbuf.c
generated
vendored
Normal file
439
Godeps/_workspace/src/github.com/sigma/vmw-guestinfo/bridge/dynbuf.c
generated
vendored
Normal file
@@ -0,0 +1,439 @@
|
||||
/*********************************************************
|
||||
* Copyright (C) 1998-2015 VMware, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published
|
||||
* by the Free Software Foundation version 2.1 and no later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
*********************************************************/
|
||||
|
||||
/*
|
||||
* dynbuf.c --
|
||||
*
|
||||
* Dynamic buffers --hpreg
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "vmware.h"
|
||||
#include "dynbuf.h"
|
||||
|
||||
|
||||
/*
|
||||
*-----------------------------------------------------------------------------
|
||||
*
|
||||
* DynBuf_Init --
|
||||
*
|
||||
* Dynamic buffer constructor --hpreg
|
||||
*
|
||||
* Results:
|
||||
* None
|
||||
*
|
||||
* Side effects:
|
||||
* None
|
||||
*
|
||||
*-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void
|
||||
DynBuf_Init(DynBuf *b) // OUT:
|
||||
{
|
||||
ASSERT(b);
|
||||
|
||||
b->data = NULL;
|
||||
b->size = 0;
|
||||
b->allocated = 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*-----------------------------------------------------------------------------
|
||||
*
|
||||
* DynBuf_Destroy --
|
||||
*
|
||||
* Dynamic buffer destructor --hpreg
|
||||
*
|
||||
* Results:
|
||||
* None
|
||||
*
|
||||
* Side effects:
|
||||
* None
|
||||
*
|
||||
*-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void
|
||||
DynBuf_Destroy(DynBuf *b) // IN/OUT:
|
||||
{
|
||||
ASSERT(b);
|
||||
|
||||
free(b->data);
|
||||
DynBuf_Init(b);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*-----------------------------------------------------------------------------
|
||||
*
|
||||
* DynBuf_AllocGet --
|
||||
*
|
||||
* Retrieve a pointer to the data contained in a dynamic buffer. Return
|
||||
* a copy of that data.
|
||||
*
|
||||
* Results:
|
||||
* The pointer to the data. NULL on out of memory failure.
|
||||
*
|
||||
* Side effects:
|
||||
* Allocates memory.
|
||||
*
|
||||
*-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void *
|
||||
DynBuf_AllocGet(DynBuf const *b) // IN
|
||||
{
|
||||
void *new_data;
|
||||
ASSERT(b);
|
||||
|
||||
new_data = malloc(b->size);
|
||||
if (new_data) {
|
||||
memcpy(new_data, b->data, b->size);
|
||||
}
|
||||
|
||||
return new_data;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*-----------------------------------------------------------------------------
|
||||
*
|
||||
* DynBuf_Attach --
|
||||
*
|
||||
* Grants ownership of the specified buffer to the DynBuf
|
||||
* object. If there is an existing buffer, it is freed.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
*
|
||||
* Side effects:
|
||||
* None
|
||||
*
|
||||
*-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void
|
||||
DynBuf_Attach(DynBuf *b, // IN
|
||||
size_t size, // IN
|
||||
void *data) // IN
|
||||
{
|
||||
ASSERT(b);
|
||||
ASSERT((size == 0) == (data == NULL));
|
||||
|
||||
free(b->data);
|
||||
b->data = data;
|
||||
b->size = b->allocated = size;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*-----------------------------------------------------------------------------
|
||||
*
|
||||
* DynBuf_Detach --
|
||||
*
|
||||
* Releases ownership of the buffer stored in the DynBuf object,
|
||||
* and returns a pointer to it.
|
||||
*
|
||||
* Results:
|
||||
* The pointer to the data.
|
||||
*
|
||||
* Side effects:
|
||||
* None
|
||||
*
|
||||
*-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void *
|
||||
DynBuf_Detach(DynBuf *b) // IN
|
||||
{
|
||||
void *data;
|
||||
|
||||
ASSERT(b);
|
||||
|
||||
data = b->data;
|
||||
b->data = NULL;
|
||||
b->allocated = 0;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*-----------------------------------------------------------------------------
|
||||
*
|
||||
* DynBufRealloc --
|
||||
*
|
||||
* Reallocate a dynamic buffer --hpreg
|
||||
*
|
||||
* Results:
|
||||
* TRUE on success
|
||||
* FALSE on failure (not enough memory)
|
||||
*
|
||||
* Side effects:
|
||||
* None
|
||||
*
|
||||
*-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static Bool
|
||||
DynBufRealloc(DynBuf *b, // IN:
|
||||
size_t newAllocated) // IN:
|
||||
{
|
||||
void *new_data;
|
||||
|
||||
ASSERT(b);
|
||||
|
||||
new_data = realloc(b->data, newAllocated);
|
||||
if (new_data == NULL && newAllocated) {
|
||||
/* Not enough memory */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
b->data = new_data;
|
||||
b->allocated = newAllocated;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*-----------------------------------------------------------------------------
|
||||
*
|
||||
* DynBuf_Enlarge --
|
||||
*
|
||||
* Enlarge a dynamic buffer. The resulting dynamic buffer is guaranteed to
|
||||
* be larger than the one you passed, and at least 'minSize' bytes
|
||||
* large --hpreg
|
||||
*
|
||||
* Results:
|
||||
* TRUE on success
|
||||
* FALSE on failure (not enough memory)
|
||||
*
|
||||
* Side effects:
|
||||
* None
|
||||
*
|
||||
*-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
Bool
|
||||
DynBuf_Enlarge(DynBuf *b, // IN:
|
||||
size_t minSize) // IN:
|
||||
{
|
||||
size_t newAllocated;
|
||||
|
||||
ASSERT(b);
|
||||
|
||||
newAllocated = b->allocated
|
||||
?
|
||||
#if defined(DYNBUF_DEBUG)
|
||||
b->allocated + 1
|
||||
#else
|
||||
/*
|
||||
* Double the previously allocated size if it is less
|
||||
* than 256KB; otherwise grow it linearly by 256KB
|
||||
*/
|
||||
(b->allocated < 256 * 1024 ? b->allocated * 2
|
||||
: b->allocated + 256 * 1024)
|
||||
#endif
|
||||
:
|
||||
#if defined(DYNBUF_DEBUG)
|
||||
1
|
||||
#else
|
||||
/*
|
||||
* Initial size: 1 KB. Most buffers are smaller than
|
||||
* that --hpreg
|
||||
*/
|
||||
1 << 10
|
||||
#endif
|
||||
;
|
||||
|
||||
if (minSize > newAllocated) {
|
||||
newAllocated = minSize;
|
||||
}
|
||||
|
||||
/*
|
||||
* Prevent integer overflow. We can use this form of checking specifically
|
||||
* because a multiple by 2 is used (in the worst case). This type of
|
||||
* checking does not work in the general case.
|
||||
*/
|
||||
|
||||
if (newAllocated < b->allocated) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return DynBufRealloc(b, newAllocated);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*-----------------------------------------------------------------------------
|
||||
*
|
||||
* DynBuf_Append --
|
||||
*
|
||||
* Append data at the end of a dynamic buffer. 'size' is the size of the
|
||||
* data. If it is <= 0, no operation is performed --hpreg
|
||||
*
|
||||
* Results:
|
||||
* TRUE on success
|
||||
* FALSE on failure (not enough memory)
|
||||
*
|
||||
* Side effects:
|
||||
* None
|
||||
*
|
||||
*-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
Bool
|
||||
DynBuf_Append(DynBuf *b, // IN
|
||||
void const *data, // IN
|
||||
size_t size) // IN
|
||||
{
|
||||
size_t new_size;
|
||||
|
||||
ASSERT(b);
|
||||
|
||||
if (size <= 0) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
ASSERT(data);
|
||||
|
||||
new_size = b->size + size;
|
||||
|
||||
if (new_size < b->size) { // Prevent integer overflow
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (new_size > b->allocated) {
|
||||
/* Not enough room */
|
||||
if (DynBuf_Enlarge(b, new_size) == FALSE) {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(b->data + b->size, data, size);
|
||||
b->size = new_size;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*-----------------------------------------------------------------------------
|
||||
*
|
||||
* DynBuf_SafeInternalAppend --
|
||||
*
|
||||
* Append data at the end of a dynamic buffer. Memory allocation failure
|
||||
* are handled the same way as Util_SafeMalloc, that is to say, with a
|
||||
* Panic.
|
||||
*
|
||||
* Results:
|
||||
* None
|
||||
*
|
||||
* Side effects:
|
||||
* None
|
||||
*
|
||||
*-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void
|
||||
DynBuf_SafeInternalAppend(DynBuf *b, // IN
|
||||
void const *data, // IN
|
||||
size_t size, // IN
|
||||
char const *file, // IN
|
||||
unsigned int lineno) // IN
|
||||
{
|
||||
if (!DynBuf_Append(b, data, size)) {
|
||||
Panic("Unrecoverable memory allocation failure at %s:%u\n",
|
||||
file, lineno);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*-----------------------------------------------------------------------------
|
||||
*
|
||||
* DynBuf_Trim --
|
||||
*
|
||||
* Reallocate a dynamic buffer to the exact size it occupies --hpreg
|
||||
*
|
||||
* Results:
|
||||
* TRUE on success
|
||||
* FALSE on failure (not enough memory)
|
||||
*
|
||||
* Side effects:
|
||||
* None
|
||||
*
|
||||
*-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
Bool
|
||||
DynBuf_Trim(DynBuf *b) // IN
|
||||
{
|
||||
ASSERT(b);
|
||||
|
||||
return DynBufRealloc(b, b->size);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*-----------------------------------------------------------------------------
|
||||
*
|
||||
* DynBuf_Copy --
|
||||
*
|
||||
* Copies all data and metadata from src dynbuff to dest dynbuf.
|
||||
*
|
||||
* Dest should be an initialized DynBuf of alloced length zero
|
||||
* to prevent memory leaks.
|
||||
*
|
||||
* Results:
|
||||
* TRUE on success, FALSE on failure.
|
||||
*
|
||||
* Side effects:
|
||||
* None
|
||||
*
|
||||
*-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
Bool
|
||||
DynBuf_Copy(DynBuf *src, // IN
|
||||
DynBuf *dest) // OUT
|
||||
{
|
||||
ASSERT(src);
|
||||
ASSERT(dest);
|
||||
ASSERT(!dest->data);
|
||||
|
||||
dest->data = malloc(src->allocated);
|
||||
|
||||
if (dest->data == NULL) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
dest->size = src->size;
|
||||
dest->allocated = src->allocated;
|
||||
|
||||
memcpy(dest->data, src->data, src->size);
|
||||
|
||||
return TRUE;
|
||||
}
|
336
Godeps/_workspace/src/github.com/sigma/vmw-guestinfo/bridge/hostinfo.c
generated
vendored
Normal file
336
Godeps/_workspace/src/github.com/sigma/vmw-guestinfo/bridge/hostinfo.c
generated
vendored
Normal file
@@ -0,0 +1,336 @@
|
||||
/*********************************************************
|
||||
* Copyright (C) 1998-2015 VMware, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published
|
||||
* by the Free Software Foundation version 2.1 and no later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
*********************************************************/
|
||||
|
||||
/*
|
||||
* hostinfo.c --
|
||||
*
|
||||
* Platform-independent code that calls into hostinfo<OS>-specific
|
||||
* code.
|
||||
*/
|
||||
|
||||
#include "vmware.h"
|
||||
#include <string.h>
|
||||
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
#include "cpuid_info.h"
|
||||
#endif
|
||||
#include "hostinfo.h"
|
||||
#include "hostinfoInt.h"
|
||||
#include "util.h"
|
||||
/* #include "str.h" */
|
||||
#include <stdio.h>
|
||||
#define Str_Sprintf snprintf
|
||||
#include "dynbuf.h"
|
||||
#include "backdoor_def.h"
|
||||
|
||||
/*
|
||||
* #define LOGLEVEL_MODULE hostinfo
|
||||
* #include "loglevel_user.h"
|
||||
*/
|
||||
#define LGPFX "HOSTINFO:"
|
||||
|
||||
|
||||
/*
|
||||
* HostinfoOSData caches its returned value.
|
||||
*/
|
||||
|
||||
volatile Bool HostinfoOSNameCacheValid = FALSE;
|
||||
char HostinfoCachedOSName[MAX_OS_NAME_LEN];
|
||||
char HostinfoCachedOSFullName[MAX_OS_FULLNAME_LEN];
|
||||
|
||||
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
/*
|
||||
*-----------------------------------------------------------------------------
|
||||
*
|
||||
* HostInfoGetCpuidStrSection --
|
||||
*
|
||||
* Append a section (either low or high) of CPUID as a string in DynBuf.
|
||||
* E.g.
|
||||
* 00000000:00000005756E65476C65746E49656E69-
|
||||
* 00000001:00000F4A000208000000649DBFEBFBFF-
|
||||
* or
|
||||
* 80000000:80000008000000000000000000000000-
|
||||
* 80000001:00000000000000000000000120100000-
|
||||
* 80000008:00003024000000000000000000000000-
|
||||
*
|
||||
* The returned eax of args[0] is used to determine the upper bound for
|
||||
* the following input arguments. And the input args should be in
|
||||
* ascending order.
|
||||
*
|
||||
* Results:
|
||||
* None. The string will be appended in buf.
|
||||
*
|
||||
* Side effect:
|
||||
* None
|
||||
*
|
||||
*-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static void
|
||||
HostInfoGetCpuidStrSection(const uint32 args[], // IN: input eax arguments
|
||||
const size_t args_size, // IN: size of the argument array
|
||||
DynBuf *buf) // IN/OUT: result string in DynBuf
|
||||
{
|
||||
static const char format[] = "%08X:%08X%08X%08X%08X-";
|
||||
CPUIDRegs reg;
|
||||
uint32 max_arg;
|
||||
char temp[64];
|
||||
int i;
|
||||
|
||||
__GET_CPUID(args[0], ®);
|
||||
max_arg = reg.eax;
|
||||
if (max_arg < args[0]) {
|
||||
Warning(LGPFX" No CPUID information available. Based = %08X.\n",
|
||||
args[0]);
|
||||
return;
|
||||
}
|
||||
DynBuf_Append(buf, temp,
|
||||
Str_Sprintf(temp, sizeof temp, format, args[0], reg.eax,
|
||||
reg.ebx, reg.ecx, reg.edx));
|
||||
|
||||
for (i = 1; i < args_size && args[i] <= max_arg; i++) {
|
||||
ASSERT(args[i] > args[i - 1]); // Ascending order.
|
||||
__GET_CPUID(args[i], ®);
|
||||
|
||||
DynBuf_Append(buf, temp,
|
||||
Str_Sprintf(temp, sizeof temp, format, args[i], reg.eax,
|
||||
reg.ebx, reg.ecx, reg.edx));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*-----------------------------------------------------------------------------
|
||||
*
|
||||
* Hostinfo_GetCpuidStr --
|
||||
*
|
||||
* Get the basic and extended CPUID as a string. E.g.
|
||||
* 00000000:00000005756E65476C65746E49656E69-
|
||||
* 00000001:00000F4A000208000000649DBFEBFBFF-
|
||||
* 80000000:80000008000000000000000000000000-
|
||||
* 80000001:00000000000000000000000120100000-
|
||||
* 80000008:00003024000000000000000000000000
|
||||
*
|
||||
* If the extended CPUID is not available, only returns the basic CPUID.
|
||||
*
|
||||
* Results:
|
||||
* The CPUID string if the processor supports the CPUID instruction and
|
||||
* this is a processor we recognize. It should never fail, since it
|
||||
* would at least return leaf 0. Caller needs to free the returned string.
|
||||
*
|
||||
* Side effect:
|
||||
* None
|
||||
*
|
||||
*-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
char *
|
||||
Hostinfo_GetCpuidStr(void)
|
||||
{
|
||||
static const uint32 basic_args[] = {0x0, 0x1, 0xa};
|
||||
static const uint32 extended_args[] = {0x80000000, 0x80000001, 0x80000008};
|
||||
DynBuf buf;
|
||||
char *result;
|
||||
|
||||
DynBuf_Init(&buf);
|
||||
|
||||
HostInfoGetCpuidStrSection(basic_args, ARRAYSIZE(basic_args), &buf);
|
||||
HostInfoGetCpuidStrSection(extended_args, ARRAYSIZE(extended_args), &buf);
|
||||
|
||||
// Trim buffer and set NULL character to replace last '-'.
|
||||
DynBuf_Trim(&buf);
|
||||
result = (char*)DynBuf_Get(&buf);
|
||||
ASSERT(result && result[0]); // We should at least get result from eax = 0x0.
|
||||
result[DynBuf_GetSize(&buf) - 1] = '\0';
|
||||
|
||||
return DynBuf_Detach(&buf);
|
||||
}
|
||||
#endif // defined(__i386__) || defined(__x86_64__)
|
||||
|
||||
|
||||
/*
|
||||
*-----------------------------------------------------------------------------
|
||||
*
|
||||
* Hostinfo_GetCpuid --
|
||||
*
|
||||
* Get cpuid information for a CPU. Which CPU the information is for
|
||||
* depends on the OS scheduler. We are assuming that all CPUs in
|
||||
* the system have identical numbers of cores and threads.
|
||||
*
|
||||
* Results:
|
||||
* TRUE if the processor supports the cpuid instruction and this
|
||||
* is a process we recognize, FALSE otherwise.
|
||||
*
|
||||
* Side effect:
|
||||
* None
|
||||
*
|
||||
*-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
Bool
|
||||
Hostinfo_GetCpuid(HostinfoCpuIdInfo *info) // OUT
|
||||
{
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
CPUIDSummary cpuid;
|
||||
CPUIDRegs id0;
|
||||
|
||||
/*
|
||||
* Can't do cpuid = {0} as an initializer above because gcc throws
|
||||
* some idiotic warning.
|
||||
*/
|
||||
|
||||
memset(&cpuid, 0, sizeof(cpuid));
|
||||
|
||||
/*
|
||||
* Get basic and extended CPUID info.
|
||||
*/
|
||||
|
||||
__GET_CPUID(0, &id0);
|
||||
|
||||
cpuid.id0.numEntries = id0.eax;
|
||||
|
||||
if (0 == cpuid.id0.numEntries) {
|
||||
Warning(LGPFX" No CPUID information available.\n");
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
*(uint32*)(cpuid.id0.name + 0) = id0.ebx;
|
||||
*(uint32*)(cpuid.id0.name + 4) = id0.edx;
|
||||
*(uint32*)(cpuid.id0.name + 8) = id0.ecx;
|
||||
*(uint32*)(cpuid.id0.name + 12) = 0;
|
||||
|
||||
__GET_CPUID(1, (CPUIDRegs*)&cpuid.id1);
|
||||
__GET_CPUID(0xa, (CPUIDRegs*)&cpuid.ida);
|
||||
__GET_CPUID(0x80000000, (CPUIDRegs*)&cpuid.id80);
|
||||
__GET_CPUID(0x80000001, (CPUIDRegs*)&cpuid.id81);
|
||||
__GET_CPUID(0x80000008, (CPUIDRegs*)&cpuid.id88);
|
||||
|
||||
/*
|
||||
* Calculate vendor information.
|
||||
*/
|
||||
|
||||
if (0 == strcmp(cpuid.id0.name, CPUID_INTEL_VENDOR_STRING_FIXED)) {
|
||||
info->vendor = CPUID_VENDOR_INTEL;
|
||||
} else if (strcmp(cpuid.id0.name, CPUID_AMD_VENDOR_STRING_FIXED) == 0) {
|
||||
info->vendor = CPUID_VENDOR_AMD;
|
||||
} else {
|
||||
info->vendor = CPUID_VENDOR_UNKNOWN;
|
||||
}
|
||||
/*
|
||||
* Pull out versioning and feature information.
|
||||
*/
|
||||
|
||||
info->version = cpuid.id1.version;
|
||||
info->family = CPUID_GET(1, EAX, FAMILY, cpuid.id1.version);
|
||||
info->model = CPUID_GET(1, EAX, MODEL, cpuid.id1.version);
|
||||
info->stepping = CPUID_GET(1, EAX, STEPPING, cpuid.id1.version);
|
||||
info->type = (cpuid.id1.version >> 12) & 0x0003;
|
||||
|
||||
info->extfeatures = cpuid.id1.ecxFeatures;
|
||||
info->features = cpuid.id1.edxFeatures;
|
||||
|
||||
return TRUE;
|
||||
#else // defined(__i386__) || defined(__x86_64__)
|
||||
return FALSE;
|
||||
#endif // defined(__i386__) || defined(__x86_64__)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*-----------------------------------------------------------------------------
|
||||
*
|
||||
* Hostinfo_GetOSName --
|
||||
*
|
||||
* Query the operating system and build a string to identify it.
|
||||
*
|
||||
* Examples:
|
||||
* Windows: <OS NAME> <SERVICE PACK> (Build <BUILD_NUMBER>)
|
||||
* example: Windows XP Professional Service Pack 2 (Build 2600)
|
||||
*
|
||||
* Linux: <OS NAME> <OS RELEASE> <SPECIFIC_DISTRO_INFO>
|
||||
* example: Linux 2.4.18-3 Red Hat Linux release 7.3 (Valhalla)
|
||||
*
|
||||
* Mac OS: <OS NAME> <OS VERSION> (<BUILD VERSION>) <KERNEL NAME> <KERNEL RELEASE>
|
||||
* example: Mac OS X 10.8.5 (12F45) Darwin 12.5.0
|
||||
*
|
||||
* Return value:
|
||||
* NULL Unable to obtain the OS name.
|
||||
* !NULL The OS name. The caller is responsible for freeing it.
|
||||
*
|
||||
* Side effects:
|
||||
* Memory is allocated.
|
||||
*
|
||||
*-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* char *
|
||||
* Hostinfo_GetOSName(void)
|
||||
* {
|
||||
* char *name;
|
||||
* Bool data = HostinfoOSNameCacheValid ? TRUE : HostinfoOSData();
|
||||
*
|
||||
* if (data) {
|
||||
* name = Util_SafeStrdup(HostinfoCachedOSFullName);
|
||||
* } else {
|
||||
* name = NULL;
|
||||
* }
|
||||
*
|
||||
* return name;
|
||||
* }
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/*
|
||||
*-----------------------------------------------------------------------------
|
||||
*
|
||||
* Hostinfo_GetOSGuestString --
|
||||
*
|
||||
* Query the operating system and build a string to identify it. The
|
||||
* returned string is the same as you'd see in a VM's .vmx file.
|
||||
*
|
||||
* Return value:
|
||||
* NULL Unable to obtain the OS name.
|
||||
* !NULL The OS name. The caller is responsible for freeing it.
|
||||
*
|
||||
* Side effects:
|
||||
* Memory is allocated.
|
||||
*
|
||||
*-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* char *
|
||||
* Hostinfo_GetOSGuestString(void)
|
||||
* {
|
||||
* char *name;
|
||||
* Bool data = HostinfoOSNameCacheValid ? TRUE : HostinfoOSData();
|
||||
*
|
||||
* if (data) {
|
||||
* name = Util_SafeStrdup(HostinfoCachedOSName);
|
||||
* } else {
|
||||
* name = NULL;
|
||||
* }
|
||||
*
|
||||
* return name;
|
||||
* }
|
||||
*/
|
||||
|
686
Godeps/_workspace/src/github.com/sigma/vmw-guestinfo/bridge/hostinfoHV.c
generated
vendored
Normal file
686
Godeps/_workspace/src/github.com/sigma/vmw-guestinfo/bridge/hostinfoHV.c
generated
vendored
Normal file
@@ -0,0 +1,686 @@
|
||||
/*********************************************************
|
||||
* Copyright (C) 2011-2015 VMware, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published
|
||||
* by the Free Software Foundation version 2.1 and no later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
*********************************************************/
|
||||
|
||||
/*
|
||||
* hostinfoHV.c --
|
||||
*
|
||||
* Code to detect different hypervisors and features.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "vmware.h"
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
# include "cpuid_info.h"
|
||||
# include "backdoor_def.h"
|
||||
# include "backdoor_types.h"
|
||||
#endif
|
||||
#include "hostinfo.h"
|
||||
#include "util.h"
|
||||
|
||||
#define LGPFX "HOSTINFO:"
|
||||
/*
|
||||
* #define LOGLEVEL_MODULE hostinfo
|
||||
* #include "loglevel_user.h"
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* Hostinfo_HypervisorCPUIDSig --
|
||||
*
|
||||
* Get the hypervisor signature string from CPUID.
|
||||
*
|
||||
* Results:
|
||||
* Unqualified 16 byte nul-terminated hypervisor string
|
||||
* String may contain garbage and caller must free
|
||||
*
|
||||
* Side effects:
|
||||
* None
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
char *
|
||||
Hostinfo_HypervisorCPUIDSig(void)
|
||||
{
|
||||
uint32 *name = NULL;
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
CPUIDRegs regs;
|
||||
|
||||
__GET_CPUID(1, ®s);
|
||||
if (!CPUID_ISSET(1, ECX, HYPERVISOR, regs.ecx)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
regs.ebx = 0;
|
||||
regs.ecx = 0;
|
||||
regs.edx = 0;
|
||||
|
||||
__GET_CPUID(0x40000000, ®s);
|
||||
|
||||
if (regs.eax < 0x40000000) {
|
||||
Log(LGPFX" CPUID hypervisor bit is set, but no "
|
||||
"hypervisor vendor signature is present\n");
|
||||
}
|
||||
|
||||
name = Util_SafeMalloc(4 * sizeof *name);
|
||||
|
||||
name[0] = regs.ebx;
|
||||
name[1] = regs.ecx;
|
||||
name[2] = regs.edx;
|
||||
name[3] = 0;
|
||||
#endif // defined(__i386__) || defined(__x86_64__)
|
||||
|
||||
return (char *)name;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* Hostinfo_TouchXen --
|
||||
*
|
||||
* Check for Xen.
|
||||
*
|
||||
* Official way is to call Hostinfo_HypervisorCPUIDSig(), which
|
||||
* returns a hypervisor string. This is a secondary check
|
||||
* that guards against a backdoor failure. See PR156185,
|
||||
* http://xenbits.xensource.com/xen-unstable.hg?file/6a383beedf83/tools/misc/xen-detect.c
|
||||
* (Canonical way is /proc/xen, but CPUID is better).
|
||||
*
|
||||
* Results:
|
||||
* TRUE if we are running in a Xen dom0 or domU.
|
||||
* Linux:
|
||||
* Illegal instruction exception on real hardware.
|
||||
* Obscure Xen implementations might return FALSE.
|
||||
* Windows:
|
||||
* FALSE on real hardware.
|
||||
*
|
||||
* Side effects:
|
||||
* Linux: Will raise exception on native hardware.
|
||||
* Windows: None.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
Bool
|
||||
Hostinfo_TouchXen(void)
|
||||
{
|
||||
#if defined(linux) && (defined(__i386__) || defined(__x86_64__))
|
||||
#define XEN_CPUID 0x40000000
|
||||
CPUIDRegs regs;
|
||||
uint32 name[4];
|
||||
|
||||
/*
|
||||
* PV mode: ud2a "xen" cpuid (faults on native hardware).
|
||||
* (Only Linux can run PV, so skip others here).
|
||||
* Since PV cannot trap CPUID, this is a Xen hook.
|
||||
*/
|
||||
|
||||
regs.eax = XEN_CPUID;
|
||||
__asm__ __volatile__(
|
||||
"xchgl %%ebx, %0" "\n\t"
|
||||
"ud2a ; .ascii \"xen\" ; cpuid" "\n\t"
|
||||
"xchgl %%ebx, %0"
|
||||
: "=&r" (regs.ebx), "=&c" (regs.ecx), "=&d" (regs.edx)
|
||||
: "a" (regs.eax)
|
||||
);
|
||||
|
||||
name[0] = regs.ebx;
|
||||
name[1] = regs.ecx;
|
||||
name[2] = regs.edx;
|
||||
name[3] = 0;
|
||||
|
||||
if (0 == strcmp(CPUID_XEN_HYPERVISOR_VENDOR_STRING, (const char*)name)) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Passed checks. But native and anything non-Xen would #UD before here. */
|
||||
NOT_TESTED();
|
||||
Log("Xen detected but hypervisor unrecognized (Xen variant?)\n");
|
||||
Log("CPUID 0x4000 0000: eax=%x ebx=%x ecx=%x edx=%x\n",
|
||||
regs.eax, regs.ebx, regs.ecx, regs.edx);
|
||||
#endif
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* Hostinfo_SLC64Supported --
|
||||
*
|
||||
* Access the backdoor with an SLC64 control query. This is used
|
||||
* to determine if we are running in a VM that supports SLC64.
|
||||
* This function should only be called after determining that the
|
||||
* backdoor is present with Hostinfo_TouchBackdoor().
|
||||
*
|
||||
* Results:
|
||||
* TRUE if the outer VM supports SLC64.
|
||||
* FALSE otherwise.
|
||||
*
|
||||
* Side effects:
|
||||
* Exception if not in a VM, so don't do that!
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
Bool
|
||||
Hostinfo_SLC64Supported(void)
|
||||
{
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
return Hostinfo_VCPUInfoBackdoor(BDOOR_CMD_VCPU_SLC64);
|
||||
#else
|
||||
return FALSE;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* Hostinfo_NestedHVReplaySupported --
|
||||
*
|
||||
* Access the backdoor with a HV replay control query. This is used
|
||||
* to determine if we are running in a VM that supports nested HV replay.
|
||||
* This function should only be called after determining that the
|
||||
* backdoor is present with Hostinfo_TouchBackdoor().
|
||||
*
|
||||
* Results:
|
||||
* TRUE if the outer VM supports nexted HV replay.
|
||||
* FALSE otherwise.
|
||||
*
|
||||
* Side effects:
|
||||
* Exception if not in a VM, so don't do that!
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
Bool
|
||||
Hostinfo_NestedHVReplaySupported(void)
|
||||
{
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
return Hostinfo_VCPUInfoBackdoor(BDOOR_CMD_VCPU_HV_REPLAY_OK);
|
||||
#else
|
||||
return FALSE;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* Hostinfo_SynchronizedVTSCs --
|
||||
*
|
||||
* Access the backdoor to determine if the VCPUs' TSCs are
|
||||
* synchronized.
|
||||
*
|
||||
* Results:
|
||||
* TRUE if the outer VM provides synchronized VTSCs.
|
||||
* FALSE otherwise.
|
||||
*
|
||||
* Side effects:
|
||||
* Exception if not in a VM, so don't do that!
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
Bool
|
||||
Hostinfo_SynchronizedVTSCs(void)
|
||||
{
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
return Hostinfo_VCPUInfoBackdoor(BDOOR_CMD_VCPU_SYNC_VTSCS);
|
||||
#else
|
||||
return FALSE;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#if defined(_WIN32)
|
||||
|
||||
#if defined(_WIN64)
|
||||
// from touchBackdoorMasm64.asm
|
||||
void Hostinfo_BackdoorInOut(Backdoor_proto *myBp);
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* Hostinfo_TouchBackDoor --
|
||||
*
|
||||
* Access the backdoor. This is used to determine if we are
|
||||
* running in a VM or on a physical host. On a physical host
|
||||
* this should generate a GP which we catch and thereby determine
|
||||
* that we are not in a VM. However some OSes do not handle the
|
||||
* GP correctly and the process continues running returning garbage.
|
||||
* In this case we check the EBX register which should be
|
||||
* BDOOR_MAGIC if the IN was handled in a VM. Based on this we
|
||||
* return either TRUE or FALSE.
|
||||
*
|
||||
* Results:
|
||||
* TRUE if we succesfully accessed the backdoor, FALSE or segfault
|
||||
* if not.
|
||||
*
|
||||
* Side effects:
|
||||
* Exception if not in a VM.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
Bool
|
||||
Hostinfo_TouchBackDoor(void)
|
||||
{
|
||||
uint32 ebxval;
|
||||
|
||||
#if defined(_WIN64)
|
||||
Backdoor_proto bp;
|
||||
|
||||
bp.in.ax.quad = BDOOR_MAGIC;
|
||||
bp.in.size = ~BDOOR_MAGIC;
|
||||
bp.in.cx.quad = BDOOR_CMD_GETVERSION;
|
||||
bp.in.dx.quad = BDOOR_PORT;
|
||||
|
||||
Hostinfo_BackdoorInOut(&bp);
|
||||
|
||||
ebxval = bp.out.bx.words.low;
|
||||
#else // _WIN64
|
||||
_asm {
|
||||
push edx
|
||||
push ecx
|
||||
push ebx
|
||||
mov ecx, BDOOR_CMD_GETVERSION
|
||||
mov ebx, ~BDOOR_MAGIC
|
||||
mov eax, BDOOR_MAGIC
|
||||
mov dx, BDOOR_PORT
|
||||
in eax, dx
|
||||
mov ebxval, ebx
|
||||
pop ebx
|
||||
pop ecx
|
||||
pop edx
|
||||
}
|
||||
#endif // _WIN64
|
||||
|
||||
return (ebxval == BDOOR_MAGIC) ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* Hostinfo_TouchVirtualPC --
|
||||
*
|
||||
* Access MS Virtual PC's backdoor. This is used to determine if
|
||||
* we are running in a MS Virtual PC or on a physical host. Works
|
||||
* the same as Hostinfo_TouchBackDoor, except the entry to MS VPC
|
||||
* is an invalid opcode instead or writing to a port. Since
|
||||
* MS VPC is 32-bit only, the WIN64 path returns FALSE.
|
||||
* See: See: http://www.codeproject.com/KB/system/VmDetect.aspx
|
||||
*
|
||||
* Results:
|
||||
* TRUE if we succesfully accessed MS Virtual PC, FALSE or
|
||||
* segfault if not.
|
||||
*
|
||||
* Side effects:
|
||||
* Exception if not in a VM.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
Bool
|
||||
Hostinfo_TouchVirtualPC(void)
|
||||
{
|
||||
#if defined(_WIN64)
|
||||
return FALSE; // MS Virtual PC is 32-bit only
|
||||
#else // _WIN32
|
||||
uint32 ebxval;
|
||||
|
||||
_asm {
|
||||
push ebx
|
||||
mov ebx, 0
|
||||
|
||||
mov eax, 1 // Virtual PC function number
|
||||
|
||||
// execute invalid opcode to call into MS Virtual PC
|
||||
|
||||
__emit 0Fh
|
||||
__emit 3Fh
|
||||
__emit 07h
|
||||
__emit 0Bh
|
||||
|
||||
mov ebxval, ebx
|
||||
pop ebx
|
||||
}
|
||||
return !ebxval; // ebx is zero if inside Virtual PC
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* Hostinfo_NestingSupported --
|
||||
*
|
||||
* Access the backdoor with a nesting control query. This is used
|
||||
* to determine if we are running in a VM that supports nesting.
|
||||
* This function should only be called after determining that the
|
||||
* backdoor is present with Hostinfo_TouchBackdoor().
|
||||
*
|
||||
* Results:
|
||||
* TRUE if the outer VM supports nesting.
|
||||
* FALSE otherwise.
|
||||
*
|
||||
* Side effects:
|
||||
* Exception if not in a VM, so don't do that!
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
Bool
|
||||
Hostinfo_NestingSupported(void)
|
||||
{
|
||||
uint32 cmd = NESTING_CONTROL_QUERY << 16 | BDOOR_CMD_NESTING_CONTROL;
|
||||
uint32 result;
|
||||
|
||||
#if defined(_WIN64)
|
||||
Backdoor_proto bp;
|
||||
|
||||
bp.in.ax.quad = BDOOR_MAGIC;
|
||||
bp.in.cx.quad = cmd;
|
||||
bp.in.dx.quad = BDOOR_PORT;
|
||||
|
||||
Hostinfo_BackdoorInOut(&bp);
|
||||
|
||||
result = bp.out.ax.words.low;
|
||||
#else
|
||||
_asm {
|
||||
push edx
|
||||
push ecx
|
||||
mov ecx, cmd
|
||||
mov eax, BDOOR_MAGIC
|
||||
mov dx, BDOOR_PORT
|
||||
in eax, dx
|
||||
mov result, eax
|
||||
pop ecx
|
||||
pop edx
|
||||
}
|
||||
#endif
|
||||
|
||||
if (result >= NESTING_CONTROL_QUERY && result != ~0U) {
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* Hostinfo_VCPUInfoBackdoor --
|
||||
*
|
||||
* Access the backdoor with an VCPU info query. This is used to
|
||||
* determine whether a VCPU supports a particular feature,
|
||||
* determined by 'bit'. This function should only be called after
|
||||
* determining that the backdoor is present with
|
||||
* Hostinfo_TouchBackdoor().
|
||||
*
|
||||
* Results:
|
||||
* TRUE if the outer VM supports the feature.
|
||||
* FALSE otherwise.
|
||||
*
|
||||
* Side effects:
|
||||
* Exception if not in a VM, so don't do that!
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
Bool
|
||||
Hostinfo_VCPUInfoBackdoor(unsigned bit)
|
||||
{
|
||||
uint32 cmd = BDOOR_CMD_GET_VCPU_INFO;
|
||||
uint32 result;
|
||||
|
||||
#if defined(_WIN64)
|
||||
Backdoor_proto bp;
|
||||
|
||||
bp.in.ax.quad = BDOOR_MAGIC;
|
||||
bp.in.cx.quad = cmd;
|
||||
bp.in.dx.quad = BDOOR_PORT;
|
||||
|
||||
Hostinfo_BackdoorInOut(&bp);
|
||||
|
||||
result = bp.out.ax.words.low;
|
||||
#else
|
||||
_asm {
|
||||
push edx
|
||||
push ecx
|
||||
mov ecx, cmd
|
||||
mov eax, BDOOR_MAGIC
|
||||
mov dx, BDOOR_PORT
|
||||
in eax, dx
|
||||
mov result, eax
|
||||
pop ecx
|
||||
pop edx
|
||||
}
|
||||
#endif
|
||||
/* If reserved bit is 1, this command wasn't implemented. */
|
||||
return (result & (1 << BDOOR_CMD_VCPU_RESERVED)) == 0 &&
|
||||
(result & (1 << bit)) != 0;
|
||||
}
|
||||
|
||||
|
||||
#else
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* Hostinfo_TouchBackDoor --
|
||||
*
|
||||
* Access the backdoor. This is used to determine if we are
|
||||
* running in a VM or on a physical host. On a physical host
|
||||
* this should generate a GP which we catch and thereby determine
|
||||
* that we are not in a VM. However some OSes do not handle the
|
||||
* GP correctly and the process continues running returning garbage.
|
||||
* In this case we check the EBX register which should be
|
||||
* BDOOR_MAGIC if the IN was handled in a VM. Based on this we
|
||||
* return either TRUE or FALSE.
|
||||
*
|
||||
* Results:
|
||||
* TRUE if we succesfully accessed the backdoor, FALSE or segfault
|
||||
* if not.
|
||||
*
|
||||
* Side effects:
|
||||
* Exception if not in a VM.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
Bool
|
||||
Hostinfo_TouchBackDoor(void)
|
||||
{
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
uint32 eax;
|
||||
uint32 ebx;
|
||||
uint32 ecx;
|
||||
|
||||
__asm__ __volatile__(
|
||||
# if defined __PIC__ && !vm_x86_64 // %ebx is reserved by the compiler.
|
||||
"xchgl %%ebx, %1" "\n\t"
|
||||
"inl %%dx, %%eax" "\n\t"
|
||||
"xchgl %%ebx, %1"
|
||||
: "=a" (eax),
|
||||
"=&rm" (ebx),
|
||||
# else
|
||||
"inl %%dx, %%eax"
|
||||
: "=a" (eax),
|
||||
"=b" (ebx),
|
||||
# endif
|
||||
"=c" (ecx)
|
||||
: "0" (BDOOR_MAGIC),
|
||||
"1" (~BDOOR_MAGIC),
|
||||
"2" (BDOOR_CMD_GETVERSION),
|
||||
"d" (BDOOR_PORT)
|
||||
);
|
||||
if (ebx == BDOOR_MAGIC) {
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* Hostinfo_TouchVirtualPC --
|
||||
*
|
||||
* Access MS Virtual PC's backdoor. This is used to determine if
|
||||
* we are running in a MS Virtual PC or on a physical host. Works
|
||||
* the same as Hostinfo_TouchBackDoor, except the entry to MS VPC
|
||||
* is an invalid opcode instead or writing to a port. Since
|
||||
* MS VPC is 32-bit only, the 64-bit path returns FALSE.
|
||||
* See: http://www.codeproject.com/KB/system/VmDetect.aspx
|
||||
*
|
||||
* Results:
|
||||
* TRUE if we succesfully accessed MS Virtual PC, FALSE or
|
||||
* segfault if not.
|
||||
*
|
||||
* Side effects:
|
||||
* Exception if not in a VM.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
Bool
|
||||
Hostinfo_TouchVirtualPC(void)
|
||||
{
|
||||
#if defined vm_x86_64
|
||||
return FALSE;
|
||||
#else
|
||||
|
||||
uint32 ebxval;
|
||||
|
||||
__asm__ __volatile__ (
|
||||
# if defined __PIC__ // %ebx is reserved by the compiler.
|
||||
"xchgl %%ebx, %1" "\n\t"
|
||||
".long 0x0B073F0F" "\n\t"
|
||||
"xchgl %%ebx, %1"
|
||||
: "=&rm" (ebxval)
|
||||
: "a" (1),
|
||||
"0" (0)
|
||||
# else
|
||||
".long 0x0B073F0F"
|
||||
: "=b" (ebxval)
|
||||
: "a" (1),
|
||||
"b" (0)
|
||||
# endif
|
||||
);
|
||||
return !ebxval; // %%ebx is zero if inside Virtual PC
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* Hostinfo_NestingSupported --
|
||||
*
|
||||
* Access the backdoor with a nesting control query. This is used
|
||||
* to determine if we are running inside a VM that supports nesting.
|
||||
* This function should only be called after determining that the
|
||||
* backdoor is present with Hostinfo_TouchBackdoor().
|
||||
*
|
||||
* Results:
|
||||
* TRUE if the outer VM supports nesting.
|
||||
* FALSE otherwise.
|
||||
*
|
||||
* Side effects:
|
||||
* Exception if not in a VM, so don't do that!
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
Bool
|
||||
Hostinfo_NestingSupported(void)
|
||||
{
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
uint32 cmd = NESTING_CONTROL_QUERY << 16 | BDOOR_CMD_NESTING_CONTROL;
|
||||
uint32 result;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"inl %%dx, %%eax"
|
||||
: "=a" (result)
|
||||
: "0" (BDOOR_MAGIC),
|
||||
"c" (cmd),
|
||||
"d" (BDOOR_PORT)
|
||||
);
|
||||
|
||||
if (result >= NESTING_CONTROL_QUERY && result != ~0U) {
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* Hostinfo_VCPUInfoBackdoor --
|
||||
*
|
||||
* Access the backdoor with an VCPU info query. This is used to
|
||||
* determine whether a VCPU supports a particular feature,
|
||||
* determined by 'bit'. This function should only be called after
|
||||
* determining that the backdoor is present with
|
||||
* Hostinfo_TouchBackdoor().
|
||||
*
|
||||
* Results:
|
||||
* TRUE if the outer VM supports the feature.
|
||||
* FALSE otherwise.
|
||||
*
|
||||
* Side effects:
|
||||
* Exception if not in a VM, so don't do that!
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
Bool
|
||||
Hostinfo_VCPUInfoBackdoor(unsigned bit)
|
||||
{
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
uint32 result;
|
||||
__asm__ __volatile__(
|
||||
"inl %%dx, %%eax"
|
||||
: "=a" (result)
|
||||
: "0" (BDOOR_MAGIC),
|
||||
"c" (BDOOR_CMD_GET_VCPU_INFO),
|
||||
"d" (BDOOR_PORT)
|
||||
);
|
||||
/* If reserved bit is 1, this command wasn't implemented. */
|
||||
return (result & (1 << BDOOR_CMD_VCPU_RESERVED)) == 0 &&
|
||||
(result & (1 << bit)) != 0;
|
||||
#endif
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
605
Godeps/_workspace/src/github.com/sigma/vmw-guestinfo/bridge/message.c
generated
vendored
Normal file
605
Godeps/_workspace/src/github.com/sigma/vmw-guestinfo/bridge/message.c
generated
vendored
Normal file
@@ -0,0 +1,605 @@
|
||||
/*********************************************************
|
||||
* Copyright (C) 1999-2015 VMware, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published
|
||||
* by the Free Software Foundation version 2.1 and no later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
*********************************************************/
|
||||
|
||||
/*********************************************************
|
||||
* The contents of this file are subject to the terms of the Common
|
||||
* Development and Distribution License (the "License") version 1.0
|
||||
* and no later version. You may not use this file except in
|
||||
* compliance with the License.
|
||||
*
|
||||
* You can obtain a copy of the License at
|
||||
* http://www.opensource.org/licenses/cddl1.php
|
||||
*
|
||||
* See the License for the specific language governing permissions
|
||||
* and limitations under the License.
|
||||
*
|
||||
*********************************************************/
|
||||
|
||||
/*
|
||||
* message.c --
|
||||
*
|
||||
* Second layer of the internal communication channel between guest
|
||||
* applications and vmware
|
||||
*
|
||||
* Build a generic messaging system between guest applications and vmware.
|
||||
*
|
||||
* The protocol is not completely symmetrical, because:
|
||||
* . basic requests can only be sent by guest applications (when vmware
|
||||
* wants to post a message to a guest application, the message will be
|
||||
* really fetched only when the guest application will poll for new
|
||||
* available messages)
|
||||
* . several guest applications can talk to vmware, while the contrary is
|
||||
* not true
|
||||
*
|
||||
* Operations that are not atomic (in terms of number of backdoor calls)
|
||||
* can be aborted by vmware if a checkpoint/restore occurs in the middle of
|
||||
* such an operation. This layer takes care of retrying those operations.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if defined(__KERNEL__) || defined(_KERNEL) || defined(KERNEL)
|
||||
# include "kernelStubs.h"
|
||||
#else
|
||||
# include <stdio.h>
|
||||
# include <stdlib.h>
|
||||
# include "debug.h"
|
||||
#endif
|
||||
|
||||
#include "backdoor_def.h"
|
||||
#include "guest_msg_def.h"
|
||||
#include "backdoor.h"
|
||||
#include "message.h"
|
||||
|
||||
|
||||
#if defined(MESSAGE_DEBUG)
|
||||
# define MESSAGE_LOG(...) Warning(__VA_ARGS__)
|
||||
#else
|
||||
# define MESSAGE_LOG(...)
|
||||
#endif
|
||||
|
||||
/* The channel object */
|
||||
struct Message_Channel {
|
||||
/* Identifier */
|
||||
uint16 id;
|
||||
|
||||
/* Reception buffer */
|
||||
/* Data */
|
||||
unsigned char *in;
|
||||
/* Allocated size */
|
||||
size_t inAlloc;
|
||||
|
||||
/* The cookie */
|
||||
uint32 cookieHigh;
|
||||
uint32 cookieLow;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
*-----------------------------------------------------------------------------
|
||||
*
|
||||
* Message_Open --
|
||||
*
|
||||
* Open a communication channel
|
||||
*
|
||||
* Result:
|
||||
* An allocated Message_Channel on success
|
||||
* NULL on failure
|
||||
*
|
||||
* Side-effects:
|
||||
* None
|
||||
*
|
||||
*-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
Message_Channel *
|
||||
Message_Open(uint32 proto) // IN
|
||||
{
|
||||
Message_Channel *chan;
|
||||
uint32 flags;
|
||||
Backdoor_proto bp;
|
||||
|
||||
chan = (Message_Channel *)malloc(sizeof(*chan));
|
||||
if (chan == NULL) {
|
||||
goto error_quit;
|
||||
}
|
||||
|
||||
flags = GUESTMSG_FLAG_COOKIE;
|
||||
retry:
|
||||
/* IN: Type */
|
||||
bp.in.cx.halfs.high = MESSAGE_TYPE_OPEN;
|
||||
/* IN: Magic number of the protocol and flags */
|
||||
bp.in.size = proto | flags;
|
||||
|
||||
bp.in.cx.halfs.low = BDOOR_CMD_MESSAGE;
|
||||
Backdoor(&bp);
|
||||
|
||||
/* OUT: Status */
|
||||
if ((bp.in.cx.halfs.high & MESSAGE_STATUS_SUCCESS) == 0) {
|
||||
if (flags) {
|
||||
/* Cookies not supported. Fall back to no cookie. --hpreg */
|
||||
flags = 0;
|
||||
goto retry;
|
||||
}
|
||||
|
||||
MESSAGE_LOG("Message: Unable to open a communication channel\n");
|
||||
goto error_quit;
|
||||
}
|
||||
|
||||
/* OUT: Id and cookie */
|
||||
chan->id = bp.in.dx.halfs.high;
|
||||
chan->cookieHigh = bp.out.si.word;
|
||||
chan->cookieLow = bp.out.di.word;
|
||||
|
||||
/* Initialize the channel */
|
||||
chan->in = NULL;
|
||||
chan->inAlloc = 0;
|
||||
|
||||
return chan;
|
||||
|
||||
error_quit:
|
||||
free(chan);
|
||||
chan = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*-----------------------------------------------------------------------------
|
||||
*
|
||||
* Message_Send --
|
||||
*
|
||||
* Send a message over a communication channel
|
||||
*
|
||||
* Result:
|
||||
* TRUE on success
|
||||
* FALSE on failure (the message is discarded by vmware)
|
||||
*
|
||||
* Side-effects:
|
||||
* None
|
||||
*
|
||||
*-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
Bool
|
||||
Message_Send(Message_Channel *chan, // IN/OUT
|
||||
const unsigned char *buf, // IN
|
||||
size_t bufSize) // IN
|
||||
{
|
||||
const unsigned char *myBuf;
|
||||
size_t myBufSize;
|
||||
Backdoor_proto bp;
|
||||
|
||||
retry:
|
||||
myBuf = buf;
|
||||
myBufSize = bufSize;
|
||||
|
||||
/*
|
||||
* Send the size.
|
||||
*/
|
||||
|
||||
/* IN: Type */
|
||||
bp.in.cx.halfs.high = MESSAGE_TYPE_SENDSIZE;
|
||||
/* IN: Id and cookie */
|
||||
bp.in.dx.halfs.high = chan->id;
|
||||
bp.in.si.word = chan->cookieHigh;
|
||||
bp.in.di.word = chan->cookieLow;
|
||||
/* IN: Size */
|
||||
bp.in.size = myBufSize;
|
||||
|
||||
bp.in.cx.halfs.low = BDOOR_CMD_MESSAGE;
|
||||
Backdoor(&bp);
|
||||
|
||||
/* OUT: Status */
|
||||
if ((bp.in.cx.halfs.high & MESSAGE_STATUS_SUCCESS) == 0) {
|
||||
MESSAGE_LOG("Message: Unable to send a message over the communication "
|
||||
"channel %u\n", chan->id);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (bp.in.cx.halfs.high & MESSAGE_STATUS_HB) {
|
||||
/*
|
||||
* High-bandwidth backdoor port supported. Send the message in one
|
||||
* backdoor operation. --hpreg
|
||||
*/
|
||||
|
||||
if (myBufSize) {
|
||||
Backdoor_proto_hb bphb;
|
||||
|
||||
bphb.in.bx.halfs.low = BDOORHB_CMD_MESSAGE;
|
||||
bphb.in.bx.halfs.high = MESSAGE_STATUS_SUCCESS;
|
||||
bphb.in.dx.halfs.high = chan->id;
|
||||
bphb.in.bp.word = chan->cookieHigh;
|
||||
bphb.in.dstAddr = chan->cookieLow;
|
||||
bphb.in.size = myBufSize;
|
||||
bphb.in.srcAddr = (uintptr_t) myBuf;
|
||||
Backdoor_HbOut(&bphb);
|
||||
if ((bphb.in.bx.halfs.high & MESSAGE_STATUS_SUCCESS) == 0) {
|
||||
if ((bphb.in.bx.halfs.high & MESSAGE_STATUS_CPT) != 0) {
|
||||
/* A checkpoint occurred. Retry the operation. --hpreg */
|
||||
goto retry;
|
||||
}
|
||||
|
||||
MESSAGE_LOG("Message: Unable to send a message over the "
|
||||
"communication channel %u\n", chan->id);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* High-bandwidth backdoor port not supported. Send the message, 4 bytes
|
||||
* at a time. --hpreg
|
||||
*/
|
||||
|
||||
for (;;) {
|
||||
if (myBufSize == 0) {
|
||||
/* We are done */
|
||||
break;
|
||||
}
|
||||
|
||||
/* IN: Type */
|
||||
bp.in.cx.halfs.high = MESSAGE_TYPE_SENDPAYLOAD;
|
||||
/* IN: Id and cookie */
|
||||
bp.in.dx.halfs.high = chan->id;
|
||||
bp.in.si.word = chan->cookieHigh;
|
||||
bp.in.di.word = chan->cookieLow;
|
||||
/* IN: Piece of message */
|
||||
/*
|
||||
* Beware in case we are not allowed to read extra bytes beyond the
|
||||
* end of the buffer.
|
||||
*/
|
||||
switch (myBufSize) {
|
||||
case 1:
|
||||
bp.in.size = myBuf[0];
|
||||
myBufSize -= 1;
|
||||
break;
|
||||
case 2:
|
||||
bp.in.size = myBuf[0] | myBuf[1] << 8;
|
||||
myBufSize -= 2;
|
||||
break;
|
||||
case 3:
|
||||
bp.in.size = myBuf[0] | myBuf[1] << 8 | myBuf[2] << 16;
|
||||
myBufSize -= 3;
|
||||
break;
|
||||
default:
|
||||
bp.in.size = *(const uint32 *)myBuf;
|
||||
myBufSize -= 4;
|
||||
break;
|
||||
}
|
||||
|
||||
bp.in.cx.halfs.low = BDOOR_CMD_MESSAGE;
|
||||
Backdoor(&bp);
|
||||
|
||||
/* OUT: Status */
|
||||
if ((bp.in.cx.halfs.high & MESSAGE_STATUS_SUCCESS) == 0) {
|
||||
if ((bp.in.cx.halfs.high & MESSAGE_STATUS_CPT) != 0) {
|
||||
/* A checkpoint occurred. Retry the operation. --hpreg */
|
||||
goto retry;
|
||||
}
|
||||
|
||||
MESSAGE_LOG("Message: Unable to send a message over the "
|
||||
"communication channel %u\n", chan->id);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
myBuf += 4;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*-----------------------------------------------------------------------------
|
||||
*
|
||||
* Message_Receive --
|
||||
*
|
||||
* If vmware has posted a message for this channel, retrieve it
|
||||
*
|
||||
* Result:
|
||||
* TRUE on success (bufSize is 0 if there is no message)
|
||||
* FALSE on failure
|
||||
*
|
||||
* Side-effects:
|
||||
* None
|
||||
*
|
||||
*-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
Bool
|
||||
Message_Receive(Message_Channel *chan, // IN/OUT
|
||||
unsigned char **buf, // OUT
|
||||
size_t *bufSize) // OUT
|
||||
{
|
||||
Backdoor_proto bp;
|
||||
size_t myBufSize;
|
||||
unsigned char *myBuf;
|
||||
|
||||
retry:
|
||||
/*
|
||||
* Is there a message waiting for our retrieval?
|
||||
*/
|
||||
|
||||
/* IN: Type */
|
||||
bp.in.cx.halfs.high = MESSAGE_TYPE_RECVSIZE;
|
||||
/* IN: Id and cookie */
|
||||
bp.in.dx.halfs.high = chan->id;
|
||||
bp.in.si.word = chan->cookieHigh;
|
||||
bp.in.di.word = chan->cookieLow;
|
||||
|
||||
bp.in.cx.halfs.low = BDOOR_CMD_MESSAGE;
|
||||
Backdoor(&bp);
|
||||
|
||||
/* OUT: Status */
|
||||
if ((bp.in.cx.halfs.high & MESSAGE_STATUS_SUCCESS) == 0) {
|
||||
MESSAGE_LOG("Message: Unable to poll for messages over the "
|
||||
"communication channel %u\n", chan->id);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if ((bp.in.cx.halfs.high & MESSAGE_STATUS_DORECV) == 0) {
|
||||
/* No message to retrieve */
|
||||
*bufSize = 0;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Receive the size.
|
||||
*/
|
||||
|
||||
/* OUT: Type */
|
||||
if (bp.in.dx.halfs.high != MESSAGE_TYPE_SENDSIZE) {
|
||||
MESSAGE_LOG("Message: Protocol error. Expected a "
|
||||
"MESSAGE_TYPE_SENDSIZE request from vmware\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* OUT: Size */
|
||||
myBufSize = bp.out.bx.word;
|
||||
|
||||
/*
|
||||
* Allocate an extra byte for a trailing NUL character. The code that will
|
||||
* deal with this message may not know about binary strings, and may expect
|
||||
* a C string instead. --hpreg
|
||||
*/
|
||||
if (myBufSize + 1 > chan->inAlloc) {
|
||||
myBuf = (unsigned char *)realloc(chan->in, myBufSize + 1);
|
||||
if (myBuf == NULL) {
|
||||
MESSAGE_LOG("Message: Not enough memory to receive a message over "
|
||||
"the communication channel %u\n", chan->id);
|
||||
goto error_quit;
|
||||
}
|
||||
|
||||
chan->in = myBuf;
|
||||
chan->inAlloc = myBufSize + 1;
|
||||
}
|
||||
*bufSize = myBufSize;
|
||||
myBuf = *buf = chan->in;
|
||||
|
||||
if (bp.in.cx.halfs.high & MESSAGE_STATUS_HB) {
|
||||
/*
|
||||
* High-bandwidth backdoor port supported. Receive the message in one
|
||||
* backdoor operation. --hpreg
|
||||
*/
|
||||
|
||||
if (myBufSize) {
|
||||
Backdoor_proto_hb bphb;
|
||||
|
||||
bphb.in.bx.halfs.low = BDOORHB_CMD_MESSAGE;
|
||||
bphb.in.bx.halfs.high = MESSAGE_STATUS_SUCCESS;
|
||||
bphb.in.dx.halfs.high = chan->id;
|
||||
bphb.in.srcAddr = chan->cookieHigh;
|
||||
bphb.in.bp.word = chan->cookieLow;
|
||||
bphb.in.size = myBufSize;
|
||||
bphb.in.dstAddr = (uintptr_t) myBuf;
|
||||
Backdoor_HbIn(&bphb);
|
||||
if ((bphb.in.bx.halfs.high & MESSAGE_STATUS_SUCCESS) == 0) {
|
||||
if ((bphb.in.bx.halfs.high & MESSAGE_STATUS_CPT) != 0) {
|
||||
/* A checkpoint occurred. Retry the operation. --hpreg */
|
||||
goto retry;
|
||||
}
|
||||
|
||||
MESSAGE_LOG("Message: Unable to receive a message over the "
|
||||
"communication channel %u\n", chan->id);
|
||||
goto error_quit;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* High-bandwidth backdoor port not supported. Receive the message, 4
|
||||
* bytes at a time. --hpreg
|
||||
*/
|
||||
|
||||
for (;;) {
|
||||
if (myBufSize == 0) {
|
||||
/* We are done */
|
||||
break;
|
||||
}
|
||||
|
||||
/* IN: Type */
|
||||
bp.in.cx.halfs.high = MESSAGE_TYPE_RECVPAYLOAD;
|
||||
/* IN: Id and cookie */
|
||||
bp.in.dx.halfs.high = chan->id;
|
||||
bp.in.si.word = chan->cookieHigh;
|
||||
bp.in.di.word = chan->cookieLow;
|
||||
/* IN: Status for the previous request (that succeeded) */
|
||||
bp.in.size = MESSAGE_STATUS_SUCCESS;
|
||||
|
||||
bp.in.cx.halfs.low = BDOOR_CMD_MESSAGE;
|
||||
Backdoor(&bp);
|
||||
|
||||
/* OUT: Status */
|
||||
if ((bp.in.cx.halfs.high & MESSAGE_STATUS_SUCCESS) == 0) {
|
||||
if ((bp.in.cx.halfs.high & MESSAGE_STATUS_CPT) != 0) {
|
||||
/* A checkpoint occurred. Retry the operation. --hpreg */
|
||||
goto retry;
|
||||
}
|
||||
|
||||
MESSAGE_LOG("Message: Unable to receive a message over the "
|
||||
"communication channel %u\n", chan->id);
|
||||
goto error_quit;
|
||||
}
|
||||
|
||||
/* OUT: Type */
|
||||
if (bp.in.dx.halfs.high != MESSAGE_TYPE_SENDPAYLOAD) {
|
||||
MESSAGE_LOG("Message: Protocol error. Expected a "
|
||||
"MESSAGE_TYPE_SENDPAYLOAD from vmware\n");
|
||||
goto error_quit;
|
||||
}
|
||||
|
||||
/* OUT: Piece of message */
|
||||
/*
|
||||
* Beware in case we are not allowed to write extra bytes beyond the
|
||||
* end of the buffer. --hpreg
|
||||
*/
|
||||
switch (myBufSize) {
|
||||
case 1:
|
||||
myBuf[0] = bp.out.bx.word & 0xff;
|
||||
myBufSize -= 1;
|
||||
break;
|
||||
case 2:
|
||||
myBuf[0] = bp.out.bx.word & 0xff;
|
||||
myBuf[1] = (bp.out.bx.word >> 8) & 0xff;
|
||||
myBufSize -= 2;
|
||||
break;
|
||||
case 3:
|
||||
myBuf[0] = bp.out.bx.word & 0xff;
|
||||
myBuf[1] = (bp.out.bx.word >> 8) & 0xff;
|
||||
myBuf[2] = (bp.out.bx.word >> 16) & 0xff;
|
||||
myBufSize -= 3;
|
||||
break;
|
||||
default:
|
||||
*(uint32 *)myBuf = bp.out.bx.word;
|
||||
myBufSize -= 4;
|
||||
break;
|
||||
}
|
||||
|
||||
myBuf += 4;
|
||||
}
|
||||
}
|
||||
|
||||
/* Write a trailing NUL just after the message. --hpreg */
|
||||
chan->in[*bufSize] = '\0';
|
||||
|
||||
/* IN: Type */
|
||||
bp.in.cx.halfs.high = MESSAGE_TYPE_RECVSTATUS;
|
||||
/* IN: Id and cookie */
|
||||
bp.in.dx.halfs.high = chan->id;
|
||||
bp.in.si.word = chan->cookieHigh;
|
||||
bp.in.di.word = chan->cookieLow;
|
||||
/* IN: Status for the previous request (that succeeded) */
|
||||
bp.in.size = MESSAGE_STATUS_SUCCESS;
|
||||
|
||||
bp.in.cx.halfs.low = BDOOR_CMD_MESSAGE;
|
||||
Backdoor(&bp);
|
||||
|
||||
/* OUT: Status */
|
||||
if ((bp.in.cx.halfs.high & MESSAGE_STATUS_SUCCESS) == 0) {
|
||||
if ((bp.in.cx.halfs.high & MESSAGE_STATUS_CPT) != 0) {
|
||||
/* A checkpoint occurred. Retry the operation. --hpreg */
|
||||
goto retry;
|
||||
}
|
||||
|
||||
MESSAGE_LOG("Message: Unable to receive a message over the "
|
||||
"communication channel %u\n", chan->id);
|
||||
goto error_quit;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
|
||||
error_quit:
|
||||
/* IN: Type */
|
||||
if (myBufSize == 0) {
|
||||
bp.in.cx.halfs.high = MESSAGE_TYPE_RECVSTATUS;
|
||||
} else {
|
||||
bp.in.cx.halfs.high = MESSAGE_TYPE_RECVPAYLOAD;
|
||||
}
|
||||
/* IN: Id and cookie */
|
||||
bp.in.dx.halfs.high = chan->id;
|
||||
bp.in.si.word = chan->cookieHigh;
|
||||
bp.in.di.word = chan->cookieLow;
|
||||
/* IN: Status for the previous request (that failed) */
|
||||
bp.in.size = 0;
|
||||
|
||||
bp.in.cx.halfs.low = BDOOR_CMD_MESSAGE;
|
||||
Backdoor(&bp);
|
||||
|
||||
/* OUT: Status */
|
||||
if ((bp.in.cx.halfs.high & MESSAGE_STATUS_SUCCESS) == 0) {
|
||||
MESSAGE_LOG("Message: Unable to signal an error of reception over the "
|
||||
"communication channel %u\n", chan->id);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*-----------------------------------------------------------------------------
|
||||
*
|
||||
* Message_Close --
|
||||
*
|
||||
* Close a communication channel
|
||||
*
|
||||
* Result:
|
||||
* TRUE on success, the channel is destroyed
|
||||
* FALSE on failure
|
||||
*
|
||||
* Side-effects:
|
||||
* None
|
||||
*
|
||||
*-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
Bool
|
||||
Message_Close(Message_Channel *chan) // IN/OUT
|
||||
{
|
||||
Backdoor_proto bp;
|
||||
Bool ret = TRUE;
|
||||
|
||||
/* IN: Type */
|
||||
bp.in.cx.halfs.high = MESSAGE_TYPE_CLOSE;
|
||||
/* IN: Id and cookie */
|
||||
bp.in.dx.halfs.high = chan->id;
|
||||
bp.in.si.word = chan->cookieHigh;
|
||||
bp.in.di.word = chan->cookieLow;
|
||||
|
||||
bp.in.cx.halfs.low = BDOOR_CMD_MESSAGE;
|
||||
Backdoor(&bp);
|
||||
|
||||
/* OUT: Status */
|
||||
if ((bp.in.cx.halfs.high & MESSAGE_STATUS_SUCCESS) == 0) {
|
||||
MESSAGE_LOG("Message: Unable to close the communication channel %u\n",
|
||||
chan->id);
|
||||
ret = FALSE;
|
||||
}
|
||||
|
||||
free(chan->in);
|
||||
chan->in = NULL;
|
||||
|
||||
free(chan);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
416
Godeps/_workspace/src/github.com/sigma/vmw-guestinfo/bridge/utilMem.c
generated
vendored
Normal file
416
Godeps/_workspace/src/github.com/sigma/vmw-guestinfo/bridge/utilMem.c
generated
vendored
Normal file
@@ -0,0 +1,416 @@
|
||||
/*********************************************************
|
||||
* Copyright (C) 2009-2015 VMware, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published
|
||||
* by the Free Software Foundation version 2.1 and no later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
*********************************************************/
|
||||
|
||||
/*
|
||||
* utilMem.c --
|
||||
*
|
||||
* misc util functions
|
||||
*/
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#endif
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "vm_assert.h"
|
||||
#include "util.h"
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <TargetConditionals.h>
|
||||
#if !defined TARGET_OS_IPHONE
|
||||
#define TARGET_OS_IPHONE 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static NORETURN void UtilAllocationFailure0(void);
|
||||
static NORETURN void UtilAllocationFailure1(int bugNumber,
|
||||
const char *file, int lineno);
|
||||
|
||||
|
||||
static void
|
||||
UtilAllocationFailure0(void)
|
||||
{
|
||||
Panic("Unrecoverable memory allocation failure\n");
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
UtilAllocationFailure1(int bugNumber, const char *file, int lineno)
|
||||
{
|
||||
if (bugNumber == -1) {
|
||||
Panic("Unrecoverable memory allocation failure at %s:%d\n",
|
||||
file, lineno);
|
||||
} else {
|
||||
Panic("Unrecoverable memory allocation failure at %s:%d. Bug "
|
||||
"number: %d\n", file, lineno, bugNumber);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*-----------------------------------------------------------------------------
|
||||
*
|
||||
* UtilSafeMalloc0 --
|
||||
* UtilSafeMalloc1 --
|
||||
* Helper function for malloc
|
||||
*
|
||||
* Results:
|
||||
* Pointer to the dynamically allocated memory.
|
||||
*
|
||||
* Side effects:
|
||||
* May Panic if ran out of memory.
|
||||
*
|
||||
*-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void *
|
||||
UtilSafeMalloc0(size_t size) // IN:
|
||||
{
|
||||
void *result = malloc(size);
|
||||
if (result == NULL && size != 0) {
|
||||
UtilAllocationFailure0();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
void *
|
||||
UtilSafeMalloc1(size_t size, // IN:
|
||||
int bugNumber, // IN:
|
||||
const char *file, // IN:
|
||||
int lineno) // IN:
|
||||
{
|
||||
void *result = malloc(size);
|
||||
if (result == NULL && size != 0) {
|
||||
UtilAllocationFailure1(bugNumber, file, lineno);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*-----------------------------------------------------------------------------
|
||||
*
|
||||
* UtilSafeRealloc0 --
|
||||
* UtilSafeRealloc1 --
|
||||
* Helper function for realloc
|
||||
*
|
||||
* Results:
|
||||
* Pointer to the dynamically allocated memory.
|
||||
*
|
||||
* Side effects:
|
||||
* May Panic if ran out of memory.
|
||||
*
|
||||
*-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void *
|
||||
UtilSafeRealloc0(void *ptr, // IN:
|
||||
size_t size) // IN:
|
||||
{
|
||||
void *result = realloc(ptr, size);
|
||||
if (result == NULL && size != 0) {
|
||||
UtilAllocationFailure0();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
void *
|
||||
UtilSafeRealloc1(void *ptr, // IN:
|
||||
size_t size, // IN:
|
||||
int bugNumber, // IN:
|
||||
const char *file, // IN:
|
||||
int lineno) // IN:
|
||||
{
|
||||
void *result = realloc(ptr, size);
|
||||
if (result == NULL && size != 0) {
|
||||
UtilAllocationFailure1(bugNumber, file, lineno);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*-----------------------------------------------------------------------------
|
||||
*
|
||||
* UtilSafeCalloc0 --
|
||||
* UtilSafeCalloc1 --
|
||||
* Helper function for calloc
|
||||
*
|
||||
* Results:
|
||||
* Pointer to the dynamically allocated memory.
|
||||
*
|
||||
* Side effects:
|
||||
* May Panic if ran out of memory.
|
||||
*
|
||||
*-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void *
|
||||
UtilSafeCalloc0(size_t nmemb, // IN:
|
||||
size_t size) // IN:
|
||||
{
|
||||
void *result = calloc(nmemb, size);
|
||||
if (result == NULL && nmemb != 0 && size != 0) {
|
||||
UtilAllocationFailure0();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
void *
|
||||
UtilSafeCalloc1(size_t nmemb, // IN:
|
||||
size_t size, // IN:
|
||||
int bugNumber, // IN:
|
||||
const char *file, // IN:
|
||||
int lineno) // IN:
|
||||
{
|
||||
void *result = calloc(nmemb, size);
|
||||
if (result == NULL && nmemb != 0 && size != 0) {
|
||||
UtilAllocationFailure1(bugNumber, file, lineno);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*-----------------------------------------------------------------------------
|
||||
*
|
||||
* Util_SafeStrdup --
|
||||
* Helper function for strdup
|
||||
*
|
||||
* Results:
|
||||
* Pointer to the dynamically allocated, duplicate string
|
||||
*
|
||||
* Side effects:
|
||||
* May Panic if ran out of memory.
|
||||
*
|
||||
*-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
char *
|
||||
UtilSafeStrdup0(const char *s) // IN:
|
||||
{
|
||||
char *result;
|
||||
if (s == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
#if defined(_WIN32)
|
||||
if ((result = _strdup(s)) == NULL) {
|
||||
#else
|
||||
if ((result = strdup(s)) == NULL) {
|
||||
#endif
|
||||
UtilAllocationFailure0();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
char *
|
||||
UtilSafeStrdup1(const char *s, // IN:
|
||||
int bugNumber, // IN:
|
||||
const char *file, // IN:
|
||||
int lineno) // IN:
|
||||
{
|
||||
char *result;
|
||||
if (s == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
#if defined(_WIN32)
|
||||
if ((result = _strdup(s)) == NULL) {
|
||||
#else
|
||||
if ((result = strdup(s)) == NULL) {
|
||||
#endif
|
||||
UtilAllocationFailure1(bugNumber, file, lineno);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*-----------------------------------------------------------------------------
|
||||
*
|
||||
* Util_SafeStrndup --
|
||||
*
|
||||
* Returns a string consisting of first n characters of 's' if 's' has
|
||||
* length >= 'n', otherwise returns a string duplicate of 's'.
|
||||
*
|
||||
* Results:
|
||||
* Pointer to the duplicated string.
|
||||
*
|
||||
* Side effects:
|
||||
* May Panic if ran out of memory.
|
||||
*
|
||||
*-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
char *
|
||||
UtilSafeStrndup0(const char *s, // IN:
|
||||
size_t n) // IN:
|
||||
{
|
||||
size_t size;
|
||||
char *copy;
|
||||
const char *null;
|
||||
size_t newSize;
|
||||
|
||||
if (s == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
null = memchr(s, '\0', n);
|
||||
size = null ? (size_t)(null - s) : n;
|
||||
newSize = size + 1;
|
||||
if (newSize < size) { // Prevent integer overflow
|
||||
copy = NULL;
|
||||
} else {
|
||||
copy = malloc(newSize);
|
||||
}
|
||||
|
||||
if (copy == NULL) {
|
||||
UtilAllocationFailure0();
|
||||
}
|
||||
|
||||
copy[size] = '\0';
|
||||
|
||||
return (char *) memcpy(copy, s, size);
|
||||
}
|
||||
|
||||
|
||||
char *
|
||||
UtilSafeStrndup1(const char *s, // IN:
|
||||
size_t n, // IN:
|
||||
int bugNumber, // IN:
|
||||
const char *file, // IN:
|
||||
int lineno) // IN:
|
||||
{
|
||||
size_t size;
|
||||
char *copy;
|
||||
const char *null;
|
||||
size_t newSize;
|
||||
|
||||
if (s == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
null = memchr(s, '\0', n);
|
||||
size = null ? (size_t)(null - s) : n;
|
||||
newSize = size + 1;
|
||||
if (newSize < size) { // Prevent integer overflow
|
||||
copy = NULL;
|
||||
} else {
|
||||
copy = malloc(newSize);
|
||||
}
|
||||
|
||||
if (copy == NULL) {
|
||||
UtilAllocationFailure1(bugNumber, file, lineno);
|
||||
}
|
||||
|
||||
copy[size] = '\0';
|
||||
|
||||
return (char *) memcpy(copy, s, size);
|
||||
}
|
||||
|
||||
|
||||
void *
|
||||
Util_Memcpy(void *dest,
|
||||
const void *src,
|
||||
size_t count)
|
||||
{
|
||||
#if defined(__x86_64__) || defined(__i386__)
|
||||
uintptr_t align = ((uintptr_t)dest | (uintptr_t)src | count);
|
||||
|
||||
#if defined __GNUC__
|
||||
|
||||
#if defined(__x86_64__)
|
||||
|
||||
size_t dummy0;
|
||||
void *dummy1;
|
||||
void *dummy2;
|
||||
|
||||
if ((align & 7) == 0) {
|
||||
__asm__ __volatile__("\t"
|
||||
"cld" "\n\t"
|
||||
"rep ; movsq" "\n"
|
||||
: "=c" (dummy0), "=D" (dummy1), "=S" (dummy2)
|
||||
: "0" (count >> 3), "1" (dest), "2" (src)
|
||||
: "memory", "cc"
|
||||
);
|
||||
return dest;
|
||||
} else if ((align & 3) == 0) {
|
||||
__asm__ __volatile__("\t"
|
||||
"cld" "\n\t"
|
||||
"rep ; movsd" "\n"
|
||||
: "=c" (dummy0), "=D" (dummy1), "=S" (dummy2)
|
||||
: "0" (count >> 2), "1" (dest), "2" (src)
|
||||
: "memory", "cc"
|
||||
);
|
||||
return dest;
|
||||
}
|
||||
|
||||
#elif defined(__i386__)
|
||||
|
||||
size_t dummy0;
|
||||
void *dummy1;
|
||||
void *dummy2;
|
||||
|
||||
if ((align & 3) == 0) {
|
||||
__asm__ __volatile__("\t"
|
||||
"cld" "\n\t"
|
||||
"rep ; movsd" "\n"
|
||||
: "=c" (dummy0), "=D" (dummy1), "=S" (dummy2)
|
||||
: "0" (count >> 2), "1" (dest), "2" (src)
|
||||
: "memory", "cc"
|
||||
);
|
||||
return dest;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#elif defined _MSC_VER
|
||||
|
||||
#if defined(__x86_64__)
|
||||
|
||||
if ((align & 7) == 0) {
|
||||
__movsq((uint64 *)dest, (uint64 *)src, count >> 3);
|
||||
return dest;
|
||||
} else if ((align & 3) == 0) {
|
||||
__movsd((unsigned long *)dest, (unsigned long *)src, count >> 2);
|
||||
return dest;
|
||||
}
|
||||
|
||||
#elif defined(__i386__)
|
||||
|
||||
if ((((uintptr_t)dest | (uintptr_t)src | count) & 3) == 0) {
|
||||
__movsd((unsigned long *)dest, (unsigned long *)src, count >> 2);
|
||||
return dest;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
memcpy(dest, src, count);
|
||||
return dest;
|
||||
}
|
||||
|
||||
|
300
Godeps/_workspace/src/github.com/sigma/vmw-guestinfo/bridge/vmcheck.c
generated
vendored
Normal file
300
Godeps/_workspace/src/github.com/sigma/vmw-guestinfo/bridge/vmcheck.c
generated
vendored
Normal file
@@ -0,0 +1,300 @@
|
||||
/*********************************************************
|
||||
* Copyright (C) 2006-2015 VMware, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published
|
||||
* by the Free Software Foundation version 2.1 and no later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
*********************************************************/
|
||||
|
||||
|
||||
/*
|
||||
* vmcheck.c --
|
||||
*
|
||||
* Utility functions for discovering our virtualization status.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef WINNT_DDK
|
||||
# include <ntddk.h>
|
||||
#endif
|
||||
|
||||
#include "vmware.h"
|
||||
/*
|
||||
* #include "vm_version.h"
|
||||
* #include "vm_tools_version.h"
|
||||
*/
|
||||
#define VMX_TYPE_UNSET 0
|
||||
#define VERSION_MAGIC 0x6
|
||||
|
||||
#if !defined(WINNT_DDK)
|
||||
# include "hostinfo.h"
|
||||
/* # include "str.h" */
|
||||
# define Str_Strcmp(s1, s2) strcmp(s1, s2)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* backdoor.h includes some files which redefine constants in ntddk.h. Ignore
|
||||
* warnings about these redefinitions for WIN32 platform.
|
||||
*/
|
||||
#ifdef WINNT_DDK
|
||||
#pragma warning (push)
|
||||
// Warning: Conditional expression is constant.
|
||||
#pragma warning( disable:4127 )
|
||||
#endif
|
||||
|
||||
#include "backdoor.h"
|
||||
|
||||
#ifdef WINNT_DDK
|
||||
#pragma warning (pop)
|
||||
#endif
|
||||
|
||||
#include "backdoor_def.h"
|
||||
#include "debug.h"
|
||||
|
||||
|
||||
typedef Bool (*SafeCheckFn)(void);
|
||||
|
||||
#if !defined(_WIN32)
|
||||
# include "vmsignal.h"
|
||||
# include "setjmp.h"
|
||||
|
||||
static sigjmp_buf jmpBuf;
|
||||
static Bool jmpIsSet;
|
||||
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* VmCheckSegvHandler --
|
||||
*
|
||||
* Signal handler for segv. Return to the program state saved
|
||||
* by a previous call to sigsetjmp, or Panic if sigsetjmp hasn't
|
||||
* been called yet. This function never returns;
|
||||
*
|
||||
* Return Value:
|
||||
* None.
|
||||
*
|
||||
* Side effects:
|
||||
* See the manpage for sigsetjmp for details.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static void
|
||||
VmCheckSegvHandler(int clientData) // UNUSED
|
||||
{
|
||||
if (jmpIsSet) {
|
||||
siglongjmp(jmpBuf, 1);
|
||||
} else {
|
||||
Panic("Received SEGV, exiting.");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* VmCheckSafe --
|
||||
*
|
||||
* Calls a potentially unsafe function, trapping possible exceptions.
|
||||
*
|
||||
* Results:
|
||||
*
|
||||
* Return value of the passed function, or FALSE in case of exception.
|
||||
*
|
||||
* Side effects:
|
||||
*
|
||||
* Temporarily suppresses signals / SEH exceptions
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static Bool
|
||||
VmCheckSafe(SafeCheckFn checkFn)
|
||||
{
|
||||
Bool result = FALSE;
|
||||
|
||||
/*
|
||||
* On a real host this call should cause a GP and we catch
|
||||
* that and set result to FALSE.
|
||||
*/
|
||||
|
||||
#if defined(_WIN32)
|
||||
__try {
|
||||
result = checkFn();
|
||||
} __except(EXCEPTION_EXECUTE_HANDLER) {
|
||||
/* no op */
|
||||
}
|
||||
#else
|
||||
do {
|
||||
int signals[] = {
|
||||
SIGILL,
|
||||
SIGSEGV,
|
||||
};
|
||||
struct sigaction olds[ARRAYSIZE(signals)];
|
||||
|
||||
if (Signal_SetGroupHandler(signals, olds, ARRAYSIZE(signals),
|
||||
VmCheckSegvHandler) == 0) {
|
||||
Warning("%s: Failed to set signal handlers.\n", __FUNCTION__);
|
||||
break;
|
||||
}
|
||||
|
||||
if (sigsetjmp(jmpBuf, TRUE) == 0) {
|
||||
jmpIsSet = TRUE;
|
||||
result = checkFn();
|
||||
} else {
|
||||
jmpIsSet = FALSE;
|
||||
}
|
||||
|
||||
if (Signal_ResetGroupHandler(signals, olds, ARRAYSIZE(signals)) == 0) {
|
||||
Warning("%s: Failed to reset signal handlers.\n", __FUNCTION__);
|
||||
}
|
||||
} while (0);
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* VmCheck_GetVersion --
|
||||
*
|
||||
* Retrieve the version of VMware that's running on the
|
||||
* other side of the backdoor.
|
||||
*
|
||||
* Return value:
|
||||
* TRUE on success
|
||||
* *version contains the VMX version
|
||||
* *type contains the VMX type
|
||||
* FALSE on failure
|
||||
*
|
||||
* Side effects:
|
||||
* None
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
Bool
|
||||
VmCheck_GetVersion(uint32 *version, // OUT
|
||||
uint32 *type) // OUT
|
||||
{
|
||||
Backdoor_proto bp;
|
||||
|
||||
ASSERT(version);
|
||||
ASSERT(type);
|
||||
|
||||
/* Make sure EBX does not contain BDOOR_MAGIC */
|
||||
bp.in.size = ~BDOOR_MAGIC;
|
||||
/* Make sure ECX does not contain any known VMX type */
|
||||
bp.in.cx.halfs.high = 0xFFFF;
|
||||
|
||||
bp.in.cx.halfs.low = BDOOR_CMD_GETVERSION;
|
||||
Backdoor(&bp);
|
||||
if (bp.out.ax.word == 0xFFFFFFFF) {
|
||||
/*
|
||||
* No backdoor device there. This code is not executing in a VMware
|
||||
* virtual machine. --hpreg
|
||||
*/
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (bp.out.bx.word != BDOOR_MAGIC) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
*version = bp.out.ax.word;
|
||||
|
||||
/*
|
||||
* Old VMXs (workstation and express) didn't set their type. In that case,
|
||||
* our special pattern will still be there. --hpreg
|
||||
*/
|
||||
|
||||
/*
|
||||
* Need to expand this out since the toolchain's gcc doesn't like mixing
|
||||
* integral types and enums in the same trinary operator.
|
||||
*/
|
||||
if (bp.in.cx.halfs.high == 0xFFFF)
|
||||
*type = VMX_TYPE_UNSET;
|
||||
else
|
||||
*type = bp.out.cx.word;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* VmCheck_IsVirtualWorld --
|
||||
*
|
||||
* Verify that we're running in a VM & we're version compatible with our
|
||||
* environment.
|
||||
*
|
||||
* Return value:
|
||||
* TRUE if we're in a virtual machine, FALSE otherwise.
|
||||
*
|
||||
* Side effects:
|
||||
* None.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
Bool
|
||||
VmCheck_IsVirtualWorld(void)
|
||||
{
|
||||
uint32 version;
|
||||
uint32 dummy;
|
||||
|
||||
#if !defined(WINNT_DDK)
|
||||
if (VmCheckSafe(Hostinfo_TouchXen)) {
|
||||
Debug("%s: detected Xen.\n", __FUNCTION__);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (VmCheckSafe(Hostinfo_TouchVirtualPC)) {
|
||||
Debug("%s: detected Virtual PC.\n", __FUNCTION__);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!VmCheckSafe(Hostinfo_TouchBackDoor)) {
|
||||
Debug("%s: backdoor not detected.\n", __FUNCTION__);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* It should be safe to use the backdoor without a crash handler now. */
|
||||
VmCheck_GetVersion(&version, &dummy);
|
||||
#else
|
||||
/*
|
||||
* The Win32 vmwvaudio driver uses this function, so keep the old,
|
||||
* VMware-only check.
|
||||
*/
|
||||
__try {
|
||||
VmCheck_GetVersion(&version, &dummy);
|
||||
} __except (GetExceptionCode() == STATUS_PRIVILEGED_INSTRUCTION) {
|
||||
return FALSE;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (version != VERSION_MAGIC) {
|
||||
Debug("The version of this program is incompatible with your platform.\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
123
Godeps/_workspace/src/github.com/sigma/vmw-guestinfo/bridge/vmsignal.c
generated
vendored
Normal file
123
Godeps/_workspace/src/github.com/sigma/vmw-guestinfo/bridge/vmsignal.c
generated
vendored
Normal file
@@ -0,0 +1,123 @@
|
||||
/*********************************************************
|
||||
* Copyright (C) 1998-2015 VMware, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published
|
||||
* by the Free Software Foundation version 2.1 and no later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
*********************************************************/
|
||||
|
||||
|
||||
/*
|
||||
* vmsignal.c --
|
||||
*
|
||||
* Posix signal handling utility functions
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef VMX86_DEVEL
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
#include "vmsignal.h"
|
||||
|
||||
|
||||
/*
|
||||
* Signal_SetGroupHandler --
|
||||
*
|
||||
* Set a signal handler for a group of signals.
|
||||
* We carefully ensure that if the handler is only used to handle the
|
||||
* signals of the group, the handling of all the signals of the group is
|
||||
* serialized, which means that the handler is not re-entrant.
|
||||
*
|
||||
* Return value:
|
||||
* 1 on success
|
||||
* 0 on failure (detail is displayed)
|
||||
*
|
||||
* Side effects:
|
||||
* None
|
||||
*
|
||||
*/
|
||||
|
||||
int
|
||||
Signal_SetGroupHandler(int const *signals, // IN
|
||||
struct sigaction *olds, // OUT
|
||||
unsigned int nr, // IN
|
||||
void (*handler)(int signal)) // IN
|
||||
{
|
||||
unsigned int i;
|
||||
struct sigaction new;
|
||||
|
||||
new.sa_handler = handler;
|
||||
if (sigemptyset(&new.sa_mask)) {
|
||||
fprintf(stderr, "Unable to empty a signal set: %s.\n\n", strerror(errno));
|
||||
|
||||
return 0;
|
||||
}
|
||||
for (i = 0; i < nr; i++) {
|
||||
if (sigaddset(&new.sa_mask, signals[i])) {
|
||||
fprintf(stderr, "Unable to add a signal to a signal set: %s.\n\n", strerror(errno));
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
new.sa_flags = 0;
|
||||
|
||||
for (i = 0; i < nr; i++) {
|
||||
if (sigaction(signals[i], &new, &olds[i])) {
|
||||
fprintf(stderr, "Unable to modify the handler of the signal %d: %s.\n\n", signals[i], strerror(errno));
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Signal_ResetGroupHandler --
|
||||
*
|
||||
* Reset the handler of each signal of a group of signals
|
||||
*
|
||||
* Return value:
|
||||
* 1 on success
|
||||
* 0 on failure (detail is displayed)
|
||||
*
|
||||
* Side effects:
|
||||
* None
|
||||
*
|
||||
*/
|
||||
|
||||
int
|
||||
Signal_ResetGroupHandler(int const *signals, // IN
|
||||
struct sigaction const *olds, // IN
|
||||
unsigned int nr) // IN
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < nr; i++) {
|
||||
if (sigaction(signals[i], &olds[i], NULL)) {
|
||||
fprintf(stderr, "Unable to reset the handler of the signal %d: %s.\n\n", signals[i], strerror(errno));
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
22
Godeps/_workspace/src/github.com/sigma/vmw-guestinfo/examples/main.go
generated
vendored
Normal file
22
Godeps/_workspace/src/github.com/sigma/vmw-guestinfo/examples/main.go
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/coreos/coreos-cloudinit/Godeps/_workspace/src/github.com/sigma/vmw-guestinfo/rpcvmx"
|
||||
"github.com/coreos/coreos-cloudinit/Godeps/_workspace/src/github.com/sigma/vmw-guestinfo/vmcheck"
|
||||
)
|
||||
|
||||
func main() {
|
||||
if !vmcheck.IsVirtualWorld() {
|
||||
fmt.Println("not in a virtual world... :(")
|
||||
return
|
||||
}
|
||||
|
||||
version, typ := vmcheck.GetVersion()
|
||||
fmt.Println(version, typ)
|
||||
|
||||
config := rpcvmx.NewConfig()
|
||||
fmt.Println(config.GetString("foo", "foo"))
|
||||
fmt.Println(config.GetString("bar", "foo"))
|
||||
}
|
60
Godeps/_workspace/src/github.com/sigma/vmw-guestinfo/include/backdoor.h
generated
vendored
Normal file
60
Godeps/_workspace/src/github.com/sigma/vmw-guestinfo/include/backdoor.h
generated
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
/*********************************************************
|
||||
* Copyright (C) 1999-2015 VMware, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published
|
||||
* by the Free Software Foundation version 2.1 and no later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
*********************************************************/
|
||||
|
||||
/*********************************************************
|
||||
* The contents of this file are subject to the terms of the Common
|
||||
* Development and Distribution License (the "License") version 1.0
|
||||
* and no later version. You may not use this file except in
|
||||
* compliance with the License.
|
||||
*
|
||||
* You can obtain a copy of the License at
|
||||
* http://www.opensource.org/licenses/cddl1.php
|
||||
*
|
||||
* See the License for the specific language governing permissions
|
||||
* and limitations under the License.
|
||||
*
|
||||
*********************************************************/
|
||||
|
||||
/*
|
||||
* backdoor.h --
|
||||
*
|
||||
* First layer of the internal communication channel between guest
|
||||
* applications and vmware
|
||||
*/
|
||||
|
||||
#ifndef _BACKDOOR_H_
|
||||
#define _BACKDOOR_H_
|
||||
|
||||
#include "vm_basic_types.h"
|
||||
#include "vm_assert.h"
|
||||
|
||||
#include "backdoor_types.h"
|
||||
|
||||
void
|
||||
Backdoor(Backdoor_proto *bp); // IN/OUT
|
||||
|
||||
void
|
||||
Backdoor_InOut(Backdoor_proto *bp); // IN/OUT
|
||||
|
||||
void
|
||||
Backdoor_HbOut(Backdoor_proto_hb *bp); // IN/OUT
|
||||
|
||||
void
|
||||
Backdoor_HbIn(Backdoor_proto_hb *bp); // IN/OUT
|
||||
|
||||
#endif /* _BACKDOOR_H_ */
|
40
Godeps/_workspace/src/github.com/sigma/vmw-guestinfo/include/backdoorInt.h
generated
vendored
Normal file
40
Godeps/_workspace/src/github.com/sigma/vmw-guestinfo/include/backdoorInt.h
generated
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
/*********************************************************
|
||||
* Copyright (C) 2005-2015 VMware, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published
|
||||
* by the Free Software Foundation version 2.1 and no later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
*********************************************************/
|
||||
|
||||
/*********************************************************
|
||||
* The contents of this file are subject to the terms of the Common
|
||||
* Development and Distribution License (the "License") version 1.0
|
||||
* and no later version. You may not use this file except in
|
||||
* compliance with the License.
|
||||
*
|
||||
* You can obtain a copy of the License at
|
||||
* http://www.opensource.org/licenses/cddl1.php
|
||||
*
|
||||
* See the License for the specific language governing permissions
|
||||
* and limitations under the License.
|
||||
*
|
||||
*********************************************************/
|
||||
|
||||
/*
|
||||
* backdoorInt.h --
|
||||
*
|
||||
* Internal function prototypes for the real backdoor work.
|
||||
*/
|
||||
|
||||
void BackdoorHbIn(Backdoor_proto_hb *bp);
|
||||
void BackdoorHbOut(Backdoor_proto_hb *bp);
|
261
Godeps/_workspace/src/github.com/sigma/vmw-guestinfo/include/backdoor_def.h
generated
vendored
Normal file
261
Godeps/_workspace/src/github.com/sigma/vmw-guestinfo/include/backdoor_def.h
generated
vendored
Normal file
@@ -0,0 +1,261 @@
|
||||
/*********************************************************
|
||||
* Copyright (C) 1998-2015 VMware, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published
|
||||
* by the Free Software Foundation version 2.1 and no later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
*********************************************************/
|
||||
|
||||
/*********************************************************
|
||||
* The contents of this file are subject to the terms of the Common
|
||||
* Development and Distribution License (the "License") version 1.0
|
||||
* and no later version. You may not use this file except in
|
||||
* compliance with the License.
|
||||
*
|
||||
* You can obtain a copy of the License at
|
||||
* http://www.opensource.org/licenses/cddl1.php
|
||||
*
|
||||
* See the License for the specific language governing permissions
|
||||
* and limitations under the License.
|
||||
*
|
||||
*********************************************************/
|
||||
|
||||
/*
|
||||
* backdoor_def.h --
|
||||
*
|
||||
* This contains backdoor defines that can be included from
|
||||
* an assembly language file.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef _BACKDOOR_DEF_H_
|
||||
#define _BACKDOOR_DEF_H_
|
||||
|
||||
/*
|
||||
* If you want to add a new low-level backdoor call for a guest userland
|
||||
* application, please consider using the GuestRpc mechanism instead. --hpreg
|
||||
*/
|
||||
|
||||
#define BDOOR_MAGIC 0x564D5868
|
||||
|
||||
/* Low-bandwidth backdoor port. --hpreg */
|
||||
|
||||
#define BDOOR_PORT 0x5658
|
||||
|
||||
#define BDOOR_CMD_GETMHZ 1
|
||||
/*
|
||||
* BDOOR_CMD_APMFUNCTION is used by:
|
||||
*
|
||||
* o The FrobOS code, which instead should either program the virtual chipset
|
||||
* (like the new BIOS code does, matthias offered to implement that), or not
|
||||
* use any VM-specific code (which requires that we correctly implement
|
||||
* "power off on CLI HLT" for SMP VMs, boris offered to implement that)
|
||||
*
|
||||
* o The old BIOS code, which will soon be jettisoned
|
||||
*
|
||||
* --hpreg
|
||||
*/
|
||||
#define BDOOR_CMD_APMFUNCTION 2 /* CPL0 only. */
|
||||
#define BDOOR_CMD_GETDISKGEO 3
|
||||
#define BDOOR_CMD_GETPTRLOCATION 4
|
||||
#define BDOOR_CMD_SETPTRLOCATION 5
|
||||
#define BDOOR_CMD_GETSELLENGTH 6
|
||||
#define BDOOR_CMD_GETNEXTPIECE 7
|
||||
#define BDOOR_CMD_SETSELLENGTH 8
|
||||
#define BDOOR_CMD_SETNEXTPIECE 9
|
||||
#define BDOOR_CMD_GETVERSION 10
|
||||
#define BDOOR_CMD_GETDEVICELISTELEMENT 11
|
||||
#define BDOOR_CMD_TOGGLEDEVICE 12
|
||||
#define BDOOR_CMD_GETGUIOPTIONS 13
|
||||
#define BDOOR_CMD_SETGUIOPTIONS 14
|
||||
#define BDOOR_CMD_GETSCREENSIZE 15
|
||||
#define BDOOR_CMD_MONITOR_CONTROL 16 /* Disabled by default. */
|
||||
#define BDOOR_CMD_GETHWVERSION 17
|
||||
#define BDOOR_CMD_OSNOTFOUND 18 /* CPL0 only. */
|
||||
#define BDOOR_CMD_GETUUID 19
|
||||
#define BDOOR_CMD_GETMEMSIZE 20
|
||||
#define BDOOR_CMD_HOSTCOPY 21 /* Devel only. */
|
||||
//#define BDOOR_CMD_SERVICE_VM 22 /* Not in use. Never shipped. */
|
||||
#define BDOOR_CMD_GETTIME 23 /* Deprecated -> GETTIMEFULL. */
|
||||
#define BDOOR_CMD_STOPCATCHUP 24
|
||||
#define BDOOR_CMD_PUTCHR 25 /* Disabled by default. */
|
||||
#define BDOOR_CMD_ENABLE_MSG 26 /* Devel only. */
|
||||
#define BDOOR_CMD_GOTO_TCL 27 /* Devel only. */
|
||||
#define BDOOR_CMD_INITPCIOPROM 28 /* CPL 0 only. */
|
||||
//#define BDOOR_CMD_INT13 29 /* Not in use. */
|
||||
#define BDOOR_CMD_MESSAGE 30
|
||||
#define BDOOR_CMD_SIDT 31
|
||||
#define BDOOR_CMD_SGDT 32
|
||||
#define BDOOR_CMD_SLDT_STR 33
|
||||
#define BDOOR_CMD_ISACPIDISABLED 34
|
||||
//#define BDOOR_CMD_TOE 35 /* Not in use. */
|
||||
#define BDOOR_CMD_ISMOUSEABSOLUTE 36
|
||||
#define BDOOR_CMD_PATCH_SMBIOS_STRUCTS 37 /* CPL 0 only. */
|
||||
#define BDOOR_CMD_MAPMEM 38 /* Devel only */
|
||||
#define BDOOR_CMD_ABSPOINTER_DATA 39
|
||||
#define BDOOR_CMD_ABSPOINTER_STATUS 40
|
||||
#define BDOOR_CMD_ABSPOINTER_COMMAND 41
|
||||
//#define BDOOR_CMD_TIMER_SPONGE 42 /* Not in use. */
|
||||
#define BDOOR_CMD_PATCH_ACPI_TABLES 43 /* CPL 0 only. */
|
||||
//#define BDOOR_CMD_DEVEL_FAKEHARDWARE 44 /* Not in use. */
|
||||
#define BDOOR_CMD_GETHZ 45
|
||||
#define BDOOR_CMD_GETTIMEFULL 46
|
||||
#define BDOOR_CMD_STATELOGGER 47 /* Disabled by default. */
|
||||
#define BDOOR_CMD_CHECKFORCEBIOSSETUP 48 /* CPL 0 only. */
|
||||
#define BDOOR_CMD_LAZYTIMEREMULATION 49 /* CPL 0 only. */
|
||||
#define BDOOR_CMD_BIOSBBS 50 /* CPL 0 only. */
|
||||
//#define BDOOR_CMD_VASSERT 51 /* Not in use. */
|
||||
#define BDOOR_CMD_ISGOSDARWIN 52
|
||||
#define BDOOR_CMD_DEBUGEVENT 53
|
||||
#define BDOOR_CMD_OSNOTMACOSXSERVER 54 /* CPL 0 only. */
|
||||
#define BDOOR_CMD_GETTIMEFULL_WITH_LAG 55
|
||||
#define BDOOR_CMD_ACPI_HOTPLUG_DEVICE 56 /* Devel only. */
|
||||
#define BDOOR_CMD_ACPI_HOTPLUG_MEMORY 57 /* Devel only. */
|
||||
#define BDOOR_CMD_ACPI_HOTPLUG_CBRET 58 /* Devel only. */
|
||||
//#define BDOOR_CMD_GET_HOST_VIDEO_MODES 59 /* Not in use. */
|
||||
#define BDOOR_CMD_ACPI_HOTPLUG_CPU 60 /* Devel only. */
|
||||
//#define BDOOR_CMD_USB_HOTPLUG_MOUSE 61 /* Not in use. Never shipped. */
|
||||
#define BDOOR_CMD_XPMODE 62 /* CPL 0 only. */
|
||||
#define BDOOR_CMD_NESTING_CONTROL 63
|
||||
#define BDOOR_CMD_FIRMWARE_INIT 64 /* CPL 0 only. */
|
||||
#define BDOOR_CMD_FIRMWARE_ACPI_SERVICES 65 /* CPL 0 only. */
|
||||
# define BDOOR_CMD_FAS_GET_TABLE_SIZE 0
|
||||
# define BDOOR_CMD_FAS_GET_TABLE_DATA 1
|
||||
# define BDOOR_CMD_FAS_GET_PLATFORM_NAME 2
|
||||
# define BDOOR_CMD_FAS_GET_PCIE_OSC_MASK 3
|
||||
# define BDOOR_CMD_FAS_GET_APIC_ROUTING 4
|
||||
# define BDOOR_CMD_FAS_GET_TABLE_SKIP 5
|
||||
# define BDOOR_CMD_FAS_GET_SLEEP_ENABLES 6
|
||||
# define BDOOR_CMD_FAS_GET_HARD_RESET_ENABLE 7
|
||||
#define BDOOR_CMD_SENDPSHAREHINTS 66
|
||||
#define BDOOR_CMD_ENABLE_USB_MOUSE 67
|
||||
#define BDOOR_CMD_GET_VCPU_INFO 68
|
||||
# define BDOOR_CMD_VCPU_SLC64 0
|
||||
# define BDOOR_CMD_VCPU_SYNC_VTSCS 1
|
||||
# define BDOOR_CMD_VCPU_HV_REPLAY_OK 2
|
||||
# define BDOOR_CMD_VCPU_LEGACY_X2APIC_OK 3
|
||||
# define BDOOR_CMD_VCPU_RESERVED 31
|
||||
#define BDOOR_CMD_EFI_SERIALCON_CONFIG 69 /* CPL 0 only. */
|
||||
#define BDOOR_CMD_BUG328986 70 /* CPL 0 only. */
|
||||
#define BDOOR_CMD_FIRMWARE_ERROR 71 /* CPL 0 only. */
|
||||
# define BDOOR_CMD_FE_INSUFFICIENT_MEM 0
|
||||
# define BDOOR_CMD_FE_EXCEPTION 1
|
||||
#define BDOOR_CMD_VMK_INFO 72
|
||||
#define BDOOR_CMD_EFI_BOOT_CONFIG 73 /* CPL 0 only. */
|
||||
# define BDOOR_CMD_EBC_LEGACYBOOT_ENABLED 0
|
||||
# define BDOOR_CMD_EBC_GET_ORDER 1
|
||||
# define BDOOR_CMD_EBC_SHELL_ACTIVE 2
|
||||
# define BDOOR_CMD_EBC_GET_NETWORK_BOOT_PROTOCOL 3
|
||||
#define BDOOR_CMD_GET_HW_MODEL 74 /* CPL 0 only. */
|
||||
#define BDOOR_CMD_GET_SVGA_CAPABILITIES 75 /* CPL 0 only. */
|
||||
#define BDOOR_CMD_GET_FORCE_X2APIC 76 /* CPL 0 only */
|
||||
#define BDOOR_CMD_SET_PCI_HOLE 77 /* CPL 0 only */
|
||||
#define BDOOR_CMD_GET_PCI_HOLE 78 /* CPL 0 only */
|
||||
#define BDOOR_CMD_GET_PCI_BAR 79 /* CPL 0 only */
|
||||
#define BDOOR_CMD_SHOULD_GENERATE_SYSTEMID 80 /* CPL 0 only */
|
||||
#define BDOOR_CMD_READ_DEBUG_FILE 81 /* Devel only. */
|
||||
#define BDOOR_CMD_MAX 82
|
||||
|
||||
|
||||
/*
|
||||
* IMPORTANT NOTE: When modifying the behavior of an existing backdoor command,
|
||||
* you must adhere to the semantics expected by the oldest Tools who use that
|
||||
* command. Specifically, do not alter the way in which the command modifies
|
||||
* the registers. Otherwise backwards compatibility will suffer.
|
||||
*/
|
||||
|
||||
/* Processing mode for guest pshare hints (SENDPSHAREHINTS cmd) */
|
||||
#define BDOOR_PSHARE_HINTS_ASYNC 0
|
||||
#define BDOOR_PSHARE_HINTS_SYNC 1
|
||||
|
||||
#define BDOOR_PSHARE_HINTS_TYPE(ecx) (((ecx) >> 16) & 0x1)
|
||||
|
||||
/* Version of backdoor pshare hints protocol */
|
||||
#define BDOOR_PSHARE_HINTS_VERSION 1
|
||||
#define BDOOR_PSHARE_HINTS_VER(ecx) (((ecx) >> 17) & 0x7f)
|
||||
|
||||
/* Task applied to backdoor pshare hints */
|
||||
#define BDOOR_PSHARE_HINTS_CMD_SHARE 0
|
||||
#define BDOOR_PSHARE_HINTS_CMD_DROP 1
|
||||
#define BDOOR_PSHARE_HINTS_CMD_MAX 2
|
||||
|
||||
#define BDOOR_PSHARE_HINTS_CMD(ecx) (((ecx) >> 24) & 0xff)
|
||||
|
||||
/* Nesting control operations */
|
||||
|
||||
#define NESTING_CONTROL_RESTRICT_BACKDOOR 0
|
||||
#define NESTING_CONTROL_OPEN_BACKDOOR 1
|
||||
#define NESTING_CONTROL_QUERY 2
|
||||
#define NESTING_CONTROL_MAX 2
|
||||
|
||||
/* EFI Boot Order options, nibble-sized. */
|
||||
#define EFI_BOOT_ORDER_TYPE_EFI 0x0
|
||||
#define EFI_BOOT_ORDER_TYPE_LEGACY 0x1
|
||||
#define EFI_BOOT_ORDER_TYPE_NONE 0xf
|
||||
|
||||
#define BDOOR_NETWORK_BOOT_PROTOCOL_NONE 0x0
|
||||
#define BDOOR_NETWORK_BOOT_PROTOCOL_IPV4 0x1
|
||||
#define BDOOR_NETWORK_BOOT_PROTOCOL_IPV6 0x2
|
||||
|
||||
/* High-bandwidth backdoor port. --hpreg */
|
||||
|
||||
#define BDOORHB_PORT 0x5659
|
||||
|
||||
#define BDOORHB_CMD_MESSAGE 0
|
||||
#define BDOORHB_CMD_VASSERT 1
|
||||
#define BDOORHB_CMD_MAX 2
|
||||
|
||||
/*
|
||||
* There is another backdoor which allows access to certain TSC-related
|
||||
* values using otherwise illegal PMC indices when the pseudo_perfctr
|
||||
* control flag is set.
|
||||
*/
|
||||
|
||||
#define BDOOR_PMC_HW_TSC 0x10000
|
||||
#define BDOOR_PMC_REAL_NS 0x10001
|
||||
#define BDOOR_PMC_APPARENT_NS 0x10002
|
||||
#define BDOOR_PMC_PSEUDO_TSC 0x10003
|
||||
|
||||
#define IS_BDOOR_PMC(index) (((index) | 3) == 0x10003)
|
||||
#define BDOOR_CMD(ecx) ((ecx) & 0xffff)
|
||||
|
||||
/* Sub commands for BDOOR_CMD_VMK_INFO */
|
||||
#define BDOOR_CMD_VMK_INFO_ENTRY 1
|
||||
|
||||
#ifdef VMM
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* Backdoor_CmdRequiresFullyValidVCPU --
|
||||
*
|
||||
* A few backdoor commands require the full VCPU to be valid
|
||||
* (including GDTR, IDTR, TR and LDTR). The rest get read/write
|
||||
* access to GPRs and read access to Segment registers (selectors).
|
||||
*
|
||||
* Result:
|
||||
* True iff VECX contains a command that require the full VCPU to
|
||||
* be valid.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
static INLINE Bool
|
||||
Backdoor_CmdRequiresFullyValidVCPU(unsigned cmd)
|
||||
{
|
||||
return cmd == BDOOR_CMD_SIDT ||
|
||||
cmd == BDOOR_CMD_SGDT ||
|
||||
cmd == BDOOR_CMD_SLDT_STR;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
132
Godeps/_workspace/src/github.com/sigma/vmw-guestinfo/include/backdoor_types.h
generated
vendored
Normal file
132
Godeps/_workspace/src/github.com/sigma/vmw-guestinfo/include/backdoor_types.h
generated
vendored
Normal file
@@ -0,0 +1,132 @@
|
||||
/*********************************************************
|
||||
* Copyright (C) 1999-2015 VMware, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published
|
||||
* by the Free Software Foundation version 2.1 and no later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
*********************************************************/
|
||||
|
||||
/*********************************************************
|
||||
* The contents of this file are subject to the terms of the Common
|
||||
* Development and Distribution License (the "License") version 1.0
|
||||
* and no later version. You may not use this file except in
|
||||
* compliance with the License.
|
||||
*
|
||||
* You can obtain a copy of the License at
|
||||
* http://www.opensource.org/licenses/cddl1.php
|
||||
*
|
||||
* See the License for the specific language governing permissions
|
||||
* and limitations under the License.
|
||||
*
|
||||
*********************************************************/
|
||||
|
||||
/*
|
||||
* backdoor_types.h --
|
||||
*
|
||||
* Type definitions for backdoor interaction code.
|
||||
*/
|
||||
|
||||
#ifndef _BACKDOOR_TYPES_H_
|
||||
#define _BACKDOOR_TYPES_H_
|
||||
|
||||
#ifndef VM_I386
|
||||
#error The backdoor protocol is only supported on x86 architectures.
|
||||
#endif
|
||||
|
||||
/*
|
||||
* These #defines are intended for defining register structs as part of
|
||||
* existing named unions. If the union should encapsulate the register
|
||||
* (and nothing else), use DECLARE_REG_NAMED_STRUCT defined below.
|
||||
*/
|
||||
|
||||
#define DECLARE_REG32_STRUCT \
|
||||
struct { \
|
||||
uint16 low; \
|
||||
uint16 high; \
|
||||
} halfs; \
|
||||
uint32 word
|
||||
|
||||
#define DECLARE_REG64_STRUCT \
|
||||
DECLARE_REG32_STRUCT; \
|
||||
struct { \
|
||||
uint32 low; \
|
||||
uint32 high; \
|
||||
} words; \
|
||||
uint64 quad
|
||||
|
||||
#ifndef VM_X86_64
|
||||
#define DECLARE_REG_STRUCT DECLARE_REG32_STRUCT
|
||||
#else
|
||||
#define DECLARE_REG_STRUCT DECLARE_REG64_STRUCT
|
||||
#endif
|
||||
|
||||
#define DECLARE_REG_NAMED_STRUCT(_r) \
|
||||
union { DECLARE_REG_STRUCT; } _r
|
||||
|
||||
/*
|
||||
* Some of the registers are expressed by semantic name, because if they were
|
||||
* expressed as register structs declared above, we could only address them
|
||||
* by fixed size (half-word, word, quad, etc.) instead of by varying size
|
||||
* (size_t, uintptr_t).
|
||||
*
|
||||
* To be cleaner, these registers are expressed ONLY by semantic name,
|
||||
* rather than by a union of the semantic name and a register struct.
|
||||
*/
|
||||
typedef union {
|
||||
struct {
|
||||
DECLARE_REG_NAMED_STRUCT(ax);
|
||||
size_t size; /* Register bx. */
|
||||
DECLARE_REG_NAMED_STRUCT(cx);
|
||||
DECLARE_REG_NAMED_STRUCT(dx);
|
||||
DECLARE_REG_NAMED_STRUCT(si);
|
||||
DECLARE_REG_NAMED_STRUCT(di);
|
||||
} in;
|
||||
struct {
|
||||
DECLARE_REG_NAMED_STRUCT(ax);
|
||||
DECLARE_REG_NAMED_STRUCT(bx);
|
||||
DECLARE_REG_NAMED_STRUCT(cx);
|
||||
DECLARE_REG_NAMED_STRUCT(dx);
|
||||
DECLARE_REG_NAMED_STRUCT(si);
|
||||
DECLARE_REG_NAMED_STRUCT(di);
|
||||
} out;
|
||||
} Backdoor_proto;
|
||||
|
||||
typedef union {
|
||||
struct {
|
||||
DECLARE_REG_NAMED_STRUCT(ax);
|
||||
DECLARE_REG_NAMED_STRUCT(bx);
|
||||
size_t size; /* Register cx. */
|
||||
DECLARE_REG_NAMED_STRUCT(dx);
|
||||
uintptr_t srcAddr; /* Register si. */
|
||||
uintptr_t dstAddr; /* Register di. */
|
||||
DECLARE_REG_NAMED_STRUCT(bp);
|
||||
} in;
|
||||
struct {
|
||||
DECLARE_REG_NAMED_STRUCT(ax);
|
||||
DECLARE_REG_NAMED_STRUCT(bx);
|
||||
DECLARE_REG_NAMED_STRUCT(cx);
|
||||
DECLARE_REG_NAMED_STRUCT(dx);
|
||||
DECLARE_REG_NAMED_STRUCT(si);
|
||||
DECLARE_REG_NAMED_STRUCT(di);
|
||||
DECLARE_REG_NAMED_STRUCT(bp);
|
||||
} out;
|
||||
} Backdoor_proto_hb;
|
||||
|
||||
MY_ASSERTS(BACKDOOR_STRUCT_SIZES,
|
||||
ASSERT_ON_COMPILE(sizeof(Backdoor_proto) == 6 * sizeof(uintptr_t));
|
||||
ASSERT_ON_COMPILE(sizeof(Backdoor_proto_hb) == 7 * sizeof(uintptr_t));
|
||||
)
|
||||
|
||||
#undef DECLARE_REG_STRUCT
|
||||
|
||||
#endif /* _BACKDOOR_TYPES_H_ */
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user