Skip to content

Commit

Permalink
Use stat_t.st_rdev to compare block devices
Browse files Browse the repository at this point in the history
I implemented /dev/disk/by-uuid on my platform but using absolute links (where
udev typically uses relative) which broke the code in `os.DeviceUUID`.

Rather than just patch that up directly instead stat both the target and
candidate devices and pick one with matching major:minor in st_rdev. This saves
manually building paths to resolve symlinks and I think should be more robust
overall.

I also removed the initial stat of /dev/disk/by-uuid, I believe
`ioutil.Readdir` will correctly return an error if the path does not exist.

Signed-off-by: Ian Campbell <ijc@docker.com>
  • Loading branch information
ijc committed Sep 27, 2017
1 parent 0e6e593 commit 11714fb
Showing 1 changed file with 23 additions and 9 deletions.
32 changes: 23 additions & 9 deletions pkg/os/os.go
Expand Up @@ -22,6 +22,7 @@ import (
"io/ioutil"
"os"
"path/filepath"
"syscall"

containerdmount "github.com/containerd/containerd/mount"
"github.com/containerd/fifo"
Expand Down Expand Up @@ -130,28 +131,41 @@ func (RealOS) LookupMount(path string) (containerdmount.Info, error) {
return containerdmount.Lookup(path)
}

// blkdev returns the rdev of a block device or an error if not a block device
func blkrdev(device string) (uint64, error) {
info, err := os.Stat(device)
if err != nil {
return 0, err
}
stat := info.Sys().(*syscall.Stat_t)
if (stat.Mode & syscall.S_IFMT) != syscall.S_IFBLK {
return 0, fmt.Errorf("%s is not a block device", device)
}
return stat.Rdev, nil
}

// DeviceUUID gets device uuid of a device. The passed in device should be
// an absolute path of the device.
func (RealOS) DeviceUUID(device string) (string, error) {
const uuidDir = "/dev/disk/by-uuid"
if _, err := os.Stat(uuidDir); err != nil {
rdev, err := blkrdev(device)
if err != nil {
return "", err
}

const uuidDir = "/dev/disk/by-uuid"
files, err := ioutil.ReadDir(uuidDir)
if err != nil {
return "", err
}
for _, file := range files {
path := filepath.Join(uuidDir, file.Name())
target, err := os.Readlink(path)
if err != nil {
return "", err
}
dev, err := filepath.Abs(filepath.Join(uuidDir, target))

trdev, err := blkrdev(path)
if err != nil {
return "", err
continue
}
if dev == device {

if rdev == trdev {
return file.Name(), nil
}
}
Expand Down

0 comments on commit 11714fb

Please sign in to comment.