func fetchList(client *winrm.Client, remotePath string) ([]FileItem, error) { script := fmt.Sprintf("Get-ChildItem %s", remotePath) stdout, stderr, _, err := client.RunWithString("powershell -Command \""+script+" | ConvertTo-Xml -NoTypeInformation -As String\"", "") if err != nil { return nil, errors.New(fmt.Sprintf("Couldn't execute script %s: %v", script, err)) } if stderr != "" { if os.Getenv("WINRMCP_DEBUG") != "" { log.Printf("STDERR returned: %s\n", stderr) } } if stdout != "" { doc := pslist{} err := xml.Unmarshal([]byte(stdout), &doc) if err != nil { return nil, errors.New(fmt.Sprintf("Couldn't parse results: %v", err)) } return convertFileItems(doc.Objects), nil } return []FileItem{}, nil }
func restoreContent(client *winrm.Client, fromPath, toPath string) error { shell, err := client.CreateShell() if err != nil { return err } defer shell.Close() script := fmt.Sprintf(` $tmp_file_path = [System.IO.Path]::GetFullPath("%s") $dest_file_path = [System.IO.Path]::GetFullPath("%s".Trim("'")) if (Test-Path $dest_file_path) { rm $dest_file_path } else { $dest_dir = ([System.IO.Path]::GetDirectoryName($dest_file_path)) New-Item -ItemType directory -Force -ErrorAction SilentlyContinue -Path $dest_dir | Out-Null } if (Test-Path $tmp_file_path) { $base64_lines = Get-Content $tmp_file_path $base64_string = [string]::join("",$base64_lines) $bytes = [System.Convert]::FromBase64String($base64_string) [System.IO.File]::WriteAllBytes($dest_file_path, $bytes) } else { echo $null > $dest_file_path } `, fromPath, toPath) cmd, err := shell.Execute(winrm.Powershell(script)) if err != nil { return err } defer cmd.Close() var wg sync.WaitGroup copyFunc := func(w io.Writer, r io.Reader) { defer wg.Done() io.Copy(w, r) } wg.Add(2) go copyFunc(os.Stdout, cmd.Stdout) go copyFunc(os.Stderr, cmd.Stderr) cmd.Wait() wg.Wait() if cmd.ExitCode() != 0 { return errors.New(fmt.Sprintf("restore operation returned code=%d", cmd.ExitCode())) } return nil }
func cleanupContent(client *winrm.Client, filePath string) error { shell, err := client.CreateShell() if err != nil { return err } defer shell.Close() cmd, _ := shell.Execute("powershell", "Remove-Item", filePath, "-ErrorAction SilentlyContinue") cmd.Wait() cmd.Close() return nil }
func uploadChunks(client *winrm.Client, filePath string, maxChunks int, reader io.Reader) (bool, error) { shell, err := client.CreateShell() if err != nil { return false, errors.New(fmt.Sprintf("Couldn't create shell: %v", err)) } defer shell.Close() // Upload the file in chunks to get around the Windows command line size limit. // Base64 encodes each set of three bytes into four bytes. In addition the output // is padded to always be a multiple of four. // // ceil(n / 3) * 4 = m1 - m2 // // where: // n = bytes // m1 = max (8192 character command limit.) // m2 = len(filePath) chunkSize := ((8000 - len(filePath)) / 4) * 3 chunk := make([]byte, chunkSize) if maxChunks == 0 { maxChunks = 1 } for i := 0; i < maxChunks; i++ { n, err := reader.Read(chunk) if err != nil && err != io.EOF { return false, err } if n == 0 { return true, nil } content := base64.StdEncoding.EncodeToString(chunk[:n]) if err = appendContent(shell, filePath, content); err != nil { return false, err } } return false, nil }