github.com/victortrac/packer@v0.7.6-0.20160602180447-63c7fdb6e41f/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 "strings" 15 ) 16 17 // StepCreateFloppy will create a floppy disk with the given files. 18 // The floppy disk doesn't support sub-directories. Only files at the 19 // root level are supported. 20 type StepCreateFloppy struct { 21 Files []string 22 23 floppyPath string 24 25 FilesAdded map[string]bool 26 } 27 28 func (s *StepCreateFloppy) Run(state multistep.StateBag) multistep.StepAction { 29 if len(s.Files) == 0 { 30 log.Println("No floppy files specified. Floppy disk will not be made.") 31 return multistep.ActionContinue 32 } 33 34 s.FilesAdded = make(map[string]bool) 35 36 ui := state.Get("ui").(packer.Ui) 37 ui.Say("Creating floppy disk...") 38 39 // Create a temporary file to be our floppy drive 40 floppyF, err := ioutil.TempFile("", "packer") 41 if err != nil { 42 state.Put("error", 43 fmt.Errorf("Error creating temporary file for floppy: %s", err)) 44 return multistep.ActionHalt 45 } 46 defer floppyF.Close() 47 48 // Set the path so we can remove it later 49 s.floppyPath = floppyF.Name() 50 51 log.Printf("Floppy path: %s", s.floppyPath) 52 53 // Set the size of the file to be a floppy sized 54 if err := floppyF.Truncate(1440 * 1024); err != nil { 55 state.Put("error", fmt.Errorf("Error creating floppy: %s", err)) 56 return multistep.ActionHalt 57 } 58 59 // BlockDevice backed by the file for our filesystem 60 log.Println("Initializing block device backed by temporary file") 61 device, err := fs.NewFileDisk(floppyF) 62 if err != nil { 63 state.Put("error", fmt.Errorf("Error creating floppy: %s", err)) 64 return multistep.ActionHalt 65 } 66 67 // Format the block device so it contains a valid FAT filesystem 68 log.Println("Formatting the block device with a FAT filesystem...") 69 formatConfig := &fat.SuperFloppyConfig{ 70 FATType: fat.FAT12, 71 Label: "packer", 72 OEMName: "packer", 73 } 74 if err := fat.FormatSuperFloppy(device, formatConfig); err != nil { 75 state.Put("error", fmt.Errorf("Error creating floppy: %s", err)) 76 return multistep.ActionHalt 77 } 78 79 // The actual FAT filesystem 80 log.Println("Initializing FAT filesystem on block device") 81 fatFs, err := fat.New(device) 82 if err != nil { 83 state.Put("error", fmt.Errorf("Error creating floppy: %s", err)) 84 return multistep.ActionHalt 85 } 86 87 // Get the root directory to the filesystem 88 log.Println("Reading the root directory from the filesystem") 89 rootDir, err := fatFs.RootDir() 90 if err != nil { 91 state.Put("error", fmt.Errorf("Error creating floppy: %s", err)) 92 return multistep.ActionHalt 93 } 94 95 // Go over each file and copy it. 96 for _, filename := range s.Files { 97 ui.Message(fmt.Sprintf("Copying: %s", filename)) 98 if err := s.addFilespec(rootDir, filename); err != nil { 99 state.Put("error", fmt.Errorf("Error adding file to floppy: %s", err)) 100 return multistep.ActionHalt 101 } 102 } 103 104 // Set the path to the floppy so it can be used later 105 state.Put("floppy_path", s.floppyPath) 106 107 return multistep.ActionContinue 108 } 109 110 func (s *StepCreateFloppy) Cleanup(multistep.StateBag) { 111 if s.floppyPath != "" { 112 log.Printf("Deleting floppy disk: %s", s.floppyPath) 113 os.Remove(s.floppyPath) 114 } 115 } 116 117 func (s *StepCreateFloppy) addFilespec(dir fs.Directory, src string) error { 118 // same as http://golang.org/src/pkg/path/filepath/match.go#L308 119 if strings.IndexAny(src, "*?[") >= 0 { 120 matches, err := filepath.Glob(src) 121 if err != nil { 122 return err 123 } 124 return s.addFiles(dir, matches) 125 } 126 127 finfo, err := os.Stat(src) 128 if err != nil { 129 return err 130 } 131 132 if finfo.IsDir() { 133 return s.addDirectory(dir, src) 134 } 135 136 return s.addSingleFile(dir, src) 137 } 138 139 func (s *StepCreateFloppy) addFiles(dir fs.Directory, files []string) error { 140 for _, file := range files { 141 err := s.addFilespec(dir, file) 142 if err != nil { 143 return err 144 } 145 } 146 147 return nil 148 } 149 150 func (s *StepCreateFloppy) addDirectory(dir fs.Directory, src string) error { 151 log.Printf("Adding directory to floppy: %s", src) 152 153 walkFn := func(path string, finfo os.FileInfo, err error) error { 154 if err != nil { 155 return err 156 } 157 158 if path == src { 159 return nil 160 } 161 162 if finfo.IsDir() { 163 return s.addDirectory(dir, path) 164 } 165 166 return s.addSingleFile(dir, path) 167 } 168 169 return filepath.Walk(src, walkFn) 170 } 171 172 func (s *StepCreateFloppy) addSingleFile(dir fs.Directory, src string) error { 173 log.Printf("Adding file to floppy: %s", src) 174 175 inputF, err := os.Open(src) 176 if err != nil { 177 return err 178 } 179 defer inputF.Close() 180 181 entry, err := dir.AddFile(filepath.Base(src)) 182 if err != nil { 183 return err 184 } 185 186 fatFile, err := entry.File() 187 if err != nil { 188 return err 189 } 190 191 if _, err := io.Copy(fatFile, inputF); err != nil { 192 return err 193 } 194 195 s.FilesAdded[src] = true 196 197 return nil 198 }