diff --git a/NEWS.md b/NEWS.md index fac6843a88e50..f4966babc60ae 100644 --- a/NEWS.md +++ b/NEWS.md @@ -29,6 +29,10 @@ Build system changes New library functions --------------------- + +* The new `Libc.mkfifo` function wraps the `mkfifo` C function on Unix platforms ([#34587]). +* `hardlink(src, dst)` can be used to create hard links. ([#41639]) +* `diskstat(path=pwd())` can be used to return statistics about the disk. ([#42248]) * `copyuntil(out, io, delim)` and `copyline(out, io)` copy data into an `out::IO` stream ([#48273]). New library features diff --git a/base/libc.jl b/base/libc.jl index be3db81e32503..07deeca4f46a4 100644 --- a/base/libc.jl +++ b/base/libc.jl @@ -12,7 +12,7 @@ import Core.Intrinsics: bitcast export FILE, TmStruct, strftime, strptime, getpid, gethostname, free, malloc, memcpy, memmove, memset, calloc, realloc, errno, strerror, flush_cstdio, systemsleep, time, - transcode + transcode, mkfifo if Sys.iswindows() export GetLastError, FormatMessage end @@ -437,6 +437,33 @@ function srand(seed::Integer=_make_uint64_seed()) ccall(:jl_srand, Cvoid, (UInt64,), seed % UInt64) end +""" + mkfifo(path::AbstractString, [mode::Integer]) -> path + +Make a FIFO special file (a named pipe) at `path`. Return `path` as-is on success. + +`mkfifo` is supported only in Unix platforms. + +!!! compat "Julia 1.8" + `mkfifo` requires at least Julia 1.8. +""" +function mkfifo( + path::AbstractString, + mode::Integer = Base.S_IRUSR | Base.S_IWUSR | Base.S_IRGRP | Base.S_IWGRP | + Base.S_IROTH | Base.S_IWOTH, +) + @static if Sys.isunix() + # Default `mode` is compatible with `mkfifo` CLI in coreutils. + ret = ccall(:mkfifo, Cint, (Cstring, Base.Cmode_t), path, mode) + systemerror("mkfifo", ret == -1) + return path + else + # Using normal `error` because `systemerror("mkfifo", ENOTSUP)` does not + # seem to work on Windows. + error("mkfifo: Operation not supported") + end +end + struct Cpasswd username::Cstring uid::Culong diff --git a/doc/src/base/libc.md b/doc/src/base/libc.md index 643543c8afc5f..c0448b04d9db7 100644 --- a/doc/src/base/libc.md +++ b/doc/src/base/libc.md @@ -20,4 +20,5 @@ Base.Libc.TmStruct Base.Libc.FILE Base.Libc.flush_cstdio Base.Libc.systemsleep +Base.Libc.mkfifo ``` diff --git a/test/file.jl b/test/file.jl index 1d2ac4c6f9132..b392ffb3e8161 100644 --- a/test/file.jl +++ b/test/file.jl @@ -1636,6 +1636,28 @@ end end end +if Sys.isunix() + @testset "mkfifo" begin + mktempdir() do dir + path = Libc.mkfifo(joinpath(dir, "fifo")) + @sync begin + @async write(path, "hello") + cat_exec = `$(Base.julia_cmd()) --startup-file=no -e "write(stdout, read(ARGS[1]))"` + @test read(`$cat_exec $path`, String) == "hello" + end + + existing_file = joinpath(dir, "existing") + write(existing_file, "") + @test_throws SystemError Libc.mkfifo(existing_file) + end + end +else + @test_throws( + "mkfifo: Operation not supported", + Libc.mkfifo(joinpath(pwd(), "dummy_path")), + ) +end + @testset "chmod/isexecutable" begin mktempdir() do dir mkdir(joinpath(dir, "subdir"))