crtemp v0.1.0
forked from lugia-kun/tempdircrtemp.cr
Creates a temporary directory with atomic mkdtemp/mkstemp support.
Features
- Atomic creation: Uses
mkdtempon Unix andCreateFileAon Windows for race-free temp directory/file creation - Secure permissions: Directories created with
0o700, files with0o600(owner-only) - Cross-platform: Works on Unix/Linux/macOS and Windows
- Result-based API: All operations return
Resulttypes for explicit error handling - Automatic cleanup: Crtemp removes contents on
#close, block form auto-cleans
Installation
-
Add the dependency to your
shard.yml:dependencies: crtemp: github: kritoke/crtemp -
Run
shards install
Usage
require "crtemp"
Dir.mktmpdir (block form uses FunctionalCrtemp)
dir = Dir.mktmpdir(*args)
Creates a temporary directory. Arguments are passed to File.tempname as-is. See File.tempname.
The returning object is Crtemp. It removes all entries when #close-d.
With block, the created directory will be removed after block is left. The block form now uses a functional helper under the hood to guarantee cleanup.
Dir.mktmpdir do |dir|
# work with dir
end
Functional API
This library now exposes a small functional-style API via FunctionalCrtemp. It keeps resource management explicit and returns Result values for fallible operations.
Block-style (guaranteed cleanup):
FunctionalCrtemp.with_crtemp do |path|
# use path (directory is removed after the block)
end
Non-block creation (explicit handle, success wrapped in a Result):
res = FunctionalCrtemp.create
if res.success?
info = res.value!
# info.path is the directory path
info.close
else
STDERR.puts res.error!.message
end
create_tempfile_result now returns a TempdirResult::Result(String, Crtemp::Error):
res = FunctionalCrtemp.create
info = res.value!
file_res = info.create_tempfile("myprefix_")
if file_res.success?
path = file_res.value!
# use the file
else
STDERR.puts file_res.error!.message
end
info.close
Migration note
Existing code that used Crtemp.new or Dir.mktmpdir can keep working. Dir.mktmpdir still supports the block form and the non-block form now returns a value-like FunctionalCrtemp::Info (the non-block Dir.mktmpdir will raise on creation failure). If you prefer non-raising, switch to FunctionalCrtemp.create which returns an explicit Result you can handle.
Note: The deprecated create_tempfile method has been removed. Use create_tempfile_result instead for all temporary file creation.
Migration Guide
Before (v1.2.1 of original tempdir library):
require "tempdir"
# Using deprecated create_tempfile method
tempdir = Tempdir.new
path = tempdir.create_tempfile("prefix_")
puts path if path
# Or with exception handling
begin
path = tempdir.create_tempfile("prefix_", raise_on_failure: true)
rescue ex : Tempdir::TempfileError
puts ex.message
end
After (v0.1.0 crtemp):
require "crtemp"
# Using Result-based create_tempfile_result
crtemp = Crtemp.new
result = crtemp.create_tempfile_result("prefix_")
if result.success?
path = result.value!
puts path
else
# handle error
puts result.error!.message
end
# Block form remains unchanged and is recommended
Dir.mktmpdir do |dir|
result = dir.create_tempfile_result("prefix_")
if result.success?
# use result.value!
end
end
For new code, prefer the functional API:
# Functional approach with automatic cleanup
FunctionalCrtemp.with_crtemp do |dir_path|
# work with dir_path
file_result = FunctionalCrtemp.create.then { |info| info.create_tempfile("prefix_") }
if file_result.success?
# use file_result.value!
end
end
Crtemp
The temporary directory class based on Dir.
This class only rewrites the #close method to remove entries in the directory.
create_tempfile_result
Create a secure tempfile inside the crtemp using atomic mkstemp:
Dir.mktmpdir do |dir|
result = dir.create_tempfile_result("myfile_", data: Slice(UInt8).new([1, 2, 3]))
if result.success?
path = result.value!
# path is the created file path with 0o600 permissions
end
end
The data parameter is optional. If provided, writes the bytes atomically. The file is created with owner-only permissions (0o600) where supported.
Security
- Directories are created with
0o700permissions (owner-only). - Files created via
create_tempfile_resultusemkstempfor atomic creation and are set to0o600(owner read/write only). - On Unix, uses
mkdtemp/mkstempfor atomic creation avoiding TOCTOU races. - On Windows, falls back to
CreateFileAwithCREATE_NEWflag for atomic semantics.
Development
crystal spec
Contributing
- Fork it (https://github.com/kritoke/crtemp/fork)
- Create your feature branch (
git checkout -b my-new-feature) - Commit your changes (
git commit -am 'Add some feature') - Push to the branch (
git push origin my-new-feature) - Create a new Pull Request
License
MIT
crtemp
- 0
- 0
- 0
- 1
- 0
- 15 days ago
- February 23, 2026
MIT License
Sun, 15 Mar 2026 15:09:15 GMT