github.com/mvdan/u-root-coreutils@v0.0.0-20230122170626-c2eef2898555/pkg/uefivars/boot/efiDppResolver.go (about)

     1  // Copyright 2020 the u-root Authors. All rights reserved
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  //
     5  // SPDX-License-Identifier: BSD-3-Clause
     6  //
     7  
     8  package boot
     9  
    10  import (
    11  	"log"
    12  	"os"
    13  	fp "path/filepath"
    14  
    15  	"github.com/mvdan/u-root-coreutils/pkg/mount"
    16  	"github.com/mvdan/u-root-coreutils/pkg/mount/block"
    17  	"golang.org/x/sys/unix"
    18  )
    19  
    20  type EfiPathSegmentResolver interface {
    21  	// Returns description, does not require cleanup
    22  	String() string
    23  
    24  	// Mount fs, etc. You must call Cleanup() eventually.
    25  	Resolve(suggestedBasePath string) (string, error)
    26  
    27  	// For devices, returns BlockDev. Returns nil otherwise.
    28  	BlockInfo() *block.BlockDev
    29  
    30  	// For mounted devices, returns MountPoint. Returns nil otherwise.
    31  	MntPoint() *mount.MountPoint
    32  
    33  	// Unmount fs, free resources, etc
    34  	Cleanup() error
    35  }
    36  
    37  // HddResolver can identify and mount a partition.
    38  type HddResolver struct {
    39  	*block.BlockDev
    40  	*mount.MountPoint
    41  }
    42  
    43  var _ EfiPathSegmentResolver = (*HddResolver)(nil)
    44  
    45  func (r *HddResolver) String() string { return "/dev/" + r.BlockDev.Name }
    46  
    47  func (r *HddResolver) Resolve(basePath string) (string, error) {
    48  	if r.MountPoint != nil {
    49  		return r.MountPoint.Path, nil
    50  	}
    51  	var err error
    52  	if len(basePath) == 0 {
    53  		basePath, err = os.MkdirTemp("", "uefiPath")
    54  		if err != nil {
    55  			return "", err
    56  		}
    57  	} else {
    58  		fi, err := os.Stat(basePath)
    59  		if err != nil || !fi.IsDir() {
    60  			err = os.RemoveAll(basePath)
    61  			if err != nil {
    62  				return "", err
    63  			}
    64  			err = os.MkdirAll(basePath, 0o755)
    65  			if err != nil {
    66  				return "", err
    67  			}
    68  		}
    69  	}
    70  	r.MountPoint, err = r.BlockDev.Mount(basePath, 0)
    71  	return r.MountPoint.Path, err
    72  }
    73  
    74  func (r *HddResolver) BlockInfo() *block.BlockDev { return r.BlockDev }
    75  
    76  func (r *HddResolver) MntPoint() *mount.MountPoint { return r.MountPoint }
    77  
    78  func (r *HddResolver) Cleanup() error {
    79  	if r.MountPoint != nil {
    80  		err := r.MountPoint.Unmount(unix.UMOUNT_NOFOLLOW | unix.MNT_DETACH)
    81  		if err == nil {
    82  			r.MountPoint = nil
    83  		}
    84  		return err
    85  	}
    86  	return nil
    87  }
    88  
    89  // PathResolver outputs a file path.
    90  type PathResolver string
    91  
    92  var _ EfiPathSegmentResolver = (*PathResolver)(nil)
    93  
    94  func (r *PathResolver) String() string { return string(*r) }
    95  
    96  func (r *PathResolver) Resolve(basePath string) (string, error) {
    97  	if len(basePath) == 0 {
    98  		log.Printf("uefi.PathResolver: empty base path")
    99  	}
   100  	return fp.Join(basePath, string(*r)), nil
   101  }
   102  
   103  func (r *PathResolver) BlockInfo() *block.BlockDev { return nil }
   104  
   105  func (r *PathResolver) MntPoint() *mount.MountPoint { return nil }
   106  
   107  func (r *PathResolver) Cleanup() error { return nil }