mirror of https://github.com/kubernetes/kops.git
Replace kubernetes mount code with utils
This will remove one of the main dependencies on the kubernetes/kubernetes repo.
This commit is contained in:
parent
5ecf8d9aeb
commit
fc21f4255f
2
go.mod
2
go.mod
|
|
@ -134,7 +134,7 @@ require (
|
|||
k8s.io/klog v0.3.1
|
||||
k8s.io/kubernetes v1.15.3
|
||||
k8s.io/legacy-cloud-providers v0.0.0
|
||||
k8s.io/utils v0.0.0-20190506122338-8fab8cb257d5
|
||||
k8s.io/utils v0.0.0-20191114200735-6ca3b61696b6
|
||||
sigs.k8s.io/controller-runtime v0.2.2
|
||||
sigs.k8s.io/controller-tools v0.2.2-0.20190919191502-76a25b63325a
|
||||
sigs.k8s.io/yaml v1.1.0
|
||||
|
|
|
|||
2
go.sum
2
go.sum
|
|
@ -662,6 +662,8 @@ k8s.io/utils v0.0.0-20190221042446-c2654d5206da h1:ElyM7RPonbKnQqOcw7dG2IK5uvQQn
|
|||
k8s.io/utils v0.0.0-20190221042446-c2654d5206da/go.mod h1:8k8uAuAQ0rXslZKaEWd0c3oVhZz7sSzSiPnVZayjIX0=
|
||||
k8s.io/utils v0.0.0-20190506122338-8fab8cb257d5 h1:VBM/0P5TWxwk+Nw6Z+lAw3DKgO76g90ETOiA6rfLV1Y=
|
||||
k8s.io/utils v0.0.0-20190506122338-8fab8cb257d5/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
|
||||
k8s.io/utils v0.0.0-20191114200735-6ca3b61696b6 h1:p0Ai3qVtkbCG/Af26dBmU0E1W58NID3hSSh7cMyylpM=
|
||||
k8s.io/utils v0.0.0-20191114200735-6ca3b61696b6/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
|
||||
modernc.org/cc v1.0.0/go.mod h1:1Sk4//wdnYJiUIxnW8ddKpaOJCF37yAdqYnkxUpaYxw=
|
||||
modernc.org/golex v1.0.0/go.mod h1:b/QX9oBD/LhixY6NDh+IdGv17hgB+51fET1i2kPSmvk=
|
||||
modernc.org/mathutil v1.0.0/go.mod h1:wU0vUrJsVWBZ4P6e7xtFJEhFSNsfRLJ8H458uRjg03k=
|
||||
|
|
|
|||
|
|
@ -155,6 +155,7 @@ k8s.io/kops/protokube/pkg/gossip/gce
|
|||
k8s.io/kops/protokube/pkg/gossip/memberlist
|
||||
k8s.io/kops/protokube/pkg/gossip/mesh
|
||||
k8s.io/kops/protokube/pkg/gossip/openstack
|
||||
k8s.io/kops/protokube/pkg/hostmount
|
||||
k8s.io/kops/protokube/pkg/protokube
|
||||
k8s.io/kops/protokube/tests/integration/build_etcd_manifest
|
||||
k8s.io/kops/tests
|
||||
|
|
|
|||
|
|
@ -76,7 +76,8 @@ go_library(
|
|||
"//vendor/k8s.io/apimachinery/pkg/util/intstr:go_default_library",
|
||||
"//vendor/k8s.io/client-go/util/cert:go_default_library",
|
||||
"//vendor/k8s.io/klog:go_default_library",
|
||||
"//vendor/k8s.io/kubernetes/pkg/util/mount:go_default_library",
|
||||
"//vendor/k8s.io/utils/exec:go_default_library",
|
||||
"//vendor/k8s.io/utils/mount:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ import (
|
|||
"k8s.io/kops/upup/pkg/fi"
|
||||
"k8s.io/kops/upup/pkg/fi/nodeup/nodetasks"
|
||||
"k8s.io/kops/util/pkg/vfs"
|
||||
"k8s.io/kubernetes/pkg/util/mount"
|
||||
"k8s.io/utils/mount"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/session"
|
||||
|
|
|
|||
|
|
@ -22,7 +22,8 @@ import (
|
|||
"k8s.io/kops/upup/pkg/fi"
|
||||
|
||||
"k8s.io/klog"
|
||||
"k8s.io/kubernetes/pkg/util/mount"
|
||||
utilexec "k8s.io/utils/exec"
|
||||
"k8s.io/utils/mount"
|
||||
)
|
||||
|
||||
// VolumesBuilder maintains the volume mounting
|
||||
|
|
@ -49,7 +50,7 @@ func (b *VolumesBuilder) Build(c *fi.ModelBuilderContext) error {
|
|||
}
|
||||
|
||||
m := &mount.SafeFormatAndMount{
|
||||
Exec: mount.NewOsExec(),
|
||||
Exec: utilexec.New(),
|
||||
Interface: mount.New(""),
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,63 +3,60 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
|||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"nsenter_mount.go",
|
||||
"nsenter_mount_unsupported.go",
|
||||
"nsenter_linux.go",
|
||||
"nsenter_unsupported.go",
|
||||
],
|
||||
importmap = "k8s.io/kops/vendor/k8s.io/kubernetes/pkg/volume/util/nsenter",
|
||||
importpath = "k8s.io/kubernetes/pkg/volume/util/nsenter",
|
||||
importpath = "k8s.io/kops/protokube/pkg/hostmount",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = select({
|
||||
"@io_bazel_rules_go//go/platform:android": [
|
||||
"//vendor/k8s.io/klog:go_default_library",
|
||||
"//vendor/k8s.io/kubernetes/pkg/util/mount:go_default_library",
|
||||
"//vendor/k8s.io/utils/mount:go_default_library",
|
||||
"//vendor/k8s.io/utils/nsenter:go_default_library",
|
||||
"//vendor/k8s.io/utils/path:go_default_library",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:darwin": [
|
||||
"//vendor/k8s.io/kubernetes/pkg/util/mount:go_default_library",
|
||||
"//vendor/k8s.io/utils/mount:go_default_library",
|
||||
"//vendor/k8s.io/utils/nsenter:go_default_library",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:dragonfly": [
|
||||
"//vendor/k8s.io/kubernetes/pkg/util/mount:go_default_library",
|
||||
"//vendor/k8s.io/utils/mount:go_default_library",
|
||||
"//vendor/k8s.io/utils/nsenter:go_default_library",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:freebsd": [
|
||||
"//vendor/k8s.io/kubernetes/pkg/util/mount:go_default_library",
|
||||
"//vendor/k8s.io/utils/mount:go_default_library",
|
||||
"//vendor/k8s.io/utils/nsenter:go_default_library",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:ios": [
|
||||
"//vendor/k8s.io/kubernetes/pkg/util/mount:go_default_library",
|
||||
"//vendor/k8s.io/utils/mount:go_default_library",
|
||||
"//vendor/k8s.io/utils/nsenter:go_default_library",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:linux": [
|
||||
"//vendor/k8s.io/klog:go_default_library",
|
||||
"//vendor/k8s.io/kubernetes/pkg/util/mount:go_default_library",
|
||||
"//vendor/k8s.io/utils/mount:go_default_library",
|
||||
"//vendor/k8s.io/utils/nsenter:go_default_library",
|
||||
"//vendor/k8s.io/utils/path:go_default_library",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:nacl": [
|
||||
"//vendor/k8s.io/kubernetes/pkg/util/mount:go_default_library",
|
||||
"//vendor/k8s.io/utils/mount:go_default_library",
|
||||
"//vendor/k8s.io/utils/nsenter:go_default_library",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:netbsd": [
|
||||
"//vendor/k8s.io/kubernetes/pkg/util/mount:go_default_library",
|
||||
"//vendor/k8s.io/utils/mount:go_default_library",
|
||||
"//vendor/k8s.io/utils/nsenter:go_default_library",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:openbsd": [
|
||||
"//vendor/k8s.io/kubernetes/pkg/util/mount:go_default_library",
|
||||
"//vendor/k8s.io/utils/mount:go_default_library",
|
||||
"//vendor/k8s.io/utils/nsenter:go_default_library",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:plan9": [
|
||||
"//vendor/k8s.io/kubernetes/pkg/util/mount:go_default_library",
|
||||
"//vendor/k8s.io/utils/mount:go_default_library",
|
||||
"//vendor/k8s.io/utils/nsenter:go_default_library",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:solaris": [
|
||||
"//vendor/k8s.io/kubernetes/pkg/util/mount:go_default_library",
|
||||
"//vendor/k8s.io/utils/mount:go_default_library",
|
||||
"//vendor/k8s.io/utils/nsenter:go_default_library",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:windows": [
|
||||
"//vendor/k8s.io/kubernetes/pkg/util/mount:go_default_library",
|
||||
"//vendor/k8s.io/utils/mount:go_default_library",
|
||||
"//vendor/k8s.io/utils/nsenter:go_default_library",
|
||||
],
|
||||
"//conditions:default": [],
|
||||
|
|
@ -0,0 +1,129 @@
|
|||
// +build linux
|
||||
|
||||
/*
|
||||
Copyright 2019 The Kubernetes Authors.
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
package hostmount
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"k8s.io/klog"
|
||||
"k8s.io/utils/mount"
|
||||
"k8s.io/utils/nsenter"
|
||||
)
|
||||
|
||||
// Based on code from kubernetes/kubernetes: https://github.com/kubernetes/kubernetes/blob/release-1.15/pkg/volume/util/nsenter/nsenter_mount.go
|
||||
|
||||
const (
|
||||
// hostProcMountsPath is the default mount path for rootfs
|
||||
hostProcMountsPath = "/rootfs/proc/1/mounts"
|
||||
)
|
||||
|
||||
func New(ne *nsenter.Nsenter) *Mounter {
|
||||
return &Mounter{ne: ne}
|
||||
}
|
||||
|
||||
type Mounter struct {
|
||||
ne *nsenter.Nsenter
|
||||
}
|
||||
|
||||
var _ mount.Interface = &Mounter{}
|
||||
|
||||
// List returns a list of all mounted filesystems in the host's mount namespace.
|
||||
func (*Mounter) List() ([]mount.MountPoint, error) {
|
||||
return mount.ListProcMounts(hostProcMountsPath)
|
||||
}
|
||||
|
||||
// Mount runs mount(8) in the host's root mount namespace. Aside from this
|
||||
// aspect, Mount has the same semantics as the mounter returned by mount.New()
|
||||
func (n *Mounter) Mount(source string, target string, fstype string, options []string) error {
|
||||
bind, bindOpts, bindRemountOpts := mount.MakeBindOpts(options)
|
||||
|
||||
if bind {
|
||||
err := n.doNsenterMount(source, target, fstype, bindOpts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return n.doNsenterMount(source, target, fstype, bindRemountOpts)
|
||||
}
|
||||
|
||||
return n.doNsenterMount(source, target, fstype, options)
|
||||
}
|
||||
|
||||
// doNsenterMount nsenters the host's mount namespace and performs the
|
||||
// requested mount.
|
||||
func (n *Mounter) doNsenterMount(source, target, fstype string, options []string) error {
|
||||
klog.V(5).Infof("nsenter mount %s %s %s %v", source, target, fstype, options)
|
||||
cmd, args := n.makeNsenterArgs(source, target, fstype, options)
|
||||
outputBytes, err := n.ne.Exec(cmd, args).CombinedOutput()
|
||||
if len(outputBytes) != 0 {
|
||||
klog.V(5).Infof("Output of mounting %s to %s: %v", source, target, string(outputBytes))
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// makeNsenterArgs makes a list of argument to nsenter in order to do the
|
||||
// requested mount.
|
||||
func (n *Mounter) makeNsenterArgs(source, target, fstype string, options []string) (string, []string) {
|
||||
mountCmd := n.ne.AbsHostPath("mount")
|
||||
mountArgs := mount.MakeMountArgs(source, target, fstype, options)
|
||||
|
||||
if systemdRunPath, hasSystemd := n.ne.SupportsSystemd(); hasSystemd {
|
||||
// Complete command line:
|
||||
// nsenter --mount=/rootfs/proc/1/ns/mnt -- /bin/systemd-run --description=... --scope -- /bin/mount -t <type> <what> <where>
|
||||
// Expected flow is:
|
||||
// * nsenter breaks out of container's mount namespace and executes
|
||||
// host's systemd-run.
|
||||
// * systemd-run creates a transient scope (=~ cgroup) and executes its
|
||||
// argument (/bin/mount) there.
|
||||
// * mount does its job, forks a fuse daemon if necessary and finishes.
|
||||
// (systemd-run --scope finishes at this point, returning mount's exit
|
||||
// code and stdout/stderr - thats one of --scope benefits).
|
||||
// * systemd keeps the fuse daemon running in the scope (i.e. in its own
|
||||
// cgroup) until the fuse daemon dies (another --scope benefit).
|
||||
// Kubelet container can be restarted and the fuse daemon survives.
|
||||
// * When the daemon dies (e.g. during unmount) systemd removes the
|
||||
// scope automatically.
|
||||
mountCmd, mountArgs = mount.AddSystemdScope(systemdRunPath, target, mountCmd, mountArgs)
|
||||
}
|
||||
|
||||
// Fall back to simple mount when the host has no systemd:
|
||||
// Complete command line:
|
||||
// nsenter --mount=/rootfs/proc/1/ns/mnt -- /bin/mount -t <type> <what> <where>
|
||||
// Expected flow is:
|
||||
// * nsenter breaks out of container's mount namespace and executes host's /bin/mount.
|
||||
// * mount does its job, forks a fuse daemon if necessary and finishes.
|
||||
// * Any fuse daemon runs in cgroup of kubelet docker container,
|
||||
// restart of kubelet container will kill it!
|
||||
// No code here, mountCmd and mountArgs use /bin/mount
|
||||
|
||||
return mountCmd, mountArgs
|
||||
}
|
||||
|
||||
// We deliberately implement only the functions we need, so we don't have to maintain them...
|
||||
|
||||
func (n *Mounter) GetMountRefs(pathname string) ([]string, error) {
|
||||
return nil, fmt.Errorf("GetMountRefs not implemented for containerized mounter")
|
||||
}
|
||||
|
||||
func (mounter *Mounter) IsLikelyNotMountPoint(file string) (bool, error) {
|
||||
return false, fmt.Errorf("IsLikelyNotMountPoint not implemented for containerized mounter")
|
||||
}
|
||||
|
||||
func (n *Mounter) Unmount(target string) error {
|
||||
return fmt.Errorf("Unmount not implemented for containerized mounter")
|
||||
}
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
// +build !linux
|
||||
|
||||
/*
|
||||
Copyright 2014 The Kubernetes Authors.
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
package hostmount
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"k8s.io/utils/mount"
|
||||
"k8s.io/utils/nsenter"
|
||||
)
|
||||
|
||||
func New(ne *nsenter.Nsenter) *Mounter {
|
||||
return &Mounter{}
|
||||
}
|
||||
|
||||
// Mounter implements mount.Interface for unsupported platforms
|
||||
type Mounter struct {
|
||||
}
|
||||
|
||||
var errUnsupported = errors.New("util/mount on this platform is not supported")
|
||||
|
||||
// Mount always returns an error on unsupported platforms
|
||||
func (mounter *Mounter) Mount(source string, target string, fstype string, options []string) error {
|
||||
return errUnsupported
|
||||
}
|
||||
|
||||
// Unmount always returns an error on unsupported platforms
|
||||
func (mounter *Mounter) Unmount(target string) error {
|
||||
return errUnsupported
|
||||
}
|
||||
|
||||
// List always returns an error on unsupported platforms
|
||||
func (mounter *Mounter) List() ([]mount.MountPoint, error) {
|
||||
return []mount.MountPoint{}, errUnsupported
|
||||
}
|
||||
|
||||
// IsLikelyNotMountPoint always returns an error on unsupported platforms
|
||||
func (mounter *Mounter) IsLikelyNotMountPoint(file string) (bool, error) {
|
||||
return true, errUnsupported
|
||||
}
|
||||
|
||||
// GetMountRefs always returns an error on unsupported platforms
|
||||
func (mounter *Mounter) GetMountRefs(pathname string) ([]string, error) {
|
||||
return nil, errUnsupported
|
||||
}
|
||||
|
|
@ -19,7 +19,6 @@ go_library(
|
|||
"kube_dns.go",
|
||||
"labeler.go",
|
||||
"models.go",
|
||||
"nsenter_exec.go",
|
||||
"openstack_volume.go",
|
||||
"rbac.go",
|
||||
"tainter.go",
|
||||
|
|
@ -43,6 +42,7 @@ go_library(
|
|||
"//protokube/pkg/gossip/do:go_default_library",
|
||||
"//protokube/pkg/gossip/gce:go_default_library",
|
||||
"//protokube/pkg/gossip/openstack:go_default_library",
|
||||
"//protokube/pkg/hostmount:go_default_library",
|
||||
"//upup/pkg/fi/cloudup/aliup:go_default_library",
|
||||
"//upup/pkg/fi/cloudup/awsup:go_default_library",
|
||||
"//upup/pkg/fi/cloudup/gce:go_default_library",
|
||||
|
|
@ -76,9 +76,8 @@ go_library(
|
|||
"//vendor/k8s.io/client-go/kubernetes:go_default_library",
|
||||
"//vendor/k8s.io/client-go/tools/clientcmd:go_default_library",
|
||||
"//vendor/k8s.io/klog:go_default_library",
|
||||
"//vendor/k8s.io/kubernetes/pkg/util/mount:go_default_library",
|
||||
"//vendor/k8s.io/kubernetes/pkg/volume/util/nsenter:go_default_library",
|
||||
"//vendor/k8s.io/utils/exec:go_default_library",
|
||||
"//vendor/k8s.io/utils/mount:go_default_library",
|
||||
"//vendor/k8s.io/utils/nsenter:go_default_library",
|
||||
],
|
||||
)
|
||||
|
|
|
|||
|
|
@ -23,7 +23,8 @@ import (
|
|||
"time"
|
||||
|
||||
"k8s.io/klog"
|
||||
"k8s.io/kubernetes/pkg/util/mount"
|
||||
utilexec "k8s.io/utils/exec"
|
||||
"k8s.io/utils/nsenter"
|
||||
)
|
||||
|
||||
var (
|
||||
|
|
@ -184,14 +185,18 @@ func startKubeletService() error {
|
|||
// We run systemctl from the hostfs so we don't need systemd in our image
|
||||
// (and we don't risk version skew)
|
||||
|
||||
exec := mount.NewOsExec()
|
||||
exec := utilexec.New()
|
||||
if Containerized {
|
||||
exec = NewNsEnterExec()
|
||||
e, err := nsenter.NewNsenter(pathFor("/"), utilexec.New())
|
||||
if err != nil {
|
||||
return fmt.Errorf("error building nsenter executor: %v", err)
|
||||
}
|
||||
exec = e
|
||||
}
|
||||
|
||||
systemctlCommand := "systemctl"
|
||||
|
||||
output, err := exec.Run(systemctlCommand, "status", "--no-block", "kubelet")
|
||||
output, err := exec.Command(systemctlCommand, "status", "--no-block", "kubelet").CombinedOutput()
|
||||
klog.V(2).Infof("'systemctl status kubelet' output:\n%s", string(output))
|
||||
if err == nil {
|
||||
klog.V(2).Infof("kubelet systemd service already running")
|
||||
|
|
@ -199,7 +204,7 @@ func startKubeletService() error {
|
|||
}
|
||||
|
||||
klog.Infof("kubelet systemd service not running. Starting")
|
||||
output, err = exec.Run(systemctlCommand, "start", "--no-block", "kubelet")
|
||||
output, err = exec.Command(systemctlCommand, "start", "--no-block", "kubelet").CombinedOutput()
|
||||
if err != nil {
|
||||
return fmt.Errorf("error starting kubelet: %v\nOutput: %s", err, output)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,53 +0,0 @@
|
|||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
package protokube
|
||||
|
||||
import (
|
||||
"k8s.io/klog"
|
||||
"k8s.io/kubernetes/pkg/util/mount"
|
||||
"k8s.io/utils/exec"
|
||||
)
|
||||
|
||||
// Constants from nsenter_mount.go
|
||||
const (
|
||||
hostMountNamespacePath = "/rootfs/proc/1/ns/mnt"
|
||||
nsenterPath = "nsenter"
|
||||
)
|
||||
|
||||
// NewNsEnterExec builds a mount.Exec implementation that nsenters into the host process
|
||||
// It is very similar to mount.NewNsenterMounter, but execs into the host
|
||||
func NewNsEnterExec() mount.Exec {
|
||||
return &nsEnterExec{}
|
||||
}
|
||||
|
||||
// nsEnterExec is an implementation of mount.Exec that runs in the host namespace
|
||||
type nsEnterExec struct{}
|
||||
|
||||
var _ mount.Exec = &nsEnterExec{}
|
||||
|
||||
// Run implements mount.Exec::Run but runs processes in the host namespace
|
||||
func (e *nsEnterExec) Run(cmd string, args ...string) ([]byte, error) {
|
||||
nsenterArgs := []string{
|
||||
"--mount=" + hostMountNamespacePath,
|
||||
"--",
|
||||
cmd,
|
||||
}
|
||||
nsenterArgs = append(nsenterArgs, args...)
|
||||
klog.V(5).Infof("Running command : %v %v", nsenterPath, nsenterArgs)
|
||||
exe := exec.New()
|
||||
return exe.Command(nsenterPath, nsenterArgs...).CombinedOutput()
|
||||
}
|
||||
|
|
@ -24,9 +24,9 @@ import (
|
|||
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
"k8s.io/klog"
|
||||
"k8s.io/kubernetes/pkg/util/mount"
|
||||
nsenterutil "k8s.io/kubernetes/pkg/volume/util/nsenter"
|
||||
utilsexec "k8s.io/utils/exec"
|
||||
"k8s.io/kops/protokube/pkg/hostmount"
|
||||
utilexec "k8s.io/utils/exec"
|
||||
"k8s.io/utils/mount"
|
||||
"k8s.io/utils/nsenter"
|
||||
)
|
||||
|
||||
|
|
@ -115,23 +115,20 @@ func (k *VolumeMountController) safeFormatAndMount(volume *Volume, mountpoint st
|
|||
safeFormatAndMount := &mount.SafeFormatAndMount{}
|
||||
|
||||
if Containerized {
|
||||
ne, err := nsenter.NewNsenter(pathFor("/"), utilsexec.New())
|
||||
ne, err := nsenter.NewNsenter(pathFor("/"), utilexec.New())
|
||||
if err != nil {
|
||||
return fmt.Errorf("error building ns-enter object: %v", err)
|
||||
return fmt.Errorf("error building ns-enter helper: %v", err)
|
||||
}
|
||||
|
||||
// This is a directory that is mounted identically on the container and the host; we don't have that.
|
||||
sharedDir := "/no-shared-directories"
|
||||
|
||||
// Build mount & exec implementations that execute in the host namespaces
|
||||
safeFormatAndMount.Interface = nsenterutil.NewMounter(sharedDir, ne)
|
||||
safeFormatAndMount.Exec = NewNsEnterExec()
|
||||
safeFormatAndMount.Interface = hostmount.New(ne)
|
||||
safeFormatAndMount.Exec = ne
|
||||
|
||||
// Note that we don't use pathFor for operations going through safeFormatAndMount,
|
||||
// because NewNsenterMounter and NewNsEnterExec will operate in the host
|
||||
// Note that we don't use PathFor for operations going through safeFormatAndMount,
|
||||
// because our mounter and nsenter will operate in the host
|
||||
} else {
|
||||
safeFormatAndMount.Interface = mount.New("")
|
||||
safeFormatAndMount.Exec = mount.NewOsExec()
|
||||
safeFormatAndMount.Exec = utilexec.New()
|
||||
}
|
||||
|
||||
// Check if it is already mounted
|
||||
|
|
|
|||
|
|
@ -29,7 +29,8 @@ go_library(
|
|||
"//util/pkg/hashing:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
|
||||
"//vendor/k8s.io/klog:go_default_library",
|
||||
"//vendor/k8s.io/kubernetes/pkg/util/mount:go_default_library",
|
||||
"//vendor/k8s.io/utils/exec:go_default_library",
|
||||
"//vendor/k8s.io/utils/mount:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -27,7 +27,8 @@ import (
|
|||
"k8s.io/kops/upup/pkg/fi/nodeup/cloudinit"
|
||||
"k8s.io/kops/upup/pkg/fi/nodeup/local"
|
||||
"k8s.io/kops/upup/pkg/fi/utils"
|
||||
"k8s.io/kubernetes/pkg/util/mount"
|
||||
utilexec "k8s.io/utils/exec"
|
||||
"k8s.io/utils/mount"
|
||||
)
|
||||
|
||||
// MountDiskTask is responsible for mounting a device on a mountpoint
|
||||
|
|
@ -139,7 +140,7 @@ func (_ *MountDiskTask) RenderLocal(t *local.LocalTarget, a, e, changes *MountDi
|
|||
if changes.Mountpoint != "" {
|
||||
klog.Infof("Mounting device %q on %q", e.Device, e.Mountpoint)
|
||||
|
||||
mounter := &mount.SafeFormatAndMount{Interface: mount.New(""), Exec: mount.NewOsExec()}
|
||||
mounter := &mount.SafeFormatAndMount{Interface: mount.New(""), Exec: utilexec.New()}
|
||||
|
||||
fstype := ""
|
||||
options := []string{}
|
||||
|
|
|
|||
|
|
@ -1,22 +0,0 @@
|
|||
// Copyright 2013 <chaishushan{AT}gmail.com>. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/chai2010/gettext-go/gettext"
|
||||
)
|
||||
|
||||
func main() {
|
||||
gettext.SetLocale("zh_CN")
|
||||
gettext.BindTextdomain("hello", "../examples/local", nil)
|
||||
gettext.Textdomain("hello")
|
||||
|
||||
fmt.Println(gettext.Gettext("Hello, world!"))
|
||||
// Output: 你好, 世界!
|
||||
}
|
||||
|
|
@ -1,76 +0,0 @@
|
|||
// Copyright 2014 Google Inc.
|
||||
//
|
||||
// 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.
|
||||
|
||||
// +build ignore
|
||||
|
||||
// This binary compares memory usage between btree and gollrb.
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"runtime"
|
||||
"time"
|
||||
|
||||
"github.com/google/btree"
|
||||
"github.com/petar/GoLLRB/llrb"
|
||||
)
|
||||
|
||||
var (
|
||||
size = flag.Int("size", 1000000, "size of the tree to build")
|
||||
degree = flag.Int("degree", 8, "degree of btree")
|
||||
gollrb = flag.Bool("llrb", false, "use llrb instead of btree")
|
||||
)
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
vals := rand.Perm(*size)
|
||||
var t, v interface{}
|
||||
v = vals
|
||||
var stats runtime.MemStats
|
||||
for i := 0; i < 10; i++ {
|
||||
runtime.GC()
|
||||
}
|
||||
fmt.Println("-------- BEFORE ----------")
|
||||
runtime.ReadMemStats(&stats)
|
||||
fmt.Printf("%+v\n", stats)
|
||||
start := time.Now()
|
||||
if *gollrb {
|
||||
tr := llrb.New()
|
||||
for _, v := range vals {
|
||||
tr.ReplaceOrInsert(llrb.Int(v))
|
||||
}
|
||||
t = tr // keep it around
|
||||
} else {
|
||||
tr := btree.New(*degree)
|
||||
for _, v := range vals {
|
||||
tr.ReplaceOrInsert(btree.Int(v))
|
||||
}
|
||||
t = tr // keep it around
|
||||
}
|
||||
fmt.Printf("%v inserts in %v\n", *size, time.Since(start))
|
||||
fmt.Println("-------- AFTER ----------")
|
||||
runtime.ReadMemStats(&stats)
|
||||
fmt.Printf("%+v\n", stats)
|
||||
for i := 0; i < 10; i++ {
|
||||
runtime.GC()
|
||||
}
|
||||
fmt.Println("-------- AFTER GC ----------")
|
||||
runtime.ReadMemStats(&stats)
|
||||
fmt.Printf("%+v\n", stats)
|
||||
if t == v {
|
||||
fmt.Println("to make sure vals and tree aren't GC'd")
|
||||
}
|
||||
}
|
||||
|
|
@ -1,198 +0,0 @@
|
|||
//+build ignore
|
||||
|
||||
// compression_generate.go is meant to run with go generate. It will use
|
||||
// go/{importer,types} to track down all the RR struct types. Then for each type
|
||||
// it will look to see if there are (compressible) names, if so it will add that
|
||||
// type to compressionLenHelperType and comressionLenSearchType which "fake" the
|
||||
// compression so that Len() is fast.
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"go/format"
|
||||
"go/importer"
|
||||
"go/types"
|
||||
"log"
|
||||
"os"
|
||||
)
|
||||
|
||||
var packageHdr = `
|
||||
// Code generated by "go run compress_generate.go"; DO NOT EDIT.
|
||||
|
||||
package dns
|
||||
|
||||
`
|
||||
|
||||
// getTypeStruct will take a type and the package scope, and return the
|
||||
// (innermost) struct if the type is considered a RR type (currently defined as
|
||||
// those structs beginning with a RR_Header, could be redefined as implementing
|
||||
// the RR interface). The bool return value indicates if embedded structs were
|
||||
// resolved.
|
||||
func getTypeStruct(t types.Type, scope *types.Scope) (*types.Struct, bool) {
|
||||
st, ok := t.Underlying().(*types.Struct)
|
||||
if !ok {
|
||||
return nil, false
|
||||
}
|
||||
if st.Field(0).Type() == scope.Lookup("RR_Header").Type() {
|
||||
return st, false
|
||||
}
|
||||
if st.Field(0).Anonymous() {
|
||||
st, _ := getTypeStruct(st.Field(0).Type(), scope)
|
||||
return st, true
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
func main() {
|
||||
// Import and type-check the package
|
||||
pkg, err := importer.Default().Import("github.com/miekg/dns")
|
||||
fatalIfErr(err)
|
||||
scope := pkg.Scope()
|
||||
|
||||
var domainTypes []string // Types that have a domain name in them (either compressible or not).
|
||||
var cdomainTypes []string // Types that have a compressible domain name in them (subset of domainType)
|
||||
Names:
|
||||
for _, name := range scope.Names() {
|
||||
o := scope.Lookup(name)
|
||||
if o == nil || !o.Exported() {
|
||||
continue
|
||||
}
|
||||
st, _ := getTypeStruct(o.Type(), scope)
|
||||
if st == nil {
|
||||
continue
|
||||
}
|
||||
if name == "PrivateRR" {
|
||||
continue
|
||||
}
|
||||
|
||||
if scope.Lookup("Type"+o.Name()) == nil && o.Name() != "RFC3597" {
|
||||
log.Fatalf("Constant Type%s does not exist.", o.Name())
|
||||
}
|
||||
|
||||
for i := 1; i < st.NumFields(); i++ {
|
||||
if _, ok := st.Field(i).Type().(*types.Slice); ok {
|
||||
if st.Tag(i) == `dns:"domain-name"` {
|
||||
domainTypes = append(domainTypes, o.Name())
|
||||
continue Names
|
||||
}
|
||||
if st.Tag(i) == `dns:"cdomain-name"` {
|
||||
cdomainTypes = append(cdomainTypes, o.Name())
|
||||
domainTypes = append(domainTypes, o.Name())
|
||||
continue Names
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
switch {
|
||||
case st.Tag(i) == `dns:"domain-name"`:
|
||||
domainTypes = append(domainTypes, o.Name())
|
||||
continue Names
|
||||
case st.Tag(i) == `dns:"cdomain-name"`:
|
||||
cdomainTypes = append(cdomainTypes, o.Name())
|
||||
domainTypes = append(domainTypes, o.Name())
|
||||
continue Names
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
b := &bytes.Buffer{}
|
||||
b.WriteString(packageHdr)
|
||||
|
||||
// compressionLenHelperType - all types that have domain-name/cdomain-name can be used for compressing names
|
||||
|
||||
fmt.Fprint(b, "func compressionLenHelperType(c map[string]int, r RR, initLen int) int {\n")
|
||||
fmt.Fprint(b, "currentLen := initLen\n")
|
||||
fmt.Fprint(b, "switch x := r.(type) {\n")
|
||||
for _, name := range domainTypes {
|
||||
o := scope.Lookup(name)
|
||||
st, _ := getTypeStruct(o.Type(), scope)
|
||||
|
||||
fmt.Fprintf(b, "case *%s:\n", name)
|
||||
for i := 1; i < st.NumFields(); i++ {
|
||||
out := func(s string) {
|
||||
fmt.Fprintf(b, "currentLen -= len(x.%s) + 1\n", st.Field(i).Name())
|
||||
fmt.Fprintf(b, "currentLen += compressionLenHelper(c, x.%s, currentLen)\n", st.Field(i).Name())
|
||||
}
|
||||
|
||||
if _, ok := st.Field(i).Type().(*types.Slice); ok {
|
||||
switch st.Tag(i) {
|
||||
case `dns:"domain-name"`:
|
||||
fallthrough
|
||||
case `dns:"cdomain-name"`:
|
||||
// For HIP we need to slice over the elements in this slice.
|
||||
fmt.Fprintf(b, `for i := range x.%s {
|
||||
currentLen -= len(x.%s[i]) + 1
|
||||
}
|
||||
`, st.Field(i).Name(), st.Field(i).Name())
|
||||
fmt.Fprintf(b, `for i := range x.%s {
|
||||
currentLen += compressionLenHelper(c, x.%s[i], currentLen)
|
||||
}
|
||||
`, st.Field(i).Name(), st.Field(i).Name())
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
switch {
|
||||
case st.Tag(i) == `dns:"cdomain-name"`:
|
||||
fallthrough
|
||||
case st.Tag(i) == `dns:"domain-name"`:
|
||||
out(st.Field(i).Name())
|
||||
}
|
||||
}
|
||||
}
|
||||
fmt.Fprintln(b, "}\nreturn currentLen - initLen\n}\n\n")
|
||||
|
||||
// compressionLenSearchType - search cdomain-tags types for compressible names.
|
||||
|
||||
fmt.Fprint(b, "func compressionLenSearchType(c map[string]int, r RR) (int, bool, int) {\n")
|
||||
fmt.Fprint(b, "switch x := r.(type) {\n")
|
||||
for _, name := range cdomainTypes {
|
||||
o := scope.Lookup(name)
|
||||
st, _ := getTypeStruct(o.Type(), scope)
|
||||
|
||||
fmt.Fprintf(b, "case *%s:\n", name)
|
||||
j := 1
|
||||
for i := 1; i < st.NumFields(); i++ {
|
||||
out := func(s string, j int) {
|
||||
fmt.Fprintf(b, "k%d, ok%d, sz%d := compressionLenSearch(c, x.%s)\n", j, j, j, st.Field(i).Name())
|
||||
}
|
||||
|
||||
// There are no slice types with names that can be compressed.
|
||||
|
||||
switch {
|
||||
case st.Tag(i) == `dns:"cdomain-name"`:
|
||||
out(st.Field(i).Name(), j)
|
||||
j++
|
||||
}
|
||||
}
|
||||
k := "k1"
|
||||
ok := "ok1"
|
||||
sz := "sz1"
|
||||
for i := 2; i < j; i++ {
|
||||
k += fmt.Sprintf(" + k%d", i)
|
||||
ok += fmt.Sprintf(" && ok%d", i)
|
||||
sz += fmt.Sprintf(" + sz%d", i)
|
||||
}
|
||||
fmt.Fprintf(b, "return %s, %s, %s\n", k, ok, sz)
|
||||
}
|
||||
fmt.Fprintln(b, "}\nreturn 0, false, 0\n}\n\n")
|
||||
|
||||
// gofmt
|
||||
res, err := format.Source(b.Bytes())
|
||||
if err != nil {
|
||||
b.WriteTo(os.Stderr)
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
f, err := os.Create("zcompress.go")
|
||||
fatalIfErr(err)
|
||||
defer f.Close()
|
||||
f.Write(res)
|
||||
}
|
||||
|
||||
func fatalIfErr(err error) {
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,158 +0,0 @@
|
|||
//+build ignore
|
||||
|
||||
// types_generate.go is meant to run with go generate. It will use
|
||||
// go/{importer,types} to track down all the RR struct types. Then for each type
|
||||
// it will generate conversion tables (TypeToRR and TypeToString) and banal
|
||||
// methods (len, Header, copy) based on the struct tags. The generated source is
|
||||
// written to ztypes.go, and is meant to be checked into git.
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"go/format"
|
||||
"go/importer"
|
||||
"go/types"
|
||||
"log"
|
||||
"os"
|
||||
)
|
||||
|
||||
var packageHdr = `
|
||||
// Code generated by "go run duplicate_generate.go"; DO NOT EDIT.
|
||||
|
||||
package dns
|
||||
|
||||
`
|
||||
|
||||
func getTypeStruct(t types.Type, scope *types.Scope) (*types.Struct, bool) {
|
||||
st, ok := t.Underlying().(*types.Struct)
|
||||
if !ok {
|
||||
return nil, false
|
||||
}
|
||||
if st.Field(0).Type() == scope.Lookup("RR_Header").Type() {
|
||||
return st, false
|
||||
}
|
||||
if st.Field(0).Anonymous() {
|
||||
st, _ := getTypeStruct(st.Field(0).Type(), scope)
|
||||
return st, true
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
func main() {
|
||||
// Import and type-check the package
|
||||
pkg, err := importer.Default().Import("github.com/miekg/dns")
|
||||
fatalIfErr(err)
|
||||
scope := pkg.Scope()
|
||||
|
||||
// Collect actual types (*X)
|
||||
var namedTypes []string
|
||||
for _, name := range scope.Names() {
|
||||
o := scope.Lookup(name)
|
||||
if o == nil || !o.Exported() {
|
||||
continue
|
||||
}
|
||||
|
||||
if st, _ := getTypeStruct(o.Type(), scope); st == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
if name == "PrivateRR" || name == "RFC3597" {
|
||||
continue
|
||||
}
|
||||
if name == "OPT" || name == "ANY" || name == "IXFR" || name == "AXFR" {
|
||||
continue
|
||||
}
|
||||
|
||||
namedTypes = append(namedTypes, o.Name())
|
||||
}
|
||||
|
||||
b := &bytes.Buffer{}
|
||||
b.WriteString(packageHdr)
|
||||
|
||||
// Generate the giant switch that calls the correct function for each type.
|
||||
fmt.Fprint(b, "// isDuplicateRdata calls the rdata specific functions\n")
|
||||
fmt.Fprint(b, "func isDuplicateRdata(r1, r2 RR) bool {\n")
|
||||
fmt.Fprint(b, "switch r1.Header().Rrtype {\n")
|
||||
|
||||
for _, name := range namedTypes {
|
||||
|
||||
o := scope.Lookup(name)
|
||||
_, isEmbedded := getTypeStruct(o.Type(), scope)
|
||||
if isEmbedded {
|
||||
continue
|
||||
}
|
||||
fmt.Fprintf(b, "case Type%s:\nreturn isDuplicate%s(r1.(*%s), r2.(*%s))\n", name, name, name, name)
|
||||
}
|
||||
fmt.Fprintf(b, "}\nreturn false\n}\n")
|
||||
|
||||
// Generate the duplicate check for each type.
|
||||
fmt.Fprint(b, "// isDuplicate() functions\n\n")
|
||||
for _, name := range namedTypes {
|
||||
|
||||
o := scope.Lookup(name)
|
||||
st, isEmbedded := getTypeStruct(o.Type(), scope)
|
||||
if isEmbedded {
|
||||
continue
|
||||
}
|
||||
fmt.Fprintf(b, "func isDuplicate%s(r1, r2 *%s) bool {\n", name, name)
|
||||
for i := 1; i < st.NumFields(); i++ {
|
||||
field := st.Field(i).Name()
|
||||
o2 := func(s string) { fmt.Fprintf(b, s+"\n", field, field) }
|
||||
o3 := func(s string) { fmt.Fprintf(b, s+"\n", field, field, field) }
|
||||
|
||||
// For some reason, a and aaaa don't pop up as *types.Slice here (mostly like because the are
|
||||
// *indirectly* defined as a slice in the net package).
|
||||
if _, ok := st.Field(i).Type().(*types.Slice); ok || st.Tag(i) == `dns:"a"` || st.Tag(i) == `dns:"aaaa"` {
|
||||
o2("if len(r1.%s) != len(r2.%s) {\nreturn false\n}")
|
||||
|
||||
if st.Tag(i) == `dns:"cdomain-name"` || st.Tag(i) == `dns:"domain-name"` {
|
||||
o3(`for i := 0; i < len(r1.%s); i++ {
|
||||
if !isDulicateName(r1.%s[i], r2.%s[i]) {
|
||||
return false
|
||||
}
|
||||
}`)
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
o3(`for i := 0; i < len(r1.%s); i++ {
|
||||
if r1.%s[i] != r2.%s[i] {
|
||||
return false
|
||||
}
|
||||
}`)
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
switch st.Tag(i) {
|
||||
case `dns:"-"`:
|
||||
// ignored
|
||||
case `dns:"cdomain-name"`, `dns:"domain-name"`:
|
||||
o2("if !isDulicateName(r1.%s, r2.%s) {\nreturn false\n}")
|
||||
default:
|
||||
o2("if r1.%s != r2.%s {\nreturn false\n}")
|
||||
}
|
||||
}
|
||||
fmt.Fprintf(b, "return true\n}\n\n")
|
||||
}
|
||||
|
||||
// gofmt
|
||||
res, err := format.Source(b.Bytes())
|
||||
if err != nil {
|
||||
b.WriteTo(os.Stderr)
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
// write result
|
||||
f, err := os.Create("zduplicate.go")
|
||||
fatalIfErr(err)
|
||||
defer f.Close()
|
||||
f.Write(res)
|
||||
}
|
||||
|
||||
func fatalIfErr(err error) {
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,348 +0,0 @@
|
|||
//+build ignore
|
||||
|
||||
// msg_generate.go is meant to run with go generate. It will use
|
||||
// go/{importer,types} to track down all the RR struct types. Then for each type
|
||||
// it will generate pack/unpack methods based on the struct tags. The generated source is
|
||||
// written to zmsg.go, and is meant to be checked into git.
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"go/format"
|
||||
"go/importer"
|
||||
"go/types"
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var packageHdr = `
|
||||
// Code generated by "go run msg_generate.go"; DO NOT EDIT.
|
||||
|
||||
package dns
|
||||
|
||||
`
|
||||
|
||||
// getTypeStruct will take a type and the package scope, and return the
|
||||
// (innermost) struct if the type is considered a RR type (currently defined as
|
||||
// those structs beginning with a RR_Header, could be redefined as implementing
|
||||
// the RR interface). The bool return value indicates if embedded structs were
|
||||
// resolved.
|
||||
func getTypeStruct(t types.Type, scope *types.Scope) (*types.Struct, bool) {
|
||||
st, ok := t.Underlying().(*types.Struct)
|
||||
if !ok {
|
||||
return nil, false
|
||||
}
|
||||
if st.Field(0).Type() == scope.Lookup("RR_Header").Type() {
|
||||
return st, false
|
||||
}
|
||||
if st.Field(0).Anonymous() {
|
||||
st, _ := getTypeStruct(st.Field(0).Type(), scope)
|
||||
return st, true
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
func main() {
|
||||
// Import and type-check the package
|
||||
pkg, err := importer.Default().Import("github.com/miekg/dns")
|
||||
fatalIfErr(err)
|
||||
scope := pkg.Scope()
|
||||
|
||||
// Collect actual types (*X)
|
||||
var namedTypes []string
|
||||
for _, name := range scope.Names() {
|
||||
o := scope.Lookup(name)
|
||||
if o == nil || !o.Exported() {
|
||||
continue
|
||||
}
|
||||
if st, _ := getTypeStruct(o.Type(), scope); st == nil {
|
||||
continue
|
||||
}
|
||||
if name == "PrivateRR" {
|
||||
continue
|
||||
}
|
||||
|
||||
// Check if corresponding TypeX exists
|
||||
if scope.Lookup("Type"+o.Name()) == nil && o.Name() != "RFC3597" {
|
||||
log.Fatalf("Constant Type%s does not exist.", o.Name())
|
||||
}
|
||||
|
||||
namedTypes = append(namedTypes, o.Name())
|
||||
}
|
||||
|
||||
b := &bytes.Buffer{}
|
||||
b.WriteString(packageHdr)
|
||||
|
||||
fmt.Fprint(b, "// pack*() functions\n\n")
|
||||
for _, name := range namedTypes {
|
||||
o := scope.Lookup(name)
|
||||
st, _ := getTypeStruct(o.Type(), scope)
|
||||
|
||||
fmt.Fprintf(b, "func (rr *%s) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {\n", name)
|
||||
fmt.Fprint(b, `off, err := rr.Hdr.pack(msg, off, compression, compress)
|
||||
if err != nil {
|
||||
return off, err
|
||||
}
|
||||
headerEnd := off
|
||||
`)
|
||||
for i := 1; i < st.NumFields(); i++ {
|
||||
o := func(s string) {
|
||||
fmt.Fprintf(b, s, st.Field(i).Name())
|
||||
fmt.Fprint(b, `if err != nil {
|
||||
return off, err
|
||||
}
|
||||
`)
|
||||
}
|
||||
|
||||
if _, ok := st.Field(i).Type().(*types.Slice); ok {
|
||||
switch st.Tag(i) {
|
||||
case `dns:"-"`: // ignored
|
||||
case `dns:"txt"`:
|
||||
o("off, err = packStringTxt(rr.%s, msg, off)\n")
|
||||
case `dns:"opt"`:
|
||||
o("off, err = packDataOpt(rr.%s, msg, off)\n")
|
||||
case `dns:"nsec"`:
|
||||
o("off, err = packDataNsec(rr.%s, msg, off)\n")
|
||||
case `dns:"domain-name"`:
|
||||
o("off, err = packDataDomainNames(rr.%s, msg, off, compression, compress)\n")
|
||||
default:
|
||||
log.Fatalln(name, st.Field(i).Name(), st.Tag(i))
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
switch {
|
||||
case st.Tag(i) == `dns:"-"`: // ignored
|
||||
case st.Tag(i) == `dns:"cdomain-name"`:
|
||||
o("off, err = PackDomainName(rr.%s, msg, off, compression, compress)\n")
|
||||
case st.Tag(i) == `dns:"domain-name"`:
|
||||
o("off, err = PackDomainName(rr.%s, msg, off, compression, false)\n")
|
||||
case st.Tag(i) == `dns:"a"`:
|
||||
o("off, err = packDataA(rr.%s, msg, off)\n")
|
||||
case st.Tag(i) == `dns:"aaaa"`:
|
||||
o("off, err = packDataAAAA(rr.%s, msg, off)\n")
|
||||
case st.Tag(i) == `dns:"uint48"`:
|
||||
o("off, err = packUint48(rr.%s, msg, off)\n")
|
||||
case st.Tag(i) == `dns:"txt"`:
|
||||
o("off, err = packString(rr.%s, msg, off)\n")
|
||||
|
||||
case strings.HasPrefix(st.Tag(i), `dns:"size-base32`): // size-base32 can be packed just like base32
|
||||
fallthrough
|
||||
case st.Tag(i) == `dns:"base32"`:
|
||||
o("off, err = packStringBase32(rr.%s, msg, off)\n")
|
||||
|
||||
case strings.HasPrefix(st.Tag(i), `dns:"size-base64`): // size-base64 can be packed just like base64
|
||||
fallthrough
|
||||
case st.Tag(i) == `dns:"base64"`:
|
||||
o("off, err = packStringBase64(rr.%s, msg, off)\n")
|
||||
|
||||
case strings.HasPrefix(st.Tag(i), `dns:"size-hex:SaltLength`):
|
||||
// directly write instead of using o() so we get the error check in the correct place
|
||||
field := st.Field(i).Name()
|
||||
fmt.Fprintf(b, `// Only pack salt if value is not "-", i.e. empty
|
||||
if rr.%s != "-" {
|
||||
off, err = packStringHex(rr.%s, msg, off)
|
||||
if err != nil {
|
||||
return off, err
|
||||
}
|
||||
}
|
||||
`, field, field)
|
||||
continue
|
||||
case strings.HasPrefix(st.Tag(i), `dns:"size-hex`): // size-hex can be packed just like hex
|
||||
fallthrough
|
||||
case st.Tag(i) == `dns:"hex"`:
|
||||
o("off, err = packStringHex(rr.%s, msg, off)\n")
|
||||
|
||||
case st.Tag(i) == `dns:"octet"`:
|
||||
o("off, err = packStringOctet(rr.%s, msg, off)\n")
|
||||
case st.Tag(i) == "":
|
||||
switch st.Field(i).Type().(*types.Basic).Kind() {
|
||||
case types.Uint8:
|
||||
o("off, err = packUint8(rr.%s, msg, off)\n")
|
||||
case types.Uint16:
|
||||
o("off, err = packUint16(rr.%s, msg, off)\n")
|
||||
case types.Uint32:
|
||||
o("off, err = packUint32(rr.%s, msg, off)\n")
|
||||
case types.Uint64:
|
||||
o("off, err = packUint64(rr.%s, msg, off)\n")
|
||||
case types.String:
|
||||
o("off, err = packString(rr.%s, msg, off)\n")
|
||||
default:
|
||||
log.Fatalln(name, st.Field(i).Name())
|
||||
}
|
||||
default:
|
||||
log.Fatalln(name, st.Field(i).Name(), st.Tag(i))
|
||||
}
|
||||
}
|
||||
// We have packed everything, only now we know the rdlength of this RR
|
||||
fmt.Fprintln(b, "rr.Header().Rdlength = uint16(off-headerEnd)")
|
||||
fmt.Fprintln(b, "return off, nil }\n")
|
||||
}
|
||||
|
||||
fmt.Fprint(b, "// unpack*() functions\n\n")
|
||||
for _, name := range namedTypes {
|
||||
o := scope.Lookup(name)
|
||||
st, _ := getTypeStruct(o.Type(), scope)
|
||||
|
||||
fmt.Fprintf(b, "func unpack%s(h RR_Header, msg []byte, off int) (RR, int, error) {\n", name)
|
||||
fmt.Fprintf(b, "rr := new(%s)\n", name)
|
||||
fmt.Fprint(b, "rr.Hdr = h\n")
|
||||
fmt.Fprint(b, `if noRdata(h) {
|
||||
return rr, off, nil
|
||||
}
|
||||
var err error
|
||||
rdStart := off
|
||||
_ = rdStart
|
||||
|
||||
`)
|
||||
for i := 1; i < st.NumFields(); i++ {
|
||||
o := func(s string) {
|
||||
fmt.Fprintf(b, s, st.Field(i).Name())
|
||||
fmt.Fprint(b, `if err != nil {
|
||||
return rr, off, err
|
||||
}
|
||||
`)
|
||||
}
|
||||
|
||||
// size-* are special, because they reference a struct member we should use for the length.
|
||||
if strings.HasPrefix(st.Tag(i), `dns:"size-`) {
|
||||
structMember := structMember(st.Tag(i))
|
||||
structTag := structTag(st.Tag(i))
|
||||
switch structTag {
|
||||
case "hex":
|
||||
fmt.Fprintf(b, "rr.%s, off, err = unpackStringHex(msg, off, off + int(rr.%s))\n", st.Field(i).Name(), structMember)
|
||||
case "base32":
|
||||
fmt.Fprintf(b, "rr.%s, off, err = unpackStringBase32(msg, off, off + int(rr.%s))\n", st.Field(i).Name(), structMember)
|
||||
case "base64":
|
||||
fmt.Fprintf(b, "rr.%s, off, err = unpackStringBase64(msg, off, off + int(rr.%s))\n", st.Field(i).Name(), structMember)
|
||||
default:
|
||||
log.Fatalln(name, st.Field(i).Name(), st.Tag(i))
|
||||
}
|
||||
fmt.Fprint(b, `if err != nil {
|
||||
return rr, off, err
|
||||
}
|
||||
`)
|
||||
continue
|
||||
}
|
||||
|
||||
if _, ok := st.Field(i).Type().(*types.Slice); ok {
|
||||
switch st.Tag(i) {
|
||||
case `dns:"-"`: // ignored
|
||||
case `dns:"txt"`:
|
||||
o("rr.%s, off, err = unpackStringTxt(msg, off)\n")
|
||||
case `dns:"opt"`:
|
||||
o("rr.%s, off, err = unpackDataOpt(msg, off)\n")
|
||||
case `dns:"nsec"`:
|
||||
o("rr.%s, off, err = unpackDataNsec(msg, off)\n")
|
||||
case `dns:"domain-name"`:
|
||||
o("rr.%s, off, err = unpackDataDomainNames(msg, off, rdStart + int(rr.Hdr.Rdlength))\n")
|
||||
default:
|
||||
log.Fatalln(name, st.Field(i).Name(), st.Tag(i))
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
switch st.Tag(i) {
|
||||
case `dns:"-"`: // ignored
|
||||
case `dns:"cdomain-name"`:
|
||||
fallthrough
|
||||
case `dns:"domain-name"`:
|
||||
o("rr.%s, off, err = UnpackDomainName(msg, off)\n")
|
||||
case `dns:"a"`:
|
||||
o("rr.%s, off, err = unpackDataA(msg, off)\n")
|
||||
case `dns:"aaaa"`:
|
||||
o("rr.%s, off, err = unpackDataAAAA(msg, off)\n")
|
||||
case `dns:"uint48"`:
|
||||
o("rr.%s, off, err = unpackUint48(msg, off)\n")
|
||||
case `dns:"txt"`:
|
||||
o("rr.%s, off, err = unpackString(msg, off)\n")
|
||||
case `dns:"base32"`:
|
||||
o("rr.%s, off, err = unpackStringBase32(msg, off, rdStart + int(rr.Hdr.Rdlength))\n")
|
||||
case `dns:"base64"`:
|
||||
o("rr.%s, off, err = unpackStringBase64(msg, off, rdStart + int(rr.Hdr.Rdlength))\n")
|
||||
case `dns:"hex"`:
|
||||
o("rr.%s, off, err = unpackStringHex(msg, off, rdStart + int(rr.Hdr.Rdlength))\n")
|
||||
case `dns:"octet"`:
|
||||
o("rr.%s, off, err = unpackStringOctet(msg, off)\n")
|
||||
case "":
|
||||
switch st.Field(i).Type().(*types.Basic).Kind() {
|
||||
case types.Uint8:
|
||||
o("rr.%s, off, err = unpackUint8(msg, off)\n")
|
||||
case types.Uint16:
|
||||
o("rr.%s, off, err = unpackUint16(msg, off)\n")
|
||||
case types.Uint32:
|
||||
o("rr.%s, off, err = unpackUint32(msg, off)\n")
|
||||
case types.Uint64:
|
||||
o("rr.%s, off, err = unpackUint64(msg, off)\n")
|
||||
case types.String:
|
||||
o("rr.%s, off, err = unpackString(msg, off)\n")
|
||||
default:
|
||||
log.Fatalln(name, st.Field(i).Name())
|
||||
}
|
||||
default:
|
||||
log.Fatalln(name, st.Field(i).Name(), st.Tag(i))
|
||||
}
|
||||
// If we've hit len(msg) we return without error.
|
||||
if i < st.NumFields()-1 {
|
||||
fmt.Fprintf(b, `if off == len(msg) {
|
||||
return rr, off, nil
|
||||
}
|
||||
`)
|
||||
}
|
||||
}
|
||||
fmt.Fprintf(b, "return rr, off, err }\n\n")
|
||||
}
|
||||
// Generate typeToUnpack map
|
||||
fmt.Fprintln(b, "var typeToUnpack = map[uint16]func(RR_Header, []byte, int) (RR, int, error){")
|
||||
for _, name := range namedTypes {
|
||||
if name == "RFC3597" {
|
||||
continue
|
||||
}
|
||||
fmt.Fprintf(b, "Type%s: unpack%s,\n", name, name)
|
||||
}
|
||||
fmt.Fprintln(b, "}\n")
|
||||
|
||||
// gofmt
|
||||
res, err := format.Source(b.Bytes())
|
||||
if err != nil {
|
||||
b.WriteTo(os.Stderr)
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
// write result
|
||||
f, err := os.Create("zmsg.go")
|
||||
fatalIfErr(err)
|
||||
defer f.Close()
|
||||
f.Write(res)
|
||||
}
|
||||
|
||||
// structMember will take a tag like dns:"size-base32:SaltLength" and return the last part of this string.
|
||||
func structMember(s string) string {
|
||||
fields := strings.Split(s, ":")
|
||||
if len(fields) == 0 {
|
||||
return ""
|
||||
}
|
||||
f := fields[len(fields)-1]
|
||||
// f should have a closing "
|
||||
if len(f) > 1 {
|
||||
return f[:len(f)-1]
|
||||
}
|
||||
return f
|
||||
}
|
||||
|
||||
// structTag will take a tag like dns:"size-base32:SaltLength" and return base32.
|
||||
func structTag(s string) string {
|
||||
fields := strings.Split(s, ":")
|
||||
if len(fields) < 2 {
|
||||
return ""
|
||||
}
|
||||
return fields[1][len("\"size-"):]
|
||||
}
|
||||
|
||||
func fatalIfErr(err error) {
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,272 +0,0 @@
|
|||
//+build ignore
|
||||
|
||||
// types_generate.go is meant to run with go generate. It will use
|
||||
// go/{importer,types} to track down all the RR struct types. Then for each type
|
||||
// it will generate conversion tables (TypeToRR and TypeToString) and banal
|
||||
// methods (len, Header, copy) based on the struct tags. The generated source is
|
||||
// written to ztypes.go, and is meant to be checked into git.
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"go/format"
|
||||
"go/importer"
|
||||
"go/types"
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
"text/template"
|
||||
)
|
||||
|
||||
var skipLen = map[string]struct{}{
|
||||
"NSEC": {},
|
||||
"NSEC3": {},
|
||||
"OPT": {},
|
||||
"CSYNC": {},
|
||||
}
|
||||
|
||||
var packageHdr = `
|
||||
// Code generated by "go run types_generate.go"; DO NOT EDIT.
|
||||
|
||||
package dns
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"net"
|
||||
)
|
||||
|
||||
`
|
||||
|
||||
var TypeToRR = template.Must(template.New("TypeToRR").Parse(`
|
||||
// TypeToRR is a map of constructors for each RR type.
|
||||
var TypeToRR = map[uint16]func() RR{
|
||||
{{range .}}{{if ne . "RFC3597"}} Type{{.}}: func() RR { return new({{.}}) },
|
||||
{{end}}{{end}} }
|
||||
|
||||
`))
|
||||
|
||||
var typeToString = template.Must(template.New("typeToString").Parse(`
|
||||
// TypeToString is a map of strings for each RR type.
|
||||
var TypeToString = map[uint16]string{
|
||||
{{range .}}{{if ne . "NSAPPTR"}} Type{{.}}: "{{.}}",
|
||||
{{end}}{{end}} TypeNSAPPTR: "NSAP-PTR",
|
||||
}
|
||||
|
||||
`))
|
||||
|
||||
var headerFunc = template.Must(template.New("headerFunc").Parse(`
|
||||
{{range .}} func (rr *{{.}}) Header() *RR_Header { return &rr.Hdr }
|
||||
{{end}}
|
||||
|
||||
`))
|
||||
|
||||
// getTypeStruct will take a type and the package scope, and return the
|
||||
// (innermost) struct if the type is considered a RR type (currently defined as
|
||||
// those structs beginning with a RR_Header, could be redefined as implementing
|
||||
// the RR interface). The bool return value indicates if embedded structs were
|
||||
// resolved.
|
||||
func getTypeStruct(t types.Type, scope *types.Scope) (*types.Struct, bool) {
|
||||
st, ok := t.Underlying().(*types.Struct)
|
||||
if !ok {
|
||||
return nil, false
|
||||
}
|
||||
if st.Field(0).Type() == scope.Lookup("RR_Header").Type() {
|
||||
return st, false
|
||||
}
|
||||
if st.Field(0).Anonymous() {
|
||||
st, _ := getTypeStruct(st.Field(0).Type(), scope)
|
||||
return st, true
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
func main() {
|
||||
// Import and type-check the package
|
||||
pkg, err := importer.Default().Import("github.com/miekg/dns")
|
||||
fatalIfErr(err)
|
||||
scope := pkg.Scope()
|
||||
|
||||
// Collect constants like TypeX
|
||||
var numberedTypes []string
|
||||
for _, name := range scope.Names() {
|
||||
o := scope.Lookup(name)
|
||||
if o == nil || !o.Exported() {
|
||||
continue
|
||||
}
|
||||
b, ok := o.Type().(*types.Basic)
|
||||
if !ok || b.Kind() != types.Uint16 {
|
||||
continue
|
||||
}
|
||||
if !strings.HasPrefix(o.Name(), "Type") {
|
||||
continue
|
||||
}
|
||||
name := strings.TrimPrefix(o.Name(), "Type")
|
||||
if name == "PrivateRR" {
|
||||
continue
|
||||
}
|
||||
numberedTypes = append(numberedTypes, name)
|
||||
}
|
||||
|
||||
// Collect actual types (*X)
|
||||
var namedTypes []string
|
||||
for _, name := range scope.Names() {
|
||||
o := scope.Lookup(name)
|
||||
if o == nil || !o.Exported() {
|
||||
continue
|
||||
}
|
||||
if st, _ := getTypeStruct(o.Type(), scope); st == nil {
|
||||
continue
|
||||
}
|
||||
if name == "PrivateRR" {
|
||||
continue
|
||||
}
|
||||
|
||||
// Check if corresponding TypeX exists
|
||||
if scope.Lookup("Type"+o.Name()) == nil && o.Name() != "RFC3597" {
|
||||
log.Fatalf("Constant Type%s does not exist.", o.Name())
|
||||
}
|
||||
|
||||
namedTypes = append(namedTypes, o.Name())
|
||||
}
|
||||
|
||||
b := &bytes.Buffer{}
|
||||
b.WriteString(packageHdr)
|
||||
|
||||
// Generate TypeToRR
|
||||
fatalIfErr(TypeToRR.Execute(b, namedTypes))
|
||||
|
||||
// Generate typeToString
|
||||
fatalIfErr(typeToString.Execute(b, numberedTypes))
|
||||
|
||||
// Generate headerFunc
|
||||
fatalIfErr(headerFunc.Execute(b, namedTypes))
|
||||
|
||||
// Generate len()
|
||||
fmt.Fprint(b, "// len() functions\n")
|
||||
for _, name := range namedTypes {
|
||||
if _, ok := skipLen[name]; ok {
|
||||
continue
|
||||
}
|
||||
o := scope.Lookup(name)
|
||||
st, isEmbedded := getTypeStruct(o.Type(), scope)
|
||||
if isEmbedded {
|
||||
continue
|
||||
}
|
||||
fmt.Fprintf(b, "func (rr *%s) len() int {\n", name)
|
||||
fmt.Fprintf(b, "l := rr.Hdr.len()\n")
|
||||
for i := 1; i < st.NumFields(); i++ {
|
||||
o := func(s string) { fmt.Fprintf(b, s, st.Field(i).Name()) }
|
||||
|
||||
if _, ok := st.Field(i).Type().(*types.Slice); ok {
|
||||
switch st.Tag(i) {
|
||||
case `dns:"-"`:
|
||||
// ignored
|
||||
case `dns:"cdomain-name"`, `dns:"domain-name"`, `dns:"txt"`:
|
||||
o("for _, x := range rr.%s { l += len(x) + 1 }\n")
|
||||
default:
|
||||
log.Fatalln(name, st.Field(i).Name(), st.Tag(i))
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
switch {
|
||||
case st.Tag(i) == `dns:"-"`:
|
||||
// ignored
|
||||
case st.Tag(i) == `dns:"cdomain-name"`, st.Tag(i) == `dns:"domain-name"`:
|
||||
o("l += len(rr.%s) + 1\n")
|
||||
case st.Tag(i) == `dns:"octet"`:
|
||||
o("l += len(rr.%s)\n")
|
||||
case strings.HasPrefix(st.Tag(i), `dns:"size-base64`):
|
||||
fallthrough
|
||||
case st.Tag(i) == `dns:"base64"`:
|
||||
o("l += base64.StdEncoding.DecodedLen(len(rr.%s))\n")
|
||||
case strings.HasPrefix(st.Tag(i), `dns:"size-hex:`): // this has an extra field where the length is stored
|
||||
o("l += len(rr.%s)/2\n")
|
||||
case strings.HasPrefix(st.Tag(i), `dns:"size-hex`):
|
||||
fallthrough
|
||||
case st.Tag(i) == `dns:"hex"`:
|
||||
o("l += len(rr.%s)/2 + 1\n")
|
||||
case st.Tag(i) == `dns:"a"`:
|
||||
o("l += net.IPv4len // %s\n")
|
||||
case st.Tag(i) == `dns:"aaaa"`:
|
||||
o("l += net.IPv6len // %s\n")
|
||||
case st.Tag(i) == `dns:"txt"`:
|
||||
o("for _, t := range rr.%s { l += len(t) + 1 }\n")
|
||||
case st.Tag(i) == `dns:"uint48"`:
|
||||
o("l += 6 // %s\n")
|
||||
case st.Tag(i) == "":
|
||||
switch st.Field(i).Type().(*types.Basic).Kind() {
|
||||
case types.Uint8:
|
||||
o("l++ // %s\n")
|
||||
case types.Uint16:
|
||||
o("l += 2 // %s\n")
|
||||
case types.Uint32:
|
||||
o("l += 4 // %s\n")
|
||||
case types.Uint64:
|
||||
o("l += 8 // %s\n")
|
||||
case types.String:
|
||||
o("l += len(rr.%s) + 1\n")
|
||||
default:
|
||||
log.Fatalln(name, st.Field(i).Name())
|
||||
}
|
||||
default:
|
||||
log.Fatalln(name, st.Field(i).Name(), st.Tag(i))
|
||||
}
|
||||
}
|
||||
fmt.Fprintf(b, "return l }\n")
|
||||
}
|
||||
|
||||
// Generate copy()
|
||||
fmt.Fprint(b, "// copy() functions\n")
|
||||
for _, name := range namedTypes {
|
||||
o := scope.Lookup(name)
|
||||
st, isEmbedded := getTypeStruct(o.Type(), scope)
|
||||
if isEmbedded {
|
||||
continue
|
||||
}
|
||||
fmt.Fprintf(b, "func (rr *%s) copy() RR {\n", name)
|
||||
fields := []string{"rr.Hdr"}
|
||||
for i := 1; i < st.NumFields(); i++ {
|
||||
f := st.Field(i).Name()
|
||||
if sl, ok := st.Field(i).Type().(*types.Slice); ok {
|
||||
t := sl.Underlying().String()
|
||||
t = strings.TrimPrefix(t, "[]")
|
||||
if strings.Contains(t, ".") {
|
||||
splits := strings.Split(t, ".")
|
||||
t = splits[len(splits)-1]
|
||||
}
|
||||
fmt.Fprintf(b, "%s := make([]%s, len(rr.%s)); copy(%s, rr.%s)\n",
|
||||
f, t, f, f, f)
|
||||
fields = append(fields, f)
|
||||
continue
|
||||
}
|
||||
if st.Field(i).Type().String() == "net.IP" {
|
||||
fields = append(fields, "copyIP(rr."+f+")")
|
||||
continue
|
||||
}
|
||||
fields = append(fields, "rr."+f)
|
||||
}
|
||||
fmt.Fprintf(b, "return &%s{%s}\n", name, strings.Join(fields, ","))
|
||||
fmt.Fprintf(b, "}\n")
|
||||
}
|
||||
|
||||
// gofmt
|
||||
res, err := format.Source(b.Bytes())
|
||||
if err != nil {
|
||||
b.WriteTo(os.Stderr)
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
// write result
|
||||
f, err := os.Create("ztypes.go")
|
||||
fatalIfErr(err)
|
||||
defer f.Close()
|
||||
f.Write(res)
|
||||
}
|
||||
|
||||
func fatalIfErr(err error) {
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,383 +0,0 @@
|
|||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
//go:generate go run gen.go
|
||||
|
||||
// This program generates internet protocol constants and tables by
|
||||
// reading IANA protocol registries.
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/xml"
|
||||
"fmt"
|
||||
"go/format"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var registries = []struct {
|
||||
url string
|
||||
parse func(io.Writer, io.Reader) error
|
||||
}{
|
||||
{
|
||||
"https://www.iana.org/assignments/dscp-registry/dscp-registry.xml",
|
||||
parseDSCPRegistry,
|
||||
},
|
||||
{
|
||||
"https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xml",
|
||||
parseProtocolNumbers,
|
||||
},
|
||||
{
|
||||
"https://www.iana.org/assignments/address-family-numbers/address-family-numbers.xml",
|
||||
parseAddrFamilyNumbers,
|
||||
},
|
||||
}
|
||||
|
||||
func main() {
|
||||
var bb bytes.Buffer
|
||||
fmt.Fprintf(&bb, "// go generate gen.go\n")
|
||||
fmt.Fprintf(&bb, "// Code generated by the command above; DO NOT EDIT.\n\n")
|
||||
fmt.Fprintf(&bb, "// Package iana provides protocol number resources managed by the Internet Assigned Numbers Authority (IANA).\n")
|
||||
fmt.Fprintf(&bb, `package iana // import "golang.org/x/net/internal/iana"`+"\n\n")
|
||||
for _, r := range registries {
|
||||
resp, err := http.Get(r.url)
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
fmt.Fprintf(os.Stderr, "got HTTP status code %v for %v\n", resp.StatusCode, r.url)
|
||||
os.Exit(1)
|
||||
}
|
||||
if err := r.parse(&bb, resp.Body); err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
fmt.Fprintf(&bb, "\n")
|
||||
}
|
||||
b, err := format.Source(bb.Bytes())
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
if err := ioutil.WriteFile("const.go", b, 0644); err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func parseDSCPRegistry(w io.Writer, r io.Reader) error {
|
||||
dec := xml.NewDecoder(r)
|
||||
var dr dscpRegistry
|
||||
if err := dec.Decode(&dr); err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Fprintf(w, "// %s, Updated: %s\n", dr.Title, dr.Updated)
|
||||
fmt.Fprintf(w, "const (\n")
|
||||
for _, dr := range dr.escapeDSCP() {
|
||||
fmt.Fprintf(w, "DiffServ%s = %#02x", dr.Name, dr.Value)
|
||||
fmt.Fprintf(w, "// %s\n", dr.OrigName)
|
||||
}
|
||||
for _, er := range dr.escapeECN() {
|
||||
fmt.Fprintf(w, "%s = %#02x", er.Descr, er.Value)
|
||||
fmt.Fprintf(w, "// %s\n", er.OrigDescr)
|
||||
}
|
||||
fmt.Fprintf(w, ")\n")
|
||||
return nil
|
||||
}
|
||||
|
||||
type dscpRegistry struct {
|
||||
XMLName xml.Name `xml:"registry"`
|
||||
Title string `xml:"title"`
|
||||
Updated string `xml:"updated"`
|
||||
Note string `xml:"note"`
|
||||
Registries []struct {
|
||||
Title string `xml:"title"`
|
||||
Registries []struct {
|
||||
Title string `xml:"title"`
|
||||
Records []struct {
|
||||
Name string `xml:"name"`
|
||||
Space string `xml:"space"`
|
||||
} `xml:"record"`
|
||||
} `xml:"registry"`
|
||||
Records []struct {
|
||||
Value string `xml:"value"`
|
||||
Descr string `xml:"description"`
|
||||
} `xml:"record"`
|
||||
} `xml:"registry"`
|
||||
}
|
||||
|
||||
type canonDSCPRecord struct {
|
||||
OrigName string
|
||||
Name string
|
||||
Value int
|
||||
}
|
||||
|
||||
func (drr *dscpRegistry) escapeDSCP() []canonDSCPRecord {
|
||||
var drs []canonDSCPRecord
|
||||
for _, preg := range drr.Registries {
|
||||
if !strings.Contains(preg.Title, "Differentiated Services Field Codepoints") {
|
||||
continue
|
||||
}
|
||||
for _, reg := range preg.Registries {
|
||||
if !strings.Contains(reg.Title, "Pool 1 Codepoints") {
|
||||
continue
|
||||
}
|
||||
drs = make([]canonDSCPRecord, len(reg.Records))
|
||||
sr := strings.NewReplacer(
|
||||
"+", "",
|
||||
"-", "",
|
||||
"/", "",
|
||||
".", "",
|
||||
" ", "",
|
||||
)
|
||||
for i, dr := range reg.Records {
|
||||
s := strings.TrimSpace(dr.Name)
|
||||
drs[i].OrigName = s
|
||||
drs[i].Name = sr.Replace(s)
|
||||
n, err := strconv.ParseUint(dr.Space, 2, 8)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
drs[i].Value = int(n) << 2
|
||||
}
|
||||
}
|
||||
}
|
||||
return drs
|
||||
}
|
||||
|
||||
type canonECNRecord struct {
|
||||
OrigDescr string
|
||||
Descr string
|
||||
Value int
|
||||
}
|
||||
|
||||
func (drr *dscpRegistry) escapeECN() []canonECNRecord {
|
||||
var ers []canonECNRecord
|
||||
for _, reg := range drr.Registries {
|
||||
if !strings.Contains(reg.Title, "ECN Field") {
|
||||
continue
|
||||
}
|
||||
ers = make([]canonECNRecord, len(reg.Records))
|
||||
sr := strings.NewReplacer(
|
||||
"Capable", "",
|
||||
"Not-ECT", "",
|
||||
"ECT(1)", "",
|
||||
"ECT(0)", "",
|
||||
"CE", "",
|
||||
"(", "",
|
||||
")", "",
|
||||
"+", "",
|
||||
"-", "",
|
||||
"/", "",
|
||||
".", "",
|
||||
" ", "",
|
||||
)
|
||||
for i, er := range reg.Records {
|
||||
s := strings.TrimSpace(er.Descr)
|
||||
ers[i].OrigDescr = s
|
||||
ss := strings.Split(s, " ")
|
||||
if len(ss) > 1 {
|
||||
ers[i].Descr = strings.Join(ss[1:], " ")
|
||||
} else {
|
||||
ers[i].Descr = ss[0]
|
||||
}
|
||||
ers[i].Descr = sr.Replace(er.Descr)
|
||||
n, err := strconv.ParseUint(er.Value, 2, 8)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
ers[i].Value = int(n)
|
||||
}
|
||||
}
|
||||
return ers
|
||||
}
|
||||
|
||||
func parseProtocolNumbers(w io.Writer, r io.Reader) error {
|
||||
dec := xml.NewDecoder(r)
|
||||
var pn protocolNumbers
|
||||
if err := dec.Decode(&pn); err != nil {
|
||||
return err
|
||||
}
|
||||
prs := pn.escape()
|
||||
prs = append([]canonProtocolRecord{{
|
||||
Name: "IP",
|
||||
Descr: "IPv4 encapsulation, pseudo protocol number",
|
||||
Value: 0,
|
||||
}}, prs...)
|
||||
fmt.Fprintf(w, "// %s, Updated: %s\n", pn.Title, pn.Updated)
|
||||
fmt.Fprintf(w, "const (\n")
|
||||
for _, pr := range prs {
|
||||
if pr.Name == "" {
|
||||
continue
|
||||
}
|
||||
fmt.Fprintf(w, "Protocol%s = %d", pr.Name, pr.Value)
|
||||
s := pr.Descr
|
||||
if s == "" {
|
||||
s = pr.OrigName
|
||||
}
|
||||
fmt.Fprintf(w, "// %s\n", s)
|
||||
}
|
||||
fmt.Fprintf(w, ")\n")
|
||||
return nil
|
||||
}
|
||||
|
||||
type protocolNumbers struct {
|
||||
XMLName xml.Name `xml:"registry"`
|
||||
Title string `xml:"title"`
|
||||
Updated string `xml:"updated"`
|
||||
RegTitle string `xml:"registry>title"`
|
||||
Note string `xml:"registry>note"`
|
||||
Records []struct {
|
||||
Value string `xml:"value"`
|
||||
Name string `xml:"name"`
|
||||
Descr string `xml:"description"`
|
||||
} `xml:"registry>record"`
|
||||
}
|
||||
|
||||
type canonProtocolRecord struct {
|
||||
OrigName string
|
||||
Name string
|
||||
Descr string
|
||||
Value int
|
||||
}
|
||||
|
||||
func (pn *protocolNumbers) escape() []canonProtocolRecord {
|
||||
prs := make([]canonProtocolRecord, len(pn.Records))
|
||||
sr := strings.NewReplacer(
|
||||
"-in-", "in",
|
||||
"-within-", "within",
|
||||
"-over-", "over",
|
||||
"+", "P",
|
||||
"-", "",
|
||||
"/", "",
|
||||
".", "",
|
||||
" ", "",
|
||||
)
|
||||
for i, pr := range pn.Records {
|
||||
if strings.Contains(pr.Name, "Deprecated") ||
|
||||
strings.Contains(pr.Name, "deprecated") {
|
||||
continue
|
||||
}
|
||||
prs[i].OrigName = pr.Name
|
||||
s := strings.TrimSpace(pr.Name)
|
||||
switch pr.Name {
|
||||
case "ISIS over IPv4":
|
||||
prs[i].Name = "ISIS"
|
||||
case "manet":
|
||||
prs[i].Name = "MANET"
|
||||
default:
|
||||
prs[i].Name = sr.Replace(s)
|
||||
}
|
||||
ss := strings.Split(pr.Descr, "\n")
|
||||
for i := range ss {
|
||||
ss[i] = strings.TrimSpace(ss[i])
|
||||
}
|
||||
if len(ss) > 1 {
|
||||
prs[i].Descr = strings.Join(ss, " ")
|
||||
} else {
|
||||
prs[i].Descr = ss[0]
|
||||
}
|
||||
prs[i].Value, _ = strconv.Atoi(pr.Value)
|
||||
}
|
||||
return prs
|
||||
}
|
||||
|
||||
func parseAddrFamilyNumbers(w io.Writer, r io.Reader) error {
|
||||
dec := xml.NewDecoder(r)
|
||||
var afn addrFamilylNumbers
|
||||
if err := dec.Decode(&afn); err != nil {
|
||||
return err
|
||||
}
|
||||
afrs := afn.escape()
|
||||
fmt.Fprintf(w, "// %s, Updated: %s\n", afn.Title, afn.Updated)
|
||||
fmt.Fprintf(w, "const (\n")
|
||||
for _, afr := range afrs {
|
||||
if afr.Name == "" {
|
||||
continue
|
||||
}
|
||||
fmt.Fprintf(w, "AddrFamily%s = %d", afr.Name, afr.Value)
|
||||
fmt.Fprintf(w, "// %s\n", afr.Descr)
|
||||
}
|
||||
fmt.Fprintf(w, ")\n")
|
||||
return nil
|
||||
}
|
||||
|
||||
type addrFamilylNumbers struct {
|
||||
XMLName xml.Name `xml:"registry"`
|
||||
Title string `xml:"title"`
|
||||
Updated string `xml:"updated"`
|
||||
RegTitle string `xml:"registry>title"`
|
||||
Note string `xml:"registry>note"`
|
||||
Records []struct {
|
||||
Value string `xml:"value"`
|
||||
Descr string `xml:"description"`
|
||||
} `xml:"registry>record"`
|
||||
}
|
||||
|
||||
type canonAddrFamilyRecord struct {
|
||||
Name string
|
||||
Descr string
|
||||
Value int
|
||||
}
|
||||
|
||||
func (afn *addrFamilylNumbers) escape() []canonAddrFamilyRecord {
|
||||
afrs := make([]canonAddrFamilyRecord, len(afn.Records))
|
||||
sr := strings.NewReplacer(
|
||||
"IP version 4", "IPv4",
|
||||
"IP version 6", "IPv6",
|
||||
"Identifier", "ID",
|
||||
"-", "",
|
||||
"-", "",
|
||||
"/", "",
|
||||
".", "",
|
||||
" ", "",
|
||||
)
|
||||
for i, afr := range afn.Records {
|
||||
if strings.Contains(afr.Descr, "Unassigned") ||
|
||||
strings.Contains(afr.Descr, "Reserved") {
|
||||
continue
|
||||
}
|
||||
afrs[i].Descr = afr.Descr
|
||||
s := strings.TrimSpace(afr.Descr)
|
||||
switch s {
|
||||
case "IP (IP version 4)":
|
||||
afrs[i].Name = "IPv4"
|
||||
case "IP6 (IP version 6)":
|
||||
afrs[i].Name = "IPv6"
|
||||
case "AFI for L2VPN information":
|
||||
afrs[i].Name = "L2VPN"
|
||||
case "E.164 with NSAP format subaddress":
|
||||
afrs[i].Name = "E164withSubaddress"
|
||||
case "MT IP: Multi-Topology IP version 4":
|
||||
afrs[i].Name = "MTIPv4"
|
||||
case "MAC/24":
|
||||
afrs[i].Name = "MACFinal24bits"
|
||||
case "MAC/40":
|
||||
afrs[i].Name = "MACFinal40bits"
|
||||
case "IPv6/64":
|
||||
afrs[i].Name = "IPv6Initial64bits"
|
||||
default:
|
||||
n := strings.Index(s, "(")
|
||||
if n > 0 {
|
||||
s = s[:n]
|
||||
}
|
||||
n = strings.Index(s, ":")
|
||||
if n > 0 {
|
||||
s = s[:n]
|
||||
}
|
||||
afrs[i].Name = sr.Replace(s)
|
||||
}
|
||||
afrs[i].Value, _ = strconv.Atoi(afr.Value)
|
||||
}
|
||||
return afrs
|
||||
}
|
||||
|
|
@ -89,7 +89,6 @@ go_library(
|
|||
"zsys_openbsd_arm.go",
|
||||
"zsys_solaris_amd64.go",
|
||||
],
|
||||
cgo = True,
|
||||
importmap = "k8s.io/kops/vendor/golang.org/x/net/internal/socket",
|
||||
importpath = "golang.org/x/net/internal/socket",
|
||||
visibility = ["//vendor/golang.org/x/net:__subpackages__"],
|
||||
|
|
|
|||
|
|
@ -1,44 +0,0 @@
|
|||
// Copyright 2017 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
// +godefs map struct_in_addr [4]byte /* in_addr */
|
||||
// +godefs map struct_in6_addr [16]byte /* in6_addr */
|
||||
|
||||
package socket
|
||||
|
||||
/*
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
*/
|
||||
import "C"
|
||||
|
||||
const (
|
||||
sysAF_UNSPEC = C.AF_UNSPEC
|
||||
sysAF_INET = C.AF_INET
|
||||
sysAF_INET6 = C.AF_INET6
|
||||
|
||||
sysSOCK_RAW = C.SOCK_RAW
|
||||
)
|
||||
|
||||
type iovec C.struct_iovec
|
||||
|
||||
type msghdr C.struct_msghdr
|
||||
|
||||
type cmsghdr C.struct_cmsghdr
|
||||
|
||||
type sockaddrInet C.struct_sockaddr_in
|
||||
|
||||
type sockaddrInet6 C.struct_sockaddr_in6
|
||||
|
||||
const (
|
||||
sizeofIovec = C.sizeof_struct_iovec
|
||||
sizeofMsghdr = C.sizeof_struct_msghdr
|
||||
sizeofCmsghdr = C.sizeof_struct_cmsghdr
|
||||
|
||||
sizeofSockaddrInet = C.sizeof_struct_sockaddr_in
|
||||
sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
|
||||
)
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
// Copyright 2017 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
// +godefs map struct_in_addr [4]byte /* in_addr */
|
||||
// +godefs map struct_in6_addr [16]byte /* in6_addr */
|
||||
|
||||
package socket
|
||||
|
||||
/*
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
*/
|
||||
import "C"
|
||||
|
||||
const (
|
||||
sysAF_UNSPEC = C.AF_UNSPEC
|
||||
sysAF_INET = C.AF_INET
|
||||
sysAF_INET6 = C.AF_INET6
|
||||
|
||||
sysSOCK_RAW = C.SOCK_RAW
|
||||
)
|
||||
|
||||
type iovec C.struct_iovec
|
||||
|
||||
type msghdr C.struct_msghdr
|
||||
|
||||
type cmsghdr C.struct_cmsghdr
|
||||
|
||||
type sockaddrInet C.struct_sockaddr_in
|
||||
|
||||
type sockaddrInet6 C.struct_sockaddr_in6
|
||||
|
||||
const (
|
||||
sizeofIovec = C.sizeof_struct_iovec
|
||||
sizeofMsghdr = C.sizeof_struct_msghdr
|
||||
sizeofCmsghdr = C.sizeof_struct_cmsghdr
|
||||
|
||||
sizeofSockaddrInet = C.sizeof_struct_sockaddr_in
|
||||
sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
|
||||
)
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
// Copyright 2017 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
// +godefs map struct_in_addr [4]byte /* in_addr */
|
||||
// +godefs map struct_in6_addr [16]byte /* in6_addr */
|
||||
|
||||
package socket
|
||||
|
||||
/*
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
*/
|
||||
import "C"
|
||||
|
||||
const (
|
||||
sysAF_UNSPEC = C.AF_UNSPEC
|
||||
sysAF_INET = C.AF_INET
|
||||
sysAF_INET6 = C.AF_INET6
|
||||
|
||||
sysSOCK_RAW = C.SOCK_RAW
|
||||
)
|
||||
|
||||
type iovec C.struct_iovec
|
||||
|
||||
type msghdr C.struct_msghdr
|
||||
|
||||
type cmsghdr C.struct_cmsghdr
|
||||
|
||||
type sockaddrInet C.struct_sockaddr_in
|
||||
|
||||
type sockaddrInet6 C.struct_sockaddr_in6
|
||||
|
||||
const (
|
||||
sizeofIovec = C.sizeof_struct_iovec
|
||||
sizeofMsghdr = C.sizeof_struct_msghdr
|
||||
sizeofCmsghdr = C.sizeof_struct_cmsghdr
|
||||
|
||||
sizeofSockaddrInet = C.sizeof_struct_sockaddr_in
|
||||
sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
|
||||
)
|
||||
|
|
@ -1,49 +0,0 @@
|
|||
// Copyright 2017 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
// +godefs map struct_in_addr [4]byte /* in_addr */
|
||||
// +godefs map struct_in6_addr [16]byte /* in6_addr */
|
||||
|
||||
package socket
|
||||
|
||||
/*
|
||||
#include <linux/in.h>
|
||||
#include <linux/in6.h>
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <sys/socket.h>
|
||||
*/
|
||||
import "C"
|
||||
|
||||
const (
|
||||
sysAF_UNSPEC = C.AF_UNSPEC
|
||||
sysAF_INET = C.AF_INET
|
||||
sysAF_INET6 = C.AF_INET6
|
||||
|
||||
sysSOCK_RAW = C.SOCK_RAW
|
||||
)
|
||||
|
||||
type iovec C.struct_iovec
|
||||
|
||||
type msghdr C.struct_msghdr
|
||||
|
||||
type mmsghdr C.struct_mmsghdr
|
||||
|
||||
type cmsghdr C.struct_cmsghdr
|
||||
|
||||
type sockaddrInet C.struct_sockaddr_in
|
||||
|
||||
type sockaddrInet6 C.struct_sockaddr_in6
|
||||
|
||||
const (
|
||||
sizeofIovec = C.sizeof_struct_iovec
|
||||
sizeofMsghdr = C.sizeof_struct_msghdr
|
||||
sizeofMmsghdr = C.sizeof_struct_mmsghdr
|
||||
sizeofCmsghdr = C.sizeof_struct_cmsghdr
|
||||
|
||||
sizeofSockaddrInet = C.sizeof_struct_sockaddr_in
|
||||
sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
|
||||
)
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
// Copyright 2017 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
// +godefs map struct_in_addr [4]byte /* in_addr */
|
||||
// +godefs map struct_in6_addr [16]byte /* in6_addr */
|
||||
|
||||
package socket
|
||||
|
||||
/*
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
*/
|
||||
import "C"
|
||||
|
||||
const (
|
||||
sysAF_UNSPEC = C.AF_UNSPEC
|
||||
sysAF_INET = C.AF_INET
|
||||
sysAF_INET6 = C.AF_INET6
|
||||
|
||||
sysSOCK_RAW = C.SOCK_RAW
|
||||
)
|
||||
|
||||
type iovec C.struct_iovec
|
||||
|
||||
type msghdr C.struct_msghdr
|
||||
|
||||
type mmsghdr C.struct_mmsghdr
|
||||
|
||||
type cmsghdr C.struct_cmsghdr
|
||||
|
||||
type sockaddrInet C.struct_sockaddr_in
|
||||
|
||||
type sockaddrInet6 C.struct_sockaddr_in6
|
||||
|
||||
const (
|
||||
sizeofIovec = C.sizeof_struct_iovec
|
||||
sizeofMsghdr = C.sizeof_struct_msghdr
|
||||
sizeofMmsghdr = C.sizeof_struct_mmsghdr
|
||||
sizeofCmsghdr = C.sizeof_struct_cmsghdr
|
||||
|
||||
sizeofSockaddrInet = C.sizeof_struct_sockaddr_in
|
||||
sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
|
||||
)
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
// Copyright 2017 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
// +godefs map struct_in_addr [4]byte /* in_addr */
|
||||
// +godefs map struct_in6_addr [16]byte /* in6_addr */
|
||||
|
||||
package socket
|
||||
|
||||
/*
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
*/
|
||||
import "C"
|
||||
|
||||
const (
|
||||
sysAF_UNSPEC = C.AF_UNSPEC
|
||||
sysAF_INET = C.AF_INET
|
||||
sysAF_INET6 = C.AF_INET6
|
||||
|
||||
sysSOCK_RAW = C.SOCK_RAW
|
||||
)
|
||||
|
||||
type iovec C.struct_iovec
|
||||
|
||||
type msghdr C.struct_msghdr
|
||||
|
||||
type cmsghdr C.struct_cmsghdr
|
||||
|
||||
type sockaddrInet C.struct_sockaddr_in
|
||||
|
||||
type sockaddrInet6 C.struct_sockaddr_in6
|
||||
|
||||
const (
|
||||
sizeofIovec = C.sizeof_struct_iovec
|
||||
sizeofMsghdr = C.sizeof_struct_msghdr
|
||||
sizeofCmsghdr = C.sizeof_struct_cmsghdr
|
||||
|
||||
sizeofSockaddrInet = C.sizeof_struct_sockaddr_in
|
||||
sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
|
||||
)
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
// Copyright 2017 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
// +godefs map struct_in_addr [4]byte /* in_addr */
|
||||
// +godefs map struct_in6_addr [16]byte /* in6_addr */
|
||||
|
||||
package socket
|
||||
|
||||
/*
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
*/
|
||||
import "C"
|
||||
|
||||
const (
|
||||
sysAF_UNSPEC = C.AF_UNSPEC
|
||||
sysAF_INET = C.AF_INET
|
||||
sysAF_INET6 = C.AF_INET6
|
||||
|
||||
sysSOCK_RAW = C.SOCK_RAW
|
||||
)
|
||||
|
||||
type iovec C.struct_iovec
|
||||
|
||||
type msghdr C.struct_msghdr
|
||||
|
||||
type cmsghdr C.struct_cmsghdr
|
||||
|
||||
type sockaddrInet C.struct_sockaddr_in
|
||||
|
||||
type sockaddrInet6 C.struct_sockaddr_in6
|
||||
|
||||
const (
|
||||
sizeofIovec = C.sizeof_struct_iovec
|
||||
sizeofMsghdr = C.sizeof_struct_msghdr
|
||||
sizeofCmsghdr = C.sizeof_struct_cmsghdr
|
||||
|
||||
sizeofSockaddrInet = C.sizeof_struct_sockaddr_in
|
||||
sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
|
||||
)
|
||||
|
|
@ -68,7 +68,6 @@ go_library(
|
|||
"zsys_openbsd.go",
|
||||
"zsys_solaris.go",
|
||||
],
|
||||
cgo = True,
|
||||
importmap = "k8s.io/kops/vendor/golang.org/x/net/ipv4",
|
||||
importpath = "golang.org/x/net/ipv4",
|
||||
visibility = ["//visibility:public"],
|
||||
|
|
|
|||
|
|
@ -1,77 +0,0 @@
|
|||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
// +godefs map struct_in_addr [4]byte /* in_addr */
|
||||
|
||||
package ipv4
|
||||
|
||||
/*
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
*/
|
||||
import "C"
|
||||
|
||||
const (
|
||||
sysIP_OPTIONS = C.IP_OPTIONS
|
||||
sysIP_HDRINCL = C.IP_HDRINCL
|
||||
sysIP_TOS = C.IP_TOS
|
||||
sysIP_TTL = C.IP_TTL
|
||||
sysIP_RECVOPTS = C.IP_RECVOPTS
|
||||
sysIP_RECVRETOPTS = C.IP_RECVRETOPTS
|
||||
sysIP_RECVDSTADDR = C.IP_RECVDSTADDR
|
||||
sysIP_RETOPTS = C.IP_RETOPTS
|
||||
sysIP_RECVIF = C.IP_RECVIF
|
||||
sysIP_STRIPHDR = C.IP_STRIPHDR
|
||||
sysIP_RECVTTL = C.IP_RECVTTL
|
||||
sysIP_BOUND_IF = C.IP_BOUND_IF
|
||||
sysIP_PKTINFO = C.IP_PKTINFO
|
||||
sysIP_RECVPKTINFO = C.IP_RECVPKTINFO
|
||||
|
||||
sysIP_MULTICAST_IF = C.IP_MULTICAST_IF
|
||||
sysIP_MULTICAST_TTL = C.IP_MULTICAST_TTL
|
||||
sysIP_MULTICAST_LOOP = C.IP_MULTICAST_LOOP
|
||||
sysIP_ADD_MEMBERSHIP = C.IP_ADD_MEMBERSHIP
|
||||
sysIP_DROP_MEMBERSHIP = C.IP_DROP_MEMBERSHIP
|
||||
sysIP_MULTICAST_VIF = C.IP_MULTICAST_VIF
|
||||
sysIP_MULTICAST_IFINDEX = C.IP_MULTICAST_IFINDEX
|
||||
sysIP_ADD_SOURCE_MEMBERSHIP = C.IP_ADD_SOURCE_MEMBERSHIP
|
||||
sysIP_DROP_SOURCE_MEMBERSHIP = C.IP_DROP_SOURCE_MEMBERSHIP
|
||||
sysIP_BLOCK_SOURCE = C.IP_BLOCK_SOURCE
|
||||
sysIP_UNBLOCK_SOURCE = C.IP_UNBLOCK_SOURCE
|
||||
sysMCAST_JOIN_GROUP = C.MCAST_JOIN_GROUP
|
||||
sysMCAST_LEAVE_GROUP = C.MCAST_LEAVE_GROUP
|
||||
sysMCAST_JOIN_SOURCE_GROUP = C.MCAST_JOIN_SOURCE_GROUP
|
||||
sysMCAST_LEAVE_SOURCE_GROUP = C.MCAST_LEAVE_SOURCE_GROUP
|
||||
sysMCAST_BLOCK_SOURCE = C.MCAST_BLOCK_SOURCE
|
||||
sysMCAST_UNBLOCK_SOURCE = C.MCAST_UNBLOCK_SOURCE
|
||||
|
||||
sizeofSockaddrStorage = C.sizeof_struct_sockaddr_storage
|
||||
sizeofSockaddrInet = C.sizeof_struct_sockaddr_in
|
||||
sizeofInetPktinfo = C.sizeof_struct_in_pktinfo
|
||||
|
||||
sizeofIPMreq = C.sizeof_struct_ip_mreq
|
||||
sizeofIPMreqn = C.sizeof_struct_ip_mreqn
|
||||
sizeofIPMreqSource = C.sizeof_struct_ip_mreq_source
|
||||
sizeofGroupReq = C.sizeof_struct_group_req
|
||||
sizeofGroupSourceReq = C.sizeof_struct_group_source_req
|
||||
)
|
||||
|
||||
type sockaddrStorage C.struct_sockaddr_storage
|
||||
|
||||
type sockaddrInet C.struct_sockaddr_in
|
||||
|
||||
type inetPktinfo C.struct_in_pktinfo
|
||||
|
||||
type ipMreq C.struct_ip_mreq
|
||||
|
||||
type ipMreqn C.struct_ip_mreqn
|
||||
|
||||
type ipMreqSource C.struct_ip_mreq_source
|
||||
|
||||
type groupReq C.struct_group_req
|
||||
|
||||
type groupSourceReq C.struct_group_source_req
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
// +godefs map struct_in_addr [4]byte /* in_addr */
|
||||
|
||||
package ipv4
|
||||
|
||||
/*
|
||||
#include <netinet/in.h>
|
||||
*/
|
||||
import "C"
|
||||
|
||||
const (
|
||||
sysIP_OPTIONS = C.IP_OPTIONS
|
||||
sysIP_HDRINCL = C.IP_HDRINCL
|
||||
sysIP_TOS = C.IP_TOS
|
||||
sysIP_TTL = C.IP_TTL
|
||||
sysIP_RECVOPTS = C.IP_RECVOPTS
|
||||
sysIP_RECVRETOPTS = C.IP_RECVRETOPTS
|
||||
sysIP_RECVDSTADDR = C.IP_RECVDSTADDR
|
||||
sysIP_RETOPTS = C.IP_RETOPTS
|
||||
sysIP_RECVIF = C.IP_RECVIF
|
||||
sysIP_RECVTTL = C.IP_RECVTTL
|
||||
|
||||
sysIP_MULTICAST_IF = C.IP_MULTICAST_IF
|
||||
sysIP_MULTICAST_TTL = C.IP_MULTICAST_TTL
|
||||
sysIP_MULTICAST_LOOP = C.IP_MULTICAST_LOOP
|
||||
sysIP_MULTICAST_VIF = C.IP_MULTICAST_VIF
|
||||
sysIP_ADD_MEMBERSHIP = C.IP_ADD_MEMBERSHIP
|
||||
sysIP_DROP_MEMBERSHIP = C.IP_DROP_MEMBERSHIP
|
||||
|
||||
sizeofIPMreq = C.sizeof_struct_ip_mreq
|
||||
)
|
||||
|
||||
type ipMreq C.struct_ip_mreq
|
||||
|
|
@ -1,75 +0,0 @@
|
|||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
// +godefs map struct_in_addr [4]byte /* in_addr */
|
||||
|
||||
package ipv4
|
||||
|
||||
/*
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
*/
|
||||
import "C"
|
||||
|
||||
const (
|
||||
sysIP_OPTIONS = C.IP_OPTIONS
|
||||
sysIP_HDRINCL = C.IP_HDRINCL
|
||||
sysIP_TOS = C.IP_TOS
|
||||
sysIP_TTL = C.IP_TTL
|
||||
sysIP_RECVOPTS = C.IP_RECVOPTS
|
||||
sysIP_RECVRETOPTS = C.IP_RECVRETOPTS
|
||||
sysIP_RECVDSTADDR = C.IP_RECVDSTADDR
|
||||
sysIP_SENDSRCADDR = C.IP_SENDSRCADDR
|
||||
sysIP_RETOPTS = C.IP_RETOPTS
|
||||
sysIP_RECVIF = C.IP_RECVIF
|
||||
sysIP_ONESBCAST = C.IP_ONESBCAST
|
||||
sysIP_BINDANY = C.IP_BINDANY
|
||||
sysIP_RECVTTL = C.IP_RECVTTL
|
||||
sysIP_MINTTL = C.IP_MINTTL
|
||||
sysIP_DONTFRAG = C.IP_DONTFRAG
|
||||
sysIP_RECVTOS = C.IP_RECVTOS
|
||||
|
||||
sysIP_MULTICAST_IF = C.IP_MULTICAST_IF
|
||||
sysIP_MULTICAST_TTL = C.IP_MULTICAST_TTL
|
||||
sysIP_MULTICAST_LOOP = C.IP_MULTICAST_LOOP
|
||||
sysIP_ADD_MEMBERSHIP = C.IP_ADD_MEMBERSHIP
|
||||
sysIP_DROP_MEMBERSHIP = C.IP_DROP_MEMBERSHIP
|
||||
sysIP_MULTICAST_VIF = C.IP_MULTICAST_VIF
|
||||
sysIP_ADD_SOURCE_MEMBERSHIP = C.IP_ADD_SOURCE_MEMBERSHIP
|
||||
sysIP_DROP_SOURCE_MEMBERSHIP = C.IP_DROP_SOURCE_MEMBERSHIP
|
||||
sysIP_BLOCK_SOURCE = C.IP_BLOCK_SOURCE
|
||||
sysIP_UNBLOCK_SOURCE = C.IP_UNBLOCK_SOURCE
|
||||
sysMCAST_JOIN_GROUP = C.MCAST_JOIN_GROUP
|
||||
sysMCAST_LEAVE_GROUP = C.MCAST_LEAVE_GROUP
|
||||
sysMCAST_JOIN_SOURCE_GROUP = C.MCAST_JOIN_SOURCE_GROUP
|
||||
sysMCAST_LEAVE_SOURCE_GROUP = C.MCAST_LEAVE_SOURCE_GROUP
|
||||
sysMCAST_BLOCK_SOURCE = C.MCAST_BLOCK_SOURCE
|
||||
sysMCAST_UNBLOCK_SOURCE = C.MCAST_UNBLOCK_SOURCE
|
||||
|
||||
sizeofSockaddrStorage = C.sizeof_struct_sockaddr_storage
|
||||
sizeofSockaddrInet = C.sizeof_struct_sockaddr_in
|
||||
|
||||
sizeofIPMreq = C.sizeof_struct_ip_mreq
|
||||
sizeofIPMreqn = C.sizeof_struct_ip_mreqn
|
||||
sizeofIPMreqSource = C.sizeof_struct_ip_mreq_source
|
||||
sizeofGroupReq = C.sizeof_struct_group_req
|
||||
sizeofGroupSourceReq = C.sizeof_struct_group_source_req
|
||||
)
|
||||
|
||||
type sockaddrStorage C.struct_sockaddr_storage
|
||||
|
||||
type sockaddrInet C.struct_sockaddr_in
|
||||
|
||||
type ipMreq C.struct_ip_mreq
|
||||
|
||||
type ipMreqn C.struct_ip_mreqn
|
||||
|
||||
type ipMreqSource C.struct_ip_mreq_source
|
||||
|
||||
type groupReq C.struct_group_req
|
||||
|
||||
type groupSourceReq C.struct_group_source_req
|
||||
|
|
@ -1,122 +0,0 @@
|
|||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
// +godefs map struct_in_addr [4]byte /* in_addr */
|
||||
|
||||
package ipv4
|
||||
|
||||
/*
|
||||
#include <time.h>
|
||||
|
||||
#include <linux/errqueue.h>
|
||||
#include <linux/icmp.h>
|
||||
#include <linux/in.h>
|
||||
#include <linux/filter.h>
|
||||
#include <sys/socket.h>
|
||||
*/
|
||||
import "C"
|
||||
|
||||
const (
|
||||
sysIP_TOS = C.IP_TOS
|
||||
sysIP_TTL = C.IP_TTL
|
||||
sysIP_HDRINCL = C.IP_HDRINCL
|
||||
sysIP_OPTIONS = C.IP_OPTIONS
|
||||
sysIP_ROUTER_ALERT = C.IP_ROUTER_ALERT
|
||||
sysIP_RECVOPTS = C.IP_RECVOPTS
|
||||
sysIP_RETOPTS = C.IP_RETOPTS
|
||||
sysIP_PKTINFO = C.IP_PKTINFO
|
||||
sysIP_PKTOPTIONS = C.IP_PKTOPTIONS
|
||||
sysIP_MTU_DISCOVER = C.IP_MTU_DISCOVER
|
||||
sysIP_RECVERR = C.IP_RECVERR
|
||||
sysIP_RECVTTL = C.IP_RECVTTL
|
||||
sysIP_RECVTOS = C.IP_RECVTOS
|
||||
sysIP_MTU = C.IP_MTU
|
||||
sysIP_FREEBIND = C.IP_FREEBIND
|
||||
sysIP_TRANSPARENT = C.IP_TRANSPARENT
|
||||
sysIP_RECVRETOPTS = C.IP_RECVRETOPTS
|
||||
sysIP_ORIGDSTADDR = C.IP_ORIGDSTADDR
|
||||
sysIP_RECVORIGDSTADDR = C.IP_RECVORIGDSTADDR
|
||||
sysIP_MINTTL = C.IP_MINTTL
|
||||
sysIP_NODEFRAG = C.IP_NODEFRAG
|
||||
sysIP_UNICAST_IF = C.IP_UNICAST_IF
|
||||
|
||||
sysIP_MULTICAST_IF = C.IP_MULTICAST_IF
|
||||
sysIP_MULTICAST_TTL = C.IP_MULTICAST_TTL
|
||||
sysIP_MULTICAST_LOOP = C.IP_MULTICAST_LOOP
|
||||
sysIP_ADD_MEMBERSHIP = C.IP_ADD_MEMBERSHIP
|
||||
sysIP_DROP_MEMBERSHIP = C.IP_DROP_MEMBERSHIP
|
||||
sysIP_UNBLOCK_SOURCE = C.IP_UNBLOCK_SOURCE
|
||||
sysIP_BLOCK_SOURCE = C.IP_BLOCK_SOURCE
|
||||
sysIP_ADD_SOURCE_MEMBERSHIP = C.IP_ADD_SOURCE_MEMBERSHIP
|
||||
sysIP_DROP_SOURCE_MEMBERSHIP = C.IP_DROP_SOURCE_MEMBERSHIP
|
||||
sysIP_MSFILTER = C.IP_MSFILTER
|
||||
sysMCAST_JOIN_GROUP = C.MCAST_JOIN_GROUP
|
||||
sysMCAST_LEAVE_GROUP = C.MCAST_LEAVE_GROUP
|
||||
sysMCAST_JOIN_SOURCE_GROUP = C.MCAST_JOIN_SOURCE_GROUP
|
||||
sysMCAST_LEAVE_SOURCE_GROUP = C.MCAST_LEAVE_SOURCE_GROUP
|
||||
sysMCAST_BLOCK_SOURCE = C.MCAST_BLOCK_SOURCE
|
||||
sysMCAST_UNBLOCK_SOURCE = C.MCAST_UNBLOCK_SOURCE
|
||||
sysMCAST_MSFILTER = C.MCAST_MSFILTER
|
||||
sysIP_MULTICAST_ALL = C.IP_MULTICAST_ALL
|
||||
|
||||
//sysIP_PMTUDISC_DONT = C.IP_PMTUDISC_DONT
|
||||
//sysIP_PMTUDISC_WANT = C.IP_PMTUDISC_WANT
|
||||
//sysIP_PMTUDISC_DO = C.IP_PMTUDISC_DO
|
||||
//sysIP_PMTUDISC_PROBE = C.IP_PMTUDISC_PROBE
|
||||
//sysIP_PMTUDISC_INTERFACE = C.IP_PMTUDISC_INTERFACE
|
||||
//sysIP_PMTUDISC_OMIT = C.IP_PMTUDISC_OMIT
|
||||
|
||||
sysICMP_FILTER = C.ICMP_FILTER
|
||||
|
||||
sysSO_EE_ORIGIN_NONE = C.SO_EE_ORIGIN_NONE
|
||||
sysSO_EE_ORIGIN_LOCAL = C.SO_EE_ORIGIN_LOCAL
|
||||
sysSO_EE_ORIGIN_ICMP = C.SO_EE_ORIGIN_ICMP
|
||||
sysSO_EE_ORIGIN_ICMP6 = C.SO_EE_ORIGIN_ICMP6
|
||||
sysSO_EE_ORIGIN_TXSTATUS = C.SO_EE_ORIGIN_TXSTATUS
|
||||
sysSO_EE_ORIGIN_TIMESTAMPING = C.SO_EE_ORIGIN_TIMESTAMPING
|
||||
|
||||
sysSOL_SOCKET = C.SOL_SOCKET
|
||||
sysSO_ATTACH_FILTER = C.SO_ATTACH_FILTER
|
||||
|
||||
sizeofKernelSockaddrStorage = C.sizeof_struct___kernel_sockaddr_storage
|
||||
sizeofSockaddrInet = C.sizeof_struct_sockaddr_in
|
||||
sizeofInetPktinfo = C.sizeof_struct_in_pktinfo
|
||||
sizeofSockExtendedErr = C.sizeof_struct_sock_extended_err
|
||||
|
||||
sizeofIPMreq = C.sizeof_struct_ip_mreq
|
||||
sizeofIPMreqn = C.sizeof_struct_ip_mreqn
|
||||
sizeofIPMreqSource = C.sizeof_struct_ip_mreq_source
|
||||
sizeofGroupReq = C.sizeof_struct_group_req
|
||||
sizeofGroupSourceReq = C.sizeof_struct_group_source_req
|
||||
|
||||
sizeofICMPFilter = C.sizeof_struct_icmp_filter
|
||||
|
||||
sizeofSockFprog = C.sizeof_struct_sock_fprog
|
||||
)
|
||||
|
||||
type kernelSockaddrStorage C.struct___kernel_sockaddr_storage
|
||||
|
||||
type sockaddrInet C.struct_sockaddr_in
|
||||
|
||||
type inetPktinfo C.struct_in_pktinfo
|
||||
|
||||
type sockExtendedErr C.struct_sock_extended_err
|
||||
|
||||
type ipMreq C.struct_ip_mreq
|
||||
|
||||
type ipMreqn C.struct_ip_mreqn
|
||||
|
||||
type ipMreqSource C.struct_ip_mreq_source
|
||||
|
||||
type groupReq C.struct_group_req
|
||||
|
||||
type groupSourceReq C.struct_group_source_req
|
||||
|
||||
type icmpFilter C.struct_icmp_filter
|
||||
|
||||
type sockFProg C.struct_sock_fprog
|
||||
|
||||
type sockFilter C.struct_sock_filter
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
// +godefs map struct_in_addr [4]byte /* in_addr */
|
||||
|
||||
package ipv4
|
||||
|
||||
/*
|
||||
#include <netinet/in.h>
|
||||
*/
|
||||
import "C"
|
||||
|
||||
const (
|
||||
sysIP_OPTIONS = C.IP_OPTIONS
|
||||
sysIP_HDRINCL = C.IP_HDRINCL
|
||||
sysIP_TOS = C.IP_TOS
|
||||
sysIP_TTL = C.IP_TTL
|
||||
sysIP_RECVOPTS = C.IP_RECVOPTS
|
||||
sysIP_RECVRETOPTS = C.IP_RECVRETOPTS
|
||||
sysIP_RECVDSTADDR = C.IP_RECVDSTADDR
|
||||
sysIP_RETOPTS = C.IP_RETOPTS
|
||||
sysIP_RECVIF = C.IP_RECVIF
|
||||
sysIP_RECVTTL = C.IP_RECVTTL
|
||||
|
||||
sysIP_MULTICAST_IF = C.IP_MULTICAST_IF
|
||||
sysIP_MULTICAST_TTL = C.IP_MULTICAST_TTL
|
||||
sysIP_MULTICAST_LOOP = C.IP_MULTICAST_LOOP
|
||||
sysIP_ADD_MEMBERSHIP = C.IP_ADD_MEMBERSHIP
|
||||
sysIP_DROP_MEMBERSHIP = C.IP_DROP_MEMBERSHIP
|
||||
|
||||
sizeofIPMreq = C.sizeof_struct_ip_mreq
|
||||
)
|
||||
|
||||
type ipMreq C.struct_ip_mreq
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
// +godefs map struct_in_addr [4]byte /* in_addr */
|
||||
|
||||
package ipv4
|
||||
|
||||
/*
|
||||
#include <netinet/in.h>
|
||||
*/
|
||||
import "C"
|
||||
|
||||
const (
|
||||
sysIP_OPTIONS = C.IP_OPTIONS
|
||||
sysIP_HDRINCL = C.IP_HDRINCL
|
||||
sysIP_TOS = C.IP_TOS
|
||||
sysIP_TTL = C.IP_TTL
|
||||
sysIP_RECVOPTS = C.IP_RECVOPTS
|
||||
sysIP_RECVRETOPTS = C.IP_RECVRETOPTS
|
||||
sysIP_RECVDSTADDR = C.IP_RECVDSTADDR
|
||||
sysIP_RETOPTS = C.IP_RETOPTS
|
||||
sysIP_RECVIF = C.IP_RECVIF
|
||||
sysIP_RECVTTL = C.IP_RECVTTL
|
||||
|
||||
sysIP_MULTICAST_IF = C.IP_MULTICAST_IF
|
||||
sysIP_MULTICAST_TTL = C.IP_MULTICAST_TTL
|
||||
sysIP_MULTICAST_LOOP = C.IP_MULTICAST_LOOP
|
||||
sysIP_ADD_MEMBERSHIP = C.IP_ADD_MEMBERSHIP
|
||||
sysIP_DROP_MEMBERSHIP = C.IP_DROP_MEMBERSHIP
|
||||
|
||||
sizeofIPMreq = C.sizeof_struct_ip_mreq
|
||||
)
|
||||
|
||||
type ipMreq C.struct_ip_mreq
|
||||
|
|
@ -1,84 +0,0 @@
|
|||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
// +godefs map struct_in_addr [4]byte /* in_addr */
|
||||
|
||||
package ipv4
|
||||
|
||||
/*
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
*/
|
||||
import "C"
|
||||
|
||||
const (
|
||||
sysIP_OPTIONS = C.IP_OPTIONS
|
||||
sysIP_HDRINCL = C.IP_HDRINCL
|
||||
sysIP_TOS = C.IP_TOS
|
||||
sysIP_TTL = C.IP_TTL
|
||||
sysIP_RECVOPTS = C.IP_RECVOPTS
|
||||
sysIP_RECVRETOPTS = C.IP_RECVRETOPTS
|
||||
sysIP_RECVDSTADDR = C.IP_RECVDSTADDR
|
||||
sysIP_RETOPTS = C.IP_RETOPTS
|
||||
sysIP_RECVIF = C.IP_RECVIF
|
||||
sysIP_RECVSLLA = C.IP_RECVSLLA
|
||||
sysIP_RECVTTL = C.IP_RECVTTL
|
||||
|
||||
sysIP_MULTICAST_IF = C.IP_MULTICAST_IF
|
||||
sysIP_MULTICAST_TTL = C.IP_MULTICAST_TTL
|
||||
sysIP_MULTICAST_LOOP = C.IP_MULTICAST_LOOP
|
||||
sysIP_ADD_MEMBERSHIP = C.IP_ADD_MEMBERSHIP
|
||||
sysIP_DROP_MEMBERSHIP = C.IP_DROP_MEMBERSHIP
|
||||
sysIP_BLOCK_SOURCE = C.IP_BLOCK_SOURCE
|
||||
sysIP_UNBLOCK_SOURCE = C.IP_UNBLOCK_SOURCE
|
||||
sysIP_ADD_SOURCE_MEMBERSHIP = C.IP_ADD_SOURCE_MEMBERSHIP
|
||||
sysIP_DROP_SOURCE_MEMBERSHIP = C.IP_DROP_SOURCE_MEMBERSHIP
|
||||
sysIP_NEXTHOP = C.IP_NEXTHOP
|
||||
|
||||
sysIP_PKTINFO = C.IP_PKTINFO
|
||||
sysIP_RECVPKTINFO = C.IP_RECVPKTINFO
|
||||
sysIP_DONTFRAG = C.IP_DONTFRAG
|
||||
|
||||
sysIP_BOUND_IF = C.IP_BOUND_IF
|
||||
sysIP_UNSPEC_SRC = C.IP_UNSPEC_SRC
|
||||
sysIP_BROADCAST_TTL = C.IP_BROADCAST_TTL
|
||||
sysIP_DHCPINIT_IF = C.IP_DHCPINIT_IF
|
||||
|
||||
sysIP_REUSEADDR = C.IP_REUSEADDR
|
||||
sysIP_DONTROUTE = C.IP_DONTROUTE
|
||||
sysIP_BROADCAST = C.IP_BROADCAST
|
||||
|
||||
sysMCAST_JOIN_GROUP = C.MCAST_JOIN_GROUP
|
||||
sysMCAST_LEAVE_GROUP = C.MCAST_LEAVE_GROUP
|
||||
sysMCAST_BLOCK_SOURCE = C.MCAST_BLOCK_SOURCE
|
||||
sysMCAST_UNBLOCK_SOURCE = C.MCAST_UNBLOCK_SOURCE
|
||||
sysMCAST_JOIN_SOURCE_GROUP = C.MCAST_JOIN_SOURCE_GROUP
|
||||
sysMCAST_LEAVE_SOURCE_GROUP = C.MCAST_LEAVE_SOURCE_GROUP
|
||||
|
||||
sizeofSockaddrStorage = C.sizeof_struct_sockaddr_storage
|
||||
sizeofSockaddrInet = C.sizeof_struct_sockaddr_in
|
||||
sizeofInetPktinfo = C.sizeof_struct_in_pktinfo
|
||||
|
||||
sizeofIPMreq = C.sizeof_struct_ip_mreq
|
||||
sizeofIPMreqSource = C.sizeof_struct_ip_mreq_source
|
||||
sizeofGroupReq = C.sizeof_struct_group_req
|
||||
sizeofGroupSourceReq = C.sizeof_struct_group_source_req
|
||||
)
|
||||
|
||||
type sockaddrStorage C.struct_sockaddr_storage
|
||||
|
||||
type sockaddrInet C.struct_sockaddr_in
|
||||
|
||||
type inetPktinfo C.struct_in_pktinfo
|
||||
|
||||
type ipMreq C.struct_ip_mreq
|
||||
|
||||
type ipMreqSource C.struct_ip_mreq_source
|
||||
|
||||
type groupReq C.struct_group_req
|
||||
|
||||
type groupSourceReq C.struct_group_source_req
|
||||
|
|
@ -1,199 +0,0 @@
|
|||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
//go:generate go run gen.go
|
||||
|
||||
// This program generates system adaptation constants and types,
|
||||
// internet protocol constants and tables by reading template files
|
||||
// and IANA protocol registries.
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/xml"
|
||||
"fmt"
|
||||
"go/format"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/exec"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func main() {
|
||||
if err := genzsys(); err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
if err := geniana(); err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func genzsys() error {
|
||||
defs := "defs_" + runtime.GOOS + ".go"
|
||||
f, err := os.Open(defs)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
f.Close()
|
||||
cmd := exec.Command("go", "tool", "cgo", "-godefs", defs)
|
||||
b, err := cmd.Output()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
b, err = format.Source(b)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
zsys := "zsys_" + runtime.GOOS + ".go"
|
||||
switch runtime.GOOS {
|
||||
case "freebsd", "linux":
|
||||
zsys = "zsys_" + runtime.GOOS + "_" + runtime.GOARCH + ".go"
|
||||
}
|
||||
if err := ioutil.WriteFile(zsys, b, 0644); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var registries = []struct {
|
||||
url string
|
||||
parse func(io.Writer, io.Reader) error
|
||||
}{
|
||||
{
|
||||
"https://www.iana.org/assignments/icmp-parameters/icmp-parameters.xml",
|
||||
parseICMPv4Parameters,
|
||||
},
|
||||
}
|
||||
|
||||
func geniana() error {
|
||||
var bb bytes.Buffer
|
||||
fmt.Fprintf(&bb, "// go generate gen.go\n")
|
||||
fmt.Fprintf(&bb, "// Code generated by the command above; DO NOT EDIT.\n\n")
|
||||
fmt.Fprintf(&bb, "package ipv4\n\n")
|
||||
for _, r := range registries {
|
||||
resp, err := http.Get(r.url)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return fmt.Errorf("got HTTP status code %v for %v\n", resp.StatusCode, r.url)
|
||||
}
|
||||
if err := r.parse(&bb, resp.Body); err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Fprintf(&bb, "\n")
|
||||
}
|
||||
b, err := format.Source(bb.Bytes())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := ioutil.WriteFile("iana.go", b, 0644); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func parseICMPv4Parameters(w io.Writer, r io.Reader) error {
|
||||
dec := xml.NewDecoder(r)
|
||||
var icp icmpv4Parameters
|
||||
if err := dec.Decode(&icp); err != nil {
|
||||
return err
|
||||
}
|
||||
prs := icp.escape()
|
||||
fmt.Fprintf(w, "// %s, Updated: %s\n", icp.Title, icp.Updated)
|
||||
fmt.Fprintf(w, "const (\n")
|
||||
for _, pr := range prs {
|
||||
if pr.Descr == "" {
|
||||
continue
|
||||
}
|
||||
fmt.Fprintf(w, "ICMPType%s ICMPType = %d", pr.Descr, pr.Value)
|
||||
fmt.Fprintf(w, "// %s\n", pr.OrigDescr)
|
||||
}
|
||||
fmt.Fprintf(w, ")\n\n")
|
||||
fmt.Fprintf(w, "// %s, Updated: %s\n", icp.Title, icp.Updated)
|
||||
fmt.Fprintf(w, "var icmpTypes = map[ICMPType]string{\n")
|
||||
for _, pr := range prs {
|
||||
if pr.Descr == "" {
|
||||
continue
|
||||
}
|
||||
fmt.Fprintf(w, "%d: %q,\n", pr.Value, strings.ToLower(pr.OrigDescr))
|
||||
}
|
||||
fmt.Fprintf(w, "}\n")
|
||||
return nil
|
||||
}
|
||||
|
||||
type icmpv4Parameters struct {
|
||||
XMLName xml.Name `xml:"registry"`
|
||||
Title string `xml:"title"`
|
||||
Updated string `xml:"updated"`
|
||||
Registries []struct {
|
||||
Title string `xml:"title"`
|
||||
Records []struct {
|
||||
Value string `xml:"value"`
|
||||
Descr string `xml:"description"`
|
||||
} `xml:"record"`
|
||||
} `xml:"registry"`
|
||||
}
|
||||
|
||||
type canonICMPv4ParamRecord struct {
|
||||
OrigDescr string
|
||||
Descr string
|
||||
Value int
|
||||
}
|
||||
|
||||
func (icp *icmpv4Parameters) escape() []canonICMPv4ParamRecord {
|
||||
id := -1
|
||||
for i, r := range icp.Registries {
|
||||
if strings.Contains(r.Title, "Type") || strings.Contains(r.Title, "type") {
|
||||
id = i
|
||||
break
|
||||
}
|
||||
}
|
||||
if id < 0 {
|
||||
return nil
|
||||
}
|
||||
prs := make([]canonICMPv4ParamRecord, len(icp.Registries[id].Records))
|
||||
sr := strings.NewReplacer(
|
||||
"Messages", "",
|
||||
"Message", "",
|
||||
"ICMP", "",
|
||||
"+", "P",
|
||||
"-", "",
|
||||
"/", "",
|
||||
".", "",
|
||||
" ", "",
|
||||
)
|
||||
for i, pr := range icp.Registries[id].Records {
|
||||
if strings.Contains(pr.Descr, "Reserved") ||
|
||||
strings.Contains(pr.Descr, "Unassigned") ||
|
||||
strings.Contains(pr.Descr, "Deprecated") ||
|
||||
strings.Contains(pr.Descr, "Experiment") ||
|
||||
strings.Contains(pr.Descr, "experiment") {
|
||||
continue
|
||||
}
|
||||
ss := strings.Split(pr.Descr, "\n")
|
||||
if len(ss) > 1 {
|
||||
prs[i].Descr = strings.Join(ss, " ")
|
||||
} else {
|
||||
prs[i].Descr = ss[0]
|
||||
}
|
||||
s := strings.TrimSpace(prs[i].Descr)
|
||||
prs[i].OrigDescr = s
|
||||
prs[i].Descr = sr.Replace(s)
|
||||
prs[i].Value, _ = strconv.Atoi(pr.Value)
|
||||
}
|
||||
return prs
|
||||
}
|
||||
|
|
@ -65,7 +65,6 @@ go_library(
|
|||
"zsys_openbsd.go",
|
||||
"zsys_solaris.go",
|
||||
],
|
||||
cgo = True,
|
||||
importmap = "k8s.io/kops/vendor/golang.org/x/net/ipv6",
|
||||
importpath = "golang.org/x/net/ipv6",
|
||||
visibility = ["//visibility:public"],
|
||||
|
|
|
|||
|
|
@ -1,112 +0,0 @@
|
|||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
// +godefs map struct_in6_addr [16]byte /* in6_addr */
|
||||
|
||||
package ipv6
|
||||
|
||||
/*
|
||||
#define __APPLE_USE_RFC_3542
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/icmp6.h>
|
||||
*/
|
||||
import "C"
|
||||
|
||||
const (
|
||||
sysIPV6_UNICAST_HOPS = C.IPV6_UNICAST_HOPS
|
||||
sysIPV6_MULTICAST_IF = C.IPV6_MULTICAST_IF
|
||||
sysIPV6_MULTICAST_HOPS = C.IPV6_MULTICAST_HOPS
|
||||
sysIPV6_MULTICAST_LOOP = C.IPV6_MULTICAST_LOOP
|
||||
sysIPV6_JOIN_GROUP = C.IPV6_JOIN_GROUP
|
||||
sysIPV6_LEAVE_GROUP = C.IPV6_LEAVE_GROUP
|
||||
|
||||
sysIPV6_PORTRANGE = C.IPV6_PORTRANGE
|
||||
sysICMP6_FILTER = C.ICMP6_FILTER
|
||||
sysIPV6_2292PKTINFO = C.IPV6_2292PKTINFO
|
||||
sysIPV6_2292HOPLIMIT = C.IPV6_2292HOPLIMIT
|
||||
sysIPV6_2292NEXTHOP = C.IPV6_2292NEXTHOP
|
||||
sysIPV6_2292HOPOPTS = C.IPV6_2292HOPOPTS
|
||||
sysIPV6_2292DSTOPTS = C.IPV6_2292DSTOPTS
|
||||
sysIPV6_2292RTHDR = C.IPV6_2292RTHDR
|
||||
|
||||
sysIPV6_2292PKTOPTIONS = C.IPV6_2292PKTOPTIONS
|
||||
|
||||
sysIPV6_CHECKSUM = C.IPV6_CHECKSUM
|
||||
sysIPV6_V6ONLY = C.IPV6_V6ONLY
|
||||
|
||||
sysIPV6_IPSEC_POLICY = C.IPV6_IPSEC_POLICY
|
||||
|
||||
sysIPV6_RECVTCLASS = C.IPV6_RECVTCLASS
|
||||
sysIPV6_TCLASS = C.IPV6_TCLASS
|
||||
|
||||
sysIPV6_RTHDRDSTOPTS = C.IPV6_RTHDRDSTOPTS
|
||||
|
||||
sysIPV6_RECVPKTINFO = C.IPV6_RECVPKTINFO
|
||||
|
||||
sysIPV6_RECVHOPLIMIT = C.IPV6_RECVHOPLIMIT
|
||||
sysIPV6_RECVRTHDR = C.IPV6_RECVRTHDR
|
||||
sysIPV6_RECVHOPOPTS = C.IPV6_RECVHOPOPTS
|
||||
sysIPV6_RECVDSTOPTS = C.IPV6_RECVDSTOPTS
|
||||
|
||||
sysIPV6_USE_MIN_MTU = C.IPV6_USE_MIN_MTU
|
||||
sysIPV6_RECVPATHMTU = C.IPV6_RECVPATHMTU
|
||||
|
||||
sysIPV6_PATHMTU = C.IPV6_PATHMTU
|
||||
|
||||
sysIPV6_PKTINFO = C.IPV6_PKTINFO
|
||||
sysIPV6_HOPLIMIT = C.IPV6_HOPLIMIT
|
||||
sysIPV6_NEXTHOP = C.IPV6_NEXTHOP
|
||||
sysIPV6_HOPOPTS = C.IPV6_HOPOPTS
|
||||
sysIPV6_DSTOPTS = C.IPV6_DSTOPTS
|
||||
sysIPV6_RTHDR = C.IPV6_RTHDR
|
||||
|
||||
sysIPV6_AUTOFLOWLABEL = C.IPV6_AUTOFLOWLABEL
|
||||
|
||||
sysIPV6_DONTFRAG = C.IPV6_DONTFRAG
|
||||
|
||||
sysIPV6_PREFER_TEMPADDR = C.IPV6_PREFER_TEMPADDR
|
||||
|
||||
sysIPV6_MSFILTER = C.IPV6_MSFILTER
|
||||
sysMCAST_JOIN_GROUP = C.MCAST_JOIN_GROUP
|
||||
sysMCAST_LEAVE_GROUP = C.MCAST_LEAVE_GROUP
|
||||
sysMCAST_JOIN_SOURCE_GROUP = C.MCAST_JOIN_SOURCE_GROUP
|
||||
sysMCAST_LEAVE_SOURCE_GROUP = C.MCAST_LEAVE_SOURCE_GROUP
|
||||
sysMCAST_BLOCK_SOURCE = C.MCAST_BLOCK_SOURCE
|
||||
sysMCAST_UNBLOCK_SOURCE = C.MCAST_UNBLOCK_SOURCE
|
||||
|
||||
sysIPV6_BOUND_IF = C.IPV6_BOUND_IF
|
||||
|
||||
sysIPV6_PORTRANGE_DEFAULT = C.IPV6_PORTRANGE_DEFAULT
|
||||
sysIPV6_PORTRANGE_HIGH = C.IPV6_PORTRANGE_HIGH
|
||||
sysIPV6_PORTRANGE_LOW = C.IPV6_PORTRANGE_LOW
|
||||
|
||||
sizeofSockaddrStorage = C.sizeof_struct_sockaddr_storage
|
||||
sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
|
||||
sizeofInet6Pktinfo = C.sizeof_struct_in6_pktinfo
|
||||
sizeofIPv6Mtuinfo = C.sizeof_struct_ip6_mtuinfo
|
||||
|
||||
sizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq
|
||||
sizeofGroupReq = C.sizeof_struct_group_req
|
||||
sizeofGroupSourceReq = C.sizeof_struct_group_source_req
|
||||
|
||||
sizeofICMPv6Filter = C.sizeof_struct_icmp6_filter
|
||||
)
|
||||
|
||||
type sockaddrStorage C.struct_sockaddr_storage
|
||||
|
||||
type sockaddrInet6 C.struct_sockaddr_in6
|
||||
|
||||
type inet6Pktinfo C.struct_in6_pktinfo
|
||||
|
||||
type ipv6Mtuinfo C.struct_ip6_mtuinfo
|
||||
|
||||
type ipv6Mreq C.struct_ipv6_mreq
|
||||
|
||||
type icmpv6Filter C.struct_icmp6_filter
|
||||
|
||||
type groupReq C.struct_group_req
|
||||
|
||||
type groupSourceReq C.struct_group_source_req
|
||||
|
|
@ -1,84 +0,0 @@
|
|||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
// +godefs map struct_in6_addr [16]byte /* in6_addr */
|
||||
|
||||
package ipv6
|
||||
|
||||
/*
|
||||
#include <sys/param.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/icmp6.h>
|
||||
*/
|
||||
import "C"
|
||||
|
||||
const (
|
||||
sysIPV6_UNICAST_HOPS = C.IPV6_UNICAST_HOPS
|
||||
sysIPV6_MULTICAST_IF = C.IPV6_MULTICAST_IF
|
||||
sysIPV6_MULTICAST_HOPS = C.IPV6_MULTICAST_HOPS
|
||||
sysIPV6_MULTICAST_LOOP = C.IPV6_MULTICAST_LOOP
|
||||
sysIPV6_JOIN_GROUP = C.IPV6_JOIN_GROUP
|
||||
sysIPV6_LEAVE_GROUP = C.IPV6_LEAVE_GROUP
|
||||
sysIPV6_PORTRANGE = C.IPV6_PORTRANGE
|
||||
sysICMP6_FILTER = C.ICMP6_FILTER
|
||||
|
||||
sysIPV6_CHECKSUM = C.IPV6_CHECKSUM
|
||||
sysIPV6_V6ONLY = C.IPV6_V6ONLY
|
||||
|
||||
sysIPV6_IPSEC_POLICY = C.IPV6_IPSEC_POLICY
|
||||
|
||||
sysIPV6_RTHDRDSTOPTS = C.IPV6_RTHDRDSTOPTS
|
||||
sysIPV6_RECVPKTINFO = C.IPV6_RECVPKTINFO
|
||||
sysIPV6_RECVHOPLIMIT = C.IPV6_RECVHOPLIMIT
|
||||
sysIPV6_RECVRTHDR = C.IPV6_RECVRTHDR
|
||||
sysIPV6_RECVHOPOPTS = C.IPV6_RECVHOPOPTS
|
||||
sysIPV6_RECVDSTOPTS = C.IPV6_RECVDSTOPTS
|
||||
|
||||
sysIPV6_USE_MIN_MTU = C.IPV6_USE_MIN_MTU
|
||||
sysIPV6_RECVPATHMTU = C.IPV6_RECVPATHMTU
|
||||
|
||||
sysIPV6_PATHMTU = C.IPV6_PATHMTU
|
||||
|
||||
sysIPV6_PKTINFO = C.IPV6_PKTINFO
|
||||
sysIPV6_HOPLIMIT = C.IPV6_HOPLIMIT
|
||||
sysIPV6_NEXTHOP = C.IPV6_NEXTHOP
|
||||
sysIPV6_HOPOPTS = C.IPV6_HOPOPTS
|
||||
sysIPV6_DSTOPTS = C.IPV6_DSTOPTS
|
||||
sysIPV6_RTHDR = C.IPV6_RTHDR
|
||||
|
||||
sysIPV6_RECVTCLASS = C.IPV6_RECVTCLASS
|
||||
|
||||
sysIPV6_AUTOFLOWLABEL = C.IPV6_AUTOFLOWLABEL
|
||||
|
||||
sysIPV6_TCLASS = C.IPV6_TCLASS
|
||||
sysIPV6_DONTFRAG = C.IPV6_DONTFRAG
|
||||
|
||||
sysIPV6_PREFER_TEMPADDR = C.IPV6_PREFER_TEMPADDR
|
||||
|
||||
sysIPV6_PORTRANGE_DEFAULT = C.IPV6_PORTRANGE_DEFAULT
|
||||
sysIPV6_PORTRANGE_HIGH = C.IPV6_PORTRANGE_HIGH
|
||||
sysIPV6_PORTRANGE_LOW = C.IPV6_PORTRANGE_LOW
|
||||
|
||||
sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
|
||||
sizeofInet6Pktinfo = C.sizeof_struct_in6_pktinfo
|
||||
sizeofIPv6Mtuinfo = C.sizeof_struct_ip6_mtuinfo
|
||||
|
||||
sizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq
|
||||
|
||||
sizeofICMPv6Filter = C.sizeof_struct_icmp6_filter
|
||||
)
|
||||
|
||||
type sockaddrInet6 C.struct_sockaddr_in6
|
||||
|
||||
type inet6Pktinfo C.struct_in6_pktinfo
|
||||
|
||||
type ipv6Mtuinfo C.struct_ip6_mtuinfo
|
||||
|
||||
type ipv6Mreq C.struct_ipv6_mreq
|
||||
|
||||
type icmpv6Filter C.struct_icmp6_filter
|
||||
|
|
@ -1,105 +0,0 @@
|
|||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
// +godefs map struct_in6_addr [16]byte /* in6_addr */
|
||||
|
||||
package ipv6
|
||||
|
||||
/*
|
||||
#include <sys/param.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/icmp6.h>
|
||||
*/
|
||||
import "C"
|
||||
|
||||
const (
|
||||
sysIPV6_UNICAST_HOPS = C.IPV6_UNICAST_HOPS
|
||||
sysIPV6_MULTICAST_IF = C.IPV6_MULTICAST_IF
|
||||
sysIPV6_MULTICAST_HOPS = C.IPV6_MULTICAST_HOPS
|
||||
sysIPV6_MULTICAST_LOOP = C.IPV6_MULTICAST_LOOP
|
||||
sysIPV6_JOIN_GROUP = C.IPV6_JOIN_GROUP
|
||||
sysIPV6_LEAVE_GROUP = C.IPV6_LEAVE_GROUP
|
||||
sysIPV6_PORTRANGE = C.IPV6_PORTRANGE
|
||||
sysICMP6_FILTER = C.ICMP6_FILTER
|
||||
|
||||
sysIPV6_CHECKSUM = C.IPV6_CHECKSUM
|
||||
sysIPV6_V6ONLY = C.IPV6_V6ONLY
|
||||
|
||||
sysIPV6_IPSEC_POLICY = C.IPV6_IPSEC_POLICY
|
||||
|
||||
sysIPV6_RTHDRDSTOPTS = C.IPV6_RTHDRDSTOPTS
|
||||
|
||||
sysIPV6_RECVPKTINFO = C.IPV6_RECVPKTINFO
|
||||
sysIPV6_RECVHOPLIMIT = C.IPV6_RECVHOPLIMIT
|
||||
sysIPV6_RECVRTHDR = C.IPV6_RECVRTHDR
|
||||
sysIPV6_RECVHOPOPTS = C.IPV6_RECVHOPOPTS
|
||||
sysIPV6_RECVDSTOPTS = C.IPV6_RECVDSTOPTS
|
||||
|
||||
sysIPV6_USE_MIN_MTU = C.IPV6_USE_MIN_MTU
|
||||
sysIPV6_RECVPATHMTU = C.IPV6_RECVPATHMTU
|
||||
|
||||
sysIPV6_PATHMTU = C.IPV6_PATHMTU
|
||||
|
||||
sysIPV6_PKTINFO = C.IPV6_PKTINFO
|
||||
sysIPV6_HOPLIMIT = C.IPV6_HOPLIMIT
|
||||
sysIPV6_NEXTHOP = C.IPV6_NEXTHOP
|
||||
sysIPV6_HOPOPTS = C.IPV6_HOPOPTS
|
||||
sysIPV6_DSTOPTS = C.IPV6_DSTOPTS
|
||||
sysIPV6_RTHDR = C.IPV6_RTHDR
|
||||
|
||||
sysIPV6_RECVTCLASS = C.IPV6_RECVTCLASS
|
||||
|
||||
sysIPV6_AUTOFLOWLABEL = C.IPV6_AUTOFLOWLABEL
|
||||
|
||||
sysIPV6_TCLASS = C.IPV6_TCLASS
|
||||
sysIPV6_DONTFRAG = C.IPV6_DONTFRAG
|
||||
|
||||
sysIPV6_PREFER_TEMPADDR = C.IPV6_PREFER_TEMPADDR
|
||||
|
||||
sysIPV6_BINDANY = C.IPV6_BINDANY
|
||||
|
||||
sysIPV6_MSFILTER = C.IPV6_MSFILTER
|
||||
|
||||
sysMCAST_JOIN_GROUP = C.MCAST_JOIN_GROUP
|
||||
sysMCAST_LEAVE_GROUP = C.MCAST_LEAVE_GROUP
|
||||
sysMCAST_JOIN_SOURCE_GROUP = C.MCAST_JOIN_SOURCE_GROUP
|
||||
sysMCAST_LEAVE_SOURCE_GROUP = C.MCAST_LEAVE_SOURCE_GROUP
|
||||
sysMCAST_BLOCK_SOURCE = C.MCAST_BLOCK_SOURCE
|
||||
sysMCAST_UNBLOCK_SOURCE = C.MCAST_UNBLOCK_SOURCE
|
||||
|
||||
sysIPV6_PORTRANGE_DEFAULT = C.IPV6_PORTRANGE_DEFAULT
|
||||
sysIPV6_PORTRANGE_HIGH = C.IPV6_PORTRANGE_HIGH
|
||||
sysIPV6_PORTRANGE_LOW = C.IPV6_PORTRANGE_LOW
|
||||
|
||||
sizeofSockaddrStorage = C.sizeof_struct_sockaddr_storage
|
||||
sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
|
||||
sizeofInet6Pktinfo = C.sizeof_struct_in6_pktinfo
|
||||
sizeofIPv6Mtuinfo = C.sizeof_struct_ip6_mtuinfo
|
||||
|
||||
sizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq
|
||||
sizeofGroupReq = C.sizeof_struct_group_req
|
||||
sizeofGroupSourceReq = C.sizeof_struct_group_source_req
|
||||
|
||||
sizeofICMPv6Filter = C.sizeof_struct_icmp6_filter
|
||||
)
|
||||
|
||||
type sockaddrStorage C.struct_sockaddr_storage
|
||||
|
||||
type sockaddrInet6 C.struct_sockaddr_in6
|
||||
|
||||
type inet6Pktinfo C.struct_in6_pktinfo
|
||||
|
||||
type ipv6Mtuinfo C.struct_ip6_mtuinfo
|
||||
|
||||
type ipv6Mreq C.struct_ipv6_mreq
|
||||
|
||||
type groupReq C.struct_group_req
|
||||
|
||||
type groupSourceReq C.struct_group_source_req
|
||||
|
||||
type icmpv6Filter C.struct_icmp6_filter
|
||||
|
|
@ -1,147 +0,0 @@
|
|||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
// +godefs map struct_in6_addr [16]byte /* in6_addr */
|
||||
|
||||
package ipv6
|
||||
|
||||
/*
|
||||
#include <linux/in.h>
|
||||
#include <linux/in6.h>
|
||||
#include <linux/ipv6.h>
|
||||
#include <linux/icmpv6.h>
|
||||
#include <linux/filter.h>
|
||||
#include <sys/socket.h>
|
||||
*/
|
||||
import "C"
|
||||
|
||||
const (
|
||||
sysIPV6_ADDRFORM = C.IPV6_ADDRFORM
|
||||
sysIPV6_2292PKTINFO = C.IPV6_2292PKTINFO
|
||||
sysIPV6_2292HOPOPTS = C.IPV6_2292HOPOPTS
|
||||
sysIPV6_2292DSTOPTS = C.IPV6_2292DSTOPTS
|
||||
sysIPV6_2292RTHDR = C.IPV6_2292RTHDR
|
||||
sysIPV6_2292PKTOPTIONS = C.IPV6_2292PKTOPTIONS
|
||||
sysIPV6_CHECKSUM = C.IPV6_CHECKSUM
|
||||
sysIPV6_2292HOPLIMIT = C.IPV6_2292HOPLIMIT
|
||||
sysIPV6_NEXTHOP = C.IPV6_NEXTHOP
|
||||
sysIPV6_FLOWINFO = C.IPV6_FLOWINFO
|
||||
|
||||
sysIPV6_UNICAST_HOPS = C.IPV6_UNICAST_HOPS
|
||||
sysIPV6_MULTICAST_IF = C.IPV6_MULTICAST_IF
|
||||
sysIPV6_MULTICAST_HOPS = C.IPV6_MULTICAST_HOPS
|
||||
sysIPV6_MULTICAST_LOOP = C.IPV6_MULTICAST_LOOP
|
||||
sysIPV6_ADD_MEMBERSHIP = C.IPV6_ADD_MEMBERSHIP
|
||||
sysIPV6_DROP_MEMBERSHIP = C.IPV6_DROP_MEMBERSHIP
|
||||
sysMCAST_JOIN_GROUP = C.MCAST_JOIN_GROUP
|
||||
sysMCAST_LEAVE_GROUP = C.MCAST_LEAVE_GROUP
|
||||
sysMCAST_JOIN_SOURCE_GROUP = C.MCAST_JOIN_SOURCE_GROUP
|
||||
sysMCAST_LEAVE_SOURCE_GROUP = C.MCAST_LEAVE_SOURCE_GROUP
|
||||
sysMCAST_BLOCK_SOURCE = C.MCAST_BLOCK_SOURCE
|
||||
sysMCAST_UNBLOCK_SOURCE = C.MCAST_UNBLOCK_SOURCE
|
||||
sysMCAST_MSFILTER = C.MCAST_MSFILTER
|
||||
sysIPV6_ROUTER_ALERT = C.IPV6_ROUTER_ALERT
|
||||
sysIPV6_MTU_DISCOVER = C.IPV6_MTU_DISCOVER
|
||||
sysIPV6_MTU = C.IPV6_MTU
|
||||
sysIPV6_RECVERR = C.IPV6_RECVERR
|
||||
sysIPV6_V6ONLY = C.IPV6_V6ONLY
|
||||
sysIPV6_JOIN_ANYCAST = C.IPV6_JOIN_ANYCAST
|
||||
sysIPV6_LEAVE_ANYCAST = C.IPV6_LEAVE_ANYCAST
|
||||
|
||||
//sysIPV6_PMTUDISC_DONT = C.IPV6_PMTUDISC_DONT
|
||||
//sysIPV6_PMTUDISC_WANT = C.IPV6_PMTUDISC_WANT
|
||||
//sysIPV6_PMTUDISC_DO = C.IPV6_PMTUDISC_DO
|
||||
//sysIPV6_PMTUDISC_PROBE = C.IPV6_PMTUDISC_PROBE
|
||||
//sysIPV6_PMTUDISC_INTERFACE = C.IPV6_PMTUDISC_INTERFACE
|
||||
//sysIPV6_PMTUDISC_OMIT = C.IPV6_PMTUDISC_OMIT
|
||||
|
||||
sysIPV6_FLOWLABEL_MGR = C.IPV6_FLOWLABEL_MGR
|
||||
sysIPV6_FLOWINFO_SEND = C.IPV6_FLOWINFO_SEND
|
||||
|
||||
sysIPV6_IPSEC_POLICY = C.IPV6_IPSEC_POLICY
|
||||
sysIPV6_XFRM_POLICY = C.IPV6_XFRM_POLICY
|
||||
|
||||
sysIPV6_RECVPKTINFO = C.IPV6_RECVPKTINFO
|
||||
sysIPV6_PKTINFO = C.IPV6_PKTINFO
|
||||
sysIPV6_RECVHOPLIMIT = C.IPV6_RECVHOPLIMIT
|
||||
sysIPV6_HOPLIMIT = C.IPV6_HOPLIMIT
|
||||
sysIPV6_RECVHOPOPTS = C.IPV6_RECVHOPOPTS
|
||||
sysIPV6_HOPOPTS = C.IPV6_HOPOPTS
|
||||
sysIPV6_RTHDRDSTOPTS = C.IPV6_RTHDRDSTOPTS
|
||||
sysIPV6_RECVRTHDR = C.IPV6_RECVRTHDR
|
||||
sysIPV6_RTHDR = C.IPV6_RTHDR
|
||||
sysIPV6_RECVDSTOPTS = C.IPV6_RECVDSTOPTS
|
||||
sysIPV6_DSTOPTS = C.IPV6_DSTOPTS
|
||||
sysIPV6_RECVPATHMTU = C.IPV6_RECVPATHMTU
|
||||
sysIPV6_PATHMTU = C.IPV6_PATHMTU
|
||||
sysIPV6_DONTFRAG = C.IPV6_DONTFRAG
|
||||
|
||||
sysIPV6_RECVTCLASS = C.IPV6_RECVTCLASS
|
||||
sysIPV6_TCLASS = C.IPV6_TCLASS
|
||||
|
||||
sysIPV6_ADDR_PREFERENCES = C.IPV6_ADDR_PREFERENCES
|
||||
|
||||
sysIPV6_PREFER_SRC_TMP = C.IPV6_PREFER_SRC_TMP
|
||||
sysIPV6_PREFER_SRC_PUBLIC = C.IPV6_PREFER_SRC_PUBLIC
|
||||
sysIPV6_PREFER_SRC_PUBTMP_DEFAULT = C.IPV6_PREFER_SRC_PUBTMP_DEFAULT
|
||||
sysIPV6_PREFER_SRC_COA = C.IPV6_PREFER_SRC_COA
|
||||
sysIPV6_PREFER_SRC_HOME = C.IPV6_PREFER_SRC_HOME
|
||||
sysIPV6_PREFER_SRC_CGA = C.IPV6_PREFER_SRC_CGA
|
||||
sysIPV6_PREFER_SRC_NONCGA = C.IPV6_PREFER_SRC_NONCGA
|
||||
|
||||
sysIPV6_MINHOPCOUNT = C.IPV6_MINHOPCOUNT
|
||||
|
||||
sysIPV6_ORIGDSTADDR = C.IPV6_ORIGDSTADDR
|
||||
sysIPV6_RECVORIGDSTADDR = C.IPV6_RECVORIGDSTADDR
|
||||
sysIPV6_TRANSPARENT = C.IPV6_TRANSPARENT
|
||||
sysIPV6_UNICAST_IF = C.IPV6_UNICAST_IF
|
||||
|
||||
sysICMPV6_FILTER = C.ICMPV6_FILTER
|
||||
|
||||
sysICMPV6_FILTER_BLOCK = C.ICMPV6_FILTER_BLOCK
|
||||
sysICMPV6_FILTER_PASS = C.ICMPV6_FILTER_PASS
|
||||
sysICMPV6_FILTER_BLOCKOTHERS = C.ICMPV6_FILTER_BLOCKOTHERS
|
||||
sysICMPV6_FILTER_PASSONLY = C.ICMPV6_FILTER_PASSONLY
|
||||
|
||||
sysSOL_SOCKET = C.SOL_SOCKET
|
||||
sysSO_ATTACH_FILTER = C.SO_ATTACH_FILTER
|
||||
|
||||
sizeofKernelSockaddrStorage = C.sizeof_struct___kernel_sockaddr_storage
|
||||
sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
|
||||
sizeofInet6Pktinfo = C.sizeof_struct_in6_pktinfo
|
||||
sizeofIPv6Mtuinfo = C.sizeof_struct_ip6_mtuinfo
|
||||
sizeofIPv6FlowlabelReq = C.sizeof_struct_in6_flowlabel_req
|
||||
|
||||
sizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq
|
||||
sizeofGroupReq = C.sizeof_struct_group_req
|
||||
sizeofGroupSourceReq = C.sizeof_struct_group_source_req
|
||||
|
||||
sizeofICMPv6Filter = C.sizeof_struct_icmp6_filter
|
||||
|
||||
sizeofSockFprog = C.sizeof_struct_sock_fprog
|
||||
)
|
||||
|
||||
type kernelSockaddrStorage C.struct___kernel_sockaddr_storage
|
||||
|
||||
type sockaddrInet6 C.struct_sockaddr_in6
|
||||
|
||||
type inet6Pktinfo C.struct_in6_pktinfo
|
||||
|
||||
type ipv6Mtuinfo C.struct_ip6_mtuinfo
|
||||
|
||||
type ipv6FlowlabelReq C.struct_in6_flowlabel_req
|
||||
|
||||
type ipv6Mreq C.struct_ipv6_mreq
|
||||
|
||||
type groupReq C.struct_group_req
|
||||
|
||||
type groupSourceReq C.struct_group_source_req
|
||||
|
||||
type icmpv6Filter C.struct_icmp6_filter
|
||||
|
||||
type sockFProg C.struct_sock_fprog
|
||||
|
||||
type sockFilter C.struct_sock_filter
|
||||
|
|
@ -1,80 +0,0 @@
|
|||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
// +godefs map struct_in6_addr [16]byte /* in6_addr */
|
||||
|
||||
package ipv6
|
||||
|
||||
/*
|
||||
#include <sys/param.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/icmp6.h>
|
||||
*/
|
||||
import "C"
|
||||
|
||||
const (
|
||||
sysIPV6_UNICAST_HOPS = C.IPV6_UNICAST_HOPS
|
||||
sysIPV6_MULTICAST_IF = C.IPV6_MULTICAST_IF
|
||||
sysIPV6_MULTICAST_HOPS = C.IPV6_MULTICAST_HOPS
|
||||
sysIPV6_MULTICAST_LOOP = C.IPV6_MULTICAST_LOOP
|
||||
sysIPV6_JOIN_GROUP = C.IPV6_JOIN_GROUP
|
||||
sysIPV6_LEAVE_GROUP = C.IPV6_LEAVE_GROUP
|
||||
sysIPV6_PORTRANGE = C.IPV6_PORTRANGE
|
||||
sysICMP6_FILTER = C.ICMP6_FILTER
|
||||
|
||||
sysIPV6_CHECKSUM = C.IPV6_CHECKSUM
|
||||
sysIPV6_V6ONLY = C.IPV6_V6ONLY
|
||||
|
||||
sysIPV6_IPSEC_POLICY = C.IPV6_IPSEC_POLICY
|
||||
|
||||
sysIPV6_RTHDRDSTOPTS = C.IPV6_RTHDRDSTOPTS
|
||||
|
||||
sysIPV6_RECVPKTINFO = C.IPV6_RECVPKTINFO
|
||||
sysIPV6_RECVHOPLIMIT = C.IPV6_RECVHOPLIMIT
|
||||
sysIPV6_RECVRTHDR = C.IPV6_RECVRTHDR
|
||||
sysIPV6_RECVHOPOPTS = C.IPV6_RECVHOPOPTS
|
||||
sysIPV6_RECVDSTOPTS = C.IPV6_RECVDSTOPTS
|
||||
|
||||
sysIPV6_USE_MIN_MTU = C.IPV6_USE_MIN_MTU
|
||||
sysIPV6_RECVPATHMTU = C.IPV6_RECVPATHMTU
|
||||
sysIPV6_PATHMTU = C.IPV6_PATHMTU
|
||||
|
||||
sysIPV6_PKTINFO = C.IPV6_PKTINFO
|
||||
sysIPV6_HOPLIMIT = C.IPV6_HOPLIMIT
|
||||
sysIPV6_NEXTHOP = C.IPV6_NEXTHOP
|
||||
sysIPV6_HOPOPTS = C.IPV6_HOPOPTS
|
||||
sysIPV6_DSTOPTS = C.IPV6_DSTOPTS
|
||||
sysIPV6_RTHDR = C.IPV6_RTHDR
|
||||
|
||||
sysIPV6_RECVTCLASS = C.IPV6_RECVTCLASS
|
||||
|
||||
sysIPV6_TCLASS = C.IPV6_TCLASS
|
||||
sysIPV6_DONTFRAG = C.IPV6_DONTFRAG
|
||||
|
||||
sysIPV6_PORTRANGE_DEFAULT = C.IPV6_PORTRANGE_DEFAULT
|
||||
sysIPV6_PORTRANGE_HIGH = C.IPV6_PORTRANGE_HIGH
|
||||
sysIPV6_PORTRANGE_LOW = C.IPV6_PORTRANGE_LOW
|
||||
|
||||
sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
|
||||
sizeofInet6Pktinfo = C.sizeof_struct_in6_pktinfo
|
||||
sizeofIPv6Mtuinfo = C.sizeof_struct_ip6_mtuinfo
|
||||
|
||||
sizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq
|
||||
|
||||
sizeofICMPv6Filter = C.sizeof_struct_icmp6_filter
|
||||
)
|
||||
|
||||
type sockaddrInet6 C.struct_sockaddr_in6
|
||||
|
||||
type inet6Pktinfo C.struct_in6_pktinfo
|
||||
|
||||
type ipv6Mtuinfo C.struct_ip6_mtuinfo
|
||||
|
||||
type ipv6Mreq C.struct_ipv6_mreq
|
||||
|
||||
type icmpv6Filter C.struct_icmp6_filter
|
||||
|
|
@ -1,89 +0,0 @@
|
|||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
// +godefs map struct_in6_addr [16]byte /* in6_addr */
|
||||
|
||||
package ipv6
|
||||
|
||||
/*
|
||||
#include <sys/param.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/icmp6.h>
|
||||
*/
|
||||
import "C"
|
||||
|
||||
const (
|
||||
sysIPV6_UNICAST_HOPS = C.IPV6_UNICAST_HOPS
|
||||
sysIPV6_MULTICAST_IF = C.IPV6_MULTICAST_IF
|
||||
sysIPV6_MULTICAST_HOPS = C.IPV6_MULTICAST_HOPS
|
||||
sysIPV6_MULTICAST_LOOP = C.IPV6_MULTICAST_LOOP
|
||||
sysIPV6_JOIN_GROUP = C.IPV6_JOIN_GROUP
|
||||
sysIPV6_LEAVE_GROUP = C.IPV6_LEAVE_GROUP
|
||||
sysIPV6_PORTRANGE = C.IPV6_PORTRANGE
|
||||
sysICMP6_FILTER = C.ICMP6_FILTER
|
||||
|
||||
sysIPV6_CHECKSUM = C.IPV6_CHECKSUM
|
||||
sysIPV6_V6ONLY = C.IPV6_V6ONLY
|
||||
|
||||
sysIPV6_RTHDRDSTOPTS = C.IPV6_RTHDRDSTOPTS
|
||||
|
||||
sysIPV6_RECVPKTINFO = C.IPV6_RECVPKTINFO
|
||||
sysIPV6_RECVHOPLIMIT = C.IPV6_RECVHOPLIMIT
|
||||
sysIPV6_RECVRTHDR = C.IPV6_RECVRTHDR
|
||||
sysIPV6_RECVHOPOPTS = C.IPV6_RECVHOPOPTS
|
||||
sysIPV6_RECVDSTOPTS = C.IPV6_RECVDSTOPTS
|
||||
|
||||
sysIPV6_USE_MIN_MTU = C.IPV6_USE_MIN_MTU
|
||||
sysIPV6_RECVPATHMTU = C.IPV6_RECVPATHMTU
|
||||
|
||||
sysIPV6_PATHMTU = C.IPV6_PATHMTU
|
||||
|
||||
sysIPV6_PKTINFO = C.IPV6_PKTINFO
|
||||
sysIPV6_HOPLIMIT = C.IPV6_HOPLIMIT
|
||||
sysIPV6_NEXTHOP = C.IPV6_NEXTHOP
|
||||
sysIPV6_HOPOPTS = C.IPV6_HOPOPTS
|
||||
sysIPV6_DSTOPTS = C.IPV6_DSTOPTS
|
||||
sysIPV6_RTHDR = C.IPV6_RTHDR
|
||||
|
||||
sysIPV6_AUTH_LEVEL = C.IPV6_AUTH_LEVEL
|
||||
sysIPV6_ESP_TRANS_LEVEL = C.IPV6_ESP_TRANS_LEVEL
|
||||
sysIPV6_ESP_NETWORK_LEVEL = C.IPV6_ESP_NETWORK_LEVEL
|
||||
sysIPSEC6_OUTSA = C.IPSEC6_OUTSA
|
||||
sysIPV6_RECVTCLASS = C.IPV6_RECVTCLASS
|
||||
|
||||
sysIPV6_AUTOFLOWLABEL = C.IPV6_AUTOFLOWLABEL
|
||||
sysIPV6_IPCOMP_LEVEL = C.IPV6_IPCOMP_LEVEL
|
||||
|
||||
sysIPV6_TCLASS = C.IPV6_TCLASS
|
||||
sysIPV6_DONTFRAG = C.IPV6_DONTFRAG
|
||||
sysIPV6_PIPEX = C.IPV6_PIPEX
|
||||
|
||||
sysIPV6_RTABLE = C.IPV6_RTABLE
|
||||
|
||||
sysIPV6_PORTRANGE_DEFAULT = C.IPV6_PORTRANGE_DEFAULT
|
||||
sysIPV6_PORTRANGE_HIGH = C.IPV6_PORTRANGE_HIGH
|
||||
sysIPV6_PORTRANGE_LOW = C.IPV6_PORTRANGE_LOW
|
||||
|
||||
sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
|
||||
sizeofInet6Pktinfo = C.sizeof_struct_in6_pktinfo
|
||||
sizeofIPv6Mtuinfo = C.sizeof_struct_ip6_mtuinfo
|
||||
|
||||
sizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq
|
||||
|
||||
sizeofICMPv6Filter = C.sizeof_struct_icmp6_filter
|
||||
)
|
||||
|
||||
type sockaddrInet6 C.struct_sockaddr_in6
|
||||
|
||||
type inet6Pktinfo C.struct_in6_pktinfo
|
||||
|
||||
type ipv6Mtuinfo C.struct_ip6_mtuinfo
|
||||
|
||||
type ipv6Mreq C.struct_ipv6_mreq
|
||||
|
||||
type icmpv6Filter C.struct_icmp6_filter
|
||||
|
|
@ -1,114 +0,0 @@
|
|||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
// +godefs map struct_in6_addr [16]byte /* in6_addr */
|
||||
|
||||
package ipv6
|
||||
|
||||
/*
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/icmp6.h>
|
||||
*/
|
||||
import "C"
|
||||
|
||||
const (
|
||||
sysIPV6_UNICAST_HOPS = C.IPV6_UNICAST_HOPS
|
||||
sysIPV6_MULTICAST_IF = C.IPV6_MULTICAST_IF
|
||||
sysIPV6_MULTICAST_HOPS = C.IPV6_MULTICAST_HOPS
|
||||
sysIPV6_MULTICAST_LOOP = C.IPV6_MULTICAST_LOOP
|
||||
sysIPV6_JOIN_GROUP = C.IPV6_JOIN_GROUP
|
||||
sysIPV6_LEAVE_GROUP = C.IPV6_LEAVE_GROUP
|
||||
|
||||
sysIPV6_PKTINFO = C.IPV6_PKTINFO
|
||||
|
||||
sysIPV6_HOPLIMIT = C.IPV6_HOPLIMIT
|
||||
sysIPV6_NEXTHOP = C.IPV6_NEXTHOP
|
||||
sysIPV6_HOPOPTS = C.IPV6_HOPOPTS
|
||||
sysIPV6_DSTOPTS = C.IPV6_DSTOPTS
|
||||
|
||||
sysIPV6_RTHDR = C.IPV6_RTHDR
|
||||
sysIPV6_RTHDRDSTOPTS = C.IPV6_RTHDRDSTOPTS
|
||||
|
||||
sysIPV6_RECVPKTINFO = C.IPV6_RECVPKTINFO
|
||||
sysIPV6_RECVHOPLIMIT = C.IPV6_RECVHOPLIMIT
|
||||
sysIPV6_RECVHOPOPTS = C.IPV6_RECVHOPOPTS
|
||||
|
||||
sysIPV6_RECVRTHDR = C.IPV6_RECVRTHDR
|
||||
|
||||
sysIPV6_RECVRTHDRDSTOPTS = C.IPV6_RECVRTHDRDSTOPTS
|
||||
|
||||
sysIPV6_CHECKSUM = C.IPV6_CHECKSUM
|
||||
sysIPV6_RECVTCLASS = C.IPV6_RECVTCLASS
|
||||
sysIPV6_USE_MIN_MTU = C.IPV6_USE_MIN_MTU
|
||||
sysIPV6_DONTFRAG = C.IPV6_DONTFRAG
|
||||
sysIPV6_SEC_OPT = C.IPV6_SEC_OPT
|
||||
sysIPV6_SRC_PREFERENCES = C.IPV6_SRC_PREFERENCES
|
||||
sysIPV6_RECVPATHMTU = C.IPV6_RECVPATHMTU
|
||||
sysIPV6_PATHMTU = C.IPV6_PATHMTU
|
||||
sysIPV6_TCLASS = C.IPV6_TCLASS
|
||||
sysIPV6_V6ONLY = C.IPV6_V6ONLY
|
||||
|
||||
sysIPV6_RECVDSTOPTS = C.IPV6_RECVDSTOPTS
|
||||
|
||||
sysMCAST_JOIN_GROUP = C.MCAST_JOIN_GROUP
|
||||
sysMCAST_LEAVE_GROUP = C.MCAST_LEAVE_GROUP
|
||||
sysMCAST_BLOCK_SOURCE = C.MCAST_BLOCK_SOURCE
|
||||
sysMCAST_UNBLOCK_SOURCE = C.MCAST_UNBLOCK_SOURCE
|
||||
sysMCAST_JOIN_SOURCE_GROUP = C.MCAST_JOIN_SOURCE_GROUP
|
||||
sysMCAST_LEAVE_SOURCE_GROUP = C.MCAST_LEAVE_SOURCE_GROUP
|
||||
|
||||
sysIPV6_PREFER_SRC_HOME = C.IPV6_PREFER_SRC_HOME
|
||||
sysIPV6_PREFER_SRC_COA = C.IPV6_PREFER_SRC_COA
|
||||
sysIPV6_PREFER_SRC_PUBLIC = C.IPV6_PREFER_SRC_PUBLIC
|
||||
sysIPV6_PREFER_SRC_TMP = C.IPV6_PREFER_SRC_TMP
|
||||
sysIPV6_PREFER_SRC_NONCGA = C.IPV6_PREFER_SRC_NONCGA
|
||||
sysIPV6_PREFER_SRC_CGA = C.IPV6_PREFER_SRC_CGA
|
||||
|
||||
sysIPV6_PREFER_SRC_MIPMASK = C.IPV6_PREFER_SRC_MIPMASK
|
||||
sysIPV6_PREFER_SRC_MIPDEFAULT = C.IPV6_PREFER_SRC_MIPDEFAULT
|
||||
sysIPV6_PREFER_SRC_TMPMASK = C.IPV6_PREFER_SRC_TMPMASK
|
||||
sysIPV6_PREFER_SRC_TMPDEFAULT = C.IPV6_PREFER_SRC_TMPDEFAULT
|
||||
sysIPV6_PREFER_SRC_CGAMASK = C.IPV6_PREFER_SRC_CGAMASK
|
||||
sysIPV6_PREFER_SRC_CGADEFAULT = C.IPV6_PREFER_SRC_CGADEFAULT
|
||||
|
||||
sysIPV6_PREFER_SRC_MASK = C.IPV6_PREFER_SRC_MASK
|
||||
|
||||
sysIPV6_PREFER_SRC_DEFAULT = C.IPV6_PREFER_SRC_DEFAULT
|
||||
|
||||
sysIPV6_BOUND_IF = C.IPV6_BOUND_IF
|
||||
sysIPV6_UNSPEC_SRC = C.IPV6_UNSPEC_SRC
|
||||
|
||||
sysICMP6_FILTER = C.ICMP6_FILTER
|
||||
|
||||
sizeofSockaddrStorage = C.sizeof_struct_sockaddr_storage
|
||||
sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
|
||||
sizeofInet6Pktinfo = C.sizeof_struct_in6_pktinfo
|
||||
sizeofIPv6Mtuinfo = C.sizeof_struct_ip6_mtuinfo
|
||||
|
||||
sizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq
|
||||
sizeofGroupReq = C.sizeof_struct_group_req
|
||||
sizeofGroupSourceReq = C.sizeof_struct_group_source_req
|
||||
|
||||
sizeofICMPv6Filter = C.sizeof_struct_icmp6_filter
|
||||
)
|
||||
|
||||
type sockaddrStorage C.struct_sockaddr_storage
|
||||
|
||||
type sockaddrInet6 C.struct_sockaddr_in6
|
||||
|
||||
type inet6Pktinfo C.struct_in6_pktinfo
|
||||
|
||||
type ipv6Mtuinfo C.struct_ip6_mtuinfo
|
||||
|
||||
type ipv6Mreq C.struct_ipv6_mreq
|
||||
|
||||
type groupReq C.struct_group_req
|
||||
|
||||
type groupSourceReq C.struct_group_source_req
|
||||
|
||||
type icmpv6Filter C.struct_icmp6_filter
|
||||
|
|
@ -1,199 +0,0 @@
|
|||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
//go:generate go run gen.go
|
||||
|
||||
// This program generates system adaptation constants and types,
|
||||
// internet protocol constants and tables by reading template files
|
||||
// and IANA protocol registries.
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/xml"
|
||||
"fmt"
|
||||
"go/format"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/exec"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func main() {
|
||||
if err := genzsys(); err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
if err := geniana(); err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func genzsys() error {
|
||||
defs := "defs_" + runtime.GOOS + ".go"
|
||||
f, err := os.Open(defs)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
f.Close()
|
||||
cmd := exec.Command("go", "tool", "cgo", "-godefs", defs)
|
||||
b, err := cmd.Output()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
b, err = format.Source(b)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
zsys := "zsys_" + runtime.GOOS + ".go"
|
||||
switch runtime.GOOS {
|
||||
case "freebsd", "linux":
|
||||
zsys = "zsys_" + runtime.GOOS + "_" + runtime.GOARCH + ".go"
|
||||
}
|
||||
if err := ioutil.WriteFile(zsys, b, 0644); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var registries = []struct {
|
||||
url string
|
||||
parse func(io.Writer, io.Reader) error
|
||||
}{
|
||||
{
|
||||
"https://www.iana.org/assignments/icmpv6-parameters/icmpv6-parameters.xml",
|
||||
parseICMPv6Parameters,
|
||||
},
|
||||
}
|
||||
|
||||
func geniana() error {
|
||||
var bb bytes.Buffer
|
||||
fmt.Fprintf(&bb, "// go generate gen.go\n")
|
||||
fmt.Fprintf(&bb, "// Code generated by the command above; DO NOT EDIT.\n\n")
|
||||
fmt.Fprintf(&bb, "package ipv6\n\n")
|
||||
for _, r := range registries {
|
||||
resp, err := http.Get(r.url)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return fmt.Errorf("got HTTP status code %v for %v\n", resp.StatusCode, r.url)
|
||||
}
|
||||
if err := r.parse(&bb, resp.Body); err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Fprintf(&bb, "\n")
|
||||
}
|
||||
b, err := format.Source(bb.Bytes())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := ioutil.WriteFile("iana.go", b, 0644); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func parseICMPv6Parameters(w io.Writer, r io.Reader) error {
|
||||
dec := xml.NewDecoder(r)
|
||||
var icp icmpv6Parameters
|
||||
if err := dec.Decode(&icp); err != nil {
|
||||
return err
|
||||
}
|
||||
prs := icp.escape()
|
||||
fmt.Fprintf(w, "// %s, Updated: %s\n", icp.Title, icp.Updated)
|
||||
fmt.Fprintf(w, "const (\n")
|
||||
for _, pr := range prs {
|
||||
if pr.Name == "" {
|
||||
continue
|
||||
}
|
||||
fmt.Fprintf(w, "ICMPType%s ICMPType = %d", pr.Name, pr.Value)
|
||||
fmt.Fprintf(w, "// %s\n", pr.OrigName)
|
||||
}
|
||||
fmt.Fprintf(w, ")\n\n")
|
||||
fmt.Fprintf(w, "// %s, Updated: %s\n", icp.Title, icp.Updated)
|
||||
fmt.Fprintf(w, "var icmpTypes = map[ICMPType]string{\n")
|
||||
for _, pr := range prs {
|
||||
if pr.Name == "" {
|
||||
continue
|
||||
}
|
||||
fmt.Fprintf(w, "%d: %q,\n", pr.Value, strings.ToLower(pr.OrigName))
|
||||
}
|
||||
fmt.Fprintf(w, "}\n")
|
||||
return nil
|
||||
}
|
||||
|
||||
type icmpv6Parameters struct {
|
||||
XMLName xml.Name `xml:"registry"`
|
||||
Title string `xml:"title"`
|
||||
Updated string `xml:"updated"`
|
||||
Registries []struct {
|
||||
Title string `xml:"title"`
|
||||
Records []struct {
|
||||
Value string `xml:"value"`
|
||||
Name string `xml:"name"`
|
||||
} `xml:"record"`
|
||||
} `xml:"registry"`
|
||||
}
|
||||
|
||||
type canonICMPv6ParamRecord struct {
|
||||
OrigName string
|
||||
Name string
|
||||
Value int
|
||||
}
|
||||
|
||||
func (icp *icmpv6Parameters) escape() []canonICMPv6ParamRecord {
|
||||
id := -1
|
||||
for i, r := range icp.Registries {
|
||||
if strings.Contains(r.Title, "Type") || strings.Contains(r.Title, "type") {
|
||||
id = i
|
||||
break
|
||||
}
|
||||
}
|
||||
if id < 0 {
|
||||
return nil
|
||||
}
|
||||
prs := make([]canonICMPv6ParamRecord, len(icp.Registries[id].Records))
|
||||
sr := strings.NewReplacer(
|
||||
"Messages", "",
|
||||
"Message", "",
|
||||
"ICMP", "",
|
||||
"+", "P",
|
||||
"-", "",
|
||||
"/", "",
|
||||
".", "",
|
||||
" ", "",
|
||||
)
|
||||
for i, pr := range icp.Registries[id].Records {
|
||||
if strings.Contains(pr.Name, "Reserved") ||
|
||||
strings.Contains(pr.Name, "Unassigned") ||
|
||||
strings.Contains(pr.Name, "Deprecated") ||
|
||||
strings.Contains(pr.Name, "Experiment") ||
|
||||
strings.Contains(pr.Name, "experiment") {
|
||||
continue
|
||||
}
|
||||
ss := strings.Split(pr.Name, "\n")
|
||||
if len(ss) > 1 {
|
||||
prs[i].Name = strings.Join(ss, " ")
|
||||
} else {
|
||||
prs[i].Name = ss[0]
|
||||
}
|
||||
s := strings.TrimSpace(prs[i].Name)
|
||||
prs[i].OrigName = s
|
||||
prs[i].Name = sr.Replace(s)
|
||||
prs[i].Value, _ = strconv.Atoi(pr.Value)
|
||||
}
|
||||
return prs
|
||||
}
|
||||
|
|
@ -1,61 +0,0 @@
|
|||
// Copyright 2018 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
// mkasm_darwin.go generates assembly trampolines to call libSystem routines from Go.
|
||||
//This program must be run after mksyscall.go.
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func main() {
|
||||
in1, err := ioutil.ReadFile("syscall_darwin.go")
|
||||
if err != nil {
|
||||
log.Fatalf("can't open syscall_darwin.go: %s", err)
|
||||
}
|
||||
arch := os.Args[1]
|
||||
in2, err := ioutil.ReadFile(fmt.Sprintf("syscall_darwin_%s.go", arch))
|
||||
if err != nil {
|
||||
log.Fatalf("can't open syscall_darwin_%s.go: %s", arch, err)
|
||||
}
|
||||
in3, err := ioutil.ReadFile(fmt.Sprintf("zsyscall_darwin_%s.go", arch))
|
||||
if err != nil {
|
||||
log.Fatalf("can't open zsyscall_darwin_%s.go: %s", arch, err)
|
||||
}
|
||||
in := string(in1) + string(in2) + string(in3)
|
||||
|
||||
trampolines := map[string]bool{}
|
||||
|
||||
var out bytes.Buffer
|
||||
|
||||
fmt.Fprintf(&out, "// go run mkasm_darwin.go %s\n", strings.Join(os.Args[1:], " "))
|
||||
fmt.Fprintf(&out, "// Code generated by the command above; DO NOT EDIT.\n")
|
||||
fmt.Fprintf(&out, "\n")
|
||||
fmt.Fprintf(&out, "// +build go1.12\n")
|
||||
fmt.Fprintf(&out, "\n")
|
||||
fmt.Fprintf(&out, "#include \"textflag.h\"\n")
|
||||
for _, line := range strings.Split(in, "\n") {
|
||||
if !strings.HasPrefix(line, "func ") || !strings.HasSuffix(line, "_trampoline()") {
|
||||
continue
|
||||
}
|
||||
fn := line[5 : len(line)-13]
|
||||
if !trampolines[fn] {
|
||||
trampolines[fn] = true
|
||||
fmt.Fprintf(&out, "TEXT ·%s_trampoline(SB),NOSPLIT,$0-0\n", fn)
|
||||
fmt.Fprintf(&out, "\tJMP\t%s(SB)\n", fn)
|
||||
}
|
||||
}
|
||||
err = ioutil.WriteFile(fmt.Sprintf("zsyscall_darwin_%s.s", arch), out.Bytes(), 0644)
|
||||
if err != nil {
|
||||
log.Fatalf("can't write zsyscall_darwin_%s.s: %s", arch, err)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,106 +0,0 @@
|
|||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
// mkpost processes the output of cgo -godefs to
|
||||
// modify the generated types. It is used to clean up
|
||||
// the sys API in an architecture specific manner.
|
||||
//
|
||||
// mkpost is run after cgo -godefs; see README.md.
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"go/format"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Get the OS and architecture (using GOARCH_TARGET if it exists)
|
||||
goos := os.Getenv("GOOS")
|
||||
goarch := os.Getenv("GOARCH_TARGET")
|
||||
if goarch == "" {
|
||||
goarch = os.Getenv("GOARCH")
|
||||
}
|
||||
// Check that we are using the Docker-based build system if we should be.
|
||||
if goos == "linux" {
|
||||
if os.Getenv("GOLANG_SYS_BUILD") != "docker" {
|
||||
os.Stderr.WriteString("In the Docker-based build system, mkpost should not be called directly.\n")
|
||||
os.Stderr.WriteString("See README.md\n")
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
b, err := ioutil.ReadAll(os.Stdin)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
// Intentionally export __val fields in Fsid and Sigset_t
|
||||
valRegex := regexp.MustCompile(`type (Fsid|Sigset_t) struct {(\s+)X__val(\s+\S+\s+)}`)
|
||||
b = valRegex.ReplaceAll(b, []byte("type $1 struct {${2}Val$3}"))
|
||||
|
||||
// Intentionally export __fds_bits field in FdSet
|
||||
fdSetRegex := regexp.MustCompile(`type (FdSet) struct {(\s+)X__fds_bits(\s+\S+\s+)}`)
|
||||
b = fdSetRegex.ReplaceAll(b, []byte("type $1 struct {${2}Bits$3}"))
|
||||
|
||||
// If we have empty Ptrace structs, we should delete them. Only s390x emits
|
||||
// nonempty Ptrace structs.
|
||||
ptraceRexexp := regexp.MustCompile(`type Ptrace((Psw|Fpregs|Per) struct {\s*})`)
|
||||
b = ptraceRexexp.ReplaceAll(b, nil)
|
||||
|
||||
// Replace the control_regs union with a blank identifier for now.
|
||||
controlRegsRegex := regexp.MustCompile(`(Control_regs)\s+\[0\]uint64`)
|
||||
b = controlRegsRegex.ReplaceAll(b, []byte("_ [0]uint64"))
|
||||
|
||||
// Remove fields that are added by glibc
|
||||
// Note that this is unstable as the identifers are private.
|
||||
removeFieldsRegex := regexp.MustCompile(`X__glibc\S*`)
|
||||
b = removeFieldsRegex.ReplaceAll(b, []byte("_"))
|
||||
|
||||
// Convert [65]int8 to [65]byte in Utsname members to simplify
|
||||
// conversion to string; see golang.org/issue/20753
|
||||
convertUtsnameRegex := regexp.MustCompile(`((Sys|Node|Domain)name|Release|Version|Machine)(\s+)\[(\d+)\]u?int8`)
|
||||
b = convertUtsnameRegex.ReplaceAll(b, []byte("$1$3[$4]byte"))
|
||||
|
||||
// Convert [1024]int8 to [1024]byte in Ptmget members
|
||||
convertPtmget := regexp.MustCompile(`([SC]n)(\s+)\[(\d+)\]u?int8`)
|
||||
b = convertPtmget.ReplaceAll(b, []byte("$1[$3]byte"))
|
||||
|
||||
// Remove spare fields (e.g. in Statx_t)
|
||||
spareFieldsRegex := regexp.MustCompile(`X__spare\S*`)
|
||||
b = spareFieldsRegex.ReplaceAll(b, []byte("_"))
|
||||
|
||||
// Remove cgo padding fields
|
||||
removePaddingFieldsRegex := regexp.MustCompile(`Pad_cgo_\d+`)
|
||||
b = removePaddingFieldsRegex.ReplaceAll(b, []byte("_"))
|
||||
|
||||
// Remove padding, hidden, or unused fields
|
||||
removeFieldsRegex = regexp.MustCompile(`\b(X_\S+|Padding)`)
|
||||
b = removeFieldsRegex.ReplaceAll(b, []byte("_"))
|
||||
|
||||
// Remove the first line of warning from cgo
|
||||
b = b[bytes.IndexByte(b, '\n')+1:]
|
||||
// Modify the command in the header to include:
|
||||
// mkpost, our own warning, and a build tag.
|
||||
replacement := fmt.Sprintf(`$1 | go run mkpost.go
|
||||
// Code generated by the command above; see README.md. DO NOT EDIT.
|
||||
|
||||
// +build %s,%s`, goarch, goos)
|
||||
cgoCommandRegex := regexp.MustCompile(`(cgo -godefs .*)`)
|
||||
b = cgoCommandRegex.ReplaceAll(b, []byte(replacement))
|
||||
|
||||
// gofmt
|
||||
b, err = format.Source(b)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
os.Stdout.Write(b)
|
||||
}
|
||||
|
|
@ -1,407 +0,0 @@
|
|||
// Copyright 2018 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
/*
|
||||
This program reads a file containing function prototypes
|
||||
(like syscall_darwin.go) and generates system call bodies.
|
||||
The prototypes are marked by lines beginning with "//sys"
|
||||
and read like func declarations if //sys is replaced by func, but:
|
||||
* The parameter lists must give a name for each argument.
|
||||
This includes return parameters.
|
||||
* The parameter lists must give a type for each argument:
|
||||
the (x, y, z int) shorthand is not allowed.
|
||||
* If the return parameter is an error number, it must be named errno.
|
||||
|
||||
A line beginning with //sysnb is like //sys, except that the
|
||||
goroutine will not be suspended during the execution of the system
|
||||
call. This must only be used for system calls which can never
|
||||
block, as otherwise the system call could cause all goroutines to
|
||||
hang.
|
||||
*/
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var (
|
||||
b32 = flag.Bool("b32", false, "32bit big-endian")
|
||||
l32 = flag.Bool("l32", false, "32bit little-endian")
|
||||
plan9 = flag.Bool("plan9", false, "plan9")
|
||||
openbsd = flag.Bool("openbsd", false, "openbsd")
|
||||
netbsd = flag.Bool("netbsd", false, "netbsd")
|
||||
dragonfly = flag.Bool("dragonfly", false, "dragonfly")
|
||||
arm = flag.Bool("arm", false, "arm") // 64-bit value should use (even, odd)-pair
|
||||
tags = flag.String("tags", "", "build tags")
|
||||
filename = flag.String("output", "", "output file name (standard output if omitted)")
|
||||
)
|
||||
|
||||
// cmdLine returns this programs's commandline arguments
|
||||
func cmdLine() string {
|
||||
return "go run mksyscall.go " + strings.Join(os.Args[1:], " ")
|
||||
}
|
||||
|
||||
// buildTags returns build tags
|
||||
func buildTags() string {
|
||||
return *tags
|
||||
}
|
||||
|
||||
// Param is function parameter
|
||||
type Param struct {
|
||||
Name string
|
||||
Type string
|
||||
}
|
||||
|
||||
// usage prints the program usage
|
||||
func usage() {
|
||||
fmt.Fprintf(os.Stderr, "usage: go run mksyscall.go [-b32 | -l32] [-tags x,y] [file ...]\n")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// parseParamList parses parameter list and returns a slice of parameters
|
||||
func parseParamList(list string) []string {
|
||||
list = strings.TrimSpace(list)
|
||||
if list == "" {
|
||||
return []string{}
|
||||
}
|
||||
return regexp.MustCompile(`\s*,\s*`).Split(list, -1)
|
||||
}
|
||||
|
||||
// parseParam splits a parameter into name and type
|
||||
func parseParam(p string) Param {
|
||||
ps := regexp.MustCompile(`^(\S*) (\S*)$`).FindStringSubmatch(p)
|
||||
if ps == nil {
|
||||
fmt.Fprintf(os.Stderr, "malformed parameter: %s\n", p)
|
||||
os.Exit(1)
|
||||
}
|
||||
return Param{ps[1], ps[2]}
|
||||
}
|
||||
|
||||
func main() {
|
||||
// Get the OS and architecture (using GOARCH_TARGET if it exists)
|
||||
goos := os.Getenv("GOOS")
|
||||
if goos == "" {
|
||||
fmt.Fprintln(os.Stderr, "GOOS not defined in environment")
|
||||
os.Exit(1)
|
||||
}
|
||||
goarch := os.Getenv("GOARCH_TARGET")
|
||||
if goarch == "" {
|
||||
goarch = os.Getenv("GOARCH")
|
||||
}
|
||||
|
||||
// Check that we are using the Docker-based build system if we should
|
||||
if goos == "linux" {
|
||||
if os.Getenv("GOLANG_SYS_BUILD") != "docker" {
|
||||
fmt.Fprintf(os.Stderr, "In the Docker-based build system, mksyscall should not be called directly.\n")
|
||||
fmt.Fprintf(os.Stderr, "See README.md\n")
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
flag.Usage = usage
|
||||
flag.Parse()
|
||||
if len(flag.Args()) <= 0 {
|
||||
fmt.Fprintf(os.Stderr, "no files to parse provided\n")
|
||||
usage()
|
||||
}
|
||||
|
||||
endianness := ""
|
||||
if *b32 {
|
||||
endianness = "big-endian"
|
||||
} else if *l32 {
|
||||
endianness = "little-endian"
|
||||
}
|
||||
|
||||
libc := false
|
||||
if goos == "darwin" && strings.Contains(buildTags(), ",go1.12") {
|
||||
libc = true
|
||||
}
|
||||
trampolines := map[string]bool{}
|
||||
|
||||
text := ""
|
||||
for _, path := range flag.Args() {
|
||||
file, err := os.Open(path)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
s := bufio.NewScanner(file)
|
||||
for s.Scan() {
|
||||
t := s.Text()
|
||||
t = strings.TrimSpace(t)
|
||||
t = regexp.MustCompile(`\s+`).ReplaceAllString(t, ` `)
|
||||
nonblock := regexp.MustCompile(`^\/\/sysnb `).FindStringSubmatch(t)
|
||||
if regexp.MustCompile(`^\/\/sys `).FindStringSubmatch(t) == nil && nonblock == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
// Line must be of the form
|
||||
// func Open(path string, mode int, perm int) (fd int, errno error)
|
||||
// Split into name, in params, out params.
|
||||
f := regexp.MustCompile(`^\/\/sys(nb)? (\w+)\(([^()]*)\)\s*(?:\(([^()]+)\))?\s*(?:=\s*((?i)SYS_[A-Z0-9_]+))?$`).FindStringSubmatch(t)
|
||||
if f == nil {
|
||||
fmt.Fprintf(os.Stderr, "%s:%s\nmalformed //sys declaration\n", path, t)
|
||||
os.Exit(1)
|
||||
}
|
||||
funct, inps, outps, sysname := f[2], f[3], f[4], f[5]
|
||||
|
||||
// ClockGettime doesn't have a syscall number on Darwin, only generate libc wrappers.
|
||||
if goos == "darwin" && !libc && funct == "ClockGettime" {
|
||||
continue
|
||||
}
|
||||
|
||||
// Split argument lists on comma.
|
||||
in := parseParamList(inps)
|
||||
out := parseParamList(outps)
|
||||
|
||||
// Try in vain to keep people from editing this file.
|
||||
// The theory is that they jump into the middle of the file
|
||||
// without reading the header.
|
||||
text += "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n"
|
||||
|
||||
// Go function header.
|
||||
outDecl := ""
|
||||
if len(out) > 0 {
|
||||
outDecl = fmt.Sprintf(" (%s)", strings.Join(out, ", "))
|
||||
}
|
||||
text += fmt.Sprintf("func %s(%s)%s {\n", funct, strings.Join(in, ", "), outDecl)
|
||||
|
||||
// Check if err return available
|
||||
errvar := ""
|
||||
for _, param := range out {
|
||||
p := parseParam(param)
|
||||
if p.Type == "error" {
|
||||
errvar = p.Name
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Prepare arguments to Syscall.
|
||||
var args []string
|
||||
n := 0
|
||||
for _, param := range in {
|
||||
p := parseParam(param)
|
||||
if regexp.MustCompile(`^\*`).FindStringSubmatch(p.Type) != nil {
|
||||
args = append(args, "uintptr(unsafe.Pointer("+p.Name+"))")
|
||||
} else if p.Type == "string" && errvar != "" {
|
||||
text += fmt.Sprintf("\tvar _p%d *byte\n", n)
|
||||
text += fmt.Sprintf("\t_p%d, %s = BytePtrFromString(%s)\n", n, errvar, p.Name)
|
||||
text += fmt.Sprintf("\tif %s != nil {\n\t\treturn\n\t}\n", errvar)
|
||||
args = append(args, fmt.Sprintf("uintptr(unsafe.Pointer(_p%d))", n))
|
||||
n++
|
||||
} else if p.Type == "string" {
|
||||
fmt.Fprintf(os.Stderr, path+":"+funct+" uses string arguments, but has no error return\n")
|
||||
text += fmt.Sprintf("\tvar _p%d *byte\n", n)
|
||||
text += fmt.Sprintf("\t_p%d, _ = BytePtrFromString(%s)\n", n, p.Name)
|
||||
args = append(args, fmt.Sprintf("uintptr(unsafe.Pointer(_p%d))", n))
|
||||
n++
|
||||
} else if regexp.MustCompile(`^\[\](.*)`).FindStringSubmatch(p.Type) != nil {
|
||||
// Convert slice into pointer, length.
|
||||
// Have to be careful not to take address of &a[0] if len == 0:
|
||||
// pass dummy pointer in that case.
|
||||
// Used to pass nil, but some OSes or simulators reject write(fd, nil, 0).
|
||||
text += fmt.Sprintf("\tvar _p%d unsafe.Pointer\n", n)
|
||||
text += fmt.Sprintf("\tif len(%s) > 0 {\n\t\t_p%d = unsafe.Pointer(&%s[0])\n\t}", p.Name, n, p.Name)
|
||||
text += fmt.Sprintf(" else {\n\t\t_p%d = unsafe.Pointer(&_zero)\n\t}\n", n)
|
||||
args = append(args, fmt.Sprintf("uintptr(_p%d)", n), fmt.Sprintf("uintptr(len(%s))", p.Name))
|
||||
n++
|
||||
} else if p.Type == "int64" && (*openbsd || *netbsd) {
|
||||
args = append(args, "0")
|
||||
if endianness == "big-endian" {
|
||||
args = append(args, fmt.Sprintf("uintptr(%s>>32)", p.Name), fmt.Sprintf("uintptr(%s)", p.Name))
|
||||
} else if endianness == "little-endian" {
|
||||
args = append(args, fmt.Sprintf("uintptr(%s)", p.Name), fmt.Sprintf("uintptr(%s>>32)", p.Name))
|
||||
} else {
|
||||
args = append(args, fmt.Sprintf("uintptr(%s)", p.Name))
|
||||
}
|
||||
} else if p.Type == "int64" && *dragonfly {
|
||||
if regexp.MustCompile(`^(?i)extp(read|write)`).FindStringSubmatch(funct) == nil {
|
||||
args = append(args, "0")
|
||||
}
|
||||
if endianness == "big-endian" {
|
||||
args = append(args, fmt.Sprintf("uintptr(%s>>32)", p.Name), fmt.Sprintf("uintptr(%s)", p.Name))
|
||||
} else if endianness == "little-endian" {
|
||||
args = append(args, fmt.Sprintf("uintptr(%s)", p.Name), fmt.Sprintf("uintptr(%s>>32)", p.Name))
|
||||
} else {
|
||||
args = append(args, fmt.Sprintf("uintptr(%s)", p.Name))
|
||||
}
|
||||
} else if (p.Type == "int64" || p.Type == "uint64") && endianness != "" {
|
||||
if len(args)%2 == 1 && *arm {
|
||||
// arm abi specifies 64-bit argument uses
|
||||
// (even, odd) pair
|
||||
args = append(args, "0")
|
||||
}
|
||||
if endianness == "big-endian" {
|
||||
args = append(args, fmt.Sprintf("uintptr(%s>>32)", p.Name), fmt.Sprintf("uintptr(%s)", p.Name))
|
||||
} else {
|
||||
args = append(args, fmt.Sprintf("uintptr(%s)", p.Name), fmt.Sprintf("uintptr(%s>>32)", p.Name))
|
||||
}
|
||||
} else {
|
||||
args = append(args, fmt.Sprintf("uintptr(%s)", p.Name))
|
||||
}
|
||||
}
|
||||
|
||||
// Determine which form to use; pad args with zeros.
|
||||
asm := "Syscall"
|
||||
if nonblock != nil {
|
||||
if errvar == "" && goos == "linux" {
|
||||
asm = "RawSyscallNoError"
|
||||
} else {
|
||||
asm = "RawSyscall"
|
||||
}
|
||||
} else {
|
||||
if errvar == "" && goos == "linux" {
|
||||
asm = "SyscallNoError"
|
||||
}
|
||||
}
|
||||
if len(args) <= 3 {
|
||||
for len(args) < 3 {
|
||||
args = append(args, "0")
|
||||
}
|
||||
} else if len(args) <= 6 {
|
||||
asm += "6"
|
||||
for len(args) < 6 {
|
||||
args = append(args, "0")
|
||||
}
|
||||
} else if len(args) <= 9 {
|
||||
asm += "9"
|
||||
for len(args) < 9 {
|
||||
args = append(args, "0")
|
||||
}
|
||||
} else {
|
||||
fmt.Fprintf(os.Stderr, "%s:%s too many arguments to system call\n", path, funct)
|
||||
}
|
||||
|
||||
// System call number.
|
||||
if sysname == "" {
|
||||
sysname = "SYS_" + funct
|
||||
sysname = regexp.MustCompile(`([a-z])([A-Z])`).ReplaceAllString(sysname, `${1}_$2`)
|
||||
sysname = strings.ToUpper(sysname)
|
||||
}
|
||||
|
||||
var libcFn string
|
||||
if libc {
|
||||
asm = "syscall_" + strings.ToLower(asm[:1]) + asm[1:] // internal syscall call
|
||||
sysname = strings.TrimPrefix(sysname, "SYS_") // remove SYS_
|
||||
sysname = strings.ToLower(sysname) // lowercase
|
||||
if sysname == "getdirentries64" {
|
||||
// Special case - libSystem name and
|
||||
// raw syscall name don't match.
|
||||
sysname = "__getdirentries64"
|
||||
}
|
||||
libcFn = sysname
|
||||
sysname = "funcPC(libc_" + sysname + "_trampoline)"
|
||||
}
|
||||
|
||||
// Actual call.
|
||||
arglist := strings.Join(args, ", ")
|
||||
call := fmt.Sprintf("%s(%s, %s)", asm, sysname, arglist)
|
||||
|
||||
// Assign return values.
|
||||
body := ""
|
||||
ret := []string{"_", "_", "_"}
|
||||
doErrno := false
|
||||
for i := 0; i < len(out); i++ {
|
||||
p := parseParam(out[i])
|
||||
reg := ""
|
||||
if p.Name == "err" && !*plan9 {
|
||||
reg = "e1"
|
||||
ret[2] = reg
|
||||
doErrno = true
|
||||
} else if p.Name == "err" && *plan9 {
|
||||
ret[0] = "r0"
|
||||
ret[2] = "e1"
|
||||
break
|
||||
} else {
|
||||
reg = fmt.Sprintf("r%d", i)
|
||||
ret[i] = reg
|
||||
}
|
||||
if p.Type == "bool" {
|
||||
reg = fmt.Sprintf("%s != 0", reg)
|
||||
}
|
||||
if p.Type == "int64" && endianness != "" {
|
||||
// 64-bit number in r1:r0 or r0:r1.
|
||||
if i+2 > len(out) {
|
||||
fmt.Fprintf(os.Stderr, "%s:%s not enough registers for int64 return\n", path, funct)
|
||||
}
|
||||
if endianness == "big-endian" {
|
||||
reg = fmt.Sprintf("int64(r%d)<<32 | int64(r%d)", i, i+1)
|
||||
} else {
|
||||
reg = fmt.Sprintf("int64(r%d)<<32 | int64(r%d)", i+1, i)
|
||||
}
|
||||
ret[i] = fmt.Sprintf("r%d", i)
|
||||
ret[i+1] = fmt.Sprintf("r%d", i+1)
|
||||
}
|
||||
if reg != "e1" || *plan9 {
|
||||
body += fmt.Sprintf("\t%s = %s(%s)\n", p.Name, p.Type, reg)
|
||||
}
|
||||
}
|
||||
if ret[0] == "_" && ret[1] == "_" && ret[2] == "_" {
|
||||
text += fmt.Sprintf("\t%s\n", call)
|
||||
} else {
|
||||
if errvar == "" && goos == "linux" {
|
||||
// raw syscall without error on Linux, see golang.org/issue/22924
|
||||
text += fmt.Sprintf("\t%s, %s := %s\n", ret[0], ret[1], call)
|
||||
} else {
|
||||
text += fmt.Sprintf("\t%s, %s, %s := %s\n", ret[0], ret[1], ret[2], call)
|
||||
}
|
||||
}
|
||||
text += body
|
||||
|
||||
if *plan9 && ret[2] == "e1" {
|
||||
text += "\tif int32(r0) == -1 {\n"
|
||||
text += "\t\terr = e1\n"
|
||||
text += "\t}\n"
|
||||
} else if doErrno {
|
||||
text += "\tif e1 != 0 {\n"
|
||||
text += "\t\terr = errnoErr(e1)\n"
|
||||
text += "\t}\n"
|
||||
}
|
||||
text += "\treturn\n"
|
||||
text += "}\n\n"
|
||||
|
||||
if libc && !trampolines[libcFn] {
|
||||
// some system calls share a trampoline, like read and readlen.
|
||||
trampolines[libcFn] = true
|
||||
// Declare assembly trampoline.
|
||||
text += fmt.Sprintf("func libc_%s_trampoline()\n", libcFn)
|
||||
// Assembly trampoline calls the libc_* function, which this magic
|
||||
// redirects to use the function from libSystem.
|
||||
text += fmt.Sprintf("//go:linkname libc_%s libc_%s\n", libcFn, libcFn)
|
||||
text += fmt.Sprintf("//go:cgo_import_dynamic libc_%s %s \"/usr/lib/libSystem.B.dylib\"\n", libcFn, libcFn)
|
||||
text += "\n"
|
||||
}
|
||||
}
|
||||
if err := s.Err(); err != nil {
|
||||
fmt.Fprintf(os.Stderr, err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
file.Close()
|
||||
}
|
||||
fmt.Printf(srcTemplate, cmdLine(), buildTags(), text)
|
||||
}
|
||||
|
||||
const srcTemplate = `// %s
|
||||
// Code generated by the command above; see README.md. DO NOT EDIT.
|
||||
|
||||
// +build %s
|
||||
|
||||
package unix
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
var _ syscall.Errno
|
||||
|
||||
%s
|
||||
`
|
||||
|
|
@ -1,404 +0,0 @@
|
|||
// Copyright 2019 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
/*
|
||||
This program reads a file containing function prototypes
|
||||
(like syscall_aix.go) and generates system call bodies.
|
||||
The prototypes are marked by lines beginning with "//sys"
|
||||
and read like func declarations if //sys is replaced by func, but:
|
||||
* The parameter lists must give a name for each argument.
|
||||
This includes return parameters.
|
||||
* The parameter lists must give a type for each argument:
|
||||
the (x, y, z int) shorthand is not allowed.
|
||||
* If the return parameter is an error number, it must be named err.
|
||||
* If go func name needs to be different than its libc name,
|
||||
* or the function is not in libc, name could be specified
|
||||
* at the end, after "=" sign, like
|
||||
//sys getsockopt(s int, level int, name int, val uintptr, vallen *_Socklen) (err error) = libsocket.getsockopt
|
||||
*/
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var (
|
||||
b32 = flag.Bool("b32", false, "32bit big-endian")
|
||||
l32 = flag.Bool("l32", false, "32bit little-endian")
|
||||
aix = flag.Bool("aix", false, "aix")
|
||||
tags = flag.String("tags", "", "build tags")
|
||||
)
|
||||
|
||||
// cmdLine returns this programs's commandline arguments
|
||||
func cmdLine() string {
|
||||
return "go run mksyscall_aix_ppc.go " + strings.Join(os.Args[1:], " ")
|
||||
}
|
||||
|
||||
// buildTags returns build tags
|
||||
func buildTags() string {
|
||||
return *tags
|
||||
}
|
||||
|
||||
// Param is function parameter
|
||||
type Param struct {
|
||||
Name string
|
||||
Type string
|
||||
}
|
||||
|
||||
// usage prints the program usage
|
||||
func usage() {
|
||||
fmt.Fprintf(os.Stderr, "usage: go run mksyscall_aix_ppc.go [-b32 | -l32] [-tags x,y] [file ...]\n")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// parseParamList parses parameter list and returns a slice of parameters
|
||||
func parseParamList(list string) []string {
|
||||
list = strings.TrimSpace(list)
|
||||
if list == "" {
|
||||
return []string{}
|
||||
}
|
||||
return regexp.MustCompile(`\s*,\s*`).Split(list, -1)
|
||||
}
|
||||
|
||||
// parseParam splits a parameter into name and type
|
||||
func parseParam(p string) Param {
|
||||
ps := regexp.MustCompile(`^(\S*) (\S*)$`).FindStringSubmatch(p)
|
||||
if ps == nil {
|
||||
fmt.Fprintf(os.Stderr, "malformed parameter: %s\n", p)
|
||||
os.Exit(1)
|
||||
}
|
||||
return Param{ps[1], ps[2]}
|
||||
}
|
||||
|
||||
func main() {
|
||||
flag.Usage = usage
|
||||
flag.Parse()
|
||||
if len(flag.Args()) <= 0 {
|
||||
fmt.Fprintf(os.Stderr, "no files to parse provided\n")
|
||||
usage()
|
||||
}
|
||||
|
||||
endianness := ""
|
||||
if *b32 {
|
||||
endianness = "big-endian"
|
||||
} else if *l32 {
|
||||
endianness = "little-endian"
|
||||
}
|
||||
|
||||
pack := ""
|
||||
text := ""
|
||||
cExtern := "/*\n#include <stdint.h>\n#include <stddef.h>\n"
|
||||
for _, path := range flag.Args() {
|
||||
file, err := os.Open(path)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
s := bufio.NewScanner(file)
|
||||
for s.Scan() {
|
||||
t := s.Text()
|
||||
t = strings.TrimSpace(t)
|
||||
t = regexp.MustCompile(`\s+`).ReplaceAllString(t, ` `)
|
||||
if p := regexp.MustCompile(`^package (\S+)$`).FindStringSubmatch(t); p != nil && pack == "" {
|
||||
pack = p[1]
|
||||
}
|
||||
nonblock := regexp.MustCompile(`^\/\/sysnb `).FindStringSubmatch(t)
|
||||
if regexp.MustCompile(`^\/\/sys `).FindStringSubmatch(t) == nil && nonblock == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
// Line must be of the form
|
||||
// func Open(path string, mode int, perm int) (fd int, err error)
|
||||
// Split into name, in params, out params.
|
||||
f := regexp.MustCompile(`^\/\/sys(nb)? (\w+)\(([^()]*)\)\s*(?:\(([^()]+)\))?\s*(?:=\s*(?:(\w*)\.)?(\w*))?$`).FindStringSubmatch(t)
|
||||
if f == nil {
|
||||
fmt.Fprintf(os.Stderr, "%s:%s\nmalformed //sys declaration\n", path, t)
|
||||
os.Exit(1)
|
||||
}
|
||||
funct, inps, outps, modname, sysname := f[2], f[3], f[4], f[5], f[6]
|
||||
|
||||
// Split argument lists on comma.
|
||||
in := parseParamList(inps)
|
||||
out := parseParamList(outps)
|
||||
|
||||
inps = strings.Join(in, ", ")
|
||||
outps = strings.Join(out, ", ")
|
||||
|
||||
// Try in vain to keep people from editing this file.
|
||||
// The theory is that they jump into the middle of the file
|
||||
// without reading the header.
|
||||
text += "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n"
|
||||
|
||||
// Check if value return, err return available
|
||||
errvar := ""
|
||||
retvar := ""
|
||||
rettype := ""
|
||||
for _, param := range out {
|
||||
p := parseParam(param)
|
||||
if p.Type == "error" {
|
||||
errvar = p.Name
|
||||
} else {
|
||||
retvar = p.Name
|
||||
rettype = p.Type
|
||||
}
|
||||
}
|
||||
|
||||
// System call name.
|
||||
if sysname == "" {
|
||||
sysname = funct
|
||||
}
|
||||
sysname = regexp.MustCompile(`([a-z])([A-Z])`).ReplaceAllString(sysname, `${1}_$2`)
|
||||
sysname = strings.ToLower(sysname) // All libc functions are lowercase.
|
||||
|
||||
cRettype := ""
|
||||
if rettype == "unsafe.Pointer" {
|
||||
cRettype = "uintptr_t"
|
||||
} else if rettype == "uintptr" {
|
||||
cRettype = "uintptr_t"
|
||||
} else if regexp.MustCompile(`^_`).FindStringSubmatch(rettype) != nil {
|
||||
cRettype = "uintptr_t"
|
||||
} else if rettype == "int" {
|
||||
cRettype = "int"
|
||||
} else if rettype == "int32" {
|
||||
cRettype = "int"
|
||||
} else if rettype == "int64" {
|
||||
cRettype = "long long"
|
||||
} else if rettype == "uint32" {
|
||||
cRettype = "unsigned int"
|
||||
} else if rettype == "uint64" {
|
||||
cRettype = "unsigned long long"
|
||||
} else {
|
||||
cRettype = "int"
|
||||
}
|
||||
if sysname == "exit" {
|
||||
cRettype = "void"
|
||||
}
|
||||
|
||||
// Change p.Types to c
|
||||
var cIn []string
|
||||
for _, param := range in {
|
||||
p := parseParam(param)
|
||||
if regexp.MustCompile(`^\*`).FindStringSubmatch(p.Type) != nil {
|
||||
cIn = append(cIn, "uintptr_t")
|
||||
} else if p.Type == "string" {
|
||||
cIn = append(cIn, "uintptr_t")
|
||||
} else if regexp.MustCompile(`^\[\](.*)`).FindStringSubmatch(p.Type) != nil {
|
||||
cIn = append(cIn, "uintptr_t", "size_t")
|
||||
} else if p.Type == "unsafe.Pointer" {
|
||||
cIn = append(cIn, "uintptr_t")
|
||||
} else if p.Type == "uintptr" {
|
||||
cIn = append(cIn, "uintptr_t")
|
||||
} else if regexp.MustCompile(`^_`).FindStringSubmatch(p.Type) != nil {
|
||||
cIn = append(cIn, "uintptr_t")
|
||||
} else if p.Type == "int" {
|
||||
cIn = append(cIn, "int")
|
||||
} else if p.Type == "int32" {
|
||||
cIn = append(cIn, "int")
|
||||
} else if p.Type == "int64" {
|
||||
cIn = append(cIn, "long long")
|
||||
} else if p.Type == "uint32" {
|
||||
cIn = append(cIn, "unsigned int")
|
||||
} else if p.Type == "uint64" {
|
||||
cIn = append(cIn, "unsigned long long")
|
||||
} else {
|
||||
cIn = append(cIn, "int")
|
||||
}
|
||||
}
|
||||
|
||||
if funct != "fcntl" && funct != "FcntlInt" && funct != "readlen" && funct != "writelen" {
|
||||
// Imports of system calls from libc
|
||||
cExtern += fmt.Sprintf("%s %s", cRettype, sysname)
|
||||
cIn := strings.Join(cIn, ", ")
|
||||
cExtern += fmt.Sprintf("(%s);\n", cIn)
|
||||
}
|
||||
|
||||
// So file name.
|
||||
if *aix {
|
||||
if modname == "" {
|
||||
modname = "libc.a/shr_64.o"
|
||||
} else {
|
||||
fmt.Fprintf(os.Stderr, "%s: only syscall using libc are available\n", funct)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
strconvfunc := "C.CString"
|
||||
|
||||
// Go function header.
|
||||
if outps != "" {
|
||||
outps = fmt.Sprintf(" (%s)", outps)
|
||||
}
|
||||
if text != "" {
|
||||
text += "\n"
|
||||
}
|
||||
|
||||
text += fmt.Sprintf("func %s(%s)%s {\n", funct, strings.Join(in, ", "), outps)
|
||||
|
||||
// Prepare arguments to Syscall.
|
||||
var args []string
|
||||
n := 0
|
||||
argN := 0
|
||||
for _, param := range in {
|
||||
p := parseParam(param)
|
||||
if regexp.MustCompile(`^\*`).FindStringSubmatch(p.Type) != nil {
|
||||
args = append(args, "C.uintptr_t(uintptr(unsafe.Pointer("+p.Name+")))")
|
||||
} else if p.Type == "string" && errvar != "" {
|
||||
text += fmt.Sprintf("\t_p%d := uintptr(unsafe.Pointer(%s(%s)))\n", n, strconvfunc, p.Name)
|
||||
args = append(args, fmt.Sprintf("C.uintptr_t(_p%d)", n))
|
||||
n++
|
||||
} else if p.Type == "string" {
|
||||
fmt.Fprintf(os.Stderr, path+":"+funct+" uses string arguments, but has no error return\n")
|
||||
text += fmt.Sprintf("\t_p%d := uintptr(unsafe.Pointer(%s(%s)))\n", n, strconvfunc, p.Name)
|
||||
args = append(args, fmt.Sprintf("C.uintptr_t(_p%d)", n))
|
||||
n++
|
||||
} else if m := regexp.MustCompile(`^\[\](.*)`).FindStringSubmatch(p.Type); m != nil {
|
||||
// Convert slice into pointer, length.
|
||||
// Have to be careful not to take address of &a[0] if len == 0:
|
||||
// pass nil in that case.
|
||||
text += fmt.Sprintf("\tvar _p%d *%s\n", n, m[1])
|
||||
text += fmt.Sprintf("\tif len(%s) > 0 {\n\t\t_p%d = &%s[0]\n\t}\n", p.Name, n, p.Name)
|
||||
args = append(args, fmt.Sprintf("C.uintptr_t(uintptr(unsafe.Pointer(_p%d)))", n))
|
||||
n++
|
||||
text += fmt.Sprintf("\tvar _p%d int\n", n)
|
||||
text += fmt.Sprintf("\t_p%d = len(%s)\n", n, p.Name)
|
||||
args = append(args, fmt.Sprintf("C.size_t(_p%d)", n))
|
||||
n++
|
||||
} else if p.Type == "int64" && endianness != "" {
|
||||
if endianness == "big-endian" {
|
||||
args = append(args, fmt.Sprintf("uintptr(%s>>32)", p.Name), fmt.Sprintf("uintptr(%s)", p.Name))
|
||||
} else {
|
||||
args = append(args, fmt.Sprintf("uintptr(%s)", p.Name), fmt.Sprintf("uintptr(%s>>32)", p.Name))
|
||||
}
|
||||
n++
|
||||
} else if p.Type == "bool" {
|
||||
text += fmt.Sprintf("\tvar _p%d uint32\n", n)
|
||||
text += fmt.Sprintf("\tif %s {\n\t\t_p%d = 1\n\t} else {\n\t\t_p%d = 0\n\t}\n", p.Name, n, n)
|
||||
args = append(args, fmt.Sprintf("_p%d", n))
|
||||
} else if regexp.MustCompile(`^_`).FindStringSubmatch(p.Type) != nil {
|
||||
args = append(args, fmt.Sprintf("C.uintptr_t(uintptr(%s))", p.Name))
|
||||
} else if p.Type == "unsafe.Pointer" {
|
||||
args = append(args, fmt.Sprintf("C.uintptr_t(uintptr(%s))", p.Name))
|
||||
} else if p.Type == "int" {
|
||||
if (argN == 2) && ((funct == "readlen") || (funct == "writelen")) {
|
||||
args = append(args, fmt.Sprintf("C.size_t(%s)", p.Name))
|
||||
} else if argN == 0 && funct == "fcntl" {
|
||||
args = append(args, fmt.Sprintf("C.uintptr_t(%s)", p.Name))
|
||||
} else if (argN == 2) && ((funct == "fcntl") || (funct == "FcntlInt")) {
|
||||
args = append(args, fmt.Sprintf("C.uintptr_t(%s)", p.Name))
|
||||
} else {
|
||||
args = append(args, fmt.Sprintf("C.int(%s)", p.Name))
|
||||
}
|
||||
} else if p.Type == "int32" {
|
||||
args = append(args, fmt.Sprintf("C.int(%s)", p.Name))
|
||||
} else if p.Type == "int64" {
|
||||
args = append(args, fmt.Sprintf("C.longlong(%s)", p.Name))
|
||||
} else if p.Type == "uint32" {
|
||||
args = append(args, fmt.Sprintf("C.uint(%s)", p.Name))
|
||||
} else if p.Type == "uint64" {
|
||||
args = append(args, fmt.Sprintf("C.ulonglong(%s)", p.Name))
|
||||
} else if p.Type == "uintptr" {
|
||||
args = append(args, fmt.Sprintf("C.uintptr_t(%s)", p.Name))
|
||||
} else {
|
||||
args = append(args, fmt.Sprintf("C.int(%s)", p.Name))
|
||||
}
|
||||
argN++
|
||||
}
|
||||
|
||||
// Actual call.
|
||||
arglist := strings.Join(args, ", ")
|
||||
call := ""
|
||||
if sysname == "exit" {
|
||||
if errvar != "" {
|
||||
call += "er :="
|
||||
} else {
|
||||
call += ""
|
||||
}
|
||||
} else if errvar != "" {
|
||||
call += "r0,er :="
|
||||
} else if retvar != "" {
|
||||
call += "r0,_ :="
|
||||
} else {
|
||||
call += ""
|
||||
}
|
||||
call += fmt.Sprintf("C.%s(%s)", sysname, arglist)
|
||||
|
||||
// Assign return values.
|
||||
body := ""
|
||||
for i := 0; i < len(out); i++ {
|
||||
p := parseParam(out[i])
|
||||
reg := ""
|
||||
if p.Name == "err" {
|
||||
reg = "e1"
|
||||
} else {
|
||||
reg = "r0"
|
||||
}
|
||||
if reg != "e1" {
|
||||
body += fmt.Sprintf("\t%s = %s(%s)\n", p.Name, p.Type, reg)
|
||||
}
|
||||
}
|
||||
|
||||
// verify return
|
||||
if sysname != "exit" && errvar != "" {
|
||||
if regexp.MustCompile(`^uintptr`).FindStringSubmatch(cRettype) != nil {
|
||||
body += "\tif (uintptr(r0) ==^uintptr(0) && er != nil) {\n"
|
||||
body += fmt.Sprintf("\t\t%s = er\n", errvar)
|
||||
body += "\t}\n"
|
||||
} else {
|
||||
body += "\tif (r0 ==-1 && er != nil) {\n"
|
||||
body += fmt.Sprintf("\t\t%s = er\n", errvar)
|
||||
body += "\t}\n"
|
||||
}
|
||||
} else if errvar != "" {
|
||||
body += "\tif (er != nil) {\n"
|
||||
body += fmt.Sprintf("\t\t%s = er\n", errvar)
|
||||
body += "\t}\n"
|
||||
}
|
||||
|
||||
text += fmt.Sprintf("\t%s\n", call)
|
||||
text += body
|
||||
|
||||
text += "\treturn\n"
|
||||
text += "}\n"
|
||||
}
|
||||
if err := s.Err(); err != nil {
|
||||
fmt.Fprintf(os.Stderr, err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
file.Close()
|
||||
}
|
||||
imp := ""
|
||||
if pack != "unix" {
|
||||
imp = "import \"golang.org/x/sys/unix\"\n"
|
||||
|
||||
}
|
||||
fmt.Printf(srcTemplate, cmdLine(), buildTags(), pack, cExtern, imp, text)
|
||||
}
|
||||
|
||||
const srcTemplate = `// %s
|
||||
// Code generated by the command above; see README.md. DO NOT EDIT.
|
||||
|
||||
// +build %s
|
||||
|
||||
package %s
|
||||
|
||||
|
||||
%s
|
||||
*/
|
||||
import "C"
|
||||
import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
|
||||
%s
|
||||
|
||||
%s
|
||||
`
|
||||
|
|
@ -1,602 +0,0 @@
|
|||
// Copyright 2019 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
/*
|
||||
This program reads a file containing function prototypes
|
||||
(like syscall_aix.go) and generates system call bodies.
|
||||
The prototypes are marked by lines beginning with "//sys"
|
||||
and read like func declarations if //sys is replaced by func, but:
|
||||
* The parameter lists must give a name for each argument.
|
||||
This includes return parameters.
|
||||
* The parameter lists must give a type for each argument:
|
||||
the (x, y, z int) shorthand is not allowed.
|
||||
* If the return parameter is an error number, it must be named err.
|
||||
* If go func name needs to be different than its libc name,
|
||||
* or the function is not in libc, name could be specified
|
||||
* at the end, after "=" sign, like
|
||||
//sys getsockopt(s int, level int, name int, val uintptr, vallen *_Socklen) (err error) = libsocket.getsockopt
|
||||
|
||||
|
||||
This program will generate three files and handle both gc and gccgo implementation:
|
||||
- zsyscall_aix_ppc64.go: the common part of each implementation (error handler, pointer creation)
|
||||
- zsyscall_aix_ppc64_gc.go: gc part with //go_cgo_import_dynamic and a call to syscall6
|
||||
- zsyscall_aix_ppc64_gccgo.go: gccgo part with C function and conversion to C type.
|
||||
|
||||
The generated code looks like this
|
||||
|
||||
zsyscall_aix_ppc64.go
|
||||
func asyscall(...) (n int, err error) {
|
||||
// Pointer Creation
|
||||
r1, e1 := callasyscall(...)
|
||||
// Type Conversion
|
||||
// Error Handler
|
||||
return
|
||||
}
|
||||
|
||||
zsyscall_aix_ppc64_gc.go
|
||||
//go:cgo_import_dynamic libc_asyscall asyscall "libc.a/shr_64.o"
|
||||
//go:linkname libc_asyscall libc_asyscall
|
||||
var asyscall syscallFunc
|
||||
|
||||
func callasyscall(...) (r1 uintptr, e1 Errno) {
|
||||
r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_asyscall)), "nb_args", ... )
|
||||
return
|
||||
}
|
||||
|
||||
zsyscall_aix_ppc64_ggcgo.go
|
||||
|
||||
// int asyscall(...)
|
||||
|
||||
import "C"
|
||||
|
||||
func callasyscall(...) (r1 uintptr, e1 Errno) {
|
||||
r1 = uintptr(C.asyscall(...))
|
||||
e1 = syscall.GetErrno()
|
||||
return
|
||||
}
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var (
|
||||
b32 = flag.Bool("b32", false, "32bit big-endian")
|
||||
l32 = flag.Bool("l32", false, "32bit little-endian")
|
||||
aix = flag.Bool("aix", false, "aix")
|
||||
tags = flag.String("tags", "", "build tags")
|
||||
)
|
||||
|
||||
// cmdLine returns this programs's commandline arguments
|
||||
func cmdLine() string {
|
||||
return "go run mksyscall_aix_ppc64.go " + strings.Join(os.Args[1:], " ")
|
||||
}
|
||||
|
||||
// buildTags returns build tags
|
||||
func buildTags() string {
|
||||
return *tags
|
||||
}
|
||||
|
||||
// Param is function parameter
|
||||
type Param struct {
|
||||
Name string
|
||||
Type string
|
||||
}
|
||||
|
||||
// usage prints the program usage
|
||||
func usage() {
|
||||
fmt.Fprintf(os.Stderr, "usage: go run mksyscall_aix_ppc64.go [-b32 | -l32] [-tags x,y] [file ...]\n")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// parseParamList parses parameter list and returns a slice of parameters
|
||||
func parseParamList(list string) []string {
|
||||
list = strings.TrimSpace(list)
|
||||
if list == "" {
|
||||
return []string{}
|
||||
}
|
||||
return regexp.MustCompile(`\s*,\s*`).Split(list, -1)
|
||||
}
|
||||
|
||||
// parseParam splits a parameter into name and type
|
||||
func parseParam(p string) Param {
|
||||
ps := regexp.MustCompile(`^(\S*) (\S*)$`).FindStringSubmatch(p)
|
||||
if ps == nil {
|
||||
fmt.Fprintf(os.Stderr, "malformed parameter: %s\n", p)
|
||||
os.Exit(1)
|
||||
}
|
||||
return Param{ps[1], ps[2]}
|
||||
}
|
||||
|
||||
func main() {
|
||||
flag.Usage = usage
|
||||
flag.Parse()
|
||||
if len(flag.Args()) <= 0 {
|
||||
fmt.Fprintf(os.Stderr, "no files to parse provided\n")
|
||||
usage()
|
||||
}
|
||||
|
||||
endianness := ""
|
||||
if *b32 {
|
||||
endianness = "big-endian"
|
||||
} else if *l32 {
|
||||
endianness = "little-endian"
|
||||
}
|
||||
|
||||
pack := ""
|
||||
// GCCGO
|
||||
textgccgo := ""
|
||||
cExtern := "/*\n#include <stdint.h>\n"
|
||||
// GC
|
||||
textgc := ""
|
||||
dynimports := ""
|
||||
linknames := ""
|
||||
var vars []string
|
||||
// COMMON
|
||||
textcommon := ""
|
||||
for _, path := range flag.Args() {
|
||||
file, err := os.Open(path)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
s := bufio.NewScanner(file)
|
||||
for s.Scan() {
|
||||
t := s.Text()
|
||||
t = strings.TrimSpace(t)
|
||||
t = regexp.MustCompile(`\s+`).ReplaceAllString(t, ` `)
|
||||
if p := regexp.MustCompile(`^package (\S+)$`).FindStringSubmatch(t); p != nil && pack == "" {
|
||||
pack = p[1]
|
||||
}
|
||||
nonblock := regexp.MustCompile(`^\/\/sysnb `).FindStringSubmatch(t)
|
||||
if regexp.MustCompile(`^\/\/sys `).FindStringSubmatch(t) == nil && nonblock == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
// Line must be of the form
|
||||
// func Open(path string, mode int, perm int) (fd int, err error)
|
||||
// Split into name, in params, out params.
|
||||
f := regexp.MustCompile(`^\/\/sys(nb)? (\w+)\(([^()]*)\)\s*(?:\(([^()]+)\))?\s*(?:=\s*(?:(\w*)\.)?(\w*))?$`).FindStringSubmatch(t)
|
||||
if f == nil {
|
||||
fmt.Fprintf(os.Stderr, "%s:%s\nmalformed //sys declaration\n", path, t)
|
||||
os.Exit(1)
|
||||
}
|
||||
funct, inps, outps, modname, sysname := f[2], f[3], f[4], f[5], f[6]
|
||||
|
||||
// Split argument lists on comma.
|
||||
in := parseParamList(inps)
|
||||
out := parseParamList(outps)
|
||||
|
||||
inps = strings.Join(in, ", ")
|
||||
outps = strings.Join(out, ", ")
|
||||
|
||||
if sysname == "" {
|
||||
sysname = funct
|
||||
}
|
||||
|
||||
onlyCommon := false
|
||||
if funct == "readlen" || funct == "writelen" || funct == "FcntlInt" || funct == "FcntlFlock" {
|
||||
// This function call another syscall which is already implemented.
|
||||
// Therefore, the gc and gccgo part must not be generated.
|
||||
onlyCommon = true
|
||||
}
|
||||
|
||||
// Try in vain to keep people from editing this file.
|
||||
// The theory is that they jump into the middle of the file
|
||||
// without reading the header.
|
||||
|
||||
textcommon += "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n"
|
||||
if !onlyCommon {
|
||||
textgccgo += "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n"
|
||||
textgc += "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n"
|
||||
}
|
||||
|
||||
// Check if value return, err return available
|
||||
errvar := ""
|
||||
rettype := ""
|
||||
for _, param := range out {
|
||||
p := parseParam(param)
|
||||
if p.Type == "error" {
|
||||
errvar = p.Name
|
||||
} else {
|
||||
rettype = p.Type
|
||||
}
|
||||
}
|
||||
|
||||
sysname = regexp.MustCompile(`([a-z])([A-Z])`).ReplaceAllString(sysname, `${1}_$2`)
|
||||
sysname = strings.ToLower(sysname) // All libc functions are lowercase.
|
||||
|
||||
// GCCGO Prototype return type
|
||||
cRettype := ""
|
||||
if rettype == "unsafe.Pointer" {
|
||||
cRettype = "uintptr_t"
|
||||
} else if rettype == "uintptr" {
|
||||
cRettype = "uintptr_t"
|
||||
} else if regexp.MustCompile(`^_`).FindStringSubmatch(rettype) != nil {
|
||||
cRettype = "uintptr_t"
|
||||
} else if rettype == "int" {
|
||||
cRettype = "int"
|
||||
} else if rettype == "int32" {
|
||||
cRettype = "int"
|
||||
} else if rettype == "int64" {
|
||||
cRettype = "long long"
|
||||
} else if rettype == "uint32" {
|
||||
cRettype = "unsigned int"
|
||||
} else if rettype == "uint64" {
|
||||
cRettype = "unsigned long long"
|
||||
} else {
|
||||
cRettype = "int"
|
||||
}
|
||||
if sysname == "exit" {
|
||||
cRettype = "void"
|
||||
}
|
||||
|
||||
// GCCGO Prototype arguments type
|
||||
var cIn []string
|
||||
for i, param := range in {
|
||||
p := parseParam(param)
|
||||
if regexp.MustCompile(`^\*`).FindStringSubmatch(p.Type) != nil {
|
||||
cIn = append(cIn, "uintptr_t")
|
||||
} else if p.Type == "string" {
|
||||
cIn = append(cIn, "uintptr_t")
|
||||
} else if regexp.MustCompile(`^\[\](.*)`).FindStringSubmatch(p.Type) != nil {
|
||||
cIn = append(cIn, "uintptr_t", "size_t")
|
||||
} else if p.Type == "unsafe.Pointer" {
|
||||
cIn = append(cIn, "uintptr_t")
|
||||
} else if p.Type == "uintptr" {
|
||||
cIn = append(cIn, "uintptr_t")
|
||||
} else if regexp.MustCompile(`^_`).FindStringSubmatch(p.Type) != nil {
|
||||
cIn = append(cIn, "uintptr_t")
|
||||
} else if p.Type == "int" {
|
||||
if (i == 0 || i == 2) && funct == "fcntl" {
|
||||
// These fcntl arguments needs to be uintptr to be able to call FcntlInt and FcntlFlock
|
||||
cIn = append(cIn, "uintptr_t")
|
||||
} else {
|
||||
cIn = append(cIn, "int")
|
||||
}
|
||||
|
||||
} else if p.Type == "int32" {
|
||||
cIn = append(cIn, "int")
|
||||
} else if p.Type == "int64" {
|
||||
cIn = append(cIn, "long long")
|
||||
} else if p.Type == "uint32" {
|
||||
cIn = append(cIn, "unsigned int")
|
||||
} else if p.Type == "uint64" {
|
||||
cIn = append(cIn, "unsigned long long")
|
||||
} else {
|
||||
cIn = append(cIn, "int")
|
||||
}
|
||||
}
|
||||
|
||||
if !onlyCommon {
|
||||
// GCCGO Prototype Generation
|
||||
// Imports of system calls from libc
|
||||
cExtern += fmt.Sprintf("%s %s", cRettype, sysname)
|
||||
cIn := strings.Join(cIn, ", ")
|
||||
cExtern += fmt.Sprintf("(%s);\n", cIn)
|
||||
}
|
||||
// GC Library name
|
||||
if modname == "" {
|
||||
modname = "libc.a/shr_64.o"
|
||||
} else {
|
||||
fmt.Fprintf(os.Stderr, "%s: only syscall using libc are available\n", funct)
|
||||
os.Exit(1)
|
||||
}
|
||||
sysvarname := fmt.Sprintf("libc_%s", sysname)
|
||||
|
||||
if !onlyCommon {
|
||||
// GC Runtime import of function to allow cross-platform builds.
|
||||
dynimports += fmt.Sprintf("//go:cgo_import_dynamic %s %s \"%s\"\n", sysvarname, sysname, modname)
|
||||
// GC Link symbol to proc address variable.
|
||||
linknames += fmt.Sprintf("//go:linkname %s %s\n", sysvarname, sysvarname)
|
||||
// GC Library proc address variable.
|
||||
vars = append(vars, sysvarname)
|
||||
}
|
||||
|
||||
strconvfunc := "BytePtrFromString"
|
||||
strconvtype := "*byte"
|
||||
|
||||
// Go function header.
|
||||
if outps != "" {
|
||||
outps = fmt.Sprintf(" (%s)", outps)
|
||||
}
|
||||
if textcommon != "" {
|
||||
textcommon += "\n"
|
||||
}
|
||||
|
||||
textcommon += fmt.Sprintf("func %s(%s)%s {\n", funct, strings.Join(in, ", "), outps)
|
||||
|
||||
// Prepare arguments tocall.
|
||||
var argscommon []string // Arguments in the common part
|
||||
var argscall []string // Arguments for call prototype
|
||||
var argsgc []string // Arguments for gc call (with syscall6)
|
||||
var argsgccgo []string // Arguments for gccgo call (with C.name_of_syscall)
|
||||
n := 0
|
||||
argN := 0
|
||||
for _, param := range in {
|
||||
p := parseParam(param)
|
||||
if regexp.MustCompile(`^\*`).FindStringSubmatch(p.Type) != nil {
|
||||
argscommon = append(argscommon, fmt.Sprintf("uintptr(unsafe.Pointer(%s))", p.Name))
|
||||
argscall = append(argscall, fmt.Sprintf("%s uintptr", p.Name))
|
||||
argsgc = append(argsgc, p.Name)
|
||||
argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(%s)", p.Name))
|
||||
} else if p.Type == "string" && errvar != "" {
|
||||
textcommon += fmt.Sprintf("\tvar _p%d %s\n", n, strconvtype)
|
||||
textcommon += fmt.Sprintf("\t_p%d, %s = %s(%s)\n", n, errvar, strconvfunc, p.Name)
|
||||
textcommon += fmt.Sprintf("\tif %s != nil {\n\t\treturn\n\t}\n", errvar)
|
||||
|
||||
argscommon = append(argscommon, fmt.Sprintf("uintptr(unsafe.Pointer(_p%d))", n))
|
||||
argscall = append(argscall, fmt.Sprintf("_p%d uintptr ", n))
|
||||
argsgc = append(argsgc, fmt.Sprintf("_p%d", n))
|
||||
argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(_p%d)", n))
|
||||
n++
|
||||
} else if p.Type == "string" {
|
||||
fmt.Fprintf(os.Stderr, path+":"+funct+" uses string arguments, but has no error return\n")
|
||||
textcommon += fmt.Sprintf("\tvar _p%d %s\n", n, strconvtype)
|
||||
textcommon += fmt.Sprintf("\t_p%d, %s = %s(%s)\n", n, errvar, strconvfunc, p.Name)
|
||||
textcommon += fmt.Sprintf("\tif %s != nil {\n\t\treturn\n\t}\n", errvar)
|
||||
|
||||
argscommon = append(argscommon, fmt.Sprintf("uintptr(unsafe.Pointer(_p%d))", n))
|
||||
argscall = append(argscall, fmt.Sprintf("_p%d uintptr", n))
|
||||
argsgc = append(argsgc, fmt.Sprintf("_p%d", n))
|
||||
argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(_p%d)", n))
|
||||
n++
|
||||
} else if m := regexp.MustCompile(`^\[\](.*)`).FindStringSubmatch(p.Type); m != nil {
|
||||
// Convert slice into pointer, length.
|
||||
// Have to be careful not to take address of &a[0] if len == 0:
|
||||
// pass nil in that case.
|
||||
textcommon += fmt.Sprintf("\tvar _p%d *%s\n", n, m[1])
|
||||
textcommon += fmt.Sprintf("\tif len(%s) > 0 {\n\t\t_p%d = &%s[0]\n\t}\n", p.Name, n, p.Name)
|
||||
argscommon = append(argscommon, fmt.Sprintf("uintptr(unsafe.Pointer(_p%d))", n), fmt.Sprintf("len(%s)", p.Name))
|
||||
argscall = append(argscall, fmt.Sprintf("_p%d uintptr", n), fmt.Sprintf("_lenp%d int", n))
|
||||
argsgc = append(argsgc, fmt.Sprintf("_p%d", n), fmt.Sprintf("uintptr(_lenp%d)", n))
|
||||
argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(_p%d)", n), fmt.Sprintf("C.size_t(_lenp%d)", n))
|
||||
n++
|
||||
} else if p.Type == "int64" && endianness != "" {
|
||||
fmt.Fprintf(os.Stderr, path+":"+funct+" uses int64 with 32 bits mode. Case not yet implemented\n")
|
||||
} else if p.Type == "bool" {
|
||||
fmt.Fprintf(os.Stderr, path+":"+funct+" uses bool. Case not yet implemented\n")
|
||||
} else if regexp.MustCompile(`^_`).FindStringSubmatch(p.Type) != nil || p.Type == "unsafe.Pointer" {
|
||||
argscommon = append(argscommon, fmt.Sprintf("uintptr(%s)", p.Name))
|
||||
argscall = append(argscall, fmt.Sprintf("%s uintptr", p.Name))
|
||||
argsgc = append(argsgc, p.Name)
|
||||
argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(%s)", p.Name))
|
||||
} else if p.Type == "int" {
|
||||
if (argN == 0 || argN == 2) && ((funct == "fcntl") || (funct == "FcntlInt") || (funct == "FcntlFlock")) {
|
||||
// These fcntl arguments need to be uintptr to be able to call FcntlInt and FcntlFlock
|
||||
argscommon = append(argscommon, fmt.Sprintf("uintptr(%s)", p.Name))
|
||||
argscall = append(argscall, fmt.Sprintf("%s uintptr", p.Name))
|
||||
argsgc = append(argsgc, p.Name)
|
||||
argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(%s)", p.Name))
|
||||
|
||||
} else {
|
||||
argscommon = append(argscommon, p.Name)
|
||||
argscall = append(argscall, fmt.Sprintf("%s int", p.Name))
|
||||
argsgc = append(argsgc, fmt.Sprintf("uintptr(%s)", p.Name))
|
||||
argsgccgo = append(argsgccgo, fmt.Sprintf("C.int(%s)", p.Name))
|
||||
}
|
||||
} else if p.Type == "int32" {
|
||||
argscommon = append(argscommon, p.Name)
|
||||
argscall = append(argscall, fmt.Sprintf("%s int32", p.Name))
|
||||
argsgc = append(argsgc, fmt.Sprintf("uintptr(%s)", p.Name))
|
||||
argsgccgo = append(argsgccgo, fmt.Sprintf("C.int(%s)", p.Name))
|
||||
} else if p.Type == "int64" {
|
||||
argscommon = append(argscommon, p.Name)
|
||||
argscall = append(argscall, fmt.Sprintf("%s int64", p.Name))
|
||||
argsgc = append(argsgc, fmt.Sprintf("uintptr(%s)", p.Name))
|
||||
argsgccgo = append(argsgccgo, fmt.Sprintf("C.longlong(%s)", p.Name))
|
||||
} else if p.Type == "uint32" {
|
||||
argscommon = append(argscommon, p.Name)
|
||||
argscall = append(argscall, fmt.Sprintf("%s uint32", p.Name))
|
||||
argsgc = append(argsgc, fmt.Sprintf("uintptr(%s)", p.Name))
|
||||
argsgccgo = append(argsgccgo, fmt.Sprintf("C.uint(%s)", p.Name))
|
||||
} else if p.Type == "uint64" {
|
||||
argscommon = append(argscommon, p.Name)
|
||||
argscall = append(argscall, fmt.Sprintf("%s uint64", p.Name))
|
||||
argsgc = append(argsgc, fmt.Sprintf("uintptr(%s)", p.Name))
|
||||
argsgccgo = append(argsgccgo, fmt.Sprintf("C.ulonglong(%s)", p.Name))
|
||||
} else if p.Type == "uintptr" {
|
||||
argscommon = append(argscommon, p.Name)
|
||||
argscall = append(argscall, fmt.Sprintf("%s uintptr", p.Name))
|
||||
argsgc = append(argsgc, p.Name)
|
||||
argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(%s)", p.Name))
|
||||
} else {
|
||||
argscommon = append(argscommon, fmt.Sprintf("int(%s)", p.Name))
|
||||
argscall = append(argscall, fmt.Sprintf("%s int", p.Name))
|
||||
argsgc = append(argsgc, fmt.Sprintf("uintptr(%s)", p.Name))
|
||||
argsgccgo = append(argsgccgo, fmt.Sprintf("C.int(%s)", p.Name))
|
||||
}
|
||||
argN++
|
||||
}
|
||||
nargs := len(argsgc)
|
||||
|
||||
// COMMON function generation
|
||||
argscommonlist := strings.Join(argscommon, ", ")
|
||||
callcommon := fmt.Sprintf("call%s(%s)", sysname, argscommonlist)
|
||||
ret := []string{"_", "_"}
|
||||
body := ""
|
||||
doErrno := false
|
||||
for i := 0; i < len(out); i++ {
|
||||
p := parseParam(out[i])
|
||||
reg := ""
|
||||
if p.Name == "err" {
|
||||
reg = "e1"
|
||||
ret[1] = reg
|
||||
doErrno = true
|
||||
} else {
|
||||
reg = "r0"
|
||||
ret[0] = reg
|
||||
}
|
||||
if p.Type == "bool" {
|
||||
reg = fmt.Sprintf("%s != 0", reg)
|
||||
}
|
||||
if reg != "e1" {
|
||||
body += fmt.Sprintf("\t%s = %s(%s)\n", p.Name, p.Type, reg)
|
||||
}
|
||||
}
|
||||
if ret[0] == "_" && ret[1] == "_" {
|
||||
textcommon += fmt.Sprintf("\t%s\n", callcommon)
|
||||
} else {
|
||||
textcommon += fmt.Sprintf("\t%s, %s := %s\n", ret[0], ret[1], callcommon)
|
||||
}
|
||||
textcommon += body
|
||||
|
||||
if doErrno {
|
||||
textcommon += "\tif e1 != 0 {\n"
|
||||
textcommon += "\t\terr = errnoErr(e1)\n"
|
||||
textcommon += "\t}\n"
|
||||
}
|
||||
textcommon += "\treturn\n"
|
||||
textcommon += "}\n"
|
||||
|
||||
if onlyCommon {
|
||||
continue
|
||||
}
|
||||
|
||||
// CALL Prototype
|
||||
callProto := fmt.Sprintf("func call%s(%s) (r1 uintptr, e1 Errno) {\n", sysname, strings.Join(argscall, ", "))
|
||||
|
||||
// GC function generation
|
||||
asm := "syscall6"
|
||||
if nonblock != nil {
|
||||
asm = "rawSyscall6"
|
||||
}
|
||||
|
||||
if len(argsgc) <= 6 {
|
||||
for len(argsgc) < 6 {
|
||||
argsgc = append(argsgc, "0")
|
||||
}
|
||||
} else {
|
||||
fmt.Fprintf(os.Stderr, "%s: too many arguments to system call", funct)
|
||||
os.Exit(1)
|
||||
}
|
||||
argsgclist := strings.Join(argsgc, ", ")
|
||||
callgc := fmt.Sprintf("%s(uintptr(unsafe.Pointer(&%s)), %d, %s)", asm, sysvarname, nargs, argsgclist)
|
||||
|
||||
textgc += callProto
|
||||
textgc += fmt.Sprintf("\tr1, _, e1 = %s\n", callgc)
|
||||
textgc += "\treturn\n}\n"
|
||||
|
||||
// GCCGO function generation
|
||||
argsgccgolist := strings.Join(argsgccgo, ", ")
|
||||
callgccgo := fmt.Sprintf("C.%s(%s)", sysname, argsgccgolist)
|
||||
textgccgo += callProto
|
||||
textgccgo += fmt.Sprintf("\tr1 = uintptr(%s)\n", callgccgo)
|
||||
textgccgo += "\te1 = syscall.GetErrno()\n"
|
||||
textgccgo += "\treturn\n}\n"
|
||||
}
|
||||
if err := s.Err(); err != nil {
|
||||
fmt.Fprintf(os.Stderr, err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
file.Close()
|
||||
}
|
||||
imp := ""
|
||||
if pack != "unix" {
|
||||
imp = "import \"golang.org/x/sys/unix\"\n"
|
||||
|
||||
}
|
||||
|
||||
// Print zsyscall_aix_ppc64.go
|
||||
err := ioutil.WriteFile("zsyscall_aix_ppc64.go",
|
||||
[]byte(fmt.Sprintf(srcTemplate1, cmdLine(), buildTags(), pack, imp, textcommon)),
|
||||
0644)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Print zsyscall_aix_ppc64_gc.go
|
||||
vardecls := "\t" + strings.Join(vars, ",\n\t")
|
||||
vardecls += " syscallFunc"
|
||||
err = ioutil.WriteFile("zsyscall_aix_ppc64_gc.go",
|
||||
[]byte(fmt.Sprintf(srcTemplate2, cmdLine(), buildTags(), pack, imp, dynimports, linknames, vardecls, textgc)),
|
||||
0644)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Print zsyscall_aix_ppc64_gccgo.go
|
||||
err = ioutil.WriteFile("zsyscall_aix_ppc64_gccgo.go",
|
||||
[]byte(fmt.Sprintf(srcTemplate3, cmdLine(), buildTags(), pack, cExtern, imp, textgccgo)),
|
||||
0644)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
const srcTemplate1 = `// %s
|
||||
// Code generated by the command above; see README.md. DO NOT EDIT.
|
||||
|
||||
// +build %s
|
||||
|
||||
package %s
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
|
||||
%s
|
||||
|
||||
%s
|
||||
`
|
||||
const srcTemplate2 = `// %s
|
||||
// Code generated by the command above; see README.md. DO NOT EDIT.
|
||||
|
||||
// +build %s
|
||||
// +build !gccgo
|
||||
|
||||
package %s
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
)
|
||||
%s
|
||||
%s
|
||||
%s
|
||||
type syscallFunc uintptr
|
||||
|
||||
var (
|
||||
%s
|
||||
)
|
||||
|
||||
// Implemented in runtime/syscall_aix.go.
|
||||
func rawSyscall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno)
|
||||
func syscall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno)
|
||||
|
||||
%s
|
||||
`
|
||||
const srcTemplate3 = `// %s
|
||||
// Code generated by the command above; see README.md. DO NOT EDIT.
|
||||
|
||||
// +build %s
|
||||
// +build gccgo
|
||||
|
||||
package %s
|
||||
|
||||
%s
|
||||
*/
|
||||
import "C"
|
||||
import (
|
||||
"syscall"
|
||||
)
|
||||
|
||||
|
||||
%s
|
||||
|
||||
%s
|
||||
`
|
||||
|
|
@ -1,335 +0,0 @@
|
|||
// Copyright 2019 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
/*
|
||||
This program reads a file containing function prototypes
|
||||
(like syscall_solaris.go) and generates system call bodies.
|
||||
The prototypes are marked by lines beginning with "//sys"
|
||||
and read like func declarations if //sys is replaced by func, but:
|
||||
* The parameter lists must give a name for each argument.
|
||||
This includes return parameters.
|
||||
* The parameter lists must give a type for each argument:
|
||||
the (x, y, z int) shorthand is not allowed.
|
||||
* If the return parameter is an error number, it must be named err.
|
||||
* If go func name needs to be different than its libc name,
|
||||
* or the function is not in libc, name could be specified
|
||||
* at the end, after "=" sign, like
|
||||
//sys getsockopt(s int, level int, name int, val uintptr, vallen *_Socklen) (err error) = libsocket.getsockopt
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var (
|
||||
b32 = flag.Bool("b32", false, "32bit big-endian")
|
||||
l32 = flag.Bool("l32", false, "32bit little-endian")
|
||||
tags = flag.String("tags", "", "build tags")
|
||||
)
|
||||
|
||||
// cmdLine returns this programs's commandline arguments
|
||||
func cmdLine() string {
|
||||
return "go run mksyscall_solaris.go " + strings.Join(os.Args[1:], " ")
|
||||
}
|
||||
|
||||
// buildTags returns build tags
|
||||
func buildTags() string {
|
||||
return *tags
|
||||
}
|
||||
|
||||
// Param is function parameter
|
||||
type Param struct {
|
||||
Name string
|
||||
Type string
|
||||
}
|
||||
|
||||
// usage prints the program usage
|
||||
func usage() {
|
||||
fmt.Fprintf(os.Stderr, "usage: go run mksyscall_solaris.go [-b32 | -l32] [-tags x,y] [file ...]\n")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// parseParamList parses parameter list and returns a slice of parameters
|
||||
func parseParamList(list string) []string {
|
||||
list = strings.TrimSpace(list)
|
||||
if list == "" {
|
||||
return []string{}
|
||||
}
|
||||
return regexp.MustCompile(`\s*,\s*`).Split(list, -1)
|
||||
}
|
||||
|
||||
// parseParam splits a parameter into name and type
|
||||
func parseParam(p string) Param {
|
||||
ps := regexp.MustCompile(`^(\S*) (\S*)$`).FindStringSubmatch(p)
|
||||
if ps == nil {
|
||||
fmt.Fprintf(os.Stderr, "malformed parameter: %s\n", p)
|
||||
os.Exit(1)
|
||||
}
|
||||
return Param{ps[1], ps[2]}
|
||||
}
|
||||
|
||||
func main() {
|
||||
flag.Usage = usage
|
||||
flag.Parse()
|
||||
if len(flag.Args()) <= 0 {
|
||||
fmt.Fprintf(os.Stderr, "no files to parse provided\n")
|
||||
usage()
|
||||
}
|
||||
|
||||
endianness := ""
|
||||
if *b32 {
|
||||
endianness = "big-endian"
|
||||
} else if *l32 {
|
||||
endianness = "little-endian"
|
||||
}
|
||||
|
||||
pack := ""
|
||||
text := ""
|
||||
dynimports := ""
|
||||
linknames := ""
|
||||
var vars []string
|
||||
for _, path := range flag.Args() {
|
||||
file, err := os.Open(path)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
s := bufio.NewScanner(file)
|
||||
for s.Scan() {
|
||||
t := s.Text()
|
||||
t = strings.TrimSpace(t)
|
||||
t = regexp.MustCompile(`\s+`).ReplaceAllString(t, ` `)
|
||||
if p := regexp.MustCompile(`^package (\S+)$`).FindStringSubmatch(t); p != nil && pack == "" {
|
||||
pack = p[1]
|
||||
}
|
||||
nonblock := regexp.MustCompile(`^\/\/sysnb `).FindStringSubmatch(t)
|
||||
if regexp.MustCompile(`^\/\/sys `).FindStringSubmatch(t) == nil && nonblock == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
// Line must be of the form
|
||||
// func Open(path string, mode int, perm int) (fd int, err error)
|
||||
// Split into name, in params, out params.
|
||||
f := regexp.MustCompile(`^\/\/sys(nb)? (\w+)\(([^()]*)\)\s*(?:\(([^()]+)\))?\s*(?:=\s*(?:(\w*)\.)?(\w*))?$`).FindStringSubmatch(t)
|
||||
if f == nil {
|
||||
fmt.Fprintf(os.Stderr, "%s:%s\nmalformed //sys declaration\n", path, t)
|
||||
os.Exit(1)
|
||||
}
|
||||
funct, inps, outps, modname, sysname := f[2], f[3], f[4], f[5], f[6]
|
||||
|
||||
// Split argument lists on comma.
|
||||
in := parseParamList(inps)
|
||||
out := parseParamList(outps)
|
||||
|
||||
inps = strings.Join(in, ", ")
|
||||
outps = strings.Join(out, ", ")
|
||||
|
||||
// Try in vain to keep people from editing this file.
|
||||
// The theory is that they jump into the middle of the file
|
||||
// without reading the header.
|
||||
text += "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n"
|
||||
|
||||
// So file name.
|
||||
if modname == "" {
|
||||
modname = "libc"
|
||||
}
|
||||
|
||||
// System call name.
|
||||
if sysname == "" {
|
||||
sysname = funct
|
||||
}
|
||||
|
||||
// System call pointer variable name.
|
||||
sysvarname := fmt.Sprintf("proc%s", sysname)
|
||||
|
||||
strconvfunc := "BytePtrFromString"
|
||||
strconvtype := "*byte"
|
||||
|
||||
sysname = strings.ToLower(sysname) // All libc functions are lowercase.
|
||||
|
||||
// Runtime import of function to allow cross-platform builds.
|
||||
dynimports += fmt.Sprintf("//go:cgo_import_dynamic libc_%s %s \"%s.so\"\n", sysname, sysname, modname)
|
||||
// Link symbol to proc address variable.
|
||||
linknames += fmt.Sprintf("//go:linkname %s libc_%s\n", sysvarname, sysname)
|
||||
// Library proc address variable.
|
||||
vars = append(vars, sysvarname)
|
||||
|
||||
// Go function header.
|
||||
outlist := strings.Join(out, ", ")
|
||||
if outlist != "" {
|
||||
outlist = fmt.Sprintf(" (%s)", outlist)
|
||||
}
|
||||
if text != "" {
|
||||
text += "\n"
|
||||
}
|
||||
text += fmt.Sprintf("func %s(%s)%s {\n", funct, strings.Join(in, ", "), outlist)
|
||||
|
||||
// Check if err return available
|
||||
errvar := ""
|
||||
for _, param := range out {
|
||||
p := parseParam(param)
|
||||
if p.Type == "error" {
|
||||
errvar = p.Name
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
// Prepare arguments to Syscall.
|
||||
var args []string
|
||||
n := 0
|
||||
for _, param := range in {
|
||||
p := parseParam(param)
|
||||
if regexp.MustCompile(`^\*`).FindStringSubmatch(p.Type) != nil {
|
||||
args = append(args, "uintptr(unsafe.Pointer("+p.Name+"))")
|
||||
} else if p.Type == "string" && errvar != "" {
|
||||
text += fmt.Sprintf("\tvar _p%d %s\n", n, strconvtype)
|
||||
text += fmt.Sprintf("\t_p%d, %s = %s(%s)\n", n, errvar, strconvfunc, p.Name)
|
||||
text += fmt.Sprintf("\tif %s != nil {\n\t\treturn\n\t}\n", errvar)
|
||||
args = append(args, fmt.Sprintf("uintptr(unsafe.Pointer(_p%d))", n))
|
||||
n++
|
||||
} else if p.Type == "string" {
|
||||
fmt.Fprintf(os.Stderr, path+":"+funct+" uses string arguments, but has no error return\n")
|
||||
text += fmt.Sprintf("\tvar _p%d %s\n", n, strconvtype)
|
||||
text += fmt.Sprintf("\t_p%d, _ = %s(%s)\n", n, strconvfunc, p.Name)
|
||||
args = append(args, fmt.Sprintf("uintptr(unsafe.Pointer(_p%d))", n))
|
||||
n++
|
||||
} else if s := regexp.MustCompile(`^\[\](.*)`).FindStringSubmatch(p.Type); s != nil {
|
||||
// Convert slice into pointer, length.
|
||||
// Have to be careful not to take address of &a[0] if len == 0:
|
||||
// pass nil in that case.
|
||||
text += fmt.Sprintf("\tvar _p%d *%s\n", n, s[1])
|
||||
text += fmt.Sprintf("\tif len(%s) > 0 {\n\t\t_p%d = &%s[0]\n\t}\n", p.Name, n, p.Name)
|
||||
args = append(args, fmt.Sprintf("uintptr(unsafe.Pointer(_p%d))", n), fmt.Sprintf("uintptr(len(%s))", p.Name))
|
||||
n++
|
||||
} else if p.Type == "int64" && endianness != "" {
|
||||
if endianness == "big-endian" {
|
||||
args = append(args, fmt.Sprintf("uintptr(%s>>32)", p.Name), fmt.Sprintf("uintptr(%s)", p.Name))
|
||||
} else {
|
||||
args = append(args, fmt.Sprintf("uintptr(%s)", p.Name), fmt.Sprintf("uintptr(%s>>32)", p.Name))
|
||||
}
|
||||
} else if p.Type == "bool" {
|
||||
text += fmt.Sprintf("\tvar _p%d uint32\n", n)
|
||||
text += fmt.Sprintf("\tif %s {\n\t\t_p%d = 1\n\t} else {\n\t\t_p%d = 0\n\t}\n", p.Name, n, n)
|
||||
args = append(args, fmt.Sprintf("uintptr(_p%d)", n))
|
||||
n++
|
||||
} else {
|
||||
args = append(args, fmt.Sprintf("uintptr(%s)", p.Name))
|
||||
}
|
||||
}
|
||||
nargs := len(args)
|
||||
|
||||
// Determine which form to use; pad args with zeros.
|
||||
asm := "sysvicall6"
|
||||
if nonblock != nil {
|
||||
asm = "rawSysvicall6"
|
||||
}
|
||||
if len(args) <= 6 {
|
||||
for len(args) < 6 {
|
||||
args = append(args, "0")
|
||||
}
|
||||
} else {
|
||||
fmt.Fprintf(os.Stderr, "%s: too many arguments to system call\n", path)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Actual call.
|
||||
arglist := strings.Join(args, ", ")
|
||||
call := fmt.Sprintf("%s(uintptr(unsafe.Pointer(&%s)), %d, %s)", asm, sysvarname, nargs, arglist)
|
||||
|
||||
// Assign return values.
|
||||
body := ""
|
||||
ret := []string{"_", "_", "_"}
|
||||
doErrno := false
|
||||
for i := 0; i < len(out); i++ {
|
||||
p := parseParam(out[i])
|
||||
reg := ""
|
||||
if p.Name == "err" {
|
||||
reg = "e1"
|
||||
ret[2] = reg
|
||||
doErrno = true
|
||||
} else {
|
||||
reg = fmt.Sprintf("r%d", i)
|
||||
ret[i] = reg
|
||||
}
|
||||
if p.Type == "bool" {
|
||||
reg = fmt.Sprintf("%d != 0", reg)
|
||||
}
|
||||
if p.Type == "int64" && endianness != "" {
|
||||
// 64-bit number in r1:r0 or r0:r1.
|
||||
if i+2 > len(out) {
|
||||
fmt.Fprintf(os.Stderr, "%s: not enough registers for int64 return\n", path)
|
||||
os.Exit(1)
|
||||
}
|
||||
if endianness == "big-endian" {
|
||||
reg = fmt.Sprintf("int64(r%d)<<32 | int64(r%d)", i, i+1)
|
||||
} else {
|
||||
reg = fmt.Sprintf("int64(r%d)<<32 | int64(r%d)", i+1, i)
|
||||
}
|
||||
ret[i] = fmt.Sprintf("r%d", i)
|
||||
ret[i+1] = fmt.Sprintf("r%d", i+1)
|
||||
}
|
||||
if reg != "e1" {
|
||||
body += fmt.Sprintf("\t%s = %s(%s)\n", p.Name, p.Type, reg)
|
||||
}
|
||||
}
|
||||
if ret[0] == "_" && ret[1] == "_" && ret[2] == "_" {
|
||||
text += fmt.Sprintf("\t%s\n", call)
|
||||
} else {
|
||||
text += fmt.Sprintf("\t%s, %s, %s := %s\n", ret[0], ret[1], ret[2], call)
|
||||
}
|
||||
text += body
|
||||
|
||||
if doErrno {
|
||||
text += "\tif e1 != 0 {\n"
|
||||
text += "\t\terr = e1\n"
|
||||
text += "\t}\n"
|
||||
}
|
||||
text += "\treturn\n"
|
||||
text += "}\n"
|
||||
}
|
||||
if err := s.Err(); err != nil {
|
||||
fmt.Fprintf(os.Stderr, err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
file.Close()
|
||||
}
|
||||
imp := ""
|
||||
if pack != "unix" {
|
||||
imp = "import \"golang.org/x/sys/unix\"\n"
|
||||
|
||||
}
|
||||
vardecls := "\t" + strings.Join(vars, ",\n\t")
|
||||
vardecls += " syscallFunc"
|
||||
fmt.Printf(srcTemplate, cmdLine(), buildTags(), pack, imp, dynimports, linknames, vardecls, text)
|
||||
}
|
||||
|
||||
const srcTemplate = `// %s
|
||||
// Code generated by the command above; see README.md. DO NOT EDIT.
|
||||
|
||||
// +build %s
|
||||
|
||||
package %s
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
%s
|
||||
%s
|
||||
%s
|
||||
var (
|
||||
%s
|
||||
)
|
||||
|
||||
%s
|
||||
`
|
||||
|
|
@ -1,190 +0,0 @@
|
|||
// Copyright 2018 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
// Generate system call table for DragonFly, NetBSD,
|
||||
// FreeBSD, OpenBSD or Darwin from master list
|
||||
// (for example, /usr/src/sys/kern/syscalls.master or
|
||||
// sys/syscall.h).
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var (
|
||||
goos, goarch string
|
||||
)
|
||||
|
||||
// cmdLine returns this programs's commandline arguments
|
||||
func cmdLine() string {
|
||||
return "go run mksysnum.go " + strings.Join(os.Args[1:], " ")
|
||||
}
|
||||
|
||||
// buildTags returns build tags
|
||||
func buildTags() string {
|
||||
return fmt.Sprintf("%s,%s", goarch, goos)
|
||||
}
|
||||
|
||||
func checkErr(err error) {
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "%v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
// source string and substring slice for regexp
|
||||
type re struct {
|
||||
str string // source string
|
||||
sub []string // matched sub-string
|
||||
}
|
||||
|
||||
// Match performs regular expression match
|
||||
func (r *re) Match(exp string) bool {
|
||||
r.sub = regexp.MustCompile(exp).FindStringSubmatch(r.str)
|
||||
if r.sub != nil {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// fetchFile fetches a text file from URL
|
||||
func fetchFile(URL string) io.Reader {
|
||||
resp, err := http.Get(URL)
|
||||
checkErr(err)
|
||||
defer resp.Body.Close()
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
checkErr(err)
|
||||
return strings.NewReader(string(body))
|
||||
}
|
||||
|
||||
// readFile reads a text file from path
|
||||
func readFile(path string) io.Reader {
|
||||
file, err := os.Open(os.Args[1])
|
||||
checkErr(err)
|
||||
return file
|
||||
}
|
||||
|
||||
func format(name, num, proto string) string {
|
||||
name = strings.ToUpper(name)
|
||||
// There are multiple entries for enosys and nosys, so comment them out.
|
||||
nm := re{str: name}
|
||||
if nm.Match(`^SYS_E?NOSYS$`) {
|
||||
name = fmt.Sprintf("// %s", name)
|
||||
}
|
||||
if name == `SYS_SYS_EXIT` {
|
||||
name = `SYS_EXIT`
|
||||
}
|
||||
return fmt.Sprintf(" %s = %s; // %s\n", name, num, proto)
|
||||
}
|
||||
|
||||
func main() {
|
||||
// Get the OS (using GOOS_TARGET if it exist)
|
||||
goos = os.Getenv("GOOS_TARGET")
|
||||
if goos == "" {
|
||||
goos = os.Getenv("GOOS")
|
||||
}
|
||||
// Get the architecture (using GOARCH_TARGET if it exists)
|
||||
goarch = os.Getenv("GOARCH_TARGET")
|
||||
if goarch == "" {
|
||||
goarch = os.Getenv("GOARCH")
|
||||
}
|
||||
// Check if GOOS and GOARCH environment variables are defined
|
||||
if goarch == "" || goos == "" {
|
||||
fmt.Fprintf(os.Stderr, "GOARCH or GOOS not defined in environment\n")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
file := strings.TrimSpace(os.Args[1])
|
||||
var syscalls io.Reader
|
||||
if strings.HasPrefix(file, "https://") || strings.HasPrefix(file, "http://") {
|
||||
// Download syscalls.master file
|
||||
syscalls = fetchFile(file)
|
||||
} else {
|
||||
syscalls = readFile(file)
|
||||
}
|
||||
|
||||
var text, line string
|
||||
s := bufio.NewScanner(syscalls)
|
||||
for s.Scan() {
|
||||
t := re{str: line}
|
||||
if t.Match(`^(.*)\\$`) {
|
||||
// Handle continuation
|
||||
line = t.sub[1]
|
||||
line += strings.TrimLeft(s.Text(), " \t")
|
||||
} else {
|
||||
// New line
|
||||
line = s.Text()
|
||||
}
|
||||
t = re{str: line}
|
||||
if t.Match(`\\$`) {
|
||||
continue
|
||||
}
|
||||
t = re{str: line}
|
||||
|
||||
switch goos {
|
||||
case "dragonfly":
|
||||
if t.Match(`^([0-9]+)\s+STD\s+({ \S+\s+(\w+).*)$`) {
|
||||
num, proto := t.sub[1], t.sub[2]
|
||||
name := fmt.Sprintf("SYS_%s", t.sub[3])
|
||||
text += format(name, num, proto)
|
||||
}
|
||||
case "freebsd":
|
||||
if t.Match(`^([0-9]+)\s+\S+\s+(?:NO)?STD\s+({ \S+\s+(\w+).*)$`) {
|
||||
num, proto := t.sub[1], t.sub[2]
|
||||
name := fmt.Sprintf("SYS_%s", t.sub[3])
|
||||
text += format(name, num, proto)
|
||||
}
|
||||
case "openbsd":
|
||||
if t.Match(`^([0-9]+)\s+STD\s+(NOLOCK\s+)?({ \S+\s+\*?(\w+).*)$`) {
|
||||
num, proto, name := t.sub[1], t.sub[3], t.sub[4]
|
||||
text += format(name, num, proto)
|
||||
}
|
||||
case "netbsd":
|
||||
if t.Match(`^([0-9]+)\s+((STD)|(NOERR))\s+(RUMP\s+)?({\s+\S+\s*\*?\s*\|(\S+)\|(\S*)\|(\w+).*\s+})(\s+(\S+))?$`) {
|
||||
num, proto, compat := t.sub[1], t.sub[6], t.sub[8]
|
||||
name := t.sub[7] + "_" + t.sub[9]
|
||||
if t.sub[11] != "" {
|
||||
name = t.sub[7] + "_" + t.sub[11]
|
||||
}
|
||||
name = strings.ToUpper(name)
|
||||
if compat == "" || compat == "13" || compat == "30" || compat == "50" {
|
||||
text += fmt.Sprintf(" %s = %s; // %s\n", name, num, proto)
|
||||
}
|
||||
}
|
||||
case "darwin":
|
||||
if t.Match(`^#define\s+SYS_(\w+)\s+([0-9]+)`) {
|
||||
name, num := t.sub[1], t.sub[2]
|
||||
name = strings.ToUpper(name)
|
||||
text += fmt.Sprintf(" SYS_%s = %s;\n", name, num)
|
||||
}
|
||||
default:
|
||||
fmt.Fprintf(os.Stderr, "unrecognized GOOS=%s\n", goos)
|
||||
os.Exit(1)
|
||||
|
||||
}
|
||||
}
|
||||
err := s.Err()
|
||||
checkErr(err)
|
||||
|
||||
fmt.Printf(template, cmdLine(), buildTags(), text)
|
||||
}
|
||||
|
||||
const template = `// %s
|
||||
// Code generated by the command above; see README.md. DO NOT EDIT.
|
||||
|
||||
// +build %s
|
||||
|
||||
package unix
|
||||
|
||||
const(
|
||||
%s)`
|
||||
|
|
@ -1,236 +0,0 @@
|
|||
// Copyright 2018 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
// +build aix
|
||||
|
||||
/*
|
||||
Input to cgo -godefs. See also mkerrors.sh and mkall.sh
|
||||
*/
|
||||
|
||||
// +godefs map struct_in_addr [4]byte /* in_addr */
|
||||
// +godefs map struct_in6_addr [16]byte /* in6_addr */
|
||||
|
||||
package unix
|
||||
|
||||
/*
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/limits.h>
|
||||
#include <sys/un.h>
|
||||
#include <utime.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <sys/poll.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/statfs.h>
|
||||
#include <sys/termio.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include <termios.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <net/if_dl.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/icmp6.h>
|
||||
|
||||
|
||||
#include <dirent.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
enum {
|
||||
sizeofPtr = sizeof(void*),
|
||||
};
|
||||
|
||||
union sockaddr_all {
|
||||
struct sockaddr s1; // this one gets used for fields
|
||||
struct sockaddr_in s2; // these pad it out
|
||||
struct sockaddr_in6 s3;
|
||||
struct sockaddr_un s4;
|
||||
struct sockaddr_dl s5;
|
||||
};
|
||||
|
||||
struct sockaddr_any {
|
||||
struct sockaddr addr;
|
||||
char pad[sizeof(union sockaddr_all) - sizeof(struct sockaddr)];
|
||||
};
|
||||
|
||||
*/
|
||||
import "C"
|
||||
|
||||
// Machine characteristics
|
||||
|
||||
const (
|
||||
SizeofPtr = C.sizeofPtr
|
||||
SizeofShort = C.sizeof_short
|
||||
SizeofInt = C.sizeof_int
|
||||
SizeofLong = C.sizeof_long
|
||||
SizeofLongLong = C.sizeof_longlong
|
||||
PathMax = C.PATH_MAX
|
||||
)
|
||||
|
||||
// Basic types
|
||||
|
||||
type (
|
||||
_C_short C.short
|
||||
_C_int C.int
|
||||
_C_long C.long
|
||||
_C_long_long C.longlong
|
||||
)
|
||||
|
||||
type off64 C.off64_t
|
||||
type off C.off_t
|
||||
type Mode_t C.mode_t
|
||||
|
||||
// Time
|
||||
|
||||
type Timespec C.struct_timespec
|
||||
|
||||
type StTimespec C.struct_st_timespec
|
||||
|
||||
type Timeval C.struct_timeval
|
||||
|
||||
type Timeval32 C.struct_timeval32
|
||||
|
||||
type Timex C.struct_timex
|
||||
|
||||
type Time_t C.time_t
|
||||
|
||||
type Tms C.struct_tms
|
||||
|
||||
type Utimbuf C.struct_utimbuf
|
||||
|
||||
type Timezone C.struct_timezone
|
||||
|
||||
// Processes
|
||||
|
||||
type Rusage C.struct_rusage
|
||||
|
||||
type Rlimit C.struct_rlimit64
|
||||
|
||||
type Pid_t C.pid_t
|
||||
|
||||
type _Gid_t C.gid_t
|
||||
|
||||
type dev_t C.dev_t
|
||||
|
||||
// Files
|
||||
|
||||
type Stat_t C.struct_stat
|
||||
|
||||
type StatxTimestamp C.struct_statx_timestamp
|
||||
|
||||
type Statx_t C.struct_statx
|
||||
|
||||
type Dirent C.struct_dirent
|
||||
|
||||
// Sockets
|
||||
|
||||
type RawSockaddrInet4 C.struct_sockaddr_in
|
||||
|
||||
type RawSockaddrInet6 C.struct_sockaddr_in6
|
||||
|
||||
type RawSockaddrUnix C.struct_sockaddr_un
|
||||
|
||||
type RawSockaddr C.struct_sockaddr
|
||||
|
||||
type RawSockaddrAny C.struct_sockaddr_any
|
||||
|
||||
type _Socklen C.socklen_t
|
||||
|
||||
type Cmsghdr C.struct_cmsghdr
|
||||
|
||||
type ICMPv6Filter C.struct_icmp6_filter
|
||||
|
||||
type Iovec C.struct_iovec
|
||||
|
||||
type IPMreq C.struct_ip_mreq
|
||||
|
||||
type IPv6Mreq C.struct_ipv6_mreq
|
||||
|
||||
type IPv6MTUInfo C.struct_ip6_mtuinfo
|
||||
|
||||
type Linger C.struct_linger
|
||||
|
||||
type Msghdr C.struct_msghdr
|
||||
|
||||
const (
|
||||
SizeofSockaddrInet4 = C.sizeof_struct_sockaddr_in
|
||||
SizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
|
||||
SizeofSockaddrAny = C.sizeof_struct_sockaddr_any
|
||||
SizeofSockaddrUnix = C.sizeof_struct_sockaddr_un
|
||||
SizeofLinger = C.sizeof_struct_linger
|
||||
SizeofIPMreq = C.sizeof_struct_ip_mreq
|
||||
SizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq
|
||||
SizeofIPv6MTUInfo = C.sizeof_struct_ip6_mtuinfo
|
||||
SizeofMsghdr = C.sizeof_struct_msghdr
|
||||
SizeofCmsghdr = C.sizeof_struct_cmsghdr
|
||||
SizeofICMPv6Filter = C.sizeof_struct_icmp6_filter
|
||||
)
|
||||
|
||||
// Routing and interface messages
|
||||
|
||||
const (
|
||||
SizeofIfMsghdr = C.sizeof_struct_if_msghdr
|
||||
)
|
||||
|
||||
type IfMsgHdr C.struct_if_msghdr
|
||||
|
||||
// Misc
|
||||
|
||||
type FdSet C.fd_set
|
||||
|
||||
type Utsname C.struct_utsname
|
||||
|
||||
type Ustat_t C.struct_ustat
|
||||
|
||||
type Sigset_t C.sigset_t
|
||||
|
||||
const (
|
||||
AT_FDCWD = C.AT_FDCWD
|
||||
AT_REMOVEDIR = C.AT_REMOVEDIR
|
||||
AT_SYMLINK_NOFOLLOW = C.AT_SYMLINK_NOFOLLOW
|
||||
)
|
||||
|
||||
// Terminal handling
|
||||
|
||||
type Termios C.struct_termios
|
||||
|
||||
type Termio C.struct_termio
|
||||
|
||||
type Winsize C.struct_winsize
|
||||
|
||||
//poll
|
||||
|
||||
type PollFd struct {
|
||||
Fd int32
|
||||
Events uint16
|
||||
Revents uint16
|
||||
}
|
||||
|
||||
const (
|
||||
POLLERR = C.POLLERR
|
||||
POLLHUP = C.POLLHUP
|
||||
POLLIN = C.POLLIN
|
||||
POLLNVAL = C.POLLNVAL
|
||||
POLLOUT = C.POLLOUT
|
||||
POLLPRI = C.POLLPRI
|
||||
POLLRDBAND = C.POLLRDBAND
|
||||
POLLRDNORM = C.POLLRDNORM
|
||||
POLLWRBAND = C.POLLWRBAND
|
||||
POLLWRNORM = C.POLLWRNORM
|
||||
)
|
||||
|
||||
//flock_t
|
||||
|
||||
type Flock_t C.struct_flock64
|
||||
|
||||
// Statfs
|
||||
|
||||
type Fsid_t C.struct_fsid_t
|
||||
type Fsid64_t C.struct_fsid64_t
|
||||
|
||||
type Statfs_t C.struct_statfs
|
||||
|
||||
const RNDGETENTCNT = 0x80045200
|
||||
|
|
@ -1,283 +0,0 @@
|
|||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
/*
|
||||
Input to cgo -godefs. See README.md
|
||||
*/
|
||||
|
||||
// +godefs map struct_in_addr [4]byte /* in_addr */
|
||||
// +godefs map struct_in6_addr [16]byte /* in6_addr */
|
||||
|
||||
package unix
|
||||
|
||||
/*
|
||||
#define __DARWIN_UNIX03 0
|
||||
#define KERNEL
|
||||
#define _DARWIN_USE_64_BIT_INODE
|
||||
#include <dirent.h>
|
||||
#include <fcntl.h>
|
||||
#include <poll.h>
|
||||
#include <signal.h>
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
#include <mach/mach.h>
|
||||
#include <mach/message.h>
|
||||
#include <sys/event.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/ptrace.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/select.h>
|
||||
#include <sys/signal.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/uio.h>
|
||||
#include <sys/un.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <sys/wait.h>
|
||||
#include <net/bpf.h>
|
||||
#include <net/if.h>
|
||||
#include <net/if_dl.h>
|
||||
#include <net/if_var.h>
|
||||
#include <net/route.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/icmp6.h>
|
||||
#include <netinet/tcp.h>
|
||||
|
||||
enum {
|
||||
sizeofPtr = sizeof(void*),
|
||||
};
|
||||
|
||||
union sockaddr_all {
|
||||
struct sockaddr s1; // this one gets used for fields
|
||||
struct sockaddr_in s2; // these pad it out
|
||||
struct sockaddr_in6 s3;
|
||||
struct sockaddr_un s4;
|
||||
struct sockaddr_dl s5;
|
||||
};
|
||||
|
||||
struct sockaddr_any {
|
||||
struct sockaddr addr;
|
||||
char pad[sizeof(union sockaddr_all) - sizeof(struct sockaddr)];
|
||||
};
|
||||
|
||||
*/
|
||||
import "C"
|
||||
|
||||
// Machine characteristics
|
||||
|
||||
const (
|
||||
SizeofPtr = C.sizeofPtr
|
||||
SizeofShort = C.sizeof_short
|
||||
SizeofInt = C.sizeof_int
|
||||
SizeofLong = C.sizeof_long
|
||||
SizeofLongLong = C.sizeof_longlong
|
||||
)
|
||||
|
||||
// Basic types
|
||||
|
||||
type (
|
||||
_C_short C.short
|
||||
_C_int C.int
|
||||
_C_long C.long
|
||||
_C_long_long C.longlong
|
||||
)
|
||||
|
||||
// Time
|
||||
|
||||
type Timespec C.struct_timespec
|
||||
|
||||
type Timeval C.struct_timeval
|
||||
|
||||
type Timeval32 C.struct_timeval32
|
||||
|
||||
// Processes
|
||||
|
||||
type Rusage C.struct_rusage
|
||||
|
||||
type Rlimit C.struct_rlimit
|
||||
|
||||
type _Gid_t C.gid_t
|
||||
|
||||
// Files
|
||||
|
||||
type Stat_t C.struct_stat64
|
||||
|
||||
type Statfs_t C.struct_statfs64
|
||||
|
||||
type Flock_t C.struct_flock
|
||||
|
||||
type Fstore_t C.struct_fstore
|
||||
|
||||
type Radvisory_t C.struct_radvisory
|
||||
|
||||
type Fbootstraptransfer_t C.struct_fbootstraptransfer
|
||||
|
||||
type Log2phys_t C.struct_log2phys
|
||||
|
||||
type Fsid C.struct_fsid
|
||||
|
||||
type Dirent C.struct_dirent
|
||||
|
||||
// Sockets
|
||||
|
||||
type RawSockaddrInet4 C.struct_sockaddr_in
|
||||
|
||||
type RawSockaddrInet6 C.struct_sockaddr_in6
|
||||
|
||||
type RawSockaddrUnix C.struct_sockaddr_un
|
||||
|
||||
type RawSockaddrDatalink C.struct_sockaddr_dl
|
||||
|
||||
type RawSockaddr C.struct_sockaddr
|
||||
|
||||
type RawSockaddrAny C.struct_sockaddr_any
|
||||
|
||||
type _Socklen C.socklen_t
|
||||
|
||||
type Linger C.struct_linger
|
||||
|
||||
type Iovec C.struct_iovec
|
||||
|
||||
type IPMreq C.struct_ip_mreq
|
||||
|
||||
type IPv6Mreq C.struct_ipv6_mreq
|
||||
|
||||
type Msghdr C.struct_msghdr
|
||||
|
||||
type Cmsghdr C.struct_cmsghdr
|
||||
|
||||
type Inet4Pktinfo C.struct_in_pktinfo
|
||||
|
||||
type Inet6Pktinfo C.struct_in6_pktinfo
|
||||
|
||||
type IPv6MTUInfo C.struct_ip6_mtuinfo
|
||||
|
||||
type ICMPv6Filter C.struct_icmp6_filter
|
||||
|
||||
const (
|
||||
SizeofSockaddrInet4 = C.sizeof_struct_sockaddr_in
|
||||
SizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
|
||||
SizeofSockaddrAny = C.sizeof_struct_sockaddr_any
|
||||
SizeofSockaddrUnix = C.sizeof_struct_sockaddr_un
|
||||
SizeofSockaddrDatalink = C.sizeof_struct_sockaddr_dl
|
||||
SizeofLinger = C.sizeof_struct_linger
|
||||
SizeofIPMreq = C.sizeof_struct_ip_mreq
|
||||
SizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq
|
||||
SizeofMsghdr = C.sizeof_struct_msghdr
|
||||
SizeofCmsghdr = C.sizeof_struct_cmsghdr
|
||||
SizeofInet4Pktinfo = C.sizeof_struct_in_pktinfo
|
||||
SizeofInet6Pktinfo = C.sizeof_struct_in6_pktinfo
|
||||
SizeofIPv6MTUInfo = C.sizeof_struct_ip6_mtuinfo
|
||||
SizeofICMPv6Filter = C.sizeof_struct_icmp6_filter
|
||||
)
|
||||
|
||||
// Ptrace requests
|
||||
|
||||
const (
|
||||
PTRACE_TRACEME = C.PT_TRACE_ME
|
||||
PTRACE_CONT = C.PT_CONTINUE
|
||||
PTRACE_KILL = C.PT_KILL
|
||||
)
|
||||
|
||||
// Events (kqueue, kevent)
|
||||
|
||||
type Kevent_t C.struct_kevent
|
||||
|
||||
// Select
|
||||
|
||||
type FdSet C.fd_set
|
||||
|
||||
// Routing and interface messages
|
||||
|
||||
const (
|
||||
SizeofIfMsghdr = C.sizeof_struct_if_msghdr
|
||||
SizeofIfData = C.sizeof_struct_if_data
|
||||
SizeofIfaMsghdr = C.sizeof_struct_ifa_msghdr
|
||||
SizeofIfmaMsghdr = C.sizeof_struct_ifma_msghdr
|
||||
SizeofIfmaMsghdr2 = C.sizeof_struct_ifma_msghdr2
|
||||
SizeofRtMsghdr = C.sizeof_struct_rt_msghdr
|
||||
SizeofRtMetrics = C.sizeof_struct_rt_metrics
|
||||
)
|
||||
|
||||
type IfMsghdr C.struct_if_msghdr
|
||||
|
||||
type IfData C.struct_if_data
|
||||
|
||||
type IfaMsghdr C.struct_ifa_msghdr
|
||||
|
||||
type IfmaMsghdr C.struct_ifma_msghdr
|
||||
|
||||
type IfmaMsghdr2 C.struct_ifma_msghdr2
|
||||
|
||||
type RtMsghdr C.struct_rt_msghdr
|
||||
|
||||
type RtMetrics C.struct_rt_metrics
|
||||
|
||||
// Berkeley packet filter
|
||||
|
||||
const (
|
||||
SizeofBpfVersion = C.sizeof_struct_bpf_version
|
||||
SizeofBpfStat = C.sizeof_struct_bpf_stat
|
||||
SizeofBpfProgram = C.sizeof_struct_bpf_program
|
||||
SizeofBpfInsn = C.sizeof_struct_bpf_insn
|
||||
SizeofBpfHdr = C.sizeof_struct_bpf_hdr
|
||||
)
|
||||
|
||||
type BpfVersion C.struct_bpf_version
|
||||
|
||||
type BpfStat C.struct_bpf_stat
|
||||
|
||||
type BpfProgram C.struct_bpf_program
|
||||
|
||||
type BpfInsn C.struct_bpf_insn
|
||||
|
||||
type BpfHdr C.struct_bpf_hdr
|
||||
|
||||
// Terminal handling
|
||||
|
||||
type Termios C.struct_termios
|
||||
|
||||
type Winsize C.struct_winsize
|
||||
|
||||
// fchmodat-like syscalls.
|
||||
|
||||
const (
|
||||
AT_FDCWD = C.AT_FDCWD
|
||||
AT_REMOVEDIR = C.AT_REMOVEDIR
|
||||
AT_SYMLINK_FOLLOW = C.AT_SYMLINK_FOLLOW
|
||||
AT_SYMLINK_NOFOLLOW = C.AT_SYMLINK_NOFOLLOW
|
||||
)
|
||||
|
||||
// poll
|
||||
|
||||
type PollFd C.struct_pollfd
|
||||
|
||||
const (
|
||||
POLLERR = C.POLLERR
|
||||
POLLHUP = C.POLLHUP
|
||||
POLLIN = C.POLLIN
|
||||
POLLNVAL = C.POLLNVAL
|
||||
POLLOUT = C.POLLOUT
|
||||
POLLPRI = C.POLLPRI
|
||||
POLLRDBAND = C.POLLRDBAND
|
||||
POLLRDNORM = C.POLLRDNORM
|
||||
POLLWRBAND = C.POLLWRBAND
|
||||
POLLWRNORM = C.POLLWRNORM
|
||||
)
|
||||
|
||||
// uname
|
||||
|
||||
type Utsname C.struct_utsname
|
||||
|
||||
// Clockinfo
|
||||
|
||||
const SizeofClockinfo = C.sizeof_struct_clockinfo
|
||||
|
||||
type Clockinfo C.struct_clockinfo
|
||||
|
|
@ -1,263 +0,0 @@
|
|||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
/*
|
||||
Input to cgo -godefs. See README.md
|
||||
*/
|
||||
|
||||
// +godefs map struct_in_addr [4]byte /* in_addr */
|
||||
// +godefs map struct_in6_addr [16]byte /* in6_addr */
|
||||
|
||||
package unix
|
||||
|
||||
/*
|
||||
#define KERNEL
|
||||
#include <dirent.h>
|
||||
#include <fcntl.h>
|
||||
#include <poll.h>
|
||||
#include <signal.h>
|
||||
#include <termios.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/event.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/ptrace.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/select.h>
|
||||
#include <sys/signal.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/un.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <sys/wait.h>
|
||||
#include <net/bpf.h>
|
||||
#include <net/if.h>
|
||||
#include <net/if_dl.h>
|
||||
#include <net/route.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/icmp6.h>
|
||||
#include <netinet/tcp.h>
|
||||
|
||||
enum {
|
||||
sizeofPtr = sizeof(void*),
|
||||
};
|
||||
|
||||
union sockaddr_all {
|
||||
struct sockaddr s1; // this one gets used for fields
|
||||
struct sockaddr_in s2; // these pad it out
|
||||
struct sockaddr_in6 s3;
|
||||
struct sockaddr_un s4;
|
||||
struct sockaddr_dl s5;
|
||||
};
|
||||
|
||||
struct sockaddr_any {
|
||||
struct sockaddr addr;
|
||||
char pad[sizeof(union sockaddr_all) - sizeof(struct sockaddr)];
|
||||
};
|
||||
|
||||
*/
|
||||
import "C"
|
||||
|
||||
// Machine characteristics
|
||||
|
||||
const (
|
||||
SizeofPtr = C.sizeofPtr
|
||||
SizeofShort = C.sizeof_short
|
||||
SizeofInt = C.sizeof_int
|
||||
SizeofLong = C.sizeof_long
|
||||
SizeofLongLong = C.sizeof_longlong
|
||||
)
|
||||
|
||||
// Basic types
|
||||
|
||||
type (
|
||||
_C_short C.short
|
||||
_C_int C.int
|
||||
_C_long C.long
|
||||
_C_long_long C.longlong
|
||||
)
|
||||
|
||||
// Time
|
||||
|
||||
type Timespec C.struct_timespec
|
||||
|
||||
type Timeval C.struct_timeval
|
||||
|
||||
// Processes
|
||||
|
||||
type Rusage C.struct_rusage
|
||||
|
||||
type Rlimit C.struct_rlimit
|
||||
|
||||
type _Gid_t C.gid_t
|
||||
|
||||
// Files
|
||||
|
||||
type Stat_t C.struct_stat
|
||||
|
||||
type Statfs_t C.struct_statfs
|
||||
|
||||
type Flock_t C.struct_flock
|
||||
|
||||
type Dirent C.struct_dirent
|
||||
|
||||
type Fsid C.struct_fsid
|
||||
|
||||
// File system limits
|
||||
|
||||
const (
|
||||
PathMax = C.PATH_MAX
|
||||
)
|
||||
|
||||
// Sockets
|
||||
|
||||
type RawSockaddrInet4 C.struct_sockaddr_in
|
||||
|
||||
type RawSockaddrInet6 C.struct_sockaddr_in6
|
||||
|
||||
type RawSockaddrUnix C.struct_sockaddr_un
|
||||
|
||||
type RawSockaddrDatalink C.struct_sockaddr_dl
|
||||
|
||||
type RawSockaddr C.struct_sockaddr
|
||||
|
||||
type RawSockaddrAny C.struct_sockaddr_any
|
||||
|
||||
type _Socklen C.socklen_t
|
||||
|
||||
type Linger C.struct_linger
|
||||
|
||||
type Iovec C.struct_iovec
|
||||
|
||||
type IPMreq C.struct_ip_mreq
|
||||
|
||||
type IPv6Mreq C.struct_ipv6_mreq
|
||||
|
||||
type Msghdr C.struct_msghdr
|
||||
|
||||
type Cmsghdr C.struct_cmsghdr
|
||||
|
||||
type Inet6Pktinfo C.struct_in6_pktinfo
|
||||
|
||||
type IPv6MTUInfo C.struct_ip6_mtuinfo
|
||||
|
||||
type ICMPv6Filter C.struct_icmp6_filter
|
||||
|
||||
const (
|
||||
SizeofSockaddrInet4 = C.sizeof_struct_sockaddr_in
|
||||
SizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
|
||||
SizeofSockaddrAny = C.sizeof_struct_sockaddr_any
|
||||
SizeofSockaddrUnix = C.sizeof_struct_sockaddr_un
|
||||
SizeofSockaddrDatalink = C.sizeof_struct_sockaddr_dl
|
||||
SizeofLinger = C.sizeof_struct_linger
|
||||
SizeofIPMreq = C.sizeof_struct_ip_mreq
|
||||
SizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq
|
||||
SizeofMsghdr = C.sizeof_struct_msghdr
|
||||
SizeofCmsghdr = C.sizeof_struct_cmsghdr
|
||||
SizeofInet6Pktinfo = C.sizeof_struct_in6_pktinfo
|
||||
SizeofIPv6MTUInfo = C.sizeof_struct_ip6_mtuinfo
|
||||
SizeofICMPv6Filter = C.sizeof_struct_icmp6_filter
|
||||
)
|
||||
|
||||
// Ptrace requests
|
||||
|
||||
const (
|
||||
PTRACE_TRACEME = C.PT_TRACE_ME
|
||||
PTRACE_CONT = C.PT_CONTINUE
|
||||
PTRACE_KILL = C.PT_KILL
|
||||
)
|
||||
|
||||
// Events (kqueue, kevent)
|
||||
|
||||
type Kevent_t C.struct_kevent
|
||||
|
||||
// Select
|
||||
|
||||
type FdSet C.fd_set
|
||||
|
||||
// Routing and interface messages
|
||||
|
||||
const (
|
||||
SizeofIfMsghdr = C.sizeof_struct_if_msghdr
|
||||
SizeofIfData = C.sizeof_struct_if_data
|
||||
SizeofIfaMsghdr = C.sizeof_struct_ifa_msghdr
|
||||
SizeofIfmaMsghdr = C.sizeof_struct_ifma_msghdr
|
||||
SizeofIfAnnounceMsghdr = C.sizeof_struct_if_announcemsghdr
|
||||
SizeofRtMsghdr = C.sizeof_struct_rt_msghdr
|
||||
SizeofRtMetrics = C.sizeof_struct_rt_metrics
|
||||
)
|
||||
|
||||
type IfMsghdr C.struct_if_msghdr
|
||||
|
||||
type IfData C.struct_if_data
|
||||
|
||||
type IfaMsghdr C.struct_ifa_msghdr
|
||||
|
||||
type IfmaMsghdr C.struct_ifma_msghdr
|
||||
|
||||
type IfAnnounceMsghdr C.struct_if_announcemsghdr
|
||||
|
||||
type RtMsghdr C.struct_rt_msghdr
|
||||
|
||||
type RtMetrics C.struct_rt_metrics
|
||||
|
||||
// Berkeley packet filter
|
||||
|
||||
const (
|
||||
SizeofBpfVersion = C.sizeof_struct_bpf_version
|
||||
SizeofBpfStat = C.sizeof_struct_bpf_stat
|
||||
SizeofBpfProgram = C.sizeof_struct_bpf_program
|
||||
SizeofBpfInsn = C.sizeof_struct_bpf_insn
|
||||
SizeofBpfHdr = C.sizeof_struct_bpf_hdr
|
||||
)
|
||||
|
||||
type BpfVersion C.struct_bpf_version
|
||||
|
||||
type BpfStat C.struct_bpf_stat
|
||||
|
||||
type BpfProgram C.struct_bpf_program
|
||||
|
||||
type BpfInsn C.struct_bpf_insn
|
||||
|
||||
type BpfHdr C.struct_bpf_hdr
|
||||
|
||||
// Terminal handling
|
||||
|
||||
type Termios C.struct_termios
|
||||
|
||||
type Winsize C.struct_winsize
|
||||
|
||||
// fchmodat-like syscalls.
|
||||
|
||||
const (
|
||||
AT_FDCWD = C.AT_FDCWD
|
||||
AT_SYMLINK_NOFOLLOW = C.AT_SYMLINK_NOFOLLOW
|
||||
)
|
||||
|
||||
// poll
|
||||
|
||||
type PollFd C.struct_pollfd
|
||||
|
||||
const (
|
||||
POLLERR = C.POLLERR
|
||||
POLLHUP = C.POLLHUP
|
||||
POLLIN = C.POLLIN
|
||||
POLLNVAL = C.POLLNVAL
|
||||
POLLOUT = C.POLLOUT
|
||||
POLLPRI = C.POLLPRI
|
||||
POLLRDBAND = C.POLLRDBAND
|
||||
POLLRDNORM = C.POLLRDNORM
|
||||
POLLWRBAND = C.POLLWRBAND
|
||||
POLLWRNORM = C.POLLWRNORM
|
||||
)
|
||||
|
||||
// Uname
|
||||
|
||||
type Utsname C.struct_utsname
|
||||
|
|
@ -1,356 +0,0 @@
|
|||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
/*
|
||||
Input to cgo -godefs. See README.md
|
||||
*/
|
||||
|
||||
// +godefs map struct_in_addr [4]byte /* in_addr */
|
||||
// +godefs map struct_in6_addr [16]byte /* in6_addr */
|
||||
|
||||
package unix
|
||||
|
||||
/*
|
||||
#define _WANT_FREEBSD11_STAT 1
|
||||
#define _WANT_FREEBSD11_STATFS 1
|
||||
#define _WANT_FREEBSD11_DIRENT 1
|
||||
#define _WANT_FREEBSD11_KEVENT 1
|
||||
|
||||
#include <dirent.h>
|
||||
#include <fcntl.h>
|
||||
#include <poll.h>
|
||||
#include <signal.h>
|
||||
#include <termios.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/capsicum.h>
|
||||
#include <sys/event.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/ptrace.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/select.h>
|
||||
#include <sys/signal.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/un.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <sys/wait.h>
|
||||
#include <net/bpf.h>
|
||||
#include <net/if.h>
|
||||
#include <net/if_dl.h>
|
||||
#include <net/route.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/icmp6.h>
|
||||
#include <netinet/tcp.h>
|
||||
|
||||
enum {
|
||||
sizeofPtr = sizeof(void*),
|
||||
};
|
||||
|
||||
union sockaddr_all {
|
||||
struct sockaddr s1; // this one gets used for fields
|
||||
struct sockaddr_in s2; // these pad it out
|
||||
struct sockaddr_in6 s3;
|
||||
struct sockaddr_un s4;
|
||||
struct sockaddr_dl s5;
|
||||
};
|
||||
|
||||
struct sockaddr_any {
|
||||
struct sockaddr addr;
|
||||
char pad[sizeof(union sockaddr_all) - sizeof(struct sockaddr)];
|
||||
};
|
||||
|
||||
// This structure is a duplicate of if_data on FreeBSD 8-STABLE.
|
||||
// See /usr/include/net/if.h.
|
||||
struct if_data8 {
|
||||
u_char ifi_type;
|
||||
u_char ifi_physical;
|
||||
u_char ifi_addrlen;
|
||||
u_char ifi_hdrlen;
|
||||
u_char ifi_link_state;
|
||||
u_char ifi_spare_char1;
|
||||
u_char ifi_spare_char2;
|
||||
u_char ifi_datalen;
|
||||
u_long ifi_mtu;
|
||||
u_long ifi_metric;
|
||||
u_long ifi_baudrate;
|
||||
u_long ifi_ipackets;
|
||||
u_long ifi_ierrors;
|
||||
u_long ifi_opackets;
|
||||
u_long ifi_oerrors;
|
||||
u_long ifi_collisions;
|
||||
u_long ifi_ibytes;
|
||||
u_long ifi_obytes;
|
||||
u_long ifi_imcasts;
|
||||
u_long ifi_omcasts;
|
||||
u_long ifi_iqdrops;
|
||||
u_long ifi_noproto;
|
||||
u_long ifi_hwassist;
|
||||
// FIXME: these are now unions, so maybe need to change definitions?
|
||||
#undef ifi_epoch
|
||||
time_t ifi_epoch;
|
||||
#undef ifi_lastchange
|
||||
struct timeval ifi_lastchange;
|
||||
};
|
||||
|
||||
// This structure is a duplicate of if_msghdr on FreeBSD 8-STABLE.
|
||||
// See /usr/include/net/if.h.
|
||||
struct if_msghdr8 {
|
||||
u_short ifm_msglen;
|
||||
u_char ifm_version;
|
||||
u_char ifm_type;
|
||||
int ifm_addrs;
|
||||
int ifm_flags;
|
||||
u_short ifm_index;
|
||||
struct if_data8 ifm_data;
|
||||
};
|
||||
*/
|
||||
import "C"
|
||||
|
||||
// Machine characteristics
|
||||
|
||||
const (
|
||||
SizeofPtr = C.sizeofPtr
|
||||
SizeofShort = C.sizeof_short
|
||||
SizeofInt = C.sizeof_int
|
||||
SizeofLong = C.sizeof_long
|
||||
SizeofLongLong = C.sizeof_longlong
|
||||
)
|
||||
|
||||
// Basic types
|
||||
|
||||
type (
|
||||
_C_short C.short
|
||||
_C_int C.int
|
||||
_C_long C.long
|
||||
_C_long_long C.longlong
|
||||
)
|
||||
|
||||
// Time
|
||||
|
||||
type Timespec C.struct_timespec
|
||||
|
||||
type Timeval C.struct_timeval
|
||||
|
||||
// Processes
|
||||
|
||||
type Rusage C.struct_rusage
|
||||
|
||||
type Rlimit C.struct_rlimit
|
||||
|
||||
type _Gid_t C.gid_t
|
||||
|
||||
// Files
|
||||
|
||||
const (
|
||||
_statfsVersion = C.STATFS_VERSION
|
||||
_dirblksiz = C.DIRBLKSIZ
|
||||
)
|
||||
|
||||
type Stat_t C.struct_stat
|
||||
|
||||
type stat_freebsd11_t C.struct_freebsd11_stat
|
||||
|
||||
type Statfs_t C.struct_statfs
|
||||
|
||||
type statfs_freebsd11_t C.struct_freebsd11_statfs
|
||||
|
||||
type Flock_t C.struct_flock
|
||||
|
||||
type Dirent C.struct_dirent
|
||||
|
||||
type dirent_freebsd11 C.struct_freebsd11_dirent
|
||||
|
||||
type Fsid C.struct_fsid
|
||||
|
||||
// File system limits
|
||||
|
||||
const (
|
||||
PathMax = C.PATH_MAX
|
||||
)
|
||||
|
||||
// Advice to Fadvise
|
||||
|
||||
const (
|
||||
FADV_NORMAL = C.POSIX_FADV_NORMAL
|
||||
FADV_RANDOM = C.POSIX_FADV_RANDOM
|
||||
FADV_SEQUENTIAL = C.POSIX_FADV_SEQUENTIAL
|
||||
FADV_WILLNEED = C.POSIX_FADV_WILLNEED
|
||||
FADV_DONTNEED = C.POSIX_FADV_DONTNEED
|
||||
FADV_NOREUSE = C.POSIX_FADV_NOREUSE
|
||||
)
|
||||
|
||||
// Sockets
|
||||
|
||||
type RawSockaddrInet4 C.struct_sockaddr_in
|
||||
|
||||
type RawSockaddrInet6 C.struct_sockaddr_in6
|
||||
|
||||
type RawSockaddrUnix C.struct_sockaddr_un
|
||||
|
||||
type RawSockaddrDatalink C.struct_sockaddr_dl
|
||||
|
||||
type RawSockaddr C.struct_sockaddr
|
||||
|
||||
type RawSockaddrAny C.struct_sockaddr_any
|
||||
|
||||
type _Socklen C.socklen_t
|
||||
|
||||
type Linger C.struct_linger
|
||||
|
||||
type Iovec C.struct_iovec
|
||||
|
||||
type IPMreq C.struct_ip_mreq
|
||||
|
||||
type IPMreqn C.struct_ip_mreqn
|
||||
|
||||
type IPv6Mreq C.struct_ipv6_mreq
|
||||
|
||||
type Msghdr C.struct_msghdr
|
||||
|
||||
type Cmsghdr C.struct_cmsghdr
|
||||
|
||||
type Inet6Pktinfo C.struct_in6_pktinfo
|
||||
|
||||
type IPv6MTUInfo C.struct_ip6_mtuinfo
|
||||
|
||||
type ICMPv6Filter C.struct_icmp6_filter
|
||||
|
||||
const (
|
||||
SizeofSockaddrInet4 = C.sizeof_struct_sockaddr_in
|
||||
SizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
|
||||
SizeofSockaddrAny = C.sizeof_struct_sockaddr_any
|
||||
SizeofSockaddrUnix = C.sizeof_struct_sockaddr_un
|
||||
SizeofSockaddrDatalink = C.sizeof_struct_sockaddr_dl
|
||||
SizeofLinger = C.sizeof_struct_linger
|
||||
SizeofIPMreq = C.sizeof_struct_ip_mreq
|
||||
SizeofIPMreqn = C.sizeof_struct_ip_mreqn
|
||||
SizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq
|
||||
SizeofMsghdr = C.sizeof_struct_msghdr
|
||||
SizeofCmsghdr = C.sizeof_struct_cmsghdr
|
||||
SizeofInet6Pktinfo = C.sizeof_struct_in6_pktinfo
|
||||
SizeofIPv6MTUInfo = C.sizeof_struct_ip6_mtuinfo
|
||||
SizeofICMPv6Filter = C.sizeof_struct_icmp6_filter
|
||||
)
|
||||
|
||||
// Ptrace requests
|
||||
|
||||
const (
|
||||
PTRACE_TRACEME = C.PT_TRACE_ME
|
||||
PTRACE_CONT = C.PT_CONTINUE
|
||||
PTRACE_KILL = C.PT_KILL
|
||||
)
|
||||
|
||||
// Events (kqueue, kevent)
|
||||
|
||||
type Kevent_t C.struct_kevent_freebsd11
|
||||
|
||||
// Select
|
||||
|
||||
type FdSet C.fd_set
|
||||
|
||||
// Routing and interface messages
|
||||
|
||||
const (
|
||||
sizeofIfMsghdr = C.sizeof_struct_if_msghdr
|
||||
SizeofIfMsghdr = C.sizeof_struct_if_msghdr8
|
||||
sizeofIfData = C.sizeof_struct_if_data
|
||||
SizeofIfData = C.sizeof_struct_if_data8
|
||||
SizeofIfaMsghdr = C.sizeof_struct_ifa_msghdr
|
||||
SizeofIfmaMsghdr = C.sizeof_struct_ifma_msghdr
|
||||
SizeofIfAnnounceMsghdr = C.sizeof_struct_if_announcemsghdr
|
||||
SizeofRtMsghdr = C.sizeof_struct_rt_msghdr
|
||||
SizeofRtMetrics = C.sizeof_struct_rt_metrics
|
||||
)
|
||||
|
||||
type ifMsghdr C.struct_if_msghdr
|
||||
|
||||
type IfMsghdr C.struct_if_msghdr8
|
||||
|
||||
type ifData C.struct_if_data
|
||||
|
||||
type IfData C.struct_if_data8
|
||||
|
||||
type IfaMsghdr C.struct_ifa_msghdr
|
||||
|
||||
type IfmaMsghdr C.struct_ifma_msghdr
|
||||
|
||||
type IfAnnounceMsghdr C.struct_if_announcemsghdr
|
||||
|
||||
type RtMsghdr C.struct_rt_msghdr
|
||||
|
||||
type RtMetrics C.struct_rt_metrics
|
||||
|
||||
// Berkeley packet filter
|
||||
|
||||
const (
|
||||
SizeofBpfVersion = C.sizeof_struct_bpf_version
|
||||
SizeofBpfStat = C.sizeof_struct_bpf_stat
|
||||
SizeofBpfZbuf = C.sizeof_struct_bpf_zbuf
|
||||
SizeofBpfProgram = C.sizeof_struct_bpf_program
|
||||
SizeofBpfInsn = C.sizeof_struct_bpf_insn
|
||||
SizeofBpfHdr = C.sizeof_struct_bpf_hdr
|
||||
SizeofBpfZbufHeader = C.sizeof_struct_bpf_zbuf_header
|
||||
)
|
||||
|
||||
type BpfVersion C.struct_bpf_version
|
||||
|
||||
type BpfStat C.struct_bpf_stat
|
||||
|
||||
type BpfZbuf C.struct_bpf_zbuf
|
||||
|
||||
type BpfProgram C.struct_bpf_program
|
||||
|
||||
type BpfInsn C.struct_bpf_insn
|
||||
|
||||
type BpfHdr C.struct_bpf_hdr
|
||||
|
||||
type BpfZbufHeader C.struct_bpf_zbuf_header
|
||||
|
||||
// Terminal handling
|
||||
|
||||
type Termios C.struct_termios
|
||||
|
||||
type Winsize C.struct_winsize
|
||||
|
||||
// fchmodat-like syscalls.
|
||||
|
||||
const (
|
||||
AT_FDCWD = C.AT_FDCWD
|
||||
AT_REMOVEDIR = C.AT_REMOVEDIR
|
||||
AT_SYMLINK_FOLLOW = C.AT_SYMLINK_FOLLOW
|
||||
AT_SYMLINK_NOFOLLOW = C.AT_SYMLINK_NOFOLLOW
|
||||
)
|
||||
|
||||
// poll
|
||||
|
||||
type PollFd C.struct_pollfd
|
||||
|
||||
const (
|
||||
POLLERR = C.POLLERR
|
||||
POLLHUP = C.POLLHUP
|
||||
POLLIN = C.POLLIN
|
||||
POLLINIGNEOF = C.POLLINIGNEOF
|
||||
POLLNVAL = C.POLLNVAL
|
||||
POLLOUT = C.POLLOUT
|
||||
POLLPRI = C.POLLPRI
|
||||
POLLRDBAND = C.POLLRDBAND
|
||||
POLLRDNORM = C.POLLRDNORM
|
||||
POLLWRBAND = C.POLLWRBAND
|
||||
POLLWRNORM = C.POLLWRNORM
|
||||
)
|
||||
|
||||
// Capabilities
|
||||
|
||||
type CapRights C.struct_cap_rights
|
||||
|
||||
// Uname
|
||||
|
||||
type Utsname C.struct_utsname
|
||||
|
|
@ -1,289 +0,0 @@
|
|||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
/*
|
||||
Input to cgo -godefs. See README.md
|
||||
*/
|
||||
|
||||
// +godefs map struct_in_addr [4]byte /* in_addr */
|
||||
// +godefs map struct_in6_addr [16]byte /* in6_addr */
|
||||
|
||||
package unix
|
||||
|
||||
/*
|
||||
#define KERNEL
|
||||
#include <dirent.h>
|
||||
#include <fcntl.h>
|
||||
#include <poll.h>
|
||||
#include <signal.h>
|
||||
#include <termios.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/event.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/ptrace.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/select.h>
|
||||
#include <sys/signal.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/uio.h>
|
||||
#include <sys/un.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <sys/wait.h>
|
||||
#include <net/bpf.h>
|
||||
#include <net/if.h>
|
||||
#include <net/if_dl.h>
|
||||
#include <net/route.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/icmp6.h>
|
||||
#include <netinet/tcp.h>
|
||||
|
||||
enum {
|
||||
sizeofPtr = sizeof(void*),
|
||||
};
|
||||
|
||||
union sockaddr_all {
|
||||
struct sockaddr s1; // this one gets used for fields
|
||||
struct sockaddr_in s2; // these pad it out
|
||||
struct sockaddr_in6 s3;
|
||||
struct sockaddr_un s4;
|
||||
struct sockaddr_dl s5;
|
||||
};
|
||||
|
||||
struct sockaddr_any {
|
||||
struct sockaddr addr;
|
||||
char pad[sizeof(union sockaddr_all) - sizeof(struct sockaddr)];
|
||||
};
|
||||
|
||||
*/
|
||||
import "C"
|
||||
|
||||
// Machine characteristics
|
||||
|
||||
const (
|
||||
SizeofPtr = C.sizeofPtr
|
||||
SizeofShort = C.sizeof_short
|
||||
SizeofInt = C.sizeof_int
|
||||
SizeofLong = C.sizeof_long
|
||||
SizeofLongLong = C.sizeof_longlong
|
||||
)
|
||||
|
||||
// Basic types
|
||||
|
||||
type (
|
||||
_C_short C.short
|
||||
_C_int C.int
|
||||
_C_long C.long
|
||||
_C_long_long C.longlong
|
||||
)
|
||||
|
||||
// Time
|
||||
|
||||
type Timespec C.struct_timespec
|
||||
|
||||
type Timeval C.struct_timeval
|
||||
|
||||
// Processes
|
||||
|
||||
type Rusage C.struct_rusage
|
||||
|
||||
type Rlimit C.struct_rlimit
|
||||
|
||||
type _Gid_t C.gid_t
|
||||
|
||||
// Files
|
||||
|
||||
type Stat_t C.struct_stat
|
||||
|
||||
type Statfs_t C.struct_statfs
|
||||
|
||||
type Flock_t C.struct_flock
|
||||
|
||||
type Dirent C.struct_dirent
|
||||
|
||||
type Fsid C.fsid_t
|
||||
|
||||
// File system limits
|
||||
|
||||
const (
|
||||
PathMax = C.PATH_MAX
|
||||
)
|
||||
|
||||
// Advice to Fadvise
|
||||
|
||||
const (
|
||||
FADV_NORMAL = C.POSIX_FADV_NORMAL
|
||||
FADV_RANDOM = C.POSIX_FADV_RANDOM
|
||||
FADV_SEQUENTIAL = C.POSIX_FADV_SEQUENTIAL
|
||||
FADV_WILLNEED = C.POSIX_FADV_WILLNEED
|
||||
FADV_DONTNEED = C.POSIX_FADV_DONTNEED
|
||||
FADV_NOREUSE = C.POSIX_FADV_NOREUSE
|
||||
)
|
||||
|
||||
// Sockets
|
||||
|
||||
type RawSockaddrInet4 C.struct_sockaddr_in
|
||||
|
||||
type RawSockaddrInet6 C.struct_sockaddr_in6
|
||||
|
||||
type RawSockaddrUnix C.struct_sockaddr_un
|
||||
|
||||
type RawSockaddrDatalink C.struct_sockaddr_dl
|
||||
|
||||
type RawSockaddr C.struct_sockaddr
|
||||
|
||||
type RawSockaddrAny C.struct_sockaddr_any
|
||||
|
||||
type _Socklen C.socklen_t
|
||||
|
||||
type Linger C.struct_linger
|
||||
|
||||
type Iovec C.struct_iovec
|
||||
|
||||
type IPMreq C.struct_ip_mreq
|
||||
|
||||
type IPv6Mreq C.struct_ipv6_mreq
|
||||
|
||||
type Msghdr C.struct_msghdr
|
||||
|
||||
type Cmsghdr C.struct_cmsghdr
|
||||
|
||||
type Inet6Pktinfo C.struct_in6_pktinfo
|
||||
|
||||
type IPv6MTUInfo C.struct_ip6_mtuinfo
|
||||
|
||||
type ICMPv6Filter C.struct_icmp6_filter
|
||||
|
||||
const (
|
||||
SizeofSockaddrInet4 = C.sizeof_struct_sockaddr_in
|
||||
SizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
|
||||
SizeofSockaddrAny = C.sizeof_struct_sockaddr_any
|
||||
SizeofSockaddrUnix = C.sizeof_struct_sockaddr_un
|
||||
SizeofSockaddrDatalink = C.sizeof_struct_sockaddr_dl
|
||||
SizeofLinger = C.sizeof_struct_linger
|
||||
SizeofIPMreq = C.sizeof_struct_ip_mreq
|
||||
SizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq
|
||||
SizeofMsghdr = C.sizeof_struct_msghdr
|
||||
SizeofCmsghdr = C.sizeof_struct_cmsghdr
|
||||
SizeofInet6Pktinfo = C.sizeof_struct_in6_pktinfo
|
||||
SizeofIPv6MTUInfo = C.sizeof_struct_ip6_mtuinfo
|
||||
SizeofICMPv6Filter = C.sizeof_struct_icmp6_filter
|
||||
)
|
||||
|
||||
// Ptrace requests
|
||||
|
||||
const (
|
||||
PTRACE_TRACEME = C.PT_TRACE_ME
|
||||
PTRACE_CONT = C.PT_CONTINUE
|
||||
PTRACE_KILL = C.PT_KILL
|
||||
)
|
||||
|
||||
// Events (kqueue, kevent)
|
||||
|
||||
type Kevent_t C.struct_kevent
|
||||
|
||||
// Select
|
||||
|
||||
type FdSet C.fd_set
|
||||
|
||||
// Routing and interface messages
|
||||
|
||||
const (
|
||||
SizeofIfMsghdr = C.sizeof_struct_if_msghdr
|
||||
SizeofIfData = C.sizeof_struct_if_data
|
||||
SizeofIfaMsghdr = C.sizeof_struct_ifa_msghdr
|
||||
SizeofIfAnnounceMsghdr = C.sizeof_struct_if_announcemsghdr
|
||||
SizeofRtMsghdr = C.sizeof_struct_rt_msghdr
|
||||
SizeofRtMetrics = C.sizeof_struct_rt_metrics
|
||||
)
|
||||
|
||||
type IfMsghdr C.struct_if_msghdr
|
||||
|
||||
type IfData C.struct_if_data
|
||||
|
||||
type IfaMsghdr C.struct_ifa_msghdr
|
||||
|
||||
type IfAnnounceMsghdr C.struct_if_announcemsghdr
|
||||
|
||||
type RtMsghdr C.struct_rt_msghdr
|
||||
|
||||
type RtMetrics C.struct_rt_metrics
|
||||
|
||||
type Mclpool C.struct_mclpool
|
||||
|
||||
// Berkeley packet filter
|
||||
|
||||
const (
|
||||
SizeofBpfVersion = C.sizeof_struct_bpf_version
|
||||
SizeofBpfStat = C.sizeof_struct_bpf_stat
|
||||
SizeofBpfProgram = C.sizeof_struct_bpf_program
|
||||
SizeofBpfInsn = C.sizeof_struct_bpf_insn
|
||||
SizeofBpfHdr = C.sizeof_struct_bpf_hdr
|
||||
)
|
||||
|
||||
type BpfVersion C.struct_bpf_version
|
||||
|
||||
type BpfStat C.struct_bpf_stat
|
||||
|
||||
type BpfProgram C.struct_bpf_program
|
||||
|
||||
type BpfInsn C.struct_bpf_insn
|
||||
|
||||
type BpfHdr C.struct_bpf_hdr
|
||||
|
||||
type BpfTimeval C.struct_bpf_timeval
|
||||
|
||||
// Terminal handling
|
||||
|
||||
type Termios C.struct_termios
|
||||
|
||||
type Winsize C.struct_winsize
|
||||
|
||||
type Ptmget C.struct_ptmget
|
||||
|
||||
// fchmodat-like syscalls.
|
||||
|
||||
const (
|
||||
AT_FDCWD = C.AT_FDCWD
|
||||
AT_SYMLINK_NOFOLLOW = C.AT_SYMLINK_NOFOLLOW
|
||||
)
|
||||
|
||||
// poll
|
||||
|
||||
type PollFd C.struct_pollfd
|
||||
|
||||
const (
|
||||
POLLERR = C.POLLERR
|
||||
POLLHUP = C.POLLHUP
|
||||
POLLIN = C.POLLIN
|
||||
POLLNVAL = C.POLLNVAL
|
||||
POLLOUT = C.POLLOUT
|
||||
POLLPRI = C.POLLPRI
|
||||
POLLRDBAND = C.POLLRDBAND
|
||||
POLLRDNORM = C.POLLRDNORM
|
||||
POLLWRBAND = C.POLLWRBAND
|
||||
POLLWRNORM = C.POLLWRNORM
|
||||
)
|
||||
|
||||
// Sysctl
|
||||
|
||||
type Sysctlnode C.struct_sysctlnode
|
||||
|
||||
// Uname
|
||||
|
||||
type Utsname C.struct_utsname
|
||||
|
||||
// Clockinfo
|
||||
|
||||
const SizeofClockinfo = C.sizeof_struct_clockinfo
|
||||
|
||||
type Clockinfo C.struct_clockinfo
|
||||
|
|
@ -1,282 +0,0 @@
|
|||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
/*
|
||||
Input to cgo -godefs. See README.md
|
||||
*/
|
||||
|
||||
// +godefs map struct_in_addr [4]byte /* in_addr */
|
||||
// +godefs map struct_in6_addr [16]byte /* in6_addr */
|
||||
|
||||
package unix
|
||||
|
||||
/*
|
||||
#define KERNEL
|
||||
#include <dirent.h>
|
||||
#include <fcntl.h>
|
||||
#include <poll.h>
|
||||
#include <signal.h>
|
||||
#include <termios.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/event.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/ptrace.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/select.h>
|
||||
#include <sys/signal.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/uio.h>
|
||||
#include <sys/un.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <sys/wait.h>
|
||||
#include <uvm/uvmexp.h>
|
||||
#include <net/bpf.h>
|
||||
#include <net/if.h>
|
||||
#include <net/if_dl.h>
|
||||
#include <net/route.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/icmp6.h>
|
||||
#include <netinet/tcp.h>
|
||||
|
||||
enum {
|
||||
sizeofPtr = sizeof(void*),
|
||||
};
|
||||
|
||||
union sockaddr_all {
|
||||
struct sockaddr s1; // this one gets used for fields
|
||||
struct sockaddr_in s2; // these pad it out
|
||||
struct sockaddr_in6 s3;
|
||||
struct sockaddr_un s4;
|
||||
struct sockaddr_dl s5;
|
||||
};
|
||||
|
||||
struct sockaddr_any {
|
||||
struct sockaddr addr;
|
||||
char pad[sizeof(union sockaddr_all) - sizeof(struct sockaddr)];
|
||||
};
|
||||
|
||||
*/
|
||||
import "C"
|
||||
|
||||
// Machine characteristics
|
||||
|
||||
const (
|
||||
SizeofPtr = C.sizeofPtr
|
||||
SizeofShort = C.sizeof_short
|
||||
SizeofInt = C.sizeof_int
|
||||
SizeofLong = C.sizeof_long
|
||||
SizeofLongLong = C.sizeof_longlong
|
||||
)
|
||||
|
||||
// Basic types
|
||||
|
||||
type (
|
||||
_C_short C.short
|
||||
_C_int C.int
|
||||
_C_long C.long
|
||||
_C_long_long C.longlong
|
||||
)
|
||||
|
||||
// Time
|
||||
|
||||
type Timespec C.struct_timespec
|
||||
|
||||
type Timeval C.struct_timeval
|
||||
|
||||
// Processes
|
||||
|
||||
type Rusage C.struct_rusage
|
||||
|
||||
type Rlimit C.struct_rlimit
|
||||
|
||||
type _Gid_t C.gid_t
|
||||
|
||||
// Files
|
||||
|
||||
type Stat_t C.struct_stat
|
||||
|
||||
type Statfs_t C.struct_statfs
|
||||
|
||||
type Flock_t C.struct_flock
|
||||
|
||||
type Dirent C.struct_dirent
|
||||
|
||||
type Fsid C.fsid_t
|
||||
|
||||
// File system limits
|
||||
|
||||
const (
|
||||
PathMax = C.PATH_MAX
|
||||
)
|
||||
|
||||
// Sockets
|
||||
|
||||
type RawSockaddrInet4 C.struct_sockaddr_in
|
||||
|
||||
type RawSockaddrInet6 C.struct_sockaddr_in6
|
||||
|
||||
type RawSockaddrUnix C.struct_sockaddr_un
|
||||
|
||||
type RawSockaddrDatalink C.struct_sockaddr_dl
|
||||
|
||||
type RawSockaddr C.struct_sockaddr
|
||||
|
||||
type RawSockaddrAny C.struct_sockaddr_any
|
||||
|
||||
type _Socklen C.socklen_t
|
||||
|
||||
type Linger C.struct_linger
|
||||
|
||||
type Iovec C.struct_iovec
|
||||
|
||||
type IPMreq C.struct_ip_mreq
|
||||
|
||||
type IPv6Mreq C.struct_ipv6_mreq
|
||||
|
||||
type Msghdr C.struct_msghdr
|
||||
|
||||
type Cmsghdr C.struct_cmsghdr
|
||||
|
||||
type Inet6Pktinfo C.struct_in6_pktinfo
|
||||
|
||||
type IPv6MTUInfo C.struct_ip6_mtuinfo
|
||||
|
||||
type ICMPv6Filter C.struct_icmp6_filter
|
||||
|
||||
const (
|
||||
SizeofSockaddrInet4 = C.sizeof_struct_sockaddr_in
|
||||
SizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
|
||||
SizeofSockaddrAny = C.sizeof_struct_sockaddr_any
|
||||
SizeofSockaddrUnix = C.sizeof_struct_sockaddr_un
|
||||
SizeofSockaddrDatalink = C.sizeof_struct_sockaddr_dl
|
||||
SizeofLinger = C.sizeof_struct_linger
|
||||
SizeofIPMreq = C.sizeof_struct_ip_mreq
|
||||
SizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq
|
||||
SizeofMsghdr = C.sizeof_struct_msghdr
|
||||
SizeofCmsghdr = C.sizeof_struct_cmsghdr
|
||||
SizeofInet6Pktinfo = C.sizeof_struct_in6_pktinfo
|
||||
SizeofIPv6MTUInfo = C.sizeof_struct_ip6_mtuinfo
|
||||
SizeofICMPv6Filter = C.sizeof_struct_icmp6_filter
|
||||
)
|
||||
|
||||
// Ptrace requests
|
||||
|
||||
const (
|
||||
PTRACE_TRACEME = C.PT_TRACE_ME
|
||||
PTRACE_CONT = C.PT_CONTINUE
|
||||
PTRACE_KILL = C.PT_KILL
|
||||
)
|
||||
|
||||
// Events (kqueue, kevent)
|
||||
|
||||
type Kevent_t C.struct_kevent
|
||||
|
||||
// Select
|
||||
|
||||
type FdSet C.fd_set
|
||||
|
||||
// Routing and interface messages
|
||||
|
||||
const (
|
||||
SizeofIfMsghdr = C.sizeof_struct_if_msghdr
|
||||
SizeofIfData = C.sizeof_struct_if_data
|
||||
SizeofIfaMsghdr = C.sizeof_struct_ifa_msghdr
|
||||
SizeofIfAnnounceMsghdr = C.sizeof_struct_if_announcemsghdr
|
||||
SizeofRtMsghdr = C.sizeof_struct_rt_msghdr
|
||||
SizeofRtMetrics = C.sizeof_struct_rt_metrics
|
||||
)
|
||||
|
||||
type IfMsghdr C.struct_if_msghdr
|
||||
|
||||
type IfData C.struct_if_data
|
||||
|
||||
type IfaMsghdr C.struct_ifa_msghdr
|
||||
|
||||
type IfAnnounceMsghdr C.struct_if_announcemsghdr
|
||||
|
||||
type RtMsghdr C.struct_rt_msghdr
|
||||
|
||||
type RtMetrics C.struct_rt_metrics
|
||||
|
||||
type Mclpool C.struct_mclpool
|
||||
|
||||
// Berkeley packet filter
|
||||
|
||||
const (
|
||||
SizeofBpfVersion = C.sizeof_struct_bpf_version
|
||||
SizeofBpfStat = C.sizeof_struct_bpf_stat
|
||||
SizeofBpfProgram = C.sizeof_struct_bpf_program
|
||||
SizeofBpfInsn = C.sizeof_struct_bpf_insn
|
||||
SizeofBpfHdr = C.sizeof_struct_bpf_hdr
|
||||
)
|
||||
|
||||
type BpfVersion C.struct_bpf_version
|
||||
|
||||
type BpfStat C.struct_bpf_stat
|
||||
|
||||
type BpfProgram C.struct_bpf_program
|
||||
|
||||
type BpfInsn C.struct_bpf_insn
|
||||
|
||||
type BpfHdr C.struct_bpf_hdr
|
||||
|
||||
type BpfTimeval C.struct_bpf_timeval
|
||||
|
||||
// Terminal handling
|
||||
|
||||
type Termios C.struct_termios
|
||||
|
||||
type Winsize C.struct_winsize
|
||||
|
||||
// fchmodat-like syscalls.
|
||||
|
||||
const (
|
||||
AT_FDCWD = C.AT_FDCWD
|
||||
AT_SYMLINK_NOFOLLOW = C.AT_SYMLINK_NOFOLLOW
|
||||
)
|
||||
|
||||
// poll
|
||||
|
||||
type PollFd C.struct_pollfd
|
||||
|
||||
const (
|
||||
POLLERR = C.POLLERR
|
||||
POLLHUP = C.POLLHUP
|
||||
POLLIN = C.POLLIN
|
||||
POLLNVAL = C.POLLNVAL
|
||||
POLLOUT = C.POLLOUT
|
||||
POLLPRI = C.POLLPRI
|
||||
POLLRDBAND = C.POLLRDBAND
|
||||
POLLRDNORM = C.POLLRDNORM
|
||||
POLLWRBAND = C.POLLWRBAND
|
||||
POLLWRNORM = C.POLLWRNORM
|
||||
)
|
||||
|
||||
// Signal Sets
|
||||
|
||||
type Sigset_t C.sigset_t
|
||||
|
||||
// Uname
|
||||
|
||||
type Utsname C.struct_utsname
|
||||
|
||||
// Uvmexp
|
||||
|
||||
const SizeofUvmexp = C.sizeof_struct_uvmexp
|
||||
|
||||
type Uvmexp C.struct_uvmexp
|
||||
|
||||
// Clockinfo
|
||||
|
||||
const SizeofClockinfo = C.sizeof_struct_clockinfo
|
||||
|
||||
type Clockinfo C.struct_clockinfo
|
||||
|
|
@ -1,266 +0,0 @@
|
|||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
/*
|
||||
Input to cgo -godefs. See README.md
|
||||
*/
|
||||
|
||||
// +godefs map struct_in_addr [4]byte /* in_addr */
|
||||
// +godefs map struct_in6_addr [16]byte /* in6_addr */
|
||||
|
||||
package unix
|
||||
|
||||
/*
|
||||
#define KERNEL
|
||||
// These defines ensure that builds done on newer versions of Solaris are
|
||||
// backwards-compatible with older versions of Solaris and
|
||||
// OpenSolaris-based derivatives.
|
||||
#define __USE_SUNOS_SOCKETS__ // msghdr
|
||||
#define __USE_LEGACY_PROTOTYPES__ // iovec
|
||||
#include <dirent.h>
|
||||
#include <fcntl.h>
|
||||
#include <netdb.h>
|
||||
#include <limits.h>
|
||||
#include <poll.h>
|
||||
#include <signal.h>
|
||||
#include <termios.h>
|
||||
#include <termio.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/select.h>
|
||||
#include <sys/signal.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/statvfs.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/times.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <sys/un.h>
|
||||
#include <sys/wait.h>
|
||||
#include <net/bpf.h>
|
||||
#include <net/if.h>
|
||||
#include <net/if_dl.h>
|
||||
#include <net/route.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/icmp6.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <ustat.h>
|
||||
#include <utime.h>
|
||||
|
||||
enum {
|
||||
sizeofPtr = sizeof(void*),
|
||||
};
|
||||
|
||||
union sockaddr_all {
|
||||
struct sockaddr s1; // this one gets used for fields
|
||||
struct sockaddr_in s2; // these pad it out
|
||||
struct sockaddr_in6 s3;
|
||||
struct sockaddr_un s4;
|
||||
struct sockaddr_dl s5;
|
||||
};
|
||||
|
||||
struct sockaddr_any {
|
||||
struct sockaddr addr;
|
||||
char pad[sizeof(union sockaddr_all) - sizeof(struct sockaddr)];
|
||||
};
|
||||
|
||||
*/
|
||||
import "C"
|
||||
|
||||
// Machine characteristics
|
||||
|
||||
const (
|
||||
SizeofPtr = C.sizeofPtr
|
||||
SizeofShort = C.sizeof_short
|
||||
SizeofInt = C.sizeof_int
|
||||
SizeofLong = C.sizeof_long
|
||||
SizeofLongLong = C.sizeof_longlong
|
||||
PathMax = C.PATH_MAX
|
||||
MaxHostNameLen = C.MAXHOSTNAMELEN
|
||||
)
|
||||
|
||||
// Basic types
|
||||
|
||||
type (
|
||||
_C_short C.short
|
||||
_C_int C.int
|
||||
_C_long C.long
|
||||
_C_long_long C.longlong
|
||||
)
|
||||
|
||||
// Time
|
||||
|
||||
type Timespec C.struct_timespec
|
||||
|
||||
type Timeval C.struct_timeval
|
||||
|
||||
type Timeval32 C.struct_timeval32
|
||||
|
||||
type Tms C.struct_tms
|
||||
|
||||
type Utimbuf C.struct_utimbuf
|
||||
|
||||
// Processes
|
||||
|
||||
type Rusage C.struct_rusage
|
||||
|
||||
type Rlimit C.struct_rlimit
|
||||
|
||||
type _Gid_t C.gid_t
|
||||
|
||||
// Files
|
||||
|
||||
type Stat_t C.struct_stat
|
||||
|
||||
type Flock_t C.struct_flock
|
||||
|
||||
type Dirent C.struct_dirent
|
||||
|
||||
// Filesystems
|
||||
|
||||
type _Fsblkcnt_t C.fsblkcnt_t
|
||||
|
||||
type Statvfs_t C.struct_statvfs
|
||||
|
||||
// Sockets
|
||||
|
||||
type RawSockaddrInet4 C.struct_sockaddr_in
|
||||
|
||||
type RawSockaddrInet6 C.struct_sockaddr_in6
|
||||
|
||||
type RawSockaddrUnix C.struct_sockaddr_un
|
||||
|
||||
type RawSockaddrDatalink C.struct_sockaddr_dl
|
||||
|
||||
type RawSockaddr C.struct_sockaddr
|
||||
|
||||
type RawSockaddrAny C.struct_sockaddr_any
|
||||
|
||||
type _Socklen C.socklen_t
|
||||
|
||||
type Linger C.struct_linger
|
||||
|
||||
type Iovec C.struct_iovec
|
||||
|
||||
type IPMreq C.struct_ip_mreq
|
||||
|
||||
type IPv6Mreq C.struct_ipv6_mreq
|
||||
|
||||
type Msghdr C.struct_msghdr
|
||||
|
||||
type Cmsghdr C.struct_cmsghdr
|
||||
|
||||
type Inet6Pktinfo C.struct_in6_pktinfo
|
||||
|
||||
type IPv6MTUInfo C.struct_ip6_mtuinfo
|
||||
|
||||
type ICMPv6Filter C.struct_icmp6_filter
|
||||
|
||||
const (
|
||||
SizeofSockaddrInet4 = C.sizeof_struct_sockaddr_in
|
||||
SizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
|
||||
SizeofSockaddrAny = C.sizeof_struct_sockaddr_any
|
||||
SizeofSockaddrUnix = C.sizeof_struct_sockaddr_un
|
||||
SizeofSockaddrDatalink = C.sizeof_struct_sockaddr_dl
|
||||
SizeofLinger = C.sizeof_struct_linger
|
||||
SizeofIPMreq = C.sizeof_struct_ip_mreq
|
||||
SizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq
|
||||
SizeofMsghdr = C.sizeof_struct_msghdr
|
||||
SizeofCmsghdr = C.sizeof_struct_cmsghdr
|
||||
SizeofInet6Pktinfo = C.sizeof_struct_in6_pktinfo
|
||||
SizeofIPv6MTUInfo = C.sizeof_struct_ip6_mtuinfo
|
||||
SizeofICMPv6Filter = C.sizeof_struct_icmp6_filter
|
||||
)
|
||||
|
||||
// Select
|
||||
|
||||
type FdSet C.fd_set
|
||||
|
||||
// Misc
|
||||
|
||||
type Utsname C.struct_utsname
|
||||
|
||||
type Ustat_t C.struct_ustat
|
||||
|
||||
const (
|
||||
AT_FDCWD = C.AT_FDCWD
|
||||
AT_SYMLINK_NOFOLLOW = C.AT_SYMLINK_NOFOLLOW
|
||||
AT_SYMLINK_FOLLOW = C.AT_SYMLINK_FOLLOW
|
||||
AT_REMOVEDIR = C.AT_REMOVEDIR
|
||||
AT_EACCESS = C.AT_EACCESS
|
||||
)
|
||||
|
||||
// Routing and interface messages
|
||||
|
||||
const (
|
||||
SizeofIfMsghdr = C.sizeof_struct_if_msghdr
|
||||
SizeofIfData = C.sizeof_struct_if_data
|
||||
SizeofIfaMsghdr = C.sizeof_struct_ifa_msghdr
|
||||
SizeofRtMsghdr = C.sizeof_struct_rt_msghdr
|
||||
SizeofRtMetrics = C.sizeof_struct_rt_metrics
|
||||
)
|
||||
|
||||
type IfMsghdr C.struct_if_msghdr
|
||||
|
||||
type IfData C.struct_if_data
|
||||
|
||||
type IfaMsghdr C.struct_ifa_msghdr
|
||||
|
||||
type RtMsghdr C.struct_rt_msghdr
|
||||
|
||||
type RtMetrics C.struct_rt_metrics
|
||||
|
||||
// Berkeley packet filter
|
||||
|
||||
const (
|
||||
SizeofBpfVersion = C.sizeof_struct_bpf_version
|
||||
SizeofBpfStat = C.sizeof_struct_bpf_stat
|
||||
SizeofBpfProgram = C.sizeof_struct_bpf_program
|
||||
SizeofBpfInsn = C.sizeof_struct_bpf_insn
|
||||
SizeofBpfHdr = C.sizeof_struct_bpf_hdr
|
||||
)
|
||||
|
||||
type BpfVersion C.struct_bpf_version
|
||||
|
||||
type BpfStat C.struct_bpf_stat
|
||||
|
||||
type BpfProgram C.struct_bpf_program
|
||||
|
||||
type BpfInsn C.struct_bpf_insn
|
||||
|
||||
type BpfTimeval C.struct_bpf_timeval
|
||||
|
||||
type BpfHdr C.struct_bpf_hdr
|
||||
|
||||
// Terminal handling
|
||||
|
||||
type Termios C.struct_termios
|
||||
|
||||
type Termio C.struct_termio
|
||||
|
||||
type Winsize C.struct_winsize
|
||||
|
||||
// poll
|
||||
|
||||
type PollFd C.struct_pollfd
|
||||
|
||||
const (
|
||||
POLLERR = C.POLLERR
|
||||
POLLHUP = C.POLLHUP
|
||||
POLLIN = C.POLLIN
|
||||
POLLNVAL = C.POLLNVAL
|
||||
POLLOUT = C.POLLOUT
|
||||
POLLPRI = C.POLLPRI
|
||||
POLLRDBAND = C.POLLRDBAND
|
||||
POLLRDNORM = C.POLLRDNORM
|
||||
POLLWRBAND = C.POLLWRBAND
|
||||
POLLWRNORM = C.POLLWRNORM
|
||||
)
|
||||
|
|
@ -1,137 +0,0 @@
|
|||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/xml"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/text/internal/gen"
|
||||
)
|
||||
|
||||
type registry struct {
|
||||
XMLName xml.Name `xml:"registry"`
|
||||
Updated string `xml:"updated"`
|
||||
Registry []struct {
|
||||
ID string `xml:"id,attr"`
|
||||
Record []struct {
|
||||
Name string `xml:"name"`
|
||||
Xref []struct {
|
||||
Type string `xml:"type,attr"`
|
||||
Data string `xml:"data,attr"`
|
||||
} `xml:"xref"`
|
||||
Desc struct {
|
||||
Data string `xml:",innerxml"`
|
||||
// Any []struct {
|
||||
// Data string `xml:",chardata"`
|
||||
// } `xml:",any"`
|
||||
// Data string `xml:",chardata"`
|
||||
} `xml:"description,"`
|
||||
MIB string `xml:"value"`
|
||||
Alias []string `xml:"alias"`
|
||||
MIME string `xml:"preferred_alias"`
|
||||
} `xml:"record"`
|
||||
} `xml:"registry"`
|
||||
}
|
||||
|
||||
func main() {
|
||||
r := gen.OpenIANAFile("assignments/character-sets/character-sets.xml")
|
||||
reg := ®istry{}
|
||||
if err := xml.NewDecoder(r).Decode(®); err != nil && err != io.EOF {
|
||||
log.Fatalf("Error decoding charset registry: %v", err)
|
||||
}
|
||||
if len(reg.Registry) == 0 || reg.Registry[0].ID != "character-sets-1" {
|
||||
log.Fatalf("Unexpected ID %s", reg.Registry[0].ID)
|
||||
}
|
||||
|
||||
w := &bytes.Buffer{}
|
||||
fmt.Fprintf(w, "const (\n")
|
||||
for _, rec := range reg.Registry[0].Record {
|
||||
constName := ""
|
||||
for _, a := range rec.Alias {
|
||||
if strings.HasPrefix(a, "cs") && strings.IndexByte(a, '-') == -1 {
|
||||
// Some of the constant definitions have comments in them. Strip those.
|
||||
constName = strings.Title(strings.SplitN(a[2:], "\n", 2)[0])
|
||||
}
|
||||
}
|
||||
if constName == "" {
|
||||
switch rec.MIB {
|
||||
case "2085":
|
||||
constName = "HZGB2312" // Not listed as alias for some reason.
|
||||
default:
|
||||
log.Fatalf("No cs alias defined for %s.", rec.MIB)
|
||||
}
|
||||
}
|
||||
if rec.MIME != "" {
|
||||
rec.MIME = fmt.Sprintf(" (MIME: %s)", rec.MIME)
|
||||
}
|
||||
fmt.Fprintf(w, "// %s is the MIB identifier with IANA name %s%s.\n//\n", constName, rec.Name, rec.MIME)
|
||||
if len(rec.Desc.Data) > 0 {
|
||||
fmt.Fprint(w, "// ")
|
||||
d := xml.NewDecoder(strings.NewReader(rec.Desc.Data))
|
||||
inElem := true
|
||||
attr := ""
|
||||
for {
|
||||
t, err := d.Token()
|
||||
if err != nil {
|
||||
if err != io.EOF {
|
||||
log.Fatal(err)
|
||||
}
|
||||
break
|
||||
}
|
||||
switch x := t.(type) {
|
||||
case xml.CharData:
|
||||
attr = "" // Don't need attribute info.
|
||||
a := bytes.Split([]byte(x), []byte("\n"))
|
||||
for i, b := range a {
|
||||
if b = bytes.TrimSpace(b); len(b) != 0 {
|
||||
if !inElem && i > 0 {
|
||||
fmt.Fprint(w, "\n// ")
|
||||
}
|
||||
inElem = false
|
||||
fmt.Fprintf(w, "%s ", string(b))
|
||||
}
|
||||
}
|
||||
case xml.StartElement:
|
||||
if x.Name.Local == "xref" {
|
||||
inElem = true
|
||||
use := false
|
||||
for _, a := range x.Attr {
|
||||
if a.Name.Local == "type" {
|
||||
use = use || a.Value != "person"
|
||||
}
|
||||
if a.Name.Local == "data" && use {
|
||||
attr = a.Value + " "
|
||||
}
|
||||
}
|
||||
}
|
||||
case xml.EndElement:
|
||||
inElem = false
|
||||
fmt.Fprint(w, attr)
|
||||
}
|
||||
}
|
||||
fmt.Fprint(w, "\n")
|
||||
}
|
||||
for _, x := range rec.Xref {
|
||||
switch x.Type {
|
||||
case "rfc":
|
||||
fmt.Fprintf(w, "// Reference: %s\n", strings.ToUpper(x.Data))
|
||||
case "uri":
|
||||
fmt.Fprintf(w, "// Reference: %s\n", x.Data)
|
||||
}
|
||||
}
|
||||
fmt.Fprintf(w, "%s MIB = %s\n", constName, rec.MIB)
|
||||
fmt.Fprintln(w)
|
||||
}
|
||||
fmt.Fprintln(w, ")")
|
||||
|
||||
gen.WriteGoFile("mib.go", "identifier", w.Bytes())
|
||||
}
|
||||
|
|
@ -1,133 +0,0 @@
|
|||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"log"
|
||||
|
||||
"golang.org/x/text/internal/gen"
|
||||
"golang.org/x/text/internal/triegen"
|
||||
"golang.org/x/text/internal/ucd"
|
||||
)
|
||||
|
||||
var outputFile = flag.String("out", "tables.go", "output file")
|
||||
|
||||
func main() {
|
||||
gen.Init()
|
||||
gen.Repackage("gen_trieval.go", "trieval.go", "bidi")
|
||||
gen.Repackage("gen_ranges.go", "ranges_test.go", "bidi")
|
||||
|
||||
genTables()
|
||||
}
|
||||
|
||||
// bidiClass names and codes taken from class "bc" in
|
||||
// https://www.unicode.org/Public/8.0.0/ucd/PropertyValueAliases.txt
|
||||
var bidiClass = map[string]Class{
|
||||
"AL": AL, // ArabicLetter
|
||||
"AN": AN, // ArabicNumber
|
||||
"B": B, // ParagraphSeparator
|
||||
"BN": BN, // BoundaryNeutral
|
||||
"CS": CS, // CommonSeparator
|
||||
"EN": EN, // EuropeanNumber
|
||||
"ES": ES, // EuropeanSeparator
|
||||
"ET": ET, // EuropeanTerminator
|
||||
"L": L, // LeftToRight
|
||||
"NSM": NSM, // NonspacingMark
|
||||
"ON": ON, // OtherNeutral
|
||||
"R": R, // RightToLeft
|
||||
"S": S, // SegmentSeparator
|
||||
"WS": WS, // WhiteSpace
|
||||
|
||||
"FSI": Control,
|
||||
"PDF": Control,
|
||||
"PDI": Control,
|
||||
"LRE": Control,
|
||||
"LRI": Control,
|
||||
"LRO": Control,
|
||||
"RLE": Control,
|
||||
"RLI": Control,
|
||||
"RLO": Control,
|
||||
}
|
||||
|
||||
func genTables() {
|
||||
if numClass > 0x0F {
|
||||
log.Fatalf("Too many Class constants (%#x > 0x0F).", numClass)
|
||||
}
|
||||
w := gen.NewCodeWriter()
|
||||
defer w.WriteVersionedGoFile(*outputFile, "bidi")
|
||||
|
||||
gen.WriteUnicodeVersion(w)
|
||||
|
||||
t := triegen.NewTrie("bidi")
|
||||
|
||||
// Build data about bracket mapping. These bits need to be or-ed with
|
||||
// any other bits.
|
||||
orMask := map[rune]uint64{}
|
||||
|
||||
xorMap := map[rune]int{}
|
||||
xorMasks := []rune{0} // First value is no-op.
|
||||
|
||||
ucd.Parse(gen.OpenUCDFile("BidiBrackets.txt"), func(p *ucd.Parser) {
|
||||
r1 := p.Rune(0)
|
||||
r2 := p.Rune(1)
|
||||
xor := r1 ^ r2
|
||||
if _, ok := xorMap[xor]; !ok {
|
||||
xorMap[xor] = len(xorMasks)
|
||||
xorMasks = append(xorMasks, xor)
|
||||
}
|
||||
entry := uint64(xorMap[xor]) << xorMaskShift
|
||||
switch p.String(2) {
|
||||
case "o":
|
||||
entry |= openMask
|
||||
case "c", "n":
|
||||
default:
|
||||
log.Fatalf("Unknown bracket class %q.", p.String(2))
|
||||
}
|
||||
orMask[r1] = entry
|
||||
})
|
||||
|
||||
w.WriteComment(`
|
||||
xorMasks contains masks to be xor-ed with brackets to get the reverse
|
||||
version.`)
|
||||
w.WriteVar("xorMasks", xorMasks)
|
||||
|
||||
done := map[rune]bool{}
|
||||
|
||||
insert := func(r rune, c Class) {
|
||||
if !done[r] {
|
||||
t.Insert(r, orMask[r]|uint64(c))
|
||||
done[r] = true
|
||||
}
|
||||
}
|
||||
|
||||
// Insert the derived BiDi properties.
|
||||
ucd.Parse(gen.OpenUCDFile("extracted/DerivedBidiClass.txt"), func(p *ucd.Parser) {
|
||||
r := p.Rune(0)
|
||||
class, ok := bidiClass[p.String(1)]
|
||||
if !ok {
|
||||
log.Fatalf("%U: Unknown BiDi class %q", r, p.String(1))
|
||||
}
|
||||
insert(r, class)
|
||||
})
|
||||
visitDefaults(insert)
|
||||
|
||||
// TODO: use sparse blocks. This would reduce table size considerably
|
||||
// from the looks of it.
|
||||
|
||||
sz, err := t.Gen(w)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
w.Size += sz
|
||||
}
|
||||
|
||||
// dummy values to make methods in gen_common compile. The real versions
|
||||
// will be generated by this file to tables.go.
|
||||
var (
|
||||
xorMasks []rune
|
||||
)
|
||||
|
|
@ -1,57 +0,0 @@
|
|||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"unicode"
|
||||
|
||||
"golang.org/x/text/internal/gen"
|
||||
"golang.org/x/text/internal/ucd"
|
||||
"golang.org/x/text/unicode/rangetable"
|
||||
)
|
||||
|
||||
// These tables are hand-extracted from:
|
||||
// https://www.unicode.org/Public/8.0.0/ucd/extracted/DerivedBidiClass.txt
|
||||
func visitDefaults(fn func(r rune, c Class)) {
|
||||
// first write default values for ranges listed above.
|
||||
visitRunes(fn, AL, []rune{
|
||||
0x0600, 0x07BF, // Arabic
|
||||
0x08A0, 0x08FF, // Arabic Extended-A
|
||||
0xFB50, 0xFDCF, // Arabic Presentation Forms
|
||||
0xFDF0, 0xFDFF,
|
||||
0xFE70, 0xFEFF,
|
||||
0x0001EE00, 0x0001EEFF, // Arabic Mathematical Alpha Symbols
|
||||
})
|
||||
visitRunes(fn, R, []rune{
|
||||
0x0590, 0x05FF, // Hebrew
|
||||
0x07C0, 0x089F, // Nko et al.
|
||||
0xFB1D, 0xFB4F,
|
||||
0x00010800, 0x00010FFF, // Cypriot Syllabary et. al.
|
||||
0x0001E800, 0x0001EDFF,
|
||||
0x0001EF00, 0x0001EFFF,
|
||||
})
|
||||
visitRunes(fn, ET, []rune{ // European Terminator
|
||||
0x20A0, 0x20Cf, // Currency symbols
|
||||
})
|
||||
rangetable.Visit(unicode.Noncharacter_Code_Point, func(r rune) {
|
||||
fn(r, BN) // Boundary Neutral
|
||||
})
|
||||
ucd.Parse(gen.OpenUCDFile("DerivedCoreProperties.txt"), func(p *ucd.Parser) {
|
||||
if p.String(1) == "Default_Ignorable_Code_Point" {
|
||||
fn(p.Rune(0), BN) // Boundary Neutral
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func visitRunes(fn func(r rune, c Class), c Class, runes []rune) {
|
||||
for i := 0; i < len(runes); i += 2 {
|
||||
lo, hi := runes[i], runes[i+1]
|
||||
for j := lo; j <= hi; j++ {
|
||||
fn(j, c)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,64 +0,0 @@
|
|||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
package main
|
||||
|
||||
// Class is the Unicode BiDi class. Each rune has a single class.
|
||||
type Class uint
|
||||
|
||||
const (
|
||||
L Class = iota // LeftToRight
|
||||
R // RightToLeft
|
||||
EN // EuropeanNumber
|
||||
ES // EuropeanSeparator
|
||||
ET // EuropeanTerminator
|
||||
AN // ArabicNumber
|
||||
CS // CommonSeparator
|
||||
B // ParagraphSeparator
|
||||
S // SegmentSeparator
|
||||
WS // WhiteSpace
|
||||
ON // OtherNeutral
|
||||
BN // BoundaryNeutral
|
||||
NSM // NonspacingMark
|
||||
AL // ArabicLetter
|
||||
Control // Control LRO - PDI
|
||||
|
||||
numClass
|
||||
|
||||
LRO // LeftToRightOverride
|
||||
RLO // RightToLeftOverride
|
||||
LRE // LeftToRightEmbedding
|
||||
RLE // RightToLeftEmbedding
|
||||
PDF // PopDirectionalFormat
|
||||
LRI // LeftToRightIsolate
|
||||
RLI // RightToLeftIsolate
|
||||
FSI // FirstStrongIsolate
|
||||
PDI // PopDirectionalIsolate
|
||||
|
||||
unknownClass = ^Class(0)
|
||||
)
|
||||
|
||||
var controlToClass = map[rune]Class{
|
||||
0x202D: LRO, // LeftToRightOverride,
|
||||
0x202E: RLO, // RightToLeftOverride,
|
||||
0x202A: LRE, // LeftToRightEmbedding,
|
||||
0x202B: RLE, // RightToLeftEmbedding,
|
||||
0x202C: PDF, // PopDirectionalFormat,
|
||||
0x2066: LRI, // LeftToRightIsolate,
|
||||
0x2067: RLI, // RightToLeftIsolate,
|
||||
0x2068: FSI, // FirstStrongIsolate,
|
||||
0x2069: PDI, // PopDirectionalIsolate,
|
||||
}
|
||||
|
||||
// A trie entry has the following bits:
|
||||
// 7..5 XOR mask for brackets
|
||||
// 4 1: Bracket open, 0: Bracket close
|
||||
// 3..0 Class type
|
||||
|
||||
const (
|
||||
openMask = 0x10
|
||||
xorMaskShift = 5
|
||||
)
|
||||
|
|
@ -1,986 +0,0 @@
|
|||
// Copyright 2011 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
// Normalization table generator.
|
||||
// Data read from the web.
|
||||
// See forminfo.go for a description of the trie values associated with each rune.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/text/internal/gen"
|
||||
"golang.org/x/text/internal/triegen"
|
||||
"golang.org/x/text/internal/ucd"
|
||||
)
|
||||
|
||||
func main() {
|
||||
gen.Init()
|
||||
loadUnicodeData()
|
||||
compactCCC()
|
||||
loadCompositionExclusions()
|
||||
completeCharFields(FCanonical)
|
||||
completeCharFields(FCompatibility)
|
||||
computeNonStarterCounts()
|
||||
verifyComputed()
|
||||
printChars()
|
||||
testDerived()
|
||||
printTestdata()
|
||||
makeTables()
|
||||
}
|
||||
|
||||
var (
|
||||
tablelist = flag.String("tables",
|
||||
"all",
|
||||
"comma-separated list of which tables to generate; "+
|
||||
"can be 'decomp', 'recomp', 'info' and 'all'")
|
||||
test = flag.Bool("test",
|
||||
false,
|
||||
"test existing tables against DerivedNormalizationProps and generate test data for regression testing")
|
||||
verbose = flag.Bool("verbose",
|
||||
false,
|
||||
"write data to stdout as it is parsed")
|
||||
)
|
||||
|
||||
const MaxChar = 0x10FFFF // anything above this shouldn't exist
|
||||
|
||||
// Quick Check properties of runes allow us to quickly
|
||||
// determine whether a rune may occur in a normal form.
|
||||
// For a given normal form, a rune may be guaranteed to occur
|
||||
// verbatim (QC=Yes), may or may not combine with another
|
||||
// rune (QC=Maybe), or may not occur (QC=No).
|
||||
type QCResult int
|
||||
|
||||
const (
|
||||
QCUnknown QCResult = iota
|
||||
QCYes
|
||||
QCNo
|
||||
QCMaybe
|
||||
)
|
||||
|
||||
func (r QCResult) String() string {
|
||||
switch r {
|
||||
case QCYes:
|
||||
return "Yes"
|
||||
case QCNo:
|
||||
return "No"
|
||||
case QCMaybe:
|
||||
return "Maybe"
|
||||
}
|
||||
return "***UNKNOWN***"
|
||||
}
|
||||
|
||||
const (
|
||||
FCanonical = iota // NFC or NFD
|
||||
FCompatibility // NFKC or NFKD
|
||||
FNumberOfFormTypes
|
||||
)
|
||||
|
||||
const (
|
||||
MComposed = iota // NFC or NFKC
|
||||
MDecomposed // NFD or NFKD
|
||||
MNumberOfModes
|
||||
)
|
||||
|
||||
// This contains only the properties we're interested in.
|
||||
type Char struct {
|
||||
name string
|
||||
codePoint rune // if zero, this index is not a valid code point.
|
||||
ccc uint8 // canonical combining class
|
||||
origCCC uint8
|
||||
excludeInComp bool // from CompositionExclusions.txt
|
||||
compatDecomp bool // it has a compatibility expansion
|
||||
|
||||
nTrailingNonStarters uint8
|
||||
nLeadingNonStarters uint8 // must be equal to trailing if non-zero
|
||||
|
||||
forms [FNumberOfFormTypes]FormInfo // For FCanonical and FCompatibility
|
||||
|
||||
state State
|
||||
}
|
||||
|
||||
var chars = make([]Char, MaxChar+1)
|
||||
var cccMap = make(map[uint8]uint8)
|
||||
|
||||
func (c Char) String() string {
|
||||
buf := new(bytes.Buffer)
|
||||
|
||||
fmt.Fprintf(buf, "%U [%s]:\n", c.codePoint, c.name)
|
||||
fmt.Fprintf(buf, " ccc: %v\n", c.ccc)
|
||||
fmt.Fprintf(buf, " excludeInComp: %v\n", c.excludeInComp)
|
||||
fmt.Fprintf(buf, " compatDecomp: %v\n", c.compatDecomp)
|
||||
fmt.Fprintf(buf, " state: %v\n", c.state)
|
||||
fmt.Fprintf(buf, " NFC:\n")
|
||||
fmt.Fprint(buf, c.forms[FCanonical])
|
||||
fmt.Fprintf(buf, " NFKC:\n")
|
||||
fmt.Fprint(buf, c.forms[FCompatibility])
|
||||
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
// In UnicodeData.txt, some ranges are marked like this:
|
||||
// 3400;<CJK Ideograph Extension A, First>;Lo;0;L;;;;;N;;;;;
|
||||
// 4DB5;<CJK Ideograph Extension A, Last>;Lo;0;L;;;;;N;;;;;
|
||||
// parseCharacter keeps a state variable indicating the weirdness.
|
||||
type State int
|
||||
|
||||
const (
|
||||
SNormal State = iota // known to be zero for the type
|
||||
SFirst
|
||||
SLast
|
||||
SMissing
|
||||
)
|
||||
|
||||
var lastChar = rune('\u0000')
|
||||
|
||||
func (c Char) isValid() bool {
|
||||
return c.codePoint != 0 && c.state != SMissing
|
||||
}
|
||||
|
||||
type FormInfo struct {
|
||||
quickCheck [MNumberOfModes]QCResult // index: MComposed or MDecomposed
|
||||
verified [MNumberOfModes]bool // index: MComposed or MDecomposed
|
||||
|
||||
combinesForward bool // May combine with rune on the right
|
||||
combinesBackward bool // May combine with rune on the left
|
||||
isOneWay bool // Never appears in result
|
||||
inDecomp bool // Some decompositions result in this char.
|
||||
decomp Decomposition
|
||||
expandedDecomp Decomposition
|
||||
}
|
||||
|
||||
func (f FormInfo) String() string {
|
||||
buf := bytes.NewBuffer(make([]byte, 0))
|
||||
|
||||
fmt.Fprintf(buf, " quickCheck[C]: %v\n", f.quickCheck[MComposed])
|
||||
fmt.Fprintf(buf, " quickCheck[D]: %v\n", f.quickCheck[MDecomposed])
|
||||
fmt.Fprintf(buf, " cmbForward: %v\n", f.combinesForward)
|
||||
fmt.Fprintf(buf, " cmbBackward: %v\n", f.combinesBackward)
|
||||
fmt.Fprintf(buf, " isOneWay: %v\n", f.isOneWay)
|
||||
fmt.Fprintf(buf, " inDecomp: %v\n", f.inDecomp)
|
||||
fmt.Fprintf(buf, " decomposition: %X\n", f.decomp)
|
||||
fmt.Fprintf(buf, " expandedDecomp: %X\n", f.expandedDecomp)
|
||||
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
type Decomposition []rune
|
||||
|
||||
func parseDecomposition(s string, skipfirst bool) (a []rune, err error) {
|
||||
decomp := strings.Split(s, " ")
|
||||
if len(decomp) > 0 && skipfirst {
|
||||
decomp = decomp[1:]
|
||||
}
|
||||
for _, d := range decomp {
|
||||
point, err := strconv.ParseUint(d, 16, 64)
|
||||
if err != nil {
|
||||
return a, err
|
||||
}
|
||||
a = append(a, rune(point))
|
||||
}
|
||||
return a, nil
|
||||
}
|
||||
|
||||
func loadUnicodeData() {
|
||||
f := gen.OpenUCDFile("UnicodeData.txt")
|
||||
defer f.Close()
|
||||
p := ucd.New(f)
|
||||
for p.Next() {
|
||||
r := p.Rune(ucd.CodePoint)
|
||||
char := &chars[r]
|
||||
|
||||
char.ccc = uint8(p.Uint(ucd.CanonicalCombiningClass))
|
||||
decmap := p.String(ucd.DecompMapping)
|
||||
|
||||
exp, err := parseDecomposition(decmap, false)
|
||||
isCompat := false
|
||||
if err != nil {
|
||||
if len(decmap) > 0 {
|
||||
exp, err = parseDecomposition(decmap, true)
|
||||
if err != nil {
|
||||
log.Fatalf(`%U: bad decomp |%v|: "%s"`, r, decmap, err)
|
||||
}
|
||||
isCompat = true
|
||||
}
|
||||
}
|
||||
|
||||
char.name = p.String(ucd.Name)
|
||||
char.codePoint = r
|
||||
char.forms[FCompatibility].decomp = exp
|
||||
if !isCompat {
|
||||
char.forms[FCanonical].decomp = exp
|
||||
} else {
|
||||
char.compatDecomp = true
|
||||
}
|
||||
if len(decmap) > 0 {
|
||||
char.forms[FCompatibility].decomp = exp
|
||||
}
|
||||
}
|
||||
if err := p.Err(); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
// compactCCC converts the sparse set of CCC values to a continguous one,
|
||||
// reducing the number of bits needed from 8 to 6.
|
||||
func compactCCC() {
|
||||
m := make(map[uint8]uint8)
|
||||
for i := range chars {
|
||||
c := &chars[i]
|
||||
m[c.ccc] = 0
|
||||
}
|
||||
cccs := []int{}
|
||||
for v, _ := range m {
|
||||
cccs = append(cccs, int(v))
|
||||
}
|
||||
sort.Ints(cccs)
|
||||
for i, c := range cccs {
|
||||
cccMap[uint8(i)] = uint8(c)
|
||||
m[uint8(c)] = uint8(i)
|
||||
}
|
||||
for i := range chars {
|
||||
c := &chars[i]
|
||||
c.origCCC = c.ccc
|
||||
c.ccc = m[c.ccc]
|
||||
}
|
||||
if len(m) >= 1<<6 {
|
||||
log.Fatalf("too many difference CCC values: %d >= 64", len(m))
|
||||
}
|
||||
}
|
||||
|
||||
// CompositionExclusions.txt has form:
|
||||
// 0958 # ...
|
||||
// See https://unicode.org/reports/tr44/ for full explanation
|
||||
func loadCompositionExclusions() {
|
||||
f := gen.OpenUCDFile("CompositionExclusions.txt")
|
||||
defer f.Close()
|
||||
p := ucd.New(f)
|
||||
for p.Next() {
|
||||
c := &chars[p.Rune(0)]
|
||||
if c.excludeInComp {
|
||||
log.Fatalf("%U: Duplicate entry in exclusions.", c.codePoint)
|
||||
}
|
||||
c.excludeInComp = true
|
||||
}
|
||||
if e := p.Err(); e != nil {
|
||||
log.Fatal(e)
|
||||
}
|
||||
}
|
||||
|
||||
// hasCompatDecomp returns true if any of the recursive
|
||||
// decompositions contains a compatibility expansion.
|
||||
// In this case, the character may not occur in NFK*.
|
||||
func hasCompatDecomp(r rune) bool {
|
||||
c := &chars[r]
|
||||
if c.compatDecomp {
|
||||
return true
|
||||
}
|
||||
for _, d := range c.forms[FCompatibility].decomp {
|
||||
if hasCompatDecomp(d) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Hangul related constants.
|
||||
const (
|
||||
HangulBase = 0xAC00
|
||||
HangulEnd = 0xD7A4 // hangulBase + Jamo combinations (19 * 21 * 28)
|
||||
|
||||
JamoLBase = 0x1100
|
||||
JamoLEnd = 0x1113
|
||||
JamoVBase = 0x1161
|
||||
JamoVEnd = 0x1176
|
||||
JamoTBase = 0x11A8
|
||||
JamoTEnd = 0x11C3
|
||||
|
||||
JamoLVTCount = 19 * 21 * 28
|
||||
JamoTCount = 28
|
||||
)
|
||||
|
||||
func isHangul(r rune) bool {
|
||||
return HangulBase <= r && r < HangulEnd
|
||||
}
|
||||
|
||||
func isHangulWithoutJamoT(r rune) bool {
|
||||
if !isHangul(r) {
|
||||
return false
|
||||
}
|
||||
r -= HangulBase
|
||||
return r < JamoLVTCount && r%JamoTCount == 0
|
||||
}
|
||||
|
||||
func ccc(r rune) uint8 {
|
||||
return chars[r].ccc
|
||||
}
|
||||
|
||||
// Insert a rune in a buffer, ordered by Canonical Combining Class.
|
||||
func insertOrdered(b Decomposition, r rune) Decomposition {
|
||||
n := len(b)
|
||||
b = append(b, 0)
|
||||
cc := ccc(r)
|
||||
if cc > 0 {
|
||||
// Use bubble sort.
|
||||
for ; n > 0; n-- {
|
||||
if ccc(b[n-1]) <= cc {
|
||||
break
|
||||
}
|
||||
b[n] = b[n-1]
|
||||
}
|
||||
}
|
||||
b[n] = r
|
||||
return b
|
||||
}
|
||||
|
||||
// Recursively decompose.
|
||||
func decomposeRecursive(form int, r rune, d Decomposition) Decomposition {
|
||||
dcomp := chars[r].forms[form].decomp
|
||||
if len(dcomp) == 0 {
|
||||
return insertOrdered(d, r)
|
||||
}
|
||||
for _, c := range dcomp {
|
||||
d = decomposeRecursive(form, c, d)
|
||||
}
|
||||
return d
|
||||
}
|
||||
|
||||
func completeCharFields(form int) {
|
||||
// Phase 0: pre-expand decomposition.
|
||||
for i := range chars {
|
||||
f := &chars[i].forms[form]
|
||||
if len(f.decomp) == 0 {
|
||||
continue
|
||||
}
|
||||
exp := make(Decomposition, 0)
|
||||
for _, c := range f.decomp {
|
||||
exp = decomposeRecursive(form, c, exp)
|
||||
}
|
||||
f.expandedDecomp = exp
|
||||
}
|
||||
|
||||
// Phase 1: composition exclusion, mark decomposition.
|
||||
for i := range chars {
|
||||
c := &chars[i]
|
||||
f := &c.forms[form]
|
||||
|
||||
// Marks script-specific exclusions and version restricted.
|
||||
f.isOneWay = c.excludeInComp
|
||||
|
||||
// Singletons
|
||||
f.isOneWay = f.isOneWay || len(f.decomp) == 1
|
||||
|
||||
// Non-starter decompositions
|
||||
if len(f.decomp) > 1 {
|
||||
chk := c.ccc != 0 || chars[f.decomp[0]].ccc != 0
|
||||
f.isOneWay = f.isOneWay || chk
|
||||
}
|
||||
|
||||
// Runes that decompose into more than two runes.
|
||||
f.isOneWay = f.isOneWay || len(f.decomp) > 2
|
||||
|
||||
if form == FCompatibility {
|
||||
f.isOneWay = f.isOneWay || hasCompatDecomp(c.codePoint)
|
||||
}
|
||||
|
||||
for _, r := range f.decomp {
|
||||
chars[r].forms[form].inDecomp = true
|
||||
}
|
||||
}
|
||||
|
||||
// Phase 2: forward and backward combining.
|
||||
for i := range chars {
|
||||
c := &chars[i]
|
||||
f := &c.forms[form]
|
||||
|
||||
if !f.isOneWay && len(f.decomp) == 2 {
|
||||
f0 := &chars[f.decomp[0]].forms[form]
|
||||
f1 := &chars[f.decomp[1]].forms[form]
|
||||
if !f0.isOneWay {
|
||||
f0.combinesForward = true
|
||||
}
|
||||
if !f1.isOneWay {
|
||||
f1.combinesBackward = true
|
||||
}
|
||||
}
|
||||
if isHangulWithoutJamoT(rune(i)) {
|
||||
f.combinesForward = true
|
||||
}
|
||||
}
|
||||
|
||||
// Phase 3: quick check values.
|
||||
for i := range chars {
|
||||
c := &chars[i]
|
||||
f := &c.forms[form]
|
||||
|
||||
switch {
|
||||
case len(f.decomp) > 0:
|
||||
f.quickCheck[MDecomposed] = QCNo
|
||||
case isHangul(rune(i)):
|
||||
f.quickCheck[MDecomposed] = QCNo
|
||||
default:
|
||||
f.quickCheck[MDecomposed] = QCYes
|
||||
}
|
||||
switch {
|
||||
case f.isOneWay:
|
||||
f.quickCheck[MComposed] = QCNo
|
||||
case (i & 0xffff00) == JamoLBase:
|
||||
f.quickCheck[MComposed] = QCYes
|
||||
if JamoLBase <= i && i < JamoLEnd {
|
||||
f.combinesForward = true
|
||||
}
|
||||
if JamoVBase <= i && i < JamoVEnd {
|
||||
f.quickCheck[MComposed] = QCMaybe
|
||||
f.combinesBackward = true
|
||||
f.combinesForward = true
|
||||
}
|
||||
if JamoTBase <= i && i < JamoTEnd {
|
||||
f.quickCheck[MComposed] = QCMaybe
|
||||
f.combinesBackward = true
|
||||
}
|
||||
case !f.combinesBackward:
|
||||
f.quickCheck[MComposed] = QCYes
|
||||
default:
|
||||
f.quickCheck[MComposed] = QCMaybe
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func computeNonStarterCounts() {
|
||||
// Phase 4: leading and trailing non-starter count
|
||||
for i := range chars {
|
||||
c := &chars[i]
|
||||
|
||||
runes := []rune{rune(i)}
|
||||
// We always use FCompatibility so that the CGJ insertion points do not
|
||||
// change for repeated normalizations with different forms.
|
||||
if exp := c.forms[FCompatibility].expandedDecomp; len(exp) > 0 {
|
||||
runes = exp
|
||||
}
|
||||
// We consider runes that combine backwards to be non-starters for the
|
||||
// purpose of Stream-Safe Text Processing.
|
||||
for _, r := range runes {
|
||||
if cr := &chars[r]; cr.ccc == 0 && !cr.forms[FCompatibility].combinesBackward {
|
||||
break
|
||||
}
|
||||
c.nLeadingNonStarters++
|
||||
}
|
||||
for i := len(runes) - 1; i >= 0; i-- {
|
||||
if cr := &chars[runes[i]]; cr.ccc == 0 && !cr.forms[FCompatibility].combinesBackward {
|
||||
break
|
||||
}
|
||||
c.nTrailingNonStarters++
|
||||
}
|
||||
if c.nTrailingNonStarters > 3 {
|
||||
log.Fatalf("%U: Decomposition with more than 3 (%d) trailing modifiers (%U)", i, c.nTrailingNonStarters, runes)
|
||||
}
|
||||
|
||||
if isHangul(rune(i)) {
|
||||
c.nTrailingNonStarters = 2
|
||||
if isHangulWithoutJamoT(rune(i)) {
|
||||
c.nTrailingNonStarters = 1
|
||||
}
|
||||
}
|
||||
|
||||
if l, t := c.nLeadingNonStarters, c.nTrailingNonStarters; l > 0 && l != t {
|
||||
log.Fatalf("%U: number of leading and trailing non-starters should be equal (%d vs %d)", i, l, t)
|
||||
}
|
||||
if t := c.nTrailingNonStarters; t > 3 {
|
||||
log.Fatalf("%U: number of trailing non-starters is %d > 3", t)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func printBytes(w io.Writer, b []byte, name string) {
|
||||
fmt.Fprintf(w, "// %s: %d bytes\n", name, len(b))
|
||||
fmt.Fprintf(w, "var %s = [...]byte {", name)
|
||||
for i, c := range b {
|
||||
switch {
|
||||
case i%64 == 0:
|
||||
fmt.Fprintf(w, "\n// Bytes %x - %x\n", i, i+63)
|
||||
case i%8 == 0:
|
||||
fmt.Fprintf(w, "\n")
|
||||
}
|
||||
fmt.Fprintf(w, "0x%.2X, ", c)
|
||||
}
|
||||
fmt.Fprint(w, "\n}\n\n")
|
||||
}
|
||||
|
||||
// See forminfo.go for format.
|
||||
func makeEntry(f *FormInfo, c *Char) uint16 {
|
||||
e := uint16(0)
|
||||
if r := c.codePoint; HangulBase <= r && r < HangulEnd {
|
||||
e |= 0x40
|
||||
}
|
||||
if f.combinesForward {
|
||||
e |= 0x20
|
||||
}
|
||||
if f.quickCheck[MDecomposed] == QCNo {
|
||||
e |= 0x4
|
||||
}
|
||||
switch f.quickCheck[MComposed] {
|
||||
case QCYes:
|
||||
case QCNo:
|
||||
e |= 0x10
|
||||
case QCMaybe:
|
||||
e |= 0x18
|
||||
default:
|
||||
log.Fatalf("Illegal quickcheck value %v.", f.quickCheck[MComposed])
|
||||
}
|
||||
e |= uint16(c.nTrailingNonStarters)
|
||||
return e
|
||||
}
|
||||
|
||||
// decompSet keeps track of unique decompositions, grouped by whether
|
||||
// the decomposition is followed by a trailing and/or leading CCC.
|
||||
type decompSet [7]map[string]bool
|
||||
|
||||
const (
|
||||
normalDecomp = iota
|
||||
firstMulti
|
||||
firstCCC
|
||||
endMulti
|
||||
firstLeadingCCC
|
||||
firstCCCZeroExcept
|
||||
firstStarterWithNLead
|
||||
lastDecomp
|
||||
)
|
||||
|
||||
var cname = []string{"firstMulti", "firstCCC", "endMulti", "firstLeadingCCC", "firstCCCZeroExcept", "firstStarterWithNLead", "lastDecomp"}
|
||||
|
||||
func makeDecompSet() decompSet {
|
||||
m := decompSet{}
|
||||
for i := range m {
|
||||
m[i] = make(map[string]bool)
|
||||
}
|
||||
return m
|
||||
}
|
||||
func (m *decompSet) insert(key int, s string) {
|
||||
m[key][s] = true
|
||||
}
|
||||
|
||||
func printCharInfoTables(w io.Writer) int {
|
||||
mkstr := func(r rune, f *FormInfo) (int, string) {
|
||||
d := f.expandedDecomp
|
||||
s := string([]rune(d))
|
||||
if max := 1 << 6; len(s) >= max {
|
||||
const msg = "%U: too many bytes in decomposition: %d >= %d"
|
||||
log.Fatalf(msg, r, len(s), max)
|
||||
}
|
||||
head := uint8(len(s))
|
||||
if f.quickCheck[MComposed] != QCYes {
|
||||
head |= 0x40
|
||||
}
|
||||
if f.combinesForward {
|
||||
head |= 0x80
|
||||
}
|
||||
s = string([]byte{head}) + s
|
||||
|
||||
lccc := ccc(d[0])
|
||||
tccc := ccc(d[len(d)-1])
|
||||
cc := ccc(r)
|
||||
if cc != 0 && lccc == 0 && tccc == 0 {
|
||||
log.Fatalf("%U: trailing and leading ccc are 0 for non-zero ccc %d", r, cc)
|
||||
}
|
||||
if tccc < lccc && lccc != 0 {
|
||||
const msg = "%U: lccc (%d) must be <= tcc (%d)"
|
||||
log.Fatalf(msg, r, lccc, tccc)
|
||||
}
|
||||
index := normalDecomp
|
||||
nTrail := chars[r].nTrailingNonStarters
|
||||
nLead := chars[r].nLeadingNonStarters
|
||||
if tccc > 0 || lccc > 0 || nTrail > 0 {
|
||||
tccc <<= 2
|
||||
tccc |= nTrail
|
||||
s += string([]byte{tccc})
|
||||
index = endMulti
|
||||
for _, r := range d[1:] {
|
||||
if ccc(r) == 0 {
|
||||
index = firstCCC
|
||||
}
|
||||
}
|
||||
if lccc > 0 || nLead > 0 {
|
||||
s += string([]byte{lccc})
|
||||
if index == firstCCC {
|
||||
log.Fatalf("%U: multi-segment decomposition not supported for decompositions with leading CCC != 0", r)
|
||||
}
|
||||
index = firstLeadingCCC
|
||||
}
|
||||
if cc != lccc {
|
||||
if cc != 0 {
|
||||
log.Fatalf("%U: for lccc != ccc, expected ccc to be 0; was %d", r, cc)
|
||||
}
|
||||
index = firstCCCZeroExcept
|
||||
}
|
||||
} else if len(d) > 1 {
|
||||
index = firstMulti
|
||||
}
|
||||
return index, s
|
||||
}
|
||||
|
||||
decompSet := makeDecompSet()
|
||||
const nLeadStr = "\x00\x01" // 0-byte length and tccc with nTrail.
|
||||
decompSet.insert(firstStarterWithNLead, nLeadStr)
|
||||
|
||||
// Store the uniqued decompositions in a byte buffer,
|
||||
// preceded by their byte length.
|
||||
for _, c := range chars {
|
||||
for _, f := range c.forms {
|
||||
if len(f.expandedDecomp) == 0 {
|
||||
continue
|
||||
}
|
||||
if f.combinesBackward {
|
||||
log.Fatalf("%U: combinesBackward and decompose", c.codePoint)
|
||||
}
|
||||
index, s := mkstr(c.codePoint, &f)
|
||||
decompSet.insert(index, s)
|
||||
}
|
||||
}
|
||||
|
||||
decompositions := bytes.NewBuffer(make([]byte, 0, 10000))
|
||||
size := 0
|
||||
positionMap := make(map[string]uint16)
|
||||
decompositions.WriteString("\000")
|
||||
fmt.Fprintln(w, "const (")
|
||||
for i, m := range decompSet {
|
||||
sa := []string{}
|
||||
for s := range m {
|
||||
sa = append(sa, s)
|
||||
}
|
||||
sort.Strings(sa)
|
||||
for _, s := range sa {
|
||||
p := decompositions.Len()
|
||||
decompositions.WriteString(s)
|
||||
positionMap[s] = uint16(p)
|
||||
}
|
||||
if cname[i] != "" {
|
||||
fmt.Fprintf(w, "%s = 0x%X\n", cname[i], decompositions.Len())
|
||||
}
|
||||
}
|
||||
fmt.Fprintln(w, "maxDecomp = 0x8000")
|
||||
fmt.Fprintln(w, ")")
|
||||
b := decompositions.Bytes()
|
||||
printBytes(w, b, "decomps")
|
||||
size += len(b)
|
||||
|
||||
varnames := []string{"nfc", "nfkc"}
|
||||
for i := 0; i < FNumberOfFormTypes; i++ {
|
||||
trie := triegen.NewTrie(varnames[i])
|
||||
|
||||
for r, c := range chars {
|
||||
f := c.forms[i]
|
||||
d := f.expandedDecomp
|
||||
if len(d) != 0 {
|
||||
_, key := mkstr(c.codePoint, &f)
|
||||
trie.Insert(rune(r), uint64(positionMap[key]))
|
||||
if c.ccc != ccc(d[0]) {
|
||||
// We assume the lead ccc of a decomposition !=0 in this case.
|
||||
if ccc(d[0]) == 0 {
|
||||
log.Fatalf("Expected leading CCC to be non-zero; ccc is %d", c.ccc)
|
||||
}
|
||||
}
|
||||
} else if c.nLeadingNonStarters > 0 && len(f.expandedDecomp) == 0 && c.ccc == 0 && !f.combinesBackward {
|
||||
// Handle cases where it can't be detected that the nLead should be equal
|
||||
// to nTrail.
|
||||
trie.Insert(c.codePoint, uint64(positionMap[nLeadStr]))
|
||||
} else if v := makeEntry(&f, &c)<<8 | uint16(c.ccc); v != 0 {
|
||||
trie.Insert(c.codePoint, uint64(0x8000|v))
|
||||
}
|
||||
}
|
||||
sz, err := trie.Gen(w, triegen.Compact(&normCompacter{name: varnames[i]}))
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
size += sz
|
||||
}
|
||||
return size
|
||||
}
|
||||
|
||||
func contains(sa []string, s string) bool {
|
||||
for _, a := range sa {
|
||||
if a == s {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func makeTables() {
|
||||
w := &bytes.Buffer{}
|
||||
|
||||
size := 0
|
||||
if *tablelist == "" {
|
||||
return
|
||||
}
|
||||
list := strings.Split(*tablelist, ",")
|
||||
if *tablelist == "all" {
|
||||
list = []string{"recomp", "info"}
|
||||
}
|
||||
|
||||
// Compute maximum decomposition size.
|
||||
max := 0
|
||||
for _, c := range chars {
|
||||
if n := len(string(c.forms[FCompatibility].expandedDecomp)); n > max {
|
||||
max = n
|
||||
}
|
||||
}
|
||||
fmt.Fprintln(w, `import "sync"`)
|
||||
fmt.Fprintln(w)
|
||||
|
||||
fmt.Fprintln(w, "const (")
|
||||
fmt.Fprintln(w, "\t// Version is the Unicode edition from which the tables are derived.")
|
||||
fmt.Fprintf(w, "\tVersion = %q\n", gen.UnicodeVersion())
|
||||
fmt.Fprintln(w)
|
||||
fmt.Fprintln(w, "\t// MaxTransformChunkSize indicates the maximum number of bytes that Transform")
|
||||
fmt.Fprintln(w, "\t// may need to write atomically for any Form. Making a destination buffer at")
|
||||
fmt.Fprintln(w, "\t// least this size ensures that Transform can always make progress and that")
|
||||
fmt.Fprintln(w, "\t// the user does not need to grow the buffer on an ErrShortDst.")
|
||||
fmt.Fprintf(w, "\tMaxTransformChunkSize = %d+maxNonStarters*4\n", len(string(0x034F))+max)
|
||||
fmt.Fprintln(w, ")\n")
|
||||
|
||||
// Print the CCC remap table.
|
||||
size += len(cccMap)
|
||||
fmt.Fprintf(w, "var ccc = [%d]uint8{", len(cccMap))
|
||||
for i := 0; i < len(cccMap); i++ {
|
||||
if i%8 == 0 {
|
||||
fmt.Fprintln(w)
|
||||
}
|
||||
fmt.Fprintf(w, "%3d, ", cccMap[uint8(i)])
|
||||
}
|
||||
fmt.Fprintln(w, "\n}\n")
|
||||
|
||||
if contains(list, "info") {
|
||||
size += printCharInfoTables(w)
|
||||
}
|
||||
|
||||
if contains(list, "recomp") {
|
||||
// Note that we use 32 bit keys, instead of 64 bit.
|
||||
// This clips the bits of three entries, but we know
|
||||
// this won't cause a collision. The compiler will catch
|
||||
// any changes made to UnicodeData.txt that introduces
|
||||
// a collision.
|
||||
// Note that the recomposition map for NFC and NFKC
|
||||
// are identical.
|
||||
|
||||
// Recomposition map
|
||||
nrentries := 0
|
||||
for _, c := range chars {
|
||||
f := c.forms[FCanonical]
|
||||
if !f.isOneWay && len(f.decomp) > 0 {
|
||||
nrentries++
|
||||
}
|
||||
}
|
||||
sz := nrentries * 8
|
||||
size += sz
|
||||
fmt.Fprintf(w, "// recompMap: %d bytes (entries only)\n", sz)
|
||||
fmt.Fprintln(w, "var recompMap map[uint32]rune")
|
||||
fmt.Fprintln(w, "var recompMapOnce sync.Once\n")
|
||||
fmt.Fprintln(w, `const recompMapPacked = "" +`)
|
||||
var buf [8]byte
|
||||
for i, c := range chars {
|
||||
f := c.forms[FCanonical]
|
||||
d := f.decomp
|
||||
if !f.isOneWay && len(d) > 0 {
|
||||
key := uint32(uint16(d[0]))<<16 + uint32(uint16(d[1]))
|
||||
binary.BigEndian.PutUint32(buf[:4], key)
|
||||
binary.BigEndian.PutUint32(buf[4:], uint32(i))
|
||||
fmt.Fprintf(w, "\t\t%q + // 0x%.8X: 0x%.8X\n", string(buf[:]), key, uint32(i))
|
||||
}
|
||||
}
|
||||
// hack so we don't have to special case the trailing plus sign
|
||||
fmt.Fprintf(w, ` ""`)
|
||||
fmt.Fprintln(w)
|
||||
}
|
||||
|
||||
fmt.Fprintf(w, "// Total size of tables: %dKB (%d bytes)\n", (size+512)/1024, size)
|
||||
gen.WriteVersionedGoFile("tables.go", "norm", w.Bytes())
|
||||
}
|
||||
|
||||
func printChars() {
|
||||
if *verbose {
|
||||
for _, c := range chars {
|
||||
if !c.isValid() || c.state == SMissing {
|
||||
continue
|
||||
}
|
||||
fmt.Println(c)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// verifyComputed does various consistency tests.
|
||||
func verifyComputed() {
|
||||
for i, c := range chars {
|
||||
for _, f := range c.forms {
|
||||
isNo := (f.quickCheck[MDecomposed] == QCNo)
|
||||
if (len(f.decomp) > 0) != isNo && !isHangul(rune(i)) {
|
||||
log.Fatalf("%U: NF*D QC must be No if rune decomposes", i)
|
||||
}
|
||||
|
||||
isMaybe := f.quickCheck[MComposed] == QCMaybe
|
||||
if f.combinesBackward != isMaybe {
|
||||
log.Fatalf("%U: NF*C QC must be Maybe if combinesBackward", i)
|
||||
}
|
||||
if len(f.decomp) > 0 && f.combinesForward && isMaybe {
|
||||
log.Fatalf("%U: NF*C QC must be Yes or No if combinesForward and decomposes", i)
|
||||
}
|
||||
|
||||
if len(f.expandedDecomp) != 0 {
|
||||
continue
|
||||
}
|
||||
if a, b := c.nLeadingNonStarters > 0, (c.ccc > 0 || f.combinesBackward); a != b {
|
||||
// We accept these runes to be treated differently (it only affects
|
||||
// segment breaking in iteration, most likely on improper use), but
|
||||
// reconsider if more characters are added.
|
||||
// U+FF9E HALFWIDTH KATAKANA VOICED SOUND MARK;Lm;0;L;<narrow> 3099;;;;N;;;;;
|
||||
// U+FF9F HALFWIDTH KATAKANA SEMI-VOICED SOUND MARK;Lm;0;L;<narrow> 309A;;;;N;;;;;
|
||||
// U+3133 HANGUL LETTER KIYEOK-SIOS;Lo;0;L;<compat> 11AA;;;;N;HANGUL LETTER GIYEOG SIOS;;;;
|
||||
// U+318E HANGUL LETTER ARAEAE;Lo;0;L;<compat> 11A1;;;;N;HANGUL LETTER ALAE AE;;;;
|
||||
// U+FFA3 HALFWIDTH HANGUL LETTER KIYEOK-SIOS;Lo;0;L;<narrow> 3133;;;;N;HALFWIDTH HANGUL LETTER GIYEOG SIOS;;;;
|
||||
// U+FFDC HALFWIDTH HANGUL LETTER I;Lo;0;L;<narrow> 3163;;;;N;;;;;
|
||||
if i != 0xFF9E && i != 0xFF9F && !(0x3133 <= i && i <= 0x318E) && !(0xFFA3 <= i && i <= 0xFFDC) {
|
||||
log.Fatalf("%U: nLead was %v; want %v", i, a, b)
|
||||
}
|
||||
}
|
||||
}
|
||||
nfc := c.forms[FCanonical]
|
||||
nfkc := c.forms[FCompatibility]
|
||||
if nfc.combinesBackward != nfkc.combinesBackward {
|
||||
log.Fatalf("%U: Cannot combine combinesBackward\n", c.codePoint)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Use values in DerivedNormalizationProps.txt to compare against the
|
||||
// values we computed.
|
||||
// DerivedNormalizationProps.txt has form:
|
||||
// 00C0..00C5 ; NFD_QC; N # ...
|
||||
// 0374 ; NFD_QC; N # ...
|
||||
// See https://unicode.org/reports/tr44/ for full explanation
|
||||
func testDerived() {
|
||||
f := gen.OpenUCDFile("DerivedNormalizationProps.txt")
|
||||
defer f.Close()
|
||||
p := ucd.New(f)
|
||||
for p.Next() {
|
||||
r := p.Rune(0)
|
||||
c := &chars[r]
|
||||
|
||||
var ftype, mode int
|
||||
qt := p.String(1)
|
||||
switch qt {
|
||||
case "NFC_QC":
|
||||
ftype, mode = FCanonical, MComposed
|
||||
case "NFD_QC":
|
||||
ftype, mode = FCanonical, MDecomposed
|
||||
case "NFKC_QC":
|
||||
ftype, mode = FCompatibility, MComposed
|
||||
case "NFKD_QC":
|
||||
ftype, mode = FCompatibility, MDecomposed
|
||||
default:
|
||||
continue
|
||||
}
|
||||
var qr QCResult
|
||||
switch p.String(2) {
|
||||
case "Y":
|
||||
qr = QCYes
|
||||
case "N":
|
||||
qr = QCNo
|
||||
case "M":
|
||||
qr = QCMaybe
|
||||
default:
|
||||
log.Fatalf(`Unexpected quick check value "%s"`, p.String(2))
|
||||
}
|
||||
if got := c.forms[ftype].quickCheck[mode]; got != qr {
|
||||
log.Printf("%U: FAILED %s (was %v need %v)\n", r, qt, got, qr)
|
||||
}
|
||||
c.forms[ftype].verified[mode] = true
|
||||
}
|
||||
if err := p.Err(); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
// Any unspecified value must be QCYes. Verify this.
|
||||
for i, c := range chars {
|
||||
for j, fd := range c.forms {
|
||||
for k, qr := range fd.quickCheck {
|
||||
if !fd.verified[k] && qr != QCYes {
|
||||
m := "%U: FAIL F:%d M:%d (was %v need Yes) %s\n"
|
||||
log.Printf(m, i, j, k, qr, c.name)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var testHeader = `const (
|
||||
Yes = iota
|
||||
No
|
||||
Maybe
|
||||
)
|
||||
|
||||
type formData struct {
|
||||
qc uint8
|
||||
combinesForward bool
|
||||
decomposition string
|
||||
}
|
||||
|
||||
type runeData struct {
|
||||
r rune
|
||||
ccc uint8
|
||||
nLead uint8
|
||||
nTrail uint8
|
||||
f [2]formData // 0: canonical; 1: compatibility
|
||||
}
|
||||
|
||||
func f(qc uint8, cf bool, dec string) [2]formData {
|
||||
return [2]formData{{qc, cf, dec}, {qc, cf, dec}}
|
||||
}
|
||||
|
||||
func g(qc, qck uint8, cf, cfk bool, d, dk string) [2]formData {
|
||||
return [2]formData{{qc, cf, d}, {qck, cfk, dk}}
|
||||
}
|
||||
|
||||
var testData = []runeData{
|
||||
`
|
||||
|
||||
func printTestdata() {
|
||||
type lastInfo struct {
|
||||
ccc uint8
|
||||
nLead uint8
|
||||
nTrail uint8
|
||||
f string
|
||||
}
|
||||
|
||||
last := lastInfo{}
|
||||
w := &bytes.Buffer{}
|
||||
fmt.Fprintf(w, testHeader)
|
||||
for r, c := range chars {
|
||||
f := c.forms[FCanonical]
|
||||
qc, cf, d := f.quickCheck[MComposed], f.combinesForward, string(f.expandedDecomp)
|
||||
f = c.forms[FCompatibility]
|
||||
qck, cfk, dk := f.quickCheck[MComposed], f.combinesForward, string(f.expandedDecomp)
|
||||
s := ""
|
||||
if d == dk && qc == qck && cf == cfk {
|
||||
s = fmt.Sprintf("f(%s, %v, %q)", qc, cf, d)
|
||||
} else {
|
||||
s = fmt.Sprintf("g(%s, %s, %v, %v, %q, %q)", qc, qck, cf, cfk, d, dk)
|
||||
}
|
||||
current := lastInfo{c.ccc, c.nLeadingNonStarters, c.nTrailingNonStarters, s}
|
||||
if last != current {
|
||||
fmt.Fprintf(w, "\t{0x%x, %d, %d, %d, %s},\n", r, c.origCCC, c.nLeadingNonStarters, c.nTrailingNonStarters, s)
|
||||
last = current
|
||||
}
|
||||
}
|
||||
fmt.Fprintln(w, "}")
|
||||
gen.WriteVersionedGoFile("data_test.go", "norm", w.Bytes())
|
||||
}
|
||||
|
|
@ -1,117 +0,0 @@
|
|||
// Copyright 2011 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
// Trie table generator.
|
||||
// Used by make*tables tools to generate a go file with trie data structures
|
||||
// for mapping UTF-8 to a 16-bit value. All but the last byte in a UTF-8 byte
|
||||
// sequence are used to lookup offsets in the index table to be used for the
|
||||
// next byte. The last byte is used to index into a table with 16-bit values.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
)
|
||||
|
||||
const maxSparseEntries = 16
|
||||
|
||||
type normCompacter struct {
|
||||
sparseBlocks [][]uint64
|
||||
sparseOffset []uint16
|
||||
sparseCount int
|
||||
name string
|
||||
}
|
||||
|
||||
func mostFrequentStride(a []uint64) int {
|
||||
counts := make(map[int]int)
|
||||
var v int
|
||||
for _, x := range a {
|
||||
if stride := int(x) - v; v != 0 && stride >= 0 {
|
||||
counts[stride]++
|
||||
}
|
||||
v = int(x)
|
||||
}
|
||||
var maxs, maxc int
|
||||
for stride, cnt := range counts {
|
||||
if cnt > maxc || (cnt == maxc && stride < maxs) {
|
||||
maxs, maxc = stride, cnt
|
||||
}
|
||||
}
|
||||
return maxs
|
||||
}
|
||||
|
||||
func countSparseEntries(a []uint64) int {
|
||||
stride := mostFrequentStride(a)
|
||||
var v, count int
|
||||
for _, tv := range a {
|
||||
if int(tv)-v != stride {
|
||||
if tv != 0 {
|
||||
count++
|
||||
}
|
||||
}
|
||||
v = int(tv)
|
||||
}
|
||||
return count
|
||||
}
|
||||
|
||||
func (c *normCompacter) Size(v []uint64) (sz int, ok bool) {
|
||||
if n := countSparseEntries(v); n <= maxSparseEntries {
|
||||
return (n+1)*4 + 2, true
|
||||
}
|
||||
return 0, false
|
||||
}
|
||||
|
||||
func (c *normCompacter) Store(v []uint64) uint32 {
|
||||
h := uint32(len(c.sparseOffset))
|
||||
c.sparseBlocks = append(c.sparseBlocks, v)
|
||||
c.sparseOffset = append(c.sparseOffset, uint16(c.sparseCount))
|
||||
c.sparseCount += countSparseEntries(v) + 1
|
||||
return h
|
||||
}
|
||||
|
||||
func (c *normCompacter) Handler() string {
|
||||
return c.name + "Sparse.lookup"
|
||||
}
|
||||
|
||||
func (c *normCompacter) Print(w io.Writer) (retErr error) {
|
||||
p := func(f string, x ...interface{}) {
|
||||
if _, err := fmt.Fprintf(w, f, x...); retErr == nil && err != nil {
|
||||
retErr = err
|
||||
}
|
||||
}
|
||||
|
||||
ls := len(c.sparseBlocks)
|
||||
p("// %sSparseOffset: %d entries, %d bytes\n", c.name, ls, ls*2)
|
||||
p("var %sSparseOffset = %#v\n\n", c.name, c.sparseOffset)
|
||||
|
||||
ns := c.sparseCount
|
||||
p("// %sSparseValues: %d entries, %d bytes\n", c.name, ns, ns*4)
|
||||
p("var %sSparseValues = [%d]valueRange {", c.name, ns)
|
||||
for i, b := range c.sparseBlocks {
|
||||
p("\n// Block %#x, offset %#x", i, c.sparseOffset[i])
|
||||
var v int
|
||||
stride := mostFrequentStride(b)
|
||||
n := countSparseEntries(b)
|
||||
p("\n{value:%#04x,lo:%#02x},", stride, uint8(n))
|
||||
for i, nv := range b {
|
||||
if int(nv)-v != stride {
|
||||
if v != 0 {
|
||||
p(",hi:%#02x},", 0x80+i-1)
|
||||
}
|
||||
if nv != 0 {
|
||||
p("\n{value:%#04x,lo:%#02x", nv, 0x80+i)
|
||||
}
|
||||
}
|
||||
v = int(nv)
|
||||
}
|
||||
if v != 0 {
|
||||
p(",hi:%#02x},", 0x80+len(b)-1)
|
||||
}
|
||||
}
|
||||
p("\n}\n\n")
|
||||
return
|
||||
}
|
||||
|
|
@ -1,115 +0,0 @@
|
|||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
// This program generates the trie for width operations. The generated table
|
||||
// includes width category information as well as the normalization mappings.
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"math"
|
||||
"unicode/utf8"
|
||||
|
||||
"golang.org/x/text/internal/gen"
|
||||
"golang.org/x/text/internal/triegen"
|
||||
)
|
||||
|
||||
// See gen_common.go for flags.
|
||||
|
||||
func main() {
|
||||
gen.Init()
|
||||
genTables()
|
||||
genTests()
|
||||
gen.Repackage("gen_trieval.go", "trieval.go", "width")
|
||||
gen.Repackage("gen_common.go", "common_test.go", "width")
|
||||
}
|
||||
|
||||
func genTables() {
|
||||
t := triegen.NewTrie("width")
|
||||
// fold and inverse mappings. See mapComment for a description of the format
|
||||
// of each entry. Add dummy value to make an index of 0 mean no mapping.
|
||||
inverse := [][4]byte{{}}
|
||||
mapping := map[[4]byte]int{[4]byte{}: 0}
|
||||
|
||||
getWidthData(func(r rune, tag elem, alt rune) {
|
||||
idx := 0
|
||||
if alt != 0 {
|
||||
var buf [4]byte
|
||||
buf[0] = byte(utf8.EncodeRune(buf[1:], alt))
|
||||
s := string(r)
|
||||
buf[buf[0]] ^= s[len(s)-1]
|
||||
var ok bool
|
||||
if idx, ok = mapping[buf]; !ok {
|
||||
idx = len(mapping)
|
||||
if idx > math.MaxUint8 {
|
||||
log.Fatalf("Index %d does not fit in a byte.", idx)
|
||||
}
|
||||
mapping[buf] = idx
|
||||
inverse = append(inverse, buf)
|
||||
}
|
||||
}
|
||||
t.Insert(r, uint64(tag|elem(idx)))
|
||||
})
|
||||
|
||||
w := &bytes.Buffer{}
|
||||
gen.WriteUnicodeVersion(w)
|
||||
|
||||
sz, err := t.Gen(w)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
sz += writeMappings(w, inverse)
|
||||
|
||||
fmt.Fprintf(w, "// Total table size %d bytes (%dKiB)\n", sz, sz/1024)
|
||||
|
||||
gen.WriteVersionedGoFile(*outputFile, "width", w.Bytes())
|
||||
}
|
||||
|
||||
const inverseDataComment = `
|
||||
// inverseData contains 4-byte entries of the following format:
|
||||
// <length> <modified UTF-8-encoded rune> <0 padding>
|
||||
// The last byte of the UTF-8-encoded rune is xor-ed with the last byte of the
|
||||
// UTF-8 encoding of the original rune. Mappings often have the following
|
||||
// pattern:
|
||||
// A -> A (U+FF21 -> U+0041)
|
||||
// B -> B (U+FF22 -> U+0042)
|
||||
// ...
|
||||
// By xor-ing the last byte the same entry can be shared by many mappings. This
|
||||
// reduces the total number of distinct entries by about two thirds.
|
||||
// The resulting entry for the aforementioned mappings is
|
||||
// { 0x01, 0xE0, 0x00, 0x00 }
|
||||
// Using this entry to map U+FF21 (UTF-8 [EF BC A1]), we get
|
||||
// E0 ^ A1 = 41.
|
||||
// Similarly, for U+FF22 (UTF-8 [EF BC A2]), we get
|
||||
// E0 ^ A2 = 42.
|
||||
// Note that because of the xor-ing, the byte sequence stored in the entry is
|
||||
// not valid UTF-8.`
|
||||
|
||||
func writeMappings(w io.Writer, data [][4]byte) int {
|
||||
fmt.Fprintln(w, inverseDataComment)
|
||||
fmt.Fprintf(w, "var inverseData = [%d][4]byte{\n", len(data))
|
||||
for _, x := range data {
|
||||
fmt.Fprintf(w, "{ 0x%02x, 0x%02x, 0x%02x, 0x%02x },\n", x[0], x[1], x[2], x[3])
|
||||
}
|
||||
fmt.Fprintln(w, "}")
|
||||
return len(data) * 4
|
||||
}
|
||||
|
||||
func genTests() {
|
||||
w := &bytes.Buffer{}
|
||||
fmt.Fprintf(w, "\nvar mapRunes = map[rune]struct{r rune; e elem}{\n")
|
||||
getWidthData(func(r rune, tag elem, alt rune) {
|
||||
if alt != 0 {
|
||||
fmt.Fprintf(w, "\t0x%X: {0x%X, 0x%X},\n", r, alt, tag)
|
||||
}
|
||||
})
|
||||
fmt.Fprintln(w, "}")
|
||||
gen.WriteGoFile("runes_test.go", "width", w.Bytes())
|
||||
}
|
||||
|
|
@ -1,96 +0,0 @@
|
|||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
package main
|
||||
|
||||
// This code is shared between the main code generator and the test code.
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"log"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/text/internal/gen"
|
||||
"golang.org/x/text/internal/ucd"
|
||||
)
|
||||
|
||||
var (
|
||||
outputFile = flag.String("out", "tables.go", "output file")
|
||||
)
|
||||
|
||||
var typeMap = map[string]elem{
|
||||
"A": tagAmbiguous,
|
||||
"N": tagNeutral,
|
||||
"Na": tagNarrow,
|
||||
"W": tagWide,
|
||||
"F": tagFullwidth,
|
||||
"H": tagHalfwidth,
|
||||
}
|
||||
|
||||
// getWidthData calls f for every entry for which it is defined.
|
||||
//
|
||||
// f may be called multiple times for the same rune. The last call to f is the
|
||||
// correct value. f is not called for all runes. The default tag type is
|
||||
// Neutral.
|
||||
func getWidthData(f func(r rune, tag elem, alt rune)) {
|
||||
// Set the default values for Unified Ideographs. In line with Annex 11,
|
||||
// we encode full ranges instead of the defined runes in Unified_Ideograph.
|
||||
for _, b := range []struct{ lo, hi rune }{
|
||||
{0x4E00, 0x9FFF}, // the CJK Unified Ideographs block,
|
||||
{0x3400, 0x4DBF}, // the CJK Unified Ideographs Externsion A block,
|
||||
{0xF900, 0xFAFF}, // the CJK Compatibility Ideographs block,
|
||||
{0x20000, 0x2FFFF}, // the Supplementary Ideographic Plane,
|
||||
{0x30000, 0x3FFFF}, // the Tertiary Ideographic Plane,
|
||||
} {
|
||||
for r := b.lo; r <= b.hi; r++ {
|
||||
f(r, tagWide, 0)
|
||||
}
|
||||
}
|
||||
|
||||
inverse := map[rune]rune{}
|
||||
maps := map[string]bool{
|
||||
"<wide>": true,
|
||||
"<narrow>": true,
|
||||
}
|
||||
|
||||
// We cannot reuse package norm's decomposition, as we need an unexpanded
|
||||
// decomposition. We make use of the opportunity to verify that the
|
||||
// decomposition type is as expected.
|
||||
ucd.Parse(gen.OpenUCDFile("UnicodeData.txt"), func(p *ucd.Parser) {
|
||||
r := p.Rune(0)
|
||||
s := strings.SplitN(p.String(ucd.DecompMapping), " ", 2)
|
||||
if !maps[s[0]] {
|
||||
return
|
||||
}
|
||||
x, err := strconv.ParseUint(s[1], 16, 32)
|
||||
if err != nil {
|
||||
log.Fatalf("Error parsing rune %q", s[1])
|
||||
}
|
||||
if inverse[r] != 0 || inverse[rune(x)] != 0 {
|
||||
log.Fatalf("Circular dependency in mapping between %U and %U", r, x)
|
||||
}
|
||||
inverse[r] = rune(x)
|
||||
inverse[rune(x)] = r
|
||||
})
|
||||
|
||||
// <rune range>;<type>
|
||||
ucd.Parse(gen.OpenUCDFile("EastAsianWidth.txt"), func(p *ucd.Parser) {
|
||||
tag, ok := typeMap[p.String(1)]
|
||||
if !ok {
|
||||
log.Fatalf("Unknown width type %q", p.String(1))
|
||||
}
|
||||
r := p.Rune(0)
|
||||
alt, ok := inverse[r]
|
||||
if tag == tagFullwidth || tag == tagHalfwidth && r != wonSign {
|
||||
tag |= tagNeedsFold
|
||||
if !ok {
|
||||
log.Fatalf("Narrow or wide rune %U has no decomposition", r)
|
||||
}
|
||||
}
|
||||
f(r, tag, alt)
|
||||
})
|
||||
}
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
package main
|
||||
|
||||
// elem is an entry of the width trie. The high byte is used to encode the type
|
||||
// of the rune. The low byte is used to store the index to a mapping entry in
|
||||
// the inverseData array.
|
||||
type elem uint16
|
||||
|
||||
const (
|
||||
tagNeutral elem = iota << typeShift
|
||||
tagAmbiguous
|
||||
tagWide
|
||||
tagNarrow
|
||||
tagFullwidth
|
||||
tagHalfwidth
|
||||
)
|
||||
|
||||
const (
|
||||
numTypeBits = 3
|
||||
typeShift = 16 - numTypeBits
|
||||
|
||||
// tagNeedsFold is true for all fullwidth and halfwidth runes except for
|
||||
// the Won sign U+20A9.
|
||||
tagNeedsFold = 0x1000
|
||||
|
||||
// The Korean Won sign is halfwidth, but SHOULD NOT be mapped to a wide
|
||||
// variant.
|
||||
wonSign rune = 0x20A9
|
||||
)
|
||||
|
|
@ -1,99 +0,0 @@
|
|||
// Copyright 2017 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
// The gcexportdata command is a diagnostic tool that displays the
|
||||
// contents of gc export data files.
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"go/token"
|
||||
"go/types"
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"golang.org/x/tools/go/gcexportdata"
|
||||
"golang.org/x/tools/go/types/typeutil"
|
||||
)
|
||||
|
||||
var packageFlag = flag.String("package", "", "alternative package to print")
|
||||
|
||||
func main() {
|
||||
log.SetPrefix("gcexportdata: ")
|
||||
log.SetFlags(0)
|
||||
flag.Usage = func() {
|
||||
fmt.Fprintln(os.Stderr, "usage: gcexportdata [-package path] file.a")
|
||||
}
|
||||
flag.Parse()
|
||||
if flag.NArg() != 1 {
|
||||
flag.Usage()
|
||||
os.Exit(2)
|
||||
}
|
||||
filename := flag.Args()[0]
|
||||
|
||||
f, err := os.Open(filename)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
r, err := gcexportdata.NewReader(f)
|
||||
if err != nil {
|
||||
log.Fatalf("%s: %s", filename, err)
|
||||
}
|
||||
|
||||
// Decode the package.
|
||||
const primary = "<primary>"
|
||||
imports := make(map[string]*types.Package)
|
||||
fset := token.NewFileSet()
|
||||
pkg, err := gcexportdata.Read(r, fset, imports, primary)
|
||||
if err != nil {
|
||||
log.Fatalf("%s: %s", filename, err)
|
||||
}
|
||||
|
||||
// Optionally select an indirectly mentioned package.
|
||||
if *packageFlag != "" {
|
||||
pkg = imports[*packageFlag]
|
||||
if pkg == nil {
|
||||
fmt.Fprintf(os.Stderr, "export data file %s does not mention %s; has:\n",
|
||||
filename, *packageFlag)
|
||||
for p := range imports {
|
||||
if p != primary {
|
||||
fmt.Fprintf(os.Stderr, "\t%s\n", p)
|
||||
}
|
||||
}
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
// Print all package-level declarations, including non-exported ones.
|
||||
fmt.Printf("package %s\n", pkg.Name())
|
||||
for _, imp := range pkg.Imports() {
|
||||
fmt.Printf("import %q\n", imp.Path())
|
||||
}
|
||||
qual := func(p *types.Package) string {
|
||||
if pkg == p {
|
||||
return ""
|
||||
}
|
||||
return p.Name()
|
||||
}
|
||||
scope := pkg.Scope()
|
||||
for _, name := range scope.Names() {
|
||||
obj := scope.Lookup(name)
|
||||
fmt.Printf("%s: %s\n",
|
||||
fset.Position(obj.Pos()),
|
||||
types.ObjectString(obj, qual))
|
||||
|
||||
// For types, print each method.
|
||||
if _, ok := obj.(*types.TypeName); ok {
|
||||
for _, method := range typeutil.IntuitiveMethodSet(obj.Type(), nil) {
|
||||
fmt.Printf("%s: %s\n",
|
||||
fset.Position(method.Obj().Pos()),
|
||||
types.SelectionString(method, qual))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,173 +0,0 @@
|
|||
// +build ignore
|
||||
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Command mkindex creates the file "pkgindex.go" containing an index of the Go
|
||||
// standard library. The file is intended to be built as part of the imports
|
||||
// package, so that the package may be used in environments where a GOROOT is
|
||||
// not available (such as App Engine).
|
||||
package imports
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"go/build"
|
||||
"go/format"
|
||||
"go/parser"
|
||||
"go/token"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var (
|
||||
pkgIndex = make(map[string][]pkg)
|
||||
exports = make(map[string]map[string]bool)
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Don't use GOPATH.
|
||||
ctx := build.Default
|
||||
ctx.GOPATH = ""
|
||||
|
||||
// Populate pkgIndex global from GOROOT.
|
||||
for _, path := range ctx.SrcDirs() {
|
||||
f, err := os.Open(path)
|
||||
if err != nil {
|
||||
log.Print(err)
|
||||
continue
|
||||
}
|
||||
children, err := f.Readdir(-1)
|
||||
f.Close()
|
||||
if err != nil {
|
||||
log.Print(err)
|
||||
continue
|
||||
}
|
||||
for _, child := range children {
|
||||
if child.IsDir() {
|
||||
loadPkg(path, child.Name())
|
||||
}
|
||||
}
|
||||
}
|
||||
// Populate exports global.
|
||||
for _, ps := range pkgIndex {
|
||||
for _, p := range ps {
|
||||
e := loadExports(p.dir)
|
||||
if e != nil {
|
||||
exports[p.dir] = e
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Construct source file.
|
||||
var buf bytes.Buffer
|
||||
fmt.Fprint(&buf, pkgIndexHead)
|
||||
fmt.Fprintf(&buf, "var pkgIndexMaster = %#v\n", pkgIndex)
|
||||
fmt.Fprintf(&buf, "var exportsMaster = %#v\n", exports)
|
||||
src := buf.Bytes()
|
||||
|
||||
// Replace main.pkg type name with pkg.
|
||||
src = bytes.Replace(src, []byte("main.pkg"), []byte("pkg"), -1)
|
||||
// Replace actual GOROOT with "/go".
|
||||
src = bytes.Replace(src, []byte(ctx.GOROOT), []byte("/go"), -1)
|
||||
// Add some line wrapping.
|
||||
src = bytes.Replace(src, []byte("}, "), []byte("},\n"), -1)
|
||||
src = bytes.Replace(src, []byte("true, "), []byte("true,\n"), -1)
|
||||
|
||||
var err error
|
||||
src, err = format.Source(src)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
// Write out source file.
|
||||
err = ioutil.WriteFile("pkgindex.go", src, 0644)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
const pkgIndexHead = `package imports
|
||||
|
||||
func init() {
|
||||
pkgIndexOnce.Do(func() {
|
||||
pkgIndex.m = pkgIndexMaster
|
||||
})
|
||||
loadExports = func(dir string) map[string]bool {
|
||||
return exportsMaster[dir]
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
type pkg struct {
|
||||
importpath string // full pkg import path, e.g. "net/http"
|
||||
dir string // absolute file path to pkg directory e.g. "/usr/lib/go/src/fmt"
|
||||
}
|
||||
|
||||
var fset = token.NewFileSet()
|
||||
|
||||
func loadPkg(root, importpath string) {
|
||||
shortName := path.Base(importpath)
|
||||
if shortName == "testdata" {
|
||||
return
|
||||
}
|
||||
|
||||
dir := filepath.Join(root, importpath)
|
||||
pkgIndex[shortName] = append(pkgIndex[shortName], pkg{
|
||||
importpath: importpath,
|
||||
dir: dir,
|
||||
})
|
||||
|
||||
pkgDir, err := os.Open(dir)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
children, err := pkgDir.Readdir(-1)
|
||||
pkgDir.Close()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
for _, child := range children {
|
||||
name := child.Name()
|
||||
if name == "" {
|
||||
continue
|
||||
}
|
||||
if c := name[0]; c == '.' || ('0' <= c && c <= '9') {
|
||||
continue
|
||||
}
|
||||
if child.IsDir() {
|
||||
loadPkg(root, filepath.Join(importpath, name))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func loadExports(dir string) map[string]bool {
|
||||
exports := make(map[string]bool)
|
||||
buildPkg, err := build.ImportDir(dir, 0)
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), "no buildable Go source files in") {
|
||||
return nil
|
||||
}
|
||||
log.Printf("could not import %q: %v", dir, err)
|
||||
return nil
|
||||
}
|
||||
for _, file := range buildPkg.GoFiles {
|
||||
f, err := parser.ParseFile(fset, filepath.Join(dir, file), nil, 0)
|
||||
if err != nil {
|
||||
log.Printf("could not parse %q: %v", file, err)
|
||||
continue
|
||||
}
|
||||
for name := range f.Scope.Objects {
|
||||
if ast.IsExported(name) {
|
||||
exports[name] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
return exports
|
||||
}
|
||||
|
|
@ -1,128 +0,0 @@
|
|||
// +build ignore
|
||||
|
||||
// mkstdlib generates the zstdlib.go file, containing the Go standard
|
||||
// library API symbols. It's baked into the binary to avoid scanning
|
||||
// GOPATH in the common case.
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"fmt"
|
||||
"go/format"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"runtime"
|
||||
"sort"
|
||||
)
|
||||
|
||||
func mustOpen(name string) io.Reader {
|
||||
f, err := os.Open(name)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
return f
|
||||
}
|
||||
|
||||
func api(base string) string {
|
||||
return filepath.Join(runtime.GOROOT(), "api", base)
|
||||
}
|
||||
|
||||
var sym = regexp.MustCompile(`^pkg (\S+).*?, (?:var|func|type|const) ([A-Z]\w*)`)
|
||||
|
||||
var unsafeSyms = map[string]bool{"Alignof": true, "ArbitraryType": true, "Offsetof": true, "Pointer": true, "Sizeof": true}
|
||||
|
||||
func main() {
|
||||
var buf bytes.Buffer
|
||||
outf := func(format string, args ...interface{}) {
|
||||
fmt.Fprintf(&buf, format, args...)
|
||||
}
|
||||
outf("// Code generated by mkstdlib.go. DO NOT EDIT.\n\n")
|
||||
outf("package imports\n")
|
||||
outf("var stdlib = map[string][]string{\n")
|
||||
f := io.MultiReader(
|
||||
mustOpen(api("go1.txt")),
|
||||
mustOpen(api("go1.1.txt")),
|
||||
mustOpen(api("go1.2.txt")),
|
||||
mustOpen(api("go1.3.txt")),
|
||||
mustOpen(api("go1.4.txt")),
|
||||
mustOpen(api("go1.5.txt")),
|
||||
mustOpen(api("go1.6.txt")),
|
||||
mustOpen(api("go1.7.txt")),
|
||||
mustOpen(api("go1.8.txt")),
|
||||
mustOpen(api("go1.9.txt")),
|
||||
mustOpen(api("go1.10.txt")),
|
||||
mustOpen(api("go1.11.txt")),
|
||||
mustOpen(api("go1.12.txt")),
|
||||
mustOpen(api("go1.13.txt")),
|
||||
|
||||
// The API of the syscall/js package needs to be computed explicitly,
|
||||
// because it's not included in the GOROOT/api/go1.*.txt files at this time.
|
||||
syscallJSAPI(),
|
||||
)
|
||||
sc := bufio.NewScanner(f)
|
||||
|
||||
pkgs := map[string]map[string]bool{
|
||||
"unsafe": unsafeSyms,
|
||||
}
|
||||
paths := []string{"unsafe"}
|
||||
|
||||
for sc.Scan() {
|
||||
l := sc.Text()
|
||||
if m := sym.FindStringSubmatch(l); m != nil {
|
||||
path, sym := m[1], m[2]
|
||||
|
||||
if _, ok := pkgs[path]; !ok {
|
||||
pkgs[path] = map[string]bool{}
|
||||
paths = append(paths, path)
|
||||
}
|
||||
pkgs[path][sym] = true
|
||||
}
|
||||
}
|
||||
if err := sc.Err(); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
sort.Strings(paths)
|
||||
for _, path := range paths {
|
||||
outf("\t%q: []string{\n", path)
|
||||
pkg := pkgs[path]
|
||||
var syms []string
|
||||
for sym := range pkg {
|
||||
syms = append(syms, sym)
|
||||
}
|
||||
sort.Strings(syms)
|
||||
for _, sym := range syms {
|
||||
outf("\t\t%q,\n", sym)
|
||||
}
|
||||
outf("},\n")
|
||||
}
|
||||
outf("}\n")
|
||||
fmtbuf, err := format.Source(buf.Bytes())
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
err = ioutil.WriteFile("zstdlib.go", fmtbuf, 0666)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
// syscallJSAPI returns the API of the syscall/js package.
|
||||
// It's computed from the contents of $(go env GOROOT)/src/syscall/js.
|
||||
func syscallJSAPI() io.Reader {
|
||||
var exeSuffix string
|
||||
if runtime.GOOS == "windows" {
|
||||
exeSuffix = ".exe"
|
||||
}
|
||||
cmd := exec.Command("go"+exeSuffix, "run", "cmd/api", "-contexts", "js-wasm", "syscall/js")
|
||||
out, err := cmd.Output()
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
return bytes.NewReader(out)
|
||||
}
|
||||
|
|
@ -1,40 +0,0 @@
|
|||
load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"doc.go",
|
||||
"exec.go",
|
||||
"fake.go",
|
||||
"mount.go",
|
||||
"mount_helper_common.go",
|
||||
"mount_helper_unix.go",
|
||||
"mount_helper_windows.go",
|
||||
"mount_linux.go",
|
||||
"mount_unsupported.go",
|
||||
"mount_windows.go",
|
||||
],
|
||||
importmap = "k8s.io/kops/vendor/k8s.io/kubernetes/pkg/util/mount",
|
||||
importpath = "k8s.io/kubernetes/pkg/util/mount",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//vendor/k8s.io/klog:go_default_library",
|
||||
"//vendor/k8s.io/utils/exec:go_default_library",
|
||||
] + select({
|
||||
"@io_bazel_rules_go//go/platform:android": [
|
||||
"//vendor/golang.org/x/sys/unix:go_default_library",
|
||||
"//vendor/k8s.io/utils/io:go_default_library",
|
||||
"//vendor/k8s.io/utils/path:go_default_library",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:linux": [
|
||||
"//vendor/golang.org/x/sys/unix:go_default_library",
|
||||
"//vendor/k8s.io/utils/io:go_default_library",
|
||||
"//vendor/k8s.io/utils/path:go_default_library",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:windows": [
|
||||
"//vendor/k8s.io/utils/keymutex:go_default_library",
|
||||
"//vendor/k8s.io/utils/path:go_default_library",
|
||||
],
|
||||
"//conditions:default": [],
|
||||
}),
|
||||
)
|
||||
|
|
@ -1,50 +0,0 @@
|
|||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
package mount
|
||||
|
||||
import "k8s.io/utils/exec"
|
||||
|
||||
func NewOsExec() Exec {
|
||||
return &osExec{}
|
||||
}
|
||||
|
||||
// Real implementation of Exec interface that uses simple util.Exec
|
||||
type osExec struct{}
|
||||
|
||||
var _ Exec = &osExec{}
|
||||
|
||||
func (e *osExec) Run(cmd string, args ...string) ([]byte, error) {
|
||||
exe := exec.New()
|
||||
return exe.Command(cmd, args...).CombinedOutput()
|
||||
}
|
||||
|
||||
func NewFakeExec(run runHook) *FakeExec {
|
||||
return &FakeExec{runHook: run}
|
||||
}
|
||||
|
||||
// Fake for testing.
|
||||
type FakeExec struct {
|
||||
runHook runHook
|
||||
}
|
||||
type runHook func(cmd string, args ...string) ([]byte, error)
|
||||
|
||||
func (f *FakeExec) Run(cmd string, args ...string) ([]byte, error) {
|
||||
if f.runHook != nil {
|
||||
return f.runHook(cmd, args...)
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
// +build !windows
|
||||
|
||||
/*
|
||||
Copyright 2019 The Kubernetes Authors.
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
package mount
|
||||
|
||||
import (
|
||||
"os"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
// IsCorruptedMnt return true if err is about corrupted mount point
|
||||
func IsCorruptedMnt(err error) bool {
|
||||
if err == nil {
|
||||
return false
|
||||
}
|
||||
var underlyingError error
|
||||
switch pe := err.(type) {
|
||||
case nil:
|
||||
return false
|
||||
case *os.PathError:
|
||||
underlyingError = pe.Err
|
||||
case *os.LinkError:
|
||||
underlyingError = pe.Err
|
||||
case *os.SyscallError:
|
||||
underlyingError = pe.Err
|
||||
}
|
||||
|
||||
return underlyingError == syscall.ENOTCONN || underlyingError == syscall.ESTALE || underlyingError == syscall.EIO || underlyingError == syscall.EACCES
|
||||
}
|
||||
|
|
@ -1,123 +0,0 @@
|
|||
// +build !linux,!windows
|
||||
|
||||
/*
|
||||
Copyright 2014 The Kubernetes Authors.
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
package mount
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"os"
|
||||
)
|
||||
|
||||
type Mounter struct {
|
||||
mounterPath string
|
||||
}
|
||||
|
||||
var unsupportedErr = errors.New("util/mount on this platform is not supported")
|
||||
|
||||
// New returns a mount.Interface for the current system.
|
||||
// It provides options to override the default mounter behavior.
|
||||
// mounterPath allows using an alternative to `/bin/mount` for mounting.
|
||||
func New(mounterPath string) Interface {
|
||||
return &Mounter{
|
||||
mounterPath: mounterPath,
|
||||
}
|
||||
}
|
||||
|
||||
func (mounter *Mounter) Mount(source string, target string, fstype string, options []string) error {
|
||||
return unsupportedErr
|
||||
}
|
||||
|
||||
func (mounter *Mounter) Unmount(target string) error {
|
||||
return unsupportedErr
|
||||
}
|
||||
|
||||
func (mounter *Mounter) List() ([]MountPoint, error) {
|
||||
return []MountPoint{}, unsupportedErr
|
||||
}
|
||||
|
||||
func (mounter *Mounter) IsMountPointMatch(mp MountPoint, dir string) bool {
|
||||
return (mp.Path == dir)
|
||||
}
|
||||
|
||||
func (mounter *Mounter) IsLikelyNotMountPoint(file string) (bool, error) {
|
||||
return true, unsupportedErr
|
||||
}
|
||||
|
||||
func (mounter *Mounter) GetDeviceNameFromMount(mountPath, pluginMountDir string) (string, error) {
|
||||
return "", unsupportedErr
|
||||
}
|
||||
|
||||
func getDeviceNameFromMount(mounter Interface, mountPath, pluginMountDir string) (string, error) {
|
||||
return "", unsupportedErr
|
||||
}
|
||||
|
||||
func (mounter *Mounter) DeviceOpened(pathname string) (bool, error) {
|
||||
return false, unsupportedErr
|
||||
}
|
||||
|
||||
func (mounter *Mounter) PathIsDevice(pathname string) (bool, error) {
|
||||
return true, unsupportedErr
|
||||
}
|
||||
|
||||
func (mounter *Mounter) MakeRShared(path string) error {
|
||||
return unsupportedErr
|
||||
}
|
||||
|
||||
func (mounter *SafeFormatAndMount) formatAndMount(source string, target string, fstype string, options []string) error {
|
||||
return mounter.Interface.Mount(source, target, fstype, options)
|
||||
}
|
||||
|
||||
func (mounter *SafeFormatAndMount) diskLooksUnformatted(disk string) (bool, error) {
|
||||
return true, unsupportedErr
|
||||
}
|
||||
|
||||
func (mounter *Mounter) GetFileType(pathname string) (FileType, error) {
|
||||
return FileType("fake"), unsupportedErr
|
||||
}
|
||||
|
||||
func (mounter *Mounter) MakeDir(pathname string) error {
|
||||
return unsupportedErr
|
||||
}
|
||||
|
||||
func (mounter *Mounter) MakeFile(pathname string) error {
|
||||
return unsupportedErr
|
||||
}
|
||||
|
||||
func (mounter *Mounter) ExistsPath(pathname string) (bool, error) {
|
||||
return true, errors.New("not implemented")
|
||||
}
|
||||
|
||||
func (mounter *Mounter) EvalHostSymlinks(pathname string) (string, error) {
|
||||
return "", unsupportedErr
|
||||
}
|
||||
|
||||
func (mounter *Mounter) GetMountRefs(pathname string) ([]string, error) {
|
||||
return nil, errors.New("not implemented")
|
||||
}
|
||||
|
||||
func (mounter *Mounter) GetFSGroup(pathname string) (int64, error) {
|
||||
return -1, errors.New("not implemented")
|
||||
}
|
||||
|
||||
func (mounter *Mounter) GetSELinuxSupport(pathname string) (bool, error) {
|
||||
return false, errors.New("not implemented")
|
||||
}
|
||||
|
||||
func (mounter *Mounter) GetMode(pathname string) (os.FileMode, error) {
|
||||
return 0, errors.New("not implemented")
|
||||
}
|
||||
|
|
@ -1,345 +0,0 @@
|
|||
// +build linux
|
||||
|
||||
/*
|
||||
Copyright 2014 The Kubernetes Authors.
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
package nsenter
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"k8s.io/klog"
|
||||
"k8s.io/kubernetes/pkg/util/mount"
|
||||
"k8s.io/utils/nsenter"
|
||||
utilpath "k8s.io/utils/path"
|
||||
)
|
||||
|
||||
const (
|
||||
// hostProcMountsPath is the default mount path for rootfs
|
||||
hostProcMountsPath = "/rootfs/proc/1/mounts"
|
||||
// hostProcMountinfoPath is the default mount info path for rootfs
|
||||
hostProcMountinfoPath = "/rootfs/proc/1/mountinfo"
|
||||
)
|
||||
|
||||
// Mounter implements mount.Interface
|
||||
// Currently, all docker containers receive their own mount namespaces.
|
||||
// Mounter works by executing nsenter to run commands in
|
||||
// the host's mount namespace.
|
||||
type Mounter struct {
|
||||
ne *nsenter.Nsenter
|
||||
// rootDir is location of /var/lib/kubelet directory.
|
||||
rootDir string
|
||||
}
|
||||
|
||||
// NewMounter creates a new mounter for kubelet that runs as a container.
|
||||
func NewMounter(rootDir string, ne *nsenter.Nsenter) *Mounter {
|
||||
return &Mounter{
|
||||
rootDir: rootDir,
|
||||
ne: ne,
|
||||
}
|
||||
}
|
||||
|
||||
// Mounter implements mount.Interface
|
||||
var _ = mount.Interface(&Mounter{})
|
||||
|
||||
// Mount runs mount(8) in the host's root mount namespace. Aside from this
|
||||
// aspect, Mount has the same semantics as the mounter returned by mount.New()
|
||||
func (n *Mounter) Mount(source string, target string, fstype string, options []string) error {
|
||||
bind, bindOpts, bindRemountOpts := mount.IsBind(options)
|
||||
|
||||
if bind {
|
||||
err := n.doNsenterMount(source, target, fstype, bindOpts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return n.doNsenterMount(source, target, fstype, bindRemountOpts)
|
||||
}
|
||||
|
||||
return n.doNsenterMount(source, target, fstype, options)
|
||||
}
|
||||
|
||||
// doNsenterMount nsenters the host's mount namespace and performs the
|
||||
// requested mount.
|
||||
func (n *Mounter) doNsenterMount(source, target, fstype string, options []string) error {
|
||||
klog.V(5).Infof("nsenter mount %s %s %s %v", source, target, fstype, options)
|
||||
cmd, args := n.makeNsenterArgs(source, target, fstype, options)
|
||||
outputBytes, err := n.ne.Exec(cmd, args).CombinedOutput()
|
||||
if len(outputBytes) != 0 {
|
||||
klog.V(5).Infof("Output of mounting %s to %s: %v", source, target, string(outputBytes))
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// makeNsenterArgs makes a list of argument to nsenter in order to do the
|
||||
// requested mount.
|
||||
func (n *Mounter) makeNsenterArgs(source, target, fstype string, options []string) (string, []string) {
|
||||
mountCmd := n.ne.AbsHostPath("mount")
|
||||
mountArgs := mount.MakeMountArgs(source, target, fstype, options)
|
||||
|
||||
if systemdRunPath, hasSystemd := n.ne.SupportsSystemd(); hasSystemd {
|
||||
// Complete command line:
|
||||
// nsenter --mount=/rootfs/proc/1/ns/mnt -- /bin/systemd-run --description=... --scope -- /bin/mount -t <type> <what> <where>
|
||||
// Expected flow is:
|
||||
// * nsenter breaks out of container's mount namespace and executes
|
||||
// host's systemd-run.
|
||||
// * systemd-run creates a transient scope (=~ cgroup) and executes its
|
||||
// argument (/bin/mount) there.
|
||||
// * mount does its job, forks a fuse daemon if necessary and finishes.
|
||||
// (systemd-run --scope finishes at this point, returning mount's exit
|
||||
// code and stdout/stderr - thats one of --scope benefits).
|
||||
// * systemd keeps the fuse daemon running in the scope (i.e. in its own
|
||||
// cgroup) until the fuse daemon dies (another --scope benefit).
|
||||
// Kubelet container can be restarted and the fuse daemon survives.
|
||||
// * When the daemon dies (e.g. during unmount) systemd removes the
|
||||
// scope automatically.
|
||||
mountCmd, mountArgs = mount.AddSystemdScope(systemdRunPath, target, mountCmd, mountArgs)
|
||||
} else {
|
||||
// Fall back to simple mount when the host has no systemd.
|
||||
// Complete command line:
|
||||
// nsenter --mount=/rootfs/proc/1/ns/mnt -- /bin/mount -t <type> <what> <where>
|
||||
// Expected flow is:
|
||||
// * nsenter breaks out of container's mount namespace and executes host's /bin/mount.
|
||||
// * mount does its job, forks a fuse daemon if necessary and finishes.
|
||||
// * Any fuse daemon runs in cgroup of kubelet docker container,
|
||||
// restart of kubelet container will kill it!
|
||||
|
||||
// No code here, mountCmd and mountArgs use /bin/mount
|
||||
}
|
||||
|
||||
return mountCmd, mountArgs
|
||||
}
|
||||
|
||||
// Unmount runs umount(8) in the host's mount namespace.
|
||||
func (n *Mounter) Unmount(target string) error {
|
||||
args := []string{target}
|
||||
// No need to execute systemd-run here, it's enough that unmount is executed
|
||||
// in the host's mount namespace. It will finish appropriate fuse daemon(s)
|
||||
// running in any scope.
|
||||
klog.V(5).Infof("nsenter unmount args: %v", args)
|
||||
outputBytes, err := n.ne.Exec("umount", args).CombinedOutput()
|
||||
if len(outputBytes) != 0 {
|
||||
klog.V(5).Infof("Output of unmounting %s: %v", target, string(outputBytes))
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// List returns a list of all mounted filesystems in the host's mount namespace.
|
||||
func (*Mounter) List() ([]mount.MountPoint, error) {
|
||||
return mount.ListProcMounts(hostProcMountsPath)
|
||||
}
|
||||
|
||||
// IsMountPointMatch tests if dir and mp are the same path
|
||||
func (*Mounter) IsMountPointMatch(mp mount.MountPoint, dir string) bool {
|
||||
deletedDir := fmt.Sprintf("%s\\040(deleted)", dir)
|
||||
return (mp.Path == dir) || (mp.Path == deletedDir)
|
||||
}
|
||||
|
||||
// IsLikelyNotMountPoint determines whether a path is a mountpoint by calling findmnt
|
||||
// in the host's root mount namespace.
|
||||
func (n *Mounter) IsLikelyNotMountPoint(file string) (bool, error) {
|
||||
file, err := filepath.Abs(file)
|
||||
if err != nil {
|
||||
return true, err
|
||||
}
|
||||
|
||||
// Check the directory exists
|
||||
if _, err = os.Stat(file); os.IsNotExist(err) {
|
||||
klog.V(5).Infof("findmnt: directory %s does not exist", file)
|
||||
return true, err
|
||||
}
|
||||
|
||||
// Resolve any symlinks in file, kernel would do the same and use the resolved path in /proc/mounts
|
||||
resolvedFile, err := n.EvalHostSymlinks(file)
|
||||
if err != nil {
|
||||
return true, err
|
||||
}
|
||||
|
||||
// Add --first-only option: since we are testing for the absence of a mountpoint, it is sufficient to get only
|
||||
// the first of multiple possible mountpoints using --first-only.
|
||||
// Also add fstype output to make sure that the output of target file will give the full path
|
||||
// TODO: Need more refactoring for this function. Track the solution with issue #26996
|
||||
args := []string{"-o", "target,fstype", "--noheadings", "--first-only", "--target", resolvedFile}
|
||||
klog.V(5).Infof("nsenter findmnt args: %v", args)
|
||||
out, err := n.ne.Exec("findmnt", args).CombinedOutput()
|
||||
if err != nil {
|
||||
klog.V(2).Infof("Failed findmnt command for path %s: %s %v", resolvedFile, out, err)
|
||||
// Different operating systems behave differently for paths which are not mount points.
|
||||
// On older versions (e.g. 2.20.1) we'd get error, on newer ones (e.g. 2.26.2) we'd get "/".
|
||||
// It's safer to assume that it's not a mount point.
|
||||
return true, nil
|
||||
}
|
||||
mountTarget, err := parseFindMnt(string(out))
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
klog.V(5).Infof("IsLikelyNotMountPoint findmnt output for path %s: %v:", resolvedFile, mountTarget)
|
||||
|
||||
if mountTarget == resolvedFile {
|
||||
klog.V(5).Infof("IsLikelyNotMountPoint: %s is a mount point", resolvedFile)
|
||||
return false, nil
|
||||
}
|
||||
klog.V(5).Infof("IsLikelyNotMountPoint: %s is not a mount point", resolvedFile)
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// parse output of "findmnt -o target,fstype" and return just the target
|
||||
func parseFindMnt(out string) (string, error) {
|
||||
// cut trailing newline
|
||||
out = strings.TrimSuffix(out, "\n")
|
||||
// cut everything after the last space - it's the filesystem type
|
||||
i := strings.LastIndex(out, " ")
|
||||
if i == -1 {
|
||||
return "", fmt.Errorf("error parsing findmnt output, expected at least one space: %q", out)
|
||||
}
|
||||
return out[:i], nil
|
||||
}
|
||||
|
||||
// DeviceOpened checks if block device in use by calling Open with O_EXCL flag.
|
||||
// Returns true if open returns errno EBUSY, and false if errno is nil.
|
||||
// Returns an error if errno is any error other than EBUSY.
|
||||
// Returns with error if pathname is not a device.
|
||||
func (n *Mounter) DeviceOpened(pathname string) (bool, error) {
|
||||
return mount.ExclusiveOpenFailsOnDevice(pathname)
|
||||
}
|
||||
|
||||
// PathIsDevice uses FileInfo returned from os.Stat to check if path refers
|
||||
// to a device.
|
||||
func (n *Mounter) PathIsDevice(pathname string) (bool, error) {
|
||||
pathType, err := n.GetFileType(pathname)
|
||||
isDevice := pathType == mount.FileTypeCharDev || pathType == mount.FileTypeBlockDev
|
||||
return isDevice, err
|
||||
}
|
||||
|
||||
//GetDeviceNameFromMount given a mount point, find the volume id from checking /proc/mounts
|
||||
func (n *Mounter) GetDeviceNameFromMount(mountPath, pluginMountDir string) (string, error) {
|
||||
return mount.GetDeviceNameFromMountLinux(n, mountPath, pluginMountDir)
|
||||
}
|
||||
|
||||
// MakeRShared checks if path is shared and bind-mounts it as rshared if needed.
|
||||
func (n *Mounter) MakeRShared(path string) error {
|
||||
return mount.DoMakeRShared(path, hostProcMountinfoPath)
|
||||
}
|
||||
|
||||
// GetFileType checks for file/directory/socket/block/character devices.
|
||||
func (n *Mounter) GetFileType(pathname string) (mount.FileType, error) {
|
||||
var pathType mount.FileType
|
||||
outputBytes, err := n.ne.Exec("stat", []string{"-L", "--printf=%F", pathname}).CombinedOutput()
|
||||
if err != nil {
|
||||
if strings.Contains(string(outputBytes), "No such file") {
|
||||
err = fmt.Errorf("%s does not exist", pathname)
|
||||
} else {
|
||||
err = fmt.Errorf("stat %s error: %v", pathname, string(outputBytes))
|
||||
}
|
||||
return pathType, err
|
||||
}
|
||||
|
||||
switch string(outputBytes) {
|
||||
case "socket":
|
||||
return mount.FileTypeSocket, nil
|
||||
case "character special file":
|
||||
return mount.FileTypeCharDev, nil
|
||||
case "block special file":
|
||||
return mount.FileTypeBlockDev, nil
|
||||
case "directory":
|
||||
return mount.FileTypeDirectory, nil
|
||||
case "regular file", "regular empty file":
|
||||
return mount.FileTypeFile, nil
|
||||
}
|
||||
|
||||
return pathType, fmt.Errorf("only recognise file, directory, socket, block device and character device")
|
||||
}
|
||||
|
||||
// MakeDir creates a new directory.
|
||||
func (n *Mounter) MakeDir(pathname string) error {
|
||||
args := []string{"-p", pathname}
|
||||
if _, err := n.ne.Exec("mkdir", args).CombinedOutput(); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// MakeFile creates an empty file.
|
||||
func (n *Mounter) MakeFile(pathname string) error {
|
||||
args := []string{pathname}
|
||||
if _, err := n.ne.Exec("touch", args).CombinedOutput(); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ExistsPath checks if pathname exists.
|
||||
// Error is returned on any other error than "file not found".
|
||||
func (n *Mounter) ExistsPath(pathname string) (bool, error) {
|
||||
// Resolve the symlinks but allow the target not to exist. EvalSymlinks
|
||||
// would return an generic error when the target does not exist.
|
||||
hostPath, err := n.ne.EvalSymlinks(pathname, false /* mustExist */)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
kubeletpath := n.ne.KubeletPath(hostPath)
|
||||
return utilpath.Exists(utilpath.CheckFollowSymlink, kubeletpath)
|
||||
}
|
||||
|
||||
// EvalHostSymlinks returns the path name after evaluating symlinks.
|
||||
func (n *Mounter) EvalHostSymlinks(pathname string) (string, error) {
|
||||
return n.ne.EvalSymlinks(pathname, true)
|
||||
}
|
||||
|
||||
// GetMountRefs finds all mount references to the path, returns a
|
||||
// list of paths. Path could be a mountpoint path, device or a normal
|
||||
// directory (for bind mount).
|
||||
func (n *Mounter) GetMountRefs(pathname string) ([]string, error) {
|
||||
pathExists, pathErr := mount.PathExists(pathname)
|
||||
if !pathExists || mount.IsCorruptedMnt(pathErr) {
|
||||
return []string{}, nil
|
||||
} else if pathErr != nil {
|
||||
return nil, fmt.Errorf("Error checking path %s: %v", pathname, pathErr)
|
||||
}
|
||||
hostpath, err := n.ne.EvalSymlinks(pathname, true /* mustExist */)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return mount.SearchMountPoints(hostpath, hostProcMountinfoPath)
|
||||
}
|
||||
|
||||
// GetFSGroup returns FSGroup of pathname.
|
||||
func (n *Mounter) GetFSGroup(pathname string) (int64, error) {
|
||||
hostPath, err := n.ne.EvalSymlinks(pathname, true /* mustExist */)
|
||||
if err != nil {
|
||||
return -1, err
|
||||
}
|
||||
kubeletpath := n.ne.KubeletPath(hostPath)
|
||||
return mount.GetFSGroupLinux(kubeletpath)
|
||||
}
|
||||
|
||||
// GetSELinuxSupport tests if pathname is on a mount that supports SELinux.
|
||||
func (n *Mounter) GetSELinuxSupport(pathname string) (bool, error) {
|
||||
return mount.GetSELinux(pathname, hostProcMountsPath)
|
||||
}
|
||||
|
||||
// GetMode returns permissions of pathname.
|
||||
func (n *Mounter) GetMode(pathname string) (os.FileMode, error) {
|
||||
hostPath, err := n.ne.EvalSymlinks(pathname, true /* mustExist */)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
kubeletpath := n.ne.KubeletPath(hostPath)
|
||||
return mount.GetModeLinux(kubeletpath)
|
||||
}
|
||||
139
vendor/k8s.io/kubernetes/pkg/volume/util/nsenter/nsenter_mount_unsupported.go
generated
vendored
139
vendor/k8s.io/kubernetes/pkg/volume/util/nsenter/nsenter_mount_unsupported.go
generated
vendored
|
|
@ -1,139 +0,0 @@
|
|||
// +build !linux
|
||||
|
||||
/*
|
||||
Copyright 2014 The Kubernetes Authors.
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
package nsenter
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"os"
|
||||
|
||||
"k8s.io/utils/nsenter"
|
||||
|
||||
"k8s.io/kubernetes/pkg/util/mount"
|
||||
)
|
||||
|
||||
// Mounter provides the mount.Interface implementation for unsupported
|
||||
// platforms.
|
||||
type Mounter struct{}
|
||||
|
||||
// NewMounter returns a new Mounter for the current system
|
||||
func NewMounter(rootDir string, ne *nsenter.Nsenter) *Mounter {
|
||||
return &Mounter{}
|
||||
}
|
||||
|
||||
var _ = mount.Interface(&Mounter{})
|
||||
|
||||
// Mount mounts the source to the target. It is a noop for unsupported systems
|
||||
func (*Mounter) Mount(source string, target string, fstype string, options []string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Unmount unmounts the target path from the system. it is a noop for unsupported
|
||||
// systems
|
||||
func (*Mounter) Unmount(target string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// List returns a list of all mounted filesystems. It is a noop for unsupported systems
|
||||
func (*Mounter) List() ([]mount.MountPoint, error) {
|
||||
return []mount.MountPoint{}, nil
|
||||
}
|
||||
|
||||
// IsMountPointMatch tests if dir and mp are the same path
|
||||
func (*Mounter) IsMountPointMatch(mp mount.MountPoint, dir string) bool {
|
||||
return (mp.Path == dir)
|
||||
}
|
||||
|
||||
// IsLikelyNotMountPoint determines if a directory is not a mountpoint.
|
||||
// It is a noop on unsupported systems
|
||||
func (*Mounter) IsLikelyNotMountPoint(file string) (bool, error) {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// DeviceOpened checks if block device in use. I tis a noop for unsupported systems
|
||||
func (*Mounter) DeviceOpened(pathname string) (bool, error) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// PathIsDevice checks if pathname refers to a device. It is a noop for unsupported
|
||||
// systems
|
||||
func (*Mounter) PathIsDevice(pathname string) (bool, error) {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// GetDeviceNameFromMount finds the device name from its global mount point using the
|
||||
// given mountpath and plugin location. It is a noop of unsupported platforms
|
||||
func (*Mounter) GetDeviceNameFromMount(mountPath, pluginMountDir string) (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
// MakeRShared checks if path is shared and bind-mounts it as rshared if needed.
|
||||
// It is a noop on unsupported platforms
|
||||
func (*Mounter) MakeRShared(path string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetFileType checks for file/directory/socket/block/character devices.
|
||||
// Always returns an error and "fake" filetype on unsupported platforms
|
||||
func (*Mounter) GetFileType(_ string) (mount.FileType, error) {
|
||||
return mount.FileType("fake"), errors.New("not implemented")
|
||||
}
|
||||
|
||||
// MakeDir creates a new directory. Noop on unsupported platforms
|
||||
func (*Mounter) MakeDir(pathname string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// MakeFile creats an empty file. Noop on unsupported platforms
|
||||
func (*Mounter) MakeFile(pathname string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// ExistsPath checks if pathname exists. Always returns an error on unsupported
|
||||
// platforms
|
||||
func (*Mounter) ExistsPath(pathname string) (bool, error) {
|
||||
return true, errors.New("not implemented")
|
||||
}
|
||||
|
||||
// EvalHostSymlinks returns the path name after evaluating symlinks. Always
|
||||
// returns an error on unsupported platforms
|
||||
func (*Mounter) EvalHostSymlinks(pathname string) (string, error) {
|
||||
return "", errors.New("not implemented")
|
||||
}
|
||||
|
||||
// GetMountRefs finds all mount references to the path, returns a
|
||||
// list of paths. Always returns an error on unsupported platforms
|
||||
func (*Mounter) GetMountRefs(pathname string) ([]string, error) {
|
||||
return nil, errors.New("not implemented")
|
||||
}
|
||||
|
||||
// GetFSGroup returns FSGroup of pathname. Always returns an error on unsupported platforms
|
||||
func (*Mounter) GetFSGroup(pathname string) (int64, error) {
|
||||
return -1, errors.New("not implemented")
|
||||
}
|
||||
|
||||
// GetSELinuxSupport tests if pathname is on a mount that supports SELinux.
|
||||
// Always returns an error on unsupported platforms
|
||||
func (*Mounter) GetSELinuxSupport(pathname string) (bool, error) {
|
||||
return false, errors.New("not implemented")
|
||||
}
|
||||
|
||||
// GetMode returns permissions of pathname. Always returns an error on unsupported platforms
|
||||
func (*Mounter) GetMode(pathname string) (os.FileMode, error) {
|
||||
return 0, errors.New("not implemented")
|
||||
}
|
||||
|
|
@ -2,7 +2,7 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
|||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["consistentread.go"],
|
||||
srcs = ["read.go"],
|
||||
importmap = "k8s.io/kops/vendor/k8s.io/utils/io",
|
||||
importpath = "k8s.io/utils/io",
|
||||
visibility = ["//visibility:public"],
|
||||
|
|
|
|||
|
|
@ -18,10 +18,15 @@ package io
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
)
|
||||
|
||||
// ErrLimitReached means that the read limit is reached.
|
||||
var ErrLimitReached = errors.New("the read limit is reached")
|
||||
|
||||
// ConsistentRead repeatedly reads a file until it gets the same content twice.
|
||||
// This is useful when reading files in /proc that are larger than page size
|
||||
// and kernel may modify them between individual read() syscalls.
|
||||
|
|
@ -53,3 +58,17 @@ func consistentReadSync(filename string, attempts int, sync func(int)) ([]byte,
|
|||
}
|
||||
return nil, fmt.Errorf("could not get consistent content of %s after %d attempts", filename, attempts)
|
||||
}
|
||||
|
||||
// ReadAtMost reads up to `limit` bytes from `r`, and reports an error
|
||||
// when `limit` bytes are read.
|
||||
func ReadAtMost(r io.Reader, limit int64) ([]byte, error) {
|
||||
limitedReader := &io.LimitedReader{R: r, N: limit}
|
||||
data, err := ioutil.ReadAll(limitedReader)
|
||||
if err != nil {
|
||||
return data, err
|
||||
}
|
||||
if limitedReader.N <= 0 {
|
||||
return data, ErrLimitReached
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"doc.go",
|
||||
"fake_mounter.go",
|
||||
"mount.go",
|
||||
"mount_helper_common.go",
|
||||
"mount_helper_unix.go",
|
||||
"mount_helper_windows.go",
|
||||
"mount_linux.go",
|
||||
"mount_unsupported.go",
|
||||
"mount_windows.go",
|
||||
],
|
||||
importmap = "k8s.io/kops/vendor/k8s.io/utils/mount",
|
||||
importpath = "k8s.io/utils/mount",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//vendor/k8s.io/klog:go_default_library",
|
||||
"//vendor/k8s.io/utils/exec:go_default_library",
|
||||
] + select({
|
||||
"@io_bazel_rules_go//go/platform:android": [
|
||||
"//vendor/k8s.io/utils/io:go_default_library",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:darwin": [
|
||||
"//vendor/k8s.io/utils/io:go_default_library",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:dragonfly": [
|
||||
"//vendor/k8s.io/utils/io:go_default_library",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:freebsd": [
|
||||
"//vendor/k8s.io/utils/io:go_default_library",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:ios": [
|
||||
"//vendor/k8s.io/utils/io:go_default_library",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:linux": [
|
||||
"//vendor/k8s.io/utils/io:go_default_library",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:nacl": [
|
||||
"//vendor/k8s.io/utils/io:go_default_library",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:netbsd": [
|
||||
"//vendor/k8s.io/utils/io:go_default_library",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:openbsd": [
|
||||
"//vendor/k8s.io/utils/io:go_default_library",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:plan9": [
|
||||
"//vendor/k8s.io/utils/io:go_default_library",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:solaris": [
|
||||
"//vendor/k8s.io/utils/io:go_default_library",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:windows": [
|
||||
"//vendor/k8s.io/utils/keymutex:go_default_library",
|
||||
"//vendor/k8s.io/utils/path:go_default_library",
|
||||
],
|
||||
"//conditions:default": [],
|
||||
}),
|
||||
)
|
||||
0
vendor/k8s.io/kubernetes/pkg/util/mount/OWNERS → vendor/k8s.io/utils/mount/OWNERS
generated
vendored
0
vendor/k8s.io/kubernetes/pkg/util/mount/OWNERS → vendor/k8s.io/utils/mount/OWNERS
generated
vendored
2
vendor/k8s.io/kubernetes/pkg/util/mount/doc.go → vendor/k8s.io/utils/mount/doc.go
generated
vendored
2
vendor/k8s.io/kubernetes/pkg/util/mount/doc.go → vendor/k8s.io/utils/mount/doc.go
generated
vendored
|
|
@ -15,4 +15,4 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
// Package mount defines an interface to mounting filesystems.
|
||||
package mount // import "k8s.io/kubernetes/pkg/util/mount"
|
||||
package mount // import "k8s.io/utils/mount"
|
||||
121
vendor/k8s.io/kubernetes/pkg/util/mount/fake.go → vendor/k8s.io/utils/mount/fake_mounter.go
generated
vendored
121
vendor/k8s.io/kubernetes/pkg/util/mount/fake.go → vendor/k8s.io/utils/mount/fake_mounter.go
generated
vendored
|
|
@ -17,7 +17,6 @@ limitations under the License.
|
|||
package mount
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
|
|
@ -28,20 +27,26 @@ import (
|
|||
// FakeMounter implements mount.Interface for tests.
|
||||
type FakeMounter struct {
|
||||
MountPoints []MountPoint
|
||||
Log []FakeAction
|
||||
Filesystem map[string]FileType
|
||||
log []FakeAction
|
||||
// Error to return for a path when calling IsLikelyNotMountPoint
|
||||
MountCheckErrors map[string]error
|
||||
// Some tests run things in parallel, make sure the mounter does not produce
|
||||
// any golang's DATA RACE warnings.
|
||||
mutex sync.Mutex
|
||||
mutex sync.Mutex
|
||||
UnmountFunc UnmountFunc
|
||||
}
|
||||
|
||||
// UnmountFunc is a function callback to be executed during the Unmount() call.
|
||||
type UnmountFunc func(path string) error
|
||||
|
||||
var _ Interface = &FakeMounter{}
|
||||
|
||||
// Values for FakeAction.Action
|
||||
const FakeActionMount = "mount"
|
||||
const FakeActionUnmount = "unmount"
|
||||
const (
|
||||
// FakeActionMount is the string for specifying mount as FakeAction.Action
|
||||
FakeActionMount = "mount"
|
||||
// FakeActionUnmount is the string for specifying unmount as FakeAction.Action
|
||||
FakeActionUnmount = "unmount"
|
||||
)
|
||||
|
||||
// FakeAction objects are logged every time a fake mount or unmount is called.
|
||||
type FakeAction struct {
|
||||
|
|
@ -51,13 +56,31 @@ type FakeAction struct {
|
|||
FSType string // applies only to "mount" actions
|
||||
}
|
||||
|
||||
// NewFakeMounter returns a FakeMounter struct that implements Interface and is
|
||||
// suitable for testing purposes.
|
||||
func NewFakeMounter(mps []MountPoint) *FakeMounter {
|
||||
return &FakeMounter{
|
||||
MountPoints: mps,
|
||||
}
|
||||
}
|
||||
|
||||
// ResetLog clears all the log entries in FakeMounter
|
||||
func (f *FakeMounter) ResetLog() {
|
||||
f.mutex.Lock()
|
||||
defer f.mutex.Unlock()
|
||||
|
||||
f.Log = []FakeAction{}
|
||||
f.log = []FakeAction{}
|
||||
}
|
||||
|
||||
// GetLog returns the slice of FakeActions taken by the mounter
|
||||
func (f *FakeMounter) GetLog() []FakeAction {
|
||||
f.mutex.Lock()
|
||||
defer f.mutex.Unlock()
|
||||
|
||||
return f.log
|
||||
}
|
||||
|
||||
// Mount records the mount event and updates the in-memory mount points for FakeMounter
|
||||
func (f *FakeMounter) Mount(source string, target string, fstype string, options []string) error {
|
||||
f.mutex.Lock()
|
||||
defer f.mutex.Unlock()
|
||||
|
|
@ -96,10 +119,11 @@ func (f *FakeMounter) Mount(source string, target string, fstype string, options
|
|||
}
|
||||
f.MountPoints = append(f.MountPoints, MountPoint{Device: source, Path: absTarget, Type: fstype, Opts: opts})
|
||||
klog.V(5).Infof("Fake mounter: mounted %s to %s", source, absTarget)
|
||||
f.Log = append(f.Log, FakeAction{Action: FakeActionMount, Target: absTarget, Source: source, FSType: fstype})
|
||||
f.log = append(f.log, FakeAction{Action: FakeActionMount, Target: absTarget, Source: source, FSType: fstype})
|
||||
return nil
|
||||
}
|
||||
|
||||
// Unmount records the unmount event and updates the in-memory mount points for FakeMounter
|
||||
func (f *FakeMounter) Unmount(target string) error {
|
||||
f.mutex.Lock()
|
||||
defer f.mutex.Unlock()
|
||||
|
|
@ -113,6 +137,12 @@ func (f *FakeMounter) Unmount(target string) error {
|
|||
newMountpoints := []MountPoint{}
|
||||
for _, mp := range f.MountPoints {
|
||||
if mp.Path == absTarget {
|
||||
if f.UnmountFunc != nil {
|
||||
err := f.UnmountFunc(absTarget)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
klog.V(5).Infof("Fake mounter: unmounted %s from %s", mp.Device, absTarget)
|
||||
// Don't copy it to newMountpoints
|
||||
continue
|
||||
|
|
@ -120,11 +150,12 @@ func (f *FakeMounter) Unmount(target string) error {
|
|||
newMountpoints = append(newMountpoints, MountPoint{Device: mp.Device, Path: mp.Path, Type: mp.Type})
|
||||
}
|
||||
f.MountPoints = newMountpoints
|
||||
f.Log = append(f.Log, FakeAction{Action: FakeActionUnmount, Target: absTarget})
|
||||
f.log = append(f.log, FakeAction{Action: FakeActionUnmount, Target: absTarget})
|
||||
delete(f.MountCheckErrors, target)
|
||||
return nil
|
||||
}
|
||||
|
||||
// List returns all the in-memory mountpoints for FakeMounter
|
||||
func (f *FakeMounter) List() ([]MountPoint, error) {
|
||||
f.mutex.Lock()
|
||||
defer f.mutex.Unlock()
|
||||
|
|
@ -132,10 +163,8 @@ func (f *FakeMounter) List() ([]MountPoint, error) {
|
|||
return f.MountPoints, nil
|
||||
}
|
||||
|
||||
func (f *FakeMounter) IsMountPointMatch(mp MountPoint, dir string) bool {
|
||||
return mp.Path == dir
|
||||
}
|
||||
|
||||
// IsLikelyNotMountPoint determines whether a path is a mountpoint by checking
|
||||
// if the absolute path to file is in the in-memory mountpoints
|
||||
func (f *FakeMounter) IsLikelyNotMountPoint(file string) (bool, error) {
|
||||
f.mutex.Lock()
|
||||
defer f.mutex.Unlock()
|
||||
|
|
@ -166,56 +195,8 @@ func (f *FakeMounter) IsLikelyNotMountPoint(file string) (bool, error) {
|
|||
return true, nil
|
||||
}
|
||||
|
||||
func (f *FakeMounter) DeviceOpened(pathname string) (bool, error) {
|
||||
f.mutex.Lock()
|
||||
defer f.mutex.Unlock()
|
||||
|
||||
for _, mp := range f.MountPoints {
|
||||
if mp.Device == pathname {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func (f *FakeMounter) PathIsDevice(pathname string) (bool, error) {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (f *FakeMounter) GetDeviceNameFromMount(mountPath, pluginMountDir string) (string, error) {
|
||||
return getDeviceNameFromMount(f, mountPath, pluginMountDir)
|
||||
}
|
||||
|
||||
func (f *FakeMounter) MakeRShared(path string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *FakeMounter) GetFileType(pathname string) (FileType, error) {
|
||||
if t, ok := f.Filesystem[pathname]; ok {
|
||||
return t, nil
|
||||
}
|
||||
return FileType("Directory"), nil
|
||||
}
|
||||
|
||||
func (f *FakeMounter) MakeDir(pathname string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *FakeMounter) MakeFile(pathname string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *FakeMounter) ExistsPath(pathname string) (bool, error) {
|
||||
if _, ok := f.Filesystem[pathname]; ok {
|
||||
return true, nil
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func (f *FakeMounter) EvalHostSymlinks(pathname string) (string, error) {
|
||||
return pathname, nil
|
||||
}
|
||||
|
||||
// GetMountRefs finds all mount references to the path, returns a
|
||||
// list of paths.
|
||||
func (f *FakeMounter) GetMountRefs(pathname string) ([]string, error) {
|
||||
realpath, err := filepath.EvalSymlinks(pathname)
|
||||
if err != nil {
|
||||
|
|
@ -224,15 +205,3 @@ func (f *FakeMounter) GetMountRefs(pathname string) ([]string, error) {
|
|||
}
|
||||
return getMountRefsByDev(f, realpath)
|
||||
}
|
||||
|
||||
func (f *FakeMounter) GetFSGroup(pathname string) (int64, error) {
|
||||
return -1, errors.New("GetFSGroup not implemented")
|
||||
}
|
||||
|
||||
func (f *FakeMounter) GetSELinuxSupport(pathname string) (bool, error) {
|
||||
return false, errors.New("GetSELinuxSupport not implemented")
|
||||
}
|
||||
|
||||
func (f *FakeMounter) GetMode(pathname string) (os.FileMode, error) {
|
||||
return 0, errors.New("not implemented")
|
||||
}
|
||||
187
vendor/k8s.io/kubernetes/pkg/util/mount/mount.go → vendor/k8s.io/utils/mount/mount.go
generated
vendored
187
vendor/k8s.io/kubernetes/pkg/util/mount/mount.go → vendor/k8s.io/utils/mount/mount.go
generated
vendored
|
|
@ -16,114 +16,57 @@ limitations under the License.
|
|||
|
||||
// TODO(thockin): This whole pkg is pretty linux-centric. As soon as we have
|
||||
// an alternate platform, we will need to abstract further.
|
||||
|
||||
package mount
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type FileType string
|
||||
utilexec "k8s.io/utils/exec"
|
||||
)
|
||||
|
||||
const (
|
||||
// Default mount command if mounter path is not specified
|
||||
defaultMountCommand = "mount"
|
||||
FileTypeDirectory FileType = "Directory"
|
||||
FileTypeFile FileType = "File"
|
||||
FileTypeSocket FileType = "Socket"
|
||||
FileTypeCharDev FileType = "CharDevice"
|
||||
FileTypeBlockDev FileType = "BlockDevice"
|
||||
// Default mount command if mounter path is not specified.
|
||||
defaultMountCommand = "mount"
|
||||
)
|
||||
|
||||
// Interface defines the set of methods to allow for mount operations on a system.
|
||||
type Interface interface {
|
||||
// Mount mounts source to target as fstype with given options.
|
||||
Mount(source string, target string, fstype string, options []string) error
|
||||
// Unmount unmounts given target.
|
||||
Unmount(target string) error
|
||||
// List returns a list of all mounted filesystems. This can be large.
|
||||
// On some platforms, reading mounts is not guaranteed consistent (i.e.
|
||||
// it could change between chunked reads). This is guaranteed to be
|
||||
// consistent.
|
||||
// On some platforms, reading mounts directly from the OS is not guaranteed
|
||||
// consistent (i.e. it could change between chunked reads). This is guaranteed
|
||||
// to be consistent.
|
||||
List() ([]MountPoint, error)
|
||||
// IsMountPointMatch determines if the mountpoint matches the dir
|
||||
IsMountPointMatch(mp MountPoint, dir string) bool
|
||||
// IsLikelyNotMountPoint uses heuristics to determine if a directory
|
||||
// is a mountpoint.
|
||||
// is not a mountpoint.
|
||||
// It should return ErrNotExist when the directory does not exist.
|
||||
// IsLikelyNotMountPoint does NOT properly detect all mountpoint types
|
||||
// most notably linux bind mounts and symbolic link.
|
||||
// most notably linux bind mounts and symbolic link. For callers that do not
|
||||
// care about such situations, this is a faster alternative to calling List()
|
||||
// and scanning that output.
|
||||
IsLikelyNotMountPoint(file string) (bool, error)
|
||||
// DeviceOpened determines if the device is in use elsewhere
|
||||
// on the system, i.e. still mounted.
|
||||
DeviceOpened(pathname string) (bool, error)
|
||||
// PathIsDevice determines if a path is a device.
|
||||
PathIsDevice(pathname string) (bool, error)
|
||||
// GetDeviceNameFromMount finds the device name by checking the mount path
|
||||
// to get the global mount path within its plugin directory
|
||||
GetDeviceNameFromMount(mountPath, pluginMountDir string) (string, error)
|
||||
// MakeRShared checks that given path is on a mount with 'rshared' mount
|
||||
// propagation. If not, it bind-mounts the path as rshared.
|
||||
MakeRShared(path string) error
|
||||
// GetFileType checks for file/directory/socket/block/character devices.
|
||||
// Will operate in the host mount namespace if kubelet is running in a container
|
||||
GetFileType(pathname string) (FileType, error)
|
||||
// MakeFile creates an empty file.
|
||||
// Will operate in the host mount namespace if kubelet is running in a container
|
||||
MakeFile(pathname string) error
|
||||
// MakeDir creates a new directory.
|
||||
// Will operate in the host mount namespace if kubelet is running in a container
|
||||
MakeDir(pathname string) error
|
||||
// Will operate in the host mount namespace if kubelet is running in a container.
|
||||
// Error is returned on any other error than "file not found".
|
||||
ExistsPath(pathname string) (bool, error)
|
||||
// EvalHostSymlinks returns the path name after evaluating symlinks.
|
||||
// Will operate in the host mount namespace if kubelet is running in a container.
|
||||
EvalHostSymlinks(pathname string) (string, error)
|
||||
// GetMountRefs finds all mount references to the path, returns a
|
||||
// list of paths. Path could be a mountpoint path, device or a normal
|
||||
// directory (for bind mount).
|
||||
// GetMountRefs finds all mount references to pathname, returning a slice of
|
||||
// paths. Pathname can be a mountpoint path or a normal directory
|
||||
// (for bind mount). On Linux, pathname is excluded from the slice.
|
||||
// For example, if /dev/sdc was mounted at /path/a and /path/b,
|
||||
// GetMountRefs("/path/a") would return ["/path/b"]
|
||||
// GetMountRefs("/path/b") would return ["/path/a"]
|
||||
// On Windows there is no way to query all mount points; as long as pathname is
|
||||
// a valid mount, it will be returned.
|
||||
GetMountRefs(pathname string) ([]string, error)
|
||||
// GetFSGroup returns FSGroup of the path.
|
||||
GetFSGroup(pathname string) (int64, error)
|
||||
// GetSELinuxSupport returns true if given path is on a mount that supports
|
||||
// SELinux.
|
||||
GetSELinuxSupport(pathname string) (bool, error)
|
||||
// GetMode returns permissions of the path.
|
||||
GetMode(pathname string) (os.FileMode, error)
|
||||
}
|
||||
|
||||
type Subpath struct {
|
||||
// index of the VolumeMount for this container
|
||||
VolumeMountIndex int
|
||||
// Full path to the subpath directory on the host
|
||||
Path string
|
||||
// name of the volume that is a valid directory name.
|
||||
VolumeName string
|
||||
// Full path to the volume path
|
||||
VolumePath string
|
||||
// Path to the pod's directory, including pod UID
|
||||
PodDir string
|
||||
// Name of the container
|
||||
ContainerName string
|
||||
}
|
||||
|
||||
// Exec executes command where mount utilities are. This can be either the host,
|
||||
// container where kubelet runs or even a remote pod with mount utilities.
|
||||
// Usual k8s.io/utils/exec interface is not used because kubelet.RunInContainer does
|
||||
// not provide stdin/stdout/stderr streams.
|
||||
type Exec interface {
|
||||
// Run executes a command and returns its stdout + stderr combined in one
|
||||
// stream.
|
||||
Run(cmd string, args ...string) ([]byte, error)
|
||||
}
|
||||
|
||||
// Compile-time check to ensure all Mounter implementations satisfy
|
||||
// the mount interface
|
||||
// the mount interface.
|
||||
var _ Interface = &Mounter{}
|
||||
|
||||
// This represents a single line in /proc/mounts or /etc/fstab.
|
||||
// MountPoint represents a single line in /proc/mounts or /etc/fstab.
|
||||
type MountPoint struct {
|
||||
Device string
|
||||
Path string
|
||||
|
|
@ -138,7 +81,7 @@ type MountPoint struct {
|
|||
// mounts it otherwise the device is formatted first then mounted.
|
||||
type SafeFormatAndMount struct {
|
||||
Interface
|
||||
Exec
|
||||
Exec utilexec.Interface
|
||||
}
|
||||
|
||||
// FormatAndMount formats the given disk, if needed, and mounts it.
|
||||
|
|
@ -159,7 +102,7 @@ func getMountRefsByDev(mounter Interface, mountPath string) ([]string, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
// Finding the device mounted to mountPath
|
||||
// Finding the device mounted to mountPath.
|
||||
diskDev := ""
|
||||
for i := range mps {
|
||||
if mountPath == mps[i].Path {
|
||||
|
|
@ -180,8 +123,8 @@ func getMountRefsByDev(mounter Interface, mountPath string) ([]string, error) {
|
|||
return refs, nil
|
||||
}
|
||||
|
||||
// GetDeviceNameFromMount: given a mnt point, find the device from /proc/mounts
|
||||
// returns the device name, reference count, and error code
|
||||
// GetDeviceNameFromMount given a mnt point, find the device from /proc/mounts
|
||||
// returns the device name, reference count, and error code.
|
||||
func GetDeviceNameFromMount(mounter Interface, mountPath string) (string, int, error) {
|
||||
mps, err := mounter.List()
|
||||
if err != nil {
|
||||
|
|
@ -189,7 +132,7 @@ func GetDeviceNameFromMount(mounter Interface, mountPath string) (string, int, e
|
|||
}
|
||||
|
||||
// Find the device name.
|
||||
// FIXME if multiple devices mounted on the same mount path, only the first one is returned
|
||||
// FIXME if multiple devices mounted on the same mount path, only the first one is returned.
|
||||
device := ""
|
||||
// If mountPath is symlink, need get its target path.
|
||||
slTarget, err := filepath.EvalSymlinks(mountPath)
|
||||
|
|
@ -219,10 +162,10 @@ func GetDeviceNameFromMount(mounter Interface, mountPath string) (string, int, e
|
|||
// IsNotMountPoint detects bind mounts in linux.
|
||||
// IsNotMountPoint enumerates all the mountpoints using List() and
|
||||
// the list of mountpoints may be large, then it uses
|
||||
// IsMountPointMatch to evaluate whether the directory is a mountpoint
|
||||
// isMountPointMatch to evaluate whether the directory is a mountpoint.
|
||||
func IsNotMountPoint(mounter Interface, file string) (bool, error) {
|
||||
// IsLikelyNotMountPoint provides a quick check
|
||||
// to determine whether file IS A mountpoint
|
||||
// to determine whether file IS A mountpoint.
|
||||
notMnt, notMntErr := mounter.IsLikelyNotMountPoint(file)
|
||||
if notMntErr != nil && os.IsPermission(notMntErr) {
|
||||
// We were not allowed to do the simple stat() check, e.g. on NFS with
|
||||
|
|
@ -233,25 +176,25 @@ func IsNotMountPoint(mounter Interface, file string) (bool, error) {
|
|||
if notMntErr != nil {
|
||||
return notMnt, notMntErr
|
||||
}
|
||||
// identified as mountpoint, so return this fact
|
||||
// identified as mountpoint, so return this fact.
|
||||
if notMnt == false {
|
||||
return notMnt, nil
|
||||
}
|
||||
|
||||
// Resolve any symlinks in file, kernel would do the same and use the resolved path in /proc/mounts
|
||||
resolvedFile, err := mounter.EvalHostSymlinks(file)
|
||||
// Resolve any symlinks in file, kernel would do the same and use the resolved path in /proc/mounts.
|
||||
resolvedFile, err := filepath.EvalSymlinks(file)
|
||||
if err != nil {
|
||||
return true, err
|
||||
}
|
||||
|
||||
// check all mountpoints since IsLikelyNotMountPoint
|
||||
// is not reliable for some mountpoint types
|
||||
// is not reliable for some mountpoint types.
|
||||
mountPoints, mountPointsErr := mounter.List()
|
||||
if mountPointsErr != nil {
|
||||
return notMnt, mountPointsErr
|
||||
}
|
||||
for _, mp := range mountPoints {
|
||||
if mounter.IsMountPointMatch(mp, resolvedFile) {
|
||||
if isMountPointMatch(mp, resolvedFile) {
|
||||
notMnt = false
|
||||
break
|
||||
}
|
||||
|
|
@ -259,11 +202,11 @@ func IsNotMountPoint(mounter Interface, file string) (bool, error) {
|
|||
return notMnt, nil
|
||||
}
|
||||
|
||||
// IsBind detects whether a bind mount is being requested and makes the remount options to
|
||||
// MakeBindOpts detects whether a bind mount is being requested and makes the remount options to
|
||||
// use in case of bind mount, due to the fact that bind mount doesn't respect mount options.
|
||||
// The list equals:
|
||||
// options - 'bind' + 'remount' (no duplicate)
|
||||
func IsBind(options []string) (bool, []string, []string) {
|
||||
func MakeBindOpts(options []string) (bool, []string, []string) {
|
||||
// Because we have an FD opened on the subpath bind mount, the "bind" option
|
||||
// needs to be included, otherwise the mount target will error as busy if you
|
||||
// remount as readonly.
|
||||
|
|
@ -304,24 +247,6 @@ func checkForNetDev(options []string) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
// TODO: this is a workaround for the unmount device issue caused by gci mounter.
|
||||
// In GCI cluster, if gci mounter is used for mounting, the container started by mounter
|
||||
// script will cause additional mounts created in the container. Since these mounts are
|
||||
// irrelevant to the original mounts, they should be not considered when checking the
|
||||
// mount references. Current solution is to filter out those mount paths that contain
|
||||
// the string of original mount path.
|
||||
// Plan to work on better approach to solve this issue.
|
||||
|
||||
func HasMountRefs(mountPath string, mountRefs []string) bool {
|
||||
count := 0
|
||||
for _, ref := range mountRefs {
|
||||
if !strings.Contains(ref, mountPath) {
|
||||
count = count + 1
|
||||
}
|
||||
}
|
||||
return count > 0
|
||||
}
|
||||
|
||||
// PathWithinBase checks if give path is within given base directory.
|
||||
func PathWithinBase(fullPath, basePath string) bool {
|
||||
rel, err := filepath.Rel(basePath, fullPath)
|
||||
|
|
@ -329,48 +254,14 @@ func PathWithinBase(fullPath, basePath string) bool {
|
|||
return false
|
||||
}
|
||||
if StartsWithBackstep(rel) {
|
||||
// Needed to escape the base path
|
||||
// Needed to escape the base path.
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// StartsWithBackstep checks if the given path starts with a backstep segment
|
||||
// StartsWithBackstep checks if the given path starts with a backstep segment.
|
||||
func StartsWithBackstep(rel string) bool {
|
||||
// normalize to / and check for ../
|
||||
return rel == ".." || strings.HasPrefix(filepath.ToSlash(rel), "../")
|
||||
}
|
||||
|
||||
// getFileType checks for file/directory/socket and block/character devices
|
||||
func getFileType(pathname string) (FileType, error) {
|
||||
var pathType FileType
|
||||
info, err := os.Stat(pathname)
|
||||
if os.IsNotExist(err) {
|
||||
return pathType, fmt.Errorf("path %q does not exist", pathname)
|
||||
}
|
||||
// err in call to os.Stat
|
||||
if err != nil {
|
||||
return pathType, err
|
||||
}
|
||||
|
||||
// checks whether the mode is the target mode
|
||||
isSpecificMode := func(mode, targetMode os.FileMode) bool {
|
||||
return mode&targetMode == targetMode
|
||||
}
|
||||
|
||||
mode := info.Mode()
|
||||
if mode.IsDir() {
|
||||
return FileTypeDirectory, nil
|
||||
} else if mode.IsRegular() {
|
||||
return FileTypeFile, nil
|
||||
} else if isSpecificMode(mode, os.ModeSocket) {
|
||||
return FileTypeSocket, nil
|
||||
} else if isSpecificMode(mode, os.ModeDevice) {
|
||||
if isSpecificMode(mode, os.ModeCharDevice) {
|
||||
return FileTypeCharDev, nil
|
||||
}
|
||||
return FileTypeBlockDev, nil
|
||||
}
|
||||
|
||||
return pathType, fmt.Errorf("only recognise file, directory, socket, block device and character device")
|
||||
}
|
||||
|
|
@ -23,14 +23,11 @@ import (
|
|||
"k8s.io/klog"
|
||||
)
|
||||
|
||||
// CleanupMountPoint unmounts the given path and
|
||||
// deletes the remaining directory if successful.
|
||||
// if extensiveMountPointCheck is true
|
||||
// IsNotMountPoint will be called instead of IsLikelyNotMountPoint.
|
||||
// IsNotMountPoint is more expensive but properly handles bind mounts within the same fs.
|
||||
// CleanupMountPoint unmounts the given path and deletes the remaining directory
|
||||
// if successful. If extensiveMountPointCheck is true IsNotMountPoint will be
|
||||
// called instead of IsLikelyNotMountPoint. IsNotMountPoint is more expensive
|
||||
// but properly handles bind mounts within the same fs.
|
||||
func CleanupMountPoint(mountPath string, mounter Interface, extensiveMountPointCheck bool) error {
|
||||
// mounter.ExistsPath cannot be used because for containerized kubelet, we need to check
|
||||
// the path in the kubelet container, not on the host.
|
||||
pathExists, pathErr := PathExists(mountPath)
|
||||
if !pathExists {
|
||||
klog.Warningf("Warning: Unmount skipped because path does not exist: %v", mountPath)
|
||||
|
|
@ -87,8 +84,8 @@ func doCleanupMountPoint(mountPath string, mounter Interface, extensiveMountPoin
|
|||
return fmt.Errorf("Failed to unmount path %v", mountPath)
|
||||
}
|
||||
|
||||
// TODO: clean this up to use pkg/util/file/FileExists
|
||||
// PathExists returns true if the specified path exists.
|
||||
// TODO: clean this up to use pkg/util/file/FileExists
|
||||
func PathExists(path string) (bool, error) {
|
||||
_, err := os.Stat(path)
|
||||
if err == nil {
|
||||
|
|
@ -97,7 +94,6 @@ func PathExists(path string) (bool, error) {
|
|||
return false, nil
|
||||
} else if IsCorruptedMnt(err) {
|
||||
return true, err
|
||||
} else {
|
||||
return false, err
|
||||
}
|
||||
return false, err
|
||||
}
|
||||
|
|
@ -0,0 +1,140 @@
|
|||
// +build !windows
|
||||
|
||||
/*
|
||||
Copyright 2019 The Kubernetes Authors.
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
package mount
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
utilio "k8s.io/utils/io"
|
||||
)
|
||||
|
||||
const (
|
||||
// At least number of fields per line in /proc/<pid>/mountinfo.
|
||||
expectedAtLeastNumFieldsPerMountInfo = 10
|
||||
// How many times to retry for a consistent read of /proc/mounts.
|
||||
maxListTries = 3
|
||||
)
|
||||
|
||||
// IsCorruptedMnt return true if err is about corrupted mount point
|
||||
func IsCorruptedMnt(err error) bool {
|
||||
if err == nil {
|
||||
return false
|
||||
}
|
||||
var underlyingError error
|
||||
switch pe := err.(type) {
|
||||
case nil:
|
||||
return false
|
||||
case *os.PathError:
|
||||
underlyingError = pe.Err
|
||||
case *os.LinkError:
|
||||
underlyingError = pe.Err
|
||||
case *os.SyscallError:
|
||||
underlyingError = pe.Err
|
||||
}
|
||||
|
||||
return underlyingError == syscall.ENOTCONN || underlyingError == syscall.ESTALE || underlyingError == syscall.EIO || underlyingError == syscall.EACCES
|
||||
}
|
||||
|
||||
// MountInfo represents a single line in /proc/<pid>/mountinfo.
|
||||
type MountInfo struct {
|
||||
// Unique ID for the mount (maybe reused after umount).
|
||||
ID int
|
||||
// The ID of the parent mount (or of self for the root of this mount namespace's mount tree).
|
||||
ParentID int
|
||||
// The value of `st_dev` for files on this filesystem.
|
||||
MajorMinor string
|
||||
// The pathname of the directory in the filesystem which forms the root of this mount.
|
||||
Root string
|
||||
// Mount source, filesystem-specific information. e.g. device, tmpfs name.
|
||||
Source string
|
||||
// Mount point, the pathname of the mount point.
|
||||
MountPoint string
|
||||
// Optional fieds, zero or more fields of the form "tag[:value]".
|
||||
OptionalFields []string
|
||||
// The filesystem type in the form "type[.subtype]".
|
||||
FsType string
|
||||
// Per-mount options.
|
||||
MountOptions []string
|
||||
// Per-superblock options.
|
||||
SuperOptions []string
|
||||
}
|
||||
|
||||
// ParseMountInfo parses /proc/xxx/mountinfo.
|
||||
func ParseMountInfo(filename string) ([]MountInfo, error) {
|
||||
content, err := utilio.ConsistentRead(filename, maxListTries)
|
||||
if err != nil {
|
||||
return []MountInfo{}, err
|
||||
}
|
||||
contentStr := string(content)
|
||||
infos := []MountInfo{}
|
||||
|
||||
for _, line := range strings.Split(contentStr, "\n") {
|
||||
if line == "" {
|
||||
// the last split() item is empty string following the last \n
|
||||
continue
|
||||
}
|
||||
// See `man proc` for authoritative description of format of the file.
|
||||
fields := strings.Fields(line)
|
||||
if len(fields) < expectedAtLeastNumFieldsPerMountInfo {
|
||||
return nil, fmt.Errorf("wrong number of fields in (expected at least %d, got %d): %s", expectedAtLeastNumFieldsPerMountInfo, len(fields), line)
|
||||
}
|
||||
id, err := strconv.Atoi(fields[0])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
parentID, err := strconv.Atoi(fields[1])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
info := MountInfo{
|
||||
ID: id,
|
||||
ParentID: parentID,
|
||||
MajorMinor: fields[2],
|
||||
Root: fields[3],
|
||||
MountPoint: fields[4],
|
||||
MountOptions: strings.Split(fields[5], ","),
|
||||
}
|
||||
// All fields until "-" are "optional fields".
|
||||
i := 6
|
||||
for ; i < len(fields) && fields[i] != "-"; i++ {
|
||||
info.OptionalFields = append(info.OptionalFields, fields[i])
|
||||
}
|
||||
// Parse the rest 3 fields.
|
||||
i++
|
||||
if len(fields)-i < 3 {
|
||||
return nil, fmt.Errorf("expect 3 fields in %s, got %d", line, len(fields)-i)
|
||||
}
|
||||
info.FsType = fields[i]
|
||||
info.Source = fields[i+1]
|
||||
info.SuperOptions = strings.Split(fields[i+2], ",")
|
||||
infos = append(infos, info)
|
||||
}
|
||||
return infos, nil
|
||||
}
|
||||
|
||||
// isMountPointMatch returns true if the path in mp is the same as dir.
|
||||
// Handles case where mountpoint dir has been renamed due to stale NFS mount.
|
||||
func isMountPointMatch(mp MountPoint, dir string) bool {
|
||||
deletedDir := fmt.Sprintf("%s\\040(deleted)", dir)
|
||||
return ((mp.Path == dir) || (mp.Path == deletedDir))
|
||||
}
|
||||
|
|
@ -19,7 +19,10 @@ limitations under the License.
|
|||
package mount
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
"k8s.io/klog"
|
||||
|
|
@ -66,3 +69,33 @@ func IsCorruptedMnt(err error) bool {
|
|||
|
||||
return false
|
||||
}
|
||||
|
||||
// NormalizeWindowsPath makes sure the given path is a valid path on Windows
|
||||
// systems by making sure all instances of `/` are replaced with `\\`, and the
|
||||
// path beings with `c:`
|
||||
func NormalizeWindowsPath(path string) string {
|
||||
normalizedPath := strings.Replace(path, "/", "\\", -1)
|
||||
if strings.HasPrefix(normalizedPath, "\\") {
|
||||
normalizedPath = "c:" + normalizedPath
|
||||
}
|
||||
return normalizedPath
|
||||
}
|
||||
|
||||
// ValidateDiskNumber : disk number should be a number in [0, 99]
|
||||
func ValidateDiskNumber(disk string) error {
|
||||
diskNum, err := strconv.Atoi(disk)
|
||||
if err != nil {
|
||||
return fmt.Errorf("wrong disk number format: %q, err:%v", disk, err)
|
||||
}
|
||||
|
||||
if diskNum < 0 || diskNum > 99 {
|
||||
return fmt.Errorf("disk number out of range: %q", disk)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// isMountPointMatch determines if the mountpoint matches the dir
|
||||
func isMountPointMatch(mp MountPoint, dir string) bool {
|
||||
return mp.Path == dir
|
||||
}
|
||||
|
|
@ -23,26 +23,19 @@ import (
|
|||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
"k8s.io/klog"
|
||||
utilexec "k8s.io/utils/exec"
|
||||
utilio "k8s.io/utils/io"
|
||||
utilpath "k8s.io/utils/path"
|
||||
)
|
||||
|
||||
const (
|
||||
// How many times to retry for a consistent read of /proc/mounts.
|
||||
maxListTries = 3
|
||||
// Number of fields per line in /proc/mounts as per the fstab man page.
|
||||
expectedNumFieldsPerLine = 6
|
||||
// At least number of fields per line in /proc/<pid>/mountinfo.
|
||||
expectedAtLeastNumFieldsPerMountInfo = 10
|
||||
// Location of the mount file to use
|
||||
procMountsPath = "/proc/mounts"
|
||||
// Location of the mountinfo file
|
||||
|
|
@ -80,7 +73,7 @@ func (mounter *Mounter) Mount(source string, target string, fstype string, optio
|
|||
// Path to mounter binary if containerized mounter is needed. Otherwise, it is set to empty.
|
||||
// All Linux distros are expected to be shipped with a mount utility that a support bind mounts.
|
||||
mounterPath := ""
|
||||
bind, bindOpts, bindRemountOpts := IsBind(options)
|
||||
bind, bindOpts, bindRemountOpts := MakeBindOpts(options)
|
||||
if bind {
|
||||
err := mounter.doMount(mounterPath, defaultMountCommand, source, target, fstype, bindOpts)
|
||||
if err != nil {
|
||||
|
|
@ -102,14 +95,14 @@ func (mounter *Mounter) Mount(source string, target string, fstype string, optio
|
|||
}
|
||||
|
||||
// doMount runs the mount command. mounterPath is the path to mounter binary if containerized mounter is used.
|
||||
func (m *Mounter) doMount(mounterPath string, mountCmd string, source string, target string, fstype string, options []string) error {
|
||||
func (mounter *Mounter) doMount(mounterPath string, mountCmd string, source string, target string, fstype string, options []string) error {
|
||||
mountArgs := MakeMountArgs(source, target, fstype, options)
|
||||
if len(mounterPath) > 0 {
|
||||
mountArgs = append([]string{mountCmd}, mountArgs...)
|
||||
mountCmd = mounterPath
|
||||
}
|
||||
|
||||
if m.withSystemd {
|
||||
if mounter.withSystemd {
|
||||
// Try to run mount via systemd-run --scope. This will escape the
|
||||
// service where kubelet runs and any fuse daemons will be started in a
|
||||
// specific scope. kubelet service than can be restarted without killing
|
||||
|
|
@ -145,7 +138,7 @@ func (m *Mounter) doMount(mounterPath string, mountCmd string, source string, ta
|
|||
if err != nil {
|
||||
args := strings.Join(mountArgs, " ")
|
||||
klog.Errorf("Mount failed: %v\nMounting command: %s\nMounting arguments: %s\nOutput: %s\n", err, mountCmd, args, string(output))
|
||||
return fmt.Errorf("mount failed: %v\nMounting command: %s\nMounting arguments: %s\nOutput: %s\n",
|
||||
return fmt.Errorf("mount failed: %v\nMounting command: %s\nMounting arguments: %s\nOutput: %s",
|
||||
err, mountCmd, args, string(output))
|
||||
}
|
||||
return err
|
||||
|
|
@ -210,7 +203,7 @@ func (mounter *Mounter) Unmount(target string) error {
|
|||
command := exec.Command("umount", target)
|
||||
output, err := command.CombinedOutput()
|
||||
if err != nil {
|
||||
return fmt.Errorf("Unmount failed: %v\nUnmounting arguments: %s\nOutput: %s\n", err, target, string(output))
|
||||
return fmt.Errorf("unmount failed: %v\nUnmounting arguments: %s\nOutput: %s", err, target, string(output))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
@ -220,18 +213,13 @@ func (*Mounter) List() ([]MountPoint, error) {
|
|||
return ListProcMounts(procMountsPath)
|
||||
}
|
||||
|
||||
func (mounter *Mounter) IsMountPointMatch(mp MountPoint, dir string) bool {
|
||||
deletedDir := fmt.Sprintf("%s\\040(deleted)", dir)
|
||||
return ((mp.Path == dir) || (mp.Path == deletedDir))
|
||||
}
|
||||
|
||||
// IsLikelyNotMountPoint determines if a directory is not a mountpoint.
|
||||
// It is fast but not necessarily ALWAYS correct. If the path is in fact
|
||||
// a bind mount from one part of a mount to another it will not be detected.
|
||||
// It also can not distinguish between mountpoints and symbolic links.
|
||||
// mkdir /tmp/a /tmp/b; mount --bind /tmp/a /tmp/b; IsLikelyNotMountPoint("/tmp/b")
|
||||
// will return true. When in fact /tmp/b is a mount point. If this situation
|
||||
// if of interest to you, don't use this function...
|
||||
// is of interest to you, don't use this function...
|
||||
func (mounter *Mounter) IsLikelyNotMountPoint(file string) (bool, error) {
|
||||
stat, err := os.Stat(file)
|
||||
if err != nil {
|
||||
|
|
@ -249,179 +237,24 @@ func (mounter *Mounter) IsLikelyNotMountPoint(file string) (bool, error) {
|
|||
return true, nil
|
||||
}
|
||||
|
||||
// DeviceOpened checks if block device in use by calling Open with O_EXCL flag.
|
||||
// If pathname is not a device, log and return false with nil error.
|
||||
// If open returns errno EBUSY, return true with nil error.
|
||||
// If open returns nil, return false with nil error.
|
||||
// Otherwise, return false with error
|
||||
func (mounter *Mounter) DeviceOpened(pathname string) (bool, error) {
|
||||
return ExclusiveOpenFailsOnDevice(pathname)
|
||||
}
|
||||
|
||||
// PathIsDevice uses FileInfo returned from os.Stat to check if path refers
|
||||
// to a device.
|
||||
func (mounter *Mounter) PathIsDevice(pathname string) (bool, error) {
|
||||
pathType, err := mounter.GetFileType(pathname)
|
||||
isDevice := pathType == FileTypeCharDev || pathType == FileTypeBlockDev
|
||||
return isDevice, err
|
||||
}
|
||||
|
||||
// ExclusiveOpenFailsOnDevice is shared with NsEnterMounter
|
||||
func ExclusiveOpenFailsOnDevice(pathname string) (bool, error) {
|
||||
var isDevice bool
|
||||
finfo, err := os.Stat(pathname)
|
||||
if os.IsNotExist(err) {
|
||||
isDevice = false
|
||||
// GetMountRefs finds all mount references to pathname, returns a
|
||||
// list of paths. Path could be a mountpoint or a normal
|
||||
// directory (for bind mount).
|
||||
func (mounter *Mounter) GetMountRefs(pathname string) ([]string, error) {
|
||||
pathExists, pathErr := PathExists(pathname)
|
||||
if !pathExists {
|
||||
return []string{}, nil
|
||||
} else if IsCorruptedMnt(pathErr) {
|
||||
klog.Warningf("GetMountRefs found corrupted mount at %s, treating as unmounted path", pathname)
|
||||
return []string{}, nil
|
||||
} else if pathErr != nil {
|
||||
return nil, fmt.Errorf("error checking path %s: %v", pathname, pathErr)
|
||||
}
|
||||
// err in call to os.Stat
|
||||
if err != nil {
|
||||
return false, fmt.Errorf(
|
||||
"PathIsDevice failed for path %q: %v",
|
||||
pathname,
|
||||
err)
|
||||
}
|
||||
// path refers to a device
|
||||
if finfo.Mode()&os.ModeDevice != 0 {
|
||||
isDevice = true
|
||||
}
|
||||
|
||||
if !isDevice {
|
||||
klog.Errorf("Path %q is not referring to a device.", pathname)
|
||||
return false, nil
|
||||
}
|
||||
fd, errno := unix.Open(pathname, unix.O_RDONLY|unix.O_EXCL, 0)
|
||||
// If the device is in use, open will return an invalid fd.
|
||||
// When this happens, it is expected that Close will fail and throw an error.
|
||||
defer unix.Close(fd)
|
||||
if errno == nil {
|
||||
// device not in use
|
||||
return false, nil
|
||||
} else if errno == unix.EBUSY {
|
||||
// device is in use
|
||||
return true, nil
|
||||
}
|
||||
// error during call to Open
|
||||
return false, errno
|
||||
}
|
||||
|
||||
//GetDeviceNameFromMount: given a mount point, find the device name from its global mount point
|
||||
func (mounter *Mounter) GetDeviceNameFromMount(mountPath, pluginMountDir string) (string, error) {
|
||||
return GetDeviceNameFromMountLinux(mounter, mountPath, pluginMountDir)
|
||||
}
|
||||
|
||||
func getDeviceNameFromMount(mounter Interface, mountPath, pluginMountDir string) (string, error) {
|
||||
return GetDeviceNameFromMountLinux(mounter, mountPath, pluginMountDir)
|
||||
}
|
||||
|
||||
// GetDeviceNameFromMountLinux find the device name from /proc/mounts in which
|
||||
// the mount path reference should match the given plugin mount directory. In case no mount path reference
|
||||
// matches, returns the volume name taken from its given mountPath
|
||||
// This implementation is shared with NsEnterMounter
|
||||
func GetDeviceNameFromMountLinux(mounter Interface, mountPath, pluginMountDir string) (string, error) {
|
||||
refs, err := mounter.GetMountRefs(mountPath)
|
||||
if err != nil {
|
||||
klog.V(4).Infof("GetMountRefs failed for mount path %q: %v", mountPath, err)
|
||||
return "", err
|
||||
}
|
||||
if len(refs) == 0 {
|
||||
klog.V(4).Infof("Directory %s is not mounted", mountPath)
|
||||
return "", fmt.Errorf("directory %s is not mounted", mountPath)
|
||||
}
|
||||
for _, ref := range refs {
|
||||
if strings.HasPrefix(ref, pluginMountDir) {
|
||||
volumeID, err := filepath.Rel(pluginMountDir, ref)
|
||||
if err != nil {
|
||||
klog.Errorf("Failed to get volume id from mount %s - %v", mountPath, err)
|
||||
return "", err
|
||||
}
|
||||
return volumeID, nil
|
||||
}
|
||||
}
|
||||
|
||||
return path.Base(mountPath), nil
|
||||
}
|
||||
|
||||
// ListProcMounts is shared with NsEnterMounter
|
||||
func ListProcMounts(mountFilePath string) ([]MountPoint, error) {
|
||||
content, err := utilio.ConsistentRead(mountFilePath, maxListTries)
|
||||
realpath, err := filepath.EvalSymlinks(pathname)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return parseProcMounts(content)
|
||||
}
|
||||
|
||||
func parseProcMounts(content []byte) ([]MountPoint, error) {
|
||||
out := []MountPoint{}
|
||||
lines := strings.Split(string(content), "\n")
|
||||
for _, line := range lines {
|
||||
if line == "" {
|
||||
// the last split() item is empty string following the last \n
|
||||
continue
|
||||
}
|
||||
fields := strings.Fields(line)
|
||||
if len(fields) != expectedNumFieldsPerLine {
|
||||
return nil, fmt.Errorf("wrong number of fields (expected %d, got %d): %s", expectedNumFieldsPerLine, len(fields), line)
|
||||
}
|
||||
|
||||
mp := MountPoint{
|
||||
Device: fields[0],
|
||||
Path: fields[1],
|
||||
Type: fields[2],
|
||||
Opts: strings.Split(fields[3], ","),
|
||||
}
|
||||
|
||||
freq, err := strconv.Atoi(fields[4])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
mp.Freq = freq
|
||||
|
||||
pass, err := strconv.Atoi(fields[5])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
mp.Pass = pass
|
||||
|
||||
out = append(out, mp)
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (mounter *Mounter) MakeRShared(path string) error {
|
||||
return DoMakeRShared(path, procMountInfoPath)
|
||||
}
|
||||
|
||||
func (mounter *Mounter) GetFileType(pathname string) (FileType, error) {
|
||||
return getFileType(pathname)
|
||||
}
|
||||
|
||||
func (mounter *Mounter) MakeDir(pathname string) error {
|
||||
err := os.MkdirAll(pathname, os.FileMode(0755))
|
||||
if err != nil {
|
||||
if !os.IsExist(err) {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (mounter *Mounter) MakeFile(pathname string) error {
|
||||
f, err := os.OpenFile(pathname, os.O_CREATE, os.FileMode(0644))
|
||||
defer f.Close()
|
||||
if err != nil {
|
||||
if !os.IsExist(err) {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (mounter *Mounter) ExistsPath(pathname string) (bool, error) {
|
||||
return utilpath.Exists(utilpath.CheckFollowSymlink, pathname)
|
||||
}
|
||||
|
||||
func (mounter *Mounter) EvalHostSymlinks(pathname string) (string, error) {
|
||||
return filepath.EvalSymlinks(pathname)
|
||||
return SearchMountPoints(realpath, procMountInfoPath)
|
||||
}
|
||||
|
||||
// formatAndMount uses unix utils to format and mount the given disk
|
||||
|
|
@ -440,7 +273,7 @@ func (mounter *SafeFormatAndMount) formatAndMount(source string, target string,
|
|||
// Run fsck on the disk to fix repairable issues, only do this for volumes requested as rw.
|
||||
klog.V(4).Infof("Checking for issues with fsck on disk: %s", source)
|
||||
args := []string{"-a", source}
|
||||
out, err := mounter.Exec.Run("fsck", args...)
|
||||
out, err := mounter.Exec.Command("fsck", args...).CombinedOutput()
|
||||
if err != nil {
|
||||
ee, isExitError := err.(utilexec.ExitError)
|
||||
switch {
|
||||
|
|
@ -449,7 +282,7 @@ func (mounter *SafeFormatAndMount) formatAndMount(source string, target string,
|
|||
case isExitError && ee.ExitStatus() == fsckErrorsCorrected:
|
||||
klog.Infof("Device %s has errors which were corrected by fsck.", source)
|
||||
case isExitError && ee.ExitStatus() == fsckErrorsUncorrected:
|
||||
return fmt.Errorf("'fsck' found errors on device %s but could not correct them: %s.", source, string(out))
|
||||
return fmt.Errorf("'fsck' found errors on device %s but could not correct them: %s", source, string(out))
|
||||
case isExitError && ee.ExitStatus() > fsckErrorsUncorrected:
|
||||
klog.Infof("`fsck` error %s", string(out))
|
||||
}
|
||||
|
|
@ -487,7 +320,7 @@ func (mounter *SafeFormatAndMount) formatAndMount(source string, target string,
|
|||
}
|
||||
}
|
||||
klog.Infof("Disk %q appears to be unformatted, attempting to format as type: %q with options: %v", source, fstype, args)
|
||||
_, err := mounter.Exec.Run("mkfs."+fstype, args...)
|
||||
_, err := mounter.Exec.Command("mkfs."+fstype, args...).CombinedOutput()
|
||||
if err == nil {
|
||||
// the disk has been formatted successfully try to mount it again.
|
||||
klog.Infof("Disk successfully formatted (mkfs): %s - %s %s", fstype, source, target)
|
||||
|
|
@ -495,16 +328,14 @@ func (mounter *SafeFormatAndMount) formatAndMount(source string, target string,
|
|||
}
|
||||
klog.Errorf("format of disk %q failed: type:(%q) target:(%q) options:(%q)error:(%v)", source, fstype, target, options, err)
|
||||
return err
|
||||
} else {
|
||||
// Disk is already formatted and failed to mount
|
||||
if len(fstype) == 0 || fstype == existingFormat {
|
||||
// This is mount error
|
||||
return mountErr
|
||||
} else {
|
||||
// Block device is formatted with unexpected filesystem, let the user know
|
||||
return fmt.Errorf("failed to mount the volume as %q, it already contains %s. Mount error: %v", fstype, existingFormat, mountErr)
|
||||
}
|
||||
}
|
||||
// Disk is already formatted and failed to mount
|
||||
if len(fstype) == 0 || fstype == existingFormat {
|
||||
// This is mount error
|
||||
return mountErr
|
||||
}
|
||||
// Block device is formatted with unexpected filesystem, let the user know
|
||||
return fmt.Errorf("failed to mount the volume as %q, it already contains %s. Mount error: %v", fstype, existingFormat, mountErr)
|
||||
}
|
||||
return mountErr
|
||||
}
|
||||
|
|
@ -513,7 +344,7 @@ func (mounter *SafeFormatAndMount) formatAndMount(source string, target string,
|
|||
func (mounter *SafeFormatAndMount) GetDiskFormat(disk string) (string, error) {
|
||||
args := []string{"-p", "-s", "TYPE", "-s", "PTTYPE", "-o", "export", disk}
|
||||
klog.V(4).Infof("Attempting to determine if disk %q is formatted using blkid with args: (%v)", disk, args)
|
||||
dataOut, err := mounter.Exec.Run("blkid", args...)
|
||||
dataOut, err := mounter.Exec.Command("blkid", args...).CombinedOutput()
|
||||
output := string(dataOut)
|
||||
klog.V(4).Infof("Output: %q, err: %v", output, err)
|
||||
|
||||
|
|
@ -562,231 +393,62 @@ func (mounter *SafeFormatAndMount) GetDiskFormat(disk string) (string, error) {
|
|||
return fstype, nil
|
||||
}
|
||||
|
||||
// isShared returns true, if given path is on a mount point that has shared
|
||||
// mount propagation.
|
||||
func isShared(mount string, mountInfoPath string) (bool, error) {
|
||||
info, err := findMountInfo(mount, mountInfoPath)
|
||||
// ListProcMounts is shared with NsEnterMounter
|
||||
func ListProcMounts(mountFilePath string) ([]MountPoint, error) {
|
||||
content, err := utilio.ConsistentRead(mountFilePath, maxListTries)
|
||||
if err != nil {
|
||||
return false, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// parse optional parameters
|
||||
for _, opt := range info.optionalFields {
|
||||
if strings.HasPrefix(opt, "shared:") {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
return false, nil
|
||||
return parseProcMounts(content)
|
||||
}
|
||||
|
||||
// This represents a single line in /proc/<pid>/mountinfo.
|
||||
type mountInfo struct {
|
||||
// Unique ID for the mount (maybe reused after umount).
|
||||
id int
|
||||
// The ID of the parent mount (or of self for the root of this mount namespace's mount tree).
|
||||
parentID int
|
||||
// The value of `st_dev` for files on this filesystem.
|
||||
majorMinor string
|
||||
// The pathname of the directory in the filesystem which forms the root of this mount.
|
||||
root string
|
||||
// Mount source, filesystem-specific information. e.g. device, tmpfs name.
|
||||
source string
|
||||
// Mount point, the pathname of the mount point.
|
||||
mountPoint string
|
||||
// Optional fieds, zero or more fields of the form "tag[:value]".
|
||||
optionalFields []string
|
||||
// The filesystem type in the form "type[.subtype]".
|
||||
fsType string
|
||||
// Per-mount options.
|
||||
mountOptions []string
|
||||
// Per-superblock options.
|
||||
superOptions []string
|
||||
}
|
||||
|
||||
// parseMountInfo parses /proc/xxx/mountinfo.
|
||||
func parseMountInfo(filename string) ([]mountInfo, error) {
|
||||
content, err := utilio.ConsistentRead(filename, maxListTries)
|
||||
if err != nil {
|
||||
return []mountInfo{}, err
|
||||
}
|
||||
contentStr := string(content)
|
||||
infos := []mountInfo{}
|
||||
|
||||
for _, line := range strings.Split(contentStr, "\n") {
|
||||
func parseProcMounts(content []byte) ([]MountPoint, error) {
|
||||
out := []MountPoint{}
|
||||
lines := strings.Split(string(content), "\n")
|
||||
for _, line := range lines {
|
||||
if line == "" {
|
||||
// the last split() item is empty string following the last \n
|
||||
continue
|
||||
}
|
||||
// See `man proc` for authoritative description of format of the file.
|
||||
fields := strings.Fields(line)
|
||||
if len(fields) < expectedAtLeastNumFieldsPerMountInfo {
|
||||
return nil, fmt.Errorf("wrong number of fields in (expected at least %d, got %d): %s", expectedAtLeastNumFieldsPerMountInfo, len(fields), line)
|
||||
if len(fields) != expectedNumFieldsPerLine {
|
||||
return nil, fmt.Errorf("wrong number of fields (expected %d, got %d): %s", expectedNumFieldsPerLine, len(fields), line)
|
||||
}
|
||||
id, err := strconv.Atoi(fields[0])
|
||||
|
||||
mp := MountPoint{
|
||||
Device: fields[0],
|
||||
Path: fields[1],
|
||||
Type: fields[2],
|
||||
Opts: strings.Split(fields[3], ","),
|
||||
}
|
||||
|
||||
freq, err := strconv.Atoi(fields[4])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
parentID, err := strconv.Atoi(fields[1])
|
||||
mp.Freq = freq
|
||||
|
||||
pass, err := strconv.Atoi(fields[5])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
info := mountInfo{
|
||||
id: id,
|
||||
parentID: parentID,
|
||||
majorMinor: fields[2],
|
||||
root: fields[3],
|
||||
mountPoint: fields[4],
|
||||
mountOptions: strings.Split(fields[5], ","),
|
||||
}
|
||||
// All fields until "-" are "optional fields".
|
||||
i := 6
|
||||
for ; i < len(fields) && fields[i] != "-"; i++ {
|
||||
info.optionalFields = append(info.optionalFields, fields[i])
|
||||
}
|
||||
// Parse the rest 3 fields.
|
||||
i += 1
|
||||
if len(fields)-i < 3 {
|
||||
return nil, fmt.Errorf("expect 3 fields in %s, got %d", line, len(fields)-i)
|
||||
}
|
||||
info.fsType = fields[i]
|
||||
info.source = fields[i+1]
|
||||
info.superOptions = strings.Split(fields[i+2], ",")
|
||||
infos = append(infos, info)
|
||||
}
|
||||
return infos, nil
|
||||
}
|
||||
mp.Pass = pass
|
||||
|
||||
func findMountInfo(path, mountInfoPath string) (mountInfo, error) {
|
||||
infos, err := parseMountInfo(mountInfoPath)
|
||||
if err != nil {
|
||||
return mountInfo{}, err
|
||||
out = append(out, mp)
|
||||
}
|
||||
|
||||
// process /proc/xxx/mountinfo in backward order and find the first mount
|
||||
// point that is prefix of 'path' - that's the mount where path resides
|
||||
var info *mountInfo
|
||||
for i := len(infos) - 1; i >= 0; i-- {
|
||||
if PathWithinBase(path, infos[i].mountPoint) {
|
||||
info = &infos[i]
|
||||
break
|
||||
}
|
||||
}
|
||||
if info == nil {
|
||||
return mountInfo{}, fmt.Errorf("cannot find mount point for %q", path)
|
||||
}
|
||||
return *info, nil
|
||||
}
|
||||
|
||||
// DoMakeRShared is common implementation of MakeRShared on Linux. It checks if
|
||||
// path is shared and bind-mounts it as rshared if needed. mountCmd and
|
||||
// mountArgs are expected to contain mount-like command, DoMakeRShared will add
|
||||
// '--bind <path> <path>' and '--make-rshared <path>' to mountArgs.
|
||||
func DoMakeRShared(path string, mountInfoFilename string) error {
|
||||
shared, err := isShared(path, mountInfoFilename)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if shared {
|
||||
klog.V(4).Infof("Directory %s is already on a shared mount", path)
|
||||
return nil
|
||||
}
|
||||
|
||||
klog.V(2).Infof("Bind-mounting %q with shared mount propagation", path)
|
||||
// mount --bind /var/lib/kubelet /var/lib/kubelet
|
||||
if err := syscall.Mount(path, path, "" /*fstype*/, syscall.MS_BIND, "" /*data*/); err != nil {
|
||||
return fmt.Errorf("failed to bind-mount %s: %v", path, err)
|
||||
}
|
||||
|
||||
// mount --make-rshared /var/lib/kubelet
|
||||
if err := syscall.Mount(path, path, "" /*fstype*/, syscall.MS_SHARED|syscall.MS_REC, "" /*data*/); err != nil {
|
||||
return fmt.Errorf("failed to make %s rshared: %v", path, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetSELinux is common implementation of GetSELinuxSupport on Linux.
|
||||
func GetSELinux(path string, mountInfoFilename string) (bool, error) {
|
||||
info, err := findMountInfo(path, mountInfoFilename)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
// "seclabel" can be both in mount options and super options.
|
||||
for _, opt := range info.superOptions {
|
||||
if opt == "seclabel" {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
for _, opt := range info.mountOptions {
|
||||
if opt == "seclabel" {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func (mounter *Mounter) GetMountRefs(pathname string) ([]string, error) {
|
||||
pathExists, pathErr := PathExists(pathname)
|
||||
if !pathExists {
|
||||
return []string{}, nil
|
||||
} else if IsCorruptedMnt(pathErr) {
|
||||
klog.Warningf("GetMountRefs found corrupted mount at %s, treating as unmounted path", pathname)
|
||||
return []string{}, nil
|
||||
} else if pathErr != nil {
|
||||
return nil, fmt.Errorf("error checking path %s: %v", pathname, pathErr)
|
||||
}
|
||||
realpath, err := filepath.EvalSymlinks(pathname)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return SearchMountPoints(realpath, procMountInfoPath)
|
||||
}
|
||||
|
||||
func (mounter *Mounter) GetSELinuxSupport(pathname string) (bool, error) {
|
||||
return GetSELinux(pathname, procMountInfoPath)
|
||||
}
|
||||
|
||||
func (mounter *Mounter) GetFSGroup(pathname string) (int64, error) {
|
||||
realpath, err := filepath.EvalSymlinks(pathname)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return GetFSGroupLinux(realpath)
|
||||
}
|
||||
|
||||
func (mounter *Mounter) GetMode(pathname string) (os.FileMode, error) {
|
||||
return GetModeLinux(pathname)
|
||||
}
|
||||
|
||||
// GetFSGroupLinux is shared between Linux and NsEnterMounter
|
||||
// pathname must already be evaluated for symlinks
|
||||
func GetFSGroupLinux(pathname string) (int64, error) {
|
||||
info, err := os.Stat(pathname)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return int64(info.Sys().(*syscall.Stat_t).Gid), nil
|
||||
}
|
||||
|
||||
// GetModeLinux is shared between Linux and NsEnterMounter
|
||||
func GetModeLinux(pathname string) (os.FileMode, error) {
|
||||
info, err := os.Stat(pathname)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return info.Mode(), nil
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// SearchMountPoints finds all mount references to the source, returns a list of
|
||||
// mountpoints.
|
||||
// This function assumes source cannot be device.
|
||||
// The source can be a mount point or a normal directory (bind mount). We
|
||||
// didn't support device because there is no use case by now.
|
||||
// Some filesystems may share a source name, e.g. tmpfs. And for bind mounting,
|
||||
// it's possible to mount a non-root path of a filesystem, so we need to use
|
||||
// root path and major:minor to represent mount source uniquely.
|
||||
// This implementation is shared between Linux and NsEnterMounter
|
||||
func SearchMountPoints(hostSource, mountInfoPath string) ([]string, error) {
|
||||
mis, err := parseMountInfo(mountInfoPath)
|
||||
mis, err := ParseMountInfo(mountInfoPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -799,11 +461,11 @@ func SearchMountPoints(hostSource, mountInfoPath string) ([]string, error) {
|
|||
// We need search in backward order because it's possible for later mounts
|
||||
// to overlap earlier mounts.
|
||||
for i := len(mis) - 1; i >= 0; i-- {
|
||||
if hostSource == mis[i].mountPoint || PathWithinBase(hostSource, mis[i].mountPoint) {
|
||||
if hostSource == mis[i].MountPoint || PathWithinBase(hostSource, mis[i].MountPoint) {
|
||||
// If it's a mount point or path under a mount point.
|
||||
mountID = mis[i].id
|
||||
rootPath = filepath.Join(mis[i].root, strings.TrimPrefix(hostSource, mis[i].mountPoint))
|
||||
majorMinor = mis[i].majorMinor
|
||||
mountID = mis[i].ID
|
||||
rootPath = filepath.Join(mis[i].Root, strings.TrimPrefix(hostSource, mis[i].MountPoint))
|
||||
majorMinor = mis[i].MajorMinor
|
||||
break
|
||||
}
|
||||
}
|
||||
|
|
@ -814,12 +476,12 @@ func SearchMountPoints(hostSource, mountInfoPath string) ([]string, error) {
|
|||
|
||||
var refs []string
|
||||
for i := range mis {
|
||||
if mis[i].id == mountID {
|
||||
if mis[i].ID == mountID {
|
||||
// Ignore mount entry for mount source itself.
|
||||
continue
|
||||
}
|
||||
if mis[i].root == rootPath && mis[i].majorMinor == majorMinor {
|
||||
refs = append(refs, mis[i].mountPoint)
|
||||
if mis[i].Root == rootPath && mis[i].MajorMinor == majorMinor {
|
||||
refs = append(refs, mis[i].MountPoint)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
// +build !linux,!windows
|
||||
|
||||
/*
|
||||
Copyright 2014 The Kubernetes Authors.
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
package mount
|
||||
|
||||
import (
|
||||
"errors"
|
||||
)
|
||||
|
||||
// Mounter implements mount.Interface for unsupported platforms
|
||||
type Mounter struct {
|
||||
mounterPath string
|
||||
}
|
||||
|
||||
var errUnsupported = errors.New("util/mount on this platform is not supported")
|
||||
|
||||
// New returns a mount.Interface for the current system.
|
||||
// It provides options to override the default mounter behavior.
|
||||
// mounterPath allows using an alternative to `/bin/mount` for mounting.
|
||||
func New(mounterPath string) Interface {
|
||||
return &Mounter{
|
||||
mounterPath: mounterPath,
|
||||
}
|
||||
}
|
||||
|
||||
// Mount always returns an error on unsupported platforms
|
||||
func (mounter *Mounter) Mount(source string, target string, fstype string, options []string) error {
|
||||
return errUnsupported
|
||||
}
|
||||
|
||||
// Unmount always returns an error on unsupported platforms
|
||||
func (mounter *Mounter) Unmount(target string) error {
|
||||
return errUnsupported
|
||||
}
|
||||
|
||||
// List always returns an error on unsupported platforms
|
||||
func (mounter *Mounter) List() ([]MountPoint, error) {
|
||||
return []MountPoint{}, errUnsupported
|
||||
}
|
||||
|
||||
// IsLikelyNotMountPoint always returns an error on unsupported platforms
|
||||
func (mounter *Mounter) IsLikelyNotMountPoint(file string) (bool, error) {
|
||||
return true, errUnsupported
|
||||
}
|
||||
|
||||
// GetMountRefs always returns an error on unsupported platforms
|
||||
func (mounter *Mounter) GetMountRefs(pathname string) ([]string, error) {
|
||||
return nil, errUnsupported
|
||||
}
|
||||
|
||||
func (mounter *SafeFormatAndMount) formatAndMount(source string, target string, fstype string, options []string) error {
|
||||
return mounter.Interface.Mount(source, target, fstype, options)
|
||||
}
|
||||
|
||||
func (mounter *SafeFormatAndMount) diskLooksUnformatted(disk string) (bool, error) {
|
||||
return true, errUnsupported
|
||||
}
|
||||
|
|
@ -22,14 +22,12 @@ import (
|
|||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"k8s.io/klog"
|
||||
utilexec "k8s.io/utils/exec"
|
||||
"k8s.io/utils/keymutex"
|
||||
|
||||
utilpath "k8s.io/utils/path"
|
||||
)
|
||||
|
||||
|
|
@ -55,7 +53,7 @@ var getSMBMountMutex = keymutex.NewHashed(0)
|
|||
// Mount : mounts source to target with given options.
|
||||
// currently only supports cifs(smb), bind mount(for disk)
|
||||
func (mounter *Mounter) Mount(source string, target string, fstype string, options []string) error {
|
||||
target = normalizeWindowsPath(target)
|
||||
target = NormalizeWindowsPath(target)
|
||||
|
||||
if source == "tmpfs" {
|
||||
klog.V(3).Infof("mounting source (%q), target (%q), with options (%q)", source, target, options)
|
||||
|
|
@ -72,9 +70,9 @@ func (mounter *Mounter) Mount(source string, target string, fstype string, optio
|
|||
bindSource := source
|
||||
|
||||
// tell it's going to mount azure disk or azure file according to options
|
||||
if bind, _, _ := IsBind(options); bind {
|
||||
if bind, _, _ := MakeBindOpts(options); bind {
|
||||
// mount azure disk
|
||||
bindSource = normalizeWindowsPath(source)
|
||||
bindSource = NormalizeWindowsPath(source)
|
||||
} else {
|
||||
if len(options) < 2 {
|
||||
klog.Warningf("mount options(%q) command number(%d) less than 2, source:%q, target:%q, skip mounting",
|
||||
|
|
@ -155,7 +153,7 @@ func removeSMBMapping(remotepath string) (string, error) {
|
|||
// Unmount unmounts the target.
|
||||
func (mounter *Mounter) Unmount(target string) error {
|
||||
klog.V(4).Infof("azureMount: Unmount target (%q)", target)
|
||||
target = normalizeWindowsPath(target)
|
||||
target = NormalizeWindowsPath(target)
|
||||
if output, err := exec.Command("cmd", "/c", "rmdir", target).CombinedOutput(); err != nil {
|
||||
klog.Errorf("rmdir failed: %v, output: %q", err, string(output))
|
||||
return err
|
||||
|
|
@ -168,11 +166,6 @@ func (mounter *Mounter) List() ([]MountPoint, error) {
|
|||
return []MountPoint{}, nil
|
||||
}
|
||||
|
||||
// IsMountPointMatch determines if the mountpoint matches the dir
|
||||
func (mounter *Mounter) IsMountPointMatch(mp MountPoint, dir string) bool {
|
||||
return mp.Path == dir
|
||||
}
|
||||
|
||||
// IsLikelyNotMountPoint determines if a directory is not a mountpoint.
|
||||
func (mounter *Mounter) IsLikelyNotMountPoint(file string) (bool, error) {
|
||||
stat, err := os.Lstat(file)
|
||||
|
|
@ -185,7 +178,7 @@ func (mounter *Mounter) IsLikelyNotMountPoint(file string) (bool, error) {
|
|||
if err != nil {
|
||||
return true, fmt.Errorf("readlink error: %v", err)
|
||||
}
|
||||
exists, err := mounter.ExistsPath(target)
|
||||
exists, err := utilpath.Exists(utilpath.CheckFollowSymlink, target)
|
||||
if err != nil {
|
||||
return true, err
|
||||
}
|
||||
|
|
@ -195,90 +188,19 @@ func (mounter *Mounter) IsLikelyNotMountPoint(file string) (bool, error) {
|
|||
return true, nil
|
||||
}
|
||||
|
||||
// GetDeviceNameFromMount given a mnt point, find the device
|
||||
func (mounter *Mounter) GetDeviceNameFromMount(mountPath, pluginMountDir string) (string, error) {
|
||||
return getDeviceNameFromMount(mounter, mountPath, pluginMountDir)
|
||||
}
|
||||
|
||||
// getDeviceNameFromMount find the device(drive) name in which
|
||||
// the mount path reference should match the given plugin mount directory. In case no mount path reference
|
||||
// matches, returns the volume name taken from its given mountPath
|
||||
func getDeviceNameFromMount(mounter Interface, mountPath, pluginMountDir string) (string, error) {
|
||||
refs, err := mounter.GetMountRefs(mountPath)
|
||||
if err != nil {
|
||||
klog.V(4).Infof("GetMountRefs failed for mount path %q: %v", mountPath, err)
|
||||
return "", err
|
||||
// GetMountRefs : empty implementation here since there is no place to query all mount points on Windows
|
||||
func (mounter *Mounter) GetMountRefs(pathname string) ([]string, error) {
|
||||
windowsPath := NormalizeWindowsPath(pathname)
|
||||
pathExists, pathErr := PathExists(windowsPath)
|
||||
if !pathExists {
|
||||
return []string{}, nil
|
||||
} else if IsCorruptedMnt(pathErr) {
|
||||
klog.Warningf("GetMountRefs found corrupted mount at %s, treating as unmounted path", windowsPath)
|
||||
return []string{}, nil
|
||||
} else if pathErr != nil {
|
||||
return nil, fmt.Errorf("error checking path %s: %v", windowsPath, pathErr)
|
||||
}
|
||||
if len(refs) == 0 {
|
||||
return "", fmt.Errorf("directory %s is not mounted", mountPath)
|
||||
}
|
||||
basemountPath := normalizeWindowsPath(pluginMountDir)
|
||||
for _, ref := range refs {
|
||||
if strings.Contains(ref, basemountPath) {
|
||||
volumeID, err := filepath.Rel(normalizeWindowsPath(basemountPath), ref)
|
||||
if err != nil {
|
||||
klog.Errorf("Failed to get volume id from mount %s - %v", mountPath, err)
|
||||
return "", err
|
||||
}
|
||||
return volumeID, nil
|
||||
}
|
||||
}
|
||||
|
||||
return path.Base(mountPath), nil
|
||||
}
|
||||
|
||||
// DeviceOpened determines if the device is in use elsewhere
|
||||
func (mounter *Mounter) DeviceOpened(pathname string) (bool, error) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// PathIsDevice determines if a path is a device.
|
||||
func (mounter *Mounter) PathIsDevice(pathname string) (bool, error) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// MakeRShared checks that given path is on a mount with 'rshared' mount
|
||||
// propagation. Empty implementation here.
|
||||
func (mounter *Mounter) MakeRShared(path string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetFileType checks for sockets/block/character devices
|
||||
func (mounter *Mounter) GetFileType(pathname string) (FileType, error) {
|
||||
return getFileType(pathname)
|
||||
}
|
||||
|
||||
// MakeFile creates a new directory
|
||||
func (mounter *Mounter) MakeDir(pathname string) error {
|
||||
err := os.MkdirAll(pathname, os.FileMode(0755))
|
||||
if err != nil {
|
||||
if !os.IsExist(err) {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// MakeFile creates an empty file
|
||||
func (mounter *Mounter) MakeFile(pathname string) error {
|
||||
f, err := os.OpenFile(pathname, os.O_CREATE, os.FileMode(0644))
|
||||
defer f.Close()
|
||||
if err != nil {
|
||||
if !os.IsExist(err) {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ExistsPath checks whether the path exists
|
||||
func (mounter *Mounter) ExistsPath(pathname string) (bool, error) {
|
||||
return utilpath.Exists(utilpath.CheckFollowSymlink, pathname)
|
||||
}
|
||||
|
||||
// EvalHostSymlinks returns the path name after evaluating symlinks
|
||||
func (mounter *Mounter) EvalHostSymlinks(pathname string) (string, error) {
|
||||
return filepath.EvalSymlinks(pathname)
|
||||
return []string{pathname}, nil
|
||||
}
|
||||
|
||||
func (mounter *SafeFormatAndMount) formatAndMount(source string, target string, fstype string, options []string) error {
|
||||
|
|
@ -298,7 +220,7 @@ func (mounter *SafeFormatAndMount) formatAndMount(source string, target string,
|
|||
// format disk if it is unformatted(raw)
|
||||
cmd := fmt.Sprintf("Get-Disk -Number %s | Where partitionstyle -eq 'raw' | Initialize-Disk -PartitionStyle MBR -PassThru"+
|
||||
" | New-Partition -AssignDriveLetter -UseMaximumSize | Format-Volume -FileSystem %s -Confirm:$false", source, fstype)
|
||||
if output, err := mounter.Exec.Run("powershell", "/c", cmd); err != nil {
|
||||
if output, err := mounter.Exec.Command("powershell", "/c", cmd).CombinedOutput(); err != nil {
|
||||
return fmt.Errorf("diskMount: format disk failed, error: %v, output: %q", err, string(output))
|
||||
}
|
||||
klog.V(4).Infof("diskMount: Disk successfully formatted, disk: %q, fstype: %q", source, fstype)
|
||||
|
|
@ -308,41 +230,19 @@ func (mounter *SafeFormatAndMount) formatAndMount(source string, target string,
|
|||
return err
|
||||
}
|
||||
driverPath := driveLetter + ":"
|
||||
target = normalizeWindowsPath(target)
|
||||
target = NormalizeWindowsPath(target)
|
||||
klog.V(4).Infof("Attempting to formatAndMount disk: %s %s %s", fstype, driverPath, target)
|
||||
if output, err := mounter.Exec.Run("cmd", "/c", "mklink", "/D", target, driverPath); err != nil {
|
||||
if output, err := mounter.Exec.Command("cmd", "/c", "mklink", "/D", target, driverPath).CombinedOutput(); err != nil {
|
||||
klog.Errorf("mklink failed: %v, output: %q", err, string(output))
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func normalizeWindowsPath(path string) string {
|
||||
normalizedPath := strings.Replace(path, "/", "\\", -1)
|
||||
if strings.HasPrefix(normalizedPath, "\\") {
|
||||
normalizedPath = "c:" + normalizedPath
|
||||
}
|
||||
return normalizedPath
|
||||
}
|
||||
|
||||
// ValidateDiskNumber : disk number should be a number in [0, 99]
|
||||
func ValidateDiskNumber(disk string) error {
|
||||
diskNum, err := strconv.Atoi(disk)
|
||||
if err != nil {
|
||||
return fmt.Errorf("wrong disk number format: %q, err:%v", disk, err)
|
||||
}
|
||||
|
||||
if diskNum < 0 || diskNum > 99 {
|
||||
return fmt.Errorf("disk number out of range: %q", disk)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Get drive letter according to windows disk number
|
||||
func getDriveLetterByDiskNumber(diskNum string, exec Exec) (string, error) {
|
||||
func getDriveLetterByDiskNumber(diskNum string, exec utilexec.Interface) (string, error) {
|
||||
cmd := fmt.Sprintf("(Get-Partition -DiskNumber %s).DriveLetter", diskNum)
|
||||
output, err := exec.Run("powershell", "/c", cmd)
|
||||
output, err := exec.Command("powershell", "/c", cmd).CombinedOutput()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("azureMount: Get Drive Letter failed: %v, output: %q", err, string(output))
|
||||
}
|
||||
|
|
@ -378,37 +278,3 @@ func getAllParentLinks(path string) ([]string, error) {
|
|||
|
||||
return links, nil
|
||||
}
|
||||
|
||||
// GetMountRefs : empty implementation here since there is no place to query all mount points on Windows
|
||||
func (mounter *Mounter) GetMountRefs(pathname string) ([]string, error) {
|
||||
windowsPath := normalizeWindowsPath(pathname)
|
||||
pathExists, pathErr := PathExists(windowsPath)
|
||||
if !pathExists {
|
||||
return []string{}, nil
|
||||
} else if IsCorruptedMnt(pathErr) {
|
||||
klog.Warningf("GetMountRefs found corrupted mount at %s, treating as unmounted path", windowsPath)
|
||||
return []string{}, nil
|
||||
} else if pathErr != nil {
|
||||
return nil, fmt.Errorf("error checking path %s: %v", windowsPath, pathErr)
|
||||
}
|
||||
return []string{pathname}, nil
|
||||
}
|
||||
|
||||
// Note that on windows, it always returns 0. We actually don't set FSGroup on
|
||||
// windows platform, see SetVolumeOwnership implementation.
|
||||
func (mounter *Mounter) GetFSGroup(pathname string) (int64, error) {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
func (mounter *Mounter) GetSELinuxSupport(pathname string) (bool, error) {
|
||||
// Windows does not support SELinux.
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func (mounter *Mounter) GetMode(pathname string) (os.FileMode, error) {
|
||||
info, err := os.Stat(pathname)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return info.Mode(), nil
|
||||
}
|
||||
|
|
@ -16,7 +16,102 @@ limitations under the License.
|
|||
|
||||
package net
|
||||
|
||||
import "net"
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"math"
|
||||
"math/big"
|
||||
"net"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// ParseCIDRs parses a list of cidrs and return error if any is invalid.
|
||||
// order is maintained
|
||||
func ParseCIDRs(cidrsString []string) ([]*net.IPNet, error) {
|
||||
cidrs := make([]*net.IPNet, 0, len(cidrsString))
|
||||
for _, cidrString := range cidrsString {
|
||||
_, cidr, err := net.ParseCIDR(cidrString)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to parse cidr value:%q with error:%v", cidrString, err)
|
||||
}
|
||||
cidrs = append(cidrs, cidr)
|
||||
}
|
||||
return cidrs, nil
|
||||
}
|
||||
|
||||
// IsDualStackIPs returns if a slice of ips is:
|
||||
// - all are valid ips
|
||||
// - at least one ip from each family (v4 or v6)
|
||||
func IsDualStackIPs(ips []net.IP) (bool, error) {
|
||||
v4Found := false
|
||||
v6Found := false
|
||||
for _, ip := range ips {
|
||||
if ip == nil {
|
||||
return false, fmt.Errorf("ip %v is invalid", ip)
|
||||
}
|
||||
|
||||
if v4Found && v6Found {
|
||||
continue
|
||||
}
|
||||
|
||||
if IsIPv6(ip) {
|
||||
v6Found = true
|
||||
continue
|
||||
}
|
||||
|
||||
v4Found = true
|
||||
}
|
||||
|
||||
return (v4Found && v6Found), nil
|
||||
}
|
||||
|
||||
// IsDualStackIPStrings returns if
|
||||
// - all are valid ips
|
||||
// - at least one ip from each family (v4 or v6)
|
||||
func IsDualStackIPStrings(ips []string) (bool, error) {
|
||||
parsedIPs := make([]net.IP, 0, len(ips))
|
||||
for _, ip := range ips {
|
||||
parsedIP := net.ParseIP(ip)
|
||||
parsedIPs = append(parsedIPs, parsedIP)
|
||||
}
|
||||
return IsDualStackIPs(parsedIPs)
|
||||
}
|
||||
|
||||
// IsDualStackCIDRs returns if
|
||||
// - all are valid cidrs
|
||||
// - at least one cidr from each family (v4 or v6)
|
||||
func IsDualStackCIDRs(cidrs []*net.IPNet) (bool, error) {
|
||||
v4Found := false
|
||||
v6Found := false
|
||||
for _, cidr := range cidrs {
|
||||
if cidr == nil {
|
||||
return false, fmt.Errorf("cidr %v is invalid", cidr)
|
||||
}
|
||||
|
||||
if v4Found && v6Found {
|
||||
continue
|
||||
}
|
||||
|
||||
if IsIPv6(cidr.IP) {
|
||||
v6Found = true
|
||||
continue
|
||||
}
|
||||
v4Found = true
|
||||
}
|
||||
|
||||
return v4Found && v6Found, nil
|
||||
}
|
||||
|
||||
// IsDualStackCIDRStrings returns if
|
||||
// - all are valid cidrs
|
||||
// - at least one cidr from each family (v4 or v6)
|
||||
func IsDualStackCIDRStrings(cidrs []string) (bool, error) {
|
||||
parsedCIDRs, err := ParseCIDRs(cidrs)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return IsDualStackCIDRs(parsedCIDRs)
|
||||
}
|
||||
|
||||
// IsIPv6 returns if netIP is IPv6.
|
||||
func IsIPv6(netIP net.IP) bool {
|
||||
|
|
@ -35,3 +130,60 @@ func IsIPv6CIDRString(cidr string) bool {
|
|||
ip, _, _ := net.ParseCIDR(cidr)
|
||||
return IsIPv6(ip)
|
||||
}
|
||||
|
||||
// IsIPv6CIDR returns if a cidr is ipv6
|
||||
func IsIPv6CIDR(cidr *net.IPNet) bool {
|
||||
ip := cidr.IP
|
||||
return IsIPv6(ip)
|
||||
}
|
||||
|
||||
// ParsePort parses a string representing an IP port. If the string is not a
|
||||
// valid port number, this returns an error.
|
||||
func ParsePort(port string, allowZero bool) (int, error) {
|
||||
portInt, err := strconv.ParseUint(port, 10, 16)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if portInt == 0 && !allowZero {
|
||||
return 0, errors.New("0 is not a valid port number")
|
||||
}
|
||||
return int(portInt), nil
|
||||
}
|
||||
|
||||
// BigForIP creates a big.Int based on the provided net.IP
|
||||
func BigForIP(ip net.IP) *big.Int {
|
||||
b := ip.To4()
|
||||
if b == nil {
|
||||
b = ip.To16()
|
||||
}
|
||||
return big.NewInt(0).SetBytes(b)
|
||||
}
|
||||
|
||||
// AddIPOffset adds the provided integer offset to a base big.Int representing a
|
||||
// net.IP
|
||||
func AddIPOffset(base *big.Int, offset int) net.IP {
|
||||
return net.IP(big.NewInt(0).Add(base, big.NewInt(int64(offset))).Bytes())
|
||||
}
|
||||
|
||||
// RangeSize returns the size of a range in valid addresses.
|
||||
// returns the size of the subnet (or math.MaxInt64 if the range size would overflow int64)
|
||||
func RangeSize(subnet *net.IPNet) int64 {
|
||||
ones, bits := subnet.Mask.Size()
|
||||
if bits == 32 && (bits-ones) >= 31 || bits == 128 && (bits-ones) >= 127 {
|
||||
return 0
|
||||
}
|
||||
// this checks that we are not overflowing an int64
|
||||
if bits-ones >= 63 {
|
||||
return math.MaxInt64
|
||||
}
|
||||
return int64(1) << uint(bits-ones)
|
||||
}
|
||||
|
||||
// GetIndexedIP returns a net.IP that is subnet.IP + index in the contiguous IP space.
|
||||
func GetIndexedIP(subnet *net.IPNet, index int) (net.IP, error) {
|
||||
ip := AddIPOffset(BigForIP(subnet.IP), index)
|
||||
if !subnet.Contains(ip) {
|
||||
return nil, fmt.Errorf("can't generate IP with index %d from subnet. subnet too small. subnet: %q", index, subnet)
|
||||
}
|
||||
return ip, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ func Int64Ptr(i int64) *int64 {
|
|||
return &i
|
||||
}
|
||||
|
||||
// Int32PtrDerefOr dereference the int32 ptr and returns it i not nil,
|
||||
// Int32PtrDerefOr dereference the int32 ptr and returns it if not nil,
|
||||
// else returns def.
|
||||
func Int32PtrDerefOr(ptr *int32, def int32) int32 {
|
||||
if ptr != nil {
|
||||
|
|
|
|||
|
|
@ -25,31 +25,55 @@ import (
|
|||
"k8s.io/klog"
|
||||
)
|
||||
|
||||
// Field is a key value pair that provides additional details about the trace.
|
||||
type Field struct {
|
||||
Key string
|
||||
Value interface{}
|
||||
}
|
||||
|
||||
func (f Field) format() string {
|
||||
return fmt.Sprintf("%s:%v", f.Key, f.Value)
|
||||
}
|
||||
|
||||
func writeFields(b *bytes.Buffer, l []Field) {
|
||||
for i, f := range l {
|
||||
b.WriteString(f.format())
|
||||
if i < len(l)-1 {
|
||||
b.WriteString(",")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type traceStep struct {
|
||||
stepTime time.Time
|
||||
msg string
|
||||
fields []Field
|
||||
}
|
||||
|
||||
// Trace keeps track of a set of "steps" and allows us to log a specific
|
||||
// step if it took longer than its share of the total allowed time
|
||||
type Trace struct {
|
||||
name string
|
||||
fields []Field
|
||||
startTime time.Time
|
||||
steps []traceStep
|
||||
}
|
||||
|
||||
// New creates a Trace with the specified name
|
||||
func New(name string) *Trace {
|
||||
return &Trace{name, time.Now(), nil}
|
||||
// New creates a Trace with the specified name. The name identifies the operation to be traced. The
|
||||
// Fields add key value pairs to provide additional details about the trace, such as operation inputs.
|
||||
func New(name string, fields ...Field) *Trace {
|
||||
return &Trace{name: name, startTime: time.Now(), fields: fields}
|
||||
}
|
||||
|
||||
// Step adds a new step with a specific message
|
||||
func (t *Trace) Step(msg string) {
|
||||
// Step adds a new step with a specific message. Call this at the end of an execution step to record
|
||||
// how long it took. The Fields add key value pairs to provide additional details about the trace
|
||||
// step.
|
||||
func (t *Trace) Step(msg string, fields ...Field) {
|
||||
if t.steps == nil {
|
||||
// traces almost always have less than 6 steps, do this to avoid more than a single allocation
|
||||
t.steps = make([]traceStep, 0, 6)
|
||||
}
|
||||
t.steps = append(t.steps, traceStep{time.Now(), msg})
|
||||
t.steps = append(t.steps, traceStep{stepTime: time.Now(), msg: msg, fields: fields})
|
||||
}
|
||||
|
||||
// Log is used to dump all the steps in the Trace
|
||||
|
|
@ -64,12 +88,23 @@ func (t *Trace) logWithStepThreshold(stepThreshold time.Duration) {
|
|||
endTime := time.Now()
|
||||
|
||||
totalTime := endTime.Sub(t.startTime)
|
||||
buffer.WriteString(fmt.Sprintf("Trace[%d]: %q (started: %v) (total time: %v):\n", tracenum, t.name, t.startTime, totalTime))
|
||||
buffer.WriteString(fmt.Sprintf("Trace[%d]: %q ", tracenum, t.name))
|
||||
if len(t.fields) > 0 {
|
||||
writeFields(&buffer, t.fields)
|
||||
buffer.WriteString(" ")
|
||||
}
|
||||
buffer.WriteString(fmt.Sprintf("(started: %v) (total time: %v):\n", t.startTime, totalTime))
|
||||
lastStepTime := t.startTime
|
||||
for _, step := range t.steps {
|
||||
stepDuration := step.stepTime.Sub(lastStepTime)
|
||||
if stepThreshold == 0 || stepDuration > stepThreshold || klog.V(4) {
|
||||
buffer.WriteString(fmt.Sprintf("Trace[%d]: [%v] [%v] %v\n", tracenum, step.stepTime.Sub(t.startTime), stepDuration, step.msg))
|
||||
buffer.WriteString(fmt.Sprintf("Trace[%d]: [%v] [%v] ", tracenum, step.stepTime.Sub(t.startTime), stepDuration))
|
||||
buffer.WriteString(step.msg)
|
||||
if len(step.fields) > 0 {
|
||||
buffer.WriteString(" ")
|
||||
writeFields(&buffer, step.fields)
|
||||
}
|
||||
buffer.WriteString("\n")
|
||||
}
|
||||
lastStepTime = step.stepTime
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue