Introduction
Security engineers make use of Unix or Linux systems for the majority of their tasks. A popular feature with such systems is how everything is treated as a file. Files, processes, directories, sockets and even connected devices are treated as files. This holds true for virtually everything in the computer ecosystem. Consequently, a security engineer using Golang must be able to manage files effectively with the language. In this article, file management with Google’s Go Programming Language (Golang) is explained. The article expounds on the process of creating, truncating, deleting, opening, closing, renaming, and moving files comfortably in Golang. Accessing and manipulating file properties is also addressed in this article.
Creating New Files
Creating a new file is relatively easy on the terminal, but there may be need to directly transfer data collected to a file in-code. Similar to the touch
command in a Linux terminal, a new file can be created with Golang like this:
package main
import (
"log"
"os"
)
func main() {
cre8, err := os.Create("cre8.txt")
if err != nil {
log.Fatal(err)
}
log.Println(cre8)
cre8.Close()
}
One major feature that sets Go apart from other modern languages is its ability to handle possible errors during code time. This practices saves the Go developer from running into compiler errors every do often, from creating bugs, and guarantees the developer more productive time.
Truncating Files
File truncation means attenuating a file by restricting it to a preferred maximum size. If the file is smaller that the specified truncate limit, the os.Truncate
method will instead increase the file size to fit. Truncation is explained by code below in limiting a file.
package main
import (
"log"
"os")
func main() {
err := os.Truncate("cre8.txt", 100)
if err != nil {
log.Fatal(err)
}
}
The example code above truncates the file to a 100 byte file. If the file is below 100 bytes, the compiler writes enough lines of null bytes to the bottom of the file. If the file is above 100 bytes, the compiler trims away everything above the 100th bite.
Accessing File Properties
The os
package also has a Stat
method for fetching the attributes of a file. This may be it’s name, size, permissions, last modified time, and whether it is adirectory.
There is also the FileInfo.Sys()
interface which contains information about the source of the file. The file source is usually a file system on the harddisk.
package main
import (
"fmt"
"os"
"log"
)
func main() {
fileInfo, err := os.Stat("cre8.txt")
if err != nil {
log.Fatal(err)
}
fmt.Println("File name:", fileInfo.Name())
fmt.Println("Size in bytes:", fileInfo.Size())
fmt.Println("Permissions:", fileInfo.Mode())
fmt.Println("Last modified:", fileInfo.ModTime())
fmt.Println("Is Directory: ", fileInfo.IsDir())
fmt.Printf("System interface type: %T\n", fileInfo.Sys())
fmt.Printf("System info: %+v\n\n", fileInfo.Sys())
}
Opening and Closing Files
To open a file and/or close it, the os.Open()
and os.Close()
methods are used. To get more options and privileges after opening the file, the os.OpenFile()
method may be used instead. The code sample below shows how both are done in Go.
package main
import (
"log"
"os"
)
func main() {
file, err := os.Open("cre8.txt")
if err != nil {
log.Fatal(err)
}
file.Close()
file, err = os.OpenFile("cre8.txt", os.O_APPEND, 0666)
if err != nil {
log.Fatal(err)
}
file.Close()
}
Reading and Writing to Files
The owner of a file may find the need to change the ownership, timestamp, and permissions. To do so in Go, a number of functions exist in the os
package like
os.Chmod()
os.Chown()
os.Chtimes()
To practically understand their use case in Go, see the code sample below.
package main
import (
"log"
"os"
"time"
)
func main() {
err := os.Chmod("cre8.txt", 0777)
if err != nil {
log.Println(err)
}
err = os.Chown("cre8.txt", os.Getuid(), os.Getgid())
if err != nil {
log.Println(err)
}
// Change timestamps
twoDaysFromNow := time.Now().Add(48 * time.Hour)
lastAccessTime := twoDaysFromNow
lastModifyTime := twoDaysFromNow
err = os.Chtimes("cre8.txt", lastAccessTime, lastModifyTime)
if err != nil {
log.Println(err)
}
}
Renaming and Deleting Files
Renaming and moving file are synonymous terms in Go. As such, these operations are done with one method - os.Rename().
package main
import (
"log" "os"
)
func main() {
original := "cre8.txt"
new := "cre8ed.txt"
err := os.Rename(original, new)
if err != nil {
log.Fatal(err)
}
}
This also works for renaming or moving directories.
To delete files, the os.Remove()
method is used.
package main
import (
"log"
"os"
)
func main() {
err := os.Remove("test.txt")
if err != nil {
log.Fatal(err)
}
}
Archiving and Compressing Files
Archiving a file means saving it and other files into a folder and zipping it. Go’s archive package allows the programmer to either zip or far files. An example of the use-case is seen below.
package main
import (
"archive/zip"
"log"
"os"
)
func main() {
outFile, err := os.Create("cre8.zip")
if err != nil {
log.Fatal(err)
}
defer outFile.Close()
zipWriter := zip.NewWriter(outFile)
var filesToArchive = []struct {
Name, Body string
}{
{"test.txt", "String contents of file"},
{"test2.txt", "\x61\x62\x63\n"},
}
for _, file := range filesToArchive {
fileWriter, err := zipWriter.Create(file.Name)
if err != nil {
log.Fatal(err)
}
_, err = fileWriter.Write([]byte(file.Body))
if err != nil {
log.Fatal(err)
}
}
err = zipWriter.Close()
if err != nil {
log.Fatal(err)
}
}
To compress files, Go has several functions for several kinds of file formats. These are available in the compress
package in the standard documentation.
package main
import (
"compress/gzip"
"log"
"os"
)
func main() {
err := os.Create("cre8.txt.gz")
if err != nil {
log.Fatal(err)
}
gzipWriter := gzip.NewWriter(outputFile)
defer gzipWriter.Close()
_, err = gzipWriter.Write([]byte("Gophers rule!\n"))
if err != nil {
log.Fatal(err)
}
log.Println("Compressedbdata written to file.")
}
There are lots of other possible actions that can be achieved in file management with Golang. Reading through the standard library documentation for the os
and ioutil
packages would expose a lot of them.
A series of follow-up articles will be published on Security related practices.
My name is MacBobby Chibuzor and I am a Software Engineer and Technical Writer for Wevolver. I research and write about Blockchain, Security, Web Development, Data Structures and Algorithms, Machine Learning and IoT.