github.com/u-root/u-root@v7.0.1-0.20200915234505-ad7babab0a8e+incompatible/pkg/namespace/parser.go (about) 1 // Copyright 2020 the u-root Authors. All rights reserved 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Package namespace parses name space description files 6 // https://plan9.io/magic/man2html/6/namespace 7 package namespace 8 9 import ( 10 "bufio" 11 "fmt" 12 "io" 13 "os" 14 "strings" 15 ) 16 17 // Parse takes a namespace file and returns a collection 18 // of operations that build a name space in plan9. 19 // 20 // think oci runtime spec, but don't think too much cause the json 21 // will make your head hurt. 22 // 23 // http://man.cat-v.org/plan_9/1/ns 24 // 25 func Parse(r io.Reader) (File, error) { 26 scanner := bufio.NewScanner(r) 27 28 cmds := []Modifier{} 29 for scanner.Scan() { 30 buf := scanner.Bytes() 31 if len(buf) <= 0 { 32 continue 33 } 34 r := buf[0] 35 // Blank lines and lines with # as the first non–space character are ignored. 36 if r == '#' || r == ' ' { 37 continue 38 } 39 cmd, err := ParseLine(scanner.Text()) 40 41 if err != nil { 42 return nil, err 43 } 44 cmds = append(cmds, cmd) 45 } 46 if err := scanner.Err(); err != nil { 47 fmt.Fprintln(os.Stderr, "reading standard input:", err) 48 } 49 return cmds, nil 50 } 51 52 // ParseFlags parses flags as mount, bind would. 53 // Not using the os.Flag package here as that would break the 54 // name space description files. 55 // https://9p.io/magic/man2html/6/namespace 56 func ParseFlags(args []string) (mountflag, []string) { 57 flag := REPL 58 for i, arg := range args { 59 // these args are passed trough strings.Fields which doesn't return empty strings 60 // so this is ok. 61 if arg[0] == '-' { 62 args = append(args[:i], args[i+1:]...) 63 for _, r := range arg { 64 switch r { 65 case 'a': 66 flag |= AFTER 67 case 'b': 68 flag |= BEFORE 69 case 'c': 70 flag |= CREATE 71 case 'q': 72 // todo(sevki): support quiet flag 73 case 'C': 74 flag |= CACHE 75 default: 76 } 77 } 78 } 79 } 80 return flag, args 81 } 82 83 // ParseArgs could be used to parse os.Args 84 // to unify all commangs under a namespace.Main() 85 // it isn't. 86 func ParseArgs(args []string) (Modifier, error) { 87 arg := args[0] 88 args = args[1:] 89 trap := syzcall(0) 90 91 c := cmd{ 92 syscall: trap, 93 flag: REPL, 94 args: args, 95 } 96 switch arg { 97 case "bind": 98 c.syscall = BIND 99 case "mount": 100 c.syscall = MOUNT 101 case "unmount": 102 c.syscall = UNMOUNT 103 case "clear": 104 c.syscall = RFORK 105 case "cd": 106 c.syscall = CHDIR 107 case ".": 108 c.syscall = INCLUDE 109 case "import": 110 c.syscall = IMPORT 111 default: 112 panic(arg) 113 } 114 115 c.flag, c.args = ParseFlags(args) 116 117 return c, nil 118 } 119 120 // ParseLine could be used to parse os.Args 121 // to unify all commangs under a namespace.Main() 122 // it isn't. 123 func ParseLine(line string) (Modifier, error) { 124 return ParseArgs(strings.Fields(line)) 125 }