• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

JuliaLang / julia / #37728

26 Mar 2024 03:46AM UTC coverage: 80.612% (-0.8%) from 81.423%
#37728

push

local

web-flow
Update zlib to 1.3.1 (#53841)

Released January 22, 2024

69920 of 86737 relevant lines covered (80.61%)

14456248.65 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

62.89
/base/libc.jl
1
# This file is a part of Julia. License is MIT: https://julialang.org/license
2

3
module Libc
4
@doc """
5
Interface to libc, the C standard library.
6
""" Libc
7

8
import Base: transcode, windowserror, show
9
# these need to be defined separately for bootstrapping but belong to Libc
10
import Base: memcpy, memmove, memset, memcmp
11
import Core.Intrinsics: bitcast
12

13
export FILE, TmStruct, strftime, strptime, getpid, gethostname, free, malloc, memcpy,
14
    memmove, memset, calloc, realloc, errno, strerror, flush_cstdio, systemsleep, time,
15
    transcode, mkfifo
16
if Sys.iswindows()
17
    export GetLastError, FormatMessage
18
end
19

20
include(string(length(Core.ARGS) >= 2 ? Core.ARGS[2] : "", "errno_h.jl"))  # include($BUILDROOT/base/errno_h.jl)
21

22
## RawFD ##
23

24
# Wrapper for an OS file descriptor (on both Unix and Windows)
25
"""
26
    RawFD
27

28
Primitive type which wraps the native OS file descriptor.
29
`RawFD`s can be passed to methods like [`stat`](@ref) to
30
discover information about the underlying file, and can
31
also be used to open streams, with the `RawFD` describing
32
the OS file backing the stream.
33
"""
34
primitive type RawFD 32 end
35
RawFD(fd::Integer) = bitcast(RawFD, Cint(fd))
13,076✔
36
RawFD(fd::RawFD) = fd
×
37
Base.cconvert(::Type{Cint}, fd::RawFD) = bitcast(Cint, fd)
3,038✔
38

39
dup(x::RawFD) = ccall((@static Sys.iswindows() ? :_dup : :dup), RawFD, (RawFD,), x)
7✔
40
dup(src::RawFD, target::RawFD) = systemerror("dup", -1 ==
269✔
41
    ccall((@static Sys.iswindows() ? :_dup2 : :dup2), Int32,
42
                (RawFD, RawFD), src, target))
43

44
show(io::IO, fd::RawFD) = print(io, "RawFD(", bitcast(Int32, fd), ')')  # avoids invalidation via show_default
11✔
45

46
# Wrapper for an OS file descriptor (for Windows)
47
if Sys.iswindows()
48
    @doc """
49
        WindowsRawSocket
50

51
    Primitive type which wraps the native Windows file `HANDLE`.
52
    """
53
    primitive type WindowsRawSocket sizeof(Ptr) * 8 end # On Windows file descriptors are HANDLE's and 64-bit on 64-bit Windows
54
    WindowsRawSocket(handle::Ptr{Cvoid}) = bitcast(WindowsRawSocket, handle)
×
55
    WindowsRawSocket(handle::WindowsRawSocket) = handle
×
56

57
    Base.cconvert(::Type{Ptr{Cvoid}}, fd::WindowsRawSocket) = bitcast(Ptr{Cvoid}, fd)
×
58
    _get_osfhandle(fd::RawFD) = ccall(:_get_osfhandle, WindowsRawSocket, (RawFD,), fd)
×
59
    _get_osfhandle(fd::WindowsRawSocket) = fd
×
60
    function dup(src::WindowsRawSocket)
×
61
        new_handle = Ref(WindowsRawSocket(Ptr{Cvoid}(-1)))
×
62
        my_process = ccall(:GetCurrentProcess, stdcall, Ptr{Cvoid}, ())
×
63
        DUPLICATE_SAME_ACCESS = 0x2
×
64
        status = ccall(:DuplicateHandle, stdcall, Int32,
×
65
            (Ptr{Cvoid}, WindowsRawSocket, Ptr{Cvoid}, Ptr{WindowsRawSocket}, UInt32, Int32, UInt32),
66
            my_process, src, my_process, new_handle, 0, false, DUPLICATE_SAME_ACCESS)
67
        windowserror("dup failed", status == 0)
×
68
        return new_handle[]
×
69
    end
70
    function dup(src::WindowsRawSocket, target::RawFD)
×
71
        fd = ccall(:_open_osfhandle, RawFD, (WindowsRawSocket, Int32), dup(src), 0)
×
72
        dup(fd, target)
×
73
        ccall(:_close, Int32, (RawFD,), fd)
×
74
        nothing
×
75
    end
76

77
else
78
    _get_osfhandle(fd::RawFD) = fd
×
79
end
80

81
## FILE (not auto-finalized) ##
82

83
"""
84
    FILE(::Ptr)
85
    FILE(::IO)
86

87
A libc `FILE*`, representing an opened file.
88

89
It can be passed as a `Ptr{FILE}` argument to [`ccall`](@ref) and also supports
90
[`seek`](@ref), [`position`](@ref) and [`close`](@ref).
91

92
A `FILE` can be constructed from an ordinary `IO` object, provided it is an open file. It
93
must be closed afterward.
94

95
# Examples
96
```jldoctest
97
julia> using Base.Libc
98

99
julia> mktemp() do _, io
100
           # write to the temporary file using `puts(char*, FILE*)` from libc
101
           file = FILE(io)
102
           ccall(:fputs, Cint, (Cstring, Ptr{FILE}), "hello world", file)
103
           close(file)
104
           # read the file again
105
           seek(io, 0)
106
           read(io, String)
107
       end
108
"hello world"
109
```
110
"""
111
struct FILE
112
    ptr::Ptr{Cvoid}
8✔
113
end
114

115
modestr(s::IO) = modestr(isreadable(s), iswritable(s))
7✔
116
modestr(r::Bool, w::Bool) = r ? (w ? "r+" : "r") : (w ? "w" : throw(ArgumentError("neither readable nor writable")))
8✔
117

118
function FILE(fd::RawFD, mode)
8✔
119
    FILEp = ccall((@static Sys.iswindows() ? :_fdopen : :fdopen), Ptr{Cvoid}, (Cint, Cstring), fd, mode)
8✔
120
    systemerror("fdopen", FILEp == C_NULL)
8✔
121
    FILE(FILEp)
8✔
122
end
123

124
function FILE(s::IO)
7✔
125
    f = FILE(dup(RawFD(fd(s))),modestr(s))
7✔
126
    seek(f, position(s))
7✔
127
    f
7✔
128
end
129

130
Base.unsafe_convert(T::Union{Type{Ptr{Cvoid}},Type{Ptr{FILE}}}, f::FILE) = convert(T, f.ptr)
2✔
131
Base.close(f::FILE) = systemerror("fclose", ccall(:fclose, Cint, (Ptr{Cvoid},), f.ptr) != 0)
8✔
132

133
function Base.seek(h::FILE, offset::Integer)
134
    systemerror("fseek", ccall(:fseek, Cint, (Ptr{Cvoid}, Clong, Cint),
9✔
135
                               h.ptr, offset, 0) != 0)
136
    h
9✔
137
end
138

139
Base.position(h::FILE) = ccall(:ftell, Clong, (Ptr{Cvoid},), h.ptr)
4✔
140

141
# flush C stdio output from external libraries
142

143
"""
144
    flush_cstdio()
145

146
Flushes the C `stdout` and `stderr` streams (which may have been written to by external C code).
147
"""
148
flush_cstdio() = ccall(:jl_flush_cstdio, Cvoid, ())
1✔
149

150
## time-related functions ##
151

152
# TODO: check for usleep errors?
153
if Sys.isunix()
154
    systemsleep(s::Real) = ccall(:usleep, Int32, (UInt32,), round(UInt32, s*1e6))
2✔
155
elseif Sys.iswindows()
156
    function systemsleep(s::Real)
×
157
        ccall(:Sleep, stdcall, Cvoid, (UInt32,), round(UInt32, s * 1e3))
×
158
        return Int32(0)
×
159
    end
160
else
161
    error("systemsleep undefined for this OS")
162
end
163
"""
164
    systemsleep(s::Real)
165

166
Suspends execution for `s` seconds.
167
This function does not yield to Julia's scheduler and therefore blocks
168
the Julia thread that it is running on for the duration of the sleep time.
169

170
See also [`sleep`](@ref).
171
"""
172
systemsleep
173

174
struct TimeVal
175
   sec::Int64
176
   usec::Int64
177
end
178

179
function TimeVal()
180
    tv = Ref{TimeVal}()
30✔
181
    status = ccall(:jl_gettimeofday, Cint, (Ref{TimeVal},), tv)
30✔
182
    status != 0 && error("unable to determine current time: ", status)
30✔
183
    return tv[]
30✔
184
end
185

186
"""
187
    TmStruct([seconds])
188

189
Convert a number of seconds since the epoch to broken-down format, with fields `sec`, `min`,
190
`hour`, `mday`, `month`, `year`, `wday`, `yday`, and `isdst`.
191
"""
192
mutable struct TmStruct
193
    sec::Int32
194
    min::Int32
195
    hour::Int32
196
    mday::Int32
197
    month::Int32
198
    year::Int32
199
    wday::Int32
200
    yday::Int32
201
    isdst::Int32
202
    # on some platforms the struct is 14 words, even though 9 are specified
203
    _10::Int32
204
    _11::Int32
205
    _12::Int32
206
    _13::Int32
207
    _14::Int32
208

209
    TmStruct(sec, min, hour, mday, month, year, wday, yday, isdst) =
1✔
210
        new(sec, min, hour, mday, month, year, wday, yday, isdst, 0,0,0,0,0)
211
    TmStruct() = new(0,0,0,0,0,0,0,0,0,0,0,0,0,0)
63✔
212
    function TmStruct(t::Real)
56✔
213
        t = floor(t)
34✔
214
        tm = TmStruct()
56✔
215
        # TODO: add support for UTC via gmtime_r()
216
        ccall(:localtime_r, Ptr{TmStruct}, (Ref{Int}, Ref{TmStruct}), t, tm)
56✔
217
        return tm
56✔
218
    end
219
end
220

221
"""
222
    strftime([format], time)
223

224
Convert time, given as a number of seconds since the epoch or a `TmStruct`, to a formatted
225
string using the given format. Supported formats are the same as those in the standard C
226
library.
227
"""
228
strftime(t) = strftime("%c", t)
×
229
strftime(fmt::AbstractString, t::Real) = strftime(fmt, TmStruct(t))
26✔
230
# Use wcsftime instead of strftime to support different locales
231
function strftime(fmt::AbstractString, tm::TmStruct)
32✔
232
    wctimestr = Vector{Cwchar_t}(undef, 128)
32✔
233
    n = ccall(:wcsftime, Csize_t, (Ptr{Cwchar_t}, Csize_t, Cwstring, Ref{TmStruct}),
32✔
234
              wctimestr, length(wctimestr), fmt, tm)
235
    n == 0 && return ""
32✔
236
    return transcode(String, resize!(wctimestr, n))
32✔
237
end
238

239
"""
240
    strptime([format], timestr)
241

242
Parse a formatted time string into a `TmStruct` giving the seconds, minute, hour, date, etc.
243
Supported formats are the same as those in the standard C library. On some platforms,
244
timezones will not be parsed correctly. If the result of this function will be passed to
245
`time` to convert it to seconds since the epoch, the `isdst` field should be filled in
246
manually. Setting it to `-1` will tell the C library to use the current system settings to
247
determine the timezone.
248
"""
249
strptime(timestr::AbstractString) = strptime("%c", timestr)
×
250
function strptime(fmt::AbstractString, timestr::AbstractString)
7✔
251
    tm = TmStruct()
7✔
252
    r = ccall(:strptime, Cstring, (Cstring, Cstring, Ref{TmStruct}), timestr, fmt, tm)
7✔
253
    # the following would tell mktime() that this is a local time, and that
254
    # it should try to guess the timezone. not sure if/how this should be
255
    # exposed in the API.
256
    # tm.isdst = -1
257
    if r == C_NULL
7✔
258
        # TODO: better error message
259
        throw(ArgumentError("invalid arguments"))
×
260
    end
261
    @static if Sys.isapple()
262
        # if we didn't explicitly parse the weekday or year day, use mktime
263
        # to fill them in automatically.
264
        if !occursin(r"([^%]|^)%(a|A|j|w|Ow)"a, fmt)
265
            ccall(:mktime, Int, (Ref{TmStruct},), tm)
266
        end
267
    end
268
    return tm
7✔
269
end
270

271
# system date in seconds
272

273
"""
274
    time(t::TmStruct) -> Float64
275

276
Converts a `TmStruct` struct to a number of seconds since the epoch.
277
"""
278
time(tm::TmStruct) = Float64(ccall(:mktime, Int, (Ref{TmStruct},), tm))
×
279

280
"""
281
    time() -> Float64
282

283
Get the system time in seconds since the epoch, with fairly high (typically, microsecond) resolution.
284
"""
285
time() = ccall(:jl_clock_now, Float64, ())
43,694✔
286

287
## process-related functions ##
288

289
"""
290
    getpid() -> Int32
291

292
Get Julia's process ID.
293
"""
294
getpid() = ccall(:uv_os_getpid, Int32, ())
177✔
295

296
## network functions ##
297

298
"""
299
    gethostname() -> String
300

301
Get the local machine's host name.
302
"""
303
function gethostname()
1✔
304
    hn = Vector{UInt8}(undef, 256)
47✔
305
    err = @static if Sys.iswindows()
306
        ccall(:gethostname, stdcall, Int32, (Ptr{UInt8}, UInt32), hn, length(hn))
307
    else
308
        ccall(:gethostname, Int32, (Ptr{UInt8}, UInt), hn, length(hn))
47✔
309
    end
310
    systemerror("gethostname", err != 0)
47✔
311
    return GC.@preserve hn unsafe_string(pointer(hn))
47✔
312
end
313

314
## system error handling ##
315

316
"""
317
    errno([code])
318

319
Get the value of the C library's `errno`. If an argument is specified, it is used to set the
320
value of `errno`.
321

322
The value of `errno` is only valid immediately after a `ccall` to a C library routine that
323
sets it. Specifically, you cannot call `errno` at the next prompt in a REPL, because lots of
324
code is executed between prompts.
325
"""
326
errno() = ccall(:jl_errno, Cint, ())
39,513✔
327
errno(e::Integer) = ccall(:jl_set_errno, Cvoid, (Cint,), e)
39,499✔
328

329
"""
330
    strerror(n=errno())
331

332
Convert a system call error code to a descriptive string
333
"""
334
strerror(e::Integer) = unsafe_string(ccall(:strerror, Cstring, (Int32,), e))
8✔
335
strerror() = strerror(errno())
×
336

337
"""
338
    GetLastError()
339

340
Call the Win32 `GetLastError` function [only available on Windows].
341
"""
342
function GetLastError end
343

344
"""
345
    FormatMessage(n=GetLastError())
346

347
Convert a Win32 system call error code to a descriptive string [only available on Windows].
348
"""
349
function FormatMessage end
350

351
if Sys.iswindows()
352
    GetLastError() = ccall(:GetLastError, stdcall, UInt32, ())
×
353

354
    FormatMessage(e) = FormatMessage(UInt32(e))
×
355
    function FormatMessage(e::UInt32=GetLastError())
×
356
        FORMAT_MESSAGE_ALLOCATE_BUFFER = UInt32(0x100)
×
357
        FORMAT_MESSAGE_FROM_SYSTEM = UInt32(0x1000)
×
358
        FORMAT_MESSAGE_IGNORE_INSERTS = UInt32(0x200)
×
359
        FORMAT_MESSAGE_MAX_WIDTH_MASK = UInt32(0xFF)
×
360
        lpMsgBuf = Ref{Ptr{UInt16}}()
×
361
        lpMsgBuf[] = 0
×
362
        len = ccall(:FormatMessageW, stdcall, UInt32, (UInt32, Ptr{Cvoid}, UInt32, UInt32, Ptr{Ptr{UInt16}}, UInt32, Ptr{Cvoid}),
×
363
                    FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_MAX_WIDTH_MASK,
364
                    C_NULL, e, 0, lpMsgBuf, 0, C_NULL)
365
        p = lpMsgBuf[]
×
366
        len == 0 && return ""
×
367
        buf = Vector{UInt16}(undef, len)
×
368
        GC.@preserve buf unsafe_copyto!(pointer(buf), p, len)
×
369
        ccall(:LocalFree, stdcall, Ptr{Cvoid}, (Ptr{Cvoid},), p)
×
370
        return transcode(String, buf)
×
371
    end
372
end
373

374
## Memory related ##
375
"""
376
    free(addr::Ptr)
377

378
Call `free` from the C standard library. Only use this on memory obtained from [`malloc`](@ref), not
379
on pointers retrieved from other C libraries. [`Ptr`](@ref) objects obtained from C libraries should
380
be freed by the free functions defined in that library, to avoid assertion failures if
381
multiple `libc` libraries exist on the system.
382
"""
383
free(p::Ptr) = ccall(:free, Cvoid, (Ptr{Cvoid},), p)
379,712✔
384
free(p::Cstring) = free(convert(Ptr{UInt8}, p))
1✔
385
free(p::Cwstring) = free(convert(Ptr{Cwchar_t}, p))
×
386

387
"""
388
    malloc(size::Integer) -> Ptr{Cvoid}
389

390
Call `malloc` from the C standard library.
391
"""
392
malloc(size::Integer) = ccall(:malloc, Ptr{Cvoid}, (Csize_t,), size)
381,392✔
393

394
"""
395
    realloc(addr::Ptr, size::Integer) -> Ptr{Cvoid}
396

397
Call `realloc` from the C standard library.
398

399
See warning in the documentation for [`free`](@ref) regarding only using this on memory originally
400
obtained from [`malloc`](@ref).
401
"""
402
realloc(p::Ptr, size::Integer) = ccall(:realloc, Ptr{Cvoid}, (Ptr{Cvoid}, Csize_t), p, size)
×
403

404
"""
405
    calloc(num::Integer, size::Integer) -> Ptr{Cvoid}
406

407
Call `calloc` from the C standard library.
408
"""
409
calloc(num::Integer, size::Integer) = ccall(:calloc, Ptr{Cvoid}, (Csize_t, Csize_t), num, size)
×
410

411

412

413
## Random numbers ##
414

415
# Access to very high quality (kernel) randomness
416
function getrandom!(A::Union{Array,Base.RefValue})
417
    ret = ccall(:uv_random, Cint, (Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}, Csize_t,   Cuint, Ptr{Cvoid}),
48,653✔
418
                                   C_NULL,     C_NULL,     A,          sizeof(A), 0,     C_NULL)
419
    Base.uv_error("getrandom", ret)
48,653✔
420
    return A
48,653✔
421
end
422
_make_uint64_seed() = getrandom!(Base.RefValue{UInt64}())[]
1✔
423

424
# To limit dependency on rand functionality implemented in the Random module,
425
# Libc.rand is used in Base (it also is independent from Random.seed, so is
426
# only affected by `Libc.srand(seed)` calls)
427
"""
428
    rand([T::Type]=UInt32)
429

430
Generate a random number of type `T`. `T` can be `UInt32` or `Float64`.
431
"""
432
rand() = ccall(:jl_rand, UInt64, ()) % UInt32
9,363✔
433
rand(::Type{UInt32}) = rand()
×
434
rand(::Type{Float64}) = rand() * 2.0^-32
143✔
435

436
"""
437
    srand([seed])
438

439
Set a value for the current global `seed`.
440
"""
441
function srand(seed::Integer=_make_uint64_seed())
2✔
442
    ccall(:jl_srand, Cvoid, (UInt64,), seed % UInt64)
3✔
443
end
444

445
"""
446
    mkfifo(path::AbstractString, [mode::Integer]) -> path
447

448
Make a FIFO special file (a named pipe) at `path`.  Return `path` as-is on success.
449

450
`mkfifo` is supported only in Unix platforms.
451

452
!!! compat "Julia 1.11"
453
    `mkfifo` requires at least Julia 1.11.
454
"""
455
function mkfifo(
2✔
456
    path::AbstractString,
457
    mode::Integer = Base.S_IRUSR | Base.S_IWUSR | Base.S_IRGRP | Base.S_IWGRP |
458
                    Base.S_IROTH | Base.S_IWOTH,
459
)
460
    @static if Sys.isunix()
4✔
461
        # Default `mode` is compatible with `mkfifo` CLI in coreutils.
462
        ret = ccall(:mkfifo, Cint, (Cstring, Base.Cmode_t), path, mode)
2✔
463
        systemerror("mkfifo", ret == -1)
2✔
464
        return path
1✔
465
    else
466
        # Using normal `error` because `systemerror("mkfifo", ENOTSUP)` does not
467
        # seem to work on Windows.
468
        error("mkfifo: Operation not supported")
469
    end
470
end
471

472
struct Cpasswd
473
   username::Cstring
474
   uid::Culong
475
   gid::Culong
476
   shell::Cstring
477
   homedir::Cstring
478
   gecos::Cstring
479
   Cpasswd() = new(C_NULL, typemax(Culong), typemax(Culong), C_NULL, C_NULL, C_NULL)
7✔
480
end
481
mutable struct Cgroup
482
    groupname::Cstring # group name
483
    gid::Culong        # group ID
484
    mem::Ptr{Cstring}  # group members
485
    Cgroup() = new(C_NULL, typemax(Culong), C_NULL)
7✔
486
end
487
struct Passwd
488
    username::String
7✔
489
    uid::UInt
490
    gid::UInt
491
    shell::String
492
    homedir::String
493
    gecos::String
494
end
495
struct Group
496
    groupname::String
7✔
497
    gid::UInt
498
    mem::Vector{String}
499
end
500

501
# Gets password-file entry for default user, or a subset thereof
502
# (e.g., uid and guid are set to -1 on Windows)
503
function getpw()
×
504
    ref_pd = Ref(Cpasswd())
×
505
    ret = ccall(:uv_os_get_passwd, Cint, (Ref{Cpasswd},), ref_pd)
×
506
    Base.uv_error("getpw", ret)
×
507

508
    pd = ref_pd[]
×
509
    pd = Passwd(
×
510
        pd.username == C_NULL ? "" : unsafe_string(pd.username),
511
        pd.uid,
512
        pd.gid,
513
        pd.shell == C_NULL ? "" : unsafe_string(pd.shell),
514
        pd.homedir == C_NULL ? "" : unsafe_string(pd.homedir),
515
        pd.gecos == C_NULL ? "" : unsafe_string(pd.gecos),
516
    )
517
    ccall(:uv_os_free_passwd, Cvoid, (Ref{Cpasswd},), ref_pd)
×
518
    return pd
×
519
end
520

521
function getpwuid(uid::Unsigned, throw_error::Bool=true)
7✔
522
    ref_pd = Ref(Cpasswd())
7✔
523
    ret = ccall(:uv_os_get_passwd2, Cint, (Ref{Cpasswd}, Culong), ref_pd, uid)
7✔
524
    if ret != 0
7✔
525
        throw_error && Base.uv_error("getpwuid", ret)
×
526
        return
×
527
    end
528
    pd = ref_pd[]
7✔
529
    pd = Passwd(
14✔
530
        pd.username == C_NULL ? "" : unsafe_string(pd.username),
531
        pd.uid,
532
        pd.gid,
533
        pd.shell == C_NULL ? "" : unsafe_string(pd.shell),
534
        pd.homedir == C_NULL ? "" : unsafe_string(pd.homedir),
535
        pd.gecos == C_NULL ? "" : unsafe_string(pd.gecos),
536
    )
537
    ccall(:uv_os_free_passwd, Cvoid, (Ref{Cpasswd},), ref_pd)
7✔
538
    return pd
7✔
539
end
540

541
function getgrgid(gid::Unsigned, throw_error::Bool=true)
7✔
542
    ref_gp = Ref(Cgroup())
7✔
543
    ret = ccall(:uv_os_get_group, Cint, (Ref{Cgroup}, Culong), ref_gp, gid)
7✔
544
    if ret != 0
7✔
545
        throw_error && Base.uv_error("getgrgid", ret)
×
546
        return
×
547
    end
548
    gp = ref_gp[]
7✔
549
    members = String[]
7✔
550
    if gp.mem != C_NULL
7✔
551
        while true
14✔
552
            mem = unsafe_load(gp.mem, length(members) + 1)
14✔
553
            mem == C_NULL && break
14✔
554
            push!(members, unsafe_string(mem))
7✔
555
        end
7✔
556
    end
557
    gp = Group(
14✔
558
         gp.groupname == C_NULL ? "" : unsafe_string(gp.groupname),
559
         gp.gid,
560
         members,
561
    )
562
    ccall(:uv_os_free_group, Cvoid, (Ref{Cgroup},), ref_gp)
7✔
563
    return gp
7✔
564
end
565

566
getuid() = ccall(:jl_getuid, Culong, ())
1✔
567
geteuid() = ccall(:jl_geteuid, Culong, ())
3✔
568

569
# Include dlopen()/dlpath() code
570
include("libdl.jl")
571

572
end # module
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc