Compare commits

..

No commits in common. "main" and "v1.0.0" have entirely different histories.
main ... v1.0.0

12 changed files with 140 additions and 389 deletions

View file

@ -3,30 +3,41 @@ NAME = lon-tool
SRC ?= main.go SRC ?= main.go
BIN_DIR ?= ./bin BIN_DIR ?= ./bin
GIT_VERSION := $(shell git describe --abbrev=4 --dirty --always --tags) GIT_VERSION := $(shell git describe --abbrev=4 --dirty --always --tags)
GOFLAGS ?= -ldflags="-s -w -X git.timoxa0.su/timoxa0/lon-tool/cmd.version=$(GIT_VERSION)" GOFLAGS ?= -ldflags="-s -w -X lon-tool/cmd.version=$(GIT_VERSION)"
WINDOWS_GOFLAGS ?= -ldflags="-extldflags=-static -s -w -X git.timoxa0.su/timoxa0/lon-tool/cmd.version=$(GIT_VERSION)" WINDOWS_GOFLAGS ?= -ldflags="-extldflags=-static -s -w -X lon-tool/cmd.version=$(GIT_VERSION)"
# macOS settings
MACOS_BIN = $(BIN_DIR)/$(NAME)_mac_amd64
MACOS_CC = x86_64-apple-darwin23-gcc-14
MACOS_CXX = x86_64-apple-darwin23-g++-14
# Windows settings # Windows settings
WINDOWS_BIN = $(BIN_DIR)/$(NAME)_win_amd64.exe WINDOWS_BIN = $(BIN_DIR)/$(NAME)_win_amd64.exe
WINDOWS_CC = x86_64-w64-mingw32-gcc WINDOWS_CC = x86_64-w64-mingw32-gcc
WINDOWS_CXX = x86_64-w64-mingw32-g++ WINDOWS_CXX = x86_64-w64-mingw32-g++
WINDOWS_PKG_CONFIG_PATH = /usr/x86_64-w64-mingw32/lib/pkgconfig WINDOWS_PKG_CONFIG_PATH = /usr/local/x86_64-w64-mingw32/lib/pkgconfig
WINDOWS_CGO_CFLAGS = -I/usr/x86_64-w64-mingw32/include WINDOWS_CGO_CFLAGS = -I/usr/local/x86_64-w64-mingw32/include
WINDOWS_CGO_LDFLAGS = -L/usr/x86_64-w64-mingw32/lib WINDOWS_CGO_LDFLAGS = -L/usr/local/x86_64-w64-mingw32/lib
# Linux settings # Linux settings
LINUX_BIN = $(BIN_DIR)/$(NAME)_lin_amd64 LINUX_BIN = $(BIN_DIR)/$(NAME)_lin_amd64
LINUX_CC = x86_64-linux-gnu-gcc LINUX_CC = x86_64-linux-gnu-gcc
LINUX_CXX = x86_64-linux-gnu-g++ LINUX_CXX = x86_64-linux-gnu-g++
LINUX_PKG_CONFIG_PATH = /usr/lib/pkgconfig LINUX_PKG_CONFIG_PATH = /usr/local/x86_64-linux-gnu/lib/pkgconfig
LINUX_CGO_CFLAGS = -I/usr/include LINUX_CGO_CFLAGS = -I/usr/local/x86_64-linux-gnu/include
LINUX_CGO_LDFLAGS = -L/usr/lib LINUX_CGO_LDFLAGS = -L/usr/local/x86_64-linux-gnu/lib
# Targets # Targets
all: windows linux all: macos windows linux
macos:
echo "Building macos bin"
@export CGO_ENABLED=1 GOARCH=amd64 GOOS=darwin CC=$(MACOS_CC) CXX=$(MACOS_CXX) && \
go build $(GOFLAGS) -o $(MACOS_BIN) $(SRC) && \
echo "- saved to $(MACOS_BIN)"
windows: windows:
@echo "Building windows bin" echo "Building windows bin"
@export CGO_ENABLED=1 GOARCH=amd64 GOOS=windows CC=$(WINDOWS_CC) CXX=$(WINDOWS_CXX) \ @export CGO_ENABLED=1 GOARCH=amd64 GOOS=windows CC=$(WINDOWS_CC) CXX=$(WINDOWS_CXX) \
PKG_CONFIG_PATH=$(WINDOWS_PKG_CONFIG_PATH) CGO_CFLAGS=$(WINDOWS_CGO_CFLAGS) \ PKG_CONFIG_PATH=$(WINDOWS_PKG_CONFIG_PATH) CGO_CFLAGS=$(WINDOWS_CGO_CFLAGS) \
CGO_LDFLAGS=$(WINDOWS_CGO_LDFLAGS) && \ CGO_LDFLAGS=$(WINDOWS_CGO_LDFLAGS) && \
@ -34,7 +45,7 @@ windows:
echo "- saved to $(WINDOWS_BIN)" echo "- saved to $(WINDOWS_BIN)"
linux: linux:
@echo "Building linux bin" echo "Building linux bin"
@export CGO_ENABLED=1 GOARCH=amd64 GOOS=linux CC=$(LINUX_CC) CXX=$(LINUX_CXX) \ @export CGO_ENABLED=1 GOARCH=amd64 GOOS=linux CC=$(LINUX_CC) CXX=$(LINUX_CXX) \
PKG_CONFIG_PATH=$(LINUX_PKG_CONFIG_PATH) CGO_CFLAGS=$(LINUX_CGO_CFLAGS) \ PKG_CONFIG_PATH=$(LINUX_PKG_CONFIG_PATH) CGO_CFLAGS=$(LINUX_CGO_CFLAGS) \
CGO_LDFLAGS=$(LINUX_CGO_LDFLAGS) && \ CGO_LDFLAGS=$(LINUX_CGO_LDFLAGS) && \

View file

@ -1,12 +1,25 @@
# Linux on Nabu Tool # Linux on Nabu Tool
### Go tool for installing linux on xiaomi pad 5 #### Go tool for installing linux on xiaomi pad 5
## Installation #### Exit codes:
### Windows (binary) | Code | Description |
```powershell -C "irm s.tx0.su/ltw | iex"``` |:----:|:-----------------------------|
| 166 | Invalid RootFS image |
### Linux (binary) | 167 | RootFS image not found! |
```curl -Ls s.tx0.su/ltl | bash``` | 168 | Invalid args |
| 169 | Failed to start adb server |
### Linux/macOS (build from source) | 170 | Device not found |
```curl -Ls s.tx0.su/lts | bash``` | 171 | More then one device |
| 172 | Fastboot device timed out |
| 173 | Recovery device timed out |
| 174 | Incompatible partition table |
| 175 | Postinstall failed |
| 176 | Failed to patch boot image |
| 177 | Failed to boot recovery |
| 178 | Platform is not supported |
| 179 | Download error |
| 180 | Repartition error |
| 181 | Failed to switch to tcp/ip |
| 252 | Unexpected error |
| 253 | User cancel |
| 254 | Is it nabu? |

View file

@ -3,6 +3,8 @@ package cmd
import ( import (
"io" "io"
"io/fs" "io/fs"
"lon-tool/image"
"lon-tool/utils"
"net" "net"
"os" "os"
"regexp" "regexp"
@ -10,9 +12,6 @@ import (
"strings" "strings"
"time" "time"
"git.timoxa0.su/timoxa0/lon-tool/image"
"git.timoxa0.su/timoxa0/lon-tool/utils"
"github.com/pterm/pterm" "github.com/pterm/pterm"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/timoxa0/goadb/adb" "github.com/timoxa0/goadb/adb"
@ -23,9 +22,7 @@ var username string
var password string var password string
var serail string var serail string
var partsize string var partsize string
var nosimpleinit bool
var partpercent int var partpercent int
var deployCmd = &cobra.Command{ var deployCmd = &cobra.Command{
Use: "deploy <rootfs.lni>", Use: "deploy <rootfs.lni>",
Short: "Deploy system to device", Short: "Deploy system to device",
@ -39,17 +36,18 @@ var deployCmd = &cobra.Command{
image, close, err := image.ReadImage(args[0]) image, close, err := image.ReadImage(args[0])
defer close() defer close()
if err != nil { if err != nil {
logger.Fatal("Failed to read image info:", logger.Args("Error", err)) logger.Error("Failed to read image info:", logger.Args("Error", err))
os.Exit(1)
} }
adbc, err := adb.New() adbc, err := adb.New()
if err != nil { if err != nil {
logger.Fatal("Failed to get adb client", logger.Args("Error", err)) logger.Fatal("Failed to get adb client", logger.Args(err))
} }
fb_devs, err := fastboot.FindDevices() fb_devs, err := fastboot.FindDevices()
logger.Debug("Devices", logger.Args("Devices", fb_devs, "err", err)) logger.Debug("Devices", logger.Args("Devices", fb_devs, "err", err))
if err != nil { if err != nil {
logger.Fatal("Failed to get fastboot device", logger.Args("Error", err)) logger.Fatal("Failed to get fastboot device", logger.Args(err))
} }
if len(fb_devs) < 1 { if len(fb_devs) < 1 {
@ -230,24 +228,7 @@ var deployCmd = &cobra.Command{
for i := 0; i <= 120; i++ { for i := 0; i <= 120; i++ {
if i == 120 { if i == 120 {
ofoxSpinner.Stop() ofoxSpinner.Stop()
logger.Warn("Recovery device timeout") logger.Error("Recovery device timeout")
logger.Info("Trying to restart adb server")
err := adbc.KillServer();
if err != nil {
logger.Error("Failed to kill server")
os.Exit(173);
}
err = adbc.StartServer();
if err != nil {
logger.Error("Failed to start server")
os.Exit(173);
}
adbd = adbc.Device(adb.DeviceWithSerial(serail));
if s, _ := adbd.State(); s == adb.StateRecovery {
logger.Info("Device found")
break
}
logger.Error("Device not found")
os.Exit(173) os.Exit(173)
} }
if s, _ := adbd.State(); s == adb.StateRecovery { if s, _ := adbd.State(); s == adb.StateRecovery {
@ -259,7 +240,14 @@ var deployCmd = &cobra.Command{
block_size, _ := adbd.RunCommand("blockdev --getsize64 /dev/block/sda") block_size, _ := adbd.RunCommand("blockdev --getsize64 /dev/block/sda")
block_size = strings.TrimRight(block_size, "\n") block_size = strings.TrimRight(block_size, "\n")
for _, cmd := range utils.GenRepartCommands(partpercent, block_size) { is128 := false
if r, _ := regexp.MatchString(`^125[0-9]{9}$`, block_size); r {
is128 = true
} else if r, _ := regexp.MatchString(`^253[0-9]{9}$`, block_size); r {
is128 = false
}
for _, cmd := range utils.GenRepartCommands(partpercent, is128) {
adbd.RunCommand(cmd) adbd.RunCommand(cmd)
logger.Debug("Executed command", logger.Args("cmd", cmd)) logger.Debug("Executed command", logger.Args("cmd", cmd))
} }
@ -293,24 +281,7 @@ var deployCmd = &cobra.Command{
for i := 0; i <= 120; i++ { for i := 0; i <= 120; i++ {
if i == 120 { if i == 120 {
ofoxSpinner.Stop() ofoxSpinner.Stop()
logger.Warn("Recovery device timeout") logger.Error("Recovery device timeout")
logger.Info("Trying to restart adb server")
err := adbc.KillServer();
if err != nil {
logger.Error("Failed to kill server")
os.Exit(173);
}
err = adbc.StartServer();
if err != nil {
logger.Error("Failed to start server")
os.Exit(173);
}
adbd = adbc.Device(adb.DeviceWithSerial(serail));
if s, _ := adbd.State(); s == adb.StateRecovery {
logger.Info("Device found")
break
}
logger.Error("Device not found")
os.Exit(173) os.Exit(173)
} }
if s, _ := adbd.State(); s == adb.StateRecovery { if s, _ := adbd.State(); s == adb.StateRecovery {
@ -320,16 +291,15 @@ var deployCmd = &cobra.Command{
time.Sleep(time.Second) time.Sleep(time.Second)
} }
port, err := utils.GetFreePort() port, err := utils.GetFreePort()
if err != nil { if err != nil {
logger.Error("Failled to find free tcp port") logger.Error("Failled to find free tcp port")
os.Exit(181) os.Exit(181)
} }
logger.Debug("Flasher started", logger.Args("port", port)) logger.Debug("Flasher", logger.Args("port", port))
forwards, _ := adbd.ListForwards()
adbd.Forward(pterm.Sprintf("tcp:%v", port), "tcp:4444") adbd.Forward(pterm.Sprintf("tcp:%v", port), "tcp:4444")
logger.Debug("Forward started", logger.Args("forwards", forwards)) logger.Debug("ListForwards", logger.Args(adbd.ListForwards()))
doneChan1 := make(chan bool) doneChan1 := make(chan bool)
doneChan2 := make(chan bool) doneChan2 := make(chan bool)
go func() { go func() {
@ -342,7 +312,7 @@ var deployCmd = &cobra.Command{
go func() { go func() {
conn, err := net.Dial("tcp", pterm.Sprintf("127.0.0.1:%v", port)) conn, err := net.Dial("tcp", pterm.Sprintf("127.0.0.1:%v", port))
if err != nil { if err != nil {
logger.Fatal("Failled to connect to device") logger.Error("Failled to connect to device")
} }
buf := make([]byte, 409600) buf := make([]byte, 409600)
bar, _ := pbar.WithTotal(int(image.ImgSize)).WithTitle("Flashing rootfs").WithRemoveWhenDone(false).Start() bar, _ := pbar.WithTotal(int(image.ImgSize)).WithTitle("Flashing rootfs").WithRemoveWhenDone(false).Start()
@ -373,23 +343,17 @@ var deployCmd = &cobra.Command{
<-doneChan2 <-doneChan2
adbd.KillForwardAll() adbd.KillForwardAll()
pi_cmd := pterm.Sprintf("postinstall \"%s\" \"%s\" > /dev/null 2>&1; echo $?", username, strings.ReplaceAll(password, "\"", "\\\"")) out, err := adbd.RunCommand(pterm.Sprintf("postinstall %s %s > /dev/null 2>&1; echo $?", username, password))
out, err := adbd.RunCommand(pi_cmd)
out = strings.TrimRight(out, "\n") out = strings.TrimRight(out, "\n")
logger.Debug("Postinstall", logger.Args("cmd", pi_cmd, "out", out, "err", err)) logger.Debug("Postinstall", logger.Args("out", out, "err", err))
if out != "0" || err != nil { if out != "0" || err != nil {
logger.Error("Postinstall failed. Reflash stock rom and try again", logger.Args("Device error", out, "Go error", err)) logger.Error("Postinstall failed. Reflash stock rom and try again", logger.Args("Device error", out, "Go error", err))
} else { } else {
logger.Info("System cofigured") logger.Info("System cofigured")
} }
var uefi_out string
if nosimpleinit {
logger.Info("-Q flag present. Skipping simpleinit install")
uefi_out = "0"
} else {
adbd.RunCommand("mkdir /tmp/uefi-install") adbd.RunCommand("mkdir /tmp/uefi-install")
uploadBar, _ := pbar.WithTotal(2).WithTitle("Uploading uefi files").Start()
bootshim, err := utils.Files.UEFIBootshim.Get(*pbar.WithTitle("Downloading uefi bootshim")) bootshim, err := utils.Files.UEFIBootshim.Get(*pbar.WithTitle("Downloading uefi bootshim"))
if err != nil { if err != nil {
@ -403,13 +367,16 @@ var deployCmd = &cobra.Command{
conn, err := adbd.OpenWrite(pterm.Sprintf("/tmp/uefi-install/%s", utils.Files.UEFIBootshim.Name), fs.FileMode(0777), adb.MtimeOfClose) conn, err := adbd.OpenWrite(pterm.Sprintf("/tmp/uefi-install/%s", utils.Files.UEFIBootshim.Name), fs.FileMode(0777), adb.MtimeOfClose)
if err != nil { if err != nil {
uploadBar.Stop()
logger.Error("Failed to send uefi bootshim", logger.Args("Error", err)) logger.Error("Failed to send uefi bootshim", logger.Args("Error", err))
} }
_, err = conn.Write(bootshim) _, err = conn.Write(bootshim)
if err != nil { if err != nil {
uploadBar.Stop()
logger.Error("Failed to send uefi bootshim", logger.Args("Error", err)) logger.Error("Failed to send uefi bootshim", logger.Args("Error", err))
} }
conn.Close() conn.Close()
uploadBar.Add(1)
payload, err := utils.Files.UEFIPayload.Get(*pbar.WithTitle("Downloading uefi payload")) payload, err := utils.Files.UEFIPayload.Get(*pbar.WithTitle("Downloading uefi payload"))
if err != nil { if err != nil {
@ -422,35 +389,40 @@ var deployCmd = &cobra.Command{
} }
conn, err = adbd.OpenWrite(pterm.Sprintf("/tmp/uefi-install/%s", utils.Files.UEFIPayload.Name), fs.FileMode(0777), adb.MtimeOfClose) conn, err = adbd.OpenWrite(pterm.Sprintf("/tmp/uefi-install/%s", utils.Files.UEFIPayload.Name), fs.FileMode(0777), adb.MtimeOfClose)
if err != nil { if err != nil {
uploadBar.Stop()
logger.Error("Failed to send uefi payload", logger.Args("Error", err)) logger.Error("Failed to send uefi payload", logger.Args("Error", err))
} }
_, err = conn.Write(payload) _, err = conn.Write(payload)
if err != nil { if err != nil {
uploadBar.Stop()
logger.Error("Failed to send uefi payload", logger.Args("Error", err)) logger.Error("Failed to send uefi payload", logger.Args("Error", err))
} }
conn.Close() conn.Close()
uploadBar.Add(1)
uefiSpinner, _ := spinner.Start("Patching UEFI") uefiSpinner, _ := spinner.Start("Patching UEFI")
uefi_out, err = adbd.RunCommand("uefi-patch > /dev/null 2>&1; echo $?") out, err = adbd.RunCommand("uefi-patch > /dev/null 2>&1; echo $?")
out = strings.TrimRight(out, "\n")
if err != nil { if err != nil {
logger.Error("Failed to install uefi. Reflash stock rom and try again", logger.Args("Error", err)) logger.Error("Failed to install uefi. Reflash stock rom and try again", logger.Args("Error", err))
os.Exit(176) os.Exit(176)
} }
uefi_out = strings.TrimRight(uefi_out, "\n")
logger.Debug("Uefi patch", logger.Args("Out", out)) logger.Debug("Uefi patch", logger.Args("Out", out))
uefiSpinner.Stop()
}
switch uefi_out { switch out {
case "1": case "1":
uefiSpinner.Stop()
logger.Error("Failed to install uefi. Reflash stock rom and try again", logger.Args("Error", err)) logger.Error("Failed to install uefi. Reflash stock rom and try again", logger.Args("Error", err))
adbd.RunCommand("reboot bootloader") adbd.RunCommand("reboot bootloader")
os.Exit(176) os.Exit(176)
case "2": case "2":
adbd.RunCommand("reboot") adbd.RunCommand("reboot")
uefiSpinner.Stop()
logger.Info("Bootimage already patched") logger.Info("Bootimage already patched")
case "0": case "0":
adbd.RunCommand("reboot") adbd.RunCommand("reboot")
uefiSpinner.Stop()
logger.Info("Installation done!") logger.Info("Installation done!")
} }
}, },
@ -462,5 +434,4 @@ func init() {
deployCmd.Flags().StringVarP(&password, "password", "p", "", "User password") deployCmd.Flags().StringVarP(&password, "password", "p", "", "User password")
deployCmd.Flags().StringVarP(&serail, "serial", "s", "autodetect", "Device serial") deployCmd.Flags().StringVarP(&serail, "serial", "s", "autodetect", "Device serial")
deployCmd.Flags().StringVarP(&partsize, "part-size", "S", "", "Linux partition size in percents") deployCmd.Flags().StringVarP(&partsize, "part-size", "S", "", "Linux partition size in percents")
deployCmd.Flags().BoolVarP(&nosimpleinit, "no-simple-init", "Q", false, "Disable simple init install")
} }

View file

@ -3,7 +3,7 @@ package cmd
import ( import (
"io" "io"
"os" "os"
"git.timoxa0.su/timoxa0/lon-tool/image" "lon-tool/image"
"github.com/codingsince1985/checksum" "github.com/codingsince1985/checksum"
"github.com/pterm/pterm" "github.com/pterm/pterm"

View file

@ -49,14 +49,14 @@ var rootCmd = &cobra.Command{
WithShowElapsedTime(false). WithShowElapsedTime(false).
WithRemoveWhenDone(false). WithRemoveWhenDone(false).
WithShowCount(false). WithShowCount(false).
WithBarFiller(pbarFillStyle.Sprint("")). WithBarFiller(pbarFillStyle.Sprint("")).
WithLastCharacter(""). WithLastCharacter("").
WithBarCharacter(""). WithBarCharacter("").
WithTitleStyle(pbarTitleStyle). WithTitleStyle(pbarTitleStyle).
WithBarStyle(pbarStyle) WithBarStyle(pbarStyle)
spinner = *pterm.DefaultSpinner. spinner = *pterm.DefaultSpinner.
WithRemoveWhenDone(true). WithRemoveWhenDone(true).
WithSequence("", "\\", "|", "/"). WithSequence("-", "\\", "|", "/").
WithStyle(pbarTitleStyle). WithStyle(pbarTitleStyle).
WithDelay(time.Millisecond * 100) WithDelay(time.Millisecond * 100)
}, },
@ -70,5 +70,5 @@ func Execute() {
} }
func init() { func init() {
rootCmd.PersistentFlags().BoolVarP(&verbose, "verbose", "V", false, "enable debug output") rootCmd.PersistentFlags().BoolVarP(&verbose, "verbose", "V", false, "Enabled verbose output")
} }

View file

@ -1,7 +1,7 @@
package cmd package cmd
import ( import (
"git.timoxa0.su/timoxa0/lon-tool/utils" "lon-tool/utils"
"os" "os"
"github.com/pterm/pterm" "github.com/pterm/pterm"

2
go.mod
View file

@ -1,4 +1,4 @@
module git.timoxa0.su/timoxa0/lon-tool module lon-tool
go 1.22.4 go 1.22.4

View file

@ -1,28 +0,0 @@
#!/usr/bin/env bash
command -v go >/dev/null 2>&1 || {
printf "\e[33mGo is required but not installed\e[0m\n" >&2
rnm=1
}
command -v git >/dev/null 2>&1 || {
printf "\e[33mGit is required but not installed\e[0m\n" >&2
rnm=1
}
[[ "$rnm" == "1" ]] && exit 1
[ -d "$HOME/.local/bin" ] && {
mkdir --parent "$HOME/.local/bin"
}
[ -d ~/.lon-tool-src ] && rm ~/.lon-tool-src -rf
git clone https://git.timoxa0.su/timoxa0/lon-tool.git ~/.lon-tool-src || {
rm ~/.lon-tool-src -rf
exit 2
}
pushd ~/.lon-tool-src &> /dev/null
rev=$(git describe --abbrev=4 --dirty --always --tags)
go get git.timoxa0.su/timoxa0/lon-tool/cmd
go build -ldflags "-X git.timoxa0.su/timoxa0/lon-tool/cmd.version=$rev" -o "$HOME/.local/bin/lon-tool" main.go && {
printf "\e[32mDone!\e[0m Installed at %s\n" "$HOME/.local/bin/lon-tool"
}
popd &> /dev/null

View file

@ -1,21 +0,0 @@
#!/usr/bin/env bash
URL="https://git.timoxa0.su/timoxa0/lon-tool/releases/download/latest/lon-tool_lin_amd64"
[[ "$(uname -m)" != "x86_64*" ]] || {
printf "Unsupported CPU arch\n"
exit 1
}
[ -d "$HOME/.local/bin" ] || {
mkdir --parent "$HOME/.local/bin"
}
printf "Downloading lon-tool\n"
curl "$URL" -o "$HOME/.local/bin/lon-tool" -#
chmod +x "$HOME/.local/bin/lon-tool"
command -v adb >/dev/null 2>&1 || {
printf "\e[33mWARNING: adb binary not found.\e[0m\nPlease install google platform tools using your package manager\n" >&2
}
printf "\e[32mDone!\e[0m Installed at %s\n" "$HOME/.local/bin/lon-tool"

View file

@ -1,193 +0,0 @@
$url="https://git.timoxa0.su/timoxa0/lon-tool/releases/download/latest/lon-tool_win_amd64.exe"
$bin_dir = Join-Path $env:USERPROFILE ".bin"
$platform_tools_url = "https://dl.google.com/android/repository/platform-tools-latest-windows.zip"
$platform_tools_dir = Join-Path $bin_dir "platform_tools"
function Get-FileFromWeb {
param (
# Parameter help description
[Parameter(Mandatory)]
[string]$URL,
# Parameter help description
[Parameter(Mandatory)]
[string]$File
)
Begin {
function Show-Progress {
param (
# Enter total value
[Parameter(Mandatory)]
[Single]$TotalValue,
# Enter current value
[Parameter(Mandatory)]
[Single]$CurrentValue,
# Enter custom progresstext
[Parameter(Mandatory)]
[string]$ProgressText,
# Enter value suffix
[Parameter()]
[string]$ValueSuffix,
# Enter bar lengh suffix
[Parameter()]
[int]$BarSize = 40,
# show complete bar
[Parameter()]
[switch]$Complete
)
# calc %
$percent = $CurrentValue / $TotalValue
$percentComplete = $percent * 100
if ($ValueSuffix) {
$ValueSuffix = " $ValueSuffix" # add space in front
}
if ($psISE) {
Write-Progress "$ProgressText $CurrentValue$ValueSuffix of $TotalValue$ValueSuffix" -id 0 -percentComplete $percentComplete
}
else {
# build progressbar with string function
$curBarSize = $BarSize * $percent
$progbar = ""
$progbar = $progbar.PadRight($curBarSize,[char]9608)
$progbar = $progbar.PadRight($BarSize,[char]9617)
if (!$Complete.IsPresent) {
Write-Host -NoNewLine "`r$ProgressText $progbar [ $($CurrentValue.ToString("#.###").PadLeft($TotalValue.ToString("#.###").Length))$ValueSuffix / $($TotalValue.ToString("#.###"))$ValueSuffix ] $($percentComplete.ToString("##0.00").PadLeft(6)) % complete"
}
else {
Write-Host -NoNewLine "`r$ProgressText $progbar [ $($TotalValue.ToString("#.###").PadLeft($TotalValue.ToString("#.###").Length))$ValueSuffix / $($TotalValue.ToString("#.###"))$ValueSuffix ] $($percentComplete.ToString("##0.00").PadLeft(6)) % complete"
}
}
}
}
Process {
try {
$storeEAP = $ErrorActionPreference
$ErrorActionPreference = 'Stop'
# invoke request
$request = [System.Net.HttpWebRequest]::Create($URL)
$response = $request.GetResponse()
if ($response.StatusCode -eq 401 -or $response.StatusCode -eq 403 -or $response.StatusCode -eq 404) {
throw "Remote file either doesn't exist, is unauthorized, or is forbidden for '$URL'."
}
if($File -match '^\.\\') {
$File = Join-Path (Get-Location -PSProvider "FileSystem") ($File -Split '^\.')[1]
}
if($File -and !(Split-Path $File)) {
$File = Join-Path (Get-Location -PSProvider "FileSystem") $File
}
if ($File) {
$fileDirectory = $([System.IO.Path]::GetDirectoryName($File))
if (!(Test-Path($fileDirectory))) {
[System.IO.Directory]::CreateDirectory($fileDirectory) | Out-Null
}
}
[long]$fullSize = $response.ContentLength
$fullSizeMB = $fullSize / 1024 / 1024
# define buffer
[byte[]]$buffer = new-object byte[] 1048576
[long]$total = [long]$count = 0
# create reader / writer
$reader = $response.GetResponseStream()
$writer = new-object System.IO.FileStream $File, "Create"
# start download
$finalBarCount = 0 #show final bar only one time
do {
$count = $reader.Read($buffer, 0, $buffer.Length)
$writer.Write($buffer, 0, $count)
$total += $count
$totalMB = $total / 1024 / 1024
if ($fullSize -gt 0) {
Show-Progress -TotalValue $fullSizeMB -CurrentValue $totalMB -ProgressText "Downloading $($File.Name)" -ValueSuffix "MB"
}
if ($total -eq $fullSize -and $count -eq 0 -and $finalBarCount -eq 0) {
Show-Progress -TotalValue $fullSizeMB -CurrentValue $totalMB -ProgressText "Downloading $($File.Name)" -ValueSuffix "MB" -Complete
$finalBarCount++
#Write-Host "$finalBarCount"
}
} while ($count -gt 0)
}
catch {
$ExeptionMsg = $_.Exception.Message
Write-Host "Download breaks with error : $ExeptionMsg"
}
finally {
# cleanup
if ($reader) { $reader.Close() }
if ($writer) { $writer.Flush(); $writer.Close() }
$ErrorActionPreference = $storeEAP
[GC]::Collect()
}
}
}
function Install-Tool {
if (-not (Test-Path $bin_dir -PathType Container)) {
New-Item -Path $bin_dir -ItemType Directory | Out-Null
}
$currentPath = [Environment]::GetEnvironmentVariable("PATH", "User") -split ";"
if ($currentPath -notcontains $bin_dir) {
[Environment]::SetEnvironmentVariable("PATH", "$env:PATH;$bin_dir", "User")
$env:PATH="$env:PATH;$bin_dir"
Write-Host "$bin_dir added to PATH."
}
Get-FileFromWeb "$url" (Join-Path $bin_dir "lon-tool.exe")
Write-Host
}
function Install-Platoform_tools {
if (-not (Test-Path $platform_tools_dir -PathType Container)) {
New-Item -Path $platform_tools_dir -ItemType Directory | Out-Null
}
$currentPath = [Environment]::GetEnvironmentVariable("PATH", "User") -split ";"
if ($currentPath -notcontains $platform_tools_dir) {
[Environment]::SetEnvironmentVariable("PATH", "$env:PATH;$platform_tools_dir", "User")
$env:PATH="$env:PATH;$platform_tools_dir"
Write-Host "$platform_tools_dir added to PATH."
}
Get-FileFromWeb "$platform_tools_url" (Join-Path $platform_tools_dir "tools.zip")
Write-Host
Expand-Archive -Path (Join-Path $platform_tools_dir "tools.zip") -DestinationPath $platform_tools_dir
Move-Item (Join-Path $platform_tools_dir "platform-tools\*") $platform_tools_dir
Remove-Item (Join-Path $platform_tools_dir "platform-tools\*")
}
Install-Tool
if (-not (Get-Command "adb.exe" -ErrorAction SilentlyContinue)) {
$decision = $Host.UI.PromptForChoice("Adb executable not found in PATH", "Do you wand to install android platform tools?", ("&Yes", "&No"), 1)
if ($decision -eq 0) {
Install-Platoform_tools
}
}
Write-Host "Done!" -ForegroundColor Green

View file

@ -16,7 +16,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
package main package main
import "git.timoxa0.su/timoxa0/lon-tool/cmd" import "lon-tool/cmd"
func main() { func main() {
cmd.Execute() cmd.Execute()

View file

@ -4,17 +4,14 @@ import (
"fmt" "fmt"
"math" "math"
"net" "net"
"regexp"
) )
func GenRepartCommands(percent int, blocksize string) []string { func GenRepartCommands(percent int, is128 bool) []string {
var maxsize uint16 var maxsize uint8
if r, _ := regexp.MatchString(`^125[0-9]{9}$`, blocksize); r { if is128 {
maxsize = 126 maxsize = 126
} else if r, _ := regexp.MatchString(`^253[0-9]{9}$`, blocksize); r { } else {
maxsize = 254 maxsize = 254
} else if r, _ := regexp.MatchString(`^509[0-9]{9}$`, blocksize); r {
maxsize = 509
} }
linux_max := maxsize - 12 linux_max := maxsize - 12
size := math.Round(float64(linux_max)*float64(percent)) / 100 size := math.Round(float64(linux_max)*float64(percent)) / 100
@ -29,6 +26,7 @@ func GenRepartCommands(percent int, blocksize string) []string {
} }
} }
func GetFreePort() (int, error) { func GetFreePort() (int, error) {
listener, err := net.Listen("tcp", ":0") listener, err := net.Listen("tcp", ":0")
if err != nil { if err != nil {