github.com/mvdan/u-root-coreutils@v0.0.0-20230122170626-c2eef2898555/pkg/efivarfs/fs.go (about)

     1  // Copyright 2022 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  // Package efivarfs allows interaction with efivarfs of the
     6  // linux kernel.
     7  package efivarfs
     8  
     9  import (
    10  	"os"
    11  
    12  	"golang.org/x/sys/unix"
    13  )
    14  
    15  // FS_IMMUTABLE_FL is an inode flag to make a file immutable.
    16  const FS_IMMUTABLE_FL = 0x10
    17  
    18  // getInodeFlags returns the extended attributes of a file.
    19  func getInodeFlags(f *os.File) (int, error) {
    20  	// If I knew how unix.Getxattr works I'd use that...
    21  	flags, err := unix.IoctlGetInt(int(f.Fd()), unix.FS_IOC_GETFLAGS)
    22  	if err != nil {
    23  		return 0, &os.PathError{Op: "ioctl(FS_IOC_GETFLAGS)", Path: f.Name(), Err: err}
    24  	}
    25  	return flags, nil
    26  }
    27  
    28  // setInodeFlags sets the extended attributes of a file.
    29  func setInodeFlags(f *os.File, flags int) error {
    30  	// If I knew how unix.Setxattr works I'd use that...
    31  	if err := unix.IoctlSetPointerInt(int(f.Fd()), unix.FS_IOC_SETFLAGS, flags); err != nil {
    32  		return &os.PathError{Op: "ioctl(FS_IOC_SETFLAGS)", Path: f.Name(), Err: err}
    33  	}
    34  	return nil
    35  }
    36  
    37  // makeMutable will change a files xattrs so that
    38  // the immutable flag is removed and return a restore
    39  // function which can reset the flag for that filee.
    40  func makeMutable(f *os.File) (restore func(), err error) {
    41  	flags, err := getInodeFlags(f)
    42  	if err != nil {
    43  		return nil, err
    44  	}
    45  	if flags&FS_IMMUTABLE_FL == 0 {
    46  		return func() {}, nil
    47  	}
    48  
    49  	if err := setInodeFlags(f, flags&^FS_IMMUTABLE_FL); err != nil {
    50  		return nil, err
    51  	}
    52  	return func() {
    53  		if err := setInodeFlags(f, flags); err != nil {
    54  			// If setting the immutable did
    55  			// not work it's alright to do nothing
    56  			// because after a reboot the flag is
    57  			// automatically reapplied
    58  			return
    59  		}
    60  	}, nil
    61  }