+2006-08-09 Ulrich Drepper <drepper@redhat.com>
+
+ * malloc/memusagestat.c: Silence warnings.
+
+ * malloc/malloc.c: Dynamically size mmap treshold if the program
+ frees mmaped blocks.
+ Patch by Valerie Henson and Arjan van de Ven.
+
+2006-08-08 Jakub Jelinek <jakub@redhat.com>
+
+ * sysdeps/unix/sysv/linux/ia64/bits/fcntl.h (O_DIRECT): Protect with
+ __USE_GNU.
+
+ * stdlib/strtol_l.c (__strtol_ul_max_tab, __strtol_ul_rem_tab,
+ __strtol_ull_max_tab, __strtol_ull_rem_tab): Declare.
+ (DEF): Don't put the var into .gnu.linkonce.r.* section.
+ Only provide var definitions in strtol_l (or for *ull*
+ in strtoll_l).
+
+ * stdio-common/bug16.c (tests): New array.
+ (do_tests): Allow the first hexadecimal digit
+ to be 1, 2, 4 or 8. Do 3 additional tests.
+
+ * sysdeps/s390/fpu/libm-test-ulps: Update.
+
+ * sysdeps/unix/sysv/linux/s390/s390-32/fchownat.c (fchownat): Use
+ fchownat syscall if available.
+ * sysdeps/unix/sysv/linux/powerpc/fchownat.c (fchownat): Likewise.
+ * sysdeps/unix/sysv/linux/sh/fchownat.c (fchownat): Likewise.
+ * sysdeps/unix/sysv/linux/i386/fchownat.c (fchownat): Likewise.
+
+2006-08-07 Ulrich Drepper <drepper@redhat.com>
+
+ * nis/nis_xdr.c: Avoid some function calls.
+
2006-08-07 Jakub Jelinek <jakub@redhat.com>
Ulrich Drepper <drepper@redhat.com>
2006-08-07 Ulrich Drepper <drepper@redhat.com>
* nis/nis_call.c: Minor cleanups throughout.
- (rec_dirsearch) [HIGHER_NAME]: Correctly size ndomain array.
+ (rec_dirsearch) [case HIGHER_NAME]: Correctly size ndomain array.
(first_shoot): Add search_parent_first parameter. Only if it is set
search parent server first.
If directory for table found through cold start cache is not the same
glibc-base := HEAD
DIST_BRANCH := devel
COLLECTION := dist-fc4
-fedora-sync-date := 2006-08-07 18:59 UTC
-fedora-sync-tag := fedora-glibc-20060807T1859
+fedora-sync-date := 2006-08-10 06:27 UTC
+fedora-sync-tag := fedora-glibc-20060810T0627
-%define glibcrelease 18
+%define glibcrelease 19
%define auxarches i586 i686 athlon sparcv9 alphaev6
%define xenarches i686 athlon
%ifarch %{xenarches}
%endif
%changelog
+* Thu Aug 10 2006 Jakub Jelinek <jakub@redhat.com> 2.4.90-19
+- adaptive malloc brk/mmap threshold
+- fix fchownat to use kernel syscall (if available) on many arches (#201870)
+- only define O_DIRECT with -D_GNU_SOURCE on ia64 to match all
+ other arches (#201748)
+
* Mon Aug 7 2006 Jakub Jelinek <jakub@redhat.com> 2.4.90-18
- NIS+ fixes
- fix memusage and xtrace scripts (#200736)
#define DEFAULT_TOP_PAD (0)
#endif
+/*
+ MMAP_THRESHOLD_MAX and _MIN are the bounds on the dynamically
+ adjusted MMAP_THRESHOLD.
+*/
+
+#ifndef DEFAULT_MMAP_THRESHOLD_MIN
+#define DEFAULT_MMAP_THRESHOLD_MIN (128 * 1024)
+#endif
+
+#ifndef DEFAULT_MMAP_THRESHOLD_MAX
+#define DEFAULT_MMAP_THRESHOLD_MAX (8 * 1024 * 1024 * sizeof(long))
+#endif
+
/*
M_MMAP_THRESHOLD is the request size threshold for using mmap()
to service a request. Requests of at least this size that cannot
"large" chunks, but the value of "large" varies across systems. The
default is an empirically derived value that works well in most
systems.
+
+
+ Update in 2006:
+ The above was written in 2001. Since then the world has changed a lot.
+ Memory got bigger. Applications got bigger. The virtual address space
+ layout in 32 bit linux changed.
+
+ In the new situation, brk() and mmap space is shared and there are no
+ artificial limits on brk size imposed by the kernel. What is more,
+ applications have started using transient allocations larger than the
+ 128Kb as was imagined in 2001.
+
+ The price for mmap is also high now; each time glibc mmaps from the
+ kernel, the kernel is forced to zero out the memory it gives to the
+ application. Zeroing memory is expensive and eats a lot of cache and
+ memory bandwidth. This has nothing to do with the efficiency of the
+ virtual memory system, by doing mmap the kernel just has no choice but
+ to zero.
+
+ In 2001, the kernel had a maximum size for brk() which was about 800
+ megabytes on 32 bit x86, at that point brk() would hit the first
+ mmaped shared libaries and couldn't expand anymore. With current 2.6
+ kernels, the VA space layout is different and brk() and mmap
+ both can span the entire heap at will.
+
+ Rather than using a static threshold for the brk/mmap tradeoff,
+ we are now using a simple dynamic one. The goal is still to avoid
+ fragmentation. The old goals we kept are
+ 1) try to get the long lived large allocations to use mmap()
+ 2) really large allocations should always use mmap()
+ and we're adding now:
+ 3) transient allocations should use brk() to avoid forcing the kernel
+ having to zero memory over and over again
+
+ The implementation works with a sliding threshold, which is by default
+ limited to go between 128Kb and 32Mb (64Mb for 64 bitmachines) and starts
+ out at 128Kb as per the 2001 default.
+
+ This allows us to satisfy requirement 1) under the assumption that long
+ lived allocations are made early in the process' lifespan, before it has
+ started doing dynamic allocations of the same size (which will
+ increase the threshold).
+
+ The upperbound on the threshold satisfies requirement 2)
+
+ The threshold goes up in value when the application frees memory that was
+ allocated with the mmap allocator. The idea is that once the application
+ starts freeing memory of a certain size, it's highly probable that this is
+ a size the application uses for transient allocations. This estimator
+ is there to satisfy the new third requirement.
+
*/
#define M_MMAP_THRESHOLD -3
#ifndef DEFAULT_MMAP_THRESHOLD
-#define DEFAULT_MMAP_THRESHOLD (128 * 1024)
+#define DEFAULT_MMAP_THRESHOLD DEFAULT_MMAP_THRESHOLD_MIN
#endif
/*
int n_mmaps;
int n_mmaps_max;
int max_n_mmaps;
+ /* the mmap_threshold is dynamic, until the user sets
+ it manually, at which point we need to disable any
+ dynamic behavior. */
+ int no_dyn_threshold;
/* Cache malloc_getpagesize */
unsigned int pagesize;
#if HAVE_MMAP
if (chunk_is_mmapped(p)) /* release mmapped memory. */
{
+ /* see if the dynamic brk/mmap threshold needs adjusting */
+ if (!mp_.no_dyn_threshold
+ && p->size > mp_.mmap_threshold
+ && p->size <= DEFAULT_MMAP_THRESHOLD_MAX)
+ {
+ mp_.mmap_threshold = chunksize (p);
+ mp_.trim_threshold = 2 * mp_.mmap_threshold;
+ }
munmap_chunk(p);
return;
}
case M_TRIM_THRESHOLD:
mp_.trim_threshold = value;
+ mp_.no_dyn_threshold = 1;
break;
case M_TOP_PAD:
mp_.top_pad = value;
+ mp_.no_dyn_threshold = 1;
break;
case M_MMAP_THRESHOLD:
else
#endif
mp_.mmap_threshold = value;
+ mp_.no_dyn_threshold = 1;
break;
case M_MMAP_MAX:
else
#endif
mp_.n_mmaps_max = value;
+ mp_.no_dyn_threshold = 1;
break;
case M_CHECK_ACTION:
/* Generate graphic from memory profiling data.
- Copyright (C) 1998, 1999, 2000, 2005 Free Software Foundation, Inc.
+ Copyright (C) 1998, 1999, 2000, 2005, 2006 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
gdImageString (im_out, gdFontSmall, 38, ysize - 14, (unsigned char *) "0",
blue);
- snprintf(buf, sizeof (buf), heap_format, 0);
+ snprintf (buf, sizeof (buf), heap_format, 0);
gdImageString (im_out, gdFontSmall, maxsize_heap < 1024 ? 32 : 26,
- ysize - 26, buf, red);
- snprintf(buf, sizeof (buf), stack_format, 0);
+ ysize - 26, (unsigned char *) buf, red);
+ snprintf (buf, sizeof (buf), stack_format, 0);
gdImageString (im_out, gdFontSmall, xsize - 37, ysize - 26,
- buf, green);
+ (unsigned char *) buf, green);
if (string != NULL)
gdImageString (im_out, gdFontLarge, (xsize - strlen (string) * 8) / 2,
- 2, (char *) string, green);
+ 2, (unsigned char *) string, green);
gdImageStringUp (im_out, gdFontSmall, 1, ysize / 2 - 10,
(unsigned char *) "allocated", red);
(unsigned char *) "stack", green);
snprintf (buf, sizeof (buf), heap_format, maxsize_heap / heap_scale);
- gdImageString (im_out, gdFontSmall, 39 - strlen (buf) * 6, 14, buf, red);
+ gdImageString (im_out, gdFontSmall, 39 - strlen (buf) * 6, 14,
+ (unsigned char *) buf, red);
snprintf (buf, sizeof (buf), stack_format, maxsize_stack / stack_scale);
- gdImageString (im_out, gdFontSmall, xsize - 37, 14, buf, green);
+ gdImageString (im_out, gdFontSmall, xsize - 37, 14,
+ (unsigned char *) buf, green);
for (line = 1; line <= 3; ++line)
{
snprintf (buf, sizeof (buf), heap_format, maxsize_heap / 4 * line /
heap_scale);
gdImageString (im_out, gdFontSmall, 39 - strlen (buf) * 6,
- ysize - 26 - cnt, buf, red);
+ ysize - 26 - cnt, (unsigned char *) buf, red);
cnt2 = ((ysize - 40) * (maxsize_stack / 4 * line / stack_scale)) /
(maxsize_stack / stack_scale);
snprintf (buf, sizeof (buf), stack_format, maxsize_stack / 4 * line /
stack_scale);
gdImageString (im_out, gdFontSmall, xsize - 37, ysize - 26 - cnt2,
- buf, green);
+ (unsigned char *) buf, green);
}
snprintf (buf, sizeof (buf), "%llu", (unsigned long long) total);
- gdImageString (im_out, gdFontSmall, xsize - 50, ysize - 14, buf, blue);
+ gdImageString (im_out, gdFontSmall, xsize - 50, ysize - 14,
+ (unsigned char *) buf, blue);
if (!time_based)
{
return res;
}
+static __always_inline bool_t
+xdr_nis_name (XDR *xdrs, nis_name *objp)
+{
+ return xdr_string (xdrs, objp, ~0);
+}
+
bool_t
_xdr_nis_name (XDR *xdrs, nis_name *objp)
{
- return xdr_string (xdrs, objp, ~0);
+ return xdr_nis_name (xdrs, objp);
}
static __always_inline bool_t
bool_t
_xdr_nis_server (XDR *xdrs, nis_server *objp)
{
- bool_t res = _xdr_nis_name (xdrs, &objp->name);
+ bool_t res = xdr_nis_name (xdrs, &objp->name);
if (__builtin_expect (res, TRUE))
{
res = xdr_array (xdrs, (char **) &objp->ep.ep_val, &objp->ep.ep_len,
bool_t
_xdr_directory_obj (XDR *xdrs, directory_obj *objp)
{
- bool_t res = _xdr_nis_name (xdrs, &objp->do_name);
+ bool_t res = xdr_nis_name (xdrs, &objp->do_name);
if (__builtin_expect (res, TRUE))
{
res = xdr_nstype (xdrs, &objp->do_type);
&objp->li_attrs.li_attrs_len, ~0,
sizeof (nis_attr), (xdrproc_t) xdr_nis_attr);
if (__builtin_expect (res, TRUE))
- res = _xdr_nis_name (xdrs, &objp->li_name);
+ res = xdr_nis_name (xdrs, &objp->li_name);
}
return res;
}
bool_t res = xdr_nis_oid (xdrs, &objp->zo_oid);
if (__builtin_expect (res, TRUE))
{
- res = _xdr_nis_name (xdrs, &objp->zo_name);
+ res = xdr_nis_name (xdrs, &objp->zo_name);
if (__builtin_expect (res, TRUE))
{
- res = _xdr_nis_name (xdrs, &objp->zo_owner);
+ res = xdr_nis_name (xdrs, &objp->zo_owner);
if (__builtin_expect (res, TRUE))
{
- res = _xdr_nis_name (xdrs, &objp->zo_group);
+ res = xdr_nis_name (xdrs, &objp->zo_group);
if (__builtin_expect (res, TRUE))
{
- res = _xdr_nis_name (xdrs, &objp->zo_domain);
+ res = xdr_nis_name (xdrs, &objp->zo_domain);
if (__builtin_expect (res, TRUE))
{
res = xdr_u_int (xdrs, &objp->zo_access);
return res;
}
+static __always_inline bool_t
+xdr_nis_error (XDR *xdrs, nis_error *objp)
+{
+ return xdr_enum (xdrs, (enum_t *) objp);
+}
+
bool_t
_xdr_nis_error (XDR *xdrs, nis_error *objp)
{
- return xdr_enum (xdrs, (enum_t *) objp);
+ return xdr_nis_error (xdrs, objp);
}
bool_t
_xdr_nis_result (XDR *xdrs, nis_result *objp)
{
- bool_t res = _xdr_nis_error (xdrs, &objp->status);
+ bool_t res = xdr_nis_error (xdrs, &objp->status);
if (__builtin_expect (res, TRUE))
{
res = xdr_array (xdrs, (char **) &objp->objects.objects_val,
bool_t
_xdr_ns_request (XDR *xdrs, ns_request *objp)
{
- bool_t res = _xdr_nis_name (xdrs, &objp->ns_name);
+ bool_t res = xdr_nis_name (xdrs, &objp->ns_name);
if (__builtin_expect (res, TRUE))
res = xdr_array (xdrs, (char **) &objp->ns_object.ns_object_val,
&objp->ns_object.ns_object_len, 1,
bool_t
_xdr_ib_request (XDR *xdrs, ib_request *objp)
{
- bool_t res = _xdr_nis_name (xdrs, &objp->ibr_name);
+ bool_t res = xdr_nis_name (xdrs, &objp->ibr_name);
if (__builtin_expect (res, TRUE))
{
res = xdr_array (xdrs, (char **) &objp->ibr_srch.ibr_srch_val,
bool_t
_xdr_ping_args (XDR *xdrs, ping_args *objp)
{
- bool_t res = _xdr_nis_name (xdrs, &objp->dir);
+ bool_t res = xdr_nis_name (xdrs, &objp->dir);
if (__builtin_expect (res, TRUE))
res = xdr_uint32_t (xdrs, &objp->stamp);
return res;
bool_t
_xdr_cp_result (XDR *xdrs, cp_result *objp)
{
- bool_t res = _xdr_nis_error (xdrs, &objp->cp_status);
+ bool_t res = xdr_nis_error (xdrs, &objp->cp_status);
if (__builtin_expect (res, TRUE))
{
res = xdr_uint32_t (xdrs, &objp->cp_zticks);
bool_t
_xdr_fd_args (XDR *xdrs, fd_args *objp)
{
- bool_t res = _xdr_nis_name (xdrs, &objp->dir_name);
+ bool_t res = xdr_nis_name (xdrs, &objp->dir_name);
if (__builtin_expect (res, TRUE))
- res = _xdr_nis_name (xdrs, &objp->requester);
+ res = xdr_nis_name (xdrs, &objp->requester);
return res;
}
bool_t
_xdr_fd_result (XDR *xdrs, fd_result *objp)
{
- bool_t res = _xdr_nis_error (xdrs, &objp->status);
+ bool_t res = xdr_nis_error (xdrs, &objp->status);
if (__builtin_expect (res, TRUE))
{
- res = _xdr_nis_name (xdrs, &objp->source);
+ res = xdr_nis_name (xdrs, &objp->source);
if (__builtin_expect (res, TRUE))
{
res = xdr_bytes (xdrs, (char **) &objp->dir_data.dir_data_val,
#include <stdio.h>
#include <string.h>
+struct
+{
+ long double val;
+ const char str[4][7];
+} tests[] =
+{
+ { 0x0.FFFFp+0L, { "0X1P+0", "0X2P-1", "0X4P-2", "0X8P-3" } },
+ { 0x0.FFFFp+1L, { "0X1P+1", "0X2P+0", "0X4P-1", "0X8P-2" } },
+ { 0x0.FFFFp+2L, { "0X1P+2", "0X2P+1", "0X4P+0", "0X8P-1" } },
+ { 0x0.FFFFp+3L, { "0X1P+3", "0X2P+2", "0X4P+1", "0X8P+0" } }
+};
+
static int
do_test (void)
{
char buf[100];
- snprintf (buf, sizeof (buf), "%.0LA", 0x0.FFFFp+0L);
+ int ret = 0;
+
+ for (size_t i = 0; i < sizeof (tests) / sizeof (tests[0]); ++i)
+ {
+ snprintf (buf, sizeof (buf), "%.0LA", tests[i].val);
+
+ size_t j;
+ for (j = 0; j < 4; ++j)
+ if (strcmp (buf, tests[i].str[j]) == 0)
+ break;
- if (strcmp (buf, "0X1P+0") != 0)
- {
- printf ("got \"%s\", expected \"0X1P+0\"\n", buf);
- return 1;
+ if (j == 4)
+ {
+ printf ("%zd: got \"%s\", expected \"%s\" or equivalent\n",
+ i, buf, tests[i].str[0]);
+ ret = 1;
+ }
}
- return 0;
+ return ret;
}
#define TEST_FUNCTION do_test ()
/* Convert string representing a number to integer value, using given locale.
- Copyright (C) 1997, 2002, 2004 Free Software Foundation, Inc.
+ Copyright (C) 1997, 2002, 2004, 2006 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
/* Define tables of maximum values and remainders in order to detect
overflow. Do this at compile-time in order to avoid the runtime
overhead of the division. */
+extern const unsigned long __strtol_ul_max_tab[] attribute_hidden;
+extern const unsigned char __strtol_ul_rem_tab[] attribute_hidden;
+#if defined(QUAD) && __WORDSIZE == 32
+extern const unsigned long long __strtol_ull_max_tab[] attribute_hidden;
+extern const unsigned char __strtol_ull_rem_tab[] attribute_hidden;
+#endif
#define DEF(TYPE, NAME) \
- const TYPE NAME[] attribute_hidden \
- __attribute__((section(".gnu.linkonce.r." #NAME))) = \
+ const TYPE NAME[] attribute_hidden = \
{ \
F(2), F(3), F(4), F(5), F(6), F(7), F(8), F(9), F(10), \
F(11), F(12), F(13), F(14), F(15), F(16), F(17), F(18), F(19), F(20), \
F(31), F(32), F(33), F(34), F(35), F(36) \
}
-#define F(X) ULONG_MAX / X
+#if !UNSIGNED && !defined (USE_WIDE_CHAR) && !defined (QUAD)
+# define F(X) ULONG_MAX / X
DEF (unsigned long, __strtol_ul_max_tab);
-#undef F
-#if defined(QUAD) && __WORDSIZE == 32
+# undef F
+# define F(X) ULONG_MAX % X
+ DEF (unsigned char, __strtol_ul_rem_tab);
+# undef F
+#endif
+#if !UNSIGNED && !defined (USE_WIDE_CHAR) && defined (QUAD) \
+ && __WORDSIZE == 32
# define F(X) ULONG_LONG_MAX / X
DEF (unsigned long long, __strtol_ull_max_tab);
# undef F
# define F(X) ULONG_LONG_MAX % X
DEF (unsigned char, __strtol_ull_rem_tab);
# undef F
-#else
-# define F(X) ULONG_MAX % X
- DEF (unsigned char, __strtol_ul_rem_tab);
-# undef F
#endif
#undef DEF
# j0
Test "j0 (-4.0) == -3.9714980986384737228659076845169804197562E-1":
double: 1
-float: 1
+float: 2
idouble: 1
-ifloat: 1
+ifloat: 2
Test "j0 (0.75) == 0.864242275166648623555731103820923211":
float: 1
ifloat: 1
Test "j0 (10.0) == -0.245935764451348335197760862485328754":
-double: 2
+double: 3
float: 1
-idouble: 2
+idouble: 3
ifloat: 1
ildouble: 2
ldouble: 2
ldouble: 2
Test "j0 (4.0) == -3.9714980986384737228659076845169804197562E-1":
double: 1
-float: 1
+float: 2
idouble: 1
-ifloat: 1
+ifloat: 2
Test "j0 (8.0) == 0.171650807137553906090869407851972001":
float: 1
ifloat: 1
# jn
Test "jn (0, -4.0) == -3.9714980986384737228659076845169804197562E-1":
double: 1
-float: 1
+float: 2
idouble: 1
-ifloat: 1
+ifloat: 2
Test "jn (0, 0.75) == 0.864242275166648623555731103820923211":
float: 1
ifloat: 1
Test "jn (0, 10.0) == -0.245935764451348335197760862485328754":
-double: 2
+double: 3
float: 1
-idouble: 2
+idouble: 3
ifloat: 1
ildouble: 2
ldouble: 2
ldouble: 2
Test "jn (0, 4.0) == -3.9714980986384737228659076845169804197562E-1":
double: 1
-float: 1
+float: 2
idouble: 1
-ifloat: 1
+ifloat: 2
Test "jn (0, 8.0) == 0.171650807137553906090869407851972001":
float: 1
ifloat: 1
ifloat: 1
Test "jn (3, 10.0) == 0.0583793793051868123429354784103409563":
double: 3
-float: 1
+float: 2
idouble: 3
-ifloat: 1
+ifloat: 2
ildouble: 2
ldouble: 2
Test "jn (3, 2.0) == 0.128943249474402051098793332969239835":
ldouble: 1
Test "yn (10, 10.0) == -0.359814152183402722051986577343560609":
double: 2
-float: 1
+float: 2
idouble: 2
-ifloat: 1
+ifloat: 2
ildouble: 2
ldouble: 2
Test "yn (10, 2.0) == -129184.542208039282635913145923304214":
ifloat: 1
Function: "j0":
-double: 2
+double: 3
float: 2
-idouble: 2
+idouble: 3
ifloat: 2
ildouble: 2
ldouble: 2
int
fchownat (int fd, const char *file, uid_t owner, gid_t group, int flag)
{
+ int result;
+
+#ifdef __NR_fchownat
+# ifndef __ASSUME_ATFCTS
+ if (__have_atfcts >= 0)
+# endif
+ {
+ result = INLINE_SYSCALL (fchownat, 5, fd, file, owner, group, flag);
+# ifndef __ASSUME_ATFCTS
+ if (result == -1 && errno == ENOSYS)
+ __have_atfcts = -1;
+ else
+# endif
+ return result;
+ }
+#endif
+
+#ifndef __ASSUME_ATFCTS
if (flag & ~AT_SYMLINK_NOFOLLOW)
{
__set_errno (EINVAL);
file = buf;
}
- int result;
INTERNAL_SYSCALL_DECL (err);
-#if defined __NR_lchown || __ASSUME_LCHOWN_SYSCALL > 0
-# if __ASSUME_LCHOWN_SYSCALL == 0
+# if defined __NR_lchown || __ASSUME_LCHOWN_SYSCALL > 0
+# if __ASSUME_LCHOWN_SYSCALL == 0
static int __libc_old_chown;
-# ifdef __NR_chown32
+# ifdef __NR_chown32
if (__libc_missing_32bit_uids <= 0)
{
if (flag & AT_SYMLINK_NOFOLLOW)
__libc_missing_32bit_uids = 1;
}
-# endif /* __NR_chown32 */
+# endif /* __NR_chown32 */
if (((owner + 1) > (uid_t) ((__kernel_uid_t) -1U))
|| ((group + 1) > (gid_t) ((__kernel_gid_t) -1U)))
result = INTERNAL_SYSCALL (lchown, err, 3, CHECK_STRING (file), owner,
group);
-# elif __ASSUME_32BITUIDS
+# elif __ASSUME_32BITUIDS
/* This implies __ASSUME_LCHOWN_SYSCALL. */
result = INTERNAL_SYSCALL (chown32, err, 3, CHECK_STRING (file), owner,
group);
-# else
+# else
/* !__ASSUME_32BITUIDS && ASSUME_LCHOWN_SYSCALL */
-# ifdef __NR_chown32
+# ifdef __NR_chown32
if (__libc_missing_32bit_uids <= 0)
{
result = INTERNAL_SYSCALL (chown32, err, 3, CHECK_STRING (file), owner,
__libc_missing_32bit_uids = 1;
}
-# endif /* __NR_chown32 */
+# endif /* __NR_chown32 */
if (((owner + 1) > (uid_t) ((__kernel_uid_t) -1U))
|| ((group + 1) > (gid_t) ((__kernel_gid_t) -1U)))
{
}
result = INTERNAL_SYSCALL (chown, err, 3, CHECK_STRING (file), owner, group);
-# endif
-#else
+# endif
+# else
result = INTERNAL_SYSCALL (chown, err, 3, CHECK_STRING (file), owner, group);
-#endif
+# endif
if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (result, err), 0))
goto fail;
fail:
__atfct_seterrno (INTERNAL_SYSCALL_ERRNO (result, err), fd, buf);
return -1;
+#endif
}
#define O_SYNC 010000
#define O_FSYNC O_SYNC
#define O_ASYNC 020000
-#define O_DIRECT 040000
#ifdef __USE_GNU
+# define O_DIRECT 040000
# define O_DIRECTORY 0200000 /* must be a directory */
# define O_NOFOLLOW 0400000 /* don't follow links */
# define O_NOATIME 01000000 /* Do not set atime. */
int
fchownat (int fd, const char *file, uid_t owner, gid_t group, int flag)
{
+ int result;
+
+#ifdef __NR_fchownat
+# ifndef __ASSUME_ATFCTS
+ if (__have_atfcts >= 0)
+# endif
+ {
+ result = INLINE_SYSCALL (fchownat, 5, fd, file, owner, group, flag);
+# ifndef __ASSUME_ATFCTS
+ if (result == -1 && errno == ENOSYS)
+ __have_atfcts = -1;
+ else
+# endif
+ return result;
+ }
+#endif
+
+#ifndef __ASSUME_ATFCTS
if (flag & ~AT_SYMLINK_NOFOLLOW)
{
__set_errno (EINVAL);
file = buf;
}
- int result;
INTERNAL_SYSCALL_DECL (err);
-#if __ASSUME_LCHOWN_SYSCALL
+# if __ASSUME_LCHOWN_SYSCALL
if (flag & AT_SYMLINK_NOFOLLOW)
result = INTERNAL_SYSCALL (lchown, err, 3, file, owner, group);
else
result = INTERNAL_SYSCALL (chown, err, 3, file, owner, group);
-#else
+# else
char link[PATH_MAX + 2];
char path[2 * PATH_MAX + 4];
int loopct;
goto out;
}
-# ifdef __NR_lchown
+# ifdef __NR_lchown
if (flag & AT_SYMLINK_NOFOLLOW)
{
result = INTERNAL_SYSCALL (lchown, err, 3, __ptrvalue (file), owner,
}
libc_old_chown = -1;
}
-# else
+# else
if (flag & AT_SYMLINK_NOFOLLOW)
{
result = INTERNAL_SYSCALL (chown, err, 3, __ptrvalue (file), owner,
group);
goto out;
}
-# endif
+# endif
result = __readlink (file, link, PATH_MAX + 1);
if (result == -1)
{
-# ifdef __NR_lchown
+# ifdef __NR_lchown
result = INTERNAL_SYSCALL (lchown, err, 3, __ptrvalue (file), owner,
group);
-# else
+# else
result = INTERNAL_SYSCALL (chown, err, 3, __ptrvalue (file), owner,
group);
-# endif
+# endif
goto out;
}
if (result == -1)
{
-# ifdef __NR_lchown
+# ifdef __NR_lchown
result = INTERNAL_SYSCALL (lchown, err, 3, path, owner, group);
-# else
+# else
result = INTERNAL_SYSCALL (chown, err, 3, path, owner, group);
-# endif
+# endif
goto out;
}
}
return -1;
out:
-#endif
+# endif
if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (result, err), 0))
{
-#if !__ASSUME_LCHOWN_SYSCALL
+# if !__ASSUME_LCHOWN_SYSCALL
fail:
-#endif
+# endif
__atfct_seterrno (INTERNAL_SYSCALL_ERRNO (result, err), fd, buf);
result = -1;
}
return result;
+#endif
}
int
fchownat (int fd, const char *file, uid_t owner, gid_t group, int flag)
{
+ int result;
+
+#ifdef __NR_fchownat
+# ifndef __ASSUME_ATFCTS
+ if (__have_atfcts >= 0)
+# endif
+ {
+ result = INLINE_SYSCALL (fchownat, 5, fd, file, owner, group, flag);
+# ifndef __ASSUME_ATFCTS
+ if (result == -1 && errno == ENOSYS)
+ __have_atfcts = -1;
+ else
+# endif
+ return result;
+ }
+#endif
+
+#ifndef __ASSUME_ATFCTS
if (flag & ~AT_SYMLINK_NOFOLLOW)
{
__set_errno (EINVAL);
file = buf;
}
- int result;
INTERNAL_SYSCALL_DECL (err);
-#if __ASSUME_32BITUIDS > 0
+# if __ASSUME_32BITUIDS > 0
result = INTERNAL_SYSCALL (chown32, err, 3, CHECK_STRING (file), owner,
group);
-#else
+# else
static int __libc_old_chown;
-# ifdef __NR_chown32
+# ifdef __NR_chown32
if (__libc_missing_32bit_uids <= 0)
{
if (flag & AT_SYMLINK_NOFOLLOW)
__libc_missing_32bit_uids = 1;
}
-# endif /* __NR_chown32 */
+# endif /* __NR_chown32 */
if (((owner + 1) > (uid_t) ((__kernel_uid_t) -1U))
|| ((group + 1) > (gid_t) ((__kernel_gid_t) -1U)))
{
result = INTERNAL_SYSCALL (lchown, err, 3, CHECK_STRING (file), owner,
group);
-#endif
+# endif
if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (result, err), 0))
{
}
return result;
+#endif
}
int
fchownat (int fd, const char *file, uid_t owner, gid_t group, int flag)
{
+ int result;
+
+#ifdef __NR_fchownat
+# ifndef __ASSUME_ATFCTS
+ if (__have_atfcts >= 0)
+# endif
+ {
+ result = INLINE_SYSCALL (fchownat, 5, fd, file, owner, group, flag);
+# ifndef __ASSUME_ATFCTS
+ if (result == -1 && errno == ENOSYS)
+ __have_atfcts = -1;
+ else
+# endif
+ return result;
+ }
+#endif
+
+#ifndef __ASSUME_ATFCTS
if (flag & ~AT_SYMLINK_NOFOLLOW)
{
__set_errno (EINVAL);
file = buf;
}
- int result;
INTERNAL_SYSCALL_DECL (err);
-#if __ASSUME_32BITUIDS > 0
+# if __ASSUME_32BITUIDS > 0
if (flag & AT_SYMLINK_NOFOLLOW)
result = INTERNAL_SYSCALL (lchown32, err, 3, CHECK_STRING (file), owner,
group);
else
result = INTERNAL_SYSCALL (chown32, err, 3, CHECK_STRING (file), owner,
group);
-#else
-# ifdef __NR_chown32
+# else
+# ifdef __NR_chown32
if (__libc_missing_32bit_uids <= 0)
{
if (flag & AT_SYMLINK_NOFOLLOW)
__libc_missing_32bit_uids = 1;
}
-# endif /* __NR_chown32 */
+# endif /* __NR_chown32 */
if (((owner + 1) > (gid_t) ((__kernel_uid_t) -1U))
|| ((group + 1) > (gid_t) ((__kernel_gid_t) -1U)))
else
result = INTERNAL_SYSCALL (chown, err, 3, CHECK_STRING (file), owner,
group);
-#endif
+# endif
if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (result, err), 0))
{
}
return result;
+#endif
}