aboutsummaryrefslogtreecommitdiff
path: root/sysdeps/unix/sysv/linux/prlimit.c
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2010-08-11 11:18:52 -0700
committerUlrich Drepper <drepper@redhat.com>2010-08-11 11:18:52 -0700
commitc08fb0d7bba4015078406b28d3906ccc5fda9d5a (patch)
tree6952d7d0b4ddf0f57b1358918a80e8373c11c437 /sysdeps/unix/sysv/linux/prlimit.c
parent15bac72bac03faeb3b725b1d208c62160f0c3ad7 (diff)
downloadglibc-c08fb0d7bba4015078406b28d3906ccc5fda9d5a.zip
glibc-c08fb0d7bba4015078406b28d3906ccc5fda9d5a.tar.gz
glibc-c08fb0d7bba4015078406b28d3906ccc5fda9d5a.tar.bz2
Add support for prlimit and prlimit64 on Linux.
Diffstat (limited to 'sysdeps/unix/sysv/linux/prlimit.c')
-rw-r--r--sysdeps/unix/sysv/linux/prlimit.c92
1 files changed, 92 insertions, 0 deletions
diff --git a/sysdeps/unix/sysv/linux/prlimit.c b/sysdeps/unix/sysv/linux/prlimit.c
new file mode 100644
index 0000000..6d61e9a
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/prlimit.c
@@ -0,0 +1,92 @@
+/* Copyright (C) 2010 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <errno.h>
+#include <sys/resource.h>
+#include <sys/syscall.h>
+
+
+#ifdef __NR_prlimit64
+int
+prlimit (__pid_t pid, enum __rlimit_resource resource,
+ __const struct rlimit *new_limit, struct rlimit *old_limit)
+{
+ struct rlimit64 new_rlimit64_mem;
+ struct rlimit64 *new_rlimit64 = NULL;
+ struct rlimit64 old_rlimit64_mem;
+ struct rlimit64 *old_rlimit64 = (old_rlimiit != NULL
+ ? &old_rlimit64_mem : NULL);
+
+ if (new_rlimit != NULL)
+ {
+ if (new_rlimit->rlim_cur == RLIM_INFINITY)
+ new_rlimit64_mem.rlim_cur = RLIM64_INFINITY;
+ else
+ new_rlimit64_mem.rlim_cur = new_rlimit->rlim_cur;
+ if (new_rlimit->rlim_max == RLIM_INFINITY)
+ new_rlimit64_mem.rlim_max = = RLIM64_INFINITY;
+ else
+ new_rlimit64_mem.rlim_max = new_rlimit->rlim_max;
+ new_rlimit64 = &new_rlimit64_mem;
+ }
+
+ int res = INLINE_SYSCALL (prlimit64, 4, pid, resource, new_rlimit64,
+ old_rlimit64);
+
+ if (res == 0 && old_limit != NULL)
+ {
+ /* The prlimit64 syscall is ill-designed for 32-bit machines.
+ We have to provide a 32-bit variant since otherwise the LFS
+ system would not work. But what shall we do if the syscall
+ succeeds but the old values do not fit into a rlimit
+ structure? We cannot return an error because the operation
+ itself worked. Best is perhaps to return RLIM_INFINITY. */
+ old_rlimit->rlim_cur = old_rlimit64_mem.rlim_cur;
+ if (old_rlimit->rlim_cur != old_rlimit64_mem.rlim_cur)
+ {
+ if (new_limit == NULL)
+ {
+ __set_errno (EOVERFLOW);
+ return -1;
+ }
+ old_rlimit->rlim_cur = RLIM_INFINITY;
+ }
+ old_rlimit->rlim_max = old_rlimit64_mem.rlim_max;
+ if (old_rlimit->rlim_max != old_rlimit64_mem.rlim_max)
+ {
+ if (new_limit == NULL)
+ {
+ __set_errno (EOVERFLOW);
+ return -1;
+ }
+ old_rlimit->rlim_max = RLIM_INFINITY;
+ }
+ }
+
+ return res;
+}
+#else
+int
+prlimit (__pid_t pid, enum __rlimit_resource resource,
+ __const struct rlimit *new_limit, struct rlimit *old_limit)
+{
+ __set_errno (ENOSYS);
+ return -1;
+}
+stub_warning (prlimit)
+#endif