// Copyright 2018 The Prometheus 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 procfsimport ()// For the proc file format details,// see https://elixir.bootlin.com/linux/v4.17/source/net/unix/af_unix.c#L2815// and https://elixir.bootlin.com/linux/latest/source/include/uapi/linux/net.h#L48.// Constants for the various /proc/net/unix enumerations.// TODO: match against x/sys/unix or similar?const ( netUnixTypeStream = 1 netUnixTypeDgram = 2 netUnixTypeSeqpacket = 5 netUnixFlagDefault = 0 netUnixFlagListen = 1 << 16 netUnixStateUnconnected = 1 netUnixStateConnecting = 2 netUnixStateConnected = 3 netUnixStateDisconnected = 4)// NetUNIXType is the type of the type field.typeNetUNIXTypeuint64// NetUNIXFlags is the type of the flags field.typeNetUNIXFlagsuint64// NetUNIXState is the type of the state field.typeNetUNIXStateuint64// NetUNIXLine represents a line of /proc/net/unix.typeNetUNIXLinestruct { KernelPtr string RefCount uint64 Protocol uint64 Flags NetUNIXFlags Type NetUNIXType State NetUNIXState Inode uint64 Path string}// NetUNIX holds the data read from /proc/net/unix.typeNetUNIXstruct { Rows []*NetUNIXLine}// NetUNIX returns data read from /proc/net/unix.func ( FS) () (*NetUNIX, error) {returnreadNetUNIX(.proc.Path("net/unix"))}// readNetUNIX reads data in /proc/net/unix format from the specified file.func readNetUNIX( string) (*NetUNIX, error) {// This file could be quite large and a streaming read is desirable versus // reading the entire contents at once. , := os.Open()if != nil {returnnil, }defer .Close()returnparseNetUNIX()}// parseNetUNIX creates a NetUnix structure from the incoming stream.func parseNetUNIX( io.Reader) (*NetUNIX, error) {// Begin scanning by checking for the existence of Inode. := bufio.NewScanner() .Scan()// From the man page of proc(5), it does not contain an Inode field, // but in actually it exists. This code works for both cases. := strings.Contains(.Text(), "Inode")// Expect a minimum number of fields, but Inode and Path are optional: // Num RefCount Protocol Flags Type St Inode Path := 6if { ++ }varNetUNIXfor .Scan() { := .Text() , := .parseLine(, , )if != nil {returnnil, fmt.Errorf("%w: /proc/net/unix encountered data %q: %w", ErrFileParse, , ) } .Rows = append(.Rows, ) }if := .Err(); != nil {returnnil, fmt.Errorf("%w: /proc/net/unix encountered data: %w", ErrFileParse, ) }return &, nil}func ( *NetUNIX) ( string, bool, int) (*NetUNIXLine, error) { := strings.Fields() := len()if < {returnnil, fmt.Errorf("%w: expected at least %d fields but got %d", ErrFileParse, , ) }// Field offsets are as follows: // Num RefCount Protocol Flags Type St Inode Path := strings.TrimSuffix([0], ":") , := .parseUsers([1])if != nil {returnnil, fmt.Errorf("%w: ref count %q: %w", ErrFileParse, [1], ) } , := .parseFlags([3])if != nil {returnnil, fmt.Errorf("%w: Unable to parse flags %q: %w", ErrFileParse, [3], ) } , := .parseType([4])if != nil {returnnil, fmt.Errorf("%w: Failed to parse type %q: %w", ErrFileParse, [4], ) } , := .parseState([5])if != nil {returnnil, fmt.Errorf("%w: Failed to parse state %q: %w", ErrFileParse, [5], ) }varuint64if { , = .parseInode([6])if != nil {returnnil, fmt.Errorf("%w failed to parse inode %q: %w", ErrFileParse, [6], ) } } := &NetUNIXLine{KernelPtr: ,RefCount: ,Type: ,Flags: ,State: ,Inode: , }// Path field is optional.if > {// Path occurs at either index 6 or 7 depending on whether inode is // already present. := 7if ! { -- } .Path = [] }return , nil}func ( NetUNIX) ( string) (uint64, error) {returnstrconv.ParseUint(, 16, 32)}func ( NetUNIX) ( string) (NetUNIXType, error) { , := strconv.ParseUint(, 16, 16)if != nil {return0, }returnNetUNIXType(), nil}func ( NetUNIX) ( string) (NetUNIXFlags, error) { , := strconv.ParseUint(, 16, 32)if != nil {return0, }returnNetUNIXFlags(), nil}func ( NetUNIX) ( string) (NetUNIXState, error) { , := strconv.ParseInt(, 16, 8)if != nil {return0, }returnNetUNIXState(), nil}func ( NetUNIX) ( string) (uint64, error) {returnstrconv.ParseUint(, 10, 64)}func ( NetUNIXType) () string {switch {casenetUnixTypeStream:return"stream"casenetUnixTypeDgram:return"dgram"casenetUnixTypeSeqpacket:return"seqpacket" }return"unknown"}func ( NetUNIXFlags) () string {switch {casenetUnixFlagListen:return"listen"default:return"default" }}func ( NetUNIXState) () string {switch {casenetUnixStateUnconnected:return"unconnected"casenetUnixStateConnecting:return"connecting"casenetUnixStateConnected:return"connected"casenetUnixStateDisconnected:return"disconnected" }return"unknown"}
The pages are generated with Goldsv0.8.2. (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu.
PR and bug reports are welcome and can be submitted to the issue list.
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds.