From a1fdeb62fcf514ac81d174ebf25cc322e186b026 Mon Sep 17 00:00:00 2001 From: Starainrt Date: Wed, 10 Apr 2024 15:19:25 +0800 Subject: [PATCH 1/2] update host file --- hosts/hosts.go | 692 ++++++++++++++++++++++++++++++++++++---- hosts/hosts_test.go | 128 +++++++- sysconf/sysconf_test.go | 13 +- 3 files changed, 745 insertions(+), 88 deletions(-) diff --git a/hosts/hosts.go b/hosts/hosts.go index b056de2..0eaf37e 100644 --- a/hosts/hosts.go +++ b/hosts/hosts.go @@ -28,21 +28,151 @@ func SystemHostpath() string { return `/etc/hosts` } +var defaultParser = NewHosts() + +func ParseHosts(hostPath string) error { + return defaultParser.Parse(hostPath) +} + +func Parse() error { + return defaultParser.Parse(SystemHostpath()) +} + +func List() []*HostNode { + return defaultParser.List() +} + +func ListHosts() map[string][]string { + return defaultParser.ListHosts() +} + +func ListIPs() map[string][]string { + return defaultParser.ListIPs() +} + +func ListByHost(host string) []*HostNode { + return defaultParser.ListByHost(host) +} + +func ListIPsByHost(host string) []string { + return defaultParser.ListIPsByHost(host) +} + +func ListFirstIPByHost(host string) string { + return defaultParser.ListFirstIPByHost(host) +} + +func ListByIP(ip string) []*HostNode { + return defaultParser.ListByIP(ip) +} + +func ListHostsByIP(ip string) []string { + return defaultParser.ListHostsByIP(ip) +} + +func ListFirstHostByIP(ip string) string { + return defaultParser.ListFirstHostByIP(ip) +} + +func AddHosts(ip string, hosts ...string) error { + return defaultParser.AddHosts(ip, hosts...) +} + +func AddHostsComment(comment string, ip string, hosts ...string) error { + return defaultParser.AddHostsComment(comment, ip, hosts...) +} + +func RemoveIPHosts(ip string, hosts ...string) error { + return defaultParser.RemoveIPHosts(ip, hosts...) +} + +func RemoveIPs(ips ...string) error { + return defaultParser.RemoveIPs(ips...) +} + +func RemoveHosts(hosts ...string) error { + return defaultParser.RemoveHosts(hosts...) +} + +func SetIPHosts(ip string, hosts ...string) error { + return defaultParser.SetIPHosts(ip, hosts...) +} + +func SetHostIPs(host string, ips ...string) error { + return defaultParser.SetHostIPs(host, ips...) +} + +func InsertNodes(node *HostNode, before bool, comment string, ip string, hosts ...string) error { + return defaultParser.InsertNodeByData(node, before, comment, ip, hosts...) +} + +func SaveAs(path string) error { + return defaultParser.SaveAs(path) +} + +func Save() error { + return defaultParser.Save() +} + +func Build() ([]byte, error) { + return defaultParser.Build() +} + +func GetFirstNode() (*HostNode, error) { + return defaultParser.GetFirstNode() +} + +func GetNode(nodeID uint64) (*HostNode, error) { + return defaultParser.GetNode(nodeID) +} + +func GetNextNode(nodeID uint64) (*HostNode, error) { + return defaultParser.GetNextNode(nodeID) +} + +func GetLastNode(nodeID uint64) (*HostNode, error) { + return defaultParser.GetLastNode(nodeID) +} + +func GetLatestNode() (*HostNode, error) { + return defaultParser.GetLatestNode() +} + +func DeleteNode(node *HostNode) error { + return defaultParser.DeleteNode(node) +} + +func DeleteNodeByUID(uid uint64) error { + return defaultParser.DeleteNodeByUID(uid) +} + +func AddNode(node *HostNode) error { + return defaultParser.AddNode(node) +} + +func InsertNode(node *HostNode) error { + return defaultParser.InsertNode(node) +} + +func UpdateNode(node *HostNode) error { + return defaultParser.UpdateNode(node) +} + type HostNode struct { uid uint64 nextuid uint64 lastuid uint64 - IP string - Host []string - Comment string - Original string - OnlyComment bool - Valid bool + ip string + host []string + comment string + original string + onlyComment bool + valid bool } type Host struct { idx uint64 hostPath string - nextUid uint64 + firstUid uint64 lastUid uint64 fulldata map[uint64]*HostNode hostData map[string][]*HostNode @@ -61,6 +191,9 @@ func NewHosts() *Host { func (h *Host) Parse(hostPath string) error { h.Lock() defer h.Unlock() + h.idx = 0 + h.firstUid = 0 + h.lastUid = 0 h.hostPath = hostPath h.fulldata = make(map[uint64]*HostNode) h.hostData = make(map[string][]*HostNode) @@ -94,14 +227,14 @@ func (h *Host) parse() error { data.lastuid = h.idx - 1 data.nextuid = h.idx + 1 h.fulldata[data.uid] = &data - if h.nextUid == 0 { - h.nextUid = h.idx + if h.firstUid == 0 { + h.firstUid = h.idx } - if data.Valid { - for _, v := range data.Host { + if data.valid { + for _, v := range data.host { h.hostData[v] = append(h.hostData[v], &data) } - h.ipData[data.IP] = append(h.ipData[data.IP], &data) + h.ipData[data.ip] = append(h.ipData[data.ip], &data) } } @@ -110,14 +243,15 @@ func (h *Host) parse() error { func (h *Host) parseLine(data string) (HostNode, error) { var res = HostNode{ - Original: data, + original: data, } if len(data) == 0 { return res, fmt.Errorf("empty line") } if data[0] == '#' { - res.Comment = data - res.OnlyComment = true + res.comment = data + res.onlyComment = true + res.valid = true return res, nil } var dataArr []string @@ -155,16 +289,16 @@ func (h *Host) parseLine(data string) (HostNode, error) { for k, v := range dataArr { switch k { case 0: - res.IP = v + res.ip = v default: if strings.HasPrefix(v, "#") { - res.Comment = v + res.comment = v } else { - res.Host = append(res.Host, v) + res.host = append(res.host, v) } } } - res.Valid = true + res.valid = true return res, nil } @@ -172,7 +306,7 @@ func (h *Host) List() []*HostNode { h.RLock() defer h.RUnlock() var res []*HostNode - nextUid := h.nextUid + nextUid := h.firstUid for { if nextUid == 0 { break @@ -183,6 +317,36 @@ func (h *Host) List() []*HostNode { return res } +func (h *Host) ListHosts() map[string][]string { + h.RLock() + defer h.RUnlock() + if h.hostData == nil { + return nil + } + var res = make(map[string][]string) + for k, v := range h.hostData { + for _, vv := range v { + res[k] = append(res[k], vv.ip) + } + } + return res +} + +func (h *Host) ListIPs() map[string][]string { + h.RLock() + defer h.RUnlock() + if h.ipData == nil { + return nil + } + var res = make(map[string][]string) + for k, v := range h.ipData { + for _, vv := range v { + res[k] = append(res[k], vv.host...) + } + } + return res +} + func (h *Host) ListByHost(host string) []*HostNode { h.RLock() defer h.RUnlock() @@ -200,7 +364,7 @@ func (h *Host) ListIPsByHost(host string) []string { } var res []string for _, v := range h.hostData[host] { - res = append(res, v.IP) + res = append(res, v.ip) } return res } @@ -212,7 +376,7 @@ func (h *Host) ListFirstIPByHost(host string) string { return "" } for _, v := range h.hostData[host] { - return v.IP + return v.ip } return "" } @@ -228,6 +392,7 @@ func (h *Host) ListByIP(ip string) []*HostNode { func (h *Host) ListHostsByIP(ip string) []string { h.RLock() + defer h.RUnlock() return h.listHostsByIP(ip) } @@ -237,7 +402,7 @@ func (h *Host) listHostsByIP(ip string) []string { } var res []string for _, v := range h.ipData[ip] { - res = append(res, v.Host...) + res = append(res, v.host...) } return res } @@ -249,8 +414,8 @@ func (h *Host) ListFirstHostByIP(ip string) string { return "" } for _, v := range h.ipData[ip] { - if len(v.Host) > 0 { - return v.Host[0] + if len(v.host) > 0 { + return v.host[0] } } return "" @@ -277,12 +442,12 @@ func (h *Host) RemoveIPHosts(ip string, hosts ...string) error { cntfor: for _, v := range ipInfo { for _, host := range hosts { - if len(v.Host) == 1 && v.Host[0] == host { + if len(v.host) == 1 && v.host[0] == host { delete(h.ipData, ip) if v.lastuid != 0 { h.fulldata[v.lastuid].nextuid = v.nextuid } else { - h.nextUid = v.nextuid + h.firstUid = v.nextuid } if v.nextuid != 0 { h.fulldata[v.nextuid].lastuid = v.lastuid @@ -290,7 +455,7 @@ cntfor: h.lastUid = v.lastuid } var newHostData []*HostNode - for _, vv := range h.hostData[v.Host[0]] { + for _, vv := range h.hostData[v.host[0]] { if vv.uid != v.uid { newHostData = append(newHostData, vv) } @@ -300,14 +465,14 @@ cntfor: v = nil continue cntfor } - if len(v.Host) > 1 { + if len(v.host) > 1 { var newHosts []string - for _, vv := range v.Host { + for _, vv := range v.host { if vv != host { newHosts = append(newHosts, vv) } } - v.Host = newHosts + v.host = newHosts var newHostData []*HostNode for _, vv := range h.hostData[host] { if vv.uid != v.uid { @@ -338,14 +503,14 @@ func (h *Host) RemoveIPs(ips ...string) error { if v.lastuid != 0 { h.fulldata[v.lastuid].nextuid = v.nextuid } else { - h.nextUid = v.nextuid + h.firstUid = v.nextuid } if v.nextuid != 0 { h.fulldata[v.nextuid].lastuid = v.lastuid } else { h.lastUid = v.lastuid } - for _, host := range v.Host { + for _, host := range v.host { var newHostData []*HostNode for _, vv := range h.hostData[host] { if vv.uid != v.uid { @@ -373,18 +538,18 @@ func (h *Host) RemoveHosts(hosts ...string) error { delete(h.hostData, host) for _, v := range hostInfo { var newHosts []string - for _, vv := range v.Host { + for _, vv := range v.host { if vv != host { newHosts = append(newHosts, vv) } } - v.Host = newHosts - if len(v.Host) == 0 { - delete(h.ipData, v.IP) + v.host = newHosts + if len(v.host) == 0 { + delete(h.ipData, v.ip) if v.lastuid != 0 { h.fulldata[v.lastuid].nextuid = v.nextuid } else { - h.nextUid = v.nextuid + h.firstUid = v.nextuid } if v.nextuid != 0 { h.fulldata[v.nextuid].lastuid = v.lastuid @@ -399,6 +564,14 @@ func (h *Host) RemoveHosts(hosts ...string) error { } func (h *Host) SetIPHosts(ip string, hosts ...string) error { + info := h.ListByIP(ip) + if len(info) == 0 { + return h.AddHosts(ip, hosts...) + } else if len(info) == 1 { + info[0].host = hosts + info[0].comment = "" + return nil + } err := h.RemoveIPs(ip) if err != nil { return err @@ -406,6 +579,22 @@ func (h *Host) SetIPHosts(ip string, hosts ...string) error { return h.AddHosts(ip, hosts...) } +func (h *Host) SetHostIPs(host string, ips ...string) error { + info := h.ListByHost(host) + if len(info) == 0 { + return h.AddHosts(host, ips...) + } else if len(info) == 1 { + info[0].ip = ips[0] + info[0].comment = "" + return nil + } + err := h.RemoveHosts(host) + if err != nil { + return err + } + return h.AddHosts(ips[0], host) +} + func (h *Host) addHosts(comment string, ip string, hosts ...string) error { h.Lock() defer h.Unlock() @@ -422,14 +611,17 @@ func (h *Host) addHosts(comment string, ip string, hosts ...string) error { if len(needAddHosts) == 0 { return nil } + if comment != "" && !strings.HasPrefix(strings.TrimSpace(comment), "#") { + comment = "#" + comment + } hostNode := HostNode{ uid: h.idx + 1, nextuid: 0, lastuid: h.lastUid, - IP: ip, - Host: needAddHosts, - Valid: true, - Comment: comment, + ip: ip, + host: needAddHosts, + valid: true, + comment: comment, } h.idx++ h.fulldata[h.lastUid].nextuid = h.idx @@ -442,7 +634,7 @@ func (h *Host) addHosts(comment string, ip string, hosts ...string) error { return nil } -func (h *Host) InsertNodes(node *HostNode, before bool, comment string, ip string, hosts ...string) error { +func (h *Host) InsertNodeByData(node *HostNode, before bool, comment string, ip string, hosts ...string) error { h.Lock() defer h.Unlock() if h.hostData == nil { @@ -451,15 +643,18 @@ func (h *Host) InsertNodes(node *HostNode, before bool, comment string, ip strin if _, ok := h.fulldata[node.uid]; !ok { return fmt.Errorf("node not exists") } + if comment != "" && !strings.HasPrefix(strings.TrimSpace(comment), "#") { + comment = "#" + comment + } hostNode := HostNode{ uid: h.idx + 1, - IP: ip, - Host: hosts, - Valid: true, - Comment: comment, + ip: ip, + host: hosts, + valid: true, + comment: comment, } if ip == "" && len(hosts) == 0 && comment != "" { - hostNode.OnlyComment = true + hostNode.onlyComment = true } if before { hostNode.nextuid = node.uid @@ -467,7 +662,7 @@ func (h *Host) InsertNodes(node *HostNode, before bool, comment string, ip strin if node.lastuid != 0 { h.fulldata[node.lastuid].nextuid = h.idx } else { - h.nextUid = h.idx + h.firstUid = h.idx } node.lastuid = h.idx } else { @@ -483,6 +678,119 @@ func (h *Host) InsertNodes(node *HostNode, before bool, comment string, ip strin return nil } +func (h *Host) DeleteNode(node *HostNode) error { + h.Lock() + defer h.Unlock() + if h.hostData == nil { + return fmt.Errorf("hosts data not initialized") + } + if _, ok := h.fulldata[node.uid]; !ok { + return fmt.Errorf("node not exists") + } + if node.lastuid != 0 { + h.fulldata[node.lastuid].nextuid = node.nextuid + } else { + h.firstUid = node.nextuid + } + if node.nextuid != 0 { + h.fulldata[node.nextuid].lastuid = node.lastuid + } else { + h.lastUid = node.lastuid + } + for _, v := range node.host { + var newHostData []*HostNode + for _, vv := range h.hostData[v] { + if vv.uid != node.uid { + newHostData = append(newHostData, vv) + } + } + h.hostData[v] = newHostData + } + ipInfo := h.ipData[node.ip] + var newIPData []*HostNode + for _, v := range ipInfo { + if v.uid != node.uid { + newIPData = append(newIPData, v) + } + } + h.ipData[node.ip] = newIPData + delete(h.fulldata, node.uid) + return nil +} + +func (h *Host) DeleteNodeByUID(uid uint64) error { + h.RLock() + node, ok := h.fulldata[uid] + if !ok { + h.RUnlock() + return fmt.Errorf("node not exists") + } + h.RUnlock() + return h.DeleteNode(node) +} + +func (h *Host) AddNode(node *HostNode) error { + h.Lock() + defer h.Unlock() + if h.hostData == nil { + return fmt.Errorf("hosts data not initialized") + } + if node.comment != "" && !strings.HasPrefix(strings.TrimSpace(node.comment), "#") { + node.comment = "#" + node.comment + } + if node.ip == "" && len(node.host) == 0 && node.comment != "" { + node.onlyComment = true + } + h.idx++ + node.uid = h.idx + node.lastuid = h.lastUid + node.nextuid = 0 + h.fulldata[h.lastUid].nextuid = node.uid + h.lastUid = node.uid + h.fulldata[node.uid] = node + node.valid = node.CheckValid() + if node.valid { + h.ipData[node.ip] = append(h.ipData[node.ip], node) + for _, v := range node.host { + h.hostData[v] = append(h.hostData[v], node) + } + } + return nil +} + +func (h *Host) InsertNode(node *HostNode) error { + if node.lastuid == 0 && node.nextuid == 0 { + return h.AddNode(node) + } + h.Lock() + defer h.Unlock() + if h.hostData == nil { + return fmt.Errorf("hosts data not initialized") + } + if node.comment != "" && !strings.HasPrefix(strings.TrimSpace(node.comment), "#") { + node.comment = "#" + node.comment + } + if node.ip == "" && len(node.host) == 0 && node.comment != "" { + node.onlyComment = true + } + node.uid = h.idx + 1 + if h.fulldata[node.lastuid].nextuid != node.nextuid { + return fmt.Errorf("node lastuid nextuid not match") + } + h.idx++ + h.fulldata[node.lastuid].nextuid = node.uid + h.fulldata[node.nextuid].lastuid = node.uid + h.fulldata[node.uid] = node + node.valid = node.CheckValid() + if node.valid { + h.ipData[node.ip] = append(h.ipData[node.ip], node) + for _, v := range node.host { + h.hostData[v] = append(h.hostData[v], node) + } + } + return nil +} + func inArray(arr []string, v string) bool { for _, vv := range arr { if v == vv { @@ -493,75 +801,325 @@ func inArray(arr []string, v string) bool { } func (h *Host) SaveAs(path string) error { - h.Lock() - defer h.Unlock() return h.save(path) } func (h *Host) Save() error { - h.Lock() - defer h.Unlock() return h.save(h.hostPath) } func (h *Host) save(path string) error { h.Lock() defer h.Unlock() + if h.firstUid == 0 || h.fulldata == nil { + return fmt.Errorf("no data") + } f, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666) if err != nil { return fmt.Errorf("open hosts file %s error: %s", h.hostPath, err) } defer f.Close() - for _, v := range h.fulldata { - if v.OnlyComment { - if _, err := f.WriteString(v.Comment + "\n"); err != nil { + node := h.fulldata[h.firstUid] + if node == nil { + return fmt.Errorf("no data") + } + for { + if node.onlyComment { + if _, err := f.WriteString(node.comment + "\n"); err != nil { return fmt.Errorf("write hosts file error: %s", err) } + if node.nextuid == 0 { + break + } + node = h.fulldata[node.nextuid] continue } - if _, err := f.WriteString(v.IP + " "); err != nil { + if _, err := f.WriteString(node.ip + " "); err != nil { return fmt.Errorf("write hosts file error: %s", err) } - if _, err := f.WriteString(strings.Join(v.Host, " ")); err != nil { + if _, err := f.WriteString(strings.Join(node.host, " ")); err != nil { return fmt.Errorf("write hosts file error: %s", err) } - if len(v.Comment) > 0 { - if _, err := f.WriteString(" " + v.Comment); err != nil { + if len(node.comment) > 0 { + if _, err := f.WriteString(" " + node.comment); err != nil { return fmt.Errorf("write hosts file error: %s", err) } } if _, err := f.WriteString(lineBreaker); err != nil { return fmt.Errorf("write hosts file error: %s", err) } + if node.nextuid == 0 { + break + } + node = h.fulldata[node.nextuid] } return nil } func (h *Host) Build() ([]byte, error) { + if h.firstUid == 0 || h.fulldata == nil { + return nil, fmt.Errorf("no data") + } h.Lock() defer h.Unlock() var f bytes.Buffer - for _, v := range h.fulldata { - if v.OnlyComment { - if _, err := f.WriteString(v.Comment + "\n"); err != nil { + node := h.fulldata[h.firstUid] + if node == nil { + return nil, fmt.Errorf("no data") + } + for { + if node.onlyComment { + if _, err := f.WriteString(node.comment + "\n"); err != nil { return nil, fmt.Errorf("write hosts file error: %s", err) } + if node.nextuid == 0 { + break + } + node = h.fulldata[node.nextuid] continue } - if _, err := f.WriteString(v.IP + " "); err != nil { + if _, err := f.WriteString(node.ip + " "); err != nil { return nil, fmt.Errorf("write hosts file error: %s", err) } - if _, err := f.WriteString(strings.Join(v.Host, " ")); err != nil { + if _, err := f.WriteString(strings.Join(node.host, " ")); err != nil { return nil, fmt.Errorf("write hosts file error: %s", err) } - if len(v.Comment) > 0 { - if _, err := f.WriteString(" " + v.Comment); err != nil { + if len(node.comment) > 0 { + if _, err := f.WriteString(" " + node.comment); err != nil { return nil, fmt.Errorf("write hosts file error: %s", err) } } if _, err := f.WriteString(lineBreaker); err != nil { return nil, fmt.Errorf("write hosts file error: %s", err) } + if node.nextuid == 0 { + break + } + node = h.fulldata[node.nextuid] } return f.Bytes(), nil } + +func (h *Host) GetFirstNode() (*HostNode, error) { + h.RLock() + defer h.RUnlock() + if h.firstUid == 0 { + return nil, fmt.Errorf("no data") + } + if h.fulldata == nil { + return nil, fmt.Errorf("no data") + } + return h.fulldata[h.firstUid], nil +} + +func (h *Host) GetNode(nodeID uint64) (*HostNode, error) { + h.RLock() + defer h.RUnlock() + if h.fulldata == nil { + return nil, fmt.Errorf("no data") + } + if node, ok := h.fulldata[nodeID]; ok { + return node, nil + } + return nil, fmt.Errorf("node not exists") +} + +func (h *Host) GetNextNode(nodeID uint64) (*HostNode, error) { + h.RLock() + defer h.RUnlock() + if h.fulldata == nil { + return nil, fmt.Errorf("no data") + } + if node, ok := h.fulldata[nodeID]; ok { + if node.nextuid == 0 { + return nil, fmt.Errorf("no next node") + } + return h.fulldata[node.nextuid], nil + } + return nil, fmt.Errorf("node not exists") +} + +func (h *Host) GetLastNode(nodeID uint64) (*HostNode, error) { + h.RLock() + defer h.RUnlock() + if h.fulldata == nil { + return nil, fmt.Errorf("no data") + } + if node, ok := h.fulldata[nodeID]; ok { + if node.lastuid == 0 { + return nil, fmt.Errorf("no last node") + } + return h.fulldata[node.lastuid], nil + } + return nil, fmt.Errorf("node not exists") +} + +func (h *Host) GetLatestNode() (*HostNode, error) { + h.RLock() + defer h.RUnlock() + if h.lastUid == 0 { + return nil, fmt.Errorf("no data") + } + if h.fulldata == nil { + return nil, fmt.Errorf("no data") + } + return h.fulldata[h.lastUid], nil +} + +func (h *Host) UpdateNode(node *HostNode) error { + h.Lock() + defer h.Unlock() + if h.fulldata == nil { + return fmt.Errorf("no data") + } + if _, ok := h.fulldata[node.uid]; !ok { + return fmt.Errorf("node not exists") + } + if node.comment != "" && !strings.HasPrefix(strings.TrimSpace(node.comment), "#") { + node.comment = "#" + node.comment + } + if node.ip == "" && len(node.host) == 0 && node.comment != "" { + node.onlyComment = true + } + h.fulldata[node.uid] = node + node.valid = node.CheckValid() + for k, v := range h.ipData { + var newIPData []*HostNode + for _, vv := range v { + if vv.uid != node.uid { + newIPData = append(newIPData, vv) + } + } + h.ipData[k] = newIPData + } + for k, v := range h.hostData { + var newHostData []*HostNode + for _, vv := range v { + if vv.uid != node.uid { + newHostData = append(newHostData, vv) + } + } + h.hostData[k] = newHostData + } + if node.valid { + h.ipData[node.ip] = append(h.ipData[node.ip], node) + for _, v := range node.host { + h.hostData[v] = append(h.hostData[v], node) + } + } + return nil +} + +func (n *HostNode) String() string { + if n.onlyComment { + return n.comment + } + return fmt.Sprintf("%s %s %s", n.ip, strings.Join(n.host, " "), n.comment) +} + +func (n *HostNode) Bytes() []byte { + return []byte(n.String()) +} + +func (n *HostNode) Hosts() []string { + return n.host +} + +func (n *HostNode) IP() string { + return n.ip +} + +func (n *HostNode) Comment() string { + return n.comment +} + +func (n *HostNode) UID() uint64 { + return n.uid +} + +func (n *HostNode) NextUID() uint64 { + return n.nextuid +} + +func (n *HostNode) LastUID() uint64 { + return n.lastuid +} + +func (n *HostNode) Valid() bool { + return n.valid +} + +func (n *HostNode) OnlyComment() bool { + return n.onlyComment +} + +func (n *HostNode) Original() string { + return n.original +} + +func (n *HostNode) SetHosts(hosts ...string) { + n.host = hosts +} + +func (n *HostNode) SetIP(ip string) { + n.ip = ip +} + +func (n *HostNode) SetComment(comment string) { + if comment == "" { + return + } + if !strings.HasPrefix(strings.TrimSpace(comment), "#") { + n.comment = "#" + comment + return + } + n.comment = comment +} + +func (n *HostNode) SetValid(valid bool) { + n.valid = valid +} + +func (n *HostNode) SetOnlyComment(onlyComment bool) { + n.onlyComment = onlyComment +} + +func (n *HostNode) SetOriginal(original string) { + n.original = original +} + +func (n *HostNode) AddHosts(hosts ...string) { + n.host = append(n.host, hosts...) +} + +func (n *HostNode) SetLastUID(uid uint64) error { + if n.uid != 0 { + return fmt.Errorf("uid already set,you cannot change the existing node") + } + n.lastuid = uid + return nil +} + +func (n *HostNode) SetNextUID(uid uint64) error { + if n.uid != 0 { + return fmt.Errorf("uid already set,you cannot change the existing node") + } + n.nextuid = uid + return nil +} + +func (n *HostNode) CheckValid() bool { + if n.ip == "" && len(n.host) == 0 && n.comment == "" { + return true + } + if n.ip == "" && len(n.host) == 0 && n.comment != "" { + return true + } + if n.ip == "" && len(n.host) > 0 { + return false + } + if net.ParseIP(n.ip) == nil { + return false + } + return true +} diff --git a/hosts/hosts_test.go b/hosts/hosts_test.go index 80f1e2b..8ae2394 100644 --- a/hosts/hosts_test.go +++ b/hosts/hosts_test.go @@ -11,27 +11,127 @@ func Test_Hosts(t *testing.T) { if err != nil { t.Error(err) } - for _, v := range h.List() { - fmt.Printf("%+v\n", v) + next := h.firstUid + for next != 0 { + node, _ := h.GetNode(next) + fmt.Printf("Last %d, Next: %d, IP: %s, Hosts: %s, Comment: %s\n", node.LastUID(), node.NextUID(), node.IP(), node.Hosts(), node.Comment()) + next = node.NextUID() } - fmt.Println(h.nextUid, h.lastUid) - fmt.Println("") - err = h.AddHosts("122.23.12.123", "b612.me", "ok.b612.me") + data := h.ListHostsByIP("11.22.33.44") + if len(data) != 2 { + t.Error("Expected 2, got ", len(data)) + } else { + t.Log(data) + } + + data = h.ListIPsByHost("dns.b612.me") + if len(data) < 1 || data[0] != "4.5.6.7" { + t.Error("Expected 4.5.6.7, got ", data) + } else { + t.Log(data) + } + + err = h.RemoveHosts("dns.b612.me") + if err != nil { + t.Error(err) + } + data = h.ListIPsByHost("dns.b612.me") + if len(data) > 0 { + t.Error("Expected 0, got ", len(data)) + } else { + t.Log(data) + } + + err = h.RemoveHosts("test.dns.set.b612.me") + if err != nil { + t.Error(err) + } + + data = h.ListIPsByHost("remove.b612.me") + if len(data) < 1 || data[0] != "11.22.33.44" { + t.Error("Expected 11.22.33.44, got ", data) + } else { + t.Log(data) + } + + nodes := h.ListByIP("11.22.33.44") + if nodes == nil { + t.Error("Expected not nil, got ", nodes) + } else { + t.Log(nodes) + } + + nodes[0].AddHosts("hello.b612.me") + err = h.UpdateNode(nodes[0]) if err != nil { t.Error(err) } - for _, v := range h.List() { - fmt.Printf("%+v\n", v) + data = h.ListIPsByHost("hello.b612.me") + if len(data) < 1 || data[0] != "11.22.33.44" { + t.Error("Not Expected Data", data) + } else { + t.Log(data) } - fmt.Println(h.nextUid, h.lastUid) - fmt.Println("") - err = h.RemoveIPHosts("11.22.33.44", "remove.b612.me", "test.dns.set.b612.me") + insertNode := new(HostNode) + insertNode.SetIP("11.11.11.11") + insertNode.SetHosts("insert.b612.me") + insertNode.SetComment("Insert Node") + insertNode.SetNextUID(nodes[0].UID()) + insertNode.SetLastUID(nodes[0].LastUID()) + err = h.InsertNode(insertNode) if err != nil { t.Error(err) } - for _, v := range h.List() { - fmt.Printf("%+v\n", v) + data = h.ListIPsByHost("insert.b612.me") + if len(data) < 1 || data[0] != "11.11.11.11" { + t.Error("Expected 11.11.11.11 got ", data) + } else { + t.Log(data) + } + + err = h.SaveAs("./test_hosts_01.txt") + if err != nil { + t.Error(err) + } + + err = h.DeleteNode(insertNode) + if err != nil { + t.Error(err) + } + data = h.ListIPsByHost("insert.b612.me") + if len(data) > 0 { + t.Error("Expected 0 got ", data) + } else { + t.Log(data) + } + + for i := 0; i < 100; i++ { + err = h.RemoveHosts("release-ftpd") + if err != nil { + t.Error(err) + } + err = h.AddHosts("2.3.4.9", "release-ftpd") + if err != nil { + t.Error(err) + } + } + + err = h.SaveAs("./test_hosts_02.txt") + if err != nil { + t.Error(err) + } +} + +func BenchmarkAddHosts(b *testing.B) { + var h = NewHosts() + err := h.Parse("./test_hosts.txt") + if err != nil { + b.Error(err) + } + for i := 0; i < b.N; i++ { + err = h.AddHosts("1.3.4.5", "test.b612.me") + if err != nil { + b.Error(err) + } } - fmt.Println(h.nextUid, h.lastUid) - fmt.Println("") } diff --git a/sysconf/sysconf_test.go b/sysconf/sysconf_test.go index aa0e48c..76b589a 100644 --- a/sysconf/sysconf_test.go +++ b/sysconf/sysconf_test.go @@ -33,11 +33,10 @@ func Test_Parse(t *testing.T) { fmt.Println(cfg.Parse([]byte(data))) cfg.Reverse() cfg.Data[0].Delete(`pp.com`) - //fmt.Println(cfg.Data[0].Comment) + //fmt.Println(cfg.Data[0].comment) fmt.Println(string(cfg.Build())) } - type slicetest struct { A string `seg:"s" key:"a"` B string `seg:"a" key:"b"` @@ -50,7 +49,7 @@ type testme struct { func Test_Marshal(t *testing.T) { - var info string =` + var info string = ` [love] a=abc b=123 @@ -59,10 +58,10 @@ a=456 b=789 ` var tmp testme - ini:=NewIni() + ini := NewIni() ini.Parse([]byte(info)) ini.Unmarshal(&tmp) - fmt.Printf("%+v\n",tmp) - b,_:=ini.Marshal(tmp) + fmt.Printf("%+v\n", tmp) + b, _ := ini.Marshal(tmp) fmt.Println(string(b)) -} \ No newline at end of file +} From c1b5b0c2c53dd6f26859087ff88c51a7394fabdd Mon Sep 17 00:00:00 2001 From: Starainrt Date: Wed, 10 Apr 2024 15:52:57 +0800 Subject: [PATCH 2/2] update host file --- hosts/hosts.go | 17 +++++++++-------- hosts/hosts_test.go | 17 +++++++++++++++++ hosts/test_hosts.txt | 1 + 3 files changed, 27 insertions(+), 8 deletions(-) diff --git a/hosts/hosts.go b/hosts/hosts.go index 0eaf37e..411d56e 100644 --- a/hosts/hosts.go +++ b/hosts/hosts.go @@ -580,19 +580,20 @@ func (h *Host) SetIPHosts(ip string, hosts ...string) error { } func (h *Host) SetHostIPs(host string, ips ...string) error { - info := h.ListByHost(host) - if len(info) == 0 { - return h.AddHosts(host, ips...) - } else if len(info) == 1 { - info[0].ip = ips[0] - info[0].comment = "" - return nil + if len(ips) == 0 { + return fmt.Errorf("no ip address") } err := h.RemoveHosts(host) if err != nil { return err } - return h.AddHosts(ips[0], host) + for _, ip := range ips { + err := h.AddHosts(ip, host) + if err != nil { + return err + } + } + return nil } func (h *Host) addHosts(comment string, ip string, hosts ...string) error { diff --git a/hosts/hosts_test.go b/hosts/hosts_test.go index 8ae2394..d356886 100644 --- a/hosts/hosts_test.go +++ b/hosts/hosts_test.go @@ -116,6 +116,23 @@ func Test_Hosts(t *testing.T) { } } + err = h.SetHostIPs("ssh.b612.me", "9.9.9.9") + if err != nil { + t.Error(err) + } + + data = h.ListIPsByHost("ssh.b612.me") + if len(data) == 0 { + t.Error("Expected 1 got ", data) + } else { + t.Log(data) + } + + err = h.SetIPHosts("10.10.10.10", "ssh.b612.me", "ssr.b612.me") + if len(data) == 0 { + t.Error("Expected 1 got ", data) + } + err = h.SaveAs("./test_hosts_02.txt") if err != nil { t.Error(err) diff --git a/hosts/test_hosts.txt b/hosts/test_hosts.txt index 718a539..0d22a47 100644 --- a/hosts/test_hosts.txt +++ b/hosts/test_hosts.txt @@ -8,6 +8,7 @@ #special IPv6 addre 127.0.0.1 localhost 127.0.0.1 b612 +8.8.8.8 ssh.b612.me #special IPv6 addresses ::1 localhost ipv6-localhost ipv6-loopback fe00::0 ipv6-localnet