Initial commit

This commit is contained in:
mitch 2021-12-31 01:32:24 -05:00
commit 959a7c3cfb
9 changed files with 371 additions and 0 deletions

105
.gitignore vendored Normal file
View 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
View 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
View 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
View 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
View 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()
}

BIN
diskutil Executable file

Binary file not shown.

3
go.mod Normal file
View File

@ -0,0 +1,3 @@
module diskutil
go 1.17

59
main.go Normal file
View 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
View 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
}