github.com/google/osv-scalibr@v0.4.1/extractor/filesystem/os/osrelease/osrelease.go (about)

     1  // Copyright 2025 Google LLC
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  // Package osrelease parses the os-release file. More details in `man os-release 5`.
    16  package osrelease
    17  
    18  import (
    19  	"bufio"
    20  	"io"
    21  	"os"
    22  	"strings"
    23  
    24  	scalibrfs "github.com/google/osv-scalibr/fs"
    25  )
    26  
    27  // GetOSRelease tries different os-release locations and parses the first found.
    28  func GetOSRelease(fs scalibrfs.FS) (map[string]string, error) {
    29  	paths := []string{"etc/os-release", "usr/lib/os-release"}
    30  
    31  	for _, p := range paths {
    32  		f, err := fs.Open(p)
    33  		if err != nil {
    34  			if os.IsNotExist(err) {
    35  				continue
    36  			}
    37  			return nil, err
    38  		}
    39  		defer f.Close()
    40  		return parse(f), nil
    41  	}
    42  
    43  	return nil, os.ErrNotExist
    44  }
    45  
    46  // parse the os-release(5) file.
    47  func parse(r io.Reader) map[string]string {
    48  	s := bufio.NewScanner(r)
    49  
    50  	m := map[string]string{}
    51  	for s.Scan() {
    52  		line := strings.TrimSpace(s.Text())
    53  
    54  		if !strings.Contains(line, "=") || strings.HasPrefix(line, "#") {
    55  			continue
    56  		}
    57  
    58  		kv := strings.SplitN(line, "=", 2)
    59  		m[kv[0]] = resolveString(kv[1])
    60  	}
    61  	return m
    62  }
    63  
    64  // resolveString parses the right side of an environment-like shell-compatible variable assignment.
    65  // Currently it just removes double quotes. See `man os-release 5` for more details.
    66  func resolveString(s string) string {
    67  	if strings.HasPrefix(s, "\"") && strings.HasSuffix(s, "\"") {
    68  		s = s[1 : len(s)-1]
    69  	}
    70  	return s
    71  }