Replace kubernetes mount code with utils

This will remove one of the main dependencies on the
kubernetes/kubernetes repo.
This commit is contained in:
Justin Santa Barbara 2019-12-07 16:46:22 -05:00
parent 5ecf8d9aeb
commit fc21f4255f
97 changed files with 1364 additions and 11661 deletions

2
go.mod
View File

@ -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
View File

@ -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=

View File

@ -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

View File

@ -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",
],
)

View File

@ -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"

View File

@ -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(""),
}

View File

@ -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": [],

View File

@ -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")
}

View File

@ -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
}

View File

@ -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",
],
)

View File

@ -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)
}

View File

@ -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()
}

View File

@ -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

View File

@ -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",
],
)

View File

@ -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{}

View File

@ -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: 你好, 世界!
}

View File

@ -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")
}
}

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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
}

View File

@ -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__"],

View File

@ -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
)

View File

@ -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
)

View File

@ -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
)

View File

@ -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
)

View File

@ -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
)

View File

@ -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
)

View File

@ -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
)

View File

@ -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"],

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

199
vendor/golang.org/x/net/ipv4/gen.go generated vendored
View File

@ -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
}

View File

@ -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"],

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

199
vendor/golang.org/x/net/ipv6/gen.go generated vendored
View File

@ -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
}

View File

@ -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)
}
}

View File

@ -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)
}

View File

@ -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
`

View File

@ -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
`

View File

@ -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
`

View File

@ -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
`

View File

@ -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)`

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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
)

View File

@ -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 := &registry{}
if err := xml.NewDecoder(r).Decode(&reg); 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())
}

View File

@ -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
)

View File

@ -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)
}
}
}

View File

@ -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
)

View File

@ -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())
}

View File

@ -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
}

115
vendor/golang.org/x/text/width/gen.go generated vendored
View File

@ -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 (U+FF21 -> U+0041)
// -> 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())
}

View File

@ -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)
})
}

View File

@ -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
)

View File

@ -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))
}
}
}
}

View File

@ -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
}

View File

@ -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)
}

View File

@ -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": [],
}),
)

View File

@ -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
}

View File

@ -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
}

View File

@ -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")
}

View File

@ -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)
}

View File

@ -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
vendor/k8s.io/utils/io/BUILD.bazel generated vendored
View File

@ -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"],

View File

@ -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
}

62
vendor/k8s.io/utils/mount/BUILD.bazel generated vendored Normal file
View File

@ -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": [],
}),
)

View File

@ -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"

View File

@ -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")
}

View File

@ -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")
}

View File

@ -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
}

140
vendor/k8s.io/utils/mount/mount_helper_unix.go generated vendored Normal file
View File

@ -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))
}

View File

@ -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
}

View File

@ -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)
}
}

72
vendor/k8s.io/utils/mount/mount_unsupported.go generated vendored Normal file
View File

@ -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
}

View File

@ -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
}

154
vendor/k8s.io/utils/net/net.go generated vendored
View File

@ -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
}

View File

@ -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 {

51
vendor/k8s.io/utils/trace/trace.go generated vendored
View File

@ -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
}

835
vendor/modules.txt vendored

File diff suppressed because it is too large Load Diff