Initial commit
This commit is contained in:
commit
959a7c3cfb
105
.gitignore
vendored
Normal file
105
.gitignore
vendored
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
# File created using '.gitignore Generator' for Visual Studio Code: https://bit.ly/vscode-gig
|
||||||
|
|
||||||
|
# Created by https://www.gitignore.io/api/macos,visualstudiocode,terraform,windows
|
||||||
|
# Edit at https://www.gitignore.io/?templates=macos,visualstudiocode,terraform,windows
|
||||||
|
|
||||||
|
### macOS ###
|
||||||
|
# General
|
||||||
|
.DS_Store
|
||||||
|
.AppleDouble
|
||||||
|
.LSOverride
|
||||||
|
|
||||||
|
# Icon must end with two \r
|
||||||
|
Icon
|
||||||
|
|
||||||
|
# Thumbnails
|
||||||
|
._*
|
||||||
|
|
||||||
|
# Files that might appear in the root of a volume
|
||||||
|
.DocumentRevisions-V100
|
||||||
|
.fseventsd
|
||||||
|
.Spotlight-V100
|
||||||
|
.TemporaryItems
|
||||||
|
.Trashes
|
||||||
|
.VolumeIcon.icns
|
||||||
|
.com.apple.timemachine.donotpresent
|
||||||
|
|
||||||
|
# Directories potentially created on remote AFP share
|
||||||
|
.AppleDB
|
||||||
|
.AppleDesktop
|
||||||
|
Network Trash Folder
|
||||||
|
Temporary Items
|
||||||
|
.apdisk
|
||||||
|
|
||||||
|
### Terraform ###
|
||||||
|
# Local .terraform directories
|
||||||
|
**/.terraform/*
|
||||||
|
|
||||||
|
# .tfstate files
|
||||||
|
*.tfstate
|
||||||
|
*.tfstate.*
|
||||||
|
*.plan
|
||||||
|
|
||||||
|
# Crash log files
|
||||||
|
crash.log
|
||||||
|
|
||||||
|
# Ignore any .tfvars files that are generated automatically for each Terraform run. Most
|
||||||
|
# .tfvars files are managed as part of configuration and so should be included in
|
||||||
|
# version control.
|
||||||
|
#
|
||||||
|
# example.tfvars
|
||||||
|
|
||||||
|
# Ignore override files as they are usually used to override resources locally and so
|
||||||
|
# are not checked in
|
||||||
|
override.tf
|
||||||
|
override.tf.json
|
||||||
|
*_override.tf
|
||||||
|
*_override.tf.json
|
||||||
|
secrets.tfvars
|
||||||
|
|
||||||
|
# Include override files you do wish to add to version control using negated pattern
|
||||||
|
#
|
||||||
|
# !example_override.tf
|
||||||
|
|
||||||
|
### VisualStudioCode ###
|
||||||
|
.vscode/*
|
||||||
|
#!.vscode/settings.json
|
||||||
|
#!.vscode/tasks.json
|
||||||
|
#!.vscode/launch.json
|
||||||
|
#!.vscode/extensions.json
|
||||||
|
|
||||||
|
### VisualStudioCode Patch ###
|
||||||
|
# Ignore all local history of files
|
||||||
|
.history
|
||||||
|
|
||||||
|
### Windows ###
|
||||||
|
# Windows thumbnail cache files
|
||||||
|
Thumbs.db
|
||||||
|
ehthumbs.db
|
||||||
|
ehthumbs_vista.db
|
||||||
|
|
||||||
|
# Dump file
|
||||||
|
*.stackdump
|
||||||
|
|
||||||
|
# Folder config file
|
||||||
|
[Dd]esktop.ini
|
||||||
|
|
||||||
|
# Recycle Bin used on file shares
|
||||||
|
$RECYCLE.BIN/
|
||||||
|
|
||||||
|
# Windows Installer files
|
||||||
|
*.cab
|
||||||
|
*.msi
|
||||||
|
*.msix
|
||||||
|
*.msm
|
||||||
|
*.msp
|
||||||
|
|
||||||
|
# Windows shortcuts
|
||||||
|
*.lnk
|
||||||
|
|
||||||
|
# End of https://www.gitignore.io/api/macos,visualstudiocode,terraform,windows
|
||||||
|
|
||||||
|
# Custom rules (everything added below won't be overriden by 'Generate .gitignore File' if you use 'Update' option)
|
||||||
|
.vscode/*
|
||||||
|
|
||||||
|
.idea
|
5
LICENSE.md
Normal file
5
LICENSE.md
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
"THE BEER-WARE LICENSE" (Revision 42)
|
||||||
|
|
||||||
|
<mitch@nerdfortress.dev> wrote this file. As long as you retain this notice you
|
||||||
|
can do whatever you want with this stuff. If we meet some day, and you think
|
||||||
|
this stuff is worth it, you can buy me a beer in return
|
20
Makefile
Normal file
20
Makefile
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
####################################################
|
||||||
|
# Build Application
|
||||||
|
####################################################
|
||||||
|
build:
|
||||||
|
go build -o diskutil
|
||||||
|
####################################################
|
||||||
|
# Perform nothing
|
||||||
|
####################################################
|
||||||
|
all:
|
||||||
|
@echo "Nothing to do."
|
||||||
|
####################################################
|
||||||
|
# help feature
|
||||||
|
####################################################
|
||||||
|
help:
|
||||||
|
@echo ''
|
||||||
|
@echo 'Usage: make [TARGET]'
|
||||||
|
@echo 'Targets:'
|
||||||
|
@echo ' build go build -o diskutil'
|
||||||
|
@echo ' all nothing to do'
|
||||||
|
@echo ''
|
22
README.md
Normal file
22
README.md
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
##DiskUtil
|
||||||
|
A simple program for various commonly used disk utilities
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
- go compiler
|
||||||
|
|
||||||
|
## Install
|
||||||
|
`mv diskutil /usr/local/bin/`
|
||||||
|
|
||||||
|
## Commands
|
||||||
|
### wipe [-bs int] [-dod enable/disable] target
|
||||||
|
-bs defaults to 1024
|
||||||
|
-dod: defaults to disabled
|
||||||
|
This feature will saturate a volume with random data 5 times before
|
||||||
|
overriding with 0's. Default behavior will just write 0's to the volume
|
||||||
|
### clone [-bs int] source target
|
||||||
|
-bs defaults to 1024
|
||||||
|
## sample usage
|
||||||
|
`diskutil wipe /dev/sda`
|
||||||
|
`diskutil wipe -dod=enabled /dev/sda`
|
||||||
|
`diskutil clone my_cool_iso.iso /dev/sdb`
|
||||||
|
`diskutil clone -bs=4096 my_cool_iso.iso /dev/sdb`
|
45
clone.go
Normal file
45
clone.go
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
|
* "THE BEER-WARE LICENSE" (Revision 42):
|
||||||
|
* <mitch@nerdfortress.dev> wrote this file. As long as you retain this notice you
|
||||||
|
* can do whatever you want with this stuff. If we meet some day, and you think
|
||||||
|
* this stuff is worth it, you can buy me a beer in return
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
clone copies the contents of cloneSource to cloneTarget
|
||||||
|
@param cloneBs int is the block size used for the cloning
|
||||||
|
@param cloneSource string is the source file / volume for the clone
|
||||||
|
@param cloneTarget string is the target file / volume for the clone
|
||||||
|
*/
|
||||||
|
func clone(cloneBs int, cloneSource string, cloneTarget string) {
|
||||||
|
p := make([]byte, cloneBs)
|
||||||
|
fSource, err := os.Open(cloneSource)
|
||||||
|
defer fSource.Close()
|
||||||
|
errorHandler(err)
|
||||||
|
//todo add file not found handling
|
||||||
|
fTarget, err := os.OpenFile(cloneTarget, os.O_WRONLY, 0644)
|
||||||
|
defer fTarget.Close()
|
||||||
|
errorHandler(err)
|
||||||
|
//todo progress indicator
|
||||||
|
for {
|
||||||
|
n, err := fSource.Read(p)
|
||||||
|
if err == io.EOF {
|
||||||
|
_, err = fTarget.Write(p[:n])
|
||||||
|
errorHandler(err)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
errorHandler(err)
|
||||||
|
_, err = fTarget.Write(p[:n])
|
||||||
|
errorHandler(err)
|
||||||
|
}
|
||||||
|
fTarget.Sync()
|
||||||
|
}
|
59
main.go
Normal file
59
main.go
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
|
* "THE BEER-WARE LICENSE" (Revision 42):
|
||||||
|
* <mitch@nerdfortress.dev> wrote this file. As long as you retain this notice you
|
||||||
|
* can do whatever you want with this stuff. If we meet some day, and you think
|
||||||
|
* this stuff is worth it, you can buy me a beer in return
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
func errorHandler(e error) {
|
||||||
|
if e != nil {
|
||||||
|
panic(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
wipeCmd := flag.NewFlagSet("wipe", flag.ExitOnError)
|
||||||
|
wipeDod := wipeCmd.Bool("dod", false, "enable")
|
||||||
|
wipeBs := wipeCmd.Int("bs", 1024, "block size")
|
||||||
|
|
||||||
|
cloneCmd := flag.NewFlagSet("clone", flag.ExitOnError)
|
||||||
|
cloneBs := cloneCmd.Int("bs", 1024, "block size")
|
||||||
|
|
||||||
|
if len(os.Args) < 2 {
|
||||||
|
fmt.Println("Expected 'wipe' or 'clone' subcommands")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
switch os.Args[1] {
|
||||||
|
case "wipe":
|
||||||
|
wipeCmd.Parse(os.Args[2:])
|
||||||
|
if len(wipeCmd.Args()) > 1 {
|
||||||
|
fmt.Println("Only one volume to wipe is supported")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
wipeDisk := wipeCmd.Args()[0]
|
||||||
|
wipe(*wipeDod, *wipeBs, wipeDisk)
|
||||||
|
case "clone":
|
||||||
|
cloneCmd.Parse(os.Args[2:])
|
||||||
|
if len(cloneCmd.Args()) > 2 {
|
||||||
|
fmt.Println("Only one input and one output volume is supported")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
cloneSource := cloneCmd.Args()[0]
|
||||||
|
cloneTarget := cloneCmd.Args()[1]
|
||||||
|
clone(*cloneBs, cloneSource, cloneTarget)
|
||||||
|
default:
|
||||||
|
fmt.Println("Expected 'wipe' or 'clone' subcommands")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
112
wipe.go
Normal file
112
wipe.go
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
|
* "THE BEER-WARE LICENSE" (Revision 42):
|
||||||
|
* <mitch@nerdfortress.dev> wrote this file. As long as you retain this notice you
|
||||||
|
* can do whatever you want with this stuff. If we meet some day, and you think
|
||||||
|
* this stuff is worth it, you can buy me a beer in return
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/rand"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
wipe calls writeToDisk with correct arguments for dod wipe or wipe with zeros
|
||||||
|
@param wipeDod bool -- boolean for enable/disable random data over-write
|
||||||
|
@param blocksize int -- block size for each write iteration
|
||||||
|
@param wipeDisk string -- volume to wipe
|
||||||
|
*/
|
||||||
|
func wipe(wipeDod bool, blocksize int, wipeDisk string) {
|
||||||
|
if wipeDod {
|
||||||
|
for i := 0; i < 5; i++ {
|
||||||
|
fmt.Println("Starting wipe number", i+1, "at", time.Now())
|
||||||
|
writeToDisk(wipeDisk, blocksize, "random")
|
||||||
|
fmt.Println("Writing ones to disk at", time.Now())
|
||||||
|
writeToDisk(wipeDisk, blocksize, "one")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fmt.Println("Writing zeros to disk at", time.Now())
|
||||||
|
writeToDisk(wipeDisk, blocksize, "zero")
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
writeToDisk opens a reader / writer file handler then iterates through the reader blocks and writes them as it does
|
||||||
|
@param wipeDisk string is the string of the volume/file to wipe
|
||||||
|
@param blocksize int is the int of the block size
|
||||||
|
@param writetype string expects "one", or "zero" other values will return randomByte()
|
||||||
|
*/
|
||||||
|
func writeToDisk(wipeDisk string, blocksize int, writeType string) {
|
||||||
|
zero := buildZero(blocksize)
|
||||||
|
p := make([]byte, blocksize)
|
||||||
|
fTarget, err := os.OpenFile(wipeDisk, os.O_WRONLY, 0644)
|
||||||
|
defer fTarget.Close()
|
||||||
|
errorHandler(err)
|
||||||
|
fRead, err := os.Open(wipeDisk)
|
||||||
|
defer fRead.Close()
|
||||||
|
i := 0
|
||||||
|
for {
|
||||||
|
var block []byte
|
||||||
|
i++
|
||||||
|
n, err := fRead.Read(p)
|
||||||
|
if err == io.EOF {
|
||||||
|
_, err := fTarget.Write(zero[:n])
|
||||||
|
errorHandler(err)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
errorHandler(err)
|
||||||
|
if writeType == "zero" {
|
||||||
|
block = buildZero(blocksize)
|
||||||
|
} else if writeType == "one" {
|
||||||
|
block = buildOne(blocksize)
|
||||||
|
} else {
|
||||||
|
block = randomByte(blocksize)
|
||||||
|
}
|
||||||
|
_, err = fTarget.Write(block[:n])
|
||||||
|
}
|
||||||
|
fTarget.Sync()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
randomByte creates a []byte with random data
|
||||||
|
@param blocksize int -- size of the block to build
|
||||||
|
returns []byte containing random data
|
||||||
|
*/
|
||||||
|
func randomByte(blocksize int) []byte {
|
||||||
|
block := make([]byte, blocksize)
|
||||||
|
_, err := rand.Read(block)
|
||||||
|
errorHandler(err)
|
||||||
|
return block
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
buildZero creates []byte of 0
|
||||||
|
@param blocksize int -- size of the block to build
|
||||||
|
returns []byte of size blocksize containing {0..0}
|
||||||
|
*/
|
||||||
|
func buildZero(blocksize int) []byte {
|
||||||
|
block := make([]byte, blocksize)
|
||||||
|
for i := 0; i < blocksize; i++ {
|
||||||
|
block[i] = 0
|
||||||
|
}
|
||||||
|
return block
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
buildOne creates []byte of 1's
|
||||||
|
@param blocksize int -- size of block to build
|
||||||
|
returns []byte of size blocksize containing {0xff..0xff}
|
||||||
|
*/
|
||||||
|
func buildOne(blocksize int) []byte {
|
||||||
|
block := make([]byte, blocksize)
|
||||||
|
for i := 0; i < blocksize; i++ {
|
||||||
|
block[i] = 0xff
|
||||||
|
}
|
||||||
|
return block
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user