generalization of syscalls
This commit is contained in:
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
AMD64 specific Linux std parts.
|
||||
*/
|
||||
|
||||
#include "linux.c"
|
||||
|
||||
#include "../std.h"
|
||||
#include <fcntl.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
|
||||
inline com_std_fd com_std_open(char *path, uint32_t flags) {
|
||||
com_std_assert(flags != 0);
|
||||
uint32_t mode = flags & COM_STD_OPEN_READ && flags & COM_STD_OPEN_WRITE
|
||||
? O_RDWR
|
||||
: flags & COM_STD_OPEN_READ ? O_RDONLY
|
||||
: O_WRONLY;
|
||||
long ret;
|
||||
__asm__ volatile("syscall"
|
||||
: "=a"(ret)
|
||||
: "a"(2), "D"(path), "S"(mode)
|
||||
: "rcx", "r11", "memory");
|
||||
if (ret <= 0) /* Mark NULL, removing error code */
|
||||
ret = 0;
|
||||
return (void *)ret;
|
||||
}
|
||||
|
||||
inline bool com_std_write(com_std_fd fd, char const *data, uint32_t bytes) {
|
||||
long ret;
|
||||
__asm__ volatile("syscall"
|
||||
: "=a"(ret)
|
||||
: "a"(1), "D"(fd), "S"(data), "d"(bytes)
|
||||
: "rcx", "r11", "memory");
|
||||
return ret == bytes;
|
||||
}
|
||||
|
||||
inline int32_t com_std_read(com_std_fd fd, char *data, uint32_t upto) {
|
||||
long ret;
|
||||
__asm__ volatile("syscall"
|
||||
: "=a"(ret)
|
||||
: "a"(0), "D"(fd), "S"(data), "d"(upto)
|
||||
: "rcx", "r11", "memory");
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline bool com_std_sfwd(com_std_fd fd, uint32_t bytes) {
|
||||
long ret;
|
||||
__asm__ volatile("syscall"
|
||||
: "=a"(ret)
|
||||
: "a"(8), "D"(fd), "S"(bytes), "d"(SEEK_CUR)
|
||||
: "rcx", "r11", "memory");
|
||||
return ret >= 0; /* TODO: Check whether offset is bytes offset exactly? */
|
||||
}
|
||||
|
||||
inline com_std_fd com_std_socket(bool isnetwork) {
|
||||
if (!isnetwork) {
|
||||
int32_t sockfd;
|
||||
__asm__ volatile("syscall"
|
||||
: "=a"(sockfd)
|
||||
: "a"(41), "D"(AF_UNIX), "S"(SOCK_STREAM), "d"(0)
|
||||
: "rcx", "r11", "memory");
|
||||
if (sockfd < 0)
|
||||
sockfd = 0;
|
||||
return (void *)(int64_t)sockfd;
|
||||
} else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
inline bool com_std_connect(com_std_fd fd, bool isnetwork, char *address) {
|
||||
com_std_assert(address != NULL);
|
||||
if (!isnetwork) {
|
||||
struct sockaddr_un addr = {.sun_family = AF_UNIX};
|
||||
__builtin_memcpy(&addr.sun_path, address, com_str_ext_len(address));
|
||||
int32_t ret;
|
||||
__asm__ volatile("syscall"
|
||||
: "=a"(ret)
|
||||
: "a"(42), "D"(fd), "S"(&addr), "d"(sizeof addr)
|
||||
: "rcx", "r11", "memory");
|
||||
return ret == 0;
|
||||
} else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
inline void com_std_exit(uint32_t status) {
|
||||
__asm__ volatile("syscall" : : "a"(60), "D"(status) : "rcx", "r11", "memory");
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
inline void com_std_close(com_std_fd fd) {
|
||||
__asm__ volatile("syscall" : : "a"(3), "D"(fd) : "rcx", "r11", "memory");
|
||||
}
|
||||
Reference in New Issue
Block a user