-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement File.tempfile
in Crystal
#12111
Changes from all commits
6873663
1829803
3d74c03
f5bd3d5
860b89b
a1dfefa
1b1fa0a
da1491d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -47,6 +47,43 @@ module Crystal::System::File | |
m | o | ||
end | ||
|
||
LOWER_ALPHANUM = "0123456789abcdefghijklmnopqrstuvwxyz".to_slice | ||
|
||
def self.mktemp(prefix : String?, suffix : String?, dir : String, random : ::Random = ::Random::DEFAULT) : {LibC::Int, String} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there a reason the name generation logic here needs to be distinct from There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think I considered the implications for |
||
mode = LibC::O_RDWR | LibC::O_CREAT | LibC::O_EXCL | ||
perm = ::File::Permissions.new(0o600) | ||
|
||
prefix = ::File.join(dir, prefix || "") | ||
bytesize = prefix.bytesize + 8 + (suffix.try(&.bytesize) || 0) | ||
|
||
100.times do | ||
path = String.build(bytesize) do |io| | ||
io << prefix | ||
8.times do | ||
io.write_byte LOWER_ALPHANUM.sample(random) | ||
end | ||
io << suffix | ||
end | ||
|
||
fd, errno = open(path, mode, perm) | ||
|
||
if errno.none? | ||
return {fd, path} | ||
elsif error_is_file_exists?(errno) | ||
# retry | ||
next | ||
else | ||
raise ::File::Error.from_os_error("Error creating temporary file", errno, file: path) | ||
end | ||
end | ||
|
||
raise ::File::AlreadyExistsError.new("Error creating temporary file", file: "#{prefix}********#{suffix}") | ||
end | ||
|
||
private def self.error_is_file_exists?(errno) | ||
Errno.value.in?(Errno::EEXIST, WinError::ERROR_ALREADY_EXISTS) | ||
end | ||
|
||
# Closes the internal file descriptor without notifying libevent. | ||
# This is directly used after the fork of a process to close the | ||
# parent's Crystal::Signal.@@pipe reference before re initializing | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,6 +10,7 @@ lib LibC | |
FD_CLOEXEC = 1 | ||
O_CLOEXEC = 0 | ||
O_CREAT = 1_u16 << 12 | ||
O_EXCL = 4_u16 << 12 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just asking, did you go through the system headers of all supported systems to grab those There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't recall doing that explicitly. That's the problem with ridiculously long review timespans (poke @beta-ziliani 😏). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is the WASI definition I could find: https://github.com/WebAssembly/wasi-libc/blob/8daaba387ce70a6088afe3916e9e16ed1c2bc630/libc-bottom-half/headers/public/__header_fcntl.h Then it looks like Linux uses |
||
O_NOFOLLOW = 0x01000000 | ||
O_TRUNC = 8_u16 << 12 | ||
O_APPEND = 1_u16 | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't this be private?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's in the
Crystal::System
namespace, so inherently non-public.