Skip to content

os Module

The os module provides a comprehensive way to interact with the operating system, including structured device information through maps, file operations, environment variables, and system utilities.

Functions

Args()

Returns the process arguments excluding the interpreter binary. Index 0 is typically the script path, and subsequent elements are the CLI arguments you passed when invoking Harneet.

Returns: - (array, error): An array of strings with the process arguments (script path first).

Example:

Args Example
1
2
3
4
5
6
7
8
9
package main
import fmt
import os

var argv, _ = os.Args()
fmt.Println("argv:", argv)

// Often you'll drop the script path (index 0) and pass the rest to flags:
// var sel, args, tag, err = flags.Run(argv[1:])


Getenv(name)

Gets the value of an environment variable.

Parameters: - name: The name of the environment variable.

Returns: - (string, error): The value of the environment variable, or an empty string if it's not set.

Example:

Getenv Example
1
2
3
4
5
6
package main
import fmt
import os

var home, _ = os.Getenv("HOME")
fmt.Println("HOME directory:", home)


Setenv(name, value)

Sets the value of an environment variable.

Parameters: - name: The name of the environment variable. - value: The value to set.

Returns: - (None, error)

Example:

Setenv Example
1
2
3
import os

os.Setenv("MY_VAR", "my_value")


Type()

Returns the operating system type.

Returns: - (string, error): The OS type (e.g., "darwin", "linux", "windows").

Example:

Type Example
1
2
3
4
5
6
package main
import fmt
import os

var osType, _ = os.Type()
fmt.Println("OS Type:", osType)


Version()

Returns the operating system version.

Returns: - (string, error): The OS version.


Arch()

Returns the system architecture.

Returns: - (string, error): The architecture (e.g., "amd64", "arm64").


Getwd()

Returns the current working directory.

Returns: - (string, error): The current working directory path.


Chdir(path)

Changes the current working directory.

Parameters: - path: The path to the new directory.


Mkdir(path)

Creates a new directory.

Parameters: - path: The path of the directory to create.


Remove(path)

Removes a file or directory.

Parameters: - path: The path of the file or directory to remove.


Exists(path)

Checks if a file or directory exists.

Parameters: - path: The path to check.

Returns: - (boolean, error): true if the path exists, false otherwise.


TempDir()

Returns the default directory to use for temporary files.

Returns: - (string, error): The temporary directory path (e.g., "/tmp" on Unix systems).

Example:

TempDir Example
1
2
3
4
5
6
package main
import fmt
import os

var tmpDir, _ = os.TempDir()
fmt.Printf("Temp directory: %s\n", tmpDir)


CreateTemp(dir, pattern)

Creates a new temporary file in the directory dir with a name beginning with pattern and returns the file path. The file is created on disk immediately with a unique name.

Parameters: - dir (string): Directory for temp file (use empty string "" for os.TempDir()) - pattern (string): Name pattern (e.g., "myapp-*.txt" where * is replaced with random string)

Returns: - (string, error): The full path to the created temporary file.

Key Features: - Automatic location: Empty string uses system temp directory (/tmp on Unix, %TEMP% on Windows) - Pattern matching: The * in pattern is replaced with a random string to ensure uniqueness - File created: File is created on disk immediately and returned closed - No collisions: Guaranteed unique filename prevents conflicts

Pattern Examples: - "upload-*.dat"upload-1234567.dat - "cache-*.json"cache-9876543.json - "test-*"test-4567890

Example 1 - Basic Usage:

CreateTemp Basic Usage
package main
import fmt
import os

// Create temp file in default temp directory
var tmpFile, err = os.CreateTemp("", "upload-*.dat")
if err == None {
    fmt.Printf("Created temp file: %s\n", tmpFile)
    // Example output: /tmp/upload-2289271499.dat

    // Write data to it
    os.WriteFile(tmpFile, "temporary data")

    // Read it back
    var content, _ = os.ReadFile(tmpFile)
    fmt.Println(content)

    // Clean up when done
    os.Remove(tmpFile)
}

Example 2 - Upload Processing:

CreateTemp Upload Processing
package main
import os
import fmt

function processUpload(data string) {
    var tmp, err = os.CreateTemp("", "upload-*.dat")
    if err != None {
        fmt.Printf("Error creating temp file: %s\n", err)
        return
    }

    // Write uploaded data
    var _, writeErr = os.WriteFile(tmp, data)
    if writeErr != None {
        os.Remove(tmp)
        return
    }

    // Process the file
    fmt.Printf("Processing %s...\n", tmp)
    // ... your processing logic ...

    // Clean up
    os.Remove(tmp)
    fmt.Println("Processing complete")
}

Example 3 - Custom Directory:

CreateTemp Custom Directory
package main
import os
import fmt

// Create temp file in specific directory
var tmp, err = os.CreateTemp("/var/tmp", "custom-*.log")
if err == None {
    fmt.Println(tmp)  // Output: /var/tmp/custom-1234567.log

    // Use the file...
    os.WriteFile(tmp, "log data")

    // Clean up
    os.Remove(tmp)
}

Example 4 - Safe Pattern with Defer (Future):

CreateTemp with Defer
package main
import os

function doWork() {
    var tmp, err = os.CreateTemp("", "work-*.tmp")
    if err != None {
        return
    }
    // Note: defer will be supported in future for automatic cleanup
    // defer os.Remove(tmp)

    // Do work with temp file...
    os.WriteFile(tmp, "work data")

    // Manual cleanup for now
    os.Remove(tmp)
}


Chmod(name, mode)

Changes the mode (permissions) of the named file to mode.

Parameters: - name (string): Path to the file - mode (int): Unix file permissions as decimal (e.g., 420 for 0644, 493 for 0755)

Returns: - (None, error): None on success, error on failure.

Common Permission Values: - 420 (0644): rw-r--r-- - Owner read/write, group/others read - 384 (0600): rw------- - Owner read/write only - 493 (0755): rwxr-xr-x - Owner full, group/others read/execute

Example:

Chmod Example
package main
import os
import fmt

// Create file with default permissions
os.WriteFile("config.json", configData)

// Restrict to owner-only read/write
var _, err = os.Chmod("config.json", 384)  // 0600
if err == None {
    fmt.Println("Permissions changed to owner-only")
}


Chtimes(name, atime, mtime)

Changes the access and modification times of the named file.

Parameters: - name (string): Path to the file - atime (int): Access time as Unix timestamp (seconds since epoch) - mtime (int): Modification time as Unix timestamp (seconds since epoch)

Returns: - (None, error): None on success, error on failure.

Example:

Chtimes Example
package main
import os
import time
import fmt

// Set file times to a specific date
// 1609459200 = 2021-01-01 00:00:00 UTC
var _, err = os.Chtimes("document.txt", 1609459200, 1609459200)
if err == None {
    fmt.Println("File times updated")
}

// Copy file while preserving timestamps
var _, _, modTime, _ = os.Stat("original.txt")
var content, _ = os.ReadFile("original.txt")
os.WriteFile("copy.txt", content)
// Note: modTime needs to be converted to Unix timestamp


Clearenv()

Deletes all environment variables. Use with caution - this clears the entire environment!

Returns: - (None, error): None on success.

Example:

Clearenv Example
package main
import os

// Save important variables first
var originalPath, _ = os.Getenv("PATH")
var originalHome, _ = os.Getenv("HOME")

// Clear all environment variables
os.Clearenv()

// Restore critical variables
os.Setenv("PATH", originalPath)
os.Setenv("HOME", originalHome)


Environ()

Returns a copy of strings representing the environment, in the form "KEY=value".

Returns: - (array, error): Array of strings, each in "KEY=value" format.

Example:

Environ Example
package main
import fmt
import os

var env, _ = os.Environ()
fmt.Printf("Environment has %d variables\n", len(env))

for envVar in env {
    fmt.Println(envVar)
}


Getpid()

Returns the process ID of the caller.

Returns: - (int, error): The process ID.

Example:

Getpid Example
1
2
3
4
5
6
package main
import fmt
import os

var pid, _ = os.Getpid()
fmt.Printf("Current process ID: %d\n", pid)


Getppid()

Returns the process ID of the caller's parent.

Returns: - (int, error): The parent process ID.

Example:

Getppid Example
1
2
3
4
5
6
package main
import fmt
import os

var ppid, _ = os.Getppid()
fmt.Printf("Parent process ID: %d\n", ppid)


LookupUser(username)

Looks up a user by username and returns a map with user information.

Parameters: - username (string): The username to look up

Returns: - (map, error): Map with keys: uid, gid, username, name, homedir

Example:

LookupUser Example
package main
import fmt
import os

var user, err = os.LookupUser("alice")
if err == None {
    fmt.Printf("User: %s\n", user["username"])
    fmt.Printf("UID: %s\n", user["uid"])
    fmt.Printf("GID: %s\n", user["gid"])
    fmt.Printf("Full name: %s\n", user["name"])
    fmt.Printf("Home: %s\n", user["homedir"])
}


LookupGroup(groupname)

Looks up a group by name and returns a map with group information.

Parameters: - groupname (string): The group name to look up

Returns: - (map, error): Map with keys: gid, name

Example:

LookupGroup Example
1
2
3
4
5
6
7
8
9
package main
import fmt
import os

var group, err = os.LookupGroup("wheel")
if err == None {
    fmt.Printf("Group: %s\n", group["name"])
    fmt.Printf("GID: %s\n", group["gid"])
}


Hostname()

Returns the host name reported by the kernel.

Returns: - (string, error): The hostname.

Example:

Hostname Example
1
2
3
4
5
6
package main
import fmt
import os

var hostname, _ = os.Hostname()
fmt.Printf("Hostname: %s\n", hostname)


UserHomeDir()

Returns the current user's home directory.

Returns: - (string, error): The home directory path.

Example:

UserHomeDir Example
1
2
3
4
5
6
package main
import fmt
import os

var home, _ = os.UserHomeDir()
fmt.Printf("Home directory: %s\n", home)


Exec(cmd, args)

Runs an external command and returns its stdout as a string. On non-zero exit, returns an error containing stderr.

Parameters: - cmd (string): Command to execute - args (array): Array of string arguments

Returns: - (string, error): Command output or error with stderr.

Example:

Exec Example
package main
import fmt
import os

var output, err = os.Exec("ls", ["-la", "/tmp"])
if err == None {
    fmt.Println(output)
} else {
    fmt.Printf("Command failed: %s\n", err)
}


Device Functions

The following functions provide structured device information through maps, enabling modern programmatic access to system hardware data.

ListDevices()

Returns an array of device information maps for system devices.

Returns: - (array, error): Array of device maps, each containing device information.

Device Map Structure: Each device map contains the following keys: - type: Device type ("USB", "Storage", "Network") - name: Human-readable device name - id: Device identifier - status: Device status ("available", "connected", "mounted") - count: Number of devices (for USB devices)

Example:

ListDevices Example
package main
import fmt
import os

var devices, err = os.ListDevices()
if err != None {
    fmt.Printf("Error: %s\n", err)
} else {
    fmt.Printf("Found %d device types\n", len(devices))

    // Access individual device maps
    for device in devices {
        var deviceType = device["type"]
        var deviceName = device["name"]
        var deviceStatus = device["status"]

        fmt.Printf("Device: %s - %s (%s)\n", deviceType, deviceName, deviceStatus)
    }

    // Access specific device properties
    var firstDevice = devices[0]
    var usbCount = firstDevice["count"]  // For USB devices
}

Cross-Platform Support: - macOS: USB devices and storage drives - Linux: Individual USB devices with detailed information - Windows: Storage devices and system drives


GetDeviceInfo(deviceId)

Returns detailed information about a specific device as a structured map.

Parameters: - deviceId: Device identifier string (e.g., "system", "cpu")

Returns: - (map, error): Device information map with detailed hardware data.

Device Info Map Structure: The returned map contains the following keys: - id: Device identifier - type: Device type ("macOS Device", "Linux Device", "Windows Device") - name: Device name - status: Device status ("active", "inactive") - details: Nested map with hardware-specific information

Example:

GetDeviceInfo Example
import fmt
import os

var deviceInfo, err = os.GetDeviceInfo("system")
if err != None {
    fmt.Printf("Error: %s\n", err)
} else {
    // Access basic device information
    var deviceId = deviceInfo["id"]
    var deviceType = deviceInfo["type"]
    var deviceName = deviceInfo["name"]
    var deviceStatus = deviceInfo["status"]

    fmt.Printf("Device: %s (%s)\n", deviceName, deviceType)
    fmt.Printf("Status: %s\n", deviceStatus)

    // Access detailed hardware information
    var deviceDetails = deviceInfo["details"]
    if deviceDetails != None {
        // On macOS, details include:
        var chip = deviceDetails["Chip"]              // "Apple M2 Pro"
        var memory = deviceDetails["Memory"]          // "16 GB"
        var model = deviceDetails["Model Name"]       // "MacBook Pro"
        var serial = deviceDetails["Serial Number"]   // System serial

        fmt.Printf("Hardware: %s with %s\n", chip, memory)
        fmt.Printf("Model: %s\n", model)
    }
}

Platform-Specific Details:

macOS (system_profiler): - Chip/Processor information - Memory specifications - Model details and serial numbers - Hardware UUID and identifiers

Linux (lscpu): - CPU architecture and specifications - Core count and threading - Cache information - Processor features

Windows (wmic): - System manufacturer and model - Total physical memory - Computer system information

JSON Integration: Device information maps work seamlessly with JSON serialization:

Device JSON Integration
package main
import fmt
import os
import json

var devices, _ = os.ListDevices()
var deviceInfo, _ = os.GetDeviceInfo("system")

// Create system report
var systemReport = {
    "timestamp": "2024-09-24T13:30:00Z",
    "devices": devices,
    "primary_device": deviceInfo
}

var reportJson, err = json.Marshal(systemReport)
if err == None {
    fmt.Printf("System Report JSON: %s\n", reportJson)
}

MkdirAll(path)

Creates a directory and all necessary parents.

Parameters: - path: Directory to create (parents will be created as needed).

Returns: - (None, error)

Example:

MkdirAll Example
1
2
3
package main
import os
var _, err = os.MkdirAll("/tmp/harneet/demo/sub/dir")


RemoveAll(path)

Removes a path and everything it contains.

Parameters: - path: File or directory to remove recursively.

Returns: - (None, error)


Rename(old, new)

Renames (moves) a file or directory.

Parameters: - old: Source path. - new: Destination path.

Returns: - (None, error)


ReadFile(path)

Reads a file and returns its contents as a string.

Parameters: - path: File path to read.

Returns: - (string, error)

Example:

ReadFile Example
1
2
3
4
5
6
package main
import fmt
import os

var data, err = os.ReadFile("/etc/hosts")
if err == None { fmt.Println(data) }


WriteFile(path, data)

Writes a string to a file (creates or overwrites) using 0644 permissions.

Parameters: - path: Target file path. - data: String content to write.

Returns: - (None, error)


ReadDir(path)

Reads a directory and returns an array of tuples for each entry: (name string, isDir boolean, size int, modTime string) where modTime is RFC3339 UTC.

Parameters: - path: Directory path.

Returns: - (array, error)

Example:

ReadDir Example
1
2
3
4
5
6
7
8
9
package main
import fmt
import os

var entries, err = os.ReadDir("/tmp")
if err == None {
    // entries[i] is a tuple: (name, isDir, size, modTime)
    fmt.Println(entries)
}


Stat(path)

Returns basic file information: size (bytes), isDir (boolean), modTime (RFC3339 UTC).

Parameters: - path: File or directory path.

Returns: - (int, boolean, string, error)

Example:

Stat Example
1
2
3
4
5
6
7
8
package main
import fmt
import os

var size, isDir, mt, err = os.Stat("/etc/hosts")
if err == None {
    fmt.Printf("size=%d isDir=%t mtime=%s\n", size, isDir, mt)
}


Watch(path)

Watches a file or directory by taking snapshots and reporting what changed since the previous call for that same path. This is a polling, snapshot-based API, not a background watcher.

On the first call for a given path, os.Watch stores an internal snapshot and returns an empty array. On subsequent calls, it compares the current state with the last snapshot and returns an array of change maps.

Each change map has the following keys:

  • path (string): Full path to the changed entry
  • name (string): Base name of the entry
  • isDir (boolean): Whether the entry is a directory
  • size (int): Size in bytes (for files)
  • modTime (string): Last modification time (RFC3339 UTC)
  • mode (int): File permissions (Unix-style, decimal, e.g. 420 for 0644)
  • ops (array): Array of operation strings, any of:
  • "create" – entry was created since last snapshot
  • "modify" – size or modTime changed
  • "chmod" – permissions changed (mode differs)
  • "delete" – entry was removed since last snapshot

Notes:

  • For files, both content changes and permission changes are reported.
  • For directories, structural changes (created/deleted children) are reflected via child entries getting create/delete ops.
  • Snapshots are maintained per path you pass to os.Watch.

Returns: - (array, error): Array of change maps, or empty array if nothing changed.

Example:

Watch Directory Changes
package main
import fmt
import os

var dir = "/tmp/watch-demo"
os.RemoveAll(dir)
os.MkdirAll(dir)

// First call initializes the watch state; usually returns [].
var initial, err1 = os.Watch(dir)
if err1 != None {
    fmt.Printf("Watch error: %s\n", err1)
}

// Create and chmod a file
var filePath = dir + "/example.txt"
os.WriteFile(filePath, "hello")
os.Chmod(filePath, 384)  // 0600

// Second call reports the changes since the first snapshot
var changes, err2 = os.Watch(dir)
if err2 == None {
    fmt.Printf("Reported %d changes\n", len(changes))
    for change in changes {
        fmt.Printf("%s: ops=%v mode=%d\n",
            change["path"], change["ops"], change["mode"])
    }
}

### WatchStart(path, intervalMs), WatchEvents(id), WatchStop(id)

These functions provide a lower-level, event-queue based watcher built on background goroutines. They are useful when you want a dedicated watcher per path and you are comfortable polling for events.

Signatures: - os.WatchStart(path string, intervalMs int) (string, error) - os.WatchEvents(id string) (array, error) - os.WatchStop(id string) (None, error)

Behavior: - WatchStart: - Validates intervalMs > 0. - Starts a background watcher for path that snapshots the filesystem every intervalMs milliseconds and enqueues change events internally. - Returns a watcher id string like "watch-1". - WatchEvents: - Takes a watcher id and returns all pending events for that watcher. - Clears the internal event queue for that id before returning. - WatchStop: - Stops the background watcher for the given id and releases its resources.

Each event returned by WatchEvents is a map with the same shape as os.Watch change maps:

  • path (string)
  • name (string)
  • isDir (boolean)
  • size (int)
  • modTime (string, RFC3339 UTC)
  • mode (int, Unix permissions as decimal)
  • ops (array of strings like "create", "modify", "chmod", "delete")

Example:

Background Watcher with Events
package main
import fmt
import os

var dir = "/tmp/watch-events-demo"
os.RemoveAll(dir)
os.MkdirAll(dir)

// Start a watcher that polls every 100ms
var id, err = os.WatchStart(dir, 100)
if err != None {
    fmt.Printf("WatchStart error: %s\n", err)
} else {
    var filePath = dir + "/file.txt"
    os.WriteFile(filePath, "hello from events API")
    os.Chmod(filePath, 384)

    // Give the watcher time to detect the change
    sleep(300)

    var events, evErr = os.WatchEvents(id)
    if evErr == None {
        fmt.Printf("Watcher %s reported %d events\n", id, len(events))
        for ev in events {
            fmt.Printf("%s ops=%v mode=%d\n",
                ev["path"], ev["ops"], ev["mode"])
        }
    }

    // Always stop watchers when done
    os.WatchStop(id)
}

#### Pub-sub style helper (example package)

For many applications, a callback-based style is more convenient: you want changes to be pushed to a handler function instead of polling with WatchEvents. You can build this using Harneet's concurrency primitives (do, sleep, newCancelToken, cancel, sleepUntil).

The repository includes an example helper package at examples/watch/watch.ha with a small API:

watch helper API (example)
1
2
3
4
5
package watch
import os

function Subscribe(path string, intervalMs int, handler function(any)) (string, error)
function Unsubscribe(id string) (None, error)

A simplified usage pattern (adapt for your own project layout):

Pub-sub Style Watcher with Callback
package main
import fmt
import os
import "../watch" as watch

var dir = "/tmp/os_watch_pubsub"
os.RemoveAll(dir)
os.MkdirAll(dir)

var events = []

function handle(ev any) {
    fmt.Printf("event path=%s ops=%v mode=%d isDir=%t\n",
        ev["path"], ev["ops"], ev["mode"], ev["isDir"])
    events = append(events, ev)
}

var id, err = watch.Subscribe(dir, 100, handle)
if err != None {
    fmt.Printf("subscribe error: %s\n", err)
} else {
    var filePath = dir + "/pubsub.txt"
    os.WriteFile(filePath, "pubsub data")
    os.Chmod(filePath, 384)

    // Give the watcher time to detect and dispatch events
    sleep(500)

    fmt.Printf("Received %d events\n", len(events))
    watch.Unsubscribe(id)
}

This pattern keeps all callback invocation inside Harneet's scheduler while the low-level os module handles the actual filesystem polling.


Exit(code)

Terminates the current process with the given status code.

Parameters: - code: Exit status code (int).

Returns: - (None, error)

Note: This will terminate the program immediately.


ExpandEnv(s)

Expands ${VAR} or $VAR in a string using the current environment.

Parameters: - s: Input string containing env references.

Returns: - (string, error)

Example:

ExpandEnv Example
1
2
3
4
5
6
package main
import fmt
import os

var out, err = os.ExpandEnv("HOME=$HOME USER=$USER")
if err == None { fmt.Println(out) }


Device Information Maps

The os module provides structured device information through maps, making system data easy to access and process programmatically.

Map-Based Device Data

Unlike traditional string-based system information, Harneet's OS module returns structured maps that can be easily accessed, filtered, and serialized.

Benefits: - Structured Access: Use map indexing to access specific properties - Type Safety: Consistent data types for device properties - JSON Ready: Seamless integration with JSON serialization - Programmatic Processing: Easy filtering and data manipulation

Device List Structure

Device List Structure
// Example device list output
[
    {
        "type": "USB",
        "name": "USB Devices", 
        "status": "available",
        "count": 141
    },
    {
        "type": "Storage",
        "name": "Disk Drives",
        "status": "mounted"
    }
]

Device Info Structure

Device Info Structure
// Example device info output
{
    "id": "system",
    "type": "macOS Device",
    "name": "Mac Hardware", 
    "status": "active",
    "details": {
        "Chip": "Apple M2 Pro",
        "Memory": "16 GB",
        "Model Name": "MacBook Pro",
        "Serial Number": "K4V7JN6RW1",
        "Hardware UUID": "D867AE5E-6481-5E87-B778-24EAA3458572"
    }
}

Common Use Cases

System Monitoring:

System Monitoring
1
2
3
4
5
6
7
8
import os

var devices, _ = os.ListDevices()
for device in devices {
    if device["type"] == "USB" && device["count"] > 100 {
        fmt.Printf("High USB device count: %s\n", device["count"])
    }
}

Hardware Inventory:

Hardware Inventory
1
2
3
4
5
6
7
8
9
import os

var info, _ = os.GetDeviceInfo("system")
var inventory = {
    "model": info["details"]["Model Name"],
    "memory": info["details"]["Memory"],
    "processor": info["details"]["Chip"],
    "serial": info["details"]["Serial Number"]
}

API Integration:

API Integration
import os
import json

var devices, _ = os.ListDevices()
var deviceInfo, _ = os.GetDeviceInfo("system")

var apiPayload = {
    "hostname": "server-01",
    "devices": devices,
    "hardware": deviceInfo,
    "timestamp": "2024-09-24T13:30:00Z"
}

var jsonData, _ = json.Marshal(apiPayload)
// Send jsonData to monitoring API

Configuration Management:

Configuration Management
import os

var systemInfo, _ = os.GetDeviceInfo("system")
var config = {
    "deployment": {
        "target": systemInfo["details"]["Model Name"],
        "memory_gb": systemInfo["details"]["Memory"],
        "architecture": systemInfo["type"]
    }
}

Cross-Platform Compatibility

The device information maps provide consistent structure across platforms while including platform-specific details:

Platform Device Types Hardware Details Special Features
macOS USB, Storage Full system profiler data Hardware UUID, Model numbers
Linux USB (individual) CPU specifications Detailed USB device info
Windows Storage System manufacturer info Drive information

Error Handling

Device functions return structured error information:

Error Handling
package main
import fmt
import os

var devices, err = os.ListDevices()
if err != None {
    fmt.Printf("Device listing failed: %s\n", err)
} else {
    if len(devices) == 0 {
        fmt.Println("No devices found")
    } else {
        fmt.Printf("Found %d device types\n", len(devices))
    }
}

See Also

  • Maps - Harneet's map data structure
  • JSON - JSON serialization for device data
  • Arrays - Working with device lists