github.com/system-transparency/u-root@v6.0.1-0.20190919065413-ed07a650de4c+incompatible/pkg/loop/loop_linux.go (about) 1 // Copyright 2018 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 loop provides an interface to interacting with Linux loop devices. 6 // 7 // A loop device exposes a regular file as if it were a block device. 8 package loop 9 10 import ( 11 "github.com/u-root/u-root/pkg/mount" 12 "golang.org/x/sys/unix" 13 ) 14 15 // Loop represents a regular file exposed as a loop block device. 16 // 17 // Loop implements mount.Mounter. 18 type Loop struct { 19 // Dev is the loop device path. 20 Dev string 21 22 // Source is the regular file to use as a block device. 23 Source string 24 25 // FSType is the file system to use when mounting the block device. 26 FSType string 27 28 // Data is the data to pass to mount(2). 29 Data string 30 31 // Mounted indicates whether the device has been mounted. 32 Mounted bool 33 34 // dir is the directory the block device was mounted on. 35 dir string 36 } 37 38 // New initializes a Loop struct and allocates a loop device to it. 39 // 40 // source is the file to use as a loop block device. fstype the file system 41 // name. data is the data argument to the mount(2) syscall. 42 func New(source, fstype string, data string) (mount.Mounter, error) { 43 devicename, err := FindDevice() 44 if err != nil { 45 return nil, err 46 } 47 if err := SetFile(devicename, source); err != nil { 48 return nil, err 49 } 50 return &Loop{ 51 Dev: devicename, 52 Source: source, 53 FSType: fstype, 54 Data: data, 55 }, nil 56 } 57 58 // Mount mounts the provided source file, with type fstype, and flags and data options 59 // (which are usually 0 and ""), using the allocated loop device. 60 func (l *Loop) Mount(path string, flags uintptr) error { 61 l.dir = path 62 if err := unix.Mount(l.Dev, path, l.FSType, flags, l.Data); err != nil { 63 return err 64 } 65 l.Mounted = true 66 return nil 67 } 68 69 const forceUnmount = unix.MNT_FORCE | unix.MNT_DETACH 70 71 // Unmount unmounts and frees a loop. If it is mounted, it will try to unmount it. 72 // If the unmount fails, we try to free it anyway, after trying a more 73 // forceful unmount. 74 func (l *Loop) Unmount(flags int) error { 75 if l.Mounted { 76 if err := unix.Unmount(l.dir, flags); err != nil { 77 unix.Unmount(l.dir, flags|forceUnmount) 78 } 79 } 80 return ClearFile(l.Dev) 81 }