github.com/oweisse/u-root@v0.0.0-20181109060735-d005ad25fef1/pkg/loop/losetup_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 6 7 import ( 8 "fmt" 9 "os" 10 "syscall" 11 ) 12 13 const ( 14 /* 15 * IOCTL commands --- we will commandeer 0x4C ('L') 16 */ 17 LOOP_SET_CAPACITY = 0x4C07 18 LOOP_CHANGE_FD = 0x4C06 19 LOOP_GET_STATUS64 = 0x4C05 20 LOOP_SET_STATUS64 = 0x4C04 21 LOOP_GET_STATUS = 0x4C03 22 LOOP_SET_STATUS = 0x4C02 23 LOOP_CLR_FD = 0x4C01 24 LOOP_SET_FD = 0x4C00 25 LO_NAME_SIZE = 64 26 LO_KEY_SIZE = 32 27 /* /dev/loop-control interface */ 28 LOOP_CTL_ADD = 0x4C80 29 LOOP_CTL_REMOVE = 0x4C81 30 LOOP_CTL_GET_FREE = 0x4C82 31 ) 32 33 // FindDevice finds an unused loop device. 34 func FindDevice() (name string, err error) { 35 cfd, err := os.OpenFile("/dev/loop-control", os.O_RDWR, 0644) 36 if err != nil { 37 return "", err 38 } 39 defer cfd.Close() 40 41 number, err := CtlGetFree(cfd.Fd()) 42 if err != nil { 43 return "", err 44 } 45 return fmt.Sprintf("/dev/loop%d", number), nil 46 } 47 48 // ClearFd clears the loop device associated with filedescriptor fd. 49 func ClearFd(fd uintptr) error { 50 if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, fd, LOOP_CLR_FD, 0); err != 0 { 51 return err 52 } 53 54 return nil 55 } 56 57 // CtlGetFree finds a free loop device querying the loop control device pointed 58 // by fd. It returns the number of the free loop device /dev/loopX 59 func CtlGetFree(fd uintptr) (uintptr, error) { 60 number, _, err := syscall.Syscall(syscall.SYS_IOCTL, fd, LOOP_CTL_GET_FREE, 0) 61 if err != 0 { 62 return 0, err 63 } 64 return number, nil 65 } 66 67 // SetFd associates a loop device pointed by lfd with a regular file pointed by ffd. 68 func SetFd(lfd, ffd uintptr) error { 69 _, _, err := syscall.Syscall(syscall.SYS_IOCTL, lfd, LOOP_SET_FD, ffd) 70 if err != 0 { 71 return err 72 } 73 74 return nil 75 } 76 77 // SetFdFiles associates loop device "devicename" with regular file "filename" 78 func SetFdFiles(devicename, filename string) error { 79 mode := os.O_RDWR 80 file, err := os.OpenFile(filename, mode, 0644) 81 if err != nil { 82 mode = os.O_RDONLY 83 file, err = os.OpenFile(filename, mode, 0644) 84 if err != nil { 85 return err 86 } 87 } 88 defer file.Close() 89 90 device, err := os.OpenFile(devicename, mode, 0644) 91 if err != nil { 92 return err 93 } 94 defer device.Close() 95 96 return SetFd(device.Fd(), file.Fd()) 97 } 98 99 // ClearFdFile clears the loop device "devicename" 100 func ClearFdFile(devicename string) error { 101 device, err := os.Open(devicename) 102 if err != nil { 103 return err 104 } 105 defer device.Close() 106 107 return ClearFd(device.Fd()) 108 }