1570af302Sopenharmony_ci#include <sys/resource.h>
2570af302Sopenharmony_ci#include <errno.h>
3570af302Sopenharmony_ci#include "syscall.h"
4570af302Sopenharmony_ci#include "libc.h"
5570af302Sopenharmony_ci
6570af302Sopenharmony_ci#define MIN(a, b) ((a)<(b) ? (a) : (b))
7570af302Sopenharmony_ci#define FIX(x) do{ if ((x)>=SYSCALL_RLIM_INFINITY) (x)=RLIM_INFINITY; }while(0)
8570af302Sopenharmony_ci
9570af302Sopenharmony_ci#ifdef __LITEOS_A__
10570af302Sopenharmony_cistatic int __setrlimit(int resource, const struct rlimit *rlim)
11570af302Sopenharmony_ci{
12570af302Sopenharmony_ci	unsigned long long k_rlim[2];
13570af302Sopenharmony_ci	struct rlimit tmp;
14570af302Sopenharmony_ci	if (SYSCALL_RLIM_INFINITY != RLIM_INFINITY) {
15570af302Sopenharmony_ci		tmp = *rlim;
16570af302Sopenharmony_ci		FIX(tmp.rlim_cur);
17570af302Sopenharmony_ci		FIX(tmp.rlim_max);
18570af302Sopenharmony_ci		rlim = &tmp;
19570af302Sopenharmony_ci	}
20570af302Sopenharmony_ci
21570af302Sopenharmony_ci	k_rlim[0] = rlim->rlim_cur;
22570af302Sopenharmony_ci	k_rlim[1] = rlim->rlim_max;
23570af302Sopenharmony_ci	return __syscall(SYS_setrlimit, resource, k_rlim);
24570af302Sopenharmony_ci}
25570af302Sopenharmony_ci#endif
26570af302Sopenharmony_ci
27570af302Sopenharmony_cistruct ctx {
28570af302Sopenharmony_ci#ifdef __LITEOS_A__
29570af302Sopenharmony_ci	const struct rlimit *rlim;
30570af302Sopenharmony_ci#else
31570af302Sopenharmony_ci	unsigned long lim[2];
32570af302Sopenharmony_ci#endif
33570af302Sopenharmony_ci	int res;
34570af302Sopenharmony_ci	int err;
35570af302Sopenharmony_ci};
36570af302Sopenharmony_ci
37570af302Sopenharmony_ci#ifdef SYS_setrlimit
38570af302Sopenharmony_cistatic void do_setrlimit(void *p)
39570af302Sopenharmony_ci{
40570af302Sopenharmony_ci	struct ctx *c = p;
41570af302Sopenharmony_ci	if (c->err>0) return;
42570af302Sopenharmony_ci#ifdef __LITEOS_A__
43570af302Sopenharmony_ci	c->err = -__setrlimit(c->res, c->rlim);
44570af302Sopenharmony_ci#else
45570af302Sopenharmony_ci	c->err = -__syscall(SYS_setrlimit, c->res, c->lim);
46570af302Sopenharmony_ci#endif
47570af302Sopenharmony_ci}
48570af302Sopenharmony_ci#endif
49570af302Sopenharmony_ci
50570af302Sopenharmony_ciint setrlimit(int resource, const struct rlimit *rlim)
51570af302Sopenharmony_ci{
52570af302Sopenharmony_ci#ifdef __LITEOS_A__
53570af302Sopenharmony_ci	struct ctx c = { .res = resource, .rlim = rlim, .err = -1 };
54570af302Sopenharmony_ci#else
55570af302Sopenharmony_ci	struct rlimit tmp;
56570af302Sopenharmony_ci	if (SYSCALL_RLIM_INFINITY != RLIM_INFINITY) {
57570af302Sopenharmony_ci		tmp = *rlim;
58570af302Sopenharmony_ci		FIX(tmp.rlim_cur);
59570af302Sopenharmony_ci		FIX(tmp.rlim_max);
60570af302Sopenharmony_ci		rlim = &tmp;
61570af302Sopenharmony_ci	}
62570af302Sopenharmony_ci	int ret = __syscall(SYS_prlimit64, 0, resource, rlim, 0);
63570af302Sopenharmony_ci#ifdef SYS_setrlimit
64570af302Sopenharmony_ci	if (ret != -ENOSYS) return __syscall_ret(ret);
65570af302Sopenharmony_ci
66570af302Sopenharmony_ci	struct ctx c = {
67570af302Sopenharmony_ci		.lim[0] = MIN(rlim->rlim_cur, MIN(-1UL, SYSCALL_RLIM_INFINITY)),
68570af302Sopenharmony_ci		.lim[1] = MIN(rlim->rlim_max, MIN(-1UL, SYSCALL_RLIM_INFINITY)),
69570af302Sopenharmony_ci		.res = resource, .err = -1
70570af302Sopenharmony_ci	};
71570af302Sopenharmony_ci	__synccall(do_setrlimit, &c);
72570af302Sopenharmony_ci	if (c.err) {
73570af302Sopenharmony_ci		if (c.err>0) errno = c.err;
74570af302Sopenharmony_ci		return -1;
75570af302Sopenharmony_ci	}
76570af302Sopenharmony_ci	return 0;
77570af302Sopenharmony_ci#else
78570af302Sopenharmony_ci	return __syscall_ret(ret);
79570af302Sopenharmony_ci#endif
80570af302Sopenharmony_ci#endif
81570af302Sopenharmony_ci}
82570af302Sopenharmony_ci
83570af302Sopenharmony_ciweak_alias(setrlimit, setrlimit64);
84