package cmds import ( "errors" "os" "os/user" "strconv" "strings" "syscall" ) func Test(args []string) (int, error) { if len(args) <= 2 { return 1, errors.New("test requires at least two arguments") } if strings.HasPrefix(args[1], "-") { return genTest(args[1:]), nil } else { if len(args) != 4 { return 1, nil } _, err := strconv.Atoi(args[1]) if err != nil { return testString(args[1:]), nil } else { return testNumber(args[1:]), nil } } } func testString(args []string) int { sTests := map[string]func() bool{ "=": func() bool { return args[0] == args[2] }, "!=": func() bool { return args[0] != args[2] }, "<": func() bool { return strings.Compare(args[0], args[2]) < 0 }, ">": func() bool { return strings.Compare(args[0], args[2]) > 0 }, } if sTest, ok := sTests[args[1]]; ok && sTest() { return 0 } return 1 } func testNumber(args []string) int { a, _ := strconv.Atoi(args[0]) b, err := strconv.Atoi(args[2]) if err != nil { return 1 } nTests := map[string]func() bool{ "-eq": func() bool { return a == b }, "-ne": func() bool { return a != b }, "-gt": func() bool { return a > b }, "-ge": func() bool { return a >= b }, "-lt": func() bool { return a < b }, "-le": func() bool { return a <= b }, } if nTest, ok := nTests[args[1]]; ok && nTest() { return 0 } return 1 } func genTest(args []string) int { sTests := map[string]func() bool{ "-n": func() bool { return len(args[1]) > 0 }, "-z": func() bool { return len(args[1]) == 0 }, } if sTest, ok := sTests[args[0]]; ok && sTest() { return 0 } fi, err := os.Lstat(args[1]) c, _ := user.Current() if err != nil { return 1 } s := fi.Sys().(*syscall.Stat_t) uid, _ := strconv.Atoi(c.Uid) gid, _ := strconv.Atoi(c.Gid) fTests := map[string]func() bool{ "-e": func() bool { return true }, "-f": func() bool { return !fi.IsDir() }, "-d": func() bool { return fi.IsDir() }, "-r": func() bool { return fi.Mode().Perm()&0400 != 0 }, "-w": func() bool { return fi.Mode().Perm()&0200 != 0 }, "-x": func() bool { return fi.Mode().Perm()&0100 != 0 }, "-S": func() bool { return fi.Size() > 0 }, "-L": func() bool { return fi.Mode()&os.ModeSymlink != 0 }, "-O": func() bool { return uid == int(s.Uid) }, "-G": func() bool { return gid == int(s.Gid) }, } if fTest, ok := fTests[args[0]]; ok && fTest() { return 0 } return 1 }