mirror of
https://github.com/odin-lang/Odin.git
synced 2026-05-28 06:35:11 +00:00
479 lines
12 KiB
Odin
479 lines
12 KiB
Odin
#+build linux, darwin, openbsd, freebsd, netbsd
|
|
package posix
|
|
|
|
import "core:c"
|
|
|
|
when ODIN_OS == .Darwin {
|
|
foreign import lib "system:System"
|
|
} else {
|
|
foreign import lib "system:c"
|
|
}
|
|
|
|
// fcntl.h - file control options
|
|
|
|
foreign lib {
|
|
/*
|
|
Implemented as `return open(path, O_WRONLY|O_CREAT|O_TRUNC, mode);`
|
|
|
|
[[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/creat.html ]]
|
|
*/
|
|
creat :: proc(path: cstring, mode: mode_t) -> FD ---
|
|
|
|
/*
|
|
Perform the operations on open files.
|
|
|
|
[[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/fcntl.html ]]
|
|
*/
|
|
fcntl :: proc(fd: FD, cmd: FCNTL_Cmd, #c_vararg args: ..any) -> c.int ---
|
|
|
|
/*
|
|
Establish the connection between a file and a file descriptor.
|
|
It shall create an open file description that refers to a file and a file descriptor that
|
|
refers to that open file description. The file descriptor is used by other I/O functions to
|
|
refer to that file.
|
|
The path argument points to a pathname naming the file
|
|
|
|
Returns: -1 on failure (setting errno), a file descriptor on success.
|
|
|
|
Example:
|
|
// The following example opens the file /tmp/file, either by creating it (if it does not already exist),
|
|
// or by truncating its length to 0 (if it does exist). In the former case, if the call creates a new file,
|
|
// the access permission bits in the file mode of the file are set to permit reading and writing by the owner,
|
|
// and to permit reading only by group members and others.
|
|
fd := posix.open("/tmp/file", { .WRONLY, .CREAT, .TRUNC }, { .IRUSR, .IWUSR, .IRGRP, .IROTH })
|
|
|
|
// The following example uses the open() function to try to create the LOCKFILE file and open it for writing.
|
|
// Since the open() function specifies the O_EXCL flag, the call fails if the file already exists.
|
|
// In that case, the program assumes that someone else is updating the password file and exits.
|
|
fd := posix.open("/etc/ptmp", { .WRONLY, .CREAT, .EXCL }, { .IRUSR, .IWUSR, .IRGRP, .IROTH })
|
|
if fd == -1 {
|
|
fmt.println("cannot open /etc/ptmp")
|
|
}
|
|
|
|
// The following example opens a file for writing, creating the file if it does not already exist.
|
|
// If the file does exist, the system truncates the file to zero bytes.
|
|
fd := posix.open("/etc/ptmp", { .WRONLY, .CREAT, .TRUNC }, { .IRUSR, .IWUSR, .IRGRP, .IROTH })
|
|
if fd == -1 {
|
|
fmt.println("cannot open output file")
|
|
}
|
|
|
|
[[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/open.html ]]
|
|
*/
|
|
open :: proc(path: cstring, flags: O_Flags, #c_vararg mode: ..mode_t) -> FD ---
|
|
|
|
/*
|
|
Equivalent to the open() function except in the case where path specifies a relative path.
|
|
In this case the file to be opened is determined relative to the directory associated with the
|
|
file descriptor fd instead of the current working directory.
|
|
|
|
Returns: -1 on failure (setting errno), a file descriptor on success.
|
|
|
|
[[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/open.html ]]
|
|
*/
|
|
openat :: proc(fd: FD, path: cstring, flags: O_Flags, #c_vararg mode: ..mode_t) -> FD ---
|
|
}
|
|
|
|
FCNTL_Cmd :: enum c.int {
|
|
DUPFD = F_DUPFD,
|
|
DUPFD_CLOEXEC = F_DUPFD_CLOEXEC,
|
|
GETFD = F_GETFD,
|
|
SETFD = F_SETFD,
|
|
GETFL = F_GETFL,
|
|
SETFL = F_SETFL,
|
|
GETLK = F_GETLK,
|
|
SETLK = F_SETLK,
|
|
SETLKW = F_SETLKW,
|
|
GETOWN = F_GETOWN,
|
|
SETOWN = F_SETOWN,
|
|
}
|
|
|
|
Lock_Type :: enum c.short {
|
|
RDLCK = F_RDLCK,
|
|
UNLCK = F_UNLCK,
|
|
WRLCK = F_WRLCK,
|
|
}
|
|
|
|
O_Flag_Bits :: enum c.int {
|
|
// Sets FD_CLOEXEC on the file descriptor.
|
|
CLOEXEC = log2(O_CLOEXEC),
|
|
// If not exists, combined with DIRECTORY will cause creation of a directory, otherwise a regular file.
|
|
CREAT = log2(O_CREAT),
|
|
// Fails if the opened descriptor would not be a directory.
|
|
DIRECTORY = log2(O_DIRECTORY),
|
|
// If combined with CREAT, causes a failure if the file already exists.
|
|
EXCL = log2(O_EXCL),
|
|
// If terminal device, do not make it the controlling terminal for the process.
|
|
NOCTTY = log2(O_NOCTTY),
|
|
// Don't follow symbolic links, fail with errno ELOOP.
|
|
NOFOLLOW = log2(O_NOFOLLOW),
|
|
// If exists and regular, truncate the length to 0.
|
|
TRUNC = log2(O_TRUNC),
|
|
|
|
// NOTE: use with `posix.O_TTY_INIT + { .OTHER_FLAG, .OTHER_FLAG }`, unfortunately can't be in
|
|
// this bit set enum because it is 0 on some platforms and a value on others.
|
|
// TTY_INIT = O_TTY_INIT,
|
|
|
|
// Set file offset to end of file prior to each write.
|
|
APPEND = log2(O_APPEND),
|
|
// Write I/O shall complete as defined by synchronized I/O data integrity completion.
|
|
DSYNC = log2(O_DSYNC),
|
|
// Causes nonblocking behaviour in various situations.
|
|
NONBLOCK = log2(O_NONBLOCK),
|
|
// Write I/O shall complete as defined by synchronized I/O file integrity completion.
|
|
SYNC = log2(O_SYNC),
|
|
|
|
// NOTE: use with `posix.O_RSYNC + { .OTHER_FLAG, .OTHER_FLAG }`, unfortunately can't be in
|
|
// this bit set enum because it is 0 on some platforms and a value on others.
|
|
// RSYNC = O_RSYNC,
|
|
|
|
// Execute only.
|
|
EXEC = log2(O_EXEC),
|
|
// Reading and writing.
|
|
RDWR = log2(O_RDWR),
|
|
// Writing only.
|
|
WRONLY = log2(O_WRONLY),
|
|
// Reading only.
|
|
// RDONLY = 0, // Default
|
|
}
|
|
|
|
O_Flags :: bit_set[O_Flag_Bits; c.int]
|
|
|
|
O_ACCMODE :: O_Flags{ .EXEC, .RDWR, .WRONLY }
|
|
|
|
AT_Flag_Bits :: enum c.int {
|
|
EACCESS = log2(AT_EACCESS),
|
|
SYMLINK_NOFOLLOW = log2(AT_SYMLINK_NOFOLLOW),
|
|
SYMLINK_FOLLOW = log2(AT_SYMLINK_FOLLOW),
|
|
REMOVEDIR = log2(AT_REMOVEDIR),
|
|
}
|
|
AT_Flags :: bit_set[AT_Flag_Bits; c.int]
|
|
|
|
when ODIN_OS == .Darwin {
|
|
|
|
off_t :: distinct c.int64_t
|
|
pid_t :: distinct c.int32_t
|
|
|
|
F_DUPFD :: 0
|
|
F_DUPFD_CLOEXEC :: 67
|
|
F_GETFD :: 1
|
|
F_SETFD :: 2
|
|
F_GETFL :: 3
|
|
F_SETFL :: 4
|
|
F_GETLK :: 7
|
|
F_SETLK :: 8
|
|
F_SETLKW :: 9
|
|
F_GETOWN :: 5
|
|
F_SETOWN :: 6
|
|
|
|
FD_CLOEXEC :: 1
|
|
|
|
F_RDLCK :: 1
|
|
F_UNLCK :: 2
|
|
F_WRLCK :: 3
|
|
|
|
O_CLOEXEC :: 0x01000000
|
|
O_CREAT :: 0x00000200
|
|
O_DIRECTORY :: 0x00100000
|
|
O_EXCL :: 0x00000800
|
|
O_NOCTTY :: 0x00020000
|
|
O_NOFOLLOW :: 0x00000100
|
|
O_TRUNC :: 0x00000400
|
|
|
|
_O_TTY_INIT :: 0
|
|
O_TTY_INIT :: O_Flags{}
|
|
|
|
O_APPEND :: 0x00000008
|
|
O_DSYNC :: 0x00400000
|
|
O_NONBLOCK :: 0x00000004
|
|
O_SYNC :: 0x0080
|
|
|
|
_O_RSYNC :: 0
|
|
O_RSYNC :: O_Flags{}
|
|
|
|
O_EXEC :: 0x40000000
|
|
O_RDONLY :: 0
|
|
O_RDWR :: 0x0002
|
|
O_WRONLY :: 0x0001
|
|
|
|
_O_SEARCH :: O_EXEC | O_DIRECTORY
|
|
O_SEARCH :: O_Flags{.EXEC, .DIRECTORY}
|
|
|
|
AT_FDCWD: FD: -2
|
|
|
|
AT_EACCESS :: 0x0010
|
|
AT_SYMLINK_NOFOLLOW :: 0x0020
|
|
AT_SYMLINK_FOLLOW :: 0x0040
|
|
AT_REMOVEDIR :: 0x0080
|
|
|
|
flock :: struct {
|
|
l_start: off_t, /* [PSX] relative offset in bytes */
|
|
l_len: off_t, /* [PSX] size; if 0 then until EOF */
|
|
l_pid: pid_t, /* [PSX] process ID of the process holding the lock */
|
|
l_type: Lock_Type, /* [PSX] type of lock */
|
|
l_whence: c.short, /* [PSX] flag (Whence) of starting offset */
|
|
}
|
|
|
|
} else when ODIN_OS == .FreeBSD {
|
|
|
|
off_t :: distinct c.int64_t
|
|
pid_t :: distinct c.int32_t
|
|
|
|
F_DUPFD :: 0
|
|
F_DUPFD_CLOEXEC :: 17
|
|
F_GETFD :: 1
|
|
F_SETFD :: 2
|
|
F_GETFL :: 3
|
|
F_SETFL :: 4
|
|
F_GETLK :: 7
|
|
F_SETLK :: 8
|
|
F_SETLKW :: 9
|
|
F_GETOWN :: 5
|
|
F_SETOWN :: 6
|
|
|
|
FD_CLOEXEC :: 1
|
|
|
|
F_RDLCK :: 1
|
|
F_UNLCK :: 2
|
|
F_WRLCK :: 3
|
|
|
|
O_CLOEXEC :: 0x00100000
|
|
O_CREAT :: 0x0200
|
|
O_DIRECTORY :: 0x00020000
|
|
O_EXCL :: 0x0800
|
|
O_NOCTTY :: 0x8000
|
|
O_NOFOLLOW :: 0x0100
|
|
O_TRUNC :: 0x0400
|
|
|
|
_O_TTY_INIT :: 0x00080000
|
|
O_TTY_INIT :: O_Flags{O_Flag_Bits(log2(_O_TTY_INIT))}
|
|
|
|
O_APPEND :: 0x0008
|
|
O_DSYNC :: 0x01000000
|
|
O_NONBLOCK :: 0x0004
|
|
O_SYNC :: 0x0080
|
|
_O_RSYNC :: 0
|
|
O_RSYNC :: O_Flags{} // NOTE: not defined in headers
|
|
|
|
O_EXEC :: 0x00040000
|
|
O_RDONLY :: 0
|
|
O_RDWR :: 0x0002
|
|
O_WRONLY :: 0x0001
|
|
|
|
_O_SEARCH :: O_EXEC
|
|
O_SEARCH :: O_Flags{ .EXEC }
|
|
|
|
AT_FDCWD: FD: -100
|
|
|
|
AT_EACCESS :: 0x0100
|
|
AT_SYMLINK_NOFOLLOW :: 0x0200
|
|
AT_SYMLINK_FOLLOW :: 0x0400
|
|
AT_REMOVEDIR :: 0x0800
|
|
|
|
flock :: struct {
|
|
l_start: off_t, /* [PSX] relative offset in bytes */
|
|
l_len: off_t, /* [PSX] size; if 0 then until EOF */
|
|
l_pid: pid_t, /* [PSX] process ID of the process holding the lock */
|
|
l_type: Lock_Type, /* [PSX] type of lock */
|
|
l_whence: c.short, /* [PSX] flag (Whence) of starting offset */
|
|
l_sysid: c.int,
|
|
}
|
|
|
|
} else when ODIN_OS == .NetBSD {
|
|
|
|
off_t :: distinct c.int64_t
|
|
pid_t :: distinct c.int32_t
|
|
|
|
F_DUPFD :: 0
|
|
F_DUPFD_CLOEXEC :: 12
|
|
F_GETFD :: 1
|
|
F_SETFD :: 2
|
|
F_GETFL :: 3
|
|
F_SETFL :: 4
|
|
F_GETLK :: 7
|
|
F_SETLK :: 8
|
|
F_SETLKW :: 9
|
|
F_GETOWN :: 5
|
|
F_SETOWN :: 6
|
|
|
|
FD_CLOEXEC :: 1
|
|
|
|
F_RDLCK :: 1
|
|
F_UNLCK :: 2
|
|
F_WRLCK :: 3
|
|
|
|
O_CLOEXEC :: 0x00400000
|
|
O_CREAT :: 0x0200
|
|
O_DIRECTORY :: 0x0020000
|
|
O_EXCL :: 0x0800
|
|
O_NOCTTY :: 0x8000
|
|
O_NOFOLLOW :: 0x0100
|
|
O_TRUNC :: 0x0400
|
|
|
|
_O_TTY_INIT :: 0
|
|
O_TTY_INIT :: O_Flags{} // NOTE: not defined in the headers
|
|
|
|
O_APPEND :: 0x0008
|
|
O_DSYNC :: 0x010000
|
|
O_NONBLOCK :: 0x0004
|
|
O_SYNC :: 0x0080
|
|
|
|
_O_RSYNC :: 0x0002
|
|
O_RSYNC :: O_Flags{O_Flag_Bits(log2(_O_RSYNC))}
|
|
|
|
|
|
O_EXEC :: 0x04000000
|
|
O_RDONLY :: 0
|
|
O_RDWR :: 0x0002
|
|
O_WRONLY :: 0x0001
|
|
|
|
_O_SEARCH :: 0x00800000
|
|
O_SEARCH :: O_Flags{O_Flag_Bits(log2(_O_SEARCH))}
|
|
|
|
AT_FDCWD: FD: -100
|
|
|
|
AT_EACCESS :: 0x100
|
|
AT_SYMLINK_NOFOLLOW :: 0x200
|
|
AT_SYMLINK_FOLLOW :: 0x400
|
|
AT_REMOVEDIR :: 0x800
|
|
|
|
flock :: struct {
|
|
l_start: off_t, /* [PSX] relative offset in bytes */
|
|
l_len: off_t, /* [PSX] size; if 0 then until EOF */
|
|
l_pid: pid_t, /* [PSX] process ID of the process holding the lock */
|
|
l_type: Lock_Type, /* [PSX] type of lock */
|
|
l_whence: c.short, /* [PSX] flag (Whence) of starting offset */
|
|
}
|
|
|
|
} else when ODIN_OS == .OpenBSD {
|
|
|
|
off_t :: distinct c.int64_t
|
|
pid_t :: distinct c.int32_t
|
|
|
|
F_DUPFD :: 0
|
|
F_DUPFD_CLOEXEC :: 10
|
|
F_GETFD :: 1
|
|
F_SETFD :: 2
|
|
F_GETFL :: 3
|
|
F_SETFL :: 4
|
|
F_GETLK :: 7
|
|
F_SETLK :: 8
|
|
F_SETLKW :: 9
|
|
F_GETOWN :: 5
|
|
F_SETOWN :: 6
|
|
|
|
FD_CLOEXEC :: 1
|
|
|
|
F_RDLCK :: 1
|
|
F_UNLCK :: 2
|
|
F_WRLCK :: 3
|
|
|
|
O_CLOEXEC :: 0x10000
|
|
O_CREAT :: 0x0200
|
|
O_DIRECTORY :: 0x20000
|
|
O_EXCL :: 0x0800
|
|
O_NOCTTY :: 0x8000
|
|
O_NOFOLLOW :: 0x0100
|
|
O_TRUNC :: 0x0400
|
|
|
|
_O_TTY_INIT :: 0
|
|
O_TTY_INIT :: O_Flags{} // NOTE: not defined in the headers
|
|
|
|
O_APPEND :: 0x0008
|
|
O_DSYNC :: 0x010000
|
|
O_NONBLOCK :: 0x0004
|
|
O_SYNC :: 0x0080
|
|
|
|
_O_RSYNC :: O_SYNC
|
|
O_RSYNC :: O_Flags{.SYNC}
|
|
|
|
O_EXEC :: 0x04000000 // NOTE: not defined in the headers
|
|
O_RDONLY :: 0
|
|
O_RDWR :: 0x0002
|
|
O_WRONLY :: 0x0001
|
|
|
|
_O_SEARCH :: 0
|
|
O_SEARCH :: O_Flags{} // NOTE: not defined in the headers
|
|
|
|
AT_FDCWD: FD: -100
|
|
|
|
AT_EACCESS :: 0x01
|
|
AT_SYMLINK_NOFOLLOW :: 0x02
|
|
AT_SYMLINK_FOLLOW :: 0x04
|
|
AT_REMOVEDIR :: 0x08
|
|
|
|
flock :: struct {
|
|
l_start: off_t, /* [PSX] relative offset in bytes */
|
|
l_len: off_t, /* [PSX] size; if 0 then until EOF */
|
|
l_pid: pid_t, /* [PSX] process ID of the process holding the lock */
|
|
l_type: Lock_Type, /* [PSX] type of lock */
|
|
l_whence: c.short, /* [PSX] flag (Whence) of starting offset */
|
|
}
|
|
|
|
} else when ODIN_OS == .Linux {
|
|
|
|
off_t :: distinct c.int64_t
|
|
pid_t :: distinct c.int
|
|
|
|
F_DUPFD :: 0
|
|
F_GETFD :: 1
|
|
F_SETFD :: 2
|
|
F_GETFL :: 3
|
|
F_SETFL :: 4
|
|
F_GETLK :: 5
|
|
F_SETLK :: 6
|
|
F_SETLKW :: 7
|
|
F_SETOWN :: 8
|
|
F_GETOWN :: 9
|
|
F_RDLCK :: 0
|
|
F_UNLCK :: 2
|
|
F_WRLCK :: 1
|
|
|
|
F_DUPFD_CLOEXEC :: 1030
|
|
|
|
FD_CLOEXEC :: 1
|
|
|
|
O_CREAT :: 0o0_000_100
|
|
O_EXCL :: 0o0_000_200
|
|
O_NOCTTY :: 0o0_000_400
|
|
O_TRUNC :: 0o0_001_000
|
|
O_DIRECTORY :: 0o0_200_000
|
|
O_NOFOLLOW :: 0o0_400_000
|
|
O_CLOEXEC :: 0o2_000_000
|
|
|
|
_O_TTY_INIT :: 0
|
|
O_TTY_INIT :: O_Flags{}
|
|
|
|
O_APPEND :: 0o0_002_000
|
|
O_NONBLOCK :: 0o0_004_000
|
|
O_DSYNC :: 0o0_010_000
|
|
O_SYNC :: 0o4_010_000
|
|
|
|
_O_RSYNC :: 0
|
|
O_RSYNC :: O_Flags{}
|
|
|
|
O_EXEC :: 0x04000000 // NOTE: not defined in the headers
|
|
|
|
O_RDONLY :: 0
|
|
O_WRONLY :: 0o1
|
|
O_RDWR :: 0o2
|
|
|
|
_O_SEARCH :: 0
|
|
O_SEARCH :: O_Flags{}
|
|
|
|
AT_FDCWD: FD: -100
|
|
|
|
AT_EACCESS :: 0x200
|
|
AT_SYMLINK_NOFOLLOW :: 0x100
|
|
AT_SYMLINK_FOLLOW :: 0x400
|
|
AT_REMOVEDIR :: 0x200
|
|
|
|
flock :: struct {
|
|
l_type: Lock_Type, /* [PSX] type of lock. */
|
|
l_whence: c.short, /* [PSX] flag (Whence) of starting offset. */
|
|
l_start: off_t, /* [PSX] relative offset in bytes. */
|
|
l_len: off_t, /* [PSX] size; if 0 then until EOF. */
|
|
l_pid: pid_t, /* [PSX] process ID of the process holding the lock. */
|
|
}
|
|
|
|
}
|