github.com/ratrocket/u-root@v0.0.0-20180201221235-1cf9f48ee2cf/cmds/losetup/losetup.go (about)

     1  // Copyright 2012-2017 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  // Setup loop devices.
     6  //
     7  // Synopsis:
     8  //     losetup [-Ad] FILE
     9  //     losetup [-Ad] DEV FILE
    10  //
    11  // Options:
    12  //     -A: pick any device
    13  //     -d: detach the device
    14  package main
    15  
    16  import (
    17  	"flag"
    18  	"fmt"
    19  	"log"
    20  	"os"
    21  	"syscall"
    22  )
    23  
    24  const (
    25  	/*
    26  	 * IOCTL commands --- we will commandeer 0x4C ('L')
    27  	 */
    28  	LOOP_SET_CAPACITY = 0x4C07
    29  	LOOP_CHANGE_FD    = 0x4C06
    30  	LOOP_GET_STATUS64 = 0x4C05
    31  	LOOP_SET_STATUS64 = 0x4C04
    32  	LOOP_GET_STATUS   = 0x4C03
    33  	LOOP_SET_STATUS   = 0x4C02
    34  	LOOP_CLR_FD       = 0x4C01
    35  	LOOP_SET_FD       = 0x4C00
    36  	LO_NAME_SIZE      = 64
    37  	LO_KEY_SIZE       = 32
    38  	/* /dev/loop-control interface */
    39  	LOOP_CTL_ADD      = 0x4C80
    40  	LOOP_CTL_REMOVE   = 0x4C81
    41  	LOOP_CTL_GET_FREE = 0x4C82
    42  	SYS_ioctl         = 16
    43  )
    44  
    45  var (
    46  	anyLoop = flag.Bool("A", true, "Pick any device")
    47  	detach  = flag.Bool("d", false, "Detach the device")
    48  	l       = log.New(os.Stdout, "tcz: ", 0)
    49  )
    50  
    51  // consider making this a goroutine which pushes the string down the channel.
    52  func findloop() (name string, err error) {
    53  	cfd, err := syscall.Open("/dev/loop-control", syscall.O_RDWR, 0)
    54  	if err != nil {
    55  		log.Fatalf("/dev/loop-control: %v", err)
    56  	}
    57  	defer syscall.Close(cfd)
    58  	a, b, errno := syscall.Syscall(SYS_ioctl, uintptr(cfd), LOOP_CTL_GET_FREE, 0)
    59  	if errno != 0 {
    60  		log.Fatalf("ioctl: %v\n", err)
    61  	}
    62  	log.Printf("a %v b %v err %v\n", a, b, err)
    63  	name = fmt.Sprintf("/dev/loop%d", a)
    64  	return name, nil
    65  }
    66  
    67  func main() {
    68  	flag.Parse()
    69  	args := flag.Args()
    70  	if *detach {
    71  		l.Fatalf("detach: not yet")
    72  		os.Exit(1)
    73  	}
    74  	var file, dev string
    75  	var err error
    76  	if len(args) == 1 {
    77  		dev, err = findloop()
    78  		if err != nil {
    79  			l.Fatalf("can't find a loop: %v\n", err)
    80  			os.Exit(1)
    81  		}
    82  		file = args[0]
    83  	} else if len(args) == 2 {
    84  		dev = args[0]
    85  		file = args[1]
    86  	} else {
    87  		l.Fatalf("usage\n")
    88  		os.Exit(1)
    89  	}
    90  
    91  	ffd, err := syscall.Open(file, syscall.O_RDONLY, 0)
    92  	if err != nil {
    93  		l.Fatalf("file: %v, %v\n", file, err)
    94  	}
    95  	lfd, err := syscall.Open(dev, syscall.O_RDONLY, 0)
    96  	if err != nil {
    97  		l.Fatalf("dev: %v, %v\n", dev, err)
    98  	}
    99  	l.Printf("ffd %v lfd %v\n", ffd, lfd)
   100  	a, b, errno := syscall.Syscall(SYS_ioctl, uintptr(lfd), LOOP_SET_FD, uintptr(ffd))
   101  	if errno != 0 {
   102  		l.Fatalf("loop set fd ioctl: %v, %v, %v\n", a, b, errno)
   103  	}
   104  }