-
Notifications
You must be signed in to change notification settings - Fork 1
/
utils.go
186 lines (160 loc) · 4.66 KB
/
utils.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
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
package main
import (
"fmt"
"io/ioutil"
"os"
"sync"
"github.com/cheggaaa/pb"
)
func readInput(fileName string, BlockSize int, stream *chan []byte, progressStream *chan int64, wg *sync.WaitGroup) {
// Defer waitgroup go-routine done before returning
defer wg.Done()
// Open input file
file, err := os.Open(fileName)
if err != nil {
panic(err.Error())
}
// Defer file close and panic if there is an error
defer func() {
if err := file.Close(); err != nil {
panic(err.Error())
}
}()
// Get file info
fileInfo, err := file.Stat()
if err != nil {
panic(err.Error())
}
// Get input file size
fileSize := fileInfo.Size()
// Push input file size as the first input to progress stream
*progressStream <- fileSize
// Initialize offset
offset := int64(0)
for {
if fileSize-offset >= int64(BlockSize) {
// Create full-block
block := make([]byte, BlockSize)
// Read from file at offset to full-block
// Panic if there are any errors
bytesRead, err := file.ReadAt(block, offset)
if err != nil {
panic(err.Error())
}
// PUSH full-block to buffered s channel
*stream <- block
// Increment offset by bytesRead
offset += int64(bytesRead)
// Push offset to buffered progress channel
*progressStream <- offset
} else if fileSize-offset == 0 {
// Exit condition - the entire file is read, exit
// Send nil to stream to signal end of input
// Break out of loop
*stream <- nil
break
} else {
// Create partial block
block := make([]byte, fileSize-offset)
// Read from file at offset to part-block
// Panic if there are any errors
bytesRead, err := file.ReadAt(block, offset)
if err != nil {
panic(err.Error())
}
// PUSH partial-block to channel
*stream <- block
// Increment offset by bytesRead
offset += int64(bytesRead)
// Push offset to buffered progress channel
*progressStream <- offset
}
}
}
func writeOutput(fileName string, stream *chan []byte, wg *sync.WaitGroup) {
// Defer waitgroup go-routine done before returning
defer wg.Done()
// Create output file
file, err := os.Create(fileName)
if err != nil {
panic(err.Error())
}
// Defer file close and panic if there is an error
defer func() {
if err := file.Close(); err != nil {
panic(err.Error())
}
}()
// Initialize offset
offset := int64(0)
for {
// Read block from stream
block := <-*stream
// A nil block signals end, break out of loop
if block == nil {
// I WANT TO BREAK FREE
// FROM FOR LOOP
break
}
// Write block to file at offset
// Panic if there are any errors
bytesWritten, err := file.WriteAt(block, offset)
if err != nil {
panic(err.Error())
}
// Increment offset by bytesWritten
offset += int64(bytesWritten)
}
}
func progressBar(fileSize int64, progressStream *chan int64) {
// Create new progressbar with count
bar := pb.Start64(fileSize)
// Set template to full so we get remaining time
bar.SetTemplate(pb.Full)
// Set bytes to true so we get nicely formatted output
bar.Set(pb.Bytes, true)
var offset int64
for offset < fileSize {
offset = <-*progressStream
// Set bar progress to current offset from the reader
bar.SetCurrent(offset)
}
bar.Finish()
}
func fileExists(filename string) bool {
info, err := os.Stat(filename)
if os.IsNotExist(err) {
return false
}
return !info.IsDir()
}
func readFromFile(filePath string) []byte {
// Check if file exists and if not, print
if fileExists(filePath) {
data, err := ioutil.ReadFile(filePath)
if err != nil {
panic(err.Error())
}
return data
}
// If file doesn't exist, print so and exit
fmt.Println("File:", filePath, "seems to be nonexistent")
os.Exit(1)
// Fun fact: if you remove the below return
// Compile will fail - as functions which return must
// return at the end, BUT... The above OS Exit makes it
// such that it'll never execute XD
return nil
}
func printHelp() {
// Ah, yes; help.
fmt.Printf("%s is a CLI program which implements the SeaLion Block Cipher (http://github.com/sid-sun/sealion) in CFB (cipher feedback) mode with 256-Bit key length, using SHA3-256.", os.Args[0])
fmt.Printf("\nDeveloped by Sidharth Soni (Sid Sun) <[email protected]>")
fmt.Printf("\nOpen-sourced under The Unlicense")
fmt.Printf("\nSource Code: http://github.com/sid-sun/seal-256-cfb\n")
fmt.Printf("\nUsage:\n")
fmt.Printf(" To encrypt: %s (--encrypt / -e) <input file> <passphrase file> <output file (optional)>\n", os.Args[0])
fmt.Printf(" To decrypt: %s (--decrypt / -d) <encrypted input> <passphrase file> <output file (optional)>\n", os.Args[0])
fmt.Printf(" To get version number: %s (--version / -v)\n", os.Args[0])
fmt.Printf(" To get help: %s (--help / -h)\n", os.Args[0])
}