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

Proposed by Sergio Schvezov on 2015-06-12
Status: Merged
Approved by: John Lenton on 2015-06-16
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 Approve on 2015-06-16
Michael Vogt 2015-06-12 Approve on 2015-06-15
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 on 2015-06-12

Revert uneeded func name change

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
188. By Sergio Schvezov on 2015-06-15

Try to cleanly unmount on mount errors

189. By Sergio Schvezov on 2015-06-15

Message about not being able to remove basemount

190. By Sergio Schvezov on 2015-06-15

Use syscall sync

191. By Sergio Schvezov on 2015-06-15

Nicer error for unmounting

192. By Sergio Schvezov on 2015-06-15

Adding errors.go

193. By Sergio Schvezov on 2015-06-15

Mapping errors

194. By Sergio Schvezov on 2015-06-15

removing duplicate code for paths to mounts

195. By Sergio Schvezov on 2015-06-15

Cleanup moved

Michael Vogt (mvo) wrote :

Nice!

review: Approve
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