From 4a026c0935110e23e66116d419b195905b0cf387 Mon Sep 17 00:00:00 2001 From: 兔子 Date: Mon, 8 Jun 2020 14:52:16 +0800 Subject: [PATCH] v1.0.0 --- files.go | 3 +- hosts/hosts.go | 213 ++++++++++ hosts/hosts_test.go | 12 + os.go | 47 +++ os_linux.go | 17 +- os_test.go | 11 + os_windows.go | 30 ++ process_linux.go | 15 + process_win.go | 11 + sysconf/sysconf.go | 840 ++++++++++++++++++++++++++++++++++++++++ sysconf/sysconf_test.go | 38 ++ sysconf/typed.go | 1 + typed.go | 7 + 13 files changed, 1242 insertions(+), 3 deletions(-) create mode 100644 hosts/hosts.go create mode 100644 hosts/hosts_test.go create mode 100644 os.go create mode 100644 os_test.go create mode 100644 sysconf/sysconf.go create mode 100644 sysconf/sysconf_test.go create mode 100644 sysconf/typed.go diff --git a/files.go b/files.go index 0e81316..c22abb8 100644 --- a/files.go +++ b/files.go @@ -11,7 +11,6 @@ func Exists(path string) bool { return true } - // IsFile 返回给定文件地址是否是一个文件, //True为是一个文件,False为不是文件或路径无效 func IsFile(fpath string) bool { @@ -30,4 +29,4 @@ func IsFolder(fpath string) bool { return false } return s.IsDir() -} \ No newline at end of file +} diff --git a/hosts/hosts.go b/hosts/hosts.go new file mode 100644 index 0000000..8df73ff --- /dev/null +++ b/hosts/hosts.go @@ -0,0 +1,213 @@ +package hosts + +import ( + "bytes" + "io/ioutil" + "runtime" + "sync" + + "b612.me/staros/sysconf" +) + +var hostsPath string +var hostsCfg *sysconf.SysConf +var haveError error +var lock sync.Mutex +var reverse bool = false + +func init() { + if runtime.GOOS == "windows" { + hostsPath = `C:\Windows\System32\drivers\etc\hosts` + } else { + hostsPath = `/etc/hosts` + } +} + +func SetHostsPath(path string) { + hostsPath = path +} + +func GetHostsPath() string { + return hostsPath +} + +func Parse() error { + hostsCfg = new(sysconf.SysConf) + hostsCfg.EqualFlag = ` ` + hostsCfg.HaveSegMent = false + hostsCfg.CommentCR = true + hostsCfg.CommentFlag = []string{"#"} + data, haveError := ioutil.ReadFile(hostsPath) + if haveError != nil { + return haveError + } + data = bytes.ReplaceAll(data, []byte(` `), []byte(" ")) + haveError = hostsCfg.Parse(data) + return haveError +} + +func GetIpByDomain(domainName string) []string { + if haveError != nil { + return []string{} + } + lock.Lock() + defer lock.Unlock() + if !reverse { + hostsCfg.Reverse() + reverse = !reverse + } + return hostsCfg.Data[0].GetAll(domainName) +} + +func GetDomainByIp(IpAddr string) []string { + if haveError != nil { + return []string{} + } + lock.Lock() + defer lock.Unlock() + if reverse { + hostsCfg.Reverse() + reverse = !reverse + } + return hostsCfg.Data[0].GetAll(IpAddr) +} + +func AddHosts(ip, host string) { + lock.Lock() + defer lock.Unlock() + if reverse { + hostsCfg.Data[0].AddValue(host, ip, "") + } else { + hostsCfg.Data[0].AddValue(ip, host, "") + } +} + +func RemoveHost(ip, host string) { + lock.Lock() + defer lock.Unlock() + if reverse { + hostsCfg.Data[0].DeleteValue(host, ip) + } else { + hostsCfg.Data[0].DeleteValue(ip, host) + } +} + +func RemoveHostbyIp(ip string) { + lock.Lock() + defer lock.Unlock() + if reverse { + hostsCfg.Reverse() + reverse = !reverse + } + hostsCfg.Data[0].Delete(ip) +} + +func RemoveHostbyHost(host string) { + lock.Lock() + defer lock.Unlock() + if !reverse { + hostsCfg.Reverse() + reverse = !reverse + } + hostsCfg.Data[0].Delete(host) +} + +// SetHost 设定唯一的Host对应值,一个host对应一个ip,其余的删除 +func SetHost(ip, host string) { + lock.Lock() + defer lock.Unlock() + if !reverse { + hostsCfg.Reverse() + reverse = !reverse + } + hostsCfg.Data[0].Set(host, ip, "") +} + +func SetHostbyIp(ip, host string) { + lock.Lock() + defer lock.Unlock() + if reverse { + hostsCfg.Reverse() + reverse = !reverse + } + hostsCfg.Data[0].Set(ip, host, "") +} + +func Build() string { + if reverse { + hostsCfg.Reverse() + reverse = !reverse + } + return string(hostsCfg.Build()) +} + +func Write() error { + lock.Lock() + defer lock.Unlock() + data := []byte(Build()) + return ioutil.WriteFile(hostsPath, data, 0644) +} + +func GetHostList() []string { + var res []string + lock.Lock() + defer lock.Unlock() + if !reverse { + hostsCfg.Reverse() + reverse = !reverse + } + for _, v := range hostsCfg.Data[0].NodeData { + if v != nil { + res = append(res, v.Key) + } + } + return res +} + +func GetIpList() []string { + var res []string + lock.Lock() + defer lock.Unlock() + if reverse { + hostsCfg.Reverse() + reverse = !reverse + } + for _, v := range hostsCfg.Data[0].NodeData { + if v != nil { + res = append(res, v.Key) + } + } + return res +} + +func GetAllListbyHost() map[string][]string { + res := make(map[string][]string) + lock.Lock() + defer lock.Unlock() + if !reverse { + hostsCfg.Reverse() + reverse = !reverse + } + for _, v := range hostsCfg.Data[0].NodeData { + if v != nil { + res[v.Key] = v.Value + } + } + return res +} + +func GetAllListbyIp() map[string][]string { + res := make(map[string][]string) + lock.Lock() + defer lock.Unlock() + if reverse { + hostsCfg.Reverse() + reverse = !reverse + } + for _, v := range hostsCfg.Data[0].NodeData { + if v != nil { + res[v.Key] = v.Value + } + } + return res +} diff --git a/hosts/hosts_test.go b/hosts/hosts_test.go new file mode 100644 index 0000000..46a3eab --- /dev/null +++ b/hosts/hosts_test.go @@ -0,0 +1,12 @@ +package hosts + +import ( + "fmt" + "testing" +) + +func Test_Hosts(t *testing.T) { + //RemoveHostbyIp("192.168.222.33") + Parse() + fmt.Println(GetAllListbyIp()) +} diff --git a/os.go b/os.go new file mode 100644 index 0000000..49fca98 --- /dev/null +++ b/os.go @@ -0,0 +1,47 @@ +package staros + +import ( + "os/user" + "strconv" +) + +// GetUidGid +func GetUidGid(uname string) (uint32, uint32, string, error) { + usr, err := user.Lookup(uname) + if err != nil { + return 0, 0, "", err + } + uidInt, _ := strconv.Atoi(usr.Uid) + gidInt, _ := strconv.Atoi(usr.Gid) + return uint32(uidInt), uint32(gidInt), usr.HomeDir, nil +} + +// GetUid +func GetUid(uname string) (uint32, error) { + usr, err := user.Lookup(uname) + if err != nil { + return 0, err + } + uidInt, _ := strconv.Atoi(usr.Uid) + return uint32(uidInt), nil +} + +// GetGid +func GetGid(uname string) (uint32, error) { + usr, err := user.LookupGroup(uname) + if err != nil { + return 0, err + } + gidInt, _ := strconv.Atoi(usr.Gid) + return uint32(gidInt), nil +} + +// GetGidByName +func GetGidByName(uname string) (uint32, error) { + usr, err := user.Lookup(uname) + if err != nil { + return 0, err + } + uidInt, _ := strconv.Atoi(usr.Gid) + return uint32(uidInt), nil +} diff --git a/os_linux.go b/os_linux.go index 53d2c9c..d0027ad 100644 --- a/os_linux.go +++ b/os_linux.go @@ -94,7 +94,7 @@ func getCPUSample() (idle, total uint64) { } // CpuUsage 获取CPU使用量 -func CpuUsage(sleep time.Time) float64 { +func CpuUsage(sleep time.Duration) float64 { idle0, total0 := getCPUSample() time.Sleep(sleep) idle1, total1 := getCPUSample() @@ -104,3 +104,18 @@ func CpuUsage(sleep time.Time) float64 { return cpuUsage //fmt.Printf("CPU usage is %f%% [busy: %f, total: %f]\n", cpuUsage, totalTicks-idleTicks, totalTicks) } + + + +func DiskUsage(path string) (disk DiskStatus) { + fs := syscall.Statfs_t{} + err := syscall.Statfs(path, &fs) + if err != nil { + return + } + disk.All = fs.Blocks * uint64(fs.Bsize) + disk.Free = fs.Bfree * uint64(fs.Bsize) + disk.Available = fs.Bavail * uint64(fs.Bsize) + disk.Used = disk.All - disk.Free + return +} diff --git a/os_test.go b/os_test.go new file mode 100644 index 0000000..054dbc9 --- /dev/null +++ b/os_test.go @@ -0,0 +1,11 @@ +package staros + +import ( + "fmt" + "testing" +) + +func Test_Disk(t *testing.T) { + a := DiskUsage("c:") + fmt.Println(a) +} diff --git a/os_windows.go b/os_windows.go index 4b59447..55d0d0e 100644 --- a/os_windows.go +++ b/os_windows.go @@ -3,7 +3,10 @@ package staros import ( + "log" + "syscall" "time" + "unsafe" "b612.me/wincmd" @@ -41,3 +44,30 @@ func Memory() MemStatus { mem.VirtualUsed = mem.VirtualAll - mem.VirtualUsed return mem } + +func DiskUsage(path string) (disk DiskStatus) { + kernel32, err := syscall.LoadLibrary("Kernel32.dll") + if err != nil { + log.Panic(err) + } + defer syscall.FreeLibrary(kernel32) + GetDiskFreeSpaceEx, err := syscall.GetProcAddress(syscall.Handle(kernel32), "GetDiskFreeSpaceExW") + + if err != nil { + log.Panic(err) + } + + lpFreeBytesAvailable := int64(0) + lpTotalNumberOfBytes := int64(0) + lpTotalNumberOfFreeBytes := int64(0) + syscall.Syscall6(uintptr(GetDiskFreeSpaceEx), 4, + uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr("C:"))), + uintptr(unsafe.Pointer(&lpFreeBytesAvailable)), + uintptr(unsafe.Pointer(&lpTotalNumberOfBytes)), + uintptr(unsafe.Pointer(&lpTotalNumberOfFreeBytes)), 0, 0) + disk.Free = uint64(lpTotalNumberOfFreeBytes) + disk.Used = uint64(lpTotalNumberOfBytes - lpTotalNumberOfFreeBytes) + disk.All = uint64(lpTotalNumberOfBytes) + disk.Available = uint64(lpFreeBytesAvailable) + return +} diff --git a/process_linux.go b/process_linux.go index bfacf66..443e027 100644 --- a/process_linux.go +++ b/process_linux.go @@ -8,9 +8,11 @@ import ( "fmt" "io/ioutil" "os" + "os/exec" "path/filepath" "strconv" "strings" + "syscall" "time" ) @@ -130,3 +132,16 @@ func FindProcessByPid(pid int64) (datas Process, err error) { datas.Uptime = time.Unix(StartTime().Unix()+uptime/100, int64((float64(uptime)/100-float64(uptime/100))*1000000000)) return } + +func Daemon(path string, args ...string) (int, error) { + cmd := exec.Command(path, args...) + cmd.SysProcAttr = &syscall.SysProcAttr{ + Setsid: true, + } + if err := cmd.Start(); err != nil { + return -1, err + } + pid := cmd.Process.Pid + err := cmd.Process.Release() + return pid, err +} diff --git a/process_win.go b/process_win.go index f31dc27..22a5fa1 100644 --- a/process_win.go +++ b/process_win.go @@ -5,6 +5,7 @@ package staros import ( "errors" "fmt" + "os/exec" "strconv" "b612.me/wincmd" @@ -47,3 +48,13 @@ func FindProcessByPid(pid int64) (data Process, err error) { err = errors.New("Not Found") return } + +func Daemon(path string, args ...string) (int, error) { + cmd := exec.Command(path, args...) + if err := cmd.Start(); err != nil { + return -1, err + } + pid := cmd.Process.Pid + cmd.Process.Release() + return pid, nil +} diff --git a/sysconf/sysconf.go b/sysconf/sysconf.go new file mode 100644 index 0000000..5020e99 --- /dev/null +++ b/sysconf/sysconf.go @@ -0,0 +1,840 @@ +package sysconf + +import ( + "bytes" + "errors" + "fmt" + "io/ioutil" + "reflect" + "strconv" + "strings" + "sync" + + "b612.me/staros" +) + +type SysConf struct { + Data []*SysSegment + segmap map[string]int64 + segId int64 + HaveSegMent bool //是否有节这个概念 + SegStart string + SegEnd string + CommentFlag []string //评论标识符,如# + EqualFlag string //赋值标识符,如= + ValueFlag string //值标识符,如" + EscapeFlag string //转义字符 + CommentCR bool //评论是否能与value同一行,true不行,false可以 + SpaceStr string //美化符号 + lock sync.RWMutex +} + +type SysSegment struct { + Name string + //nodeMap + Comment string + NodeData []*SysNode + nodeId int64 + nodeMap map[string]int64 + lock sync.RWMutex +} + +type SysNode struct { + Key string + Value []string + Comment string + NoValue bool + lock sync.RWMutex +} + +func NewSysConf(EqualFlag string) *SysConf { + syscnf := new(SysConf) + syscnf.EqualFlag = EqualFlag + return syscnf +} + +// NewLinuxConf sysctl.conf like file +func NewLinuxConf(EqualFlag string) *SysConf { + syscnf := new(SysConf) + syscnf.EqualFlag = EqualFlag + syscnf.HaveSegMent = false + syscnf.CommentCR = true + syscnf.CommentFlag = []string{"#"} + return syscnf +} + +func (syscfg *SysConf) ParseFromFile(filepath string) error { + if !staros.Exists(filepath) { + return errors.New(filepath + " 不存在") + } + data, err := ioutil.ReadFile(filepath) + if err != nil { + return err + } + syscfg.Parse(data) + return nil +} + +// Parse 生成INI文件结构 +func (syscfg *SysConf) Parse(data []byte) error { + syscfg.lock.Lock() + defer syscfg.lock.Unlock() + if syscfg.HaveSegMent && (syscfg.SegStart == "" || syscfg.SegEnd == "") { + return errors.New("SegMent Start or End Flag Not Allowed!") + } + if !syscfg.CommentCR { + return syscfg.parseNOCRComment(data) + } + return syscfg.parseCRComment(data) +} + +func (syscfg *SysConf) parseNOCRComment(data []byte) error { //允许comment在同一行 + data = bytes.TrimSpace(data) + dataLists := bytes.Split(data, []byte("\n")) + seg := new(SysSegment) + seg.nodeMap = make(map[string]int64) + syscfg.segmap = make(map[string]int64) + if syscfg.HaveSegMent { + seg.Name = "unnamed" + } + syscfg.segId = 0 + var node *SysNode + for _, v1 := range dataLists { + var ( + isSegStart bool = false + isEscape bool = false + isEqual bool = false + isComment bool = false + tsuMo string = "" + ) + cowStr := strings.TrimSpace(string(v1)) + for i := 0; i < len(cowStr); i++ { + runeStr := cowStr[i : i+1] //当前字符,rune扫描 + if runeStr == syscfg.EscapeFlag && (!isEscape) { + isEscape = true + continue + } + if runeStr == syscfg.SegStart && (!isEscape) { + + isSegStart = true + continue + } + if runeStr == syscfg.SegEnd && (!isEscape) { + isSegStart = false + //New segment start from here + if seg.Name == "unnamed" && len(seg.NodeData) == 0 { + seg.Name = tsuMo + tsuMo = "" + continue + } + syscfg.segmap[seg.Name] = syscfg.segId + syscfg.segId++ + syscfg.Data = append(syscfg.Data, seg) + seg = new(SysSegment) + seg.nodeMap = make(map[string]int64) + seg.Name = tsuMo + tsuMo = "" + continue + } + if isSegStart { + tsuMo += runeStr + if isEscape { + isEscape = false + } + continue + } + if syscfg.EqualFlag == runeStr && (!isEscape) && (!isEqual) { + key := strings.TrimSpace(tsuMo) + if val, ok := seg.nodeMap[key]; ok { + node = seg.NodeData[val] + } else { + node = new(SysNode) + node.Key = key + seg.nodeMap[node.Key] = seg.nodeId + seg.nodeId++ + seg.NodeData = append(seg.NodeData, node) + } + tsuMo = "" + isEqual = true + if syscfg.ValueFlag != "" { + nokoriStr := strings.TrimSpace(cowStr[i+1:]) + isFound := false + isValue := false + for k4, v4 := range nokoriStr { + if string([]rune{v4}) == syscfg.ValueFlag { + isValue = !isValue + } + if SliceIn(syscfg.CommentFlag, string([]rune{v4})) && !isValue { + val := nokoriStr[:k4] + isFound = true + startFinder := strings.Index(val, syscfg.ValueFlag) + endFinder := strings.LastIndex(val, syscfg.ValueFlag) + if !((startFinder == -1 || endFinder == -1) || (endFinder-startFinder <= 0)) { + node.Value = append(node.Value, strings.TrimSpace(val[startFinder+1:endFinder])) + } + node.Comment = nokoriStr[k4+1:] + "\n" + } + } + if !isFound { + startFinder := strings.Index(nokoriStr, syscfg.ValueFlag) + endFinder := strings.LastIndex(nokoriStr, syscfg.ValueFlag) + if (startFinder == -1 || endFinder == -1) || (endFinder-startFinder <= 0) { + break + } + node.Value = append(node.Value, strings.TrimSpace(nokoriStr[startFinder+1:endFinder])) + } + break + } + continue + } + if SliceIn(syscfg.CommentFlag, runeStr) && (!isEscape) { + isComment = true + if seg.nodeId == 0 { + seg.Comment += strings.TrimSpace(cowStr[i+1:]) + "\n" + break + } + if tsuMo != "" { + node.Value = append(node.Value, strings.TrimSpace(tsuMo)) + tsuMo = "" + } + node.Comment += strings.TrimSpace(cowStr[i+1:]) + "\n" + break + } + isEscape = false + tsuMo += runeStr + } + if isEqual && tsuMo != "" { + node.Value = append(node.Value, strings.TrimSpace(tsuMo)) + } + if !isEqual && tsuMo != "" && !isComment { + node = new(SysNode) + node.Key = tsuMo + seg.nodeMap[node.Key] = seg.nodeId + seg.nodeId++ + seg.NodeData = append(seg.NodeData, node) + node.NoValue = true + } + } + if seg != nil { + syscfg.segmap[seg.Name] = syscfg.segId + syscfg.segId++ + syscfg.Data = append(syscfg.Data, seg) + } + return nil +} + +func (syscfg *SysConf) parseCRComment(data []byte) error { //不允许comment在同一行 + data = bytes.TrimSpace(data) + dataLists := bytes.Split(data, []byte("\n")) + seg := new(SysSegment) + seg.nodeMap = make(map[string]int64) + syscfg.segmap = make(map[string]int64) + if syscfg.HaveSegMent { + seg.Name = "unnamed" + } + syscfg.segId = 0 + var node *SysNode + for _, v1 := range dataLists { + var ( + isSegStart bool = false + isEscape bool = false + isEqual bool = false + isComment bool = false + tsuMo string = "" + ) + cowStr := strings.TrimSpace(string(v1)) + for i := 0; i < len(cowStr); i++ { + runeStr := cowStr[i : i+1] //当前字符,rune扫描 + if runeStr == syscfg.EscapeFlag && (!isEscape) { + isEscape = true + continue + } + if runeStr == syscfg.SegStart && (!isEscape) { + + isSegStart = true + continue + } + if runeStr == syscfg.SegEnd && (!isEscape) { + isSegStart = false + //New segment start from here + if seg.Name == "unnamed" && len(seg.NodeData) == 0 { + seg.Name = tsuMo + tsuMo = "" + break + } + syscfg.segmap[seg.Name] = syscfg.segId + syscfg.segId++ + syscfg.Data = append(syscfg.Data, seg) + seg = new(SysSegment) + seg.nodeMap = make(map[string]int64) + seg.Name = tsuMo + tsuMo = "" + break + } + if isSegStart { + tsuMo += runeStr + if isEscape { + isEscape = false + } + continue + } + if syscfg.EqualFlag == runeStr && (!isEscape) && (!isEqual) { + key := strings.TrimSpace(tsuMo) + if val, ok := seg.nodeMap[key]; ok { + node = seg.NodeData[val] + } else { + node = new(SysNode) + node.Key = key + seg.nodeMap[node.Key] = seg.nodeId + seg.nodeId++ + seg.NodeData = append(seg.NodeData, node) + } + tsuMo = "" + isEqual = true + if syscfg.ValueFlag == "" { + node.Value = append(node.Value, TrimEscape(strings.TrimSpace(cowStr[i+1:]), syscfg.EscapeFlag)) + } else { + nokoriStr := strings.TrimSpace(cowStr[i+1:]) + startFinder := strings.Index(nokoriStr, syscfg.ValueFlag) + endFinder := strings.LastIndex(nokoriStr, syscfg.ValueFlag) + if (startFinder == -1 || endFinder == -1) || (endFinder-startFinder <= 0) { + break + } + node.Value = append(node.Value, strings.TrimSpace(nokoriStr[startFinder+1:endFinder])) + } + break + } + if SliceIn(syscfg.CommentFlag, runeStr) && (!isEscape) { + isComment = true + tsuMo = "" + if seg.nodeId == 0 { + seg.Comment += strings.TrimSpace(cowStr[i+1:]) + "\n" + break + } + node.Comment += strings.TrimSpace(cowStr[i+1:]) + "\n" + break + } + isEscape = false + tsuMo += runeStr + } + if !isEqual && tsuMo != "" && !isComment { + node = new(SysNode) + node.Key = tsuMo + seg.nodeMap[node.Key] = seg.nodeId + seg.nodeId++ + seg.NodeData = append(seg.NodeData, node) + node.NoValue = true + } + } + if seg != nil { + syscfg.segmap[seg.Name] = syscfg.segId + syscfg.segId++ + syscfg.Data = append(syscfg.Data, seg) + } + return nil +} + +func (syscfg *SysConf) Build() []byte { + syscfg.lock.Lock() + defer syscfg.lock.Unlock() + var outPut string + for _, v := range syscfg.Data { + if v == nil { + continue + } + if syscfg.HaveSegMent { + outPut += syscfg.SegStart + v.Name + syscfg.SegEnd + "\n" + } + if v.Comment != "" { + v.Comment = v.Comment[:len(v.Comment)-1] + comment := strings.Split(v.Comment, "\n") + for _, vc := range comment { + if vc != "" { + outPut += syscfg.CommentFlag[0] + vc + "\n" + } else { + outPut += "\n" + } + } + } + for _, v2 := range v.NodeData { + if v2 == nil { + continue + } + if v2.NoValue { + outPut += v2.Key + "\n" + } else { + for _, v3 := range v2.Value { + if syscfg.ValueFlag != "" { + outPut += v2.Key + syscfg.SpaceStr + syscfg.EqualFlag + syscfg.SpaceStr + syscfg.ValueFlag + v3 + syscfg.ValueFlag + "\n" + } else { + outPut += v2.Key + syscfg.SpaceStr + syscfg.EqualFlag + syscfg.SpaceStr + syscfg.addEscape(v3) + "\n" + } + } + if len(v2.Value) == 0 { + outPut += v2.Key + syscfg.SpaceStr + syscfg.EqualFlag + "\n" + } + if v2.Comment != "" { + v2.Comment = v2.Comment[:len(v2.Comment)-1] + comment := strings.Split(v2.Comment, "\n") + for _, vc := range comment { + if vc != "" { + outPut += syscfg.CommentFlag[0] + vc + "\n" + } else { + outPut += "\n" + } + } + } + } + } + } + return []byte(outPut) +} + +func (syscfg *SysConf) addEscape(str string) string { + str = strings.ReplaceAll(str, syscfg.EscapeFlag, syscfg.EscapeFlag+syscfg.EscapeFlag) + str = strings.ReplaceAll(str, syscfg.EqualFlag, syscfg.EscapeFlag+syscfg.EqualFlag) + str = strings.ReplaceAll(str, syscfg.SegStart, syscfg.EscapeFlag+syscfg.SegStart) + str = strings.ReplaceAll(str, syscfg.SegEnd, syscfg.EscapeFlag+syscfg.SegEnd) + for _, v := range syscfg.CommentFlag { + str = strings.ReplaceAll(str, v, syscfg.EscapeFlag+v) + } + return str +} + +func (syscfg *SysConf) Reverse() { + syscfg.lock.Lock() + defer syscfg.lock.Unlock() + for _, v := range syscfg.Data { + if v == nil { + continue + } + var ( + NodeData []*SysNode + nodeId int64 + nodeMap map[string]int64 + ) + nodeMap = make(map[string]int64) + for _, v2 := range v.NodeData { + if v2 == nil { + continue + } + for _, v3 := range v2.Value { + var node *SysNode + if val, ok := nodeMap[v3]; ok { + node = NodeData[val] + } else { + node = new(SysNode) + node.Key = v3 + NodeData = append(NodeData, node) + nodeMap[v3] = nodeId + nodeId++ + } + node.Value = append(node.Value, strings.TrimSpace(v2.Key)) + node.Comment += v2.Comment + } + v.NodeData = NodeData + v.nodeId = nodeId + v.nodeMap = nodeMap + } + } +} + +func TrimEscape(text, escape string) string { + var isEscape bool = false + var outPut []rune + if escape == "" { + return text + } + text = strings.TrimSpace(text) + for _, v := range text { + if v == []rune(escape)[0] && !isEscape { + isEscape = true + continue + } + outPut = append(outPut, v) + } + return string(outPut) +} + +func SliceIn(slice interface{}, data interface{}) bool { + typed := reflect.ValueOf(slice) + if typed.Kind() == reflect.Slice || typed.Kind() == reflect.Array { + for i := 0; i < typed.Len(); i++ { + if typed.Index(i).Interface() == data { + return true + } + } + } + return false +} + +// Unmarshal 输出结果到结构体中 +func (cfg *SysConf) Unmarshal(ins interface{}) error { + var structSet func(t reflect.Type, v reflect.Value) error + t := reflect.TypeOf(ins) + v := reflect.ValueOf(ins).Elem() + if v.Kind() != reflect.Struct { + return errors.New("Not a Struct") + } + if t.Kind() != reflect.Ptr || !v.CanSet() { + return errors.New("Cannot Write!") + } + t = t.Elem() + structSet = func(t reflect.Type, v reflect.Value) error { + for i := 0; i < t.NumField(); i++ { + tp := t.Field(i) + vl := v.Field(i) + if !vl.CanSet() { + continue + } + if vl.Type().Kind() == reflect.Struct { + structSet(vl.Type(), vl) + continue + } + seg := tp.Tag.Get("seg") + key := tp.Tag.Get("key") + if seg == "" || key == "" { + continue + } + if _, ok := cfg.segmap[seg]; !ok { + continue + } + segs := cfg.Data[cfg.segmap[seg]] + if segs.Get(key) == "" { + continue + } + switch vl.Kind() { + case reflect.String: + vl.SetString(segs.Get(key)) + case reflect.Int, reflect.Int32, reflect.Int64: + vl.SetInt(segs.Int64(key)) + case reflect.Float32, reflect.Float64: + vl.SetFloat(segs.Float64(key)) + case reflect.Bool: + vl.SetBool(segs.Bool(key)) + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + vl.SetUint(uint64(segs.Int64(key))) + default: + continue + } + } + return nil + } + return structSet(t, v) +} + +// Marshal 输出结果到结构体中 +func (cfg *SysConf) Marshal(ins interface{}) ([]byte, error) { + var structSet func(t reflect.Type, v reflect.Value) + t := reflect.TypeOf(ins) + v := reflect.ValueOf(ins) + if v.Kind() != reflect.Struct { + return nil, errors.New("Not a Struct") + } + if t.Kind() == reflect.Ptr { + t = t.Elem() + v = v.Elem() + } + structSet = func(t reflect.Type, v reflect.Value) { + for i := 0; i < t.NumField(); i++ { + var seg, key, comment string = "", "", "" + tp := t.Field(i) + vl := v.Field(i) + if vl.Type().Kind() == reflect.Struct { + structSet(vl.Type(), vl) + continue + } + seg = tp.Tag.Get("seg") + key = tp.Tag.Get("key") + comment = tp.Tag.Get("comment") + if seg == "" || key == "" { + continue + } + if _, ok := cfg.segmap[seg]; !ok { + cfg.AddSeg(seg) + } + cfg.Seg(seg).Set(key, fmt.Sprint(vl), comment) + } + + } + structSet(t, v) + return cfg.Build(), nil +} + +func (syscfg *SysConf) Seg(name string) *SysSegment { + if _, ok := syscfg.segmap[name]; !ok { + return nil + } + seg := syscfg.Data[syscfg.segmap[name]] + return seg +} + +func (syscfg *SysConf) AddSeg(name string) *SysSegment { + syscfg.lock.Lock() + defer syscfg.lock.Unlock() + if _, ok := syscfg.segmap[name]; !ok { + newseg := new(SysSegment) + newseg.Name = name + newseg.nodeMap = make(map[string]int64) + syscfg.Data = append(syscfg.Data, newseg) + syscfg.segId++ + if syscfg.segmap == nil { + syscfg.segId = 0 + syscfg.segmap = make(map[string]int64) + } + syscfg.segmap[newseg.Name] = syscfg.segId + return newseg + } + seg := syscfg.Data[syscfg.segmap[name]] + return seg +} + +func (syscfg *SysConf) DeleteSeg(name string) error { + syscfg.lock.Lock() + defer syscfg.lock.Unlock() + if _, ok := syscfg.segmap[name]; !ok { + return errors.New("Seg Not Exists") + } + syscfg.Data[syscfg.segmap[name]] = nil + delete(syscfg.segmap, name) + return nil +} + +func (syscfg *SysSegment) GetComment(key string) string { + if v, ok := syscfg.nodeMap[key]; !ok { + return "" + } else { + return syscfg.NodeData[v].Comment + } +} + +func (syscfg *SysSegment) SetComment(key, comment string) error { + syscfg.lock.Lock() + defer syscfg.lock.Unlock() + if v, ok := syscfg.nodeMap[key]; !ok { + return errors.New("Key Not Exists") + } else { + syscfg.NodeData[v].Comment = comment + return nil + } +} + +func (syscfg *SysSegment) Exist(key string) bool { + if _, ok := syscfg.nodeMap[key]; !ok { + return false + } else { + return true + } +} + +func (syscfg *SysSegment) Get(key string) string { + if v, ok := syscfg.nodeMap[key]; !ok { + return "" + } else { + if len(syscfg.NodeData[v].Value) >= 1 { + return syscfg.NodeData[v].Value[0] + } + } + return "" +} + +func (syscfg *SysSegment) GetAll(key string) []string { + if v, ok := syscfg.nodeMap[key]; !ok { + return []string{} + } else { + return syscfg.NodeData[v].Value + } +} + +func (syscfg *SysSegment) Int(key string) int { + val := syscfg.Get(key) + if val == "" { + return 0 + } + res, _ := strconv.Atoi(val) + return res +} + +func (syscfg *SysSegment) Int64(key string) int64 { + val := syscfg.Get(key) + if val == "" { + return 0 + } + res, _ := strconv.ParseInt(val, 10, 64) + return res +} + +func (syscfg *SysSegment) Int32(key string) int32 { + val := syscfg.Get(key) + if val == "" { + return 0 + } + res, _ := strconv.ParseInt(val, 10, 32) + return int32(res) +} + +func (syscfg *SysSegment) Float64(key string) float64 { + val := syscfg.Get(key) + if val == "" { + return 0 + } + res, _ := strconv.ParseFloat(val, 64) + return res +} + +func (syscfg *SysSegment) Float32(key string) float32 { + val := syscfg.Get(key) + if val == "" { + return 0 + } + res, _ := strconv.ParseFloat(val, 32) + return float32(res) +} + +func (syscfg *SysSegment) Bool(key string) bool { + val := syscfg.Get(key) + if val == "" { + return false + } + res, _ := strconv.ParseBool(val) + return res +} + +func (syscfg *SysSegment) SetBool(key string, value bool, comment string) error { + res := strconv.FormatBool(value) + return syscfg.Set(key, res, comment) +} + +func (syscfg *SysSegment) SetFloat64(key string, prec int, value float64, comment string) error { + res := strconv.FormatFloat(value, 'f', prec, 64) + return syscfg.Set(key, res, comment) +} + +func (syscfg *SysSegment) SetFloat32(key string, prec int, value float32, comment string) error { + res := strconv.FormatFloat(float64(value), 'f', prec, 32) + return syscfg.Set(key, res, comment) +} + +func (syscfg *SysSegment) SetUint64(key string, value uint64, comment string) error { + res := strconv.FormatUint(value, 10) + return syscfg.Set(key, res, comment) +} + +func (syscfg *SysSegment) SetInt64(key string, value int64, comment string) error { + res := strconv.FormatInt(value, 10) + return syscfg.Set(key, res, comment) +} + +func (syscfg *SysSegment) SetInt32(key string, value int32, comment string) error { + res := strconv.FormatInt(int64(value), 10) + return syscfg.Set(key, res, comment) +} + +func (syscfg *SysSegment) SetInt(key string, value int, comment string) error { + res := strconv.Itoa(value) + return syscfg.Set(key, res, comment) +} + +func (syscfg *SysSegment) Set(key, value, comment string) error { + syscfg.lock.Lock() + defer syscfg.lock.Unlock() + if v, ok := syscfg.nodeMap[key]; !ok { + node := new(SysNode) + node.Key = key + node.Value = append(node.Value, value) + node.Comment = comment + syscfg.NodeData = append(syscfg.NodeData, node) + syscfg.nodeMap[key] = syscfg.nodeId + syscfg.nodeId++ + return nil + } else { + syscfg.NodeData[v].Value = []string{value} + if comment != "" { + syscfg.NodeData[v].Comment = comment + } + } + return nil +} +func (syscfg *SysSegment) SetAll(key string, value []string, comment string) error { + syscfg.lock.Lock() + defer syscfg.lock.Unlock() + if v, ok := syscfg.nodeMap[key]; !ok { + node := new(SysNode) + node.Key = key + node.Value = value + node.Comment = comment + syscfg.NodeData = append(syscfg.NodeData, node) + syscfg.nodeMap[key] = syscfg.nodeId + syscfg.nodeId++ + return nil + } else { + syscfg.NodeData[v].Value = value + if comment != "" { + syscfg.NodeData[v].Comment = comment + } + } + return nil +} +func (syscfg *SysSegment) AddValue(key, value, comment string) error { + syscfg.lock.Lock() + defer syscfg.lock.Unlock() + if v, ok := syscfg.nodeMap[key]; !ok { + node := new(SysNode) + node.Key = key + node.Value = append(node.Value, value) + node.Comment = comment + syscfg.NodeData = append(syscfg.NodeData, node) + syscfg.nodeMap[key] = syscfg.nodeId + syscfg.nodeId++ + return nil + } else { + syscfg.NodeData[v].Value = append(syscfg.NodeData[v].Value, value) + if comment != "" { + syscfg.NodeData[v].Comment = comment + } + } + return nil +} + +func (syscfg *SysSegment) Delete(key string) error { + syscfg.lock.Lock() + defer syscfg.lock.Unlock() + if v, ok := syscfg.nodeMap[key]; !ok { + return errors.New("Key not exists!") + } else { + if syscfg.NodeData[v].Comment != "" { + cmtSet := false + for j := v - 1; j >= 0; j-- { + if syscfg.NodeData[j] != nil { + syscfg.NodeData[j].Comment += syscfg.NodeData[v].Comment + cmtSet = true + break + } + } + if !cmtSet { + syscfg.Comment += syscfg.NodeData[v].Comment + } + } + syscfg.NodeData[v] = nil + delete(syscfg.nodeMap, key) + } + return nil +} + +func (syscfg *SysSegment) DeleteValue(key string, Value string) error { + syscfg.lock.Lock() + defer syscfg.lock.Unlock() + if v, ok := syscfg.nodeMap[key]; !ok { + return errors.New("Key not exists!") + } else { + data := syscfg.NodeData[v].Value + var vals []string + for _, v := range data { + if v != Value { + vals = append(vals, v) + } + } + syscfg.NodeData[v].Value = vals + } + return nil +} diff --git a/sysconf/sysconf_test.go b/sysconf/sysconf_test.go new file mode 100644 index 0000000..54d3920 --- /dev/null +++ b/sysconf/sysconf_test.go @@ -0,0 +1,38 @@ +package sysconf + +import ( + "fmt" + "testing" +) + +func Test_SliceIn(t *testing.T) { + slice := []string{"ok", "11", "22"} + fmt.Println(SliceIn(slice, "ok")) + fmt.Println(SliceIn(slice, []rune("22"))) + fmt.Println(SliceIn(slice, "342423r")) + fmt.Println(SliceIn(slice, 444)) +} + +func Test_Parse(t *testing.T) { + data := ` +1.2.3.4 'ok.com' +#2.3.4.5 ppp.eor +2.3.4.5 'pp.com' +5.6.7.8 'ok.com' +` + cfg := new(SysConf) + cfg.SegStart = "[" + cfg.SegEnd = "]" + cfg.ValueFlag = "'" + cfg.EqualFlag = " " + //cfg.CommentCR = true + cfg.CommentFlag = []string{"#"} + cfg.EscapeFlag = "\\" + cfg.HaveSegMent = false + cfg.segmap = make(map[string]int64) + fmt.Println(cfg.Parse([]byte(data))) + cfg.Reverse() + cfg.Data[0].Delete(`pp.com`) + //fmt.Println(cfg.Data[0].Comment) + fmt.Println(string(cfg.Build())) +} diff --git a/sysconf/typed.go b/sysconf/typed.go new file mode 100644 index 0000000..fbc7330 --- /dev/null +++ b/sysconf/typed.go @@ -0,0 +1 @@ +package sysconf diff --git a/typed.go b/typed.go index 29c8e6b..87ac891 100644 --- a/typed.go +++ b/typed.go @@ -35,3 +35,10 @@ type MemStatus struct { VirtualAvail uint64 AvailExtended uint64 } + +type DiskStatus struct { + All uint64 + Used uint64 + Free uint64 + Available uint64 +}