Skip to content

Commit

Permalink
feat: add permission check for self-update (#9)
Browse files Browse the repository at this point in the history
  • Loading branch information
fioncat authored Aug 22, 2023
1 parent d74ffc6 commit 4a95666
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 21 deletions.
34 changes: 13 additions & 21 deletions command.go
Original file line number Diff line number Diff line change
Expand Up @@ -256,15 +256,15 @@ var UpdateCommand = &cobra.Command{

var err error
if targetVersion == "" {
fmt.Println("Checking new version for csync")
ExecInfo("Checking new version for csync")
targetVersion, err = GetLatestVersion()
if err != nil {
return fmt.Errorf("Get latest release from github: %w", err)
}
}

if Version == targetVersion {
fmt.Println("Your csync is up-to-date")
ExecInfo("Your csync is up-to-date")
return nil
}

Expand All @@ -278,14 +278,14 @@ var UpdateCommand = &cobra.Command{
tmpDir := os.TempDir()
tarPath := filepath.Join(tmpDir, "csync-update", "csync.tar.gz")
target := fmt.Sprintf("%s-%s", runtime.GOOS, runtime.GOARCH)
fmt.Printf("Downloading csync(version:%s, target:%s) to %s\n", targetVersion, target, tarPath)
ExecInfo("Downloading csync")
err = DownloadRelease(targetVersion, target, tarPath)
if err != nil {
return fmt.Errorf("Download github release: %w", err)
}

binPath := filepath.Join(tmpDir, "csync-update", "bin")
fmt.Printf("Untaring csync binary to %s\n", binPath)
ExecInfo("Untaring tar.gz")
err = UnTarTo(tarPath, binPath)
if err != nil {
return fmt.Errorf("Untar tar.gz file: %w", err)
Expand All @@ -297,30 +297,22 @@ var UpdateCommand = &cobra.Command{
return fmt.Errorf("Get current executable file: %w", err)
}

fmt.Printf("Replacing binary %s\n", currentBinPath)

// FIXME: Support windows
var buf bytes.Buffer
cmd := exec.Command("mv", binPath, currentBinPath)
cmd.Stdout = &buf
cmd.Stderr = &buf
err = cmd.Run()
ExecInfo("Replacing binary")
err = ReplaceBinary(currentBinPath, binPath)
if err != nil {
return fmt.Errorf("Move binary file error: %s", buf.String())
}

fmt.Printf("Update csync to %s done\n", targetVersion)

toRemoveDir := filepath.Join(tmpDir, "csync-update")
err = os.RemoveAll(toRemoveDir)
if err != nil {
return fmt.Errorf("Remove update tmp dir: %w", err)
return fmt.Errorf("Replace binary: %w", err)
}

return nil
},
}

func ExecInfo(msg string, args ...any) {
msg = fmt.Sprintf(msg, args...)
attr := color.New(color.FgCyan, color.Bold)
fmt.Printf("%s %s\n", attr.Sprint("==>"), msg)
}

func init() {
SendCommand.PersistentFlags().StringVarP(&sendFilename, "file", "f", "", "Read text file to send")
SendCommand.PersistentFlags().StringVarP(&sendImage, "image", "i", "", "Read image file to send")
Expand Down
36 changes: 36 additions & 0 deletions self_update.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"io"
"net/http"
"os"
"os/exec"
"path/filepath"
"time"
)
Expand Down Expand Up @@ -154,3 +155,38 @@ func UnTarTo(src, dst string) error {
}
}
}

func ReplaceBinary(dstPath, srcPath string) error {
// TODO: support Windows system
dstDir := filepath.Dir(dstPath)

testPath := filepath.Join(dstDir, "test.txt")
checkPermissionCmd := exec.Command("touch", testPath)

err := checkPermissionCmd.Run()
requirePermission := err != nil
if !requirePermission {
err = os.Remove(testPath)
if err != nil {
return fmt.Errorf("Remove tmp test file: %w", err)
}
}

var mvCmd *exec.Cmd
if requirePermission {
ExecInfo("Escalated permissions are required, please input sudo password")
mvCmd = exec.Command("sudo", "mv", srcPath, dstPath)
} else {
mvCmd = exec.Command("mv", srcPath, dstPath)
}
mvCmd.Stdout = os.Stdout
mvCmd.Stderr = os.Stderr
mvCmd.Stdin = os.Stdin

err = mvCmd.Run()
if err != nil {
return fmt.Errorf("Execute mv command: %w", err)
}

return nil
}

0 comments on commit 4a95666

Please sign in to comment.