diff -Nru goget-ubuntu-touch-0.4+15.04.20141104.1/debian/changelog goget-ubuntu-touch-0.4+15.04.20141125/debian/changelog --- goget-ubuntu-touch-0.4+15.04.20141104.1/debian/changelog 2014-11-27 10:18:17.000000000 +0000 +++ goget-ubuntu-touch-0.4+15.04.20141125/debian/changelog 2014-11-27 10:18:17.000000000 +0000 @@ -1,3 +1,60 @@ +goget-ubuntu-touch (0.4+15.04.20141125-0ubuntu1) vivid; urgency=low + + [ Sergio Schvezov ] + * ubuntu-emulator: allow setting a default password for the phablet + user when creating (LP: #1390476) + * ubuntu-emulator: fixing password setup for phablet user when setting + up an armhf instance (LP: #1393398) + * ubuntu-device-flash: dual images for core + + -- Ubuntu daily release Tue, 25 Nov 2014 23:51:15 +0000 + +goget-ubuntu-touch (0.4+15.04.20141121-0ubuntu1) vivid; urgency=low + + [ Sergio Schvezov ] + * ubuntu-device-flash: better priv escalation handling + + -- Ubuntu daily release Fri, 21 Nov 2014 11:33:00 +0000 + +goget-ubuntu-touch (0.4+15.04.20141120.1-0ubuntu1) vivid; urgency=low + + [ Michael Vogt ] + * ubuntu-device-flash: adding /etc/default/grub.d/50-system-image.cfg + for core to fix grub issues, the oustanding one being + GRUB_RECORDFAIL_TIMEOUT=0. + + -- Ubuntu daily release Thu, 20 Nov 2014 10:53:28 +0000 + +goget-ubuntu-touch (0.4+15.04.20141120-0ubuntu1) vivid; urgency=low + + [ Sergio Schvezov ] + * ubuntu-device-flash: don't display hidden channels (LP: #1394257) + * ubuntu-device-flash: error message improvements and best effort to + block sigterm in some cases + * ubuntu-device-flash: add a --developer-mode that for now copies ssh + keys into the image + + -- Ubuntu daily release Thu, 20 Nov 2014 01:46:02 +0000 + +goget-ubuntu-touch (0.4+15.04.20141118.1-0ubuntu1) vivid; urgency=low + + [ Sergio Schvezov ] + * debian/control: explicitly depending on kpartx for ubuntu-device- + flash + + [ Michael Vogt ] + * ubuntu-device-flash: don't create user-data for core images. + + -- Ubuntu daily release Tue, 18 Nov 2014 16:50:22 +0000 + +goget-ubuntu-touch (0.4+15.04.20141113-0ubuntu1) vivid; urgency=low + + [ Michael Vogt ] + * ubuntu-device-flash: trivial branch to fix crash if no + /etc/default/keyboard file is available + + -- Ubuntu daily release Thu, 13 Nov 2014 15:06:36 +0000 + goget-ubuntu-touch (0.4+15.04.20141104.1-0ubuntu1) vivid; urgency=low [ Sergio Schvezov ] diff -Nru goget-ubuntu-touch-0.4+15.04.20141104.1/debian/control goget-ubuntu-touch-0.4+15.04.20141125/debian/control --- goget-ubuntu-touch-0.4+15.04.20141104.1/debian/control 2014-11-27 10:18:17.000000000 +0000 +++ goget-ubuntu-touch-0.4+15.04.20141125/debian/control 2014-11-27 10:18:17.000000000 +0000 @@ -18,10 +18,11 @@ Architecture: any Depends: android-tools-adb, android-tools-fastboot, + kpartx, ${misc:Depends}, ${shlibs:Depends}, Built-Using: ${misc:Built-Using} -Description: Flash supported Nexus devices with Ubuntu +Description: Flash supported devices with Ubuntu Use this tool to flash a suported device with Ubuntu by either bootstrapping from fastboot or reflashing from an already supported device. @@ -42,6 +43,7 @@ ${misc:Depends}, ${shlibs:Depends}, Recommends: android-tools-adb, + qemu-user-static, Built-Using: ${misc:Built-Using} Description: Create and run emulator images of Ubuntu Touch Create and destroy Ubuntu Touch instances and run them with the emulator diff -Nru goget-ubuntu-touch-0.4+15.04.20141104.1/diskimage/customization.go goget-ubuntu-touch-0.4+15.04.20141125/diskimage/customization.go --- goget-ubuntu-touch-0.4+15.04.20141104.1/diskimage/customization.go 2014-11-04 18:41:40.000000000 +0000 +++ goget-ubuntu-touch-0.4+15.04.20141125/diskimage/customization.go 2014-11-25 23:50:53.000000000 +0000 @@ -20,11 +20,9 @@ // with this program. If not, see . import ( - "errors" "fmt" "io/ioutil" "os" - "os/exec" "path/filepath" ) @@ -85,14 +83,3 @@ writeFlag := filepath.Join(img.Mountpoint, ".adb_onlock") return ioutil.WriteFile(writeFlag, []byte(""), 0644) } - -//SetPassword is an ugly hack to set the password -func (img DiskImage) SetPassword(user, password string) error { - // Run something that would look like this - // PATH=$path chroot "$SYSTEM_MOUNTPOINT" /bin/sh -c "echo -n "$user:$password" | chpasswd" - chrootCmd := fmt.Sprintf("echo -n '%s:%s' | chpasswd", user, password) - if out, err := exec.Command("chroot", img.Mountpoint, "/bin/sh", "-c", chrootCmd).CombinedOutput(); err != nil { - return errors.New(string(out)) - } - return nil -} diff -Nru goget-ubuntu-touch-0.4+15.04.20141104.1/diskimage/image.go goget-ubuntu-touch-0.4+15.04.20141125/diskimage/image.go --- goget-ubuntu-touch-0.4+15.04.20141104.1/diskimage/image.go 2014-11-04 18:41:00.000000000 +0000 +++ goget-ubuntu-touch-0.4+15.04.20141125/diskimage/image.go 2014-11-25 23:51:02.000000000 +0000 @@ -37,13 +37,15 @@ type directory string const ( - systemDataLabel imageLabel = "system-data" - userDataLabel imageLabel = "user-data" + systemDataLabel imageLabel = "system-data" + systemDataLabel2 imageLabel = "system-data-2" + userDataLabel imageLabel = "user-data" ) const ( - systemDataDir directory = "system" - userDataDir directory = "user-data" + systemDataDir directory = "system" + systemDataDir2 directory = "system-2" + userDataDir directory = "user-data" ) type partition struct { @@ -128,16 +130,19 @@ } //System returns the system path -func (img *DiskImage) System() (string, error) { +func (img *DiskImage) System() ([]string, error) { if img.parts == nil { - return "", errors.New("img is not setup with partitions") + return nil, errors.New("img is not setup with partitions") } if img.Mountpoint == "" { - return "", errors.New("img not mounted") + return nil, errors.New("img not mounted") } - return filepath.Join(img.Mountpoint, string(systemDataDir)), nil + return []string{ + filepath.Join(img.Mountpoint, string(systemDataDir)), + filepath.Join(img.Mountpoint, string(systemDataDir2)), + }, nil } //Mount the DiskImage @@ -166,7 +171,7 @@ return err } if out, err := exec.Command("mount", filepath.Join("/dev/mapper", part.loop), mountpoint).CombinedOutput(); err != nil { - return fmt.Errorf("unable to dir to create system image: %s", out) + return fmt.Errorf("unable to mount dir to create system image: %s", out) } } return nil @@ -208,7 +213,7 @@ for _, part := range img.parts { mountpoint := filepath.Join(img.Mountpoint, string(part.dir)) if out, err := exec.Command("umount", mountpoint).CombinedOutput(); err != nil { - return fmt.Errorf("unable to dir to create system image: %s", out) + return fmt.Errorf("unable to unmount dir for image: %s", out) } if err := os.Remove(mountpoint); err != nil { return err @@ -245,7 +250,7 @@ } //Partition creates a partitioned image from an img -func (img *DiskImage) Partition() error { +func (img *DiskImage) Partition(dual bool) error { if err := sysutils.CreateEmptyFile(img.path, img.size); err != nil { return err } @@ -257,17 +262,22 @@ } stdin.Write([]byte("mklabel msdos\n")) - stdin.Write([]byte("mkpart primary ext4 2048s 4G\n")) - stdin.Write([]byte("mkpart primary ext4 4G -1s\n")) + stdin.Write([]byte("mkpart primary ext4 2048s 3905535s\n")) + if dual { + stdin.Write([]byte("mkpart primary ext4 3905536s 7809023s\n")) + stdin.Write([]byte("mkpart primary ext4 7809024s -1s\n")) + } else { + stdin.Write([]byte("mkpart primary ext4 3905536s -1s\n")) + } stdin.Write([]byte("set 1 boot on\n")) - stdin.Write([]byte("print\n")) + stdin.Write([]byte("unit s print\n")) stdin.Write([]byte("quit\n")) return partedCmd.Run() } //MapPartitions creates loop devices for the partitions -func (img *DiskImage) MapPartitions() error { +func (img *DiskImage) MapPartitions(dual bool) error { kpartxCmd := exec.Command("kpartx", "-avs", img.path) stdout, err := kpartxCmd.StdoutPipe() if err != nil { @@ -278,10 +288,11 @@ return err } - loops := make([]string, 0, 2) + loops := make([]string, 0, 3) scanner := bufio.NewScanner(stdout) for scanner.Scan() { fields := strings.Fields(scanner.Text()) + if len(fields) > 2 { loops = append(loops, fields[2]) } else { @@ -292,13 +303,26 @@ return err } - if len(loops) != 2 { + expectedLoops := 2 + if dual { + expectedLoops = 3 + } + + if len(loops) != expectedLoops { return errors.New("more partitions then expected while creating loop mapping") } - img.parts = []partition{ - partition{label: systemDataLabel, dir: systemDataDir, loop: loops[0]}, - partition{label: userDataLabel, dir: userDataDir, loop: loops[1]}, + if dual { + img.parts = []partition{ + partition{label: systemDataLabel, dir: systemDataDir, loop: loops[0]}, + partition{label: systemDataLabel2, dir: systemDataDir2, loop: loops[1]}, + partition{label: userDataLabel, dir: userDataDir, loop: loops[2]}, + } + } else { + img.parts = []partition{ + partition{label: systemDataLabel, dir: systemDataDir, loop: loops[0]}, + partition{label: userDataLabel, dir: userDataDir, loop: loops[1]}, + } } if err := kpartxCmd.Wait(); err != nil { @@ -329,8 +353,8 @@ for _, part := range img.parts { dev := filepath.Join("/dev/mapper", part.loop) - if err := exec.Command("mkfs.ext4", "-F", "-L", string(part.label), dev).Run(); err != nil { - return err + if out, err := exec.Command("mkfs.ext4", "-F", "-L", string(part.label), dev).CombinedOutput(); err != nil { + return fmt.Errorf("unable to create filesystem: %s", out) } } diff -Nru goget-ubuntu-touch-0.4+15.04.20141104.1/README goget-ubuntu-touch-0.4+15.04.20141125/README --- goget-ubuntu-touch-0.4+15.04.20141104.1/README 1970-01-01 00:00:00.000000000 +0000 +++ goget-ubuntu-touch-0.4+15.04.20141125/README 2014-11-25 23:50:32.000000000 +0000 @@ -0,0 +1,5 @@ +To build run: +$ sudo apt-get build-dep goget-ubuntu-touch + +?!?! there is surely a better way +$ debian/rules clean build diff -Nru goget-ubuntu-touch-0.4+15.04.20141104.1/ubuntu-device-flash/common.go goget-ubuntu-touch-0.4+15.04.20141125/ubuntu-device-flash/common.go --- goget-ubuntu-touch-0.4+15.04.20141104.1/ubuntu-device-flash/common.go 2014-11-04 18:41:00.000000000 +0000 +++ goget-ubuntu-touch-0.4+15.04.20141125/ubuntu-device-flash/common.go 2014-11-25 23:50:32.000000000 +0000 @@ -3,7 +3,10 @@ import ( "log" "path/filepath" + "runtime" + "syscall" + "launchpad.net/goget-ubuntu-touch/sysutils" "launchpad.net/goget-ubuntu-touch/ubuntuimage" ) @@ -20,6 +23,16 @@ // bitDownloader downloads func bitDownloader(file ubuntuimage.File, files chan<- Files, server, downloadDir string) { + // hack to circumvent https://code.google.com/p/go/issues/detail?id=1435 + if syscall.Getuid() == 0 { + runtime.GOMAXPROCS(1) + runtime.LockOSThread() + + if err := sysutils.DropPrivs(); err != nil { + log.Fatal(err) + } + } + err := file.MakeRelativeToServer(server) if err != nil { log.Fatal(err) diff -Nru goget-ubuntu-touch-0.4+15.04.20141104.1/ubuntu-device-flash/core.go goget-ubuntu-touch-0.4+15.04.20141125/ubuntu-device-flash/core.go --- goget-ubuntu-touch-0.4+15.04.20141104.1/ubuntu-device-flash/core.go 2014-11-04 18:41:19.000000000 +0000 +++ goget-ubuntu-touch-0.4+15.04.20141125/ubuntu-device-flash/core.go 2014-11-25 23:51:02.000000000 +0000 @@ -11,9 +11,11 @@ import ( "errors" "fmt" + "io" "io/ioutil" "os" "os/exec" + "os/signal" "path/filepath" "runtime" "strings" @@ -45,22 +47,33 @@ } type CoreCmd struct { - Channel string `long:"channel" description:"Specify the channel to use" default:"ubuntu-core/devel"` - Device string `long:"device" description:"Specify the device to use" default:"generic_amd64"` - Keyboard string `long:"keyboard-layout" description:"Specify the keyboard layout" default:"us"` - Output string `long:"output" short:"o" description:"Name of the image file to create" required:"true"` - Size int64 `long:"size" short:"s" description:"Size of image file to create in GB (min 6)" default:"20"` + Channel string `long:"channel" description:"Specify the channel to use" default:"ubuntu-core/devel"` + Device string `long:"device" description:"Specify the device to use" default:"generic_amd64"` + Keyboard string `long:"keyboard-layout" description:"Specify the keyboard layout" default:"us"` + Output string `long:"output" short:"o" description:"Name of the image file to create" required:"true"` + Size int64 `long:"size" short:"s" description:"Size of image file to create in GB (min 6)" default:"20"` + DeveloperMode bool `long:"developer-mode" description:"Finds the latest public key in your ~/.ssh and sets it up"` + Dual bool `long:"dual-images" description:"Sets up two images to upgrade with providing rollback support"` } var coreCmd CoreCmd -const cloudInitMetaData = `instance-id: nocloud-static` +const cloudInitMetaData = `instance-id: nocloud-static +` + const cloudInitUserData = `#cloud-config password: passw0rd chpasswd: { expire: False } ssh_pwauth: True ` +const grubCfgContent = `# console only, no graphics/vga +GRUB_CMDLINE_LINUX_DEFAULT="console=tty1 console=ttyS0" +GRUB_TERMINAL=console +# LP: #1035279 +GRUB_RECORDFAIL_TIMEOUT=0 +` + func (coreCmd *CoreCmd) Execute(args []string) error { if syscall.Getuid() != 0 { return errors.New("command requires sudo/pkexec (root)") @@ -115,7 +128,7 @@ }() img := diskimage.New(coreCmd.Output, "", coreCmd.Size) - if err := img.Partition(); err != nil { + if err := img.Partition(coreCmd.Dual); err != nil { return err } defer func() { @@ -124,8 +137,21 @@ } }() + // Handle SIGINT and SIGTERM. + go func() { + ch := make(chan os.Signal) + signal.Notify(ch, syscall.SIGINT, syscall.SIGTERM) + + for sig := range ch { + fmt.Println("Received", sig, "... ignoring") + } + }() + // Execute the following code with escalated privs and drop them when done err = func() error { + // hack to circumvent https://code.google.com/p/go/issues/detail?id=1435 + runtime.GOMAXPROCS(1) + runtime.LockOSThread() if err := sysutils.EscalatePrivs(); err != nil { return err } @@ -145,14 +171,14 @@ return err } - fmt.Println("New image complete, launch by running: kvm", coreCmd.Output) + fmt.Println("New image complete, launch by running: kvm -m 768", coreCmd.Output) return nil } func (coreCmd *CoreCmd) partition(img *diskimage.DiskImage) error { - if err := img.MapPartitions(); err != nil { - return err + if err := img.MapPartitions(coreCmd.Dual); err != nil { + return fmt.Errorf("issue while mapping partitions: %s", err) } defer img.UnMapPartitions() @@ -160,7 +186,7 @@ } func (coreCmd *CoreCmd) setup(img *diskimage.DiskImage, filePathChan <-chan string) error { - if err := img.MapPartitions(); err != nil { + if err := img.MapPartitions(coreCmd.Dual); err != nil { return err } defer img.UnMapPartitions() @@ -176,33 +202,44 @@ } } - systemPath, err := img.System() + systemPaths, err := img.System() if err != nil { return err } - if err := coreCmd.setupBootloader(systemPath); err != nil { - return err - } - - if err := coreCmd.setupKeyboardLayout(systemPath); err != nil { - return err - } - userPath, err := img.User() if err != nil { return err } - for _, dir := range []string{"system-data", "user-data", "cache"} { + if coreCmd.Dual { + src := fmt.Sprintf("%s/system/.", img.Mountpoint) + dst := fmt.Sprintf("%s/system-2", img.Mountpoint) + cmd := exec.Command("cp", "-r", "--preserve=all", src, dst) + if out, err := cmd.CombinedOutput(); err != nil { + return fmt.Errorf("failed to replicate image contents: %s", out) + } + } + + for _, dir := range []string{"system-data", "cache"} { dirPath := filepath.Join(userPath, dir) if err := os.Mkdir(dirPath, 0755); err != nil { return err } } - if err := coreCmd.setupCloudInit(systemPath, filepath.Join(userPath, "system-data")); err != nil { - return err + for i := range systemPaths { + if err := coreCmd.setupBootloader(systemPaths[i]); err != nil { + return err + } + + if err := coreCmd.setupKeyboardLayout(systemPaths[i]); err != nil { + return err + } + + if err := coreCmd.setupCloudInit(systemPaths[i], filepath.Join(userPath, "system-data")); err != nil { + return err + } } return nil @@ -220,13 +257,39 @@ return err } - metaDataPath := filepath.Join(cloudDir, "meta-data") - if err := ioutil.WriteFile(metaDataPath, []byte(cloudInitMetaData), 0600); err != nil { + metaDataFile, err := os.Create(filepath.Join(cloudDir, "meta-data")) + if err != nil { + return err + } + defer metaDataFile.Close() + + if _, err := io.WriteString(metaDataFile, cloudInitMetaData); err != nil { + return err + } + + if coreCmd.DeveloperMode { + authorizedKey, err := getAuthorizedSshKey() + if err != nil { + return fmt.Errorf("failed to obtain a public key for developer mode: %s", err) + } + + if _, err := io.WriteString(metaDataFile, "public-keys:\n"); err != nil { + return err + } + + if _, err := io.WriteString(metaDataFile, fmt.Sprintf(" - %s\n", authorizedKey)); err != nil { + return err + } + + } + + userDataFile, err := os.Create(filepath.Join(cloudDir, "user-data")) + if err != nil { return err } + defer userDataFile.Close() - userDataPath := filepath.Join(cloudDir, "user-data") - if err := ioutil.WriteFile(userDataPath, []byte(cloudInitUserData), 0600); err != nil { + if _, err := io.WriteString(userDataFile, cloudInitUserData); err != nil { return err } @@ -236,6 +299,11 @@ func (coreCmd *CoreCmd) setupKeyboardLayout(systemPath string) error { kbFilePath := filepath.Join(systemPath, "etc", "default", "keyboard") + // do not error if the image has no keyboard + if _, err := os.Stat(kbFilePath); err != nil && os.IsNotExist(err) { + return nil + } + kbFileContents, err := ioutil.ReadFile(kbFilePath) if err != nil { return err @@ -288,6 +356,20 @@ fmt.Println(string(out)) } + // ensure we run not into recordfail issue + grubDir := filepath.Join(systemPath, "etc", "default", "grub.d") + if err := os.MkdirAll(grubDir, 0755); err != nil { + return fmt.Errorf("unable to create %s dir: %s", grubDir, err) + } + grubFile, err := os.Create(filepath.Join(grubDir, "50-system-image.cfg")) + if err != nil { + return fmt.Errorf("unable to create %s file: %s", grubFile, err) + } + defer grubFile.Close() + if _, err := io.WriteString(grubFile, grubCfgContent); err != nil { + return err + } + // I don't know why this is needed, I just picked it up from the original implementation time.Sleep(3 * time.Second) @@ -315,3 +397,34 @@ return nil } + +func getAuthorizedSshKey() (string, error) { + sshDir := os.ExpandEnv("$HOME/.ssh") + + fis, err := ioutil.ReadDir(sshDir) + if err != nil { + return "", fmt.Errorf("%s: no pub ssh key found, run ssh-keygen first", err) + } + + var preferredPubKey string + var latestModTime time.Time + for i := range fis { + file := fis[i].Name() + if strings.HasSuffix(file, ".pub") && !strings.HasSuffix(file, "cert.pub") { + fileMod := fis[i].ModTime() + + if fileMod.After(latestModTime) { + latestModTime = fileMod + preferredPubKey = file + } + } + } + + if preferredPubKey == "" { + return "", errors.New("no pub ssh key found, run ssh-keygen first") + } + + pubKey, err := ioutil.ReadFile(filepath.Join(sshDir, preferredPubKey)) + + return string(pubKey), err +} diff -Nru goget-ubuntu-touch-0.4+15.04.20141104.1/ubuntu-device-flash/query.go goget-ubuntu-touch-0.4+15.04.20141125/ubuntu-device-flash/query.go --- goget-ubuntu-touch-0.4+15.04.20141104.1/ubuntu-device-flash/query.go 2014-11-04 18:41:00.000000000 +0000 +++ goget-ubuntu-touch-0.4+15.04.20141125/ubuntu-device-flash/query.go 2014-11-25 23:50:32.000000000 +0000 @@ -84,10 +84,12 @@ } for k, v := range channels { - if v.Alias != "" { - fmt.Printf("%s (alias to %s)\n", k, v.Alias) - } else { - fmt.Println(k) + if !v.Hidden { + if v.Alias != "" { + fmt.Printf("%s (alias to %s)\n", k, v.Alias) + } else { + fmt.Println(k) + } } } diff -Nru goget-ubuntu-touch-0.4+15.04.20141104.1/ubuntu-emulator/create.go goget-ubuntu-touch-0.4+15.04.20141125/ubuntu-emulator/create.go --- goget-ubuntu-touch-0.4+15.04.20141104.1/ubuntu-emulator/create.go 2014-11-04 18:41:40.000000000 +0000 +++ goget-ubuntu-touch-0.4+15.04.20141125/ubuntu-emulator/create.go 2014-11-25 23:50:53.000000000 +0000 @@ -23,6 +23,7 @@ "errors" "fmt" "os" + "os/exec" "path/filepath" "runtime" "syscall" @@ -39,6 +40,7 @@ RawDisk bool `long:"use-raw-disk" description:"Use raw disks instead of qcow2"` SDCard bool `long:"with-sdcard" description:"Create an external vfat sdcard"` Arch string `long:"arch" description:"Device architecture to use (i386 or armhf)"` + Password string `long:"password" description:"This sets up the default password for the phablet user" default:"0000"` } var createCmd CreateCmd @@ -49,6 +51,11 @@ defaultArch = "i386" ) +const ( + binQemuArmStatic = "/usr/bin/qemu-arm-static" + pkgQemuUserStatic = "qemu-user-static" +) + func init() { createCmd.Arch = defaultArch createCmd.Channel = defaultChannel @@ -66,6 +73,10 @@ } instanceName := args[0] + if err := createCmd.verifyDependencies(); err != nil { + return err + } + var device string if d, ok := devices[createCmd.Arch]; ok { device = d["name"] @@ -118,7 +129,7 @@ sdcardImage := diskimage.New(filepath.Join(dataDir, "sdcard.img"), "USERDATA", 4) systemImage := diskimage.NewExisting(filepath.Join(dataDir, "system.img")) - if err := createSystem(ubuntuImage, sdcardImage, files); err != nil { + if err := createCmd.createSystem(ubuntuImage, sdcardImage, files); err != nil { return err } @@ -179,7 +190,18 @@ return systemImage.ExtractFile("build.prop", filepath.Join(dataDir, "system")) } -func createSystem(ubuntuImage, sdcardImage *diskimage.DiskImage, files []string) (err error) { +func (createCmd *CreateCmd) verifyDependencies() error { + switch createCmd.Arch { + case "armhf": + if _, err := os.Stat(binQemuArmStatic); err != nil { + return fmt.Errorf("missing dependency %s (apt install %s)", binQemuArmStatic, pkgQemuUserStatic) + } + } + + return nil +} + +func (createCmd *CreateCmd) createSystem(ubuntuImage, sdcardImage *diskimage.DiskImage, files []string) (err error) { for _, img := range []*diskimage.DiskImage{ubuntuImage, sdcardImage} { if err := img.CreateExt4(); err != nil { return err @@ -205,13 +227,15 @@ } return err } - fmt.Println("Setting up a default password for phablet to: '0000'") - if err := ubuntuImage.SetPassword("phablet", "0000"); err != nil { + + fmt.Printf("Setting up a default password for phablet to: '%s'\n", createCmd.Password) + if err := createCmd.setPassword(ubuntuImage.Mountpoint); err != nil { if err := ubuntuImage.Unmount(); err != nil { fmt.Println("Unmount error :", err) } return err } + if err := ubuntuImage.Unmount(); err != nil { return err } @@ -230,6 +254,25 @@ } return nil } + +// setPassword is an ugly hack to set the password +func (createCmd *CreateCmd) setPassword(chroot string) error { + if createCmd.Arch == "armhf" { + dst := filepath.Join(chroot, binQemuArmStatic) + if out, err := exec.Command("cp", binQemuArmStatic, dst).CombinedOutput(); err != nil { + return fmt.Errorf("issues while setting up password: %s", out) + } + defer os.Remove(dst) + } + + // Run something that would look like this + // PATH=$path chroot "$SYSTEM_MOUNTPOINT" /bin/sh -c "echo -n "$user:$password" | chpasswd" + chrootCmd := fmt.Sprintf("echo -n '%s:%s' | chpasswd", "phablet", createCmd.Password) + if out, err := exec.Command("chroot", chroot, "/bin/sh", "-c", chrootCmd).CombinedOutput(); err != nil { + return errors.New(string(out)) + } + return nil +} func download(image ubuntuimage.Image) (files []string, err error) { cacheDir := ubuntuimage.GetCacheDir() diff -Nru goget-ubuntu-touch-0.4+15.04.20141104.1/ubuntuimage/types.go goget-ubuntu-touch-0.4+15.04.20141125/ubuntuimage/types.go --- goget-ubuntu-touch-0.4+15.04.20141104.1/ubuntuimage/types.go 2014-11-04 18:40:34.000000000 +0000 +++ goget-ubuntu-touch-0.4+15.04.20141125/ubuntuimage/types.go 2014-11-25 23:50:32.000000000 +0000 @@ -24,14 +24,15 @@ } type Channel struct { - Devices map[string]Device - Alias string + Devices map[string]Device `json:"devices"` + Alias string `json:"alias"` + Hidden bool `json:"hidden,omitempty"` } type Channels map[string]Channel type ImageVersion struct { - Description string + Description string } type ImageVersions map[int]ImageVersion