package main import ( "fmt" "sort" "strings" ) // Host is one static host entry: hostname, IP, optional MAC, free-text comment. type Host struct { Name string IP string MAC string // "" if not set Comment string } const hostHeader = "# ipadm host database - managed with `ipadm`, do not edit while ipadm is running\n" + "# name\tip\tmac\tcomment\n" // One line per host, tab-separated: name\tip\tmac\tcomment // MAC is stored as "-" when empty. func parseHostLine(line string) (Host, error) { parts := strings.SplitN(line, "\t", 4) if len(parts) < 3 { return Host{}, fmt.Errorf("invalid line (expected at least 3 tab-separated fields): %q", line) } mac := parts[2] if mac == "-" { mac = "" } comment := "" if len(parts) == 4 { comment = parts[3] } return Host{Name: parts[0], IP: parts[1], MAC: mac, Comment: comment}, nil } func formatHostLine(h Host) string { mac := h.MAC if mac == "" { mac = "-" } return fmt.Sprintf("%s\t%s\t%s\t%s", h.Name, h.IP, mac, h.Comment) } func openHostStore(path string) (*LineStore[Host], error) { return openLineStore(path, hostHeader, parseHostLine, formatHostLine) } func sortHosts(hosts []Host) { sort.Slice(hosts, func(i, j int) bool { return strings.ToLower(hosts[i].Name) < strings.ToLower(hosts[j].Name) }) } func findHost(hosts []Host, name string) int { for i, h := range hosts { if strings.EqualFold(h.Name, name) { return i } } return -1 } func findByIP(hosts []Host, ip string, exceptIdx int) int { for i, h := range hosts { if i != exceptIdx && h.IP == ip { return i } } return -1 } func findByMAC(hosts []Host, mac string, exceptIdx int) int { if mac == "" { return -1 } for i, h := range hosts { if i != exceptIdx && h.MAC != "" && strings.EqualFold(h.MAC, mac) { return i } } return -1 }