github.com/jerryclinesmith/packer@v0.3.7/common/step_create_floppy.go (about)

     1  package common
     2  
     3  import (
     4  	"fmt"
     5  	"github.com/mitchellh/go-fs"
     6  	"github.com/mitchellh/go-fs/fat"
     7  	"github.com/mitchellh/multistep"
     8  	"github.com/mitchellh/packer/packer"
     9  	"io"
    10  	"io/ioutil"
    11  	"log"
    12  	"os"
    13  	"path/filepath"
    14  )
    15  
    16  // StepCreateFloppy will create a floppy disk with the given files.
    17  // The floppy disk doesn't support sub-directories. Only files at the
    18  // root level are supported.
    19  type StepCreateFloppy struct {
    20  	Files []string
    21  
    22  	floppyPath string
    23  }
    24  
    25  func (s *StepCreateFloppy) Run(state multistep.StateBag) multistep.StepAction {
    26  	if len(s.Files) == 0 {
    27  		log.Println("No floppy files specified. Floppy disk will not be made.")
    28  		return multistep.ActionContinue
    29  	}
    30  
    31  	ui := state.Get("ui").(packer.Ui)
    32  	ui.Say("Creating floppy disk...")
    33  
    34  	// Create a temporary file to be our floppy drive
    35  	floppyF, err := ioutil.TempFile("", "packer")
    36  	if err != nil {
    37  		state.Put("error",
    38  			fmt.Errorf("Error creating temporary file for floppy: %s", err))
    39  		return multistep.ActionHalt
    40  	}
    41  	defer floppyF.Close()
    42  
    43  	// Set the path so we can remove it later
    44  	s.floppyPath = floppyF.Name()
    45  
    46  	log.Printf("Floppy path: %s", floppyF.Name())
    47  
    48  	// Set the size of the file to be a floppy sized
    49  	if err := floppyF.Truncate(1440 * 1024); err != nil {
    50  		state.Put("error", fmt.Errorf("Error creating floppy: %s", err))
    51  		return multistep.ActionHalt
    52  	}
    53  
    54  	// BlockDevice backed by the file for our filesystem
    55  	log.Println("Initializing block device backed by temporary file")
    56  	device, err := fs.NewFileDisk(floppyF)
    57  	if err != nil {
    58  		state.Put("error", fmt.Errorf("Error creating floppy: %s", err))
    59  		return multistep.ActionHalt
    60  	}
    61  
    62  	// Format the block device so it contains a valid FAT filesystem
    63  	log.Println("Formatting the block device with a FAT filesystem...")
    64  	formatConfig := &fat.SuperFloppyConfig{
    65  		FATType: fat.FAT12,
    66  		Label:   "packer",
    67  		OEMName: "packer",
    68  	}
    69  	if fat.FormatSuperFloppy(device, formatConfig); err != nil {
    70  		state.Put("error", fmt.Errorf("Error creating floppy: %s", err))
    71  		return multistep.ActionHalt
    72  	}
    73  
    74  	// The actual FAT filesystem
    75  	log.Println("Initializing FAT filesystem on block device")
    76  	fatFs, err := fat.New(device)
    77  	if err != nil {
    78  		state.Put("error", fmt.Errorf("Error creating floppy: %s", err))
    79  		return multistep.ActionHalt
    80  	}
    81  
    82  	// Get the root directory to the filesystem
    83  	log.Println("Reading the root directory from the filesystem")
    84  	rootDir, err := fatFs.RootDir()
    85  	if err != nil {
    86  		state.Put("error", fmt.Errorf("Error creating floppy: %s", err))
    87  		return multistep.ActionHalt
    88  	}
    89  
    90  	// Go over each file and copy it.
    91  	for _, filename := range s.Files {
    92  		ui.Message(fmt.Sprintf("Copying: %s", filepath.Base(filename)))
    93  		if s.addSingleFile(rootDir, filename); err != nil {
    94  			state.Put("error", fmt.Errorf("Error adding file to floppy: %s", err))
    95  			return multistep.ActionHalt
    96  		}
    97  	}
    98  
    99  	// Set the path to the floppy so it can be used later
   100  	state.Put("floppy_path", s.floppyPath)
   101  
   102  	return multistep.ActionContinue
   103  }
   104  
   105  func (s *StepCreateFloppy) Cleanup(multistep.StateBag) {
   106  	if s.floppyPath != "" {
   107  		log.Printf("Deleting floppy disk: %s", s.floppyPath)
   108  		os.Remove(s.floppyPath)
   109  	}
   110  }
   111  
   112  func (s *StepCreateFloppy) addSingleFile(dir fs.Directory, src string) error {
   113  	log.Printf("Adding file to floppy: %s", src)
   114  
   115  	inputF, err := os.Open(src)
   116  	if err != nil {
   117  		return err
   118  	}
   119  	defer inputF.Close()
   120  
   121  	entry, err := dir.AddFile(filepath.Base(src))
   122  	if err != nil {
   123  		return err
   124  	}
   125  
   126  	fatFile, err := entry.File()
   127  	if err != nil {
   128  		return err
   129  	}
   130  
   131  	if _, err := io.Copy(fatFile, inputF); err != nil {
   132  		return err
   133  	}
   134  
   135  	return nil
   136  }