osfs

package module
v1.0.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 12, 2025 License: MIT Imports: 10 Imported by: 1

README

osfs - Operating System Filesystem

Go Reference Go Report Card CI License

osfs provides an absfs FileSystem implementation that wraps the Go standard library's os package for direct operating system filesystem access.

Features

  • Native OS Access: Direct access to your operating system's filesystem
  • Cross-Platform Support: Works on Unix, macOS, and Windows
  • Windows Drive Mapping: WindowsDriveMapper for seamless Unix-style paths on Windows
  • Full absfs Compatibility: Implements the complete absfs.FileSystem interface

Install

go get github.com/absfs/osfs

Quick Start

Basic Usage
package main

import (
	"log"
	"github.com/absfs/osfs"
)

func main() {
	fs, err := osfs.NewFS()
	if err != nil {
		log.Fatal(err)
	}

	// Create and write to a file
	f, err := fs.Create("example.txt")
	if err != nil {
		log.Fatal(err)
	}
	defer f.Close()

	_, err = f.Write([]byte("Hello, world!\n"))
	if err != nil {
		log.Fatal(err)
	}
}
Cross-Platform Applications

For applications that need to work across Unix and Windows, use the build tag pattern with WindowsDriveMapper:

Create filesystem_windows.go:

//go:build windows

package myapp

import "github.com/absfs/osfs"

func NewFS(drive string) absfs.FileSystem {
	if drive == "" {
		drive = "C:"
	}
	fs, _ := osfs.NewFS()
	return osfs.NewWindowsDriveMapper(fs, drive)
}

Create filesystem_unix.go:

//go:build !windows

package myapp

import "github.com/absfs/osfs"

func NewFS(drive string) absfs.FileSystem {
	fs, _ := osfs.NewFS()
	return fs
}

Use it everywhere:

package main

import "myapp"

func main() {
	fs := myapp.NewFS("")

	// Works identically on all platforms!
	fs.Create("/config/app.json")      // → /config/app.json on Unix, C:\config\app.json on Windows
	fs.MkdirAll("/var/log/app", 0755)  // → /var/log/app on Unix, C:\var\log\app on Windows
}

See the absfs PATH_HANDLING.md guide for complete cross-platform patterns.

WindowsDriveMapper

The WindowsDriveMapper enables Unix-style absolute paths on Windows by translating virtual-absolute paths to Windows drive paths:

fs, _ := osfs.NewFS()
mapped := osfs.NewWindowsDriveMapper(fs, "C:")

// Unix-style paths work on Windows
mapped.Create("/tmp/config.json")    // Creates C:\tmp\config.json
mapped.MkdirAll("/var/log", 0755)    // Creates C:\var\log

// OS-absolute paths pass through unchanged
mapped.Open("C:\\Windows\\file.txt") // Opens C:\Windows\file.txt
mapped.Open("\\\\server\\share\\f")  // Opens UNC path \\server\share\f
Path Translation Rules
Input Path Windows Result Notes
/config/app.json C:\config\app.json Virtual-absolute → mapped to drive
C:\Windows\file C:\Windows\file OS-absolute → pass through
\\server\share\f \\server\share\f UNC path → pass through
relative/path relative\path Relative → pass through

The osfs package provides full symbolic link support via the absfs.SymLinker interface:

fs, _ := osfs.NewFS()

// Create a symlink
fs.Symlink("/path/to/target", "/path/to/link")

// Read symlink target
target, _ := fs.Readlink("/path/to/link")

// Get symlink info without following
info, _ := fs.Lstat("/path/to/link")

Windows users: Symlinks require elevated privileges or Developer Mode. See SYMLINKS.md for configuration instructions and platform-specific behavior.

API Overview

Creating Filesystems
// Standard OS filesystem
fs, err := osfs.NewFS()

// With Windows drive mapping (Windows only)
mapped := osfs.NewWindowsDriveMapper(fs, "D:")
File Operations
// Open files
f, err := fs.Open("/path/to/file.txt")
f, err := fs.Create("/path/to/new.txt")
f, err := fs.OpenFile("/path", os.O_RDWR|os.O_CREATE, 0644)

// File info
info, err := fs.Stat("/path/to/file.txt")

// Remove files
err = fs.Remove("/path/to/file.txt")
Directory Operations
// Create directories
err = fs.Mkdir("/path/to/dir", 0755)
err = fs.MkdirAll("/path/to/nested/dirs", 0755)

// Remove directories
err = fs.Remove("/empty/dir")
err = fs.RemoveAll("/path/to/dir")
Additional Operations
// Rename/move
err = fs.Rename("/old/path", "/new/path")

// Permissions and attributes
err = fs.Chmod("/path/to/file", 0644)
err = fs.Chtimes("/path/to/file", atime, mtime)
err = fs.Chown("/path/to/file", uid, gid)

// Working directory
err = fs.Chdir("/new/directory")
cwd, err := fs.Getwd()

Examples

See example_drivemapper_test.go for complete Windows drive mapping examples.

Advanced Operations

Directory Walking

For advanced directory traversal operations on absfs filesystems, use the fstools package:

import (
    "github.com/absfs/fstools"
    "github.com/absfs/osfs"
)

fs, _ := osfs.NewFS()

// Simple walk compatible with filepath.WalkFunc
err := fstools.Walk(fs, "/path", func(path string, info os.FileInfo, err error) error {
    fmt.Println(path)
    return nil
})

// Walk with options for different traversal strategies
options := &fstools.Options{
    Sort:      true,
    Traversal: fstools.BreadthTraversal,  // Also: PreOrder, PostOrder, KeyOrder
}
err = fstools.WalkWithOptions(fs, options, "/path", walkFunc)

The fstools package provides:

  • Multiple traversal strategies: PreOrder, PostOrder, BreadthFirst, and KeyOrder (files only)
  • Sorting options: Custom sort functions or alphabetical
  • Filesystem operations: Copy, Describe, Diff, Patch, and Apply
  • Works with any absfs.Filer implementation

See github.com/absfs/fstools for complete documentation.

Documentation

  • absfs - Core filesystem abstraction
  • fstools - Advanced filesystem operations (Walk, Copy, Diff, Patch)
  • memfs - In-memory filesystem
  • basefs - Chroot filesystem wrapper
  • rofs - Read-only filesystem wrapper

License

This project is governed by the MIT License. See LICENSE

Documentation

Overview

Package osfs provides helpers for converting between Unix-style absfs paths and native OS paths. All absfs filesystems use Unix-style forward slash paths for consistency and composability. The osfs package provides conversion helpers for interacting with native filesystem APIs.

Path Conventions

absfs paths use Unix-style conventions regardless of the host OS:

  • Forward slashes: /foo/bar
  • Drive letters (Windows): /c/Users/foo (lowercase)
  • UNC paths (Windows): //server/share/path
  • No drive = current drive: /foo resolves using cwd's drive

Windows Examples

FromNative("C:\\Users\\foo") → "/c/Users/foo"
FromNative("\\\\server\\share") → "//server/share"
ToNative("/c/Users/foo") → "C:\\Users\\foo"
ToNative("//server/share") → "\\\\server\\share"

Unix Examples

On Unix systems, ToNative and FromNative are effectively no-ops since Unix already uses forward slashes. Drive letter functions return empty strings and pass through paths unchanged.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func FromNative

func FromNative(path string) string

FromNative converts an OS-native path to a Unix-style absfs path.

On Windows:

  • "C:\foo\bar" → "/c/foo/bar"
  • "\\server\share\path" → "//server/share/path"
  • "\foo\bar" → "/foo/bar"

On Unix: returns the path unchanged (no-op).

func GetDrive

func GetDrive(path string) string

GetDrive returns just the drive letter from a Unix-style absfs path. Returns empty string if path has no drive letter.

Examples:

GetDrive("/c/foo") → "c"
GetDrive("/foo") → ""
GetDrive("//server/share") → ""

func IsReservedName

func IsReservedName(name string) bool

IsReservedName returns true if name is a reserved device name on Windows. Always returns false on Unix.

Reserved names (case-insensitive): CON, PRN, AUX, NUL, COM1-COM9, LPT1-LPT9

Examples:

IsReservedName("CON") → true (Windows), false (Unix)
IsReservedName("con.txt") → true (Windows), false (Unix)
IsReservedName("config") → false

func IsUNC

func IsUNC(path string) bool

IsUNC returns true if the path is a UNC-style path (//server/share).

Examples:

IsUNC("//server/share") → true
IsUNC("//server/share/path") → true
IsUNC("/c/foo") → false
IsUNC("/foo") → false

func JoinDrive

func JoinDrive(drive, path string) string

JoinDrive combines a drive letter with a path to create a Unix-style absfs path.

Examples:

JoinDrive("c", "/foo") → "/c/foo"
JoinDrive("C", "/foo") → "/c/foo"  // normalized to lowercase
JoinDrive("", "/foo") → "/foo"      // no drive
JoinDrive("c", "foo") → "/c/foo"    // ensures leading slash

func JoinUNC

func JoinUNC(server, share, path string) string

JoinUNC creates a UNC path from server, share, and path components.

Examples:

JoinUNC("server", "share", "/foo") → "//server/share/foo"
JoinUNC("server", "share", "/") → "//server/share"
JoinUNC("server", "share", "") → "//server/share"

func SetDrive

func SetDrive(path, drive string) string

SetDrive returns the path with its drive letter changed (or added). If the path already has a drive, it is replaced. If not, one is added.

Examples:

SetDrive("/c/foo", "d") → "/d/foo"
SetDrive("/foo", "c") → "/c/foo"
SetDrive("foo", "c") → "/c/foo"

func SplitDrive

func SplitDrive(path string) (drive, rest string)

SplitDrive extracts the drive letter from a Unix-style absfs path. Returns the drive letter (lowercase, without colon) and the remaining path.

Examples:

SplitDrive("/c/foo") → ("c", "/foo")
SplitDrive("/C/foo") → ("c", "/foo")  // normalized to lowercase
SplitDrive("/foo") → ("", "/foo")      // no drive
SplitDrive("//server/share") → ("", "//server/share")  // UNC, no drive
SplitDrive("foo/bar") → ("", "foo/bar")  // relative path

func SplitUNC

func SplitUNC(path string) (server, share, rest string)

SplitUNC splits a UNC path into server, share, and remaining path components. Returns empty strings if the path is not a valid UNC path.

Examples:

SplitUNC("//server/share/foo/bar") → ("server", "share", "/foo/bar")
SplitUNC("//server/share") → ("server", "share", "/")
SplitUNC("/c/foo") → ("", "", "")  // not UNC

func StripDrive

func StripDrive(path string) string

StripDrive removes the drive prefix from a Unix-style absfs path.

Examples:

StripDrive("/c/foo") → "/foo"
StripDrive("/foo") → "/foo"  // no change
StripDrive("//server/share/path") → "//server/share/path"  // UNC unchanged

func ToNative

func ToNative(path string) string

ToNative converts a Unix-style absfs path to an OS-native path.

On Windows:

  • "/c/foo/bar" → "C:\foo\bar"
  • "//server/share/path" → "\\server\share\path"
  • "/foo/bar" → "\foo\bar" (no drive, relative to current drive root)

On Unix: returns the path unchanged (no-op).

func ValidatePath

func ValidatePath(path string) error

ValidatePath checks if a path is valid for the current OS. Returns nil if valid, or an error describing the issue.

On Windows, checks for:

  • Reserved device names (CON, PRN, NUL, etc.)
  • Invalid characters (< > : " | ? *)
  • Trailing spaces or periods in path components

On Unix: most paths are valid, only checks for null bytes.

Types

type File

type File struct {
	// contains filtered or unexported fields
}

func (*File) Close

func (f *File) Close() error

func (*File) Name

func (f *File) Name() string

Name returns the file name in Unix-style format. On Windows, this includes the drive letter (e.g., "/c/Users/foo/file.txt").

func (*File) Read

func (f *File) Read(p []byte) (int, error)

func (*File) ReadAt

func (f *File) ReadAt(b []byte, off int64) (n int, err error)

func (*File) ReadDir

func (f *File) ReadDir(n int) ([]fs.DirEntry, error)

ReadDir reads the contents of the directory and returns a slice of up to n DirEntry values in directory order. This delegates to the underlying os.File.ReadDir which uses high-performance native OS directory reading APIs.

If n > 0, ReadDir returns at most n entries. In this case, if ReadDir returns an empty slice, it will return a non-nil error explaining why. At the end of a directory, the error is io.EOF.

If n <= 0, ReadDir returns all entries from the directory in a single slice. In this case, if ReadDir succeeds (reads all the way to the end of the directory), it returns the slice and a nil error.

func (*File) Readdir

func (f *File) Readdir(n int) ([]os.FileInfo, error)

func (*File) Readdirnames

func (f *File) Readdirnames(n int) ([]string, error)

func (*File) Seek

func (f *File) Seek(offset int64, whence int) (ret int64, err error)

func (*File) Stat

func (f *File) Stat() (os.FileInfo, error)

func (*File) Sync

func (f *File) Sync() error

func (*File) Truncate

func (f *File) Truncate(size int64) error

func (*File) Write

func (f *File) Write(p []byte) (int, error)

func (*File) WriteAt

func (f *File) WriteAt(b []byte, off int64) (n int, err error)

func (*File) WriteString

func (f *File) WriteString(s string) (n int, err error)

type FileSystem

type FileSystem struct {
	// contains filtered or unexported fields
}

FileSystem implements absfs.SymlinkFileSystem using the host OS filesystem. All paths are Unix-style (forward slashes) for consistency with absfs conventions. On Windows, drive letters are represented as /c/, /d/, etc.

func NewFS

func NewFS() (*FileSystem, error)

NewFS creates a new FileSystem rooted at the OS current working directory. The cwd is stored in Unix-style format.

func (*FileSystem) Chdir

func (fs *FileSystem) Chdir(name string) error

Chdir changes the current working directory. The name can be a Unix-style path (e.g., "/c/Users" on Windows).

func (*FileSystem) Chmod

func (fs *FileSystem) Chmod(name string, mode os.FileMode) error

Chmod changes the mode of the named file.

func (*FileSystem) Chown

func (fs *FileSystem) Chown(name string, uid, gid int) error

Chown changes the owner and group ids of the named file.

func (*FileSystem) Chtimes

func (fs *FileSystem) Chtimes(name string, atime time.Time, mtime time.Time) error

Chtimes changes the access and modification times of the named file.

func (*FileSystem) Create

func (fs *FileSystem) Create(name string) (absfs.File, error)

Create creates or truncates the named file.

func (*FileSystem) Getwd

func (fs *FileSystem) Getwd() (dir string, err error)

Getwd returns the current working directory in Unix-style format. On Windows, this includes the drive letter (e.g., "/c/Users/foo").

func (*FileSystem) Lchown

func (fs *FileSystem) Lchown(name string, uid, gid int) error

Lchown changes the owner and group ids of a symlink.

func (*FileSystem) Lstat

func (fs *FileSystem) Lstat(name string) (os.FileInfo, error)

Lstat returns file information without following symlinks.

func (*FileSystem) Mkdir

func (fs *FileSystem) Mkdir(name string, perm os.FileMode) error

Mkdir creates a directory with the specified permissions.

func (*FileSystem) MkdirAll

func (fs *FileSystem) MkdirAll(name string, perm os.FileMode) error

MkdirAll creates a directory and all necessary parents.

func (*FileSystem) Open

func (fs *FileSystem) Open(name string) (absfs.File, error)

Open opens the named file for reading.

func (*FileSystem) OpenFile

func (fs *FileSystem) OpenFile(name string, flag int, perm os.FileMode) (absfs.File, error)

OpenFile opens a file with the specified flags and permissions.

func (*FileSystem) ReadDir

func (fs *FileSystem) ReadDir(name string) ([]fs.DirEntry, error)

ReadDir reads the named directory and returns a list of directory entries. Uses platform-specific optimizations for high-performance directory reading: - Linux: syscall.Getdents with 32KB buffer (vs default 8KB) - macOS: os.ReadDir (uses getattrlistbulk internally) - Windows: FindFirstFileEx with optimizations - Other platforms: os.ReadDir fallback

func (*FileSystem) ReadFile

func (fs *FileSystem) ReadFile(name string) ([]byte, error)

ReadFile reads the named file and returns its contents. Uses os.ReadFile for optimized file reading with proper size pre-allocation.

func (fs *FileSystem) Readlink(name string) (string, error)

Readlink returns the symlink target in Unix-style format.

func (*FileSystem) Remove

func (fs *FileSystem) Remove(name string) error

Remove removes the named file or empty directory.

func (*FileSystem) RemoveAll

func (fs *FileSystem) RemoveAll(name string) error

RemoveAll removes a file or directory and any children.

func (*FileSystem) Rename

func (fs *FileSystem) Rename(oldpath, newpath string) error

Rename renames (moves) a file or directory.

func (*FileSystem) Stat

func (fs *FileSystem) Stat(name string) (os.FileInfo, error)

Stat returns file information for the named file.

func (*FileSystem) Sub

func (fs *FileSystem) Sub(dir string) (fs.FS, error)

Sub returns an fs.FS corresponding to the subtree rooted at dir. The directory must exist and be a valid directory.

func (fs *FileSystem) Symlink(oldname, newname string) error

Symlink creates a symbolic link. The oldname (target) is stored exactly as given - it can be relative or absolute. Only the newname (link location) is converted to a native path.

func (*FileSystem) TempDir

func (fs *FileSystem) TempDir() string

TempDir returns the OS temp directory in Unix-style format.

func (*FileSystem) Truncate

func (fs *FileSystem) Truncate(name string, size int64) error

Truncate changes the size of the named file.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL