@@ -56,14 +56,17 @@ type IDMap struct {
5656 Count int64
5757}
5858
59- func parseLine (line []byte , v ... any ) error {
59+ func parseLine (line []byte , v ... any ) (ok bool , _ error ) {
60+ line = bytes .TrimSpace (line )
61+ if len (line ) == 0 {
62+ return false , nil
63+ }
6064 return parseParts (bytes .Split (line , []byte (":" )), v ... )
6165}
6266
63- func parseParts (parts [][]byte , v ... any ) error {
67+ func parseParts (parts [][]byte , v ... any ) ( ok bool , _ error ) {
6468 if len (parts ) == 0 {
65- // TODO(thaJeztah); do we need an "ok" return so that we can skip these in loops?
66- return nil
69+ return false , nil
6770 }
6871
6972 for i , p := range parts {
@@ -82,18 +85,18 @@ func parseParts(parts [][]byte, v ...any) error {
8285 if len (p ) != 0 {
8386 n , ok , err := parseNumeric (string (p ))
8487 if err != nil {
85- return fmt .Errorf ("parsing integer field %d: %w" , i , err )
88+ return true , fmt .Errorf ("parsing integer field %d: %w" , i , err )
8689 }
8790 if ! ok {
88- return fmt .Errorf ("parsing integer field %d: %q is not numeric" , i , p )
91+ return true , fmt .Errorf ("parsing integer field %d: %q is not numeric" , i , p )
8992 }
9093 * e = n
9194 }
9295 case * int64 :
9396 if len (p ) != 0 {
9497 n , err := strconv .ParseInt (string (p ), 10 , 64 )
9598 if err != nil {
96- return fmt .Errorf ("parsing integer field %d: %w" , i , err )
99+ return true , fmt .Errorf ("parsing integer field %d: %w" , i , err )
97100 }
98101 * e = n
99102 }
@@ -109,7 +112,7 @@ func parseParts(parts [][]byte, v ...any) error {
109112 panic (fmt .Sprintf ("parseLine only accepts {*string, *int, *int64, *[]string} as arguments! %#v is not a pointer!" , e ))
110113 }
111114 }
112- return nil
115+ return true , nil
113116}
114117
115118func ParsePasswdFile (path string ) ([]User , error ) {
@@ -151,8 +154,9 @@ func ParsePasswdFilter(r io.Reader, filter func(User) bool) ([]User, error) {
151154 // root:x:0:0:root:/root:/bin/bash
152155 // adm:x:3:4:adm:/var/adm:/bin/false
153156 p := User {}
154- if err := parseLine (line , & p .Name , & p .Pass , & p .Uid , & p .Gid , & p .Gecos , & p .Home , & p .Shell ); err != nil {
155- // Skip malformed lines, and don't consider them.
157+ ok , err := parseLine (line , & p .Name , & p .Pass , & p .Uid , & p .Gid , & p .Gecos , & p .Home , & p .Shell )
158+ if err != nil || ! ok {
159+ // Skip malformed and empty lines, and don't consider them.
156160 continue
157161 }
158162
@@ -213,8 +217,9 @@ func ParseGroupFilter(r io.Reader, filter func(Group) bool) ([]Group, error) {
213217 // root:x:0:root
214218 // adm:x:4:root,adm,daemon
215219 p := Group {}
216- if err := parseLine (line , & p .Name , & p .Pass , & p .Gid , & p .List ); err != nil {
217- // Skip malformed lines, and don't consider them.
220+ ok , err := parseLine (line , & p .Name , & p .Pass , & p .Gid , & p .List )
221+ if err != nil || ! ok {
222+ // Skip malformed and empty lines, and don't consider them.
218223 continue
219224 }
220225
@@ -530,8 +535,9 @@ func ParseSubIDFilter(r io.Reader, filter func(SubID) bool) ([]SubID, error) {
530535
531536 // see: man 5 subuid
532537 p := SubID {}
533- if err := parseLine (line , & p .Name , & p .SubID , & p .Count ); err != nil {
534- // Skip malformed lines, and don't consider them.
538+ ok , err := parseLine (line , & p .Name , & p .SubID , & p .Count )
539+ if err != nil || ! ok {
540+ // Skip malformed and empty lines, and don't consider them.
535541 continue
536542 }
537543
@@ -581,8 +587,9 @@ func ParseIDMapFilter(r io.Reader, filter func(IDMap) bool) ([]IDMap, error) {
581587
582588 // see: man 7 user_namespaces
583589 p := IDMap {}
584- if err := parseParts (bytes .Fields (line ), & p .ID , & p .ParentID , & p .Count ); err != nil {
585- // Skip malformed lines, and don't consider them.
590+ ok , err := parseParts (bytes .Fields (line ), & p .ID , & p .ParentID , & p .Count )
591+ if err != nil || ! ok {
592+ // Skip malformed and empty lines, and don't consider them.
586593 continue
587594 }
588595
0 commit comments