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 }