Skip to content

Commit

Permalink
Merge pull request #63 from blp1526/os_release
Browse files Browse the repository at this point in the history
Add os_release
  • Loading branch information
blp1526 authored Dec 8, 2019
2 parents dc2d107 + 737073e commit 6b3a5ac
Show file tree
Hide file tree
Showing 3 changed files with 163 additions and 67 deletions.
117 changes: 81 additions & 36 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,62 +16,107 @@ $ tar zxvf blkinfo_linux_x86_64.tar.gz

## Usage

### As A CLI

```
$ blkinfo /dev/vda
$ blkinfo /dev/vda3
```

```json
{
"major_minor": "252:0",
"path": "/dev/vda",
"real_path": "/dev/vda",
"parent_path": "",
"child_paths": [
"/dev/vda1"
],
"sys_path": "/sys/devices/pci0000:00/0000:00:08.0/virtio2/block/vda",
"path": "/dev/vda3",
"resolved_path": "/dev/vda3",
"parent_path": "/dev/vda",
"child_paths": [],
"sys_path": "/sys/block/vda/vda3",
"resolved_sys_path": "/sys/devices/pci0000:00/0000:00:05.0/virtio2/block/vda/vda3",
"sys": {
"uevent": [
"MAJOR=252",
"MINOR=0",
"DEVNAME=vda",
"DEVTYPE=disk"
"MINOR=3",
"DEVNAME=vda3",
"DEVTYPE=partition",
"PARTN=3"
],
"slaves": [],
"holders": []
},
"udev_data_path": "/run/udev/data/b252:0",
"major_minor": "252:3",
"udev_data_path": "/run/udev/data/b252:3",
"udev_data": [
"S:disk/by-path/virtio-pci-0000:00:08.0",
"S:disk/by-path/pci-0000:00:08.0",
"W:3",
"I:2430960",
"E:ID_PATH=pci-0000:00:08.0",
"E:ID_PATH_TAG=pci-0000_00_08_0",
"E:ID_PART_TABLE_UUID=xxxxxxxx",
"E:ID_PART_TABLE_TYPE=dos",
"E:ID_FS_TYPE=",
"S:disk/by-uuid/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"S:disk/by-partuuid/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"S:disk/by-path/virtio-pci-0000:00:05.0-part3",
"S:disk/by-path/pci-0000:00:05.0-part3",
"W:4",
"I:1583813",
"E:ID_SCSI=1",
"E:ID_PART_TABLE_TYPE=gpt",
"E:ID_PART_TABLE_UUID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"E:ID_PATH=pci-0000:00:05.0",
"E:ID_PATH_TAG=pci-0000_00_05_0",
"E:ID_FS_UUID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"E:ID_FS_UUID_ENC=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"E:ID_FS_VERSION=1.0",
"E:ID_FS_TYPE=ext4",
"E:ID_FS_USAGE=filesystem",
"E:ID_PART_ENTRY_SCHEME=gpt",
"E:ID_PART_ENTRY_UUID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"E:ID_PART_ENTRY_TYPE=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"E:ID_PART_ENTRY_NUMBER=3",
"E:ID_PART_ENTRY_OFFSET=8392704",
"E:ID_PART_ENTRY_SIZE=33548288",
"E:ID_PART_ENTRY_DISK=252:0",
"E:net.ifnames=0",
"G:systemd"
],
"mount_info_path": "/proc/self/mountinfo",
"mount_info": {
"mount_id": "",
"parent_id": "",
"major_minor": "",
"root": "",
"mount_point": "",
"mount_options": [],
"optional_fields": [],
"filesystem_type": "",
"mount_source": "",
"super_options": []
"mount_id": "28",
"parent_id": "0",
"major_minor": "252:3",
"root": "/",
"mount_point": "/",
"mount_options": [
"rw",
"relatime"
],
"optional_fields": [
"shared:1"
],
"filesystem_type": "ext4",
"mount_source": "/dev/vda3",
"super_options": [
"rw",
"errors=remount-ro",
"data=ordered"
]
},
"os_release_path": "/etc/os-release",
"os_release": {
"BUG_REPORT_URL": "https://bugs.launchpad.net/ubuntu/",
"HOME_URL": "https://www.ubuntu.com/",
"ID": "ubuntu",
"ID_LIKE": "debian",
"NAME": "Ubuntu",
"PRETTY_NAME": "Ubuntu 18.04.3 LTS",
"PRIVACY_POLICY_URL": "https://www.ubuntu.com/legal/terms-and-policies/privacy-policy",
"SUPPORT_URL": "https://help.ubuntu.com/",
"UBUNTU_CODENAME": "bionic",
"VERSION": "18.04.3 LTS (Bionic Beaver)",
"VERSION_CODENAME": "bionic",
"VERSION_ID": "18.04"
}
}
```

### As A Package
### Options

|Option|Description|
|---|---|
|--help, -h|show help|
|--output value, -o value|output as "json" or "yaml" (default: "json")|
|--version, -v|print the version|

## Package

```go
package main
Expand All @@ -84,7 +129,7 @@ import (
)

func main() {
bi, _ := blkinfo.New("/dev/vda")
bi, _ := blkinfo.New("/dev/vda3")
b, _ := json.Marshal(bi)
fmt.Println(string(b))
}
Expand Down
109 changes: 80 additions & 29 deletions blkinfo.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
package blkinfo

import (
"errors"
"fmt"
"io/ioutil"
"os"
"path/filepath"
Expand All @@ -11,17 +11,20 @@ import (

// BlkInfo shows block device information.
type BlkInfo struct {
Path string `json:"path" `
RealPath string `json:"real_path" `
ParentPath string `json:"parent_path" `
ChildPaths []string `json:"child_paths" `
SysPath string `json:"sys_path" `
Sys *Sys `json:"sys" `
MajorMinor string `json:"major_minor" `
UdevDataPath string `json:"udev_data_path" `
UdevData []string `json:"udev_data" `
MountInfoPath string `json:"mount_info_path"`
MountInfo *MountInfo `json:"mount_info" `
Path string `json:"path" `
ResolvedPath string `json:"resolved_path" `
ParentPath string `json:"parent_path" `
ChildPaths []string `json:"child_paths" `
SysPath string `json:"sys_path" `
ResolevedSysPath string `json:"resolved_sys_path"`
Sys *Sys `json:"sys" `
MajorMinor string `json:"major_minor" `
UdevDataPath string `json:"udev_data_path" `
UdevData []string `json:"udev_data" `
MountInfoPath string `json:"mount_info_path" `
MountInfo *MountInfo `json:"mount_info" `
OSReleasePath string `json:"os_release_path" `
OSRelease map[string]string `json:"os_release" `
}

// Sys shows sys information.
Expand Down Expand Up @@ -50,25 +53,25 @@ type MountInfo struct {
}

// New initializes *BlkInfo.
func New(path string) (*BlkInfo, error) {
func New(path string) (*BlkInfo, error) { // nolint: funlen
var err error

if path == "" {
return nil, errors.New("a path is not given")
return nil, fmt.Errorf("a path is not given")
}

bi := &BlkInfo{
Sys: &Sys{},
}

bi.Path = path
bi.RealPath, err = filepath.EvalSymlinks(bi.Path)
bi.ResolvedPath, err = filepath.EvalSymlinks(bi.Path)

if err != nil {
return nil, err
}

bi.SysPath, bi.ParentPath, bi.ChildPaths, err = relatedPaths(bi.RealPath)
bi.SysPath, bi.ResolevedSysPath, bi.ParentPath, bi.ChildPaths, err = relatedPaths(bi.ResolvedPath)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -101,7 +104,15 @@ func New(path string) (*BlkInfo, error) {
}

bi.MountInfoPath = filepath.Join("/", "proc", "self", "mountinfo")
bi.MountInfo, err = newMountInfo(bi.MountInfoPath, bi.RealPath)
bi.MountInfo, err = newMountInfo(bi.MountInfoPath, bi.ResolvedPath)

if err != nil {
return nil, err
}

bi.OSReleasePath = osReleasePath(bi.MountInfo.MountPoint)

bi.OSRelease, err = newOSRelease(bi.OSReleasePath)

if err != nil {
return nil, err
Expand Down Expand Up @@ -161,7 +172,7 @@ func ls(path string) ([]string, error) {
}

func newMountInfo(mountInfoPath string, path string) (*MountInfo, error) {
realPath, err := filepath.EvalSymlinks(path)
resolvedPath, err := filepath.EvalSymlinks(path)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -192,7 +203,7 @@ func newMountInfo(mountInfoPath string, path string) (*MountInfo, error) {
return nil, err
}

if realPath == realMountSource {
if resolvedPath == realMountSource {
mountInfo.MountID = separatedFirst[0]
mountInfo.ParentID = separatedFirst[1]
mountInfo.MajorMinor = separatedFirst[2]
Expand All @@ -211,18 +222,18 @@ func newMountInfo(mountInfoPath string, path string) (*MountInfo, error) {
return mountInfo, nil
}

func relatedPaths(path string) (sysPath string, parentPath string, childPaths []string, err error) {
realPath, err := filepath.EvalSymlinks(path)
func relatedPaths(path string) (sysPath string, resolvedSysPath string, parentPath string, childPaths []string, err error) {
resolvedPath, err := filepath.EvalSymlinks(path)
if err != nil {
return "", "", []string{}, err
return "", "", "", []string{}, err
}

devName := filepath.Base(realPath)
devName := filepath.Base(resolvedPath)
blockPath := filepath.Join("/", "sys", "block")
fileInfoList, err := ioutil.ReadDir(blockPath)

if err != nil {
return "", "", []string{}, err
return "", "", "", []string{}, err
}

for _, fileInfo := range fileInfoList {
Expand All @@ -235,7 +246,7 @@ func relatedPaths(path string) (sysPath string, parentPath string, childPaths []
fileInfoList, err = ioutil.ReadDir(sysPath)

if err != nil {
return "", "", []string{}, err
return "", "", "", []string{}, err
}

childPaths = []string{}
Expand All @@ -253,16 +264,16 @@ func relatedPaths(path string) (sysPath string, parentPath string, childPaths []
childPaths = []string{}
}

sysPath, err = filepath.EvalSymlinks(sysPath)
resolvedSysPath, err := filepath.EvalSymlinks(sysPath)
if err != nil {
return "", "", []string{}, err
return "", "", "", []string{}, err
}

return sysPath, parentPath, childPaths, nil
return sysPath, resolvedSysPath, parentPath, childPaths, nil
}
}

return "", "", []string{}, errors.New("sysPath, parentPath, and childPaths are not found")
return "", "", "", []string{}, fmt.Errorf("sysPath, parentPath, and childPaths are not found")
}

func majorMinor(sysPath string) (string, error) {
Expand All @@ -273,3 +284,43 @@ func majorMinor(sysPath string) (string, error) {

return majorMinor, nil
}

func osReleasePath(mountPoint string) (path string) {
if mountPoint != "" {
path = filepath.Join(mountPoint, "etc", "os-release")
}

return path
}

func newOSRelease(osReleasePath string) (osRelease map[string]string, err error) {
osRelease = map[string]string{}

if osReleasePath != "" {
osReleaseLines, err := lines(osReleasePath)
if err != nil {
return map[string]string{}, err
}

for _, osReleaseLine := range osReleaseLines {
line := strings.TrimSpace(osReleaseLine)
if line == "" || strings.HasPrefix(line, "#") {
continue
}

kv := strings.SplitN(osReleaseLine, "=", 2)
expectedKVSize := 2

if len(kv) != expectedKVSize {
return map[string]string{}, fmt.Errorf(`unexpected osReleaseLine, "%s"`, osReleaseLine)
}

key := kv[0]
value := kv[1]

osRelease[key] = trimQuotationMarks(value)
}
}

return osRelease, nil
}
4 changes: 2 additions & 2 deletions cmd/blkinfo/blkinfo.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ func main() { // nolint: funlen
},
}
app.HideHelp = true
allowedOutput := "[json|yaml]"
allowedOutput := `"json" or "yaml"`
app.Flags = []cli.Flag{
cli.BoolFlag{
Name: "help, h",
Expand Down Expand Up @@ -70,7 +70,7 @@ func main() { // nolint: funlen
case "yaml":
bytes, err = yaml.JSONToYAML(bytes)
default:
err = fmt.Errorf("unknown output '%s', expected %s", output, allowedOutput)
err = fmt.Errorf(`unknown output "%s", expected %s`, output, allowedOutput)
}

if err != nil {
Expand Down

0 comments on commit 6b3a5ac

Please sign in to comment.