Files
SirHumza--orbisRPC/orbisrpc/compat.c
T

124 lines
3.9 KiB
C

/* compat.c - tiny libc shims for the PS4 link environment.
* SceLibcInternal lacks getentropy/__errno_location/gmtime_r, and
* mbedTLS wants a platform entropy poll. Compiled into payload + plugin. */
#include <stddef.h>
#include <fcntl.h>
#include <unistd.h>
#include <time.h>
#include <stdint.h>
#include "clock.h"
#ifdef ORBISRPC_SDK_PAYLOAD
/* Payload-SDK builds: the SDK libc already provides errno, gmtime_r,
* clock_gettime and friends. Only the entropy poll + monotonic clock
* live here, written against plain POSIX. */
int mbedtls_platform_entropy_poll(void *data, unsigned char *out,
size_t len, size_t *olen){
(void)data;
if(!out || len == 0) return -1;
int fd = open("/dev/urandom", O_RDONLY);
if(fd < 0) return -1;
size_t got = 0;
while(got < len){
long r = read(fd, (char *)out + got, len - got);
if(r <= 0){ close(fd); return -1; }
got += (size_t)r;
}
close(fd);
*olen = len;
return 0;
}
int64_t orbis_mono_s(void){
struct timespec ts;
if(clock_gettime(CLOCK_MONOTONIC, &ts) != 0) return (int64_t)time(NULL);
return (int64_t)ts.tv_sec;
}
#else
int *__errno_location(void) __attribute__((weak));
int *__errno_location(void){
static int errno_slot;
return &errno_slot;
}
__attribute__((weak)) int getentropy(void *buf, size_t n){
int fd = open("/dev/urandom", O_RDONLY);
if(fd < 0) return -1;
size_t got = 0;
while(got < n){
long r = read(fd, (char*)buf + got, n - got);
if(r <= 0){ close(fd); return -1; }
got += (size_t)r;
}
close(fd);
return 0;
}
__attribute__((weak)) struct tm *gmtime_r(const time_t *t, struct tm *r){
/* Thread-safe: pure arithmetic, no static buffer (gmtime() is shared). */
if(!t || !r) return NULL;
long long secs = (long long)*t;
long long days = secs / 86400LL;
long long rem = secs % 86400LL;
if(rem < 0){ rem += 86400LL; days--; }
r->tm_hour = (int)(rem / 3600); rem %= 3600;
r->tm_min = (int)(rem / 60);
r->tm_sec = (int)(rem % 60);
/* civil_from_days (Howard Hinnant) */
long long z = days + 719468LL;
long long era = (z >= 0 ? z : z - 146096LL) / 146097LL;
unsigned doe = (unsigned)(z - era * 146097LL);
unsigned yoe = (doe - doe/1460U + doe/36524U - doe/146096U) / 365U;
long long y = (long long)yoe + era * 400LL;
unsigned doy = doe - (365U*yoe + yoe/4U - yoe/100U);
unsigned mp = (5U*doy + 2U)/153U;
unsigned d = doy - (153U*mp+2U)/5U + 1U;
unsigned m = mp + (mp < 10U ? 3U : (unsigned)-9);
y += (m <= 2);
r->tm_mday = (int)d;
r->tm_mon = (int)(m - 1);
r->tm_year = (int)(y - 1900LL);
/* weekday: 1970-01-01 was Thursday */
r->tm_wday = (int)((days % 7 + 7 + 4) % 7);
/* yearday */
{
int leap = ((y%4==0 && y%100!=0) || y%400==0);
static const int cum[12] = {0,31,59,90,120,151,181,212,243,273,304,334};
r->tm_yday = cum[r->tm_mon] + (int)d - 1 + (leap && r->tm_mon > 1 ? 1 : 0);
}
r->tm_isdst = 0;
return r;
}
/* mbedTLS platform entropy: /dev/urandom, the only strong source here. */
int mbedtls_platform_entropy_poll(void *data, unsigned char *out,
size_t len, size_t *olen){
(void)data;
if(!out || len == 0) return -1;
if(getentropy(out, len) != 0) return -1;
*olen = len;
return 0;
}
int64_t orbis_mono_s(void){
#if defined(__PS4__) || (defined(__FreeBSD__) && !defined(__APPLE__))
/* PS4 builds (--target=x86_64-pc-freebsd12-elf, -D__PS4__). Declared
* here instead of including orbis headers so host builds stay clean. */
extern unsigned long long sceKernelGetProcessTime(void);
return (int64_t)(sceKernelGetProcessTime() / 1000000ull);
#else
struct timespec ts;
#if defined(CLOCK_MONOTONIC)
clock_gettime(CLOCK_MONOTONIC, &ts);
#else
ts.tv_sec = time(NULL);
ts.tv_nsec = 0;
#endif
return (int64_t)ts.tv_sec;
#endif
}
#endif /* ORBISRPC_SDK_PAYLOAD */