<commit_before>// Copyright 2017-2020 the u-root Authors. All rights reserved
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package block finds, mounts, and modifies block devices on Linux systems.
package block

import (
	"bufio"
	"encoding/binary"
	"errors"
	"fmt"
	"io"
	"log"
	"os"
	"path/filepath"
	"strconv"
	"strings"
	"unicode"
	"unsafe"

	"github.com/rekby/gpt"
	"github.com/u-root/u-root/pkg/mount"
	"github.com/u-root/u-root/pkg/pci"
	"golang.org/x/sys/unix"
)

var (
	// LinuxMountsPath is the standard mountpoint list path
	LinuxMountsPath = "/proc/mounts"

	// Debug function to override for verbose logging.
	Debug = func(string, ...interface{}) {}

	// SystemPartitionGUID is the GUID of EFI system partitions
	// EFI System partitions have GUID C12A7328-F81F-11D2-BA4B-00A0C93EC93B
	SystemPartitionGUID = gpt.Guid([...]byte{
		0x28, 0x73, 0x2a, 0xc1,
		0x1f, 0xf8,
		0xd2, 0x11,
		0xba, 0x4b,
		0x00, 0xa0, 0xc9, 0x3e, 0xc9, 0x3b,
	})
)

// BlockDev maps a device name to a BlockStat structure for a given block device
type BlockDev struct {
	Name   string
	FSType string
	FsUUID string
}

// Device makes sure the block device exists and returns a handle to it.
//
// maybeDevpath can be path like /dev/sda1, /sys/class/block/sda1 or just sda1.
// We will just use the last component.
func Device(maybeDevpath string) (*BlockDev, error) {
	devname := filepath.Base(maybeDevpath)
	if _, err := os.Stat(filepath.Join("/sys/class/block", devname)); err != nil {
		return nil, err
	}

	devpath := filepath.Join("/dev/", devname)
	if uuid, err := getFSUUID(devpath); err == nil {
		return &BlockDev{Name: devname, FsUUID: uuid}, nil
	}
	return &BlockDev{Name: devname}, nil
}

// String implements fmt.Stringer.
func (b *BlockDev) String() string {
	if len(b.FSType) > 0 {
		return fmt.Sprintf("BlockDevice(name=%s, fs_type=%s, fs_uuid=%s)", b.Name, b.FSType, b.FsUUID)
	}
	return fmt.Sprintf("BlockDevice(name=%s, fs_uuid=%s)", b.Name, b.FsUUID)
}

// DevicePath is the path to the actual device.
func (b BlockDev) DevicePath() string {
	return filepath.Join("/dev/", b.Name)
}

// Name implements mount.Mounter.
func (b *BlockDev) DevName() string {
	return b.Name
}

// Mount implements mount.Mounter.
func (b *BlockDev) Mount(path string, flags uintptr) (*mount.MountPoint, error) {
	devpath := filepath.Join("/dev", b.Name)
	if len(b.FSType) > 0 {
		return mount.Mount(devpath, path, b.FSType, "", flags)
	}

	return mount.TryMount(devpath, path, "", flags)
}

// GPTTable tries to read a GPT table from the block device described by the
// passed BlockDev object, and returns a gpt.Table object, or an error if any
func (b *BlockDev) GPTTable() (*gpt.Table, error) {
	fd, err := os.Open(b.DevicePath())
	if err != nil {
		return nil, err
	}
	defer fd.Close()

	blkSize, err := b.BlockSize()
	if err != nil {
		blkSize = 512
	}

	if _, err := fd.Seek(int64(blkSize), io.SeekStart); err != nil {
		return nil, err
	}
	table, err := gpt.ReadTable(fd, uint64(blkSize))
	if err != nil {
		return nil, err
	}
	return &table, nil
}

// PhysicalBlockSize returns the physical block size.
func (b *BlockDev) PhysicalBlockSize() (int, error) {
	f, err := os.Open(b.DevicePath())
	if err != nil {
		return 0, err<commit_msg>pkg/mount/block: Add opts parameter to function Mount by following commit 686c9d2<commit_after>// Copyright 2017-2020 the u-root Authors. All rights reserved
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package block finds, mounts, and modifies block devices on Linux systems.
package block

import (
	"bufio"
	"encoding/binary"
	"errors"
	"fmt"
	"io"
	"log"
	"os"
	"path/filepath"
	"strconv"
	"strings"
	"unicode"
	"unsafe"

	"github.com/rekby/gpt"
	"github.com/u-root/u-root/pkg/mount"
	"github.com/u-root/u-root/pkg/pci"
	"golang.org/x/sys/unix"
)

var (
	// LinuxMountsPath is the standard mountpoint list path
	LinuxMountsPath = "/proc/mounts"

	// Debug function to override for verbose logging.
	Debug = func(string, ...interface{}) {}

	// SystemPartitionGUID is the GUID of EFI system partitions
	// EFI System partitions have GUID C12A7328-F81F-11D2-BA4B-00A0C93EC93B
	SystemPartitionGUID = gpt.Guid([...]byte{
		0x28, 0x73, 0x2a, 0xc1,
		0x1f, 0xf8,
		0xd2, 0x11,
		0xba, 0x4b,
		0x00, 0xa0, 0xc9, 0x3e, 0xc9, 0x3b,
	})
)

// BlockDev maps a device name to a BlockStat structure for a given block device
type BlockDev struct {
	Name   string
	FSType string
	FsUUID string
}

// Device makes sure the block device exists and returns a handle to it.
//
// maybeDevpath can be path like /dev/sda1, /sys/class/block/sda1 or just sda1.
// We will just use the last component.
func Device(maybeDevpath string) (*BlockDev, error) {
	devname := filepath.Base(maybeDevpath)
	if _, err := os.Stat(filepath.Join("/sys/class/block", devname)); err != nil {
		return nil, err
	}

	devpath := filepath.Join("/dev/", devname)
	if uuid, err := getFSUUID(devpath); err == nil {
		return &BlockDev{Name: devname, FsUUID: uuid}, nil
	}
	return &BlockDev{Name: devname}, nil
}

// String implements fmt.Stringer.
func (b *BlockDev) String() string {
	if len(b.FSType) > 0 {
		return fmt.Sprintf("BlockDevice(name=%s, fs_type=%s, fs_uuid=%s)", b.Name, b.FSType, b.FsUUID)
	}
	return fmt.Sprintf("BlockDevice(name=%s, fs_uuid=%s)", b.Name, b.FsUUID)
}

// DevicePath is the path to the actual device.
func (b BlockDev) DevicePath() string {
	return filepath.Join("/dev/", b.Name)
}

// Name implements mount.Mounter.
func (b *BlockDev) DevName() string {
	return b.Name
}

// Mount implements mount.Mounter.
func (b *BlockDev) Mount(path string, flags uintptr, opts ...func() error) (*mount.MountPoint, error) {
	devpath := filepath.Join("/dev", b.Name)
	if len(b.FSType) > 0 {
		return mount.Mount(devpath, path, b.FSType, "", flags, opts...)
	}

	return mount.TryMount(devpath, path, "", flags, opts...)
}

// GPTTable tries to read a GPT table from the block device described by the
// passed BlockDev object, and returns a gpt.Table object, or an error if any
func (b *BlockDev) GPTTable() (*gpt.Table, error) {
	fd, err := os.Open(b.DevicePath())
	if err != nil {
		return nil, err
	}
	defer fd.Close()

	blkSize, err := b.BlockSize()
	if err != nil {
		blkSize = 512
	}

	if _, err := fd.Seek(int64(blkSize), io.SeekStart); err != nil {
		return nil, err
	}
	table, err := gpt.ReadTable(fd, uint64(blkSize))
	if err != nil {
		return nil, err
	}
	return &table, nil
}

// PhysicalBlockSize returns the physical block size.
func (b *BlockDev) PhysicalBlockSize() (int, error) {
	f, err := os.Open(b.DevicePath())
	if err != nil {
		return 0, err
{'fraction_non_alphanumeric': 0.14023297491039427, 'fraction_numerical': 0.023148148148148147, 'mean_word_length': 3.6996491228070174, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6026625', 'n_tokens_mistral': 2601, 'n_tokens_neox': 2468, 'n_words': 752}