-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathunrar.go
149 lines (138 loc) · 3.66 KB
/
unrar.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
package main
import (
"bufio"
"fmt"
"io"
"os"
"os/exec"
"path/filepath"
"regexp"
"strconv"
"strings"
"time"
"github.com/schollz/progressbar/v3"
)
func unrar() error {
Log.Info("Starting unrar process")
var (
rarExitCodes map[int]string
parameters []string
cmdReader io.ReadCloser
scanner *bufio.Scanner
rarProgressBar *progressbar.ProgressBar
err error
)
// rar exit codes
rarExitCodes = map[int]string{
0: "Successful operation",
1: "Warning. Non fatal error(s) occurred",
2: "A fatal error occurred",
3: "Invalid checksum. Data is damaged",
4: "Attempt to modify a locked archive",
5: "Write error",
6: "File open error",
7: "Wrong command line option",
8: "Not enough memory",
9: "File create error",
10: "No files matching the specified mask and options were found",
11: "Wrong password",
255: "User break",
}
// check for rar files
hasRarFiles := false
exp, _ := regexp.Compile(`^.+\.rar`)
if err = filepath.Walk(conf.TempPath, func(file string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if !info.IsDir() && exp.MatchString(filepath.Base(info.Name())) {
hasRarFiles = true
}
return nil
}); err != nil {
checkForFatalErr(err)
}
if !hasRarFiles {
Log.Info("No rar files found. Skipping unrar.")
return nil
}
// set parameters
parameters = append(parameters, "x", "-o+")
if conf.Password != "" {
parameters = append(parameters, fmt.Sprintf("-p%v", conf.Password))
} else {
parameters = append(parameters, "-p-")
}
parameters = append(parameters, filepath.Join(conf.TempPath, "*.rar"))
parameters = append(parameters, conf.DestPath)
cmd := exec.Command(conf.RarExe, parameters...)
Log.Debug("Unrar command: %s", cmd.String())
if conf.Debug || conf.Verbose > 0 {
// create a pipe for the output of the program
if cmdReader, err = cmd.StdoutPipe(); err != nil {
return err
}
scanner = bufio.NewScanner(cmdReader)
go func() {
// progress bar
if conf.Verbose > 0 {
rarProgressBar = progressbar.NewOptions(int(100),
progressbar.OptionSetDescription("INFO: Extracting files "),
progressbar.OptionSetRenderBlankState(true),
progressbar.OptionThrottle(time.Millisecond*100),
progressbar.OptionShowElapsedTimeOnFinish(),
progressbar.OptionOnCompletion(newline),
)
}
for scanner.Scan() {
output := strings.Trim(scanner.Text(), " \r\n")
if conf.Debug {
if output != "" && !strings.Contains(output, "%") {
Log.Debug("RAR: %v", output)
}
}
if conf.Verbose > 0 {
exp := regexp.MustCompile(`0*(\d+)%`)
if output != "" && exp.MatchString(output) {
percentStr := exp.FindStringSubmatch(output)
percentInt, _ := strconv.Atoi(percentStr[1])
rarProgressBar.Set(percentInt)
}
}
}
}()
}
if err = cmd.Run(); err != nil {
if exitError, ok := err.(*exec.ExitError); ok && exitError.ExitCode() > 1 {
if rarProgressBar != nil {
rarProgressBar.Exit()
}
if errMsg, ok := rarExitCodes[exitError.ExitCode()]; ok {
return fmt.Errorf(errMsg)
} else {
return fmt.Errorf("Unknown error")
}
}
}
if rarProgressBar != nil {
rarProgressBar.Finish()
}
Log.Info("Unrar successful")
if conf.DeleteRar {
Log.Info("Deleting the rar files")
if err = filepath.Walk(conf.TempPath, func(file string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if !info.IsDir() && filepath.Ext(file) == ".rar" {
if err = os.Remove(file); err != nil {
Log.Warn("Unable to remove rar file \"%v\": %v", file, err)
}
}
return nil
}); err != nil {
checkForFatalErr(err)
}
}
return nil
}