Added devp-deploy to rbd-exporter

This commit is contained in:
Пивкин Александр Николаевич 2026-01-02 16:13:44 +03:00
parent 0e1294eb8e
commit 77c0e5419c
10 changed files with 364 additions and 0 deletions

View File

@ -0,0 +1,62 @@
package ftp
import (
"bufio"
"fmt"
"net"
"strings"
)
type Conn struct {
conn net.Conn
dataType dataType
dataPort *dataPort
rootDir string
workDir string
}
func NewConn(conn net.Conn, rootDir string) *Conn {
return &Conn{
conn: conn,
rootDir: rootDir,
workDir: "/",
}
}
func Serve (c *Conn) {
c.respond(status220)
s := bufio.NewScanner(c.conn)
for s.Scan() {
input := strings.Fields(s.Text())
if len(input) == 0 {
continue
}
command, args := input[0], input[1:]
fmt.Printf("<< %s %v", command, args)
switch command {
case "CWD": // cd
c.cwd(args)
case "LIST": // ls
c.list(args)
case "PORT":
c.port(args)
case "USER":
c.user(args)
case "QUIT": // close
c.respond(status221)
return
case "RETR": // get
c.retr(args)
case "TYPE":
c.setDataType(args)
default:
c.respond(status502)
}
}
if s.Err() != nil {
fmt.Print(s.Err())
}
}

View File

@ -0,0 +1,25 @@
package ftp
import (
"fmt"
"os"
"path/filepath"
)
func (c *Conn) cwd(args []string) {
if len(args) != 1 {
c.respond(status501)
return
}
workDir := filepath.Join(c.workDir, args[0])
absPath := filepath.Join(c.rootDir, workDir)
_, err := os.Stat(absPath)
if err != nil {
fmt.Print(err)
c.respond(status550)
return
}
c.workDir = workDir
c.respond(status200)
}

View File

@ -0,0 +1,65 @@
package ftp
import "net"
func (c *Conn) dataConnect() (net.Conn, error) {
conn, err := net.Dial("tcp", c.dataPort.toAddress())
if err != nil {
return nil, err
}
return conn, nil
}
dataConn, err := c.dataConnect()
if err != nil {
log.Print(err)
c.respond(status425)
return
}
defer dataConn.Close()
for _, file := range files {
_, err := fmt.Fprint(dataConn, file.Name(), c.EOL())
if err != nil {
log.Print(err)
c.respond(status426)
}
}
_, err = fmt.Fprintf(dataConn, c.EOL())
if err != nil {
log.Print(err)
c.respond(status426)
}
c.respond(status226)
func (c *Conn) retr(args []string) {
if len(args) != 1 {
c.respond(status501)
return
}
path := filepath.Join(c.rootDir, c.workDir, args[0])
file, err := os.Open(path)
if err != nil {
log.Print(err)
c.respond(status550)
}
c.respond(status150)
dataConn, err := c.dataConnect()
if err != nil {
log.Print(err)
c.respond(status425)
}
defer dataConn.Close()
_, err = io.Copy(dataConn, file)
if err != nil {
log.Print(err)
c.respond(status426)
return
}
io.WriteString(dataConn, c.EOL())
c.respond(status226)
}

View File

@ -0,0 +1,25 @@
package ftp
type dataType int
const (
ascii dataType = iota
binary
)
func (c *Conn) setDataType(args []string) {
if len(args) == 0 {
c.respond(status501)
}
switch args[0] {
case "A":
c.dataType = ascii
case "I": // image/binary
c.dataType = binary
default:
c.respond(status504)
return
}
c.respond(status200)
}

View File

@ -0,0 +1,47 @@
package ftp
import (
"fmt"
"io/ioutil"
"path/filepath"
)
func (c *Conn) list(args []string) {
var target string
if len(args) > 0 {
target = filepath.Join(c.rootDir, c.workDir, args[0])
} else {
target = filepath.Join(c.rootDir, c.workDir)
}
files, err := ioutil.ReadDir(target)
if err != nil {
fmt.Print(err)
c.respond(status550)
return
}
c.respond(status150)
dataConn, err := c.dataConnect()
if err != nil {
fmt.Print(err)
c.respond(status425)
return
}
defer dataConn.Close()
for _, file := range files {
_, err := fmt.Fprint(dataConn, file.Name(), c.EOL())
if err != nil {
fmt.Print(err)
c.respond(status426)
}
}
_, err = fmt.Fprintf(dataConn, c.EOL())
if err != nil {
fmt.Print(err)
c.respond(status426)
}
c.respond(status226)
}

View File

@ -0,0 +1,42 @@
package ftp
import "fmt"
func (c *Conn) port(args []string) {
if len(args) != 1 {
c.respond(status501)
return
}
dataPort, err := dataPortFromHostPort(args[0])
if err != nil {
fmt.Print(err)
c.respond(status501)
return
}
c.dataPort = dataPort
c.respond(status200)
}
type dataPort struct {
h1, h2, h3, h4 int // host
p1, p2 int // port
}
func dataPortFromHostPort(hostPort string) (*dataPort, error) {
var dp dataPort
_, err := fmt.Sscanf(hostPort, "%d,%d,%d,%d,%d,%d",
&dp.h1, &dp.h2, &dp.h3, &dp.h4, &dp.p1, &dp.p2)
if err != nil {
return nil, err
}
return &dp, nil
}
func (d *dataPort) toAddress() string {
if d == nil {
return ""
}
// convert hex port bytes to decimal port
port := d.p1<<8 + d.p2
return fmt.Sprintf("%d.%d.%d.%d:%d", d.h1, d.h2, d.h3, d.h4, port)
}

View File

@ -0,0 +1,40 @@
package ftp
import "fmt"
const (
status150 = "150 File status okay; about to open data connection."
status200 = "200 Command okay."
status220 = "220 Service ready for new user."
status221 = "221 Service closing control connection."
status226 = "226 Closing data connection. Requested file action successful."
status230 = "230 User %s logged in, proceed."
status425 = "425 Can't open data connection."
status426 = "426 Connection closed; transfer aborted."
status501 = "501 Syntax error in parameters or arguments."
status502 = "502 Command not implemented."
status504 = "504 Cammand not implemented for that parameter."
status550 = "550 Requested action not taken. File unavailable."
)
// respond copies a string to the client and terminates it with the appropriate FTP line terminator
// for the datatype.
func (c *Conn) respond(s string) {
fmt.Print(">> ", s)
_, err := fmt.Fprint(c.conn, s, c.EOL())
if err != nil {
fmt.Print(err)
}
}
// EOL returns the line terminator matching the FTP standard for the datatype.
func (c *Conn) EOL() string {
switch c.dataType {
case ascii:
return "\r\n"
case binary:
return "\n"
default:
return "\n"
}
}

View File

@ -0,0 +1,10 @@
package ftp
import (
"fmt"
"strings"
)
func (c *Conn) user(args []string) {
c.respond(fmt.Sprintf(status230, strings.Join(args, " ")))
}

View File

@ -0,0 +1,3 @@
module main
go 1.24.5

View File

@ -0,0 +1,45 @@
package main
import (
"flag"
"fmt"
"log"
"net"
"path/filepath"
"main/ftp"
)
var port int
var rootDir string
func init() {
flag.IntVar(&port,"port",9090,"port to listet")
flag.StringVar(&rootDir,"rootDir","public","root Directory")
flag.Parse()
}
func handleConn(conn net.Conn) {
defer conn.Close()
absPath, err := filepath.Abs(rootDir)
if err != nil {
fmt.Print(err)
}
ftp.Serve(ftp.NewConn(conn,absPath))
}
func main() {
server := fmt.Sprintf(":%d",port)
listener,err := net.Listen("tcp",server)
if err != nil {
log.Fatal(err)
}
for {
conn, err := listener.Accept()
if err != nil {
fmt.Print(err)
continue
}
handleConn(conn)
}
}