Merge lp:~sergiusens/goget-ubuntu-touch/beBetter into lp:goget-ubuntu-touch

Proposed by Sergio Schvezov
Status: Merged
Approved by: John Lenton
Approved revision: 195
Merged at revision: 183
Proposed branch: lp:~sergiusens/goget-ubuntu-touch/beBetter
Merge into: lp:goget-ubuntu-touch
Diff against target: 833 lines (+282/-405)
5 files modified
diskimage/common.go (+232/-19)
diskimage/core_grub.go (+8/-194)
diskimage/core_uboot.go (+9/-181)
diskimage/errors.go (+32/-0)
ubuntu-device-flash/core.go (+1/-11)
To merge this branch: bzr merge lp:~sergiusens/goget-ubuntu-touch/beBetter
Reviewer Review Type Date Requested Status
John Lenton (community) Approve
Michael Vogt (community) Approve
Review via email: mp+261804@code.launchpad.net

Commit message

Remove code duplication and manage mounting/unmounting better

To post a comment you must log in.
187. By Sergio Schvezov

Revert uneeded func name change

Revision history for this message
Michael Vogt (mvo) wrote :

Woah, very nice consolidation. I have a lot of questions in the begining probably because its very hot here. Feel free to ignore, this is great and fine to land - I like how it kills duplication.

review: Approve
Revision history for this message
Sergio Schvezov (sergiusens) :
188. By Sergio Schvezov

Try to cleanly unmount on mount errors

189. By Sergio Schvezov

Message about not being able to remove basemount

190. By Sergio Schvezov

Use syscall sync

191. By Sergio Schvezov

Nicer error for unmounting

192. By Sergio Schvezov

Adding errors.go

193. By Sergio Schvezov

Mapping errors

194. By Sergio Schvezov

removing duplicate code for paths to mounts

195. By Sergio Schvezov

Cleanup moved

Revision history for this message
Michael Vogt (mvo) wrote :

Nice!

review: Approve
Revision history for this message
John Lenton (chipaca) wrote :

LGTM.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'diskimage/common.go'
2--- diskimage/common.go 2015-04-21 19:35:46 +0000
3+++ diskimage/common.go 2015-06-15 15:32:50 +0000
4@@ -8,6 +8,7 @@
5 package diskimage
6
7 import (
8+ "bufio"
9 "errors"
10 "fmt"
11 "io/ioutil"
12@@ -15,6 +16,7 @@
13 "os/exec"
14 "path/filepath"
15 "strings"
16+ "syscall"
17 )
18
19 // This program is free software: you can redistribute it and/or modify it
20@@ -37,6 +39,10 @@
21 }
22 }
23
24+var (
25+ syscallSync = syscall.Sync
26+)
27+
28 type Image interface {
29 Mount() error
30 Unmount() error
31@@ -149,40 +155,247 @@
32 return strings.TrimSpace(string(out)), err
33 }
34
35-func mount(partitions []partition) (baseMount string, err error) {
36- baseMount, err = ioutil.TempDir(os.TempDir(), "diskimage")
37+// BaseImage implements the basic primitives to manage images.
38+type BaseImage struct {
39+ baseMount string
40+ hardware HardwareDescription
41+ location string
42+ oem OemDescription
43+ parts []partition
44+ partCount int
45+ size int64
46+}
47+
48+// Mount mounts the image. This also maps the loop device.
49+func (img *BaseImage) Mount() error {
50+ if err := img.Map(); err != nil {
51+ return err
52+ }
53+
54+ baseMount, err := ioutil.TempDir(os.TempDir(), "diskimage")
55 if err != nil {
56- return "", err
57- }
58-
59- // We change the mode so snappy can unpack as non root
60- if err := os.Chmod(baseMount, 0755); err != nil {
61- return "", err
62+ return err
63 }
64
65 //Remove Mountpoint if we fail along the way
66 defer func() {
67 if err != nil {
68- os.Remove(baseMount)
69+ if err := os.Remove(baseMount); err != nil {
70+ fmt.Println("WARNING: cannot remove", baseMount, "due to", err)
71+ }
72 }
73 }()
74
75- for _, part := range partitions {
76+ // We change the mode so snappy can unpack as non root
77+ if err := os.Chmod(baseMount, 0755); err != nil {
78+ return err
79+ }
80+
81+ for _, part := range img.parts {
82 if part.fs == fsNone {
83 continue
84 }
85
86 mountpoint := filepath.Join(baseMount, string(part.dir))
87 if err := os.MkdirAll(mountpoint, 0755); err != nil {
88- return "", err
89- }
90- if out, err := exec.Command("mount", filepath.Join("/dev/mapper", part.loop), mountpoint).CombinedOutput(); err != nil {
91- return "", fmt.Errorf("unable to mount dir to create system image: %s", out)
92- }
93- }
94-
95- return baseMount, nil
96-
97+ return err
98+ }
99+
100+ dev := filepath.Join("/dev/mapper", part.loop)
101+ printOut("Mounting", dev, part.fs, "to", mountpoint)
102+ if out, errMount := exec.Command("mount", filepath.Join("/dev/mapper", part.loop), mountpoint).CombinedOutput(); errMount != nil {
103+ return ErrMount{dev: dev, mountpoint: mountpoint, fs: part.fs, out: out}
104+ }
105+ // this is cleanup in case one of the mounts fail
106+ defer func() {
107+ if err != nil {
108+ if err := exec.Command("umount", mountpoint).Run(); err != nil {
109+ fmt.Println("WARNING:", mountpoint, "could not be unmounted")
110+ return
111+ }
112+
113+ if err := os.Remove(mountpoint); err != nil {
114+ fmt.Println("WARNING: could not remove ", mountpoint)
115+ }
116+ }
117+ }()
118+ }
119+ img.baseMount = baseMount
120+
121+ return nil
122+
123+}
124+
125+// Unmount unmounts the image. This also unmaps the loop device.
126+func (img *BaseImage) Unmount() error {
127+ if img.baseMount == "" {
128+ panic("No base mountpoint set")
129+ }
130+
131+ syscallSync()
132+
133+ for _, part := range img.parts {
134+ if part.fs == fsNone {
135+ continue
136+ }
137+
138+ mountpoint := filepath.Join(img.baseMount, string(part.dir))
139+ if out, err := exec.Command("umount", mountpoint).CombinedOutput(); err != nil {
140+ lsof, _ := exec.Command("lsof", "-w", mountpoint).CombinedOutput()
141+ printOut(string(lsof))
142+ dev := filepath.Join("/dev/mapper", part.loop)
143+ return ErrMount{dev: dev, mountpoint: mountpoint, fs: part.fs, out: out}
144+ }
145+ }
146+
147+ if err := os.RemoveAll(img.baseMount); err != nil {
148+ return err
149+ }
150+ img.baseMount = ""
151+
152+ return img.Unmap()
153+}
154+
155+// Map maps the image to loop devices
156+func (img *BaseImage) Map() error {
157+ if isMapped(img.parts) {
158+ panic("cannot double map partitions")
159+ }
160+
161+ kpartxCmd := exec.Command("kpartx", "-avs", img.location)
162+ stdout, err := kpartxCmd.StdoutPipe()
163+ if err != nil {
164+ return err
165+ }
166+
167+ if err := kpartxCmd.Start(); err != nil {
168+ return err
169+ }
170+
171+ loops := make([]string, 0, img.partCount)
172+ scanner := bufio.NewScanner(stdout)
173+ for scanner.Scan() {
174+ fields := strings.Fields(scanner.Text())
175+
176+ if len(fields) > 2 {
177+ loops = append(loops, fields[2])
178+ } else {
179+ return fmt.Errorf("issues while determining drive mappings (%q)", fields)
180+ }
181+ }
182+ if err := scanner.Err(); err != nil {
183+ return err
184+ }
185+
186+ if len(loops) != img.partCount {
187+ return ErrMapCount{expectedParts: img.partCount, foundParts: len(loops)}
188+ }
189+
190+ mapPartitions(img.parts, loops)
191+
192+ if err := kpartxCmd.Wait(); err != nil {
193+ return err
194+ }
195+
196+ return nil
197+}
198+
199+//Unmap destroys loop devices for the partitions
200+func (img *BaseImage) Unmap() error {
201+ if img.baseMount != "" {
202+ panic("cannot unmap mounted partitions")
203+ }
204+
205+ for _, part := range img.parts {
206+ if err := exec.Command("dmsetup", "clear", part.loop).Run(); err != nil {
207+ return err
208+ }
209+ }
210+
211+ if err := exec.Command("kpartx", "-ds", img.location).Run(); err != nil {
212+ return err
213+ }
214+
215+ unmapPartitions(img.parts)
216+
217+ return nil
218+}
219+
220+// Format formats the image following the partition types and labels them
221+// accordingly.
222+func (img BaseImage) Format() error {
223+ for _, part := range img.parts {
224+ dev := filepath.Join("/dev/mapper", part.loop)
225+
226+ if part.fs == fsFat32 {
227+ cmd := []string{"-F", "32", "-n", string(part.label)}
228+
229+ size, err := sectorSize(dev)
230+ if err != nil {
231+ return err
232+ }
233+
234+ if size != "512" {
235+ cmd = append(cmd, "-s", "1")
236+ }
237+
238+ cmd = append(cmd, "-S", size, dev)
239+
240+ if out, err := exec.Command("mkfs.vfat", cmd...).CombinedOutput(); err != nil {
241+ return fmt.Errorf("unable to create filesystem: %s", out)
242+ }
243+ } else {
244+ if out, err := exec.Command("mkfs.ext4", "-F", "-L", string(part.label), dev).CombinedOutput(); err != nil {
245+ return fmt.Errorf("unable to create filesystem: %s", out)
246+ }
247+ }
248+ }
249+
250+ return nil
251+}
252+
253+// User returns the writable path
254+func (img BaseImage) Writable() string {
255+ if img.parts == nil {
256+ panic("img is not setup with partitions")
257+ }
258+
259+ if img.baseMount == "" {
260+ panic("img not mounted")
261+ }
262+
263+ return filepath.Join(img.baseMount, string(writableDir))
264+}
265+
266+func (img BaseImage) pathToMount(dir directory) string {
267+ if img.parts == nil {
268+ panic("img is not setup with partitions")
269+ }
270+
271+ if img.baseMount == "" {
272+ panic("img not mounted")
273+ }
274+
275+ return filepath.Join(img.baseMount, string(dir))
276+}
277+
278+//System returns the system path
279+func (img BaseImage) System() string {
280+ return img.pathToMount(systemADir)
281+}
282+
283+// Boot returns the system-boot path
284+func (img BaseImage) Boot() string {
285+ return img.pathToMount(bootDir)
286+}
287+
288+// BaseMount returns the base directory used to mount the image partitions.
289+func (img BaseImage) BaseMount() string {
290+ if img.baseMount == "" {
291+ panic("image needs to be mounted")
292+ }
293+
294+ return img.baseMount
295 }
296
297 func printOut(args ...interface{}) {
298
299=== modified file 'diskimage/core_grub.go'
300--- diskimage/core_grub.go 2015-06-11 03:13:19 +0000
301+++ diskimage/core_grub.go 2015-06-15 15:32:50 +0000
302@@ -8,14 +8,12 @@
303 package diskimage
304
305 import (
306- "bufio"
307 "errors"
308 "fmt"
309 "io"
310 "os"
311 "os/exec"
312 "path/filepath"
313- "strings"
314 "time"
315
316 "launchpad.net/goget-ubuntu-touch/sysutils"
317@@ -34,21 +32,18 @@
318 // with this program. If not, see <http://www.gnu.org/licenses/>.
319
320 type CoreGrubImage struct {
321- CoreImage
322- hardware HardwareDescription
323- oem OemDescription
324- location string
325- size int64
326- baseMount string
327- parts []partition
328+ BaseImage
329 }
330
331 func NewCoreGrubImage(location string, size int64, hw HardwareDescription, oem OemDescription) *CoreGrubImage {
332 return &CoreGrubImage{
333- location: location,
334- size: size,
335- hardware: hw,
336- oem: oem,
337+ BaseImage{
338+ location: location,
339+ size: size,
340+ hardware: hw,
341+ oem: oem,
342+ partCount: 5,
343+ },
344 }
345 }
346
347@@ -63,43 +58,6 @@
348 configfile $prefix/grub.cfg
349 `
350
351-func (img *CoreGrubImage) Mount() error {
352- baseMount, err := mount(img.parts)
353- if err != nil {
354- return err
355- }
356- img.baseMount = baseMount
357-
358- return nil
359-}
360-
361-func (img *CoreGrubImage) Unmount() (err error) {
362- if img.baseMount == "" {
363- panic("No base mountpoint set")
364- }
365- defer os.Remove(img.baseMount)
366-
367- if out, err := exec.Command("sync").CombinedOutput(); err != nil {
368- return fmt.Errorf("Failed to sync filesystems before unmounting: %s", out)
369- }
370-
371- for _, part := range img.parts {
372- if part.fs == fsNone {
373- continue
374- }
375-
376- mountpoint := filepath.Join(img.baseMount, string(part.dir))
377- if out, err := exec.Command("umount", "-l", mountpoint).CombinedOutput(); err != nil {
378- return fmt.Errorf("unable to unmount dir for image: %s", out)
379- } else {
380- }
381- }
382-
383- img.baseMount = ""
384-
385- return nil
386-}
387-
388 //Partition creates a partitioned image from an img
389 func (img *CoreGrubImage) Partition() error {
390 if err := sysutils.CreateEmptyFile(img.location, img.size, sysutils.GB); err != nil {
391@@ -125,150 +83,6 @@
392 return parted.create(img.location)
393 }
394
395-//Map creates loop devices for the partitions
396-func (img *CoreGrubImage) Map() error {
397- if isMapped(img.parts) {
398- panic("cannot double map partitions")
399- }
400-
401- kpartxCmd := exec.Command("kpartx", "-avs", img.location)
402- stdout, err := kpartxCmd.StdoutPipe()
403- if err != nil {
404- return err
405- }
406-
407- if err := kpartxCmd.Start(); err != nil {
408- return err
409- }
410-
411- loops := make([]string, 0, 4)
412- scanner := bufio.NewScanner(stdout)
413- for scanner.Scan() {
414- fields := strings.Fields(scanner.Text())
415-
416- if len(fields) > 2 {
417- loops = append(loops, fields[2])
418- } else {
419- return errors.New("issues while determining drive mappings")
420- }
421- }
422- if err := scanner.Err(); err != nil {
423- return err
424- }
425-
426- // there are 5 partitions, so there should be five loop mounts
427- if len(loops) != 5 {
428- return errors.New("more partitions then expected while creating loop mapping")
429- }
430-
431- mapPartitions(img.parts, loops)
432-
433- if err := kpartxCmd.Wait(); err != nil {
434- return err
435- }
436-
437- return nil
438-}
439-
440-//Unmap destroys loop devices for the partitions
441-func (img *CoreGrubImage) Unmap() error {
442- if img.baseMount != "" {
443- panic("cannot unmap mounted partitions")
444- }
445-
446- for _, part := range img.parts {
447- if err := exec.Command("dmsetup", "clear", part.loop).Run(); err != nil {
448- return err
449- }
450- }
451-
452- if err := exec.Command("kpartx", "-d", img.location).Run(); err != nil {
453- return err
454- }
455-
456- unmapPartitions(img.parts)
457-
458- return nil
459-}
460-
461-func (img CoreGrubImage) Format() error {
462- for _, part := range img.parts {
463- dev := filepath.Join("/dev/mapper", part.loop)
464-
465- if part.fs == fsFat32 {
466- cmd := []string{"-F", "32", "-n", string(part.label)}
467-
468- size, err := sectorSize(dev)
469- if err != nil {
470- return err
471- }
472-
473- if size != "512" {
474- cmd = append(cmd, "-s", "1")
475- }
476-
477- cmd = append(cmd, "-S", size, dev)
478-
479- if out, err := exec.Command("mkfs.vfat", cmd...).CombinedOutput(); err != nil {
480- return fmt.Errorf("unable to create filesystem: %s", out)
481- }
482- } else if part.fs == fsExt4 {
483- if out, err := exec.Command("mkfs.ext4", "-F", "-L", string(part.label), dev).CombinedOutput(); err != nil {
484- return fmt.Errorf("unable to create filesystem: %s", out)
485- }
486- }
487- }
488-
489- return nil
490-}
491-
492-// User returns the writable path
493-func (img CoreGrubImage) Writable() string {
494- if img.parts == nil {
495- panic("img is not setup with partitions")
496- }
497-
498- if img.baseMount == "" {
499- panic("img not mounted")
500- }
501-
502- return filepath.Join(img.baseMount, string(writableDir))
503-}
504-
505-// Boot returns the system-boot path
506-func (img CoreGrubImage) Boot() string {
507- if img.parts == nil {
508- panic("img is not setup with partitions")
509- }
510-
511- if img.baseMount == "" {
512- panic("img not mounted")
513- }
514-
515- return filepath.Join(img.baseMount, string(bootDir))
516-}
517-
518-//System returns the system path
519-func (img CoreGrubImage) System() string {
520- if img.parts == nil {
521- panic("img is not setup with partitions")
522- }
523-
524- if img.baseMount == "" {
525- panic("img not mounted")
526- }
527-
528- return filepath.Join(img.baseMount, string(systemADir))
529-}
530-
531-func (img CoreGrubImage) BaseMount() string {
532- if img.baseMount == "" {
533- panic("image needs to be mounted")
534- }
535-
536- return img.baseMount
537-}
538-
539 func (img *CoreGrubImage) SetupBoot(oemRootPath string) error {
540 for _, dev := range []string{"dev", "proc", "sys"} {
541 src := filepath.Join("/", dev)
542
543=== modified file 'diskimage/core_uboot.go'
544--- diskimage/core_uboot.go 2015-06-11 03:13:19 +0000
545+++ diskimage/core_uboot.go 2015-06-15 15:32:50 +0000
546@@ -8,14 +8,10 @@
547 package diskimage
548
549 import (
550- "bufio"
551- "errors"
552 "fmt"
553 "io/ioutil"
554 "os"
555- "os/exec"
556 "path/filepath"
557- "strings"
558 "text/template"
559
560 "launchpad.net/goget-ubuntu-touch/sysutils"
561@@ -34,14 +30,7 @@
562 // with this program. If not, see <http://www.gnu.org/licenses/>.
563
564 type CoreUBootImage struct {
565- CoreImage
566- SystemImage
567- hardware HardwareDescription
568- oem OemDescription
569- location string
570- size int64
571- baseMount string
572- parts []partition
573+ BaseImage
574 }
575
576 const snappySystemTemplate = `# This is a snappy variables and boot logic file and is entirely generated and
577@@ -79,44 +68,14 @@
578
579 func NewCoreUBootImage(location string, size int64, hw HardwareDescription, oem OemDescription) *CoreUBootImage {
580 return &CoreUBootImage{
581- hardware: hw,
582- oem: oem,
583- location: location,
584- size: size,
585- }
586-}
587-
588-func (img *CoreUBootImage) Mount() error {
589- baseMount, err := mount(img.parts)
590- if err != nil {
591- return err
592- }
593- img.baseMount = baseMount
594-
595- return nil
596-}
597-
598-func (img *CoreUBootImage) Unmount() (err error) {
599- if img.baseMount == "" {
600- panic("No base mountpoint set")
601- }
602- defer func() {
603- os.Remove(img.baseMount)
604- img.baseMount = ""
605- }()
606-
607- if out, err := exec.Command("sync").CombinedOutput(); err != nil {
608- return fmt.Errorf("Failed to sync filesystems before unmounting: %s", out)
609- }
610-
611- for _, part := range img.parts {
612- mountpoint := filepath.Join(img.baseMount, string(part.dir))
613- if out, err := exec.Command("umount", "-l", mountpoint).CombinedOutput(); err != nil {
614- panic(fmt.Sprintf("unable to unmount dir for image: %s", out))
615- }
616- }
617-
618- return nil
619+ BaseImage{
620+ hardware: hw,
621+ oem: oem,
622+ location: location,
623+ size: size,
624+ partCount: 4,
625+ },
626+ }
627 }
628
629 //Partition creates a partitioned image from an img
630@@ -142,137 +101,6 @@
631 return parted.create(img.location)
632 }
633
634-//Map creates loop devices for the partitions
635-func (img *CoreUBootImage) Map() error {
636- if isMapped(img.parts) {
637- panic("cannot double map partitions")
638- }
639-
640- kpartxCmd := exec.Command("kpartx", "-avs", img.location)
641- stdout, err := kpartxCmd.StdoutPipe()
642- if err != nil {
643- return err
644- }
645-
646- if err := kpartxCmd.Start(); err != nil {
647- return err
648- }
649-
650- loops := make([]string, 0, 4)
651- scanner := bufio.NewScanner(stdout)
652- for scanner.Scan() {
653- fields := strings.Fields(scanner.Text())
654-
655- if len(fields) > 2 {
656- loops = append(loops, fields[2])
657- } else {
658- return errors.New("issues while determining drive mappings")
659- }
660- }
661- if err := scanner.Err(); err != nil {
662- return err
663- }
664-
665- // there are 5 partitions, so there should be five loop mounts
666- if len(loops) != 4 {
667- return errors.New("more partitions then expected while creating loop mapping")
668- }
669-
670- mapPartitions(img.parts, loops)
671-
672- if err := kpartxCmd.Wait(); err != nil {
673- return err
674- }
675-
676- return nil
677-}
678-
679-//Unmap destroys loop devices for the partitions
680-func (img *CoreUBootImage) Unmap() error {
681- if img.baseMount != "" {
682- panic("cannot unmap mounted partitions")
683- }
684-
685- for _, part := range img.parts {
686- if err := exec.Command("dmsetup", "clear", part.loop).Run(); err != nil {
687- return err
688- }
689- }
690-
691- if err := exec.Command("kpartx", "-d", img.location).Run(); err != nil {
692- return err
693- }
694-
695- unmapPartitions(img.parts)
696-
697- return nil
698-}
699-
700-func (img CoreUBootImage) Format() error {
701- for _, part := range img.parts {
702- dev := filepath.Join("/dev/mapper", part.loop)
703-
704- if part.fs == fsFat32 {
705- cmd := []string{"-F", "32", "-n", string(part.label)}
706-
707- size, err := sectorSize(dev)
708- if err != nil {
709- return err
710- }
711-
712- if size != "512" {
713- cmd = append(cmd, "-s", "1")
714- }
715-
716- cmd = append(cmd, "-S", size, dev)
717-
718- if out, err := exec.Command("mkfs.vfat", cmd...).CombinedOutput(); err != nil {
719- return fmt.Errorf("unable to create filesystem: %s", out)
720- }
721- } else {
722- if out, err := exec.Command("mkfs.ext4", "-F", "-L", string(part.label), dev).CombinedOutput(); err != nil {
723- return fmt.Errorf("unable to create filesystem: %s", out)
724- }
725- }
726- }
727-
728- return nil
729-}
730-
731-// User returns the writable path
732-func (img *CoreUBootImage) Writable() string {
733- if img.parts == nil {
734- panic("img is not setup with partitions")
735- }
736-
737- if img.baseMount == "" {
738- panic("img not mounted")
739- }
740-
741- return filepath.Join(img.baseMount, string(writableDir))
742-}
743-
744-//System returns the system path
745-func (img *CoreUBootImage) System() string {
746- if img.parts == nil {
747- panic("img is not setup with partitions")
748- }
749-
750- if img.baseMount == "" {
751- panic("img not mounted")
752- }
753-
754- return filepath.Join(img.baseMount, string(systemADir))
755-}
756-
757-func (img CoreUBootImage) BaseMount() string {
758- if img.baseMount == "" {
759- panic("image needs to be mounted")
760- }
761-
762- return img.baseMount
763-}
764-
765 func (img CoreUBootImage) SetupBoot(oemRootPath string) error {
766 // destinations
767 bootPath := filepath.Join(img.baseMount, string(bootDir))
768
769=== added file 'diskimage/errors.go'
770--- diskimage/errors.go 1970-01-01 00:00:00 +0000
771+++ diskimage/errors.go 2015-06-15 15:32:50 +0000
772@@ -0,0 +1,32 @@
773+//
774+// diskimage - handles ubuntu disk images
775+//
776+// Copyright (c) 2015 Canonical Ltd.
777+//
778+// Written by Sergio Schvezov <sergio.schvezov@canonical.com>
779+//
780+package diskimage
781+
782+import "fmt"
783+
784+// ErrMount represents a mount error
785+type ErrMount struct {
786+ dev string
787+ mountpoint string
788+ fs fsType
789+ out []byte
790+}
791+
792+func (e ErrMount) Error() string {
793+ return fmt.Sprintf("cannot mount %s(%s) on %s: %s", e.dev, e.fs, e.mountpoint, e.out)
794+}
795+
796+// ErrMapCount represents an error on the expected amount of partitions
797+type ErrMapCount struct {
798+ foundParts int
799+ expectedParts int
800+}
801+
802+func (e ErrMapCount) Error() string {
803+ return fmt.Sprintf("expected %d partitons but found %d", e.expectedParts, e.foundParts)
804+}
805
806=== modified file 'ubuntu-device-flash/core.go'
807--- ubuntu-device-flash/core.go 2015-06-09 13:57:34 +0000
808+++ ubuntu-device-flash/core.go 2015-06-15 15:32:50 +0000
809@@ -322,24 +322,14 @@
810 }
811
812 func (coreCmd *CoreCmd) setup(img diskimage.CoreImage, filePathChan <-chan string, fileCount int) error {
813- printOut("Mapping...")
814- if err := img.Map(); err != nil {
815- return err
816- }
817- defer func() {
818- printOut("Unmapping...")
819- defer img.Unmap()
820- }()
821-
822 printOut("Mounting...")
823 if err := img.Mount(); err != nil {
824- fmt.Println(err)
825 return err
826 }
827 defer func() {
828 printOut("Unmounting...")
829 if err := img.Unmount(); err != nil {
830- fmt.Println(err)
831+ fmt.Println("WARNING: unexpected issue:", err)
832 }
833 }()
834

Subscribers

People subscribed via source and target branches