# This is a BitKeeper generated patch for the following project: # Project Name: glibc # This patch format is intended for GNU patch command version 2.5 or higher. # This patch includes the following deltas: # ChangeSet 1.2.1.2 -> 1.51 # sysdeps/unix/Dist 1.1 -> 1.4 # locale/locale.h 1.1 -> 1.3 # linuxthreads/sysdeps/pthread/bits/libc-lock.h 1.1 -> 1.2 # sysdeps/unix/make-syscalls.sh 1.1 -> 1.13 # elf/dl-load.c 1.1.1.2 -> 1.10 # sysdeps/unix/sysv/linux/i386/lxstat.c 1.1 -> 1.3 # stdio-common/Makefile 1.1.1.1 -> 1.4 # linuxthreads/cancel.c 1.1 -> 1.2 # include/locale.h 1.1 -> 1.2 # locale/bits/locale.h 1.1 -> 1.2 # locale/programs/ld-identification.c 1.1 -> 1.3 # sysdeps/unix/sysv/linux/lxstat64.c 1.1 -> 1.3 # locale/Makefile 1.1.1.1 -> 1.7 # locale/programs/config.h 1.1 -> 1.2 # elf/dl-minimal.c 1.1.1.1 -> 1.9 # sysdeps/unix/sysv/linux/xstat64.c 1.1 -> 1.3 # sysdeps/unix/sysv/linux/not-cancel.h 1.1 -> 1.2 # locale/Versions 1.1 -> 1.4 # sysdeps/unix/sysv/linux/getdents.c 1.1.1.1 -> 1.13 # linuxthreads/internals.h 1.1 -> 1.2 # configure.in 1.1.1.2 -> 1.4 # locale/langinfo.h 1.1 -> 1.4 # sysdeps/unix/syscalls.list 1.1 -> 1.12 # sysdeps/unix/sysv/linux/utimes.c 1.1 -> 1.6 # sysdeps/unix/sysv/linux/xstat.c 1.1 -> 1.3 # include/sys/stat.h 1.1 -> 1.3 # locale/newlocale.c 1.1 -> 1.2 # sysdeps/unix/sysv/linux/Dist 1.1 -> 1.2 # sysdeps/unix/sysv/linux/open64.c 1.1 -> 1.7 # sysdeps/unix/sysv/linux/truncate64.c 1.1 -> 1.5 # locale/programs/locarchive.c 1.1.1.1 -> 1.3 # locale/setlocale.c 1.1.1.1 -> 1.3 # sysdeps/unix/sysv/syscalls.list 1.1 -> 1.2 # iconv/gconv_dl.c 1.1 -> 1.3 # io/Makefile 1.1 -> 1.8 # include/unistd.h 1.1.1.1 -> 1.7 # linuxthreads/Versions 1.1 -> 1.2 # linuxthreads/sysdeps/unix/sysv/linux/i386/sysdep-cancel.h 1.1 -> 1.4 # locale/findlocale.c 1.1 -> 1.3 # sysdeps/unix/Makefile 1.1 -> 1.7 # sysdeps/unix/common/syscalls.list 1.1 -> 1.3 # locale/loadarchive.c 1.1 -> 1.2 # include/fcntl.h 1.1 -> 1.6 # sysdeps/unix/sysv/linux/i386/lchown.c 1.1 -> 1.5 # misc/Makefile 1.1.1.1 -> 1.4 # sysdeps/unix/sysv/linux/lxstat.c 1.1 -> 1.3 # config.h.in 1.1.1.2 -> 1.4 # config.make.in 1.1.1.2 -> 1.4 # include/stdio.h 1.1 -> 1.3 # linuxthreads/Makefile 1.1.1.1 -> 1.6 # include/utime.h 1.1 -> 1.3 # sysdeps/unix/sysv/linux/getcwd.c 1.1 -> 1.5 # sysdeps/unix/sysv/linux/i386/xstat.c 1.1 -> 1.3 # sysdeps/unix/sysv/linux/i386/sysdep.h 1.1 -> 1.4 # linuxthreads/libc-cancellation.c 1.1 -> 1.2 # sysdeps/generic/sysdep-cancel.h 1.1 -> 1.2 # sysdeps/unix/sysv/linux/i386/chown.c 1.1.1.1 -> 1.7 # sysdeps/unix/sysv/linux/xmknod.c 1.1 -> 1.2 # locale/xlocale.h 1.1 -> 1.4 # iconv/gconv_trans.c 1.1 -> 1.3 # locale/freelocale.c 1.1 -> 1.2 # locale/categories.def 1.1 -> 1.4 # include/dlfcn.h 1.1.1.1 -> 1.3 # sysdeps/unix/sysv/linux/syscalls.list 1.1 -> 1.3 # (new) -> 1.2 sysdeps/unix/s-proto-xlate.S # (new) -> 1.3 sysdeps/unix/symlink.c # (new) -> 1.2 locale/lc-fsctype.c # (new) -> 1.3 locale/programs/ld-fsctype.c # (new) -> 1.7 sysdeps/unix/readlink.c # (new) -> 1.3 sysdeps/generic/sysdep-cancel-xlate.h # (new) -> 1.5 locale/C-fsctype.c # (new) -> 1.24 locale/fsctype.h # (new) -> 1.13 sysdeps/unix/sysdep-doxlate.h # (new) -> 1.4 sysdeps/unix/open.c # (new) -> 1.1 include/fsctype.h # (new) -> 1.2 sysdeps/unix/c-proto-cancel-doxlate.c # (new) -> 1.1 sysdeps/unix/s-proto-cancel-xlate.S # (new) -> 1.17 locale/fsctype.c # (new) -> 1.2 sysdeps/generic/sysdep-xlate.h # (new) -> 1.6 sysdeps/unix/sysv/linux/getdents-xlate.c # (new) -> 1.2 sysdeps/unix/c-proto-doxlate.c # (new) -> 1.6 sysdeps/unix/sysdep-cancel-doxlate.h # (new) -> 1.5 sysdeps/unix/sysv/linux/i386/sysdep-xlate.h # # The following is the BitKeeper ChangeSet Log # -------------------------------------------- # 04/03/17 address@hidden 1.49 # Merge cl.aratech.co.kr:/mnt/tj-work/lc_fsctype/glibc-bk # into cl.aratech.co.kr:/mnt/tj-work/lc_fsctype/glibc-lc_fsctype # -------------------------------------------- # 04/03/20 address@hidden 1.50 # rule changed for arguments which can specify new file. # -------------------------------------------- # 04/03/22 address@hidden 1.51 # symlink rule fix # arg0 NULL bug fix # -------------------------------------------- # diff -Nru a/config.h.in b/config.h.in --- a/config.h.in Mon Mar 22 14:59:24 2004 +++ b/config.h.in Mon Mar 22 14:59:24 2004 @@ -88,6 +88,9 @@ /* Define if static NSS modules are wanted. */ #undef DO_STATIC_NSS +/* Define if LC_FSCTYPE xlate is enabled. */ +#undef DO_FSCTYPE_XLATE + /* Define if gcc uses DWARF2 unwind information for exception support. */ #undef HAVE_DWARF2_UNWIND_INFO diff -Nru a/config.make.in b/config.make.in --- a/config.make.in Mon Mar 22 14:59:24 2004 +++ b/config.make.in Mon Mar 22 14:59:24 2004 @@ -85,6 +85,7 @@ build-omitfp = @omitfp@ build-bounded = @bounded@ build-static-nss = @static_nss@ +build-fsctype-xlate = @fsctype_xlate@ add-ons = @subdirs@ cross-compiling = @cross_compiling@ force-install = @force_install@ diff -Nru a/configure.in b/configure.in --- a/configure.in Mon Mar 22 14:59:24 2004 +++ b/configure.in Mon Mar 22 14:59:24 2004 @@ -157,6 +157,16 @@ [enable_versioning=$enableval], [enable_versioning=yes]) +AC_ARG_ENABLE([fsctype-xlate], + AC_HELP_STRING([--enable-fsctype-xlate], + [enable LC_FSCTYPE filename translation @<:@default=no@:>@]), + [fsctype_xlate=$enableval], + [fsctype_xlate=no]) +if test x"$fsctype_xlate" = xyes; then + AC_DEFINE(DO_FSCTYPE_XLATE) +fi +AC_SUBST(fsctype_xlate) + AC_ARG_ENABLE([oldest-abi], AC_HELP_STRING([--enable-oldest-abi=ABI], [configure the oldest ABI supported @<:@e.g. 2.2@:>@ @<:@default=glibc default@:>@]), diff -Nru a/elf/dl-load.c b/elf/dl-load.c --- a/elf/dl-load.c Mon Mar 22 14:59:24 2004 +++ b/elf/dl-load.c Mon Mar 22 14:59:24 2004 @@ -1400,7 +1400,7 @@ this could mean there is something wrong in the installation and the user might want to know about this. */ static int -open_verify (const char *name, struct filebuf *fbp) +open_verify (const char *name, int noxlate, struct filebuf *fbp) { /* This is the expected ELF header. */ #define ELF32_CLASS ELFCLASS32 @@ -1435,7 +1435,15 @@ int errval = 0; /* Open the file. We always open files read-only. */ +#ifdef FSCTYPE_XLATE_ENABLED + /* gconv functions call dlopen with __RTLD_NOXLATE to avoid infinite + recursion when loading gconv modules for LC_FSCTYPE. */ + extern int __libc_open_noxlate (const char *file, int oflag, ...); + fd = noxlate ? __libc_open_noxlate (name, O_RDONLY) + : __open (name, O_RDONLY); +#else fd = __open (name, O_RDONLY); +#endif if (fd != -1) { ElfW(Ehdr) *ehdr; @@ -1591,7 +1599,7 @@ if MAY_FREE_DIRS is true. */ static int -open_path (const char *name, size_t namelen, int preloaded, +open_path (const char *name, size_t namelen, int noxlate, int preloaded, struct r_search_path_struct *sps, char **realname, struct filebuf *fbp) { @@ -1637,7 +1645,7 @@ if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_LIBS, 0)) _dl_debug_printf (" trying file=%s\n", buf); - fd = open_verify (buf, fbp); + fd = open_verify (buf, noxlate, fbp); if (this_dir->status[cnt] == unknown) { if (fd != -1) @@ -1735,6 +1743,7 @@ char *name_copy; struct link_map *l; struct filebuf fb; + int noxlate = mode & __RTLD_NOXLATE; /* Look for this name among those already loaded. */ for (l = GL(dl_loaded); l; l = l->l_next) @@ -1792,28 +1801,28 @@ to be loaded. Then that object's dependent, and on up. */ for (l = loader; fd == -1 && l; l = l->l_loader) if (cache_rpath (l, &l->l_rpath_dirs, DT_RPATH, "RPATH")) - fd = open_path (name, namelen, preloaded, &l->l_rpath_dirs, - &realname, &fb); + fd = open_path (name, namelen, noxlate, preloaded, + &l->l_rpath_dirs, &realname, &fb); /* If dynamically linked, try the DT_RPATH of the executable itself. */ l = GL(dl_loaded); if (fd == -1 && l && l->l_type != lt_loaded && l != loader && l->l_rpath_dirs.dirs != (void *) -1) - fd = open_path (name, namelen, preloaded, &l->l_rpath_dirs, - &realname, &fb); + fd = open_path (name, namelen, noxlate, preloaded, + &l->l_rpath_dirs, &realname, &fb); } /* Try the LD_LIBRARY_PATH environment variable. */ if (fd == -1 && env_path_list.dirs != (void *) -1) - fd = open_path (name, namelen, preloaded, &env_path_list, - &realname, &fb); + fd = open_path (name, namelen, noxlate, preloaded, + &env_path_list, &realname, &fb); /* Look at the RUNPATH information for this binary. */ if (fd == -1 && loader != NULL && cache_rpath (loader, &loader->l_runpath_dirs, DT_RUNPATH, "RUNPATH")) - fd = open_path (name, namelen, preloaded, + fd = open_path (name, namelen, noxlate, preloaded, &loader->l_runpath_dirs, &realname, &fb); if (fd == -1 @@ -1861,7 +1870,7 @@ if (cached != NULL) { - fd = open_verify (cached, &fb); + fd = open_verify (cached, noxlate, &fb); if (__builtin_expect (fd != -1, 1)) { realname = local_strdup (cached); @@ -1880,8 +1889,8 @@ && ((l = loader ?: GL(dl_loaded)) == NULL || __builtin_expect (!(l->l_flags_1 & DF_1_NODEFLIB), 1)) && rtld_search_dirs.dirs != (void *) -1) - fd = open_path (name, namelen, preloaded, &rtld_search_dirs, - &realname, &fb); + fd = open_path (name, namelen, noxlate, preloaded, + &rtld_search_dirs, &realname, &fb); /* Add another newline when we are tracing the library loading. */ if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_LIBS, 0)) @@ -1897,7 +1906,7 @@ fd = -1; else { - fd = open_verify (realname, &fb); + fd = open_verify (realname, noxlate, &fb); if (__builtin_expect (fd, 0) == -1) free (realname); } diff -Nru a/elf/dl-minimal.c b/elf/dl-minimal.c --- a/elf/dl-minimal.c Mon Mar 22 14:59:24 2004 +++ b/elf/dl-minimal.c Mon Mar 22 14:59:24 2004 @@ -359,3 +359,18 @@ up to 36. We don't need this here. */ const char INTUSE(_itoa_lower_digits)[16] attribute_hidden = "0123456789abcdef"; + +#ifdef DO_FSCTYPE_XLATE + +/* We currently do not support LC_FSCTYPE functionality in rtld even + when it's enabled in glibc. The following dummy variables prevent + locale/fsctype.o from linking into rtld. */ + +int _nl_fsctype_get_conv_1 = 0; +int _nl_fsctype_free_conv = 0; +int _nl_fsctype_xlate = 0; +int __nl_fsctype_next_file = 0; +int __nl_fsctype_free_conv_iter = 0; +int __nl_fsctype_xlate_used = 0; + +#endif /* DO_FSCTYPE_XLATE */ diff -Nru a/iconv/gconv_dl.c b/iconv/gconv_dl.c --- a/iconv/gconv_dl.c Mon Mar 22 14:59:24 2004 +++ b/iconv/gconv_dl.c Mon Mar 22 14:59:24 2004 @@ -113,7 +113,11 @@ if (found->counter < -TRIES_BEFORE_UNLOAD) { assert (found->handle == NULL); - found->handle = __libc_dlopen (found->name); + /* dlopen uses open(2). So, if we're loading gconv module + for LC_FSCTYPE, we will fall into inifinite loop. Use + __RTLD_NOXLATE flag to avoid it. */ + found->handle = __libc_dlopen_mode (found->name, + RTLD_LAZY|__RTLD_NOXLATE); if (found->handle != NULL) { found->fct = __libc_dlsym (found->handle, "gconv"); diff -Nru a/iconv/gconv_trans.c b/iconv/gconv_trans.c --- a/iconv/gconv_trans.c Mon Mar 22 14:59:24 2004 +++ b/iconv/gconv_trans.c Mon Mar 22 14:59:24 2004 @@ -269,7 +269,10 @@ { __gconv_trans_query_fct queryfct; - trans->handle = __libc_dlopen (trans->fname); + /* dlopen uses open(2). So, if we're loading gconv module for + LC_FSCTYPE, we will fall into inifinite loop. Use __RTLD_NOXLATE + flag to avoid it. */ + trans->handle = __libc_dlopen_mode (trans->fname, RTLD_LAZY|__RTLD_NOXLATE); if (trans->handle == NULL) /* Not available. */ return 1; diff -Nru a/include/dlfcn.h b/include/dlfcn.h --- a/include/dlfcn.h Mon Mar 22 14:59:24 2004 +++ b/include/dlfcn.h Mon Mar 22 14:59:24 2004 @@ -6,6 +6,7 @@ #define __RTLD_DLOPEN 0x80000000 #define __RTLD_SPROF 0x40000000 #define __RTLD_OPENEXEC 0x20000000 +#define __RTLD_NOXLATE 0x10000000 /* Now define the internal interfaces. */ extern void *__dlvsym (void *__handle, __const char *__name, diff -Nru a/include/fsctype.h b/include/fsctype.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/include/fsctype.h Mon Mar 22 14:59:24 2004 @@ -0,0 +1 @@ +#include diff -Nru a/include/locale.h b/include/locale.h --- a/include/locale.h Mon Mar 22 14:59:24 2004 +++ b/include/locale.h Mon Mar 22 14:59:24 2004 @@ -6,7 +6,8 @@ libc_hidden_proto (setlocale) /* This has to be changed whenever a new locale is defined. */ -#define __LC_LAST 13 +#define __LC_LAST 14 +#define __LC_LOADABLE(cat) ((cat) != __LC_ALL && (cat) != __LC_FSCTYPE) extern struct loaded_l10nfile *_nl_locale_file_list[] attribute_hidden; diff -Nru a/linuxthreads/Makefile b/linuxthreads/Makefile --- a/linuxthreads/Makefile Mon Mar 22 14:59:24 2004 +++ b/linuxthreads/Makefile Mon Mar 22 14:59:24 2004 @@ -50,7 +50,7 @@ ptw-open ptw-open64 ptw-pause ptw-pread ptw-pread64 \ ptw-pwrite ptw-pwrite64 ptw-tcdrain ptw-wait \ ptw-waitpid pt-system old_pthread_atfork pthread_atfork \ - ptcleanup + ptcleanup ptw-sys_open # Don't generate deps for calls with no sources. See sysdeps/unix/Makefile. omit-deps = $(unix-syscalls:%=ptw-%) diff -Nru a/linuxthreads/Versions b/linuxthreads/Versions --- a/linuxthreads/Versions Mon Mar 22 14:59:24 2004 +++ b/linuxthreads/Versions Mon Mar 22 14:59:24 2004 @@ -33,7 +33,8 @@ __libc_creat; __libc_poll; __libc_pselect; __libc_select; __libc_sigpause; __libc_sigsuspend; __libc_sigwait; __libc_sigwaitinfo; __libc_waitid; __libc___xpg_sigpause; __librt_enable_asynccancel; - __librt_disable_asynccancel; __librt_multiple_threads; + __librt_disable_asynccancel; __librt_enable_deferredcancel; + __librt_disable_deferredcancel; __librt_multiple_threads; } } diff -Nru a/linuxthreads/cancel.c b/linuxthreads/cancel.c --- a/linuxthreads/cancel.c Mon Mar 22 14:59:24 2004 +++ b/linuxthreads/cancel.c Mon Mar 22 14:59:24 2004 @@ -85,6 +85,27 @@ THREAD_SETMEM(self, p_canceltype, oldtype); } +int +internal_function attribute_hidden +__pthread_enable_deferredcancel (void) +{ + pthread_descr self = thread_self(); + int oldtype = THREAD_GETMEM(self, p_canceltype); + THREAD_SETMEM(self, p_canceltype, PTHREAD_CANCEL_DEFERRED); + return oldtype; +} + +void +internal_function attribute_hidden +__pthread_disable_deferredcancel (int oldtype) +{ + pthread_descr self = thread_self(); + THREAD_SETMEM(self, p_canceltype, oldtype); + if (oldtype == PTHREAD_CANCEL_ASYNCHRONOUS && + __builtin_expect (THREAD_GETMEM(self, p_canceled), 0) && + THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE) + __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); +} int pthread_cancel(pthread_t thread) { diff -Nru a/linuxthreads/internals.h b/linuxthreads/internals.h --- a/linuxthreads/internals.h Mon Mar 22 14:59:24 2004 +++ b/linuxthreads/internals.h Mon Mar 22 14:59:24 2004 @@ -467,15 +467,25 @@ extern int __pthread_enable_asynccancel (void) attribute_hidden; extern void __pthread_disable_asynccancel (int oldtype) internal_function attribute_hidden; +extern int __pthread_enable_deferredcancel (void) + internal_function attribute_hidden; +extern void __pthread_disable_deferredcancel (int oldtype) + internal_function attribute_hidden; /* The two functions are in libc.so and not exported. */ extern int __libc_enable_asynccancel (void) attribute_hidden; extern void __libc_disable_asynccancel (int oldtype) internal_function attribute_hidden; +extern int __libc_enable_deferredcancel (void) + internal_function attribute_hidden; +extern void __libc_disable_deferredcancel (int oldtype) + internal_function attribute_hidden; /* The two functions are in libc.so and are exported. */ extern int __librt_enable_asynccancel (void); extern void __librt_disable_asynccancel (int oldtype) internal_function; +extern int __librt_enable_deferredcancel (void) internal_function; +extern void __librt_disable_deferredcancel (int oldtype) internal_function; extern void __pthread_cleanup_upto (__jmp_buf target, char *targetframe) attribute_hidden; @@ -486,6 +496,10 @@ __libc_enable_asynccancel () # define LIBC_CANCEL_RESET(oldtype) \ __libc_disable_asynccancel (oldtype) +# define LIBC_CANCEL_DEFERRED() \ + __libc_enable_deferredcancel () +# define LIBC_CANCEL_DEFERRED_RESET(oldtype) \ + __libc_disable_deferredcancel (oldtype) # define LIBC_CANCEL_HANDLED() \ __asm (".globl " __SYMBOL_PREFIX "__libc_enable_asynccancel"); \ __asm (".globl " __SYMBOL_PREFIX "__libc_disable_asynccancel") @@ -494,6 +508,10 @@ __pthread_enable_asynccancel () # define LIBC_CANCEL_RESET(oldtype) \ __pthread_disable_asynccancel (oldtype) +# define LIBC_CANCEL_DEFERRED() \ + __pthread_enable_deferredcancel () +# define LIBC_CANCEL_DEFERRED_RESET(oldtype) \ + __pthread_disable_deferredcancel (oldtype) # define LIBC_CANCEL_HANDLED() \ __asm (".globl " __SYMBOL_PREFIX "__pthread_enable_asynccancel"); \ __asm (".globl " __SYMBOL_PREFIX "__pthread_disable_asynccancel") @@ -502,12 +520,18 @@ __librt_enable_asynccancel () # define LIBC_CANCEL_RESET(oldtype) \ __librt_disable_asynccancel (oldtype) +# define LIBC_CANCEL_DEFERRED() \ + __librt_enable_deferredcancel () +# define LIBC_CANCEL_DEFERRED_RESET(oldtype) \ + __librt_disable_deferredcancel (oldtype) # define LIBC_CANCEL_HANDLED() \ __asm (".globl " __SYMBOL_PREFIX "__librt_enable_asynccancel"); \ __asm (".globl " __SYMBOL_PREFIX "__librt_disable_asynccancel") #else # define LIBC_CANCEL_ASYNC() 0 /* Just a dummy value. */ # define LIBC_CANCEL_RESET(val) ((void)(val)) /* Nothing, but evaluate it. */ +# define LIBC_CANCEL_DEFERRED() 0 /* Just a dummy value. */ +# define LIBC_CANCEL_DEFERRED_RESET(val) ((void)(val)) /* Nothing, but evaluate it. */ # define LIBC_CANCEL_HANDLED() /* Nothing. */ #endif diff -Nru a/linuxthreads/libc-cancellation.c b/linuxthreads/libc-cancellation.c --- a/linuxthreads/libc-cancellation.c Mon Mar 22 14:59:24 2004 +++ b/linuxthreads/libc-cancellation.c Mon Mar 22 14:59:24 2004 @@ -34,7 +34,7 @@ int __libc_multiple_threads attribute_hidden __attribute__((nocommon)); strong_alias (__libc_multiple_threads, __librt_multiple_threads); -/* The next two functions are similar to pthread_setcanceltype() but +/* The next four functions are similar to pthread_setcanceltype() but more specialized for the use in the cancelable functions like write(). They do not need to check parameters etc. */ int @@ -60,5 +60,30 @@ LIBC_THREAD_SETMEM(self, p_canceltype, oldtype); } strong_alias (__libc_disable_asynccancel, __librt_disable_asynccancel) + +int +internal_function attribute_hidden +__libc_enable_deferredcancel (void) +{ + pthread_descr self = thread_self(); + int oldtype = LIBC_THREAD_GETMEM(self, p_canceltype); + LIBC_THREAD_SETMEM(self, p_canceltype, PTHREAD_CANCEL_DEFERRED); + return oldtype; +} +strong_alias (__libc_enable_deferredcancel, __librt_enable_deferredcancel) + +void +internal_function attribute_hidden +__libc_disable_deferredcancel (int oldtype) +{ + pthread_descr self = thread_self(); + LIBC_THREAD_SETMEM(self, p_canceltype, oldtype); + if (oldtype == PTHREAD_CANCEL_ASYNCHRONOUS && + __builtin_expect (LIBC_THREAD_GETMEM(self, p_canceled), 0) && + LIBC_THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE) + __libc_maybe_call2 (pthread_do_exit, + (PTHREAD_CANCELED, CURRENT_STACK_FRAME), 0); +} +strong_alias (__libc_disable_deferredcancel, __librt_disable_deferredcancel) #endif diff -Nru a/linuxthreads/sysdeps/pthread/bits/libc-lock.h b/linuxthreads/sysdeps/pthread/bits/libc-lock.h --- a/linuxthreads/sysdeps/pthread/bits/libc-lock.h Mon Mar 22 14:59:24 2004 +++ b/linuxthreads/sysdeps/pthread/bits/libc-lock.h Mon Mar 22 14:59:24 2004 @@ -23,7 +23,7 @@ #include -#if defined _LIBC && !defined NOT_IN_libc +#if defined _LIBC && (!defined NOT_IN_libc || IS_IN_libpthread == 1) #include #endif diff -Nru a/linuxthreads/sysdeps/unix/sysv/linux/i386/sysdep-cancel.h b/linuxthreads/sysdeps/unix/sysv/linux/i386/sysdep-cancel.h --- a/linuxthreads/sysdeps/unix/sysv/linux/i386/sysdep-cancel.h Mon Mar 22 14:59:24 2004 +++ b/linuxthreads/sysdeps/unix/sysv/linux/i386/sysdep-cancel.h Mon Mar 22 14:59:24 2004 @@ -26,16 +26,19 @@ #if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt -# undef PSEUDO -# define PSEUDO(name, syscall_name, args) \ +# undef __PSEUDO +# define __PSEUDO(name, prefix, syscall_name, args) \ .text; \ ENTRY (name) \ + CHECK_XLATE (prefix, syscall_name, args) \ SINGLE_THREAD_P; \ jne L(pseudo_cancel); \ + ENTRY (prefix##_nocancel) \ DO_CALL (syscall_name, args); \ cmpl $-4095, %eax; \ jae SYSCALL_ERROR_LABEL; \ ret; \ + END (prefix##_nocancel) \ L(pseudo_cancel): \ CENABLE \ SAVE_OLDTYPE_##args \ @@ -48,6 +51,10 @@ cmpl $-4095, %eax; \ jae SYSCALL_ERROR_LABEL; \ L(pseudo_end): + +#undef PSEUDO +#define PSEUDO(name, syscall_name, args) \ + __PSEUDO (name, bug bug bug, syscall_name, args) # define SAVE_OLDTYPE_0 movl %eax, %ecx; # define SAVE_OLDTYPE_1 SAVE_OLDTYPE_0 diff -Nru a/locale/C-fsctype.c b/locale/C-fsctype.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/locale/C-fsctype.c Mon Mar 22 14:59:24 2004 @@ -0,0 +1,34 @@ +/* Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Tejun Heo , 2004. + + 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 +#include "localeinfo.h" + +const struct locale_data _nl_C_LC_FSCTYPE attribute_hidden = +{ + _nl_C_name, + NULL, 0, 0, /* no file mapped */ + { NULL, }, /* no cached data */ + UNDELETABLE, + 0, + 2, + { + { .string = _nl_C_codeset } + } +}; diff -Nru a/locale/Makefile b/locale/Makefile --- a/locale/Makefile Mon Mar 22 14:59:24 2004 +++ b/locale/Makefile Mon Mar 22 14:59:24 2004 @@ -26,7 +26,7 @@ iso-4217.def weight.h weightwc.h strlen-hash.h elem-hash.h \ indigits.h indigitswc.h outdigits.h outdigitswc.h \ coll-lookup.h C-translit.h.in C-translit.h gen-translit.pl \ - locarchive.h hashval.h \ + locarchive.h hashval.h fsctype.h fsctype.c \ $(addprefix programs/, \ locale.c localedef.c \ $(localedef-modules:=.c) $(locale-modules:=.c) \ @@ -40,7 +40,7 @@ newlocale duplocale freelocale uselocale tests = tst-C-locale categories = ctype messages monetary numeric time paper name \ - address telephone measurement identification collate + address telephone measurement identification collate fsctype aux = $(categories:%=lc-%) $(categories:%=C-%) SYS_libc C_name \ xlocale localename global-locale coll-lookup others = localedef locale @@ -68,6 +68,12 @@ GPERF = gperf GPERFFLAGS = -acCgopt -k1,2,5,9,$$ -L ANSI-C + +include ../Makeconfig + +ifeq (yes,$(build-fsctype-xlate)) +routines += fsctype +endif include ../Rules diff -Nru a/locale/Versions b/locale/Versions --- a/locale/Versions Mon Mar 22 14:59:24 2004 +++ b/locale/Versions Mon Mar 22 14:59:24 2004 @@ -70,5 +70,8 @@ # global variables __collate_element_hash; __collate_element_strings; __collate_symbol_classes; __collate_symbol_hash; __collate_symbol_strings; + # fsctype related + __nl_fsctype_xlate_used; __nl_fsctype_next_file; + __nl_fsctype_free_conv_iter; } } diff -Nru a/locale/bits/locale.h b/locale/bits/locale.h --- a/locale/bits/locale.h Mon Mar 22 14:59:24 2004 +++ b/locale/bits/locale.h Mon Mar 22 14:59:24 2004 @@ -38,7 +38,8 @@ __LC_ADDRESS = 9, __LC_TELEPHONE = 10, __LC_MEASUREMENT = 11, - __LC_IDENTIFICATION = 12 + __LC_IDENTIFICATION = 12, + __LC_FSCTYPE = 13 }; #endif /* bits/locale.h */ diff -Nru a/locale/categories.def b/locale/categories.def --- a/locale/categories.def Mon Mar 22 14:59:24 2004 +++ b/locale/categories.def Mon Mar 22 14:59:24 2004 @@ -340,6 +340,14 @@ DEFINE_ELEMENT (_NL_IDENTIFICATION_ABBREVIATION, "abbreviation", std, string) DEFINE_ELEMENT (_NL_IDENTIFICATION_REVISION, "revision", std, string) DEFINE_ELEMENT (_NL_IDENTIFICATION_DATE, "date", std, string) - DEFINE_ELEMENT (_NL_IDENTIFICATION_CATEGORY, "category", std, stringarray, 13, 13) + DEFINE_ELEMENT (_NL_IDENTIFICATION_CATEGORY, "category", std, stringarray, 14, 14) DEFINE_ELEMENT (_NL_IDENTIFICATION_CODESET, "identification-codeset", std, string) + ), NO_POSTLOAD) + +/* Pseudo FSCTYPE locale */ +DEFINE_CATEGORY +( + LC_FSCTYPE, "LC_FSCTYPE", + ( + DEFINE_ELEMENT (_NL_FSCTYPE_CODESET, "fsctype-codeset", opt, string) ), NO_POSTLOAD) diff -Nru a/locale/findlocale.c b/locale/findlocale.c --- a/locale/findlocale.c Mon Mar 22 14:59:24 2004 +++ b/locale/findlocale.c Mon Mar 22 14:59:24 2004 @@ -27,6 +27,7 @@ #endif #include "localeinfo.h" +#include "fsctype.h" #include "../iconv/gconv_charset.h" #include "../iconv/gconv_int.h" @@ -66,7 +67,7 @@ { int mask; /* Name of the locale for this category. */ - char *loc_name; + char *loc_name, *tmp_name; const char *language; const char *modifier; const char *territory; @@ -101,7 +102,7 @@ /* We really have to load some data. First we try the archive, but only if there was no LOCPATH environment variable specified. */ - if (__builtin_expect (locale_path == NULL, 1)) + if (__builtin_expect (locale_path == NULL, 1) && category != LC_FSCTYPE) { struct locale_data *data = _nl_load_locale_from_archive (category, name); if (__builtin_expect (data != NULL, 1)) @@ -121,7 +122,7 @@ loc_name = (char *) *name; /* Make a writable copy of the locale name. */ - loc_name = strdupa (loc_name); + tmp_name = strdupa (loc_name); /* LOCALE can consist of up to four recognized parts for the XPG syntax: @@ -136,8 +137,23 @@ (3) territory (4) modifier */ - mask = _nl_explode_name (loc_name, &language, &modifier, &territory, + mask = _nl_explode_name (tmp_name, &language, &modifier, &territory, &codeset, &normalized_codeset); + + /* LC_FSCTYPE locale data are created on the fly. */ + if (category == LC_FSCTYPE) + { + struct locale_data *data = NULL; + + codeset = (mask & XPG_NORM_CODESET) ? normalized_codeset : codeset; + if (codeset != NULL) + data = _nl_fsctype_get_locale_data (loc_name, codeset); + + if (mask & XPG_NORM_CODESET) + free ((void *) normalized_codeset); + + return data; + } /* If exactly this locale was already asked for we have an entry with the complete name. */ diff -Nru a/locale/freelocale.c b/locale/freelocale.c --- a/locale/freelocale.c Mon Mar 22 14:59:24 2004 +++ b/locale/freelocale.c Mon Mar 22 14:59:24 2004 @@ -23,6 +23,7 @@ #include #include "localeinfo.h" +#include "fsctype.h" /* Lock for protecting global data. */ @@ -48,6 +49,9 @@ /* It's done. */ __libc_lock_unlock (__libc_setlocale_lock); + + /* Destroy fsctype cache. */ + _nl_fsctype_destroy_conv_cache (dataset); /* Free the locale_t handle itself. */ free (dataset); diff -Nru a/locale/fsctype.c b/locale/fsctype.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/locale/fsctype.c Mon Mar 22 14:59:24 2004 @@ -0,0 +1,542 @@ +/* Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Tejun Heo , 2004. + + 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 "fsctype.h" +#include "../libio/stdio.h" + +extern int __access_noxlate (__const char *__name, int __type); + +#define CONV_CACHE_SIZE 15 /* enough? */ + +int __nl_fsctype_xlate_used = 0; + +__libc_lock_define_initialized (static, ldata_cache_lock); +__libc_lock_define_initialized (static, conv_cache_lock); + +static struct locale_data *ldata_cache_head; +static struct locale_data *ldata_cache_hint; + +struct locale_data * +internal_function +_nl_fsctype_get_locale_data (const char *loc_name, const char *codeset) +{ + struct locale_data *data; + unsigned nstrings, loc_name_len, codeset_len; + char *tcs; + + if (ldata_cache_hint && + strcmp (codeset, ldata_cache_hint-> + values[_NL_ITEM_INDEX (_NL_FSCTYPE_CODESET)].string) == 0) + return ldata_cache_hint; + + __libc_lock_lock (ldata_cache_lock); + + /* Search the cache. */ + for (data = ldata_cache_head; data != NULL; data = (void *) data->filedata) + { + if (strcmp (data->values[_NL_ITEM_INDEX (_NL_FSCTYPE_CODESET)].string, + codeset) == 0) + { + /* Okay, matching locale_data found. */ + ldata_cache_hint = data; + goto out_unlock; + } + } + + /* Create the requested locale. */ + nstrings = _NL_ITEM_INDEX (_NL_NUM_LC_FSCTYPE); + loc_name_len = strlen (loc_name) + 1; + codeset_len = strlen (codeset) + 1; + data = malloc (sizeof(*data) + nstrings * sizeof(union locale_data_value) + + loc_name_len + codeset_len); + if (data == NULL) + goto out_unlock; + + data->name = (char *) &data->values[nstrings]; + memcpy ((char *) data->name, loc_name, loc_name_len); + + tcs = (char *) data->name + loc_name_len; + memcpy (tcs, codeset, codeset_len); + data->values[_NL_ITEM_INDEX(_NL_FSCTYPE_CODESET)].string = tcs; + + data->usage_count = UNDELETABLE; + data->nstrings = nstrings; + + /* Link into the cache list. */ + data->filedata = (void *) ldata_cache_head; + ldata_cache_head = data; + ldata_cache_hint = data; + + out_unlock: + __libc_lock_unlock (ldata_cache_lock); + return data; +} + +extern void +internal_function +_nl_fsctype_destroy_locale_cache (void) +{ + struct locale_data *data, *next; + + __libc_lock_lock (ldata_cache_lock); /* Well, just in case */ + + for (data = ldata_cache_head; data != NULL; data = next) + { + next = (void *) data->filedata; + free (data); + } + + ldata_cache_head = NULL; + ldata_cache_hint = NULL; + + __libc_lock_unlock (ldata_cache_lock); +} + +void +internal_function +_nl_fsctype_init_conv (__locale_t locale) +{ + locale->__fsctype_codeset = NULL; + locale->__fsctype_fs_codeset = NULL; + locale->__fsctype_conv_cache_gen = 0; + locale->__fsctype_conv_cache_cnts[0] = 0; + locale->__fsctype_conv_cache_cnts[1] = 0; + locale->__fsctype_conv_cache_heads[0] = NULL; + locale->__fsctype_conv_cache_heads[1] = NULL; + _nl_fsctype_update_conv (locale); +} + +static inline void +destroy_conv_cache_locked (__locale_t locale) +{ + int i; + struct fsctype_conv *conv, *next; + for (i = 0; i < 2; i++) + for (conv = locale->__fsctype_conv_cache_heads[i]; + conv != NULL; conv = next) + { + next = conv->next; + iconv_close (conv->iconv); + free (conv); + } +} + +void +internal_function +_nl_fsctype_update_conv (__locale_t locale) +{ + const char *cs, *fscs; + iconv_t conv; + + cs = locale->__locales[LC_CTYPE]->values[_NL_ITEM_INDEX (CODESET)].string; + fscs = locale->__locales[LC_FSCTYPE]-> + values[_NL_ITEM_INDEX (_NL_FSCTYPE_CODESET)].string; + + if (strcmp(cs, _nl_C_codeset) == 0 || strcmp(fscs, _nl_C_codeset) == 0 + || strcmp(cs, fscs) == 0 || (conv = iconv_open(cs, fscs)) == (iconv_t)-1) + { + cs = NULL; + fscs = NULL; + } + else + { + __nl_fsctype_xlate_used = 1; + iconv_close(conv); + } + + __libc_lock_lock (conv_cache_lock); + + destroy_conv_cache_locked (locale); + locale->__fsctype_codeset = cs; + locale->__fsctype_fs_codeset = fscs; + locale->__fsctype_conv_cache_gen++; + + __libc_lock_unlock (conv_cache_lock); + pdfsctype ("locale=%p cs=%s fscs=%s\n", locale, cs, fscs); +} + +void +internal_function +_nl_fsctype_destroy_conv_cache (__locale_t locale) +{ + __libc_lock_lock (conv_cache_lock); + destroy_conv_cache_locked (locale); + __libc_lock_unlock (conv_cache_lock); +} + +int +internal_function +_nl_fsctype_get_conv_1 (int tofscs, struct fsctype_conv **pconv, + __locale_t locale) +{ + const char *cs, *fscs; + struct fsctype_conv *conv; + unsigned gen; + + __libc_lock_lock (conv_cache_lock); + + if (locale->__fsctype_conv_cache_heads[tofscs] != NULL) + { + conv = locale->__fsctype_conv_cache_heads[tofscs]; + locale->__fsctype_conv_cache_heads[tofscs] = conv->next; + locale->__fsctype_conv_cache_cnts[tofscs]--; + __libc_lock_unlock (conv_cache_lock); + pdfsctype ("returning cached conv %p\n", conv); + *pconv = conv; + return 1; + } + + gen = locale->__fsctype_conv_cache_gen; + cs = locale->__locales[LC_CTYPE]->values[_NL_ITEM_INDEX (CODESET)].string; + fscs = locale->__locales[LC_FSCTYPE]-> + values[_NL_ITEM_INDEX (_NL_FSCTYPE_CODESET)].string; + + __libc_lock_unlock (conv_cache_lock); + + if (fscs == NULL) + return 0; + + if ((conv = malloc (sizeof(*conv))) == NULL) + { + pdfsctype("failed to allocate conv\n"); + return -1; + } + + conv->next = NULL; + conv->tofscs = tofscs; + conv->gen = gen; + conv->iconv = iconv_open (tofscs ? fscs : cs, tofscs ? cs : fscs); + + if (conv->iconv == (iconv_t) -1) + { + pdfsctype("iconv_open failed, errno=%d", errno); + free(conv); + return -1; + } + + pdfsctype ("returning new conv %p\n", conv); + *pconv = conv; + + return 1; +} + +void +internal_function +_nl_fsctype_free_conv (struct fsctype_conv *conv) +{ + __locale_t locale; + int tofscs; + + locale = _NL_CURRENT_LOCALE; + tofscs = conv->tofscs; + + __libc_lock_lock (conv_cache_lock); + + if (conv->gen == locale->__fsctype_conv_cache_gen + && locale->__fsctype_conv_cache_cnts[tofscs] < CONV_CACHE_SIZE) + { + pdfsctype ("caching conv %p\n", conv); + conv->next = locale->__fsctype_conv_cache_heads[tofscs]; + locale->__fsctype_conv_cache_heads[tofscs] = conv; + locale->__fsctype_conv_cache_cnts[tofscs]++; + conv = NULL; + } + + __libc_lock_unlock (conv_cache_lock); + + if (conv) + { + pdfsctype ("freeing conv %p\n", conv); + iconv_close (conv->iconv); + free(conv); + } +} + +#define toXdigit(v) ((v) < 10 ? '0' + (v) : 'A' + (v) - 10) +#define isXdigit(c) (((c) >= '0' && (c) <= '9') || ((c) >= 'A' && (c) <= 'F')) +#define toXval(c) ((c) <= '9' ? (c) - '0' : (c) - 'A' + 10) + +int +internal_function +_nl_fsctype_xlate (struct fsctype_conv *conv, + char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft) +{ + int saved_errno = errno; + + while (iconv (conv->iconv, inbuf, inbytesleft, + outbuf, outbytesleft) == (size_t) -1) + { + unsigned char un, ln; + switch (errno) { + case EILSEQ: + case EINVAL: + if (*outbytesleft < 3) + { + __set_errno(E2BIG); + iconv (conv->iconv, NULL, NULL, NULL, NULL); + return -1; + } + + un = (*inbuf)[0] >> 4 & 0xf; /* upper nibble */ + ln = (*inbuf)[0] & 0xf; /* lower nibble */ + (*outbuf)[0] = '^'; + (*outbuf)[1] = toXdigit(un); + (*outbuf)[2] = toXdigit(ln); + + (*inbuf)++; + (*inbytesleft)--; + (*outbuf) += 3; + (*outbytesleft) -= 3; + break; + + default: + iconv (conv->iconv, NULL, NULL, NULL, NULL); + return -1; + } + } + + __set_errno(saved_errno); + iconv (conv->iconv, NULL, NULL, NULL, NULL); + return 0; +} + +/* + * when access_first == 0 + * STATE_INITIAL ---> STATE_DECODE ---> STATE_XLATE ---> STATE_DONE ---> END + * \------------------> + * when access_first == 1 + * STATE_INITIAL ---> STATE_DONE ---> END + */ + +enum { + STATE_INITIAL, + STATE_DECODE, + STATE_XLATE, + STATE_DONE, + STATE_NULL, +}; + +static int +decode_hex (const char *istr, char *ostr, size_t *ostr_len) +{ + char *orig_ostr = ostr; + int hex_encountered = 0; + + do { + if (istr[0] == '^' && isXdigit(istr[1]) && isXdigit(istr[2])) + { + *ostr = (toXval(istr[1]) << 4) + toXval(istr[2]); + istr += 3; + ostr += 1; + hex_encountered = 1; + } + else + *ostr++ = *istr++; + } while (*istr != '\0'); + + *ostr++ = '\0'; + *ostr_len = ostr - orig_ostr; + + return hex_encountered; +} + +static char * +match_path (int symlink_arg0, const char *orig, char *buf0, char *buf1, + size_t buf_size, struct fsctype_conv *conv) +{ + char *ip, *op, *cp; + size_t ilen, olen, orig_len, buf0_len, buf1_len; + int hex_decoded; + + ip = (char *) orig; + op = buf0; + orig_len = ilen = strlen (ip) + 1; + olen = buf_size; + if (_nl_fsctype_xlate (conv, &ip, &ilen, &op, &olen) < 0) + return NULL; + buf0_len = olen; + + hex_decoded = decode_hex (buf0, buf1, &buf1_len); + + if (symlink_arg0 + || (cp = memrchr (buf1 + buf1_len - 1, '/', buf1_len - 1)) == NULL) + { + if (__access_noxlate (buf1, F_OK) == 0) + return buf1; + if (!symlink_arg0 && errno != ENOENT) + return NULL; + + if (hex_decoded) + { + if (__access_noxlate (buf0, F_OK) == 0) + return buf0; + if (!symlink_arg0 && errno != ENOENT) + return NULL; + } + + if (__access_noxlate (orig, F_OK) == 0) + return (char *) orig; + if (!symlink_arg0 && errno != ENOENT) + return NULL; + + return buf1; + } + else + { + *cp = '\0'; + if (__access_noxlate (buf1, F_OK) == 0) + { + *cp = '/'; + return buf1; + } + if (errno != ENOENT) + return NULL; + + if (hex_decoded) + { + cp = memrchr (buf0 + buf0_len - 1, '/', buf0_len - 1); + *cp = '\0'; + if (__access_noxlate (buf0, F_OK) == 0) + { + *cp = '/'; + return buf0; + } + if (errno != ENOENT) + return NULL; + } + + if (orig_len > buf_size) + { + errno = E2BIG; + return NULL; + } + memcpy (buf1, orig, orig_len); + buf1_len = orig_len; + + cp = memrchr (buf1 + buf1_len - 1, '/', buf1_len - 1); + *cp = '\0'; + if (__access_noxlate (buf1, F_OK) == 0) + { + *cp = '/'; + return buf1; + } + return NULL; + } +} + +int +__nl_fsctype_next_file (struct fsctype_conv_iter *iter) +{ +#define SWAP_ARG0 do { \ + char *swap_cp = iter->tmp; \ + iter->tmp = iter->arg0; \ + iter->arg0 = swap_cp; \ +} while (0) + + int ret = -1; + + switch (iter->state) { + case STATE_INITIAL: + switch (_nl_fsctype_get_conv (1, &iter->conv)) { + case -1: + return -1; + case 0: + iter->arg0 = (char *)iter->orig[0]; + iter->arg1 = (char *)iter->orig[1]; + iter->state = STATE_NULL; + return 1; + case 1: + /* fall through */ ; + } + + iter->tmp = iter->conv->bufs[1]; + + if (iter->orig[1]) + { + iter->arg1 = match_path (0, iter->orig[1], + iter->conv->bufs[1], iter->conv->bufs[2], + sizeof (iter->conv->bufs[0]), iter->conv); + if (iter->arg1 == NULL) + goto out_free; + + if (iter->tmp == iter->arg1) + iter->tmp = iter->conv->bufs[2]; + } + + if (iter->match_first) + { + iter->arg0 = match_path (1, iter->orig[0], + iter->conv->bufs[0], iter->tmp, + sizeof (iter->conv->bufs[0]), iter->conv); + if (iter->arg0 == NULL) + goto out_free; + + iter->state = STATE_DONE; + } + else + { + char *ip, *op; + size_t ilen, olen; + + iter->arg0 = iter->conv->bufs[0]; + + ip = (char *) iter->orig[0]; + op = iter->tmp; + ilen = strlen (ip) + 1; + olen = sizeof(iter->conv->bufs[0]); + if (_nl_fsctype_xlate (iter->conv, &ip, &ilen, &op, &olen) < 0) + goto out_free; + + if (decode_hex (iter->tmp, iter->arg0, &olen)) + iter->state = STATE_DECODE; + else + iter->state = STATE_XLATE; + } + return 1; + + case STATE_DECODE: + SWAP_ARG0; + iter->state = STATE_XLATE; + return 1; + + case STATE_XLATE: + iter->arg0 = (char *) iter->orig[0]; + iter->state = STATE_DONE; + return 1; + + case STATE_DONE: + ret = 0; + goto out_free; + + case STATE_NULL: + return 0; + } + + out_free: + _nl_fsctype_free_conv (iter->conv); + return ret; +#undef SWAP_ARG0 +} + +void +__nl_fsctype_free_conv_iter (struct fsctype_conv_iter *iter) +{ + _nl_fsctype_free_conv (iter->conv); +} diff -Nru a/locale/fsctype.h b/locale/fsctype.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/locale/fsctype.h Mon Mar 22 14:59:24 2004 @@ -0,0 +1,219 @@ +/* Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Tejun Heo , 2004. + + 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. */ + +#ifndef _FSCTYPE_H +#define _FSCTYPE_H + +#include +#include +#include +#include +#include +#include "localeinfo.h" +#include "../iconv/iconv.h" + +struct fsctype_conv { + struct fsctype_conv *next; + int tofscs; + unsigned gen; + iconv_t iconv; + char bufs[3][NAME_MAX+1]; +}; + +#if 0 +#include +#define pdfsctype(fmt, args...) \ + fprintf(stderr, "fsctype<%s>: "fmt, __FUNCTION__ , ##args) +#else +#define pdfsctype(fmt, args...) +#endif + +# if !defined DO_FSCTYPE_XLATE || IS_IN_rtld == 1 +# undef FSCTYPE_XLATE_ENABLED + +static inline struct locale_data * +_nl_fsctype_get_locale_data (const char *loc_name, const char *codeset) +{ + return NULL; +} + +static inline void +_nl_fsctype_destroy_locale_cache (void) +{ } + +static inline void +_nl_fsctype_init_conv (__locale_t locale) +{ + locale->__fsctype_codeset = NULL; +} + +static inline void +_nl_fsctype_update_conv (__locale_t locale) +{ } + +static inline void +_nl_fsctype_destroy_conv_cache (__locale_t locale) +{ } + +#define __NL_FSCTYPE_XLATE1(check, match_first, cancel, fn, file, args...) \ + (fn) ((file) , ##args) +#define __NL_FSCTYPE_XLATE2(check, match_first, cancel, \ + fn, ofile, nfile, args...) \ + (fn) ((ofile), (nfile) , ##args) + +# else /* !defined DO_FSCTYPE_XLATE || IS_IN_rtld == 1 */ +# define FSCTYPE_XLATE_ENABLED + +extern struct locale_data * _nl_fsctype_get_locale_data (const char *loc_name, + const char *codeset) + internal_function attribute_hidden; + +extern void _nl_fsctype_destroy_locale_cache (void) + internal_function attribute_hidden; + +extern void _nl_fsctype_init_conv (__locale_t locale) + internal_function attribute_hidden; + +extern void _nl_fsctype_update_conv (__locale_t locale) + internal_function attribute_hidden; + +extern void _nl_fsctype_destroy_conv_cache (__locale_t locale) + internal_function attribute_hidden; + +extern int _nl_fsctype_get_conv_1 (int tofscs, struct fsctype_conv **pconv, + __locale_t locale) + internal_function attribute_hidden; + +static inline int +_nl_fsctype_get_conv (int tofscs, struct fsctype_conv **pconv) +{ + __locale_t locale; + + if ((locale = _NL_CURRENT_LOCALE)->__fsctype_codeset == NULL) + return 0; + return _nl_fsctype_get_conv_1 (tofscs, pconv, locale); +} + +extern void _nl_fsctype_free_conv (struct fsctype_conv *conv) + internal_function attribute_hidden; + +extern int _nl_fsctype_xlate (struct fsctype_conv *conv, + char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft) + internal_function attribute_hidden; + +struct fsctype_conv_iter { + const char *orig[2]; + int match_first; + struct fsctype_conv *conv; + int state; + char *arg0, *arg1, *tmp; +}; + +static inline int __nl_fsctype_xlate_enabled (void) +{ + return _NL_CURRENT_LOCALE->__fsctype_codeset != NULL; +} + +extern int __nl_fsctype_next_file (struct fsctype_conv_iter *iter); +extern void __nl_fsctype_free_conv_iter (struct fsctype_conv_iter *iter); + +#define __NL_FSCTYPE_CANCEL_NONE_START +#define __NL_FSCTYPE_CANCEL_NONE_END +#define __NL_FSCTYPE_CANCEL_DEFERRED_START \ + { int __single, __oldtype = 0 /* just to keep gcc happy */; \ + if (!(__single = SINGLE_THREAD_P)) __oldtype = LIBC_CANCEL_DEFERRED (); +#define __NL_FSCTYPE_CANCEL_DEFERRED_END \ + if (!__single) LIBC_CANCEL_DEFERRED_RESET (__oldtype); } +#define __NL_FSCTYPE_CANCEL_ASYNC_START \ + __libc_cleanup_region_start (1, \ + (void (*)(void *)) __nl_fsctype_free_conv_iter, &__iter); +#define __NL_FSCTYPE_CANCEL_ASYNC_END \ + __libc_cleanup_region_end (0); + +#define __NL_FSCTYPE_XLATE1(check, match_first, cancel, fn, file, args...) \ +({ \ + int __ret, __ret2; \ + if (check && !__nl_fsctype_xlate_enabled ()) \ + __ret = (fn) ((file) , ##args); \ + else \ + { \ + int __saved_errno = errno; \ + struct fsctype_conv_iter __iter = { { (file), NULL }, (match_first) }; \ + __NL_FSCTYPE_CANCEL_##cancel##_START \ + __ret = -1; \ + while ((__ret2 = __nl_fsctype_next_file (&__iter)) == 1) \ + { \ + __ret = (fn) (__iter.arg0 , ##args); \ + if (__ret != -1 || errno != ENOENT) \ + { \ + __nl_fsctype_free_conv_iter (&__iter); \ + break; \ + } \ + } \ + __NL_FSCTYPE_CANCEL_##cancel##_END \ + __ret = __ret2 == -1 ? -1 : __ret; \ + if (__ret != -1) \ + __set_errno (__saved_errno); \ + } \ + __ret; \ +}) + +#define __NL_FSCTYPE_XLATE2(check, match_first, cancel, \ + fn, ofile, nfile, args...) \ +({ \ + int __ret, __ret2; \ + if (check && !__nl_fsctype_xlate_enabled ()) \ + __ret = (fn) ((ofile), (nfile) , ##args); \ + else \ + { \ + int __saved_errno = errno; \ + struct fsctype_conv_iter __iter = { { (ofile), (nfile) }, \ + (match_first) }; \ + __NL_FSCTYPE_CANCEL_##cancel##_START \ + __ret = -1; \ + while ((__ret2 = __nl_fsctype_next_file (&__iter)) == 1) \ + { \ + __ret = (fn) (__iter.arg0, __iter.arg1 , ##args); \ + if (__ret != -1 || errno != ENOENT) \ + { \ + __nl_fsctype_free_conv_iter (&__iter); \ + break; \ + } \ + } \ + __NL_FSCTYPE_CANCEL_##cancel##_END \ + __ret = __ret2 == -1 ? -1 : __ret; \ + if (__ret != -1) \ + __set_errno (__saved_errno); \ + } \ + __ret; \ +}) + +# endif /* !defined DO_FSCTYPE_XLATE || IS_IN_rtld == 1 */ + +#define _NL_FSCTYPE_XLATE1(fn, file, args...) \ + __NL_FSCTYPE_XLATE1 (1, 0, DEFERRED, fn, file , ##args) +#define _NL_FSCTYPE_XLATE2(fn, ofile, nfile, args...) \ + __NL_FSCTYPE_XLATE2 (1, 0, DEFERRED, fn, ofile, nfile , ##args) +#define _NL_FSCTYPE_XLATE1_ASYNC(fn, file, args...) \ + __NL_FSCTYPE_XLATE1 (1, 0, ASYNC, fn, file , ##args) +#define _NL_FSCTYPE_XLATE2_ASYNC(fn, ofile, nfile, args...) \ + __NL_FSCTYPE_XLATE2 (1, 0, ASYNC, fn, ofile, nfile , ##args) + +#endif /*_FSCTYPE_H*/ diff -Nru a/locale/langinfo.h b/locale/langinfo.h --- a/locale/langinfo.h Mon Mar 22 14:59:24 2004 +++ b/locale/langinfo.h Mon Mar 22 14:59:24 2004 @@ -562,6 +562,9 @@ _NL_IDENTIFICATION_CODESET, _NL_NUM_LC_IDENTIFICATION, + _NL_FSCTYPE_CODESET = _NL_ITEM (__LC_FSCTYPE, 0), + _NL_NUM_LC_FSCTYPE, + /* This marks the highest value used. */ _NL_NUM }; diff -Nru a/locale/lc-fsctype.c b/locale/lc-fsctype.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/locale/lc-fsctype.c Mon Mar 22 14:59:24 2004 @@ -0,0 +1,23 @@ +/* Define current locale data for LC_FSCTYPE category. + Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Tejun Heo , 2004. + + 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 "localeinfo.h" + +_NL_CURRENT_DEFINE (LC_FSCTYPE); diff -Nru a/locale/loadarchive.c b/locale/loadarchive.c --- a/locale/loadarchive.c Mon Mar 22 14:59:24 2004 +++ b/locale/loadarchive.c Mon Mar 22 14:59:24 2004 @@ -306,7 +306,7 @@ /* We already have the whole locale archive mapped in. */ assert (headmap.len == archive_stat.st_size); for (cnt = 0; cnt < __LC_LAST; ++cnt) - if (cnt != LC_ALL) + if (__LC_LOADABLE(cnt)) { if (locrec->record[cnt].offset + locrec->record[cnt].len > headmap.len) @@ -320,7 +320,7 @@ { /* Get the offsets of the data files and sort them. */ for (cnt = nranges = 0; cnt < __LC_LAST; ++cnt) - if (cnt != LC_ALL) + if (__LC_LOADABLE(cnt)) { ranges[nranges].from = locrec->record[cnt].offset; ranges[nranges].len = locrec->record[cnt].len; @@ -468,7 +468,7 @@ archloaded = lia; for (cnt = 0; cnt < __LC_LAST; ++cnt) - if (cnt != LC_ALL) + if (__LC_LOADABLE(cnt)) { lia->data[cnt] = _nl_intern_locale_data (cnt, results[cnt].addr, @@ -510,7 +510,7 @@ free (dead->name); for (category = 0; category < __LC_LAST; ++category) - if (category != LC_ALL) + if (__LC_LOADABLE(category)) { /* _nl_unload_locale just does this free for the archive case. */ if (dead->data[category]->private.cleanup) diff -Nru a/locale/locale.h b/locale/locale.h --- a/locale/locale.h Mon Mar 22 14:59:24 2004 +++ b/locale/locale.h Mon Mar 22 14:59:24 2004 @@ -46,7 +46,9 @@ #define LC_TELEPHONE __LC_TELEPHONE #define LC_MEASUREMENT __LC_MEASUREMENT #define LC_IDENTIFICATION __LC_IDENTIFICATION - +#ifdef __USE_GNU +#define LC_FSCTYPE __LC_FSCTYPE +#endif /* Structure giving information about numeric and monetary notation. */ struct lconv @@ -170,6 +172,7 @@ # define LC_TELEPHONE_MASK (1 << __LC_TELEPHONE) # define LC_MEASUREMENT_MASK (1 << __LC_MEASUREMENT) # define LC_IDENTIFICATION_MASK (1 << __LC_IDENTIFICATION) +# define LC_FSCTYPE_MASK (1 << __LC_FSCTYPE) # define LC_ALL_MASK (LC_CTYPE_MASK \ | LC_NUMERIC_MASK \ | LC_TIME_MASK \ @@ -182,6 +185,7 @@ | LC_TELEPHONE_MASK \ | LC_MEASUREMENT_MASK \ | LC_IDENTIFICATION_MASK \ + | LC_FSCTYPE_MASK \ ) /* Return a duplicate of the set of locale in DATASET. All usage diff -Nru a/locale/newlocale.c b/locale/newlocale.c --- a/locale/newlocale.c Mon Mar 22 14:59:24 2004 +++ b/locale/newlocale.c Mon Mar 22 14:59:24 2004 @@ -25,6 +25,7 @@ #include #include "localeinfo.h" +#include "fsctype.h" /* Use this when we come along an error. */ @@ -259,6 +260,8 @@ ctypes[_NL_ITEM_INDEX (_NL_CTYPE_TOLOWER)].string + 128; result_ptr->__ctype_toupper = (const int *) ctypes[_NL_ITEM_INDEX (_NL_CTYPE_TOUPPER)].string + 128; + + _nl_fsctype_init_conv(result_ptr); } return result_ptr; diff -Nru a/locale/programs/config.h b/locale/programs/config.h --- a/locale/programs/config.h Mon Mar 22 14:59:24 2004 +++ b/locale/programs/config.h Mon Mar 22 14:59:24 2004 @@ -39,7 +39,7 @@ #endif /* This must be one higer than the last used LC_xxx category value. */ -#define __LC_LAST 13 +#define __LC_LAST 14 #include_next #endif diff -Nru a/locale/programs/ld-fsctype.c b/locale/programs/ld-fsctype.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/locale/programs/ld-fsctype.c Mon Mar 22 14:59:24 2004 @@ -0,0 +1,21 @@ +/* Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Tejun Heo , 2004. + + 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. */ + +/* Being a pseudo locale, LC_FSCTYPE doesn't require read/output + functions. This file exists only to satisfy Make dependency. */ diff -Nru a/locale/programs/ld-identification.c b/locale/programs/ld-identification.c --- a/locale/programs/ld-identification.c Mon Mar 22 14:59:24 2004 +++ b/locale/programs/ld-identification.c Mon Mar 22 14:59:24 2004 @@ -69,7 +69,8 @@ [LC_ADDRESS] = "LC_ADDRESS", [LC_TELEPHONE] = "LC_TELEPHONE", [LC_MEASUREMENT] = "LC_MEASUREMENT", - [LC_IDENTIFICATION] = "LC_IDENTIFICATION" + [LC_IDENTIFICATION] = "LC_IDENTIFICATION", + [LC_FSCTYPE] = "LC_FSCTYPE" }; @@ -85,6 +86,8 @@ locale->categories[LC_IDENTIFICATION].identification->category[LC_ALL] = ""; + locale->categories[LC_IDENTIFICATION].identification->category[LC_FSCTYPE] = + ""; } if (lr != NULL) @@ -165,7 +168,7 @@ TEST_ELEM (date); for (num = 0; num < __LC_LAST; ++num) - if (num != LC_ALL && identification->category[num] == NULL) + if (__LC_LOADABLE(num) && identification->category[num] == NULL) { if (verbose && ! nothing) WITH_CUR_LOCALE (error (0, 0, _("\ @@ -184,7 +187,7 @@ struct locale_identification_t *identification = locale->categories[LC_IDENTIFICATION].identification; struct iovec iov[2 + _NL_ITEM_INDEX (_NL_NUM_LC_IDENTIFICATION) - + (__LC_LAST - 2)]; + + (__LC_LAST - 3)]; struct locale_file data; uint32_t idx[_NL_ITEM_INDEX (_NL_NUM_LC_IDENTIFICATION)]; size_t cnt = 0; @@ -275,7 +278,7 @@ last_idx = cnt - 1; idx[last_idx] = idx[cnt - 2]; for (num = 0; num < __LC_LAST; ++num) - if (num != LC_ALL) + if (__LC_LOADABLE(num)) { iov[cnt].iov_base = (void *) identification->category[num]; iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1; @@ -289,7 +292,7 @@ ++cnt; assert (cnt == (2 + _NL_ITEM_INDEX (_NL_NUM_LC_IDENTIFICATION) - + (__LC_LAST - 2))); + + (__LC_LAST - 3))); write_locale_data (output_path, LC_IDENTIFICATION, "LC_IDENTIFICATION", cnt, iov); diff -Nru a/locale/programs/locarchive.c b/locale/programs/locarchive.c --- a/locale/programs/locarchive.c Mon Mar 22 14:59:24 2004 +++ b/locale/programs/locarchive.c Mon Mar 22 14:59:24 2004 @@ -192,7 +192,7 @@ int cnt; for (cnt = 0; cnt < __LC_LAST; ++cnt) - if (cnt != LC_ALL) + if (__LC_LOADABLE(cnt)) { if (la->record[cnt].offset < start_a) start_a = la->record[cnt].offset; @@ -203,7 +203,7 @@ assert (end_a != 0); for (cnt = 0; cnt < __LC_LAST; ++cnt) - if (cnt != LC_ALL) + if (__LC_LOADABLE(cnt)) { if (lb->record[cnt].offset < start_b) start_b = lb->record[cnt].offset; @@ -363,7 +363,7 @@ struct locrecent *oldlocrec = oldlocrecarray[cnt].locrec; for (idx = 0; idx < __LC_LAST; ++idx) - if (idx != LC_ALL) + if (__LC_LOADABLE(idx)) { old_data[idx].size = oldlocrec->record[idx].len; old_data[idx].addr @@ -683,10 +683,11 @@ memset (file_offsets, 0, sizeof (file_offsets)); - size_order[LC_ALL] = NULL; for (cnt = 0; cnt < __LC_LAST; ++cnt) - if (cnt != LC_ALL) + if (__LC_LOADABLE(cnt)) size_order[cnt] = &data[cnt]; + else + size_order[cnt] = NULL; /* Sort the array in ascending order of data size. */ qsort (size_order, __LC_LAST, sizeof size_order[0], cmpcategorysize); @@ -728,7 +729,9 @@ /* For each locale category data set determine whether the same data is already somewhere in the archive. */ for (cnt = 0; cnt < __LC_LAST; ++cnt) - if (small_mask == 0 ? cnt != LC_ALL : !(small_mask & (1 << cnt))) + if (small_mask == 0 + ? __LC_LOADABLE(cnt) + : (cnt == LC_ALL || __LC_LOADABLE(cnt)) && !(small_mask & (1 << cnt))) { ++num_new_offsets; @@ -775,7 +778,9 @@ /* Add the locale data which is not yet in the archive. */ for (cnt = 0, lastoffset = 0; cnt < __LC_LAST; ++cnt) - if ((small_mask == 0 ? cnt != LC_ALL : !(small_mask & (1 << cnt))) + if ((small_mask == 0 + ? __LC_LOADABLE(cnt) + : (cnt == LC_ALL || __LC_LOADABLE(cnt)) && !(small_mask & (1 << cnt))) && file_offsets[cnt] == 0) { /* The data for this section is not yet available in the @@ -1151,7 +1156,7 @@ while ((d = readdir64 (dirp)) != NULL) { for (cnt = 0; cnt < __LC_LAST; ++cnt) - if (cnt != LC_ALL) + if (__LC_LOADABLE(cnt)) if (strcmp (d->d_name, locnames[cnt]) == 0) { unsigned char d_type; @@ -1222,7 +1227,7 @@ /* Add the files to the archive. To do this we first compute sizes and the MD5 sums of all the files. */ for (cnt = 0; cnt < __LC_LAST; ++cnt) - if (cnt != LC_ALL) + if (__LC_LOADABLE(cnt)) { char fullname[fnamelen + 2 * strlen (locnames[cnt]) + 7]; int fd; @@ -1275,7 +1280,7 @@ if (cnt != __LC_LAST) { while (cnt-- > 0) - if (cnt != LC_ALL) + if (__LC_LOADABLE(cnt)) munmap (data[cnt].addr, data[cnt].size); error (0, 0, _("cannot read all files in \"%s\": ignored"), fname); @@ -1286,7 +1291,7 @@ result |= add_locale_to_archive (&ah, basename (fname), data, replace); for (cnt = 0; cnt < __LC_LAST; ++cnt) - if (cnt != LC_ALL) + if (__LC_LOADABLE(cnt)) munmap (data[cnt].addr, data[cnt].size); } @@ -1459,13 +1464,13 @@ + names[cnt].locrec_offset); for (idx = 0; idx < __LC_LAST; ++idx) if (locrec->record[LC_ALL].offset != 0 - ? (idx == LC_ALL - || (locrec->record[idx].offset - < locrec->record[LC_ALL].offset) - || (locrec->record[idx].offset + locrec->record[idx].len - > (locrec->record[LC_ALL].offset - + locrec->record[LC_ALL].len))) - : idx != LC_ALL) + ? (idx == LC_ALL || (__LC_LOADABLE(idx) + && ((locrec->record[idx].offset + < locrec->record[LC_ALL].offset) + || (locrec->record[idx].offset + locrec->record[idx].len + > (locrec->record[LC_ALL].offset + + locrec->record[LC_ALL].len))))) + : __LC_LOADABLE(idx)) { struct dataent *data, dataent; @@ -1487,7 +1492,7 @@ locrec = (struct locrecent *) ((char *) ah.addr + names[cnt].locrec_offset); for (idx = 0; idx < __LC_LAST; ++idx) - if (idx != LC_ALL) + if (__LC_LOADABLE(idx)) { struct dataent *data, dataent; diff -Nru a/locale/setlocale.c b/locale/setlocale.c --- a/locale/setlocale.c Mon Mar 22 14:59:24 2004 +++ b/locale/setlocale.c Mon Mar 22 14:59:24 2004 @@ -26,6 +26,7 @@ #include #include "localeinfo.h" +#include "fsctype.h" #ifdef NL_CURRENT_INDIRECT @@ -214,6 +215,7 @@ size_t locale_path_len; const char *locpath_var; char *composite; + int need_update_conv = 0; /* Sanity check for CATEGORY argument. */ if (__builtin_expect (category, 0) < 0 @@ -322,6 +324,9 @@ break; } + if (category == LC_CTYPE || category == LC_FSCTYPE) + need_update_conv = 1; + /* We must not simply free a global locale since we have no control over the usage. So we mark it as un-deletable. And yes, the 'if' is needed, the data @@ -358,6 +363,9 @@ } setname (LC_ALL, composite); + if (need_update_conv) + _nl_fsctype_update_conv (&_nl_global_locale); + /* We successfully loaded a new locale. Let the message catalog functions know about this. */ ++_nl_msg_cat_cntr; @@ -392,6 +400,9 @@ if (newdata == NULL) goto abort_single; + if (category == LC_CTYPE || category == LC_FSCTYPE) + need_update_conv = 1; + /* We must not simply free a global locale since we have no control over the usage. So we mark it as un-deletable. @@ -428,6 +439,9 @@ setname (category, newname[0]); setname (LC_ALL, composite); + if (need_update_conv) + _nl_fsctype_update_conv (&_nl_global_locale); + /* We successfully loaded a new locale. Let the message catalog functions know about this. */ ++_nl_msg_cat_cntr; @@ -496,6 +510,10 @@ #endif setname (LC_ALL, _nl_C_name); + + /* Clean up fsctype locale/conv caches */ + _nl_fsctype_destroy_conv_cache (&_nl_global_locale); + _nl_fsctype_destroy_locale_cache (); /* This frees the data structures associated with the locale archive. The locales from the archive are not in the file list, so we have diff -Nru a/locale/xlocale.h b/locale/xlocale.h --- a/locale/xlocale.h Mon Mar 22 14:59:24 2004 +++ b/locale/xlocale.h Mon Mar 22 14:59:24 2004 @@ -28,15 +28,22 @@ typedef struct __locale_struct { /* Note: LC_ALL is not a valid index into this array. */ - struct locale_data *__locales[13]; /* 13 = __LC_LAST. */ + struct locale_data *__locales[14]; /* 14 = __LC_LAST. */ /* To increase the speed of this solution we add some special members. */ const unsigned short int *__ctype_b; const int *__ctype_tolower; const int *__ctype_toupper; + /* LC_FSCTYPE related. */ + const char *__fsctype_codeset; + const char *__fsctype_fs_codeset; + unsigned __fsctype_conv_cache_gen; + unsigned __fsctype_conv_cache_cnts[2]; + void *__fsctype_conv_cache_heads[2]; + /* Note: LC_ALL is not a valid index into this array. */ - const char *__names[13]; + const char *__names[14]; } *__locale_t; #endif /* xlocale.h */ diff -Nru a/sysdeps/generic/sysdep-cancel-xlate.h b/sysdeps/generic/sysdep-cancel-xlate.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/sysdeps/generic/sysdep-cancel-xlate.h Mon Mar 22 14:59:24 2004 @@ -0,0 +1,21 @@ +/* Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Tejun Heo , 2004. + + 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 +#include diff -Nru a/sysdeps/generic/sysdep-cancel.h b/sysdeps/generic/sysdep-cancel.h --- a/sysdeps/generic/sysdep-cancel.h Mon Mar 22 14:59:24 2004 +++ b/sysdeps/generic/sysdep-cancel.h Mon Mar 22 14:59:24 2004 @@ -4,4 +4,7 @@ #define SINGLE_THREAD_P (1) #define LIBC_CANCEL_ASYNC() 0 /* Just a dummy value. */ #define LIBC_CANCEL_RESET(val) ((void)(val)) /* Nothing, but evaluate it. */ +#define LIBC_CANCEL_DEFERRED() 0 /* Just a dummy value. */ +#define LIBC_CANCEL_DEFERRED_RESET(val) \ + ((void)(val)) /* Nothing, but evaluate it. */ #define LIBC_CANCEL_HANDLED() /* Nothing. */ diff -Nru a/sysdeps/generic/sysdep-xlate.h b/sysdeps/generic/sysdep-xlate.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/sysdeps/generic/sysdep-xlate.h Mon Mar 22 14:59:24 2004 @@ -0,0 +1,26 @@ +/* Copyright (C) 1998-2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Tejun Heo , 2004. + + 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 + +#undef PSEUDO +#define PSEUDO_XLATE __PSEUDO_XLATE + +#undef CHECK_XLATE +#define CHECK_XLATE diff -Nru a/sysdeps/unix/Dist b/sysdeps/unix/Dist --- a/sysdeps/unix/Dist Mon Mar 22 14:59:24 2004 +++ b/sysdeps/unix/Dist Mon Mar 22 14:59:24 2004 @@ -5,10 +5,16 @@ snarf-ioctls make_errlist.c mk-local_lim.c -s-proto.S make-syscalls.sh i386/dl-brk.S mips/dl-brk.S sparc/dl-brk.S +s-proto.S s-proto-bp.S +s-proto-xlate.S s-proto-cancel.S +s-proto-cancel-xlate.S +c-proto-doxlate.c +c-proto-cancel-doxlate.c +sysdep-doxlate.h +sysdep-cancel-doxlate.h diff -Nru a/sysdeps/unix/Makefile b/sysdeps/unix/Makefile --- a/sysdeps/unix/Makefile Mon Mar 22 14:59:24 2004 +++ b/sysdeps/unix/Makefile Mon Mar 22 14:59:24 2004 @@ -323,14 +323,17 @@ # This is the end of the pipeline for compiling the syscall stubs. # The stdin in assembler with cpp using sysdep.h macros. # Be sure to disable debugging info since it would all just say "". -compile-syscall = $(filter-out -g%,$(COMPILE.S)) -x assembler-with-cpp -o $@ - +compile-syscall = $(filter-out -g%,$(COMPILE.S)) -x assembler-with-cpp +compile-c-syscall = $(filter-out -g%,$(COMPILE.c)) -x c +reloc-link-syscall = $(LINK.o) -nostdlib -nostartfiles -r ifndef avoid-generated $(common-objpfx)sysd-syscalls: $(..)sysdeps/unix/make-syscalls.sh \ $(wildcard $(+sysdep_dirs:%=%/syscalls.list)) for dir in $(+sysdep_dirs); do \ test -f $$dir/syscalls.list && \ - { $(SHELL) $(dir $<)$(notdir $<) $$dir || exit 1; }; \ + { $(SHELL) $(dir $<)$(notdir $<) $(build-fsctype-xlate) $$dir \ + || exit 1; }; \ test $$dir = $(..)sysdeps/unix && break; \ done > address@hidden mv -f address@hidden $@ @@ -346,6 +349,10 @@ -include $(common-objpfx)s-proto.d -include $(common-objpfx)s-proto-bp.d -include $(common-objpfx)s-proto-cancel.d +-include $(common-objpfx)s-proto-xlate.d +-include $(common-objpfx)s-proto-cancel-xlate.d +-include $(common-objpfx)c-proto-doxlate.d +-include $(common-objpfx)c-proto-cancel-doxlate.d endif endif @@ -353,7 +360,12 @@ $(wildcard $(+sysdep_dirs:%=%/syscalls.list)) $(+make-deps) -common-generated += s-proto.d s-proto-bp.d s-proto-cancel.d +$(common-objpfx)c-%.d: $(..)sysdeps/unix/c-%.c \ + $(wildcard $(+sysdep_dirs:%=%/syscalls.list)) + $(+make-deps) + +common-generated += s-proto.d s-proto-bp.d s-proto-cancel.d s-proto-xlate.d \ + s-proto-cancel-xlate.d c-proto-doxlate.d c-proto-cancel-doxlate.d postclean-generated += sysd-syscalls endif diff -Nru a/sysdeps/unix/c-proto-cancel-doxlate.c b/sysdeps/unix/c-proto-cancel-doxlate.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/sysdeps/unix/c-proto-cancel-doxlate.c Mon Mar 22 14:59:24 2004 @@ -0,0 +1,5 @@ +/* This file exists just to have its dependencies determined. + Those dependencies are then used for the objects which do actual + translation of cancellable system calls. */ + +#include diff -Nru a/sysdeps/unix/c-proto-doxlate.c b/sysdeps/unix/c-proto-doxlate.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/sysdeps/unix/c-proto-doxlate.c Mon Mar 22 14:59:24 2004 @@ -0,0 +1,5 @@ +/* This file exists just to have its dependencies determined. + Those dependencies are then used for the objects which do actual + translation of non-cancellable system calls. */ + +#include diff -Nru a/sysdeps/unix/common/syscalls.list b/sysdeps/unix/common/syscalls.list --- a/sysdeps/unix/common/syscalls.list Mon Mar 22 14:59:24 2004 +++ b/sysdeps/unix/common/syscalls.list Mon Mar 22 14:59:24 2004 @@ -11,6 +11,6 @@ setregid - setregid i:ii __setregid setregid setreuid - setreuid i:ii __setreuid setreuid sigaction - sigaction i:ipp __sigaction sigaction -sys_lstat lxstat lstat i:sp __syscall_lstat -truncate - truncate i:si truncate +sys_lstat lxstat lstat xi:sp __syscall_lstat +truncate - truncate xi:si truncate vhangup - vhangup i:i vhangup diff -Nru a/sysdeps/unix/make-syscalls.sh b/sysdeps/unix/make-syscalls.sh --- a/sysdeps/unix/make-syscalls.sh Mon Mar 22 14:59:24 2004 +++ b/sysdeps/unix/make-syscalls.sh Mon Mar 22 14:59:24 2004 @@ -30,6 +30,7 @@ ############################################################################## +build_fsctype_xlate=$1; shift thisdir=$1; shift echo '' @@ -91,6 +92,29 @@ V*) noerrno=_ERRVAL; args=`echo $args | sed 's/V:\?//'`;; esac + xlate=no + case $args in + x*) xlate=yes; rule=1; args=`echo $args | sed 's/x:\?//'`;; + y*) xlate=yes; rule=2; args=`echo $args | sed 's/y:\?//'`;; + esac + + if [ x$build_fsctype_xlate = xyes ]; then + if [ $xlate = yes ]; then + if [ x$noerrno != x ]; then + echo >&2 "$0: xlate turned on for noerrno syscall ($strong $weak)" + exit 2 + fi + fi + else + xlate=no + fi + + case "$strong" in + __*) fn_prefix=${strong};; + _*) fn_prefix=_${strong};; + *) fn_prefix=__${strong};; + esac + # Derive the number of arguments from the argument signature case $args in [0-9]) nargs=$args;; @@ -126,54 +150,46 @@ x-*) echo "ifeq (,\$(filter $file,\$(unix-syscalls)))" - case $weak in - address@hidden) - # The versioned symbols are only in the shared library. - echo "ifneq (,\$(filter .os,\$(object-suffixes)))" - ;; - esac - # Accumulate the list of syscall files for this directory. - echo "unix-syscalls += $file" - test x$caller = x- || echo "unix-extra-syscalls += $file" - - # Emit a compilation rule for this syscall. - case $weak in - address@hidden) - # The versioned symbols are only in the shared library. - echo "\ -shared-only-routines += $file -\$(objpfx)${file}.os: \\" - ;; - *) - echo "\ -\$(foreach o,\$(object-suffixes),\$(objpfx)$file\$o) \ -\$(foreach o,\$(object-suffixes),\$(objpfx)ptw-$file\$o) \ -\$(objpfx)rtld-$file.os: \\" - ;; - esac + # Prepare to emit a compilation rule for this syscall. + shared_target="\$(objpfx)${file}.os" + normal_target="\$(foreach o,\$(object-suffixes),\$(objpfx)${file}\$o)" + ptw_target="\$(foreach o,\$(object-suffixes),\$(objpfx)ptw-${file}\$o)" + rtld_target="\$(objpfx)rtld-${file}.os" - echo " \$(common-objpfx)s-proto$cancellable.d" - case x"$callnum" in - x_) - echo "\ + dummy_build_head="\ + \$(common-objpfx)s-proto$cancellable.d (echo '/* Dummy module requested by syscalls.list */'; \\" - ;; - x*) - echo "\ + + normal_build_head="\ + \$(common-objpfx)s-proto$cancellable.d \$(make-target-directory) - (echo '#include '; \\ - echo 'PSEUDO$noerrno ($strong, $syscall, $nargs)'; \\ + (echo '#include '; \\ + echo '__PSEUDO$noerrno ($strong, $fn_prefix, $syscall, $nargs)'; \\ echo ' ret$noerrno'; \\ - echo 'PSEUDO_END$noerrno($strong)'; \\ + echo 'PSEUDO_END$noerrno ($strong)'; \\ + echo 'libc_hidden_def ($strong)'; \\" + if [ x${cancellable} != x ]; then + normal_build_head=${normal_build_head}" + echo 'libc_hidden_def (${fn_prefix}_nocancel)'; \\" + fi + + xlate_build_head="\ + \$(common-objpfx)s-proto${cancellable}-xlate.d \\ + \$(common-objpfx)c-proto${cancellable}-doxlate.d + \$(make-target-directory) + (echo '#include '; \\ + echo '__PSEUDO ($strong, $fn_prefix, $syscall, $nargs)'; \\ + echo ' ret'; \\ + echo 'PSEUDO_END ($strong)'; \\ echo 'libc_hidden_def ($strong)'; \\" - ;; - esac # Append any weak aliases or versions defined for this syscall function. # A shortcoming in the current gas is that it will only allow one # version-alias per symbol. So we create new strong aliases as needed. + vcount="" + aliases="" for name in $weak; do case $name in @@ -186,9 +202,11 @@ else source="${strong}_${vcount}" vcount=`expr $vcount + 1` - echo " echo 'strong_alias ($strong, $source)'; \\" + aliases=${aliases}" + echo 'strong_alias ($strong, $source)'; \\" fi - echo " echo 'default_symbol_version($source, $base, $ver)'; \\" + aliases=${aliases}" + echo 'default_symbol_version($source, $base, $ver)'; \\" ;; address@hidden) base=`echo $name | sed 's/@.*//'` @@ -199,30 +217,78 @@ else source="${strong}_${vcount}" vcount=`expr $vcount + 1` - echo " echo 'strong_alias ($strong, $source)'; \\" + aliases=${aliases}" + echo 'strong_alias ($strong, $source)'; \\" fi - echo " echo 'symbol_version($source, $base, $ver)'; \\" + aliases=${aliases}" + echo 'symbol_version($source, $base, $ver)'; \\" ;; !*) name=`echo $name | sed 's/.//'` - echo " echo 'strong_alias ($strong, $name)'; \\" - echo " echo 'libc_hidden_def ($name)'; \\" + aliases=${aliases}" + echo 'strong_alias ($strong, $name)'; \\ + echo 'libc_hidden_def ($name)'; \\" ;; *) - echo " echo 'weak_alias ($strong, $name)'; \\" - echo " echo 'libc_hidden_weak ($name)'; \\" + aliases=${aliases}" + echo 'weak_alias ($strong, $name)'; \\ + echo 'libc_hidden_weak ($name)'; \\" ;; esac done - # And finally, pipe this all into the compiler. - echo ' ) | $(compile-syscall)' + normal_build_tail=" + ) | \$(compile-syscall) -o \$@ -" + dummy_build_tail="$normal_build_tail" + xlate_build_tail=" + ) | \$(compile-syscall) -o address@hidden - + (echo '#include '; \\ + echo 'PSEUDO_DOXLATE ($rule, $fn_prefix, $syscall, $nargs)';\\ + ) | \$(compile-c-syscall) -o address@hidden - + \$(reloc-link-syscall) -o \$@ address@hidden address@hidden + rm -f address@hidden address@hidden" + + dummy_build="${dummy_build_head}${aliases}${dummy_build_tail}" + normal_build="${normal_build_head}${aliases}${normal_build_tail}" + xlate_build="${xlate_build_head}${aliases}${xlate_build_tail}" + + # Ok, now we have all needed strings, emit the rules + echo "unix-syscalls += $file" + test x$caller = x- || echo "unix-extra-syscalls += $file" case $weak in - address@hidden) - # The versioned symbols are only in the shared library. - echo endif - ;; + address@hidden) + # The versioned symbols are only in the shared library. + echo "ifneq (,\$(filter .os,\$(object-suffixes)))" + echo "shared-only-routines += $file" + echo "${shared_target}: \\" + case "$callnum:$xlate" in + _:*) echo "$dummy_build" ;; + *:no) echo "$normal_build" ;; + *:yes) echo "$xlate_build" ;; + esac + echo "endif" + ;; + *) + if [ $xlate = no ]; then + echo "${normal_target} ${ptw_target} ${rtld_target}: \\" + case "$callnum" in + _) echo "$dummy_build" ;; + *) echo "$normal_build" ;; + esac + else + echo "${normal_target} ${ptw_target}: \\" + case "$callnum" in + _) echo "$dummy_build" ;; + *) echo "$xlate_build" ;; + esac + echo "${rtld_target}: \\" + case "$callnum" in + _) echo "$dummy_build" ;; + *) echo "$normal_build" ;; + esac + fi + ;; esac echo endif diff -Nru a/sysdeps/unix/open.c b/sysdeps/unix/open.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/sysdeps/unix/open.c Mon Mar 22 14:59:24 2004 @@ -0,0 +1,81 @@ +/* Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Tejun Heo , 2004. + + 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 +#include +#include +#include +#include + +extern int __syscall_open (const char *file, int oflag, int mode) + attribute_hidden; + +/* Open FILE with access OFLAG. If OFLAG includes O_CREAT, + a third argument is the file protection. */ + +int +__libc_open (const char *file, int oflag, ...) +{ + int mode = 0; + + if (oflag & O_CREAT) + { + va_list arg; + va_start (arg, oflag); + mode = va_arg (arg, int); + va_end (arg); + } + + return __NL_FSCTYPE_XLATE1 (1, oflag & O_CREAT, ASYNC, __syscall_open, + CHECK_STRING (file), oflag, mode); +} +libc_hidden_def (__libc_open) + +weak_alias (__libc_open, __open) +libc_hidden_weak (__open) +weak_alias (__libc_open, open) + +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt + +extern int __syscall_open_nocancel (const char *file, int oflag, int mode) + attribute_hidden; + +extern int __open_nocancel (const char *file, int oflag, ...) + attribute_hidden; + +int +attribute_hidden +__open_nocancel (const char *file, int oflag, ...) +{ + int mode = 0; + + if (oflag & O_CREAT) + { + va_list arg; + va_start (arg, oflag); + mode = va_arg (arg, int); + va_end (arg); + } + + return __NL_FSCTYPE_XLATE1 (1, oflag & O_CREAT, DEFERRED, + __syscall_open_nocancel, + CHECK_STRING (file), oflag, mode); +} + +#endif diff -Nru a/sysdeps/unix/readlink.c b/sysdeps/unix/readlink.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/sysdeps/unix/readlink.c Mon Mar 22 14:59:24 2004 @@ -0,0 +1,83 @@ +/* Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Tejun Heo , 2004. + + 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 +#include +#include +#include +#include + +extern int __syscall_readlink (const char *path, char *buf, size_t len) + attribute_hidden; + +int +__readlink (const char *path, char *buf, size_t len) +{ +#ifdef FSCTYPE_XLATE_ENABLED + int single, oldtype = 0; + struct fsctype_conv *conv; + + + if (!(single = SINGLE_THREAD_P)) + oldtype = LIBC_CANCEL_DEFERRED (); + switch (_nl_fsctype_get_conv (0, &conv)) + { + case -1: + return -1; + case 0: + if (!single) + LIBC_CANCEL_DEFERRED_RESET (oldtype); + break; + case 1: { + int ret; + char *ip, *op; + size_t ilen, olen; + int saved_errno; + + ret = __NL_FSCTYPE_XLATE1 (0, 0, NONE, __syscall_readlink, + CHECK_STRING (path), conv->bufs[0], + sizeof (conv->bufs[0])); + if (ret < 0) + goto out_free; + + ip = conv->bufs[0]; + ilen = ret; + op = CHECK_N (buf, len); + olen = len; + + saved_errno = errno; + if ((ret = _nl_fsctype_xlate (conv, &ip, &ilen, &op, &olen)) < 0) + { + if (errno != E2BIG) + goto out_free; + __set_errno (saved_errno); + } + ret = len - olen; + + out_free: + _nl_fsctype_free_conv (conv); + if (!single) + LIBC_CANCEL_DEFERRED_RESET (oldtype); + return ret; + } + } +#endif + return __syscall_readlink (CHECK_STRING (path), CHECK_N (buf, len), len); +} +weak_alias (__readlink, readlink) diff -Nru a/sysdeps/unix/s-proto-cancel-xlate.S b/sysdeps/unix/s-proto-cancel-xlate.S --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/sysdeps/unix/s-proto-cancel-xlate.S Mon Mar 22 14:59:24 2004 @@ -0,0 +1,5 @@ +/* This file exists just to have its dependencies determined. + Those dependencies are then used for the objects of the cancellable + translating system calls. */ + +#include diff -Nru a/sysdeps/unix/s-proto-xlate.S b/sysdeps/unix/s-proto-xlate.S --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/sysdeps/unix/s-proto-xlate.S Mon Mar 22 14:59:24 2004 @@ -0,0 +1,5 @@ +/* This file exists just to have its dependencies determined. + Those dependencies are then used for the non-cancellable + translating system call objects. */ + +#include diff -Nru a/sysdeps/unix/symlink.c b/sysdeps/unix/symlink.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/sysdeps/unix/symlink.c Mon Mar 22 14:59:24 2004 @@ -0,0 +1,33 @@ +/* Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Tejun Heo , 2004. + + 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 +#include +#include +#include +#include + +extern int __syscall_symlink (const char *from, const char *to) + attribute_hidden; + +int __symlink (const char *from, const char *to) +{ + return __NL_FSCTYPE_XLATE2 (1, 1, DEFERRED, __syscall_symlink, from, to); +} +weak_alias (__symlink, symlink) diff -Nru a/sysdeps/unix/syscalls.list b/sysdeps/unix/syscalls.list --- a/sysdeps/unix/syscalls.list Mon Mar 22 14:59:24 2004 +++ b/sysdeps/unix/syscalls.list Mon Mar 22 14:59:24 2004 @@ -1,10 +1,10 @@ # File name Caller Syscall name Args Strong name Weak names -access - access i:si __access access +access - access xi:si __access access acct - acct i:S acct -chdir - chdir i:s __chdir chdir -chmod - chmod i:si __chmod chmod -chown - chown i:sii __chown __chown_internal chown +chdir - chdir xi:s __chdir chdir +chmod - chmod xi:si __chmod chmod +chown - chown xi:sii __chown __chown_internal chown chroot - chroot i:s chroot close - close Ci:i __libc_close __close close dup - dup i:i __dup dup @@ -23,18 +23,18 @@ getuid - getuid Ei: __getuid getuid ioctl - ioctl i:iiI __ioctl ioctl kill - kill i:ii __kill kill -link - link i:ss __link link +link - link yi:ss __link link lseek - lseek i:iii __libc_lseek __lseek lseek -mkdir - mkdir i:si __mkdir mkdir -open - open Ci:siv __libc_open __open open +mkdir - mkdir xi:si __mkdir mkdir +sys_open open open Ci:siv __syscall_open profil - profil i:piii __profil profil ptrace - ptrace i:iiii ptrace read - read Ci:ibn __libc_read __read read -readlink - readlink i:spi __readlink readlink +sys_readlink readlink readlink i:spi __syscall_readlink readv - readv Ci:ipi __readv readv reboot - reboot i:i reboot -rename - rename i:ss rename -rmdir - rmdir i:s __rmdir rmdir +rename - rename yi:ss rename +rmdir - rmdir xi:s __rmdir rmdir select - select Ci:iPPPP __select __libc_select select setdomain - setdomainname i:si setdomainname setegid - setegid i:i __setegid setegid @@ -52,14 +52,14 @@ statfs - statfs i:sp __statfs statfs swapoff - swapoff i:s swapoff swapon - swapon i:s swapon -symlink - symlink i:ss __symlink symlink +sys_symlink symlink symlink i:ss __syscall_symlink sync - sync i: sync sys_fstat fxstat fstat i:ip __syscall_fstat -sys_mknod xmknod mknod i:sii __syscall_mknod -sys_stat xstat stat i:sp __syscall_stat +sys_mknod xmknod mknod xi:sii __syscall_mknod +sys_stat xstat stat xi:sp __syscall_stat umask - umask Ei:i __umask umask uname - uname i:p __uname uname -unlink - unlink i:s __unlink unlink -utimes - utimes i:sp __utimes utimes +unlink - unlink xi:s __unlink unlink +utimes - utimes xi:sp __utimes utimes write - write Ci:ibn __libc_write __write write writev - writev Ci:ipi __writev writev diff -Nru a/sysdeps/unix/sysdep-cancel-doxlate.h b/sysdeps/unix/sysdep-cancel-doxlate.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/sysdeps/unix/sysdep-cancel-doxlate.h Mon Mar 22 14:59:24 2004 @@ -0,0 +1,28 @@ +/* Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Tejun Heo , 2004. + + 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. */ + +#ifndef _SYSDEP_CANCEL_DOXLATE_H +#define _SYSDEP_CANCEL_DOXLATE_H + +#include + +#undef PSEUDO_CANCEL +#define PSEUDO_CANCEL _ASYNC + +#endif /*_SYSDEP_CANCEL_DOXLATE_H*/ diff -Nru a/sysdeps/unix/sysdep-doxlate.h b/sysdeps/unix/sysdep-doxlate.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/sysdeps/unix/sysdep-doxlate.h Mon Mar 22 14:59:24 2004 @@ -0,0 +1,58 @@ +/* Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Tejun Heo , 2004. + + 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. */ + +#ifndef _SYSDEP_DOXLATE_H +#define _SYSDEP_DOXLATE_H + +#include + +#define PSEUDO_XLATE1_ARGDEFS_1 const char *file +#define PSEUDO_XLATE1_ARGDEFS_2 const char *file,void *a2 +#define PSEUDO_XLATE1_ARGDEFS_3 const char *file,void *a2,void *a3 +#define PSEUDO_XLATE1_ARGDEFS_4 const char *file,void *a2,void *a3,void *a4 +#define PSEUDO_XLATE1_ARGDEFS_5 const char *file,void *a2,void *a3,void *a4,void *a5 +#define PSEUDO_XLATE2_ARGDEFS_2 const char *ofile,const char *nfile + +#define PSEUDO_XLATE1_ARGS_1 file +#define PSEUDO_XLATE1_ARGS_2 file,a2 +#define PSEUDO_XLATE1_ARGS_3 file,a2,a3 +#define PSEUDO_XLATE1_ARGS_4 file,a2,a3,a4 +#define PSEUDO_XLATE1_ARGS_5 file,a2,a3,a4,a5 +#define PSEUDO_XLATE2_ARGS_2 ofile,nfile + +#define PSEUDO_CALL_XLATE1(rule, cancel, fn, args...) \ + _NL_FSCTYPE_XLATE##rule##cancel (fn, args) +#define PSEUDO_CALL_XLATE(rule, cancel, fn, args...) \ + PSEUDO_CALL_XLATE1 (rule, cancel, fn, args) + +#undef PSEUDO_CANCEL +#define PSEUDO_CANCEL + +#define PSEUDO_DOXLATE(rule, prefix, syscall, nargs) \ +extern int prefix##_noxlate (PSEUDO_XLATE##rule##_ARGDEFS_##nargs) \ + attribute_hidden; \ +extern int prefix##_xlate (PSEUDO_XLATE##rule##_ARGDEFS_##nargs) \ + attribute_hidden; \ +int prefix##_xlate (PSEUDO_XLATE##rule##_ARGDEFS_##nargs) \ +{ \ + return PSEUDO_CALL_XLATE (rule, PSEUDO_CANCEL, prefix##_noxlate, \ + PSEUDO_XLATE##rule##_ARGS_##nargs); \ +} + +#endif /*_SYSDEP_DOXLATE_H*/ diff -Nru a/sysdeps/unix/sysv/linux/Dist b/sysdeps/unix/sysv/linux/Dist --- a/sysdeps/unix/sysv/linux/Dist Mon Mar 22 14:59:24 2004 +++ b/sysdeps/unix/sysv/linux/Dist Mon Mar 22 14:59:24 2004 @@ -80,5 +80,6 @@ xstatconv.c xstatconv.h getdents64.c +getdents-xlate.c umount.S umount2.S diff -Nru a/sysdeps/unix/sysv/linux/getcwd.c b/sysdeps/unix/sysv/linux/getcwd.c --- a/sysdeps/unix/sysv/linux/getcwd.c Mon Mar 22 14:59:24 2004 +++ b/sysdeps/unix/sysv/linux/getcwd.c Mon Mar 22 14:59:24 2004 @@ -26,6 +26,7 @@ #include #include +#include #include #include "kernel-features.h" @@ -66,6 +67,55 @@ # endif #endif +#if defined __NR_getcwd || __LINUX_GETCWD_SYSCALL > 0 +static inline int +__syscall_getcwd (char *buf, size_t size) +{ +# ifdef FSCTYPE_XLATE_ENABLED + int single, oldtype = 0; + struct fsctype_conv *conv; + + if (!(single = SINGLE_THREAD_P)) + oldtype = LIBC_CANCEL_DEFERRED (); + switch (_nl_fsctype_get_conv (0, &conv)) + { + case -1: + return -1; + case 0: + if (!single) + LIBC_CANCEL_DEFERRED_RESET (oldtype); + break; + case 1: { + int ret; + char *ip, *op; + size_t ilen, olen; + + if ((ret = INLINE_SYSCALL (getcwd, 2, conv->bufs[0], + sizeof (conv->bufs[0]))) < 0) + goto out; + + ip = conv->bufs[0]; + ilen = ret; + op = buf; + olen = size; + + if ((ret = _nl_fsctype_xlate (conv, &ip, &ilen, &op, &olen)) >= 0) + ret = size - olen; + else if (errno == E2BIG && size < PATH_MAX) + __set_errno (ERANGE); + + out: + _nl_fsctype_free_conv (conv); + if (!single) + LIBC_CANCEL_DEFERRED_RESET (oldtype); + return ret; + } + } +# endif /* FSCTYPE_XLATE_ENABLED */ + return INLINE_SYSCALL (getcwd, 2, buf, size); +} +#endif /* defined __NR_getcwd || __LINUX_GETCWD_SYSCALL > 0 */ + char * __getcwd (char *buf, size_t size) { @@ -106,7 +156,7 @@ { int retval; - retval = INLINE_SYSCALL (getcwd, 2, CHECK_STRING (path), alloc_size); + retval = __syscall_getcwd (CHECK_STRING (path), alloc_size); if (retval >= 0) { # ifndef NO_ALLOCATION diff -Nru a/sysdeps/unix/sysv/linux/getdents-xlate.c b/sysdeps/unix/sysv/linux/getdents-xlate.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/sysdeps/unix/sysv/linux/getdents-xlate.c Mon Mar 22 14:59:24 2004 @@ -0,0 +1,107 @@ +/* Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Tejun Heo , 2004. + + 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. */ + +static inline ssize_t +__DO_GETDENTS_XLATE (int fd, char *buf, size_t nbytes, size_t kbytes, + struct fsctype_conv *conv) +{ + off64_t last_offset; + ssize_t retval; + int error; + K_DIRENT_TYPE *kbuf = NULL, *kdir, *kend; + DIRENT_TYPE *udir, *uend; + + if ((kbuf = malloc (kbytes)) == NULL) + { + __set_errno (ENOMEM); + return -1; + } + + last_offset = __lseek64 (fd, 0, SEEK_CUR); + if ((retval = INLINE_SYSCALL (GETDENTS_SYSCALL, 3, fd, + CHECK_N(kbuf, kbytes), kbytes)) <= 0) + { + free (kbuf); + return retval; + } + + kdir = kbuf; + udir = (DIRENT_TYPE *) buf; + kend = (void *) kbuf + retval; + uend = (void *) buf + nbytes; + + error = EINVAL; + while (kdir < kend) + { + char *kp, *up; + size_t klen, ulen, alignment; + + if (udir->d_name >= (char *) uend) + goto out_rewind; + + udir->d_type = K_DIRENT_GET_D_TYPE(kdir); + DIRENT_SET_DP_INO (udir, kdir->d_ino); + udir->d_off = kdir->d_off; + + if ((sizeof (udir->d_ino) != sizeof (kdir->d_ino) + && udir->d_ino != kdir->d_ino) + || ((sizeof (udir->d_off) != sizeof (kdir->d_off)) + && udir->d_off != kdir->d_off)) + { + error = EOVERFLOW; + goto out_rewind; + } + + kp = kdir->d_name; + klen = strlen (kp) + 1; + up = udir->d_name; + ulen = (char *) uend - udir->d_name; + if (ulen >= sizeof (udir->d_name)) + { + ulen = sizeof (udir->d_name); + error = EOVERFLOW; + } + + if (_nl_fsctype_xlate (conv, &kp, &klen, &up, &ulen) < 0) + goto out_rewind; + + ulen = offsetof (DIRENT_TYPE, d_name) + (up - udir->d_name); + alignment = __alignof__ (DIRENT_TYPE); + udir->d_reclen = (ulen + alignment - 1) & ~(alignment - 1); + + /* Check if the aligned dirent lies within the buffer. */ + if ((void *)udir + udir->d_reclen > (void *)uend) + goto out_rewind; + + last_offset = kdir->d_off; + kdir = (void *) kdir + kdir->d_reclen; + udir = (void *) udir + udir->d_reclen; + } + + free (kbuf); + return (char *) udir - buf; + + out_rewind: + free (kbuf); + __lseek64 (fd, last_offset, SEEK_SET); + if ((char *) udir - buf) + return (char *) udir - buf; + __set_errno (error); + return -1; +} diff -Nru a/sysdeps/unix/sysv/linux/getdents.c b/sysdeps/unix/sysv/linux/getdents.c --- a/sysdeps/unix/sysv/linux/getdents.c Mon Mar 22 14:59:24 2004 +++ b/sysdeps/unix/sysv/linux/getdents.c Mon Mar 22 14:59:24 2004 @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -31,6 +32,8 @@ #include #include +#include + #include #include "kernel-features.h" @@ -86,6 +89,94 @@ # define DIRENT_SET_DP_INO(dp, value) (dp)->d_ino = (value) #endif +#define CONCAT1(x,y,z) x##y##z +#define CONCAT(x,y,z) CONCAT1 (x,y,z) +#define GETDENTS_XLATE CONCAT (, __GETDENTS, _xlate) +#define DO_GETDENTS_XLATE CONCAT (do_, __GETDENTS, _xlate) +#define DO_GETDENTS64_XLATE CONCAT (do_, __GETDENTS, _64_xlate) + +#ifdef FSCTYPE_XLATE_ENABLED + +#define __DO_GETDENTS_XLATE DO_GETDENTS64_XLATE +#define GETDENTS_SYSCALL getdents64 +#define K_DIRENT_TYPE struct kernel_dirent64 +#define K_DIRENT_GET_D_TYPE(d) ((d)->d_type) +#include "getdents-xlate.c" +#undef __DO_GETDENTS_XLATE +#undef GETDENTS_SYSCALL +#undef K_DIRENT_TYPE +#undef K_DIRENT_GET_D_TYPE + +#define __DO_GETDENTS_XLATE DO_GETDENTS_XLATE +#define GETDENTS_SYSCALL getdents +#define K_DIRENT_TYPE struct kernel_dirent +#ifdef __ASSUME_GETDENTS32_D_TYPE +# define K_DIRENT_GET_D_TYPE(d) *((unsigned char *)(d) + (d)->d_reclen - 1) +#else +# define K_DIRENT_GET_D_TYPE(d) DT_UNKNOWN +#endif +#include "getdents-xlate.c" +#undef __DO_GETDENTS_XLATE +#undef GETDENTS_SYSCALL +#undef K_DIRENT_TYPE +#undef K_DIRENT_GET_D_TYPE + +static inline ssize_t +GETDENTS_XLATE (int fd, char *buf, size_t nbytes, struct fsctype_conv *conv) +{ + ssize_t retval; + size_t kbytes; + +#ifdef __ASSUME_GETDENTS32_D_TYPE + if (sizeof (DIRENT_TYPE) == sizeof (struct dirent)) + { + retval = DO_GETDNETS_XLATE (fd, buf, nbytes, nbytes, conv); + _nl_fsctype_free_conv (conv); + return retval; + } +#endif + +#ifdef __NR_getdents64 + if (!__have_no_getdents64) + { +# ifndef __ASSUME_GETDENTS64_SYSCALL + int saved_errno = errno; +# endif + if (offsetof (DIRENT_TYPE, d_name) + < offsetof (struct kernel_dirent64, d_name) + && nbytes <= sizeof (DIRENT_TYPE)) + kbytes = nbytes + offsetof (struct kernel_dirent64, d_name) + - offsetof (DIRENT_TYPE, d_name); + else + kbytes = nbytes; + retval = DO_GETDENTS64_XLATE (fd, buf, nbytes, kbytes, conv); +# ifndef __ASSUME_GETDENTS64_SYSCALL + if (retval != -1 || (errno != EINVAL && errno != ENOSYS)) +# endif + { + _nl_fsctype_free_conv (conv); + return retval; + } +# ifndef __ASSUME_GETDENTS64_SYSCALL + __set_errno (saved_errno); + __have_no_getdents64 = 1; +# endif + } +#endif + + const size_t size_diff = (offsetof (DIRENT_TYPE, d_name) + - offsetof (struct kernel_dirent, d_name)); + kbytes = MIN (nbytes + - ((nbytes / (offsetof (DIRENT_TYPE, d_name) + 14)) + * size_diff), + nbytes - size_diff); + retval = DO_GETDENTS_XLATE (fd, buf, nbytes, kbytes, conv); + _nl_fsctype_free_conv (conv); + return retval; +} + +#endif /* FSCTYPE_XLATE_ENABLED */ + /* The problem here is that we cannot simply read the next NBYTES bytes. We need to take the additional field into account. We use some heuristic. Assuming the directory contains names with 14 @@ -99,6 +190,28 @@ __GETDENTS (int fd, char *buf, size_t nbytes) { ssize_t retval; +#ifdef FSCTYPE_XLATE_ENABLED + int single, oldtype = 0; + struct fsctype_conv *conv; + + if (!(single = SINGLE_THREAD_P)) + oldtype = LIBC_CANCEL_DEFERRED (); + switch (_nl_fsctype_get_conv (0, &conv)) + { + case -1: + return -1; + case 0: + if (!single) + LIBC_CANCEL_DEFERRED_RESET (oldtype); + break; + case 1: { + retval = GETDENTS_XLATE (fd, buf, nbytes, conv); + if (!single) + LIBC_CANCEL_DEFERRED_RESET (oldtype); + return retval; + } + } +#endif /* FSCTYPE_XLATE_ENABLED */ #ifdef __ASSUME_GETDENTS32_D_TYPE if (sizeof (DIRENT_TYPE) == sizeof (struct dirent)) diff -Nru a/sysdeps/unix/sysv/linux/i386/chown.c b/sysdeps/unix/sysv/linux/i386/chown.c --- a/sysdeps/unix/sysv/linux/i386/chown.c Mon Mar 22 14:59:24 2004 +++ b/sysdeps/unix/sysv/linux/i386/chown.c Mon Mar 22 14:59:24 2004 @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -41,6 +42,14 @@ gid_t __group); extern int __real_chown (const char *__file, uid_t __owner, gid_t __group); +# if (!defined __NR_lchown && __ASSUME_LCHOWN_SYSCALL == 0) \ + || (__ASSUME_LCHOWN_SYSCALL == 0 || __ASSUME_32BIT_UIDS == 0) +static inline int +__syscall_chown (const char *file, uid_t owner, gid_t group) +{ + return INLINE_SYSCALL (chown, 3, CHECK_STRING (file), owner, group); +} +#endif #if defined __NR_lchown || __ASSUME_LCHOWN_SYSCALL > 0 /* Running under Linux > 2.1.80. */ @@ -51,6 +60,11 @@ uids. */ extern int __libc_missing_32bit_uids; # endif +static inline int +__syscall_chown32 (const char *file, uid_t owner, gid_t group) +{ + return INLINE_SYSCALL (chown32, 3, CHECK_STRING (file), owner, group); +} # endif /* __NR_chown32 */ int @@ -69,7 +83,7 @@ int result; int saved_errno = errno; - result = INLINE_SYSCALL (chown32, 3, CHECK_STRING (file), owner, group); + result = _NL_FSCTYPE_XLATE1 (__syscall_chown32, file, owner, group); if (result == 0 || errno != ENOSYS) return result; @@ -84,7 +98,7 @@ return -1; } - result = INLINE_SYSCALL (chown, 3, CHECK_STRING (file), owner, group); + result = _NL_FSCTYPE_XLATE1 (__syscall_chown, file, owner, group); if (result >= 0 || errno != ENOSYS) return result; @@ -96,7 +110,7 @@ return __lchown (file, owner, group); # elif __ASSUME_32BITUIDS /* This implies __ASSUME_LCHOWN_SYSCALL. */ - return INLINE_SYSCALL (chown32, 3, CHECK_STRING (file), owner, group); + return _NL_FSCTYPE_XLATE1 (__syscall_chown32, file, owner, group); # else /* !__ASSUME_32BITUIDS && ASSUME_LCHOWN_SYSCALL */ # ifdef __NR_chown32 @@ -105,7 +119,7 @@ int result; int saved_errno = errno; - result = INLINE_SYSCALL (chown32, 3, CHECK_STRING (file), owner, group); + result = _NL_FSCTYPE_XLATE1 (__syscall_chown32, file, owner, group); if (result == 0 || errno != ENOSYS) return result; @@ -120,7 +134,7 @@ return -1; } - return INLINE_SYSCALL (chown, 3, CHECK_STRING (file), owner, group); + return _NL_FSCTYPE_XLATE1 (__syscall_chown, file, owner, group); # endif } #endif @@ -131,7 +145,7 @@ int __chown_is_lchown (const char *file, uid_t owner, gid_t group) { - return INLINE_SYSCALL (chown, 3, CHECK_STRING (file), owner, group); + return _NL_FSCTYPE_XLATE1 (__syscall_chown, file, owner, group); } #elif SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_1) /* Compiling for compatibiity. */ diff -Nru a/sysdeps/unix/sysv/linux/i386/lchown.c b/sysdeps/unix/sysv/linux/i386/lchown.c --- a/sysdeps/unix/sysv/linux/i386/lchown.c Mon Mar 22 14:59:24 2004 +++ b/sysdeps/unix/sysv/linux/i386/lchown.c Mon Mar 22 14:59:24 2004 @@ -21,25 +21,40 @@ #include #include +#include #include #include #include "kernel-features.h" #ifdef __NR_lchown + +# if ! defined __NR_lchown32 || __ASSUME_32BITUIDS == 0 +static inline int +__syscall_lchown (const char *file, uid_t owner, gid_t group) +{ + return INLINE_SYSCALL (lchown, 3, CHECK_STRING (file), owner, group); +} +# endif + # ifdef __NR_lchown32 # if __ASSUME_32BITUIDS == 0 /* This variable is shared with all files that need to check for 32bit uids. */ extern int __libc_missing_32bit_uids; # endif +static inline int +__syscall_lchown32 (const char *file, uid_t owner, gid_t group) +{ + return INLINE_SYSCALL (lchown32, 3, CHECK_STRING (file), owner, group); +} # endif /* __NR_lchown32 */ int __lchown (const char *file, uid_t owner, gid_t group) { # if __ASSUME_32BITUIDS > 0 - return INLINE_SYSCALL (lchown32, 3, CHECK_STRING (file), owner, group); + return _NL_FSCTYPE_XLATE1 (__syscall_lchown32, file, owner, group); # else # ifdef __NR_lchown32 if (__libc_missing_32bit_uids <= 0) @@ -47,7 +62,7 @@ int result; int saved_errno = errno; - result = INLINE_SYSCALL (lchown32, 3, CHECK_STRING (file), owner, group); + result = _NL_FSCTYPE_XLATE1 (__syscall_lchown32, file, owner, group); if (result == 0 || errno != ENOSYS) return result; @@ -63,7 +78,7 @@ return -1; } - return INLINE_SYSCALL (lchown, 3, CHECK_STRING (file), owner, group); + return _NL_FSCTYPE_XLATE1 (__syscall_lchown, file, owner, group); # endif } diff -Nru a/sysdeps/unix/sysv/linux/i386/lxstat.c b/sysdeps/unix/sysv/linux/i386/lxstat.c --- a/sysdeps/unix/sysv/linux/i386/lxstat.c Mon Mar 22 14:59:24 2004 +++ b/sysdeps/unix/sysv/linux/i386/lxstat.c Mon Mar 22 14:59:24 2004 @@ -29,17 +29,29 @@ #include #include +#include #include #include "kernel-features.h" #include +static inline int +__syscall_lstat (const char *name, struct kernel_stat *buf) +{ + return INLINE_SYSCALL (lstat, 2, name, buf); +} + #ifdef __NR_stat64 # if __ASSUME_STAT64_SYSCALL == 0 /* The variable is shared between all wrappers around *stat64 calls. */ extern int __have_no_stat64; # endif +static inline int +__syscall_lstat64 (const char *name, struct stat64 *buf64) +{ + return INLINE_SYSCALL (lstat64, 2, name, buf64); +} #endif @@ -53,26 +65,29 @@ int result; if (vers == _STAT_VER_KERNEL) - return INLINE_SYSCALL (lstat, 2, CHECK_STRING (name), CHECK_1 ((struct kernel_stat *) buf)); + return _NL_FSCTYPE_XLATE1 (__syscall_lstat, CHECK_STRING (name), + CHECK_1 ((struct kernel_stat *) buf)); #if __ASSUME_STAT64_SYSCALL > 0 { struct stat64 buf64; - result = INLINE_SYSCALL (lstat64, 2, CHECK_STRING (name), __ptrvalue (&buf64)); + result = _NL_FSCTYPE_XLATE1 (__syscall_lstat64, CHECK_STRING (name), + __ptrvalue (&buf64)); if (result == 0) result = __xstat32_conv (vers, &buf64, buf); return result; } #else - # if defined __NR_stat64 /* To support 32 bit UIDs, we have to use stat64. The normal stat call only returns 16 bit UIDs. */ if (! __have_no_stat64) { struct stat64 buf64; - result = INLINE_SYSCALL (lstat64, 2, CHECK_STRING (name), __ptrvalue (&buf64)); + + result = _NL_FSCTYPE_XLATE1 (__syscall_lstat64, CHECK_STRING (name), + __ptrvalue (&buf64)); if (result == 0) result = __xstat32_conv (vers, &buf64, buf); @@ -83,8 +98,8 @@ __have_no_stat64 = 1; } # endif - - result = INLINE_SYSCALL (lstat, 2, CHECK_STRING (name), __ptrvalue (&kbuf)); + result = _NL_FSCTYPE_XLATE1 (__syscall_lstat, CHECK_STRING (name), + __ptrvalue (&kbuf)); if (result == 0) result = __xstat_conv (vers, &kbuf, buf); diff -Nru a/sysdeps/unix/sysv/linux/i386/sysdep-xlate.h b/sysdeps/unix/sysv/linux/i386/sysdep-xlate.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/sysdeps/unix/sysv/linux/i386/sysdep-xlate.h Mon Mar 22 14:59:24 2004 @@ -0,0 +1,51 @@ +/* Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Tejun Heo , 2004. + + 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 + +#undef CHECK_XLATE + +#ifdef PIC +# ifndef HAVE_HIDDEN +# define XLATE_SETUP_PIC_REG SETUP_PIC_REG (cx) +# else +# define XLATE_SETUP_PIC_REG call __i686.get_pc_thunk.cx +# endif +# if !defined NOT_IN_libc +# define CHECK_XLATE(prefix, syscall_name, args) \ + XLATE_SETUP_PIC_REG; \ + addl $_GLOBAL_OFFSET_TABLE_, %ecx; \ + cmpl $0, C_SYMBOL_NAME(__nl_fsctype_xlate_used)@GOTOFF(%ecx); \ + jne C_SYMBOL_NAME(prefix##_xlate); \ + ENTRY (prefix##_noxlate) +# else +# define CHECK_XLATE(prefix, syscall_name, args) \ + XLATE_SETUP_PIC_REG; \ + addl $_GLOBAL_OFFSET_TABLE_, %ecx; \ + movl C_SYMBOL_NAME(__nl_fsctype_xlate_used)@GOT(%ecx), %ecx; \ + cmpl $0, (%ecx); \ + jne C_SYMBOL_NAME(prefix##_xlate); \ + ENTRY (prefix##_noxlate) +# endif +#else /* PIC */ +# define CHECK_XLATE(prefix, syscall_name, args) \ + cmpl $0, C_SYMBOL_NAME(__nl_fsctype_xlate_used); \ + jne C_SYMBOL_NAME(prefix##_xlate); \ + ENTRY (prefix##_noxlate) +#endif /* PIC */ diff -Nru a/sysdeps/unix/sysv/linux/i386/sysdep.h b/sysdeps/unix/sysv/linux/i386/sysdep.h --- a/sysdeps/unix/sysv/linux/i386/sysdep.h Mon Mar 22 14:59:24 2004 +++ b/sysdeps/unix/sysv/linux/i386/sysdep.h Mon Mar 22 14:59:24 2004 @@ -64,15 +64,23 @@ # define SYSCALL_ERROR_LABEL syscall_error #endif -#undef PSEUDO -#define PSEUDO(name, syscall_name, args) \ +#undef CHECK_XLATE +#define CHECK_XLATE(prefix, syscall_name, args) + +#undef __PSEUDO +#define __PSEUDO(name, prefix, syscall_name, args) \ .text; \ ENTRY (name) \ + CHECK_XLATE (prefix, syscall_name, args) \ DO_CALL (syscall_name, args); \ cmpl $-4095, %eax; \ jae SYSCALL_ERROR_LABEL; \ L(pseudo_end): +#undef PSEUDO +#define PSEUDO(name, syscall_name, args) \ + __PSEUDO (name, bug bug bug, syscall_name, args) + #undef PSEUDO_END #define PSEUDO_END(name) \ SYSCALL_ERROR_HANDLER \ @@ -84,6 +92,10 @@ ENTRY (name) \ DO_CALL (syscall_name, args) +#undef __PSEUDO_NOERRNO +#define __PSEUDO_NOERRNO(name, prefix, syscall_name, args) \ + PSEUDO_NOERRNO (name, syscall_name, args) + #undef PSEUDO_END_NOERRNO #define PSEUDO_END_NOERRNO(name) \ END (name) @@ -92,11 +104,15 @@ /* The function has to return the error code. */ #undef PSEUDO_ERRVAL -#define PSEUDO_ERRVAL(name, syscall_name, args) \ +#define PSEUDO_ERRVAL(name, syscall_name, args) \ .text; \ ENTRY (name) \ DO_CALL (syscall_name, args); \ negl %eax + +#undef __PSEUDO_ERRVAL +#define __PSEUDO_ERRVAL(name, prefix, syscall_name, args) \ + PSEUDO_ERRVAL (name, syscall_name, args) #undef PSEUDO_END_ERRVAL #define PSEUDO_END_ERRVAL(name) \ diff -Nru a/sysdeps/unix/sysv/linux/i386/xstat.c b/sysdeps/unix/sysv/linux/i386/xstat.c --- a/sysdeps/unix/sysv/linux/i386/xstat.c Mon Mar 22 14:59:24 2004 +++ b/sysdeps/unix/sysv/linux/i386/xstat.c Mon Mar 22 14:59:24 2004 @@ -28,17 +28,29 @@ #include #include +#include #include #include "kernel-features.h" #include +static inline int +__syscall_stat (const char *name, struct kernel_stat *buf) +{ + return INLINE_SYSCALL (stat, 2, name, buf); +} + #ifdef __NR_stat64 # if __ASSUME_STAT64_SYSCALL == 0 /* The variable is shared between all wrappers around *stat64 calls. */ extern int __have_no_stat64; # endif +static inline int +__syscall_stat64 (const char *name, struct stat64 *buf64) +{ + return INLINE_SYSCALL (stat64, 2, name, buf64); +} #endif @@ -52,13 +64,15 @@ int result; if (vers == _STAT_VER_KERNEL) - return INLINE_SYSCALL (stat, 2, CHECK_STRING (name), CHECK_1 ((struct kernel_stat *) buf)); + return _NL_FSCTYPE_XLATE1 (__syscall_stat, CHECK_STRING (name), + CHECK_1 ((struct kernel_stat *) buf)); #if __ASSUME_STAT64_SYSCALL > 0 { struct stat64 buf64; - result = INLINE_SYSCALL (stat64, 2, CHECK_STRING (name), __ptrvalue (&buf64)); + result = _NL_FSCTYPE_XLATE1 (__syscall_stat64, CHECK_STRING (name), + __ptrvalue (&buf64)); if (result == 0) result = __xstat32_conv (vers, &buf64, buf); return result; @@ -71,7 +85,8 @@ { struct stat64 buf64; - result = INLINE_SYSCALL (stat64, 2, CHECK_STRING (name), __ptrvalue (&buf64)); + result = _NL_FSCTYPE_XLATE1 (__syscall_stat64, CHECK_STRING (name), + __ptrvalue (&buf64)); if (result == 0) result = __xstat32_conv (vers, &buf64, buf); @@ -82,7 +97,8 @@ __have_no_stat64 = 1; } # endif - result = INLINE_SYSCALL (stat, 2, CHECK_STRING (name), __ptrvalue (&kbuf)); + result = _NL_FSCTYPE_XLATE1 (__syscall_stat, CHECK_STRING (name), + __ptrvalue (&kbuf)); if (result == 0) result = __xstat_conv (vers, &kbuf, buf); diff -Nru a/sysdeps/unix/sysv/linux/lxstat.c b/sysdeps/unix/sysv/linux/lxstat.c --- a/sysdeps/unix/sysv/linux/lxstat.c Mon Mar 22 14:59:24 2004 +++ b/sysdeps/unix/sysv/linux/lxstat.c Mon Mar 22 14:59:24 2004 @@ -28,17 +28,24 @@ #include #include +#include #include #include +static inline int +__syscall_lstat (const char *name, struct kernel_stat *buf) +{ + return INLINE_SYSCALL (lstat, 2, name, buf); +} + /* Get information about the file NAME in BUF. */ int __lxstat (int vers, const char *name, struct stat *buf) { if (vers == _STAT_VER_KERNEL) - return INLINE_SYSCALL (lstat, 2, CHECK_STRING (name), - CHECK_1 ((struct kernel_stat *) buf)); + return _NL_FSCTYPE_XLATE1 (__syscall_lstat, CHECK_STRING (name), + CHECK_1 ((struct kernel_stat *) buf)); #ifdef STAT_IS_KERNEL_STAT errno = EINVAL; @@ -47,7 +54,8 @@ struct kernel_stat kbuf; int result; - result = INLINE_SYSCALL (lstat, 2, CHECK_STRING (name), __ptrvalue (&kbuf)); + result = _NL_FSCTYPE_XLATE1 (__syscall_lstat, CHECK_STRING (name), + __ptrvalue (&kbuf)); if (result == 0) result = __xstat_conv (vers, &kbuf, buf); diff -Nru a/sysdeps/unix/sysv/linux/lxstat64.c b/sysdeps/unix/sysv/linux/lxstat64.c --- a/sysdeps/unix/sysv/linux/lxstat64.c Mon Mar 22 14:59:24 2004 +++ b/sysdeps/unix/sysv/linux/lxstat64.c Mon Mar 22 14:59:24 2004 @@ -24,12 +24,18 @@ #include #include +#include #include #include "kernel-features.h" #if __ASSUME_STAT64_SYSCALL == 0 # include +static inline int +__syscall_lstat (const char *name, struct kernel_stat *buf) +{ + return INLINE_SYSCALL (lstat, 2, name, buf); +} #endif #ifdef __NR_lstat64 @@ -37,6 +43,11 @@ /* The variable is shared between all wrappers around *stat64 calls. */ extern int __have_no_stat64; # endif +static inline int +__syscall_lstat64 (const char *name, struct stat64 *buf) +{ + return INLINE_SYSCALL (lstat64, 2, name, buf); +} #endif /* Get information about the file NAME in BUF. */ @@ -45,7 +56,8 @@ { int result; #ifdef __ASSUME_STAT64_SYSCALL - result = INLINE_SYSCALL (lstat64, 2, CHECK_STRING (name), CHECK_1 (buf)); + result = _NL_FSCTYPE_XLATE1 (__syscall_lstat64, + CHECK_STRING (name), CHECK_1 (buf)); # if defined _HAVE_STAT64___ST_INO && __ASSUME_ST_INO_64_BIT == 0 if (__builtin_expect (!result, 1) && buf->__st_ino != (__ino_t) buf->st_ino) buf->st_ino = buf->__st_ino; @@ -57,7 +69,8 @@ if (! __have_no_stat64) { int saved_errno = errno; - result = INLINE_SYSCALL (lstat64, 2, CHECK_STRING (name), CHECK_1 (buf)); + result = _NL_FSCTYPE_XLATE1 (__syscall_lstat64, + CHECK_STRING (name), CHECK_1 (buf)); if (result != -1 || errno != ENOSYS) { @@ -72,7 +85,8 @@ __have_no_stat64 = 1; } # endif - result = INLINE_SYSCALL (lstat, 2, CHECK_STRING (name), __ptrvalue (&kbuf)); + result = _NL_FSCTYPE_XLATE1 (__syscall_lstat, + CHECK_STRING (name), __ptrvalue (&kbuf)); if (result == 0) result = __xstat64_conv (vers, &kbuf, buf); diff -Nru a/sysdeps/unix/sysv/linux/not-cancel.h b/sysdeps/unix/sysv/linux/not-cancel.h --- a/sysdeps/unix/sysv/linux/not-cancel.h Mon Mar 22 14:59:24 2004 +++ b/sysdeps/unix/sysv/linux/not-cancel.h Mon Mar 22 14:59:24 2004 @@ -21,10 +21,16 @@ #include /* Uncancelable open. */ +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt +extern int __open_nocancel (const char *, int, ...) attribute_hidden; +#define open_not_cancel(name, flags, mode) __open_nocancel (name, flags, mode) +#define open_not_cancel_2(name, flags) __open_nocancel (name, flags) +#else #define open_not_cancel(name, flags, mode) \ INLINE_SYSCALL (open, 3, (const char *) (name), (flags), (mode)) #define open_not_cancel_2(name, flags) \ INLINE_SYSCALL (open, 2, (const char *) (name), (flags)) +#endif /* Uncancelable close. */ #define close_not_cancel(fd) \ diff -Nru a/sysdeps/unix/sysv/linux/open64.c b/sysdeps/unix/sysv/linux/open64.c --- a/sysdeps/unix/sysv/linux/open64.c Mon Mar 22 14:59:24 2004 +++ b/sysdeps/unix/sysv/linux/open64.c Mon Mar 22 14:59:24 2004 @@ -21,6 +21,23 @@ #include #include #include +#include + +static inline int +__syscall_open64 (const char *file, int oflag, int mode) +{ + return INLINE_SYSCALL (open, 3, file, oflag, mode); +} + +static inline int +__syscall_open64_async (const char *file, int oflag, int mode) +{ + int oldtype, ret; + oldtype = LIBC_CANCEL_ASYNC (); + ret = INLINE_SYSCALL (open, 3, file, oflag, mode); + LIBC_CANCEL_RESET (oldtype); + return ret; +} /* Open FILE with access OFLAG. If OFLAG includes O_CREAT, a third argument is the file protection. */ @@ -38,15 +55,11 @@ } if (SINGLE_THREAD_P) - return INLINE_SYSCALL (open, 3, file, oflag | O_LARGEFILE, mode); - - int oldtype = LIBC_CANCEL_ASYNC (); - - int result = INLINE_SYSCALL (open, 3, file, oflag | O_LARGEFILE, mode); - - LIBC_CANCEL_RESET (oldtype); + return __NL_FSCTYPE_XLATE1 (1, oflag & O_CREAT, NONE, __syscall_open64, + file, oflag | O_LARGEFILE, mode); - return result; + return __NL_FSCTYPE_XLATE1 (1, oflag & O_CREAT, ASYNC, __syscall_open64_async, + file, oflag | O_LARGEFILE, mode); } weak_alias (__libc_open64, BP_SYM (__open64)) libc_hidden_weak (BP_SYM (__open64)) diff -Nru a/sysdeps/unix/sysv/linux/syscalls.list b/sysdeps/unix/sysv/linux/syscalls.list --- a/sysdeps/unix/sysv/linux/syscalls.list Mon Mar 22 14:59:24 2004 +++ b/sysdeps/unix/sysv/linux/syscalls.list Mon Mar 22 14:59:24 2004 @@ -4,7 +4,7 @@ bdflush EXTRA bdflush i:ii bdflush capget EXTRA capget i:pp capget capset EXTRA capset i:pp capset -creat - creat Ci:si __libc_creat creat +creat - creat Cxi:si __libc_creat creat create_module EXTRA create_module 3 create_module delete_module EXTRA delete_module 3 delete_module epoll_create EXTRA epoll_create i:i epoll_create @@ -27,7 +27,7 @@ ioperm - ioperm i:iii ioperm iopl - iopl i:i iopl klogctl EXTRA syslog i:isi klogctl -lchown - lchown i:sii __lchown lchown +lchown - lchown xi:sii __lchown lchown posix_madvise - madvise Vi:pii posix_madvise madvise - madvise i:pii madvise mincore - mincore i:anV mincore @@ -72,17 +72,17 @@ uselib EXTRA uselib i:s uselib wait4 - wait4 i:iWiP __wait4 wait4 -chown - chown i:sii __libc_chown __chown chown +chown - chown xi:sii __libc_chown __chown chown -setxattr - setxattr i:sspii setxattr -lsetxattr - lsetxattr i:sspii lsetxattr +setxattr - setxattr xi:sspii setxattr +lsetxattr - lsetxattr xi:sspii lsetxattr fsetxattr - fsetxattr i:ispii fsetxattr -getxattr - getxattr i:sspi getxattr -lgetxattr - lgetxattr i:sspi lgetxattr +getxattr - getxattr xi:sspi getxattr +lgetxattr - lgetxattr xi:sspi lgetxattr fgetxattr - fgetxattr i:ispi fgetxattr -listxattr - listxattr i:ssi listxattr -llistxattr - llistxattr i:ssi llistxattr +listxattr - listxattr xi:ssi listxattr +llistxattr - llistxattr xi:ssi llistxattr flistxattr - flistxattr i:isi flistxattr -removexattr - removexattr i:ss removexattr -lremovexattr - lremovexattr i:ss lremovexattr +removexattr - removexattr xi:ss removexattr +lremovexattr - lremovexattr xi:ss lremovexattr fremovexattr - fremovexattr i:is fremovexattr diff -Nru a/sysdeps/unix/sysv/linux/truncate64.c b/sysdeps/unix/sysv/linux/truncate64.c --- a/sysdeps/unix/sysv/linux/truncate64.c Mon Mar 22 14:59:24 2004 +++ b/sysdeps/unix/sysv/linux/truncate64.c Mon Mar 22 14:59:24 2004 @@ -23,6 +23,7 @@ #include #include +#include #include #include "kernel-features.h" @@ -33,6 +34,13 @@ int __have_no_truncate64; #endif +static inline int +__syscall_truncate64 (const char *path, unsigned int high, unsigned int low) +{ + return INLINE_SYSCALL (truncate64, 3, CHECK_STRING (path), + __LONG_LONG_PAIR (high, low)); +} + /* Truncate the file FD refers to to LENGTH bytes. */ int truncate64 (const char *path, off64_t length) @@ -46,8 +54,7 @@ #ifndef __ASSUME_TRUNCATE64_SYSCALL int saved_errno = errno; #endif - int result = INLINE_SYSCALL (truncate64, 3, CHECK_STRING (path), - __LONG_LONG_PAIR (high, low)); + int result = _NL_FSCTYPE_XLATE1 (__syscall_truncate64, path, high, low); #ifndef __ASSUME_TRUNCATE64_SYSCALL if (result != -1 || errno != ENOSYS) #endif diff -Nru a/sysdeps/unix/sysv/linux/utimes.c b/sysdeps/unix/sysv/linux/utimes.c --- a/sysdeps/unix/sysv/linux/utimes.c Mon Mar 22 14:59:24 2004 +++ b/sysdeps/unix/sysv/linux/utimes.c Mon Mar 22 14:59:24 2004 @@ -21,8 +21,24 @@ #include #include #include +#include #include "kernel-features.h" +#ifdef __NR_utimes +static inline int +__syscall_utimes (const char *file, const struct timeval tvp[2]) +{ + return INLINE_SYSCALL (utimes, 2, file, tvp); +} +#endif + +#ifndef __ASSUME_UTIMES +static inline int +__syscall_utime (const char *file, const struct utimbuf *times) +{ + return INLINE_SYSCALL (utime, 2, file, times); +} +#endif /* Change the access time of FILE to TVP[0] and the modification time of FILE to TVP[1]. */ @@ -30,7 +46,7 @@ __utimes (const char *file, const struct timeval tvp[2]) { #ifdef __NR_utimes - int result = INLINE_SYSCALL (utimes, 2, file, tvp); + int result = _NL_FSCTYPE_XLATE1 (__syscall_utimes, file, tvp); # ifndef __ASSUME_UTIMES if (result != -1 || errno != ENOSYS) # endif @@ -53,7 +69,7 @@ else times = NULL; - return INLINE_SYSCALL (utime, 2, file, times); + return _NL_FSCTYPE_XLATE1 (__syscall_utime, file, times); #endif } diff -Nru a/sysdeps/unix/sysv/linux/xmknod.c b/sysdeps/unix/sysv/linux/xmknod.c --- a/sysdeps/unix/sysv/linux/xmknod.c Mon Mar 22 14:59:24 2004 +++ b/sysdeps/unix/sysv/linux/xmknod.c Mon Mar 22 14:59:24 2004 @@ -25,8 +25,15 @@ #include #include +#include #include +static inline int +__syscall_mknod (const char *path, mode_t mode, unsigned int k_dev) +{ + return INLINE_SYSCALL (mknod, 3, path, mode, k_dev); +} + /* Create a device file named PATH, with permission and special bits MODE and device number DEV (which can be constructed from major and minor device numbers with the `makedev' macro above). */ @@ -49,8 +56,8 @@ return -1; } - return INLINE_SYSCALL (mknod, 3, CHECK_STRING (path), mode, - (unsigned int) k_dev); + return _NL_FSCTYPE_XLATE1 (__syscall_mknod, CHECK_STRING (path), mode, + (unsigned int) k_dev); } weak_alias (__xmknod, _xmknod) diff -Nru a/sysdeps/unix/sysv/linux/xstat.c b/sysdeps/unix/sysv/linux/xstat.c --- a/sysdeps/unix/sysv/linux/xstat.c Mon Mar 22 14:59:24 2004 +++ b/sysdeps/unix/sysv/linux/xstat.c Mon Mar 22 14:59:24 2004 @@ -28,17 +28,24 @@ #include #include +#include #include #include +static inline int +__syscall_stat (const char *name, struct kernel_stat *buf) +{ + return INLINE_SYSCALL (stat, 2, name, buf); +} + /* Get information about the file NAME in BUF. */ int __xstat (int vers, const char *name, struct stat *buf) { if (vers == _STAT_VER_KERNEL) - return INLINE_SYSCALL (stat, 2, CHECK_STRING (name), - CHECK_1 ((struct kernel_stat *) buf)); + return _NL_FSCTYPE_XLATE1 (__syscall_stat, CHECK_STRING (name), + CHECK_1 ((struct kernel_stat *) buf)); #ifdef STAT_IS_KERNEL_STAT errno = EINVAL; @@ -47,8 +54,8 @@ struct kernel_stat kbuf; int result; - result = INLINE_SYSCALL (stat, 2, CHECK_STRING (name), - __ptrvalue (&kbuf)); + result = _NL_FSCTYPE_XLATE1 (__syscall_stat, CHECK_STRING (name), + __ptrvalue (&kbuf)); if (result == 0) result = __xstat_conv (vers, &kbuf, buf); diff -Nru a/sysdeps/unix/sysv/linux/xstat64.c b/sysdeps/unix/sysv/linux/xstat64.c --- a/sysdeps/unix/sysv/linux/xstat64.c Mon Mar 22 14:59:24 2004 +++ b/sysdeps/unix/sysv/linux/xstat64.c Mon Mar 22 14:59:24 2004 @@ -24,12 +24,18 @@ #include #include +#include #include #include "kernel-features.h" #if __ASSUME_STAT64_SYSCALL == 0 # include +static inline int +__syscall_stat (const char *name, struct kernel_stat *buf) +{ + return INLINE_SYSCALL (stat, 2, name, buf); +} #endif #ifdef __NR_stat64 @@ -38,6 +44,11 @@ This is the definition. */ int __have_no_stat64; # endif +static inline int +__syscall_stat64 (const char *name, struct stat64 *buf) +{ + return INLINE_SYSCALL (stat64, 2, name, buf); +} #endif /* Get information about the file NAME in BUF. */ @@ -47,7 +58,8 @@ { int result; #if __ASSUME_STAT64_SYSCALL > 0 - result = INLINE_SYSCALL (stat64, 2, CHECK_STRING (name), CHECK_1 (buf)); + result = _NL_FSCTYPE_XLATE1 (__syscall_stat64, + CHECK_STRING (name), CHECK_1 (buf)); # if defined _HAVE_STAT64___ST_INO && __ASSUME_ST_INO_64_BIT == 0 if (__builtin_expect (!result, 1) && buf->__st_ino != (__ino_t) buf->st_ino) buf->st_ino = buf->__st_ino; @@ -59,7 +71,8 @@ if (! __have_no_stat64) { int saved_errno = errno; - result = INLINE_SYSCALL (stat64, 2, CHECK_STRING (name), CHECK_1 (buf)); + result = _NL_FSCTYPE_XLATE1 (__syscall_stat64, + CHECK_STRING (name), CHECK_1 (buf)); if (result != -1 || errno != ENOSYS) { @@ -75,7 +88,8 @@ } # endif - result = INLINE_SYSCALL (stat, 2, CHECK_STRING (name), __ptrvalue (&kbuf)); + result = _NL_FSCTYPE_XLATE1 (__syscall_stat, + CHECK_STRING (name), __ptrvalue (&kbuf)); if (result == 0) result = __xstat64_conv (vers, &kbuf, buf); diff -Nru a/sysdeps/unix/sysv/syscalls.list b/sysdeps/unix/sysv/syscalls.list --- a/sysdeps/unix/sysv/syscalls.list Mon Mar 22 14:59:24 2004 +++ b/sysdeps/unix/sysv/syscalls.list Mon Mar 22 14:59:24 2004 @@ -13,4 +13,4 @@ time - time Ei:P time times - times i:p __times times ulimit - ulimit i:ii ulimit -utime - utime i:sP utime +utime - utime xi:sP utime