{"action":"created","comment":{"url":"https://api.github.com/repos/u-root/u-root/pulls/comments/185979645","pull_request_review_id":117481358,"id":185979645,"diff_hunk":"@@ -0,0 +1,154 @@\n+/* The cmdline package provides a parser and convienence functions for reading\n+   configuration data from /proc/cmdline it's conformant with\n+   https://www.kernel.org/doc/html/v4.14/admin-guide/kernel-parameters.html,\n+   though making 'var_name' and 'var-name' equivalent may need to be done\n+   separately. */\n+\n+package cmdline\n+\n+import (\n+\t\"fmt\"\n+\t\"io\"\n+\t\"io/ioutil\"\n+\t\"log\"\n+\t\"os\"\n+\t\"strings\"\n+\t\"sync\"\n+\t\"unicode\"\n+)\n+\n+// CmdLine lets people view the raw & parsed /proc/cmdline in one place\n+type CmdLine struct {\n+\traw   string\n+\tasmap map[string]string\n+\terr   error\n+}\n+\n+var (\n+\t// procCmdLine package level static variable initialized once\n+\tonce        sync.Once\n+\tprocCmdLine CmdLine\n+)\n+\n+func cmdLineOpener() {\n+\tcmdlineReader, err := os.Open(\"/proc/cmdline\")\n+\tif err != nil {\n+\t\terrorMsg := fmt.Sprintf(\"Can't open /proc/cmdline: %v\", err)\n+\t\tlog.Print(errorMsg)\n+\t\tprocCmdLine = CmdLine{err: fmt.Errorf(errorMsg)}\n+\t\treturn\n+\t}\n+\n+\tprocCmdLine = parse(cmdlineReader)\n+\tcmdlineReader.Close()\n+}\n+\n+// NewCmdLine returns a populated CmdLine struct\n+func NewCmdLine() CmdLine {\n+\t// We use cmdLineReader so tests can inject here\n+\tonce.Do(cmdLineOpener)\n+\treturn procCmdLine\n+}\n+\n+// FullCmdLine returns the full, raw cmdline string\n+func FullCmdLine() string {\n+\tonce.Do(cmdLineOpener)\n+\treturn procCmdLine.raw\n+}\n+\n+// parse returns the current command line, trimmed\n+func parse(cmdlineReader io.Reader) CmdLine {\n+\traw, err := ioutil.ReadAll(cmdlineReader)\n+\tline := CmdLine{}\n+\tif err != nil {\n+\t\tlog.Printf(\"Can't read command line: %v\", err)\n+\t\tline.err = err\n+\t} else {\n+\t\tline.raw = strings.TrimRight(string(raw), \"\\n\")\n+\t\tline.asmap = parseToMap(line.raw)\n+\t}\n+\treturn line\n+}\n+\n+// parseToMap turns a space-separated kernel commandline into a map\n+func parseToMap(input string) map[string]string {\n+\n+\tlastQuote := rune(0)\n+\tquotedFieldsCheck := func(c rune) bool {\n+\t\tswitch {\n+\t\tcase c == lastQuote:\n+\t\t\tlastQuote = rune(0)\n+\t\t\treturn false\n+\t\tcase lastQuote != rune(0):\n+\t\t\treturn false\n+\t\tcase unicode.In(c, unicode.Quotation_Mark):\n+\t\t\tlastQuote = c\n+\t\t\treturn false\n+\t\tdefault:\n+\t\t\treturn unicode.IsSpace(c)\n+\t\t}\n+\t}\n+\n+\tflagMap := make(map[string]string)\n+\tfor _, flag := range strings.FieldsFunc(string(input), quotedFieldsCheck) {\n+\t\t// kernel variables must allow '-' and '_' to be equivalent in variable\n+\t\t// names. We will replace dashes with underscores for processing.\n+\n+\t\t// Split the flag into a key and value, setting value=\"1\" if none\n+\t\tsplit := strings.Index(flag, \"=\")\n+\n+\t\tif len(flag) == 0 {\n+\t\t\tcontinue\n+\t\t}\n+\t\tvar key, value string\n+\t\tif split == -1 {\n+\t\t\tkey = flag\n+\t\t\tvalue = \"1\"\n+\t\t} else {\n+\t\t\tkey = flag[:split]\n+\t\t\tvalue = flag[split+1:]\n+\t\t}\n+\t\t// We store the value twice, once with dash, once with underscores\n+\t\t// Just in case people check with the wrong method\n+\t\tcanonicalKey := strings.Replace(key, \"-\", \"_\", -1)\n+\t\ttrimmedValue := strings.Trim(value, \"\\\"'\")\n+\t\tflagMap[canonicalKey] = trimmedValue\n+\t\tflagMap[key] = trimmedValue\n+\t}\n+\n+\treturn flagMap\n+}\n+\n+// ContainsFlag verifies that the kernel cmdline has a flag set\n+func ContainsFlag(flag string) bool {\n+\tonce.Do(cmdLineOpener)\n+\t_, present := Flag(flag)\n+\treturn present\n+}\n+\n+// Flag returns the a flag, and whether it was set\n+func Flag(flag string) (string, bool) {\n+\tonce.Do(cmdLineOpener)\n+\tcanonicalFlag := strings.Replace(flag, \"-\", \"_\", -1)\n+\tvalue, present := procCmdLine.asmap[canonicalFlag]\n+\treturn value, present\n+}\n+\n+// getFlagMap gets specified flags as a map\n+func getFlagMap(flagName string) map[string]string {\n+\treturn parseToMap(flagName)\n+}\n+\n+// GetUinitFlagMap gets the uinit flags as a map\n+func GetUinitFlagMap() map[string]string {\n+\tonce.Do(cmdLineOpener)\n+\tuinitflags, _ := Flag(\"uroot.uinitflags\")\n+\treturn getFlagMap(uinitflags)\n+}\n+\n+// GetInitFlagMap gets the init flags as a map\n+func GetInitFlagMap() map[string]string {\n+\tonce.Do(cmdLineOpener)","path":"pkg/cmdline/cmdline.go","position":151,"original_position":151,"commit_id":"028ea606b70b56a431c1dd74b5ee91d4dbd0cd21","original_commit_id":"028ea606b70b56a431c1dd74b5ee91d4dbd0cd21","user":{"login":"hugelgupf","id":1994130,"avatar_url":"https://avatars2.githubusercontent.com/u/1994130?v=4","gravatar_id":"","url":"https://api.github.com/users/hugelgupf","html_url":"https://github.com/hugelgupf","followers_url":"https://api.github.com/users/hugelgupf/followers","following_url":"https://api.github.com/users/hugelgupf/following{/other_user}","gists_url":"https://api.github.com/users/hugelgupf/gists{/gist_id}","starred_url":"https://api.github.com/users/hugelgupf/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/hugelgupf/subscriptions","organizations_url":"https://api.github.com/users/hugelgupf/orgs","repos_url":"https://api.github.com/users/hugelgupf/repos","events_url":"https://api.github.com/users/hugelgupf/events{/privacy}","received_events_url":"https://api.github.com/users/hugelgupf/received_events","type":"User","site_admin":false},"body":"ditto","created_at":"2018-05-04T02:14:09Z","updated_at":"2018-05-04T02:14:09Z","html_url":"https://github.com/u-root/u-root/pull/734#discussion_r185979645","pull_request_url":"https://api.github.com/repos/u-root/u-root/pulls/734","author_association":"OWNER","_links":{"self":{"href":"https://api.github.com/repos/u-root/u-root/pulls/comments/185979645"},"html":{"href":"https://github.com/u-root/u-root/pull/734#discussion_r185979645"},"pull_request":{"href":"https://api.github.com/repos/u-root/u-root/pulls/734"}}},"pull_request":{"url":"https://api.github.com/repos/u-root/u-root/pulls/734","id":185763532,"html_url":"https://github.com/u-root/u-root/pull/734","diff_url":"https://github.com/u-root/u-root/pull/734.diff","patch_url":"https://github.com/u-root/u-root/pull/734.patch","issue_url":"https://api.github.com/repos/u-root/u-root/issues/734","number":734,"state":"open","locked":false,"title":"pkg/cmdline abstracts /proc/cmdline parsing&flags","user":{"login":"BigValen","id":1176368,"avatar_url":"https://avatars2.githubusercontent.com/u/1176368?v=4","gravatar_id":"","url":"https://api.github.com/users/BigValen","html_url":"https://github.com/BigValen","followers_url":"https://api.github.com/users/BigValen/followers","following_url":"https://api.github.com/users/BigValen/following{/other_user}","gists_url":"https://api.github.com/users/BigValen/gists{/gist_id}","starred_url":"https://api.github.com/users/BigValen/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/BigValen/subscriptions","organizations_url":"https://api.github.com/users/BigValen/orgs","repos_url":"https://api.github.com/users/BigValen/repos","events_url":"https://api.github.com/users/BigValen/events{/privacy}","received_events_url":"https://api.github.com/users/BigValen/received_events","type":"User","site_admin":false},"body":"This makes a command line parsing package that can be used to pull out flags, and nested flags, in /proc/cmdline. It takes care to ensure that keys containing dashes and underscores are considered equivalent.\r\n\r\nIt introduces methods for pulling out 'nested flags', namely:\r\n- uroot.uinitflags\r\n- uroot.initflags\r\nThat can be used to configure uroot's init & uinit.\r\n\r\nThe package was designed with an init() method, so that it parses /proc/cmdline on loading. It shouldn't use much resources, but I'd appreciate considering if that's appropriate before approving.\r\n\r\nSigned-off-by: John Looney <johnlooney@fb.com>\r\n","created_at":"2018-05-03T15:59:33Z","updated_at":"2018-05-04T02:14:09Z","closed_at":null,"merged_at":null,"merge_commit_sha":"b1959dbc3c036ea7cc263e006aa0392367000a57","assignee":null,"assignees":[],"requested_reviewers":[{"login":"insomniacslk","id":2356960,"avatar_url":"https://avatars3.githubusercontent.com/u/2356960?v=4","gravatar_id":"","url":"https://api.github.com/users/insomniacslk","html_url":"https://github.com/insomniacslk","followers_url":"https://api.github.com/users/insomniacslk/followers","following_url":"https://api.github.com/users/insomniacslk/following{/other_user}","gists_url":"https://api.github.com/users/insomniacslk/gists{/gist_id}","starred_url":"https://api.github.com/users/insomniacslk/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/insomniacslk/subscriptions","organizations_url":"https://api.github.com/users/insomniacslk/orgs","repos_url":"https://api.github.com/users/insomniacslk/repos","events_url":"https://api.github.com/users/insomniacslk/events{/privacy}","received_events_url":"https://api.github.com/users/insomniacslk/received_events","type":"User","site_admin":false}],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/u-root/u-root/pulls/734/commits","review_comments_url":"https://api.github.com/repos/u-root/u-root/pulls/734/comments","review_comment_url":"https://api.github.com/repos/u-root/u-root/pulls/comments{/number}","comments_url":"https://api.github.com/repos/u-root/u-root/issues/734/comments","statuses_url":"https://api.github.com/repos/u-root/u-root/statuses/028ea606b70b56a431c1dd74b5ee91d4dbd0cd21","head":{"label":"BigValen:master","ref":"master","sha":"028ea606b70b56a431c1dd74b5ee91d4dbd0cd21","user":{"login":"BigValen","id":1176368,"avatar_url":"https://avatars2.githubusercontent.com/u/1176368?v=4","gravatar_id":"","url":"https://api.github.com/users/BigValen","html_url":"https://github.com/BigValen","followers_url":"https://api.github.com/users/BigValen/followers","following_url":"https://api.github.com/users/BigValen/following{/other_user}","gists_url":"https://api.github.com/users/BigValen/gists{/gist_id}","starred_url":"https://api.github.com/users/BigValen/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/BigValen/subscriptions","organizations_url":"https://api.github.com/users/BigValen/orgs","repos_url":"https://api.github.com/users/BigValen/repos","events_url":"https://api.github.com/users/BigValen/events{/privacy}","received_events_url":"https://api.github.com/users/BigValen/received_events","type":"User","site_admin":false},"repo":{"id":131707927,"name":"u-root","full_name":"BigValen/u-root","owner":{"login":"BigValen","id":1176368,"avatar_url":"https://avatars2.githubusercontent.com/u/1176368?v=4","gravatar_id":"","url":"https://api.github.com/users/BigValen","html_url":"https://github.com/BigValen","followers_url":"https://api.github.com/users/BigValen/followers","following_url":"https://api.github.com/users/BigValen/following{/other_user}","gists_url":"https://api.github.com/users/BigValen/gists{/gist_id}","starred_url":"https://api.github.com/users/BigValen/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/BigValen/subscriptions","organizations_url":"https://api.github.com/users/BigValen/orgs","repos_url":"https://api.github.com/users/BigValen/repos","events_url":"https://api.github.com/users/BigValen/events{/privacy}","received_events_url":"https://api.github.com/users/BigValen/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/BigValen/u-root","description":"A fully Go userland! u-root can create a root file system (initramfs) containing a busybox-like set of tools written in Go.","fork":true,"url":"https://api.github.com/repos/BigValen/u-root","forks_url":"https://api.github.com/repos/BigValen/u-root/forks","keys_url":"https://api.github.com/repos/BigValen/u-root/keys{/key_id}","collaborators_url":"https://api.github.com/repos/BigValen/u-root/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/BigValen/u-root/teams","hooks_url":"https://api.github.com/repos/BigValen/u-root/hooks","issue_events_url":"https://api.github.com/repos/BigValen/u-root/issues/events{/number}","events_url":"https://api.github.com/repos/BigValen/u-root/events","assignees_url":"https://api.github.com/repos/BigValen/u-root/assignees{/user}","branches_url":"https://api.github.com/repos/BigValen/u-root/branches{/branch}","tags_url":"https://api.github.com/repos/BigValen/u-root/tags","blobs_url":"https://api.github.com/repos/BigValen/u-root/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/BigValen/u-root/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/BigValen/u-root/git/refs{/sha}","trees_url":"https://api.github.com/repos/BigValen/u-root/git/trees{/sha}","statuses_url":"https://api.github.com/repos/BigValen/u-root/statuses/{sha}","languages_url":"https://api.github.com/repos/BigValen/u-root/languages","stargazers_url":"https://api.github.com/repos/BigValen/u-root/stargazers","contributors_url":"https://api.github.com/repos/BigValen/u-root/contributors","subscribers_url":"https://api.github.com/repos/BigValen/u-root/subscribers","subscription_url":"https://api.github.com/repos/BigValen/u-root/subscription","commits_url":"https://api.github.com/repos/BigValen/u-root/commits{/sha}","git_commits_url":"https://api.github.com/repos/BigValen/u-root/git/commits{/sha}","comments_url":"https://api.github.com/repos/BigValen/u-root/comments{/number}","issue_comment_url":"https://api.github.com/repos/BigValen/u-root/issues/comments{/number}","contents_url":"https://api.github.com/repos/BigValen/u-root/contents/{+path}","compare_url":"https://api.github.com/repos/BigValen/u-root/compare/{base}...{head}","merges_url":"https://api.github.com/repos/BigValen/u-root/merges","archive_url":"https://api.github.com/repos/BigValen/u-root/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/BigValen/u-root/downloads","issues_url":"https://api.github.com/repos/BigValen/u-root/issues{/number}","pulls_url":"https://api.github.com/repos/BigValen/u-root/pulls{/number}","milestones_url":"https://api.github.com/repos/BigValen/u-root/milestones{/number}","notifications_url":"https://api.github.com/repos/BigValen/u-root/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/BigValen/u-root/labels{/name}","releases_url":"https://api.github.com/repos/BigValen/u-root/releases{/id}","deployments_url":"https://api.github.com/repos/BigValen/u-root/deployments","created_at":"2018-05-01T11:58:20Z","updated_at":"2018-05-03T22:25:24Z","pushed_at":"2018-05-03T22:25:22Z","git_url":"git://github.com/BigValen/u-root.git","ssh_url":"git@github.com:BigValen/u-root.git","clone_url":"https://github.com/BigValen/u-root.git","svn_url":"https://github.com/BigValen/u-root","homepage":"http://u-root.tk","size":32549,"stargazers_count":0,"watchers_count":0,"language":"Go","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"archived":false,"open_issues_count":0,"license":{"key":"bsd-3-clause","name":"BSD 3-Clause \"New\" or \"Revised\" License","spdx_id":"BSD-3-Clause","url":"https://api.github.com/licenses/bsd-3-clause"},"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"u-root:master","ref":"master","sha":"e624da1c4bbc739c2271d1cbff626d87441091e5","user":{"login":"u-root","id":13317538,"avatar_url":"https://avatars3.githubusercontent.com/u/13317538?v=4","gravatar_id":"","url":"https://api.github.com/users/u-root","html_url":"https://github.com/u-root","followers_url":"https://api.github.com/users/u-root/followers","following_url":"https://api.github.com/users/u-root/following{/other_user}","gists_url":"https://api.github.com/users/u-root/gists{/gist_id}","starred_url":"https://api.github.com/users/u-root/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/u-root/subscriptions","organizations_url":"https://api.github.com/users/u-root/orgs","repos_url":"https://api.github.com/users/u-root/repos","events_url":"https://api.github.com/users/u-root/events{/privacy}","received_events_url":"https://api.github.com/users/u-root/received_events","type":"Organization","site_admin":false},"repo":{"id":46462030,"name":"u-root","full_name":"u-root/u-root","owner":{"login":"u-root","id":13317538,"avatar_url":"https://avatars3.githubusercontent.com/u/13317538?v=4","gravatar_id":"","url":"https://api.github.com/users/u-root","html_url":"https://github.com/u-root","followers_url":"https://api.github.com/users/u-root/followers","following_url":"https://api.github.com/users/u-root/following{/other_user}","gists_url":"https://api.github.com/users/u-root/gists{/gist_id}","starred_url":"https://api.github.com/users/u-root/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/u-root/subscriptions","organizations_url":"https://api.github.com/users/u-root/orgs","repos_url":"https://api.github.com/users/u-root/repos","events_url":"https://api.github.com/users/u-root/events{/privacy}","received_events_url":"https://api.github.com/users/u-root/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/u-root/u-root","description":"A fully Go userland! u-root can create a root file system (initramfs) containing a busybox-like set of tools written in Go.","fork":false,"url":"https://api.github.com/repos/u-root/u-root","forks_url":"https://api.github.com/repos/u-root/u-root/forks","keys_url":"https://api.github.com/repos/u-root/u-root/keys{/key_id}","collaborators_url":"https://api.github.com/repos/u-root/u-root/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/u-root/u-root/teams","hooks_url":"https://api.github.com/repos/u-root/u-root/hooks","issue_events_url":"https://api.github.com/repos/u-root/u-root/issues/events{/number}","events_url":"https://api.github.com/repos/u-root/u-root/events","assignees_url":"https://api.github.com/repos/u-root/u-root/assignees{/user}","branches_url":"https://api.github.com/repos/u-root/u-root/branches{/branch}","tags_url":"https://api.github.com/repos/u-root/u-root/tags","blobs_url":"https://api.github.com/repos/u-root/u-root/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/u-root/u-root/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/u-root/u-root/git/refs{/sha}","trees_url":"https://api.github.com/repos/u-root/u-root/git/trees{/sha}","statuses_url":"https://api.github.com/repos/u-root/u-root/statuses/{sha}","languages_url":"https://api.github.com/repos/u-root/u-root/languages","stargazers_url":"https://api.github.com/repos/u-root/u-root/stargazers","contributors_url":"https://api.github.com/repos/u-root/u-root/contributors","subscribers_url":"https://api.github.com/repos/u-root/u-root/subscribers","subscription_url":"https://api.github.com/repos/u-root/u-root/subscription","commits_url":"https://api.github.com/repos/u-root/u-root/commits{/sha}","git_commits_url":"https://api.github.com/repos/u-root/u-root/git/commits{/sha}","comments_url":"https://api.github.com/repos/u-root/u-root/comments{/number}","issue_comment_url":"https://api.github.com/repos/u-root/u-root/issues/comments{/number}","contents_url":"https://api.github.com/repos/u-root/u-root/contents/{+path}","compare_url":"https://api.github.com/repos/u-root/u-root/compare/{base}...{head}","merges_url":"https://api.github.com/repos/u-root/u-root/merges","archive_url":"https://api.github.com/repos/u-root/u-root/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/u-root/u-root/downloads","issues_url":"https://api.github.com/repos/u-root/u-root/issues{/number}","pulls_url":"https://api.github.com/repos/u-root/u-root/pulls{/number}","milestones_url":"https://api.github.com/repos/u-root/u-root/milestones{/number}","notifications_url":"https://api.github.com/repos/u-root/u-root/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/u-root/u-root/labels{/name}","releases_url":"https://api.github.com/repos/u-root/u-root/releases{/id}","deployments_url":"https://api.github.com/repos/u-root/u-root/deployments","created_at":"2015-11-19T02:28:59Z","updated_at":"2018-05-03T16:02:44Z","pushed_at":"2018-05-04T01:52:08Z","git_url":"git://github.com/u-root/u-root.git","ssh_url":"git@github.com:u-root/u-root.git","clone_url":"https://github.com/u-root/u-root.git","svn_url":"https://github.com/u-root/u-root","homepage":"http://u-root.tk","size":33732,"stargazers_count":599,"watchers_count":599,"language":"Go","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":86,"mirror_url":null,"archived":false,"open_issues_count":95,"license":{"key":"bsd-3-clause","name":"BSD 3-Clause \"New\" or \"Revised\" License","spdx_id":"BSD-3-Clause","url":"https://api.github.com/licenses/bsd-3-clause"},"forks":86,"open_issues":95,"watchers":599,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/u-root/u-root/pulls/734"},"html":{"href":"https://github.com/u-root/u-root/pull/734"},"issue":{"href":"https://api.github.com/repos/u-root/u-root/issues/734"},"comments":{"href":"https://api.github.com/repos/u-root/u-root/issues/734/comments"},"review_comments":{"href":"https://api.github.com/repos/u-root/u-root/pulls/734/comments"},"review_comment":{"href":"https://api.github.com/repos/u-root/u-root/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/u-root/u-root/pulls/734/commits"},"statuses":{"href":"https://api.github.com/repos/u-root/u-root/statuses/028ea606b70b56a431c1dd74b5ee91d4dbd0cd21"}},"author_association":"NONE"}}
{"actor":{"display_login":"hugelgupf"}}