/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "Licence").
 * You may not use this file except in compliance with the Licence.
 *
 * CDDL HEADER END
 *
 * Copyright (c) RISC OS Developments 2026. All rights reserved.
 * SPDX-License-Identifier: CDDL-1.0
 */
/* Unix interfaces referenced by OpenSSL but absent from SharedCLibrary. */
#include <dirent.h>
#include <errno.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <sys/poll.h>
#include <sys/stat.h>
#include <time.h>
#include <unistd.h>

#include "kernel.h"
#include "swis.h"

int stat(const char *name, struct stat *details)
{
    FILE *file;
    long size;

    if(name == NULL || details == NULL)
    {
        errno = EINVAL;
        return -1;
    }
    file = fopen(name, "rb");
    if(file == NULL) return -1;
    if(fseek(file, 0, SEEK_END) != 0 || (size = ftell(file)) < 0)
    {
        fclose(file);
        return -1;
    }
    fclose(file);
    memset(details, 0, sizeof(*details));
    details->st_mode = S_IFREG | S_IRUSR;
    details->st_size = size;
    return 0;
}

int lstat(const char *name, struct stat *details)
{
    return stat(name, details);
}

int poll(struct pollfd *descriptors, nfds_t count, int timeout)
{
    nfds_t index;

    (void)timeout;
    for(index = 0; index < count; index++) descriptors[index].revents = 0;
    return 0;
}

int getaddrinfo(const char *name, const char *service,
                const struct addrinfo *request, struct addrinfo **result)
{
    (void)name;
    (void)service;
    (void)request;
    if(result != NULL) *result = NULL;
    return EAI_FAIL;
}

void freeaddrinfo(struct addrinfo *address)
{
    (void)address;
}

const char *gai_strerror(int code)
{
    (void)code;
    return "name service unavailable";
}

int getnameinfo(const struct sockaddr *address, socklen_t address_size,
                char *host, socklen_t host_size, char *service,
                socklen_t service_size, unsigned int flags)
{
    (void)address;
    (void)address_size;
    (void)host;
    (void)host_size;
    (void)service;
    (void)service_size;
    (void)flags;
    return EAI_FAIL;
}

DIR *opendir(const char *name)
{
    (void)name;
    errno = ENOSYS;
    return NULL;
}

struct dirent *readdir(DIR *directory)
{
    (void)directory;
    errno = ENOSYS;
    return NULL;
}

int closedir(DIR *directory)
{
    (void)directory;
    return 0;
}

int nanosleep(const struct timespec *request, struct timespec *remaining)
{
    (void)request;
    if(remaining != NULL) memset(remaining, 0, sizeof(*remaining));
    errno = ENOSYS;
    return -1;
}

int getpid(void)
{
    _kernel_swi_regs registers;

    if(_kernel_swi(OS_ReadMonotonicTime, &registers, &registers) == NULL)
        return registers.r[0] | 1;
    return 1;
}

unsigned int getuid(void) { return 0; }
unsigned int geteuid(void) { return 0; }
unsigned int getgid(void) { return 0; }
unsigned int getegid(void) { return 0; }
