fs
packageAPI reference for the fs
package.
Imports
(13)IsMounted
IsMounted checks if the given source path is mounted in the given
destination path. It does so by reading the /proc/mounts file.
Parameters
Returns
func IsMounted(source string, destination string) (bool, error)
{
mounts, err := os.Open("/proc/mounts")
if err != nil {
return false, fmt.Errorf("error opening /proc/mounts: %w", err)
}
defer mounts.Close()
scanner := bufio.NewScanner(mounts)
for scanner.Scan() {
line := scanner.Text()
if strings.Contains(line, source) && strings.Contains(line, destination) {
return true, nil
}
}
return false, nil
}
Example
mounted, err := fs.IsMounted("tmpfs", "/tmp")
if err != nil {
fmt.Printf("Error checking if /tmp is mounted: %v", err)
return
}
fmt.Printf("/tmp is mounted: %v", mounted)
Mount
Mount mounts the given source path in the given destination path. It also
creates the destination path if it does not exist. An error is returned if
the source path does not exist.
Notes (for developers):
Avoid mapping the fsType into a custom type, as it would require further
maintenance once a new filesystem type is added to Vanilla OS.
Parameters
Returns
func Mount(source, destination, fsType, data string, mode uintptr) error
{
info, err := os.Stat(source)
if err != nil {
return err
}
if info.IsDir() {
_ = os.MkdirAll(destination, 0o755)
} else {
file, _ := os.Create(destination)
defer func() { _ = file.Close() }()
}
return syscall.Mount(source, destination, fsType, mode, data)
}
Example
err := fs.Mount("/dev/sda1", "/mnt", "ext4", "", syscall.MS_RDONLY)
if err != nil {
fmt.Printf("Error mounting /dev/sda1: %v", err)
return
}
MountBind
MountBind mounts bind the given source path in the given destination path.
Parameters
Returns
func MountBind(src, dest string) error
{
return Mount(
src,
dest,
"bind",
"",
syscall.MS_BIND|
syscall.MS_REC|
syscall.MS_RDONLY|
syscall.MS_NOSUID|
syscall.MS_NOEXEC|
syscall.MS_NODEV|
syscall.MS_PRIVATE,
)
}
Example
err := fs.MountBind("/bruce", "/batman")
if err != nil {
fmt.Printf("Error bind mounting /batman: %v", err)
return
}
Notes
This is just a wrapper of the Mount function, for convenience.
MountOverlay
MountOverlay mounts the given lower, upper and work directories in the
given destination path as an overlay filesystem.
Parameters
Returns
func MountOverlay(lowerDir, upperDir, workDir string) error
{
return Mount(
"overlay",
lowerDir,
"overlay",
fmt.Sprintf(
"lowerdir=%s,upperdir=%s,workdir=%s,userxattr",
lowerDir, upperDir, workDir,
),
0,
)
}
Example
err := fs.MountOverlay("/batman/lower", "/batman/upper", "/batman/work")
if err != nil {
fmt.Printf("Error overlay mounting /batman: %v", err)
return
}
Notes
This is just a wrapper of the Mount function, for convenience.
MountFuseOverlay
MountFuseOverlay mounts the given lower, upper and work directories in the
given destination path as an overlay filesystem using fuse-overlayfs.
Parameters
Returns
func MountFuseOverlay(targetDir, lowerDir, upperDir, workDir string) (err error)
{
// TODO: Replace the command-line tool with a Go library, if available.
c := exec.Command(
"fuse-overlayfs",
targetDir,
"-o",
fmt.Sprintf(
"lowerdir=%s,upperdir=%s,workdir=%s",
lowerDir, upperDir, workDir,
),
)
c.Stdout = os.Stdout
c.Stderr = os.Stderr
return c.Run()
}
Example
err := fs.MountFuseOverlay("/batman", "/batman/lower", "/batman/upper", "/batman/work")
if err != nil {
fmt.Printf("Error fuse-overlayfs mounting /batman: %v", err)
return
}
Notes
This implementation uses the fuse-overlayfs command-line tool, if that
is not available in the system, this function will return an error.
Unmount
Unmount unmounts the given path. An error is returned if the path is not
mounted.
Parameters
Returns
func Unmount(target string) error
{
return syscall.Unmount(target, 0)
}
Example
err := fs.Unmount("/mnt")
if err != nil {
fmt.Printf("Error unmounting /mnt: %v", err)
return
}
UnmountFuseOverlay
UnmountFuseOverlay unmounts the given path using the fuse-overlayfs command-
line tool. An error is returned if the path is not mounted.
Parameters
Returns
func UnmountFuseOverlay(targetDir string) (err error)
{
// TODO: Replace the command-line tool with a Go library, if available.
c := exec.Command("fusermount", "-u", targetDir)
c.Stdout = os.Stdout
c.Stderr = os.Stderr
return c.Run()
}
Example
err := fs.UnmountFuseOverlay("/batman")
if err != nil {
fmt.Printf("Error fuse-overlayfs unmounting /batman: %v", err)
return
}
Notes
This implementation uses the fuse-overlayfs command-line tool, if that
is not available in the system, this function will return an error.
AtomicSwap
AtomicSwap atomically swaps two files or directories
Parameters
Returns
func AtomicSwap(sourcePath, destinationPath string) error
{
orig, err := os.Open(sourcePath)
if err != nil {
return err
}
newfile, err := os.Open(destinationPath)
if err != nil {
return err
}
err = unix.Renameat2(int(orig.Fd()), sourcePath, int(newfile.Fd()), destinationPath, unix.RENAME_EXCHANGE)
if err != nil {
return err
}
return nil
}
Example
err := fs.AtomicSwap("/tmp/file1", "/tmp/file2")
if err != nil {
fmt.Printf("Error swapping files: %v", err)
return
}
GetFileDiff
GetFileDiff compares the content of two files and returns the changes
Parameters
Returns
func GetFileDiff(firstFile, secondFile string) (types.FileDiffInfo, error)
{
firstContent, err := os.ReadFile(firstFile)
if err != nil {
return types.FileDiffInfo{}, err
}
secondContent, err := os.ReadFile(secondFile)
if err != nil {
return types.FileDiffInfo{}, err
}
diff := types.FileDiffInfo{}
dmp := diffmatchpatch.New()
diffs := dmp.DiffMain(string(firstContent), string(secondContent), false)
for _, d := range diffs {
switch d.Type {
case diffmatchpatch.DiffInsert:
diff.AddedLines = append(diff.AddedLines, d.Text)
case diffmatchpatch.DiffDelete:
diff.RemovedLines = append(diff.RemovedLines, d.Text)
}
}
return diff, nil
}
Example
diff, err := fs.GetFileDiff("/tmp/batman", "/tmp/robin")
if err != nil {
fmt.Printf("Error getting file diff: %v", err)
return
}
fmt.Printf("Added lines: %v\n", diff.AddedLines)
fmt.Printf("Removed lines: %v\n", diff.RemovedLines)
GetDiskList
GetDiskList returns a list of disks on the system
Returns
func GetDiskList() ([]types.DiskInfo, error)
{
var disks []types.DiskInfo
files, err := os.ReadDir("/sys/class/block")
if err != nil {
return nil, err
}
diskMap := make(map[string]types.DiskInfo)
for _, file := range files {
name := file.Name()
if isPartition(name) {
continue
}
// Skip non-disk entries
if strings.HasPrefix(name, "loop") ||
strings.HasPrefix(name, "ram") ||
strings.HasPrefix(name, "zram") {
continue
}
diskPath := filepath.Join("/dev", name)
info, err := GetDiskInfo(diskPath)
if err != nil {
return nil, err
}
partitions, err := GetPartitionList(diskPath)
if err != nil {
return nil, err
}
diskInfo := types.DiskInfo{
BaseInfo: info,
Partitions: partitions,
}
diskMap[diskPath] = diskInfo
}
for _, disk := range diskMap {
disks = append(disks, disk)
}
return disks, nil
}
Example
disks, err := fs.GetDiskList()
if err != nil {
fmt.Printf("Error getting disk list: %v", err)
return
}
for _, disk := range disks {
fmt.Printf("Disk: %s\n", disk.Path)
fmt.Printf("Size: %d\n", disk.Size)
fmt.Printf("HumanSize: %s\n", disk.HumanSize)
for _, partition := range disk.Partitions {
fmt.Printf("Partition: %s\n", partition.Path)
fmt.Printf("Size: %d\n", partition.Size)
fmt.Printf("HumanSize: %s\n", partition.HumanSize)
fmt.Printf("Filesystem: %s\n", partition.Filesystem)
fmt.Printf("Mountpoint: %s\n", partition.Mountpoint)
fmt.Printf("Label: %s\n", partition.Label)
fmt.Printf("UUID: %s\n", partition.UUID)
fmt.Printf("PARTUUID: %s\n", partition.PARTUUID)
fmt.Printf("Flags: %v\n", partition.Flags)
}
}
GetPartitionList
GetPartitionList returns a list of disk partitions on the specified disk
Parameters
Returns
func GetPartitionList(diskPath string) ([]types.PartitionInfo, error)
{
var partitions []types.PartitionInfo
files, err := os.ReadDir(filepath.Join("/sys/class/block", filepath.Base(diskPath)))
if err != nil {
return nil, err
}
for _, file := range files {
name := file.Name()
// Skip non-partition entries
if !strings.HasPrefix(name, filepath.Base(diskPath)) {
continue
}
partitionPath := filepath.Join("/dev", name)
info, err := GetDiskInfo(partitionPath)
if err != nil {
return nil, err
}
partitionInfo := types.PartitionInfo{
BaseInfo: info,
}
partitions = append(partitions, partitionInfo)
}
return partitions, nil
}
Example
partitions, err := fs.GetPartitionList("/dev/sda")
if err != nil {
fmt.Printf("Error getting partition list: %v", err)
return
}
for _, partition := range partitions {
fmt.Printf("Partition: %s\n", partition.Path)
fmt.Printf("Size: %d\n", partition.Size)
fmt.Printf("HumanSize: %s\n", partition.HumanSize)
}
GetDiskInfo
GetDiskInfo returns information about a specific disk partition
Parameters
Returns
func GetDiskInfo(partitionPath string) (types.BaseInfo, error)
{
info := types.BaseInfo{
Path: partitionPath,
}
sizePath := filepath.Join("/sys/class/block", filepath.Base(partitionPath), "size")
size, err := os.ReadFile(sizePath)
if err != nil {
return info, err
}
sectorSize := 512
info.Size = int64(sectorSize) * int64(parseUint64(strings.TrimSpace(string(size))))
info.HumanSize = GetHumanSize(info.Size)
fsInfo := GetFilesystemInfo(partitionPath)
info.Filesystem = fsInfo["TYPE"]
info.Label = fsInfo["LABEL"]
info.UUID = fsInfo["UUID"]
info.PARTUUID = fsInfo["PARTUUID"]
return info, nil
}
Example
info, err := fs.GetDiskInfo("/dev/sda1")
if err != nil {
fmt.Printf("Error getting partition info: %v", err)
return
}
fmt.Printf("Path: %s\n", info.Path)
fmt.Printf("Size: %d\n", info.Size)
fmt.Printf("HumanSize: %s\n", info.HumanSize)
parseUint64
parseUint64 parses a string into a uint64 or returns 0 if parsing fails
Parameters
Returns
func parseUint64(s string) uint64
{
value, err := strconv.ParseUint(s, 10, 64)
if err != nil {
return 0
}
return value
}
GetHumanSize
GetHumanSize converts the size from bytes to a human-readable format.
For example, 1024 bytes would be converted to “1 kB”.
Parameters
Returns
func GetHumanSize(size int64) string
{
const (
kB = 1024.0
mB = kB * 1024.0
gB = mB * 1024.0
tB = gB * 1024.0
)
sizeFloat := float64(size)
switch {
case size < int64(kB):
return fmt.Sprintf("%d B", size)
case size < int64(mB):
return fmt.Sprintf("%.2f kB", sizeFloat/kB)
case size < int64(gB):
return fmt.Sprintf("%.2f MB", sizeFloat/mB)
case size < int64(tB):
return fmt.Sprintf("%.2f GB", sizeFloat/gB)
default:
return fmt.Sprintf("%.2f TB", sizeFloat/tB)
}
}
Example
fmt.Println(GetHumanSize(1024)) // 1 kB
isPartition
isPartition returns true if the specified block device is a partition
Parameters
Returns
func isPartition(deviceName string) bool
{
path := filepath.Join("/sys/class/block", deviceName, "partition")
info, err := os.Stat(path)
if err == nil && !info.IsDir() {
return true
}
return false
}
GetFilesystemInfo
GetFilesystemInfo returns information about the filesystem of a file or
partition by reading from /etc/mtab.
Parameters
Returns
func GetFilesystemInfo(path string) map[string]string
{
info := make(map[string]string)
u := udev.Udev{}
d := u.NewDeviceFromSyspath(filepath.Join("/sys/class/block", filepath.Base(path)))
info["LABEL"] = d.PropertyValue("ID_FS_LABEL")
info["TYPE"] = d.PropertyValue("ID_FS_TYPE")
info["UUID"] = d.PropertyValue("ID_FS_UUID")
info["PARTUUID"] = d.PropertyValue("ID_PART_ENTRY_UUID")
return info
}
GetFilesystemInfo
GetFilesystemInfo returns information about the filesystem of a file or
partition by reading from /etc/mtab.
Parameters
Returns
func GetFilesystemInfo(path string) map[string]string
{
return map[string]string{
"LABEL": "",
"TYPE": "",
"UUID": "",
"PARTUUID": "",
}
}
GetFileList
GetFileList returns a list of files in the specified directory.
If recursive is true, the function will recursively search for files, if
fullPaths is true, the full path of the file will be returned instead of
the relative path.
Parameters
Returns
func GetFileList(directory string, recursive, fullPaths bool) ([]types.FileInfo, error)
{
var fileList []types.FileInfo
walkFunc := func(path string, d fs.DirEntry, err error) error {
if err != nil {
return err
}
if !recursive && path != directory {
return fs.SkipDir
}
if d.IsDir() {
return nil
}
info, err := d.Info()
if err != nil {
return err
}
filePath := path
if !fullPaths {
filePath, _ = filepath.Rel(directory, path)
}
permissions := convertPermissions(info.Mode())
fileList = append(fileList, types.FileInfo{
Path: filePath,
ParentPath: filepath.Dir(filePath),
IsDirectory: false,
Size: info.Size(),
Permissions: permissions,
Extension: GetFileExtension(path),
})
return nil
}
if err := filepath.WalkDir(directory, walkFunc); err != nil {
return nil, err
}
return fileList, nil
}
Example
fileList, err := fs.GetFileList("/batmans/cave", true, false)
if err != nil {
fmt.Printf("Error: %v\n", err)
return
}
for _, file := range fileList {
fmt.Printf("Path: %s\n", file.Path)
fmt.Printf("Size: %d\n", file.Size)
fmt.Printf("Permissions: %s\n", file.Permissions.String())
fmt.Printf("Extension: %s\n", file.Extension)
}
convertPermissions
convertPermissions converts file mode to Permission type
Parameters
Returns
func convertPermissions(mode os.FileMode) types.Permission
{
return types.Permission{
OwnerRead: mode&0400 != 0,
OwnerWrite: mode&0200 != 0,
OwnerExecute: mode&0100 != 0,
GroupRead: mode&0040 != 0,
GroupWrite: mode&0020 != 0,
GroupExecute: mode&0010 != 0,
OthersRead: mode&0004 != 0,
OthersWrite: mode&0002 != 0,
OthersExecute: mode&0001 != 0,
}
}
GetFile
GetFile returns the file info of the specified file.
If fullPath is true, the full path of the file will be returned instead of
the relative path.
Parameters
Returns
func GetFile(filePath string, fullPath bool) (types.FileInfo, error)
{
info, err := os.Stat(filePath)
if err != nil {
return types.FileInfo{}, err
}
permissions := convertPermissions(info.Mode())
file := types.FileInfo{
Path: filePath,
ParentPath: filepath.Dir(filePath),
IsDirectory: info.IsDir(),
Size: info.Size(),
Permissions: permissions,
Extension: GetFileExtension(filePath),
}
if !fullPath {
file.Path, _ = filepath.Rel(".", filePath)
}
return file, nil
}
Example
file, err := fs.GetFile("/batmans/cave/batmobile.txt", false)
if err != nil {
fmt.Printf("Error: %v\n", err)
return
}
fmt.Printf("Path: %s\n", file.Path)
fmt.Printf("Size: %d\n", file.Size)
fmt.Printf("Permissions: %s\n", file.Permissions.String())
GetFileExtension
GetFileExtension returns the extension of the given file
Parameters
Returns
func GetFileExtension(filePath string) string
{
ext := filepath.Ext(filePath)
if ext != "" {
return strings.TrimPrefix(ext, ".")
}
return ""
}
Example
extension := fs.GetFileExtension("/batmans/cave/batmobile.txt")
fmt.Printf("Extension: %s\n", extension)
IsFile
IsFile checks whether the given path is a regular file
Parameters
Returns
func IsFile(filePath string) bool
{
info, err := os.Stat(filePath)
if err != nil {
return false
}
return info.Mode().IsRegular()
}
Example
if fs.IsFile("/batmans/cave/batmobile.txt") {
fmt.Println("It's a file!")
}
IsDirectory
IsDirectory checks whether the given path is a directory
Parameters
Returns
func IsDirectory(dirPath string) bool
{
info, err := os.Stat(dirPath)
if err != nil {
return false
}
return info.Mode().IsDir()
}
Example
if fs.IsDirectory("/batmans/cave") {
fmt.Println("It's a directory!")
}
GetFileSize
GetFileSize returns the size of the specified file in bytes
Parameters
Returns
func GetFileSize(filePath string) int64
{
info, err := os.Stat(filePath)
if err != nil {
return 0
}
return info.Size()
}
Example
size := fs.GetFileSize("/batmans/cave/batmobile.txt")
fmt.Printf("Size: %d\n", size)
WriteFileContent
WriteFileContent writes content to the specified file
Parameters
Returns
func WriteFileContent(filePath, content string) error
{
err := os.WriteFile(filePath, []byte(content), 0644)
if err != nil {
return err
}
return nil
}
Example
err := fs.WriteFileContent("/tmp/batman", "I'm Batman!")
if err != nil {
fmt.Printf("Error writing file content: %v", err)
return
}
FileExists
FileExists checks if a file exists
Parameters
Returns
func FileExists(filePath string) bool
{
_, err := os.Stat(filePath)
return err == nil
}
Example
if fs.FileExists("/tmp/batman") {
fmt.Println("The file exists!")
}
DirectoryExists
DirectoryExists checks if a directory exists
Parameters
Returns
func DirectoryExists(directoryPath string) bool
{
fileInfo, err := os.Stat(directoryPath)
return err == nil && fileInfo.IsDir()
}
Example
if fs.DirectoryExists("/tmp/batman") {
fmt.Println("The directory exists!")
}
ListDirectories
ListDirectories returns a list of directories in the specified directory
Parameters
Returns
func ListDirectories(directoryPath string) ([]string, error)
{
var directories []string
files, err := os.ReadDir(directoryPath)
if err != nil {
return nil, err
}
for _, file := range files {
if file.IsDir() {
directories = append(directories, file.Name())
}
}
return directories, nil
}
Example
directories, err := fs.ListDirectories("/tmp")
if err != nil {
fmt.Printf("Error: %v\n", err)
return
}
for _, directory := range directories {
fmt.Printf("Directory: %s\n", directory)
}
CopyFile
CopyFile copies the contents of one file to another
Parameters
Returns
func CopyFile(sourcePath, destinationPath string) error
{
source, err := os.ReadFile(sourcePath)
if err != nil {
return err
}
err = os.WriteFile(destinationPath, source, 0644)
if err != nil {
return err
}
return nil
}
Example
err := fs.CopyFile("/tmp/batman", "/tmp/robin")
if err != nil {
fmt.Printf("Error copying file: %v", err)
return
}
MoveFile
MoveFile moves a file from one location to another
Parameters
Returns
func MoveFile(sourcePath, destinationPath string) error
{
err := os.Rename(sourcePath, destinationPath)
if err != nil {
return err
}
return nil
}
Example
err := fs.MoveFile("/tmp/batman", "/tmp/robin")
if err != nil {
fmt.Printf("Error moving file: %v", err)
return
}
DeleteFile
DeleteFile deletes a file
Parameters
Returns
func DeleteFile(filePath string) error
{
err := os.Remove(filePath)
if err != nil {
return err
}
return nil
}
Example
err := fs.DeleteFile("/tmp/batman")
if err != nil {
fmt.Printf("Error deleting file: %v", err)
return
}
CreateDirectory
CreateDirectory creates a new directory
Parameters
Returns
func CreateDirectory(directoryPath string) error
{
err := os.Mkdir(directoryPath, 0755)
if err != nil {
return err
}
return nil
}
Example
err := fs.CreateDirectory("/tmp/batman")
if err != nil {
fmt.Printf("Error creating directory: %v", err)
return
}
DeleteDirectory
DeleteDirectory deletes a directory and its contents
Parameters
Returns
func DeleteDirectory(directoryPath string) error
{
err := os.RemoveAll(directoryPath)
if err != nil {
return err
}
return nil
}
Example
err := fs.DeleteDirectory("/tmp/batman")
if err != nil {
fmt.Printf("Error deleting directory: %v", err)
return
}