summaryrefslogtreecommitdiff
path: root/posix
diff options
context:
space:
mode:
authorSamuel Thibault <samuel.thibault@ens-lyon.org>2018-12-27 19:30:36 +0000
committerSamuel Thibault <samuel.thibault@ens-lyon.org>2018-12-27 19:30:36 +0000
commit704e05ff173885df6d1d27f381604429f27fd4de (patch)
treefc67caec36bc5ed0c4190cafd38f69850a10ca0a /posix
parentecfe3e291f848cf598309d746619de62ea88fabb (diff)
parent3fcbb67b7949a8b362de5558bf1c6dd7ec5d21cf (diff)
Merge branch 't/tls-threadvar' into refs/top-bases/t/ONSTACK
Diffstat (limited to 'posix')
-rw-r--r--posix/Makefile114
-rw-r--r--posix/PCRE.tests13
-rw-r--r--posix/Versions4
-rw-r--r--posix/_exit.c2
-rw-r--r--posix/alarm.c2
-rw-r--r--posix/annexc.c16
-rw-r--r--posix/bits/cpu-set.h124
-rw-r--r--posix/bits/getopt_core.h96
-rw-r--r--posix/bits/getopt_ext.h77
-rw-r--r--posix/bits/getopt_posix.h51
-rw-r--r--posix/bits/posix1_lim.h12
-rw-r--r--posix/bits/posix2_lim.h2
-rw-r--r--posix/bits/types.h216
-rw-r--r--posix/bits/unistd.h4
-rw-r--r--posix/bsd-getpgrp.c2
-rw-r--r--posix/bug-getopt1.c9
-rw-r--r--posix/bug-getopt2.c9
-rw-r--r--posix/bug-getopt3.c9
-rw-r--r--posix/bug-getopt4.c25
-rw-r--r--posix/bug-getopt5.c9
-rw-r--r--posix/bug-glob1.c88
-rw-r--r--posix/bug-glob2.c26
-rw-r--r--posix/bug-regex10.c2
-rw-r--r--posix/bug-regex11.c2
-rw-r--r--posix/bug-regex12.c2
-rw-r--r--posix/bug-regex13.c2
-rw-r--r--posix/bug-regex14.c2
-rw-r--r--posix/bug-regex17.c2
-rw-r--r--posix/bug-regex18.c2
-rw-r--r--posix/bug-regex19.c2
-rw-r--r--posix/bug-regex2.c2
-rw-r--r--posix/bug-regex20.c2
-rw-r--r--posix/bug-regex21.c2
-rw-r--r--posix/bug-regex22.c2
-rw-r--r--posix/bug-regex23.c2
-rw-r--r--posix/bug-regex25.c2
-rw-r--r--posix/bug-regex26.c2
-rw-r--r--posix/bug-regex27.c2
-rw-r--r--posix/bug-regex28.c48
-rw-r--r--posix/bug-regex3.c2
-rw-r--r--posix/bug-regex30.c2
-rw-r--r--posix/bug-regex33.c8
-rw-r--r--posix/bug-regex34.c2
-rw-r--r--posix/bug-regex35.c2
-rw-r--r--posix/bug-regex36.c2
-rw-r--r--posix/bug-regex37.c32
-rw-r--r--posix/bug-regex38.c32
-rw-r--r--posix/bug-regex4.c2
-rw-r--r--posix/bug-regex5.c4
-rw-r--r--posix/bug-regex6.c2
-rw-r--r--posix/bug-regex7.c2
-rw-r--r--posix/bug-regex8.c2
-rw-r--r--posix/bug-regex9.c2
-rw-r--r--posix/confstr.c2
-rw-r--r--posix/cpio.h2
-rw-r--r--posix/execl.c70
-rw-r--r--posix/execle.c72
-rw-r--r--posix/execlp.c68
-rw-r--r--posix/execv.c2
-rw-r--r--posix/execve.c2
-rw-r--r--posix/execvp.c2
-rw-r--r--posix/execvpe.c293
-rw-r--r--posix/fexecve.c2
-rw-r--r--posix/flexmember.h45
-rw-r--r--posix/fnmatch.c8
-rw-r--r--posix/fnmatch.h2
-rw-r--r--posix/fnmatch_loop.c13
-rw-r--r--posix/fork.c2
-rw-r--r--posix/fpathconf.c2
-rw-r--r--posix/gai_strerror.c2
-rw-r--r--posix/get_child_max.c2
-rw-r--r--posix/getaddrinfo.c2
-rw-r--r--posix/getconf-speclist.c2
-rw-r--r--posix/getconf.c88
-rw-r--r--posix/getegid.c2
-rw-r--r--posix/geteuid.c2
-rw-r--r--posix/getgid.c2
-rw-r--r--posix/getgroups.c2
-rw-r--r--posix/getopt.c1156
-rw-r--r--posix/getopt.h181
-rw-r--r--posix/getopt1.c69
-rw-r--r--posix/getopt_init.c74
-rw-r--r--posix/getopt_int.h95
-rw-r--r--posix/getpgid.c2
-rw-r--r--posix/getpgrp.c2
-rw-r--r--posix/getpid.c2
-rw-r--r--posix/getppid.c2
-rw-r--r--posix/getresgid.c2
-rw-r--r--posix/getresuid.c2
-rw-r--r--posix/getsid.c2
-rw-r--r--posix/getuid.c2
-rw-r--r--posix/glob-lstat-compat.c36
-rw-r--r--posix/glob.c1254
-rw-r--r--posix/glob.h4
-rw-r--r--posix/glob64-lstat-compat.c36
-rw-r--r--posix/glob64.c13
-rw-r--r--posix/glob_internal.h65
-rw-r--r--posix/glob_pattern_p.c33
-rw-r--r--posix/globfree.c41
-rw-r--r--posix/globfree64.c31
-rw-r--r--posix/globtest.c2
-rwxr-xr-xposix/globtest.sh27
-rw-r--r--posix/group_member.c2
-rw-r--r--posix/nanosleep.c4
-rw-r--r--posix/pathconf.c2
-rw-r--r--posix/pause.c2
-rw-r--r--posix/posix-conf-vars.h2
-rw-r--r--posix/posix-envs.def2
-rw-r--r--posix/posix_madvise.c4
-rw-r--r--posix/pread.c2
-rw-r--r--posix/pread64.c3
-rw-r--r--posix/pwrite.c2
-rw-r--r--posix/pwrite64.c2
-rw-r--r--posix/re_comp.h2
-rw-r--r--posix/regcomp.c660
-rw-r--r--posix/regex.c23
-rw-r--r--posix/regex.h337
-rw-r--r--posix/regex_internal.c350
-rw-r--r--posix/regex_internal.h457
-rw-r--r--posix/regexec.c1134
-rw-r--r--posix/runptests.c2
-rw-r--r--posix/sched.h19
-rw-r--r--posix/sched_cpualloc.c2
-rw-r--r--posix/sched_cpucount.c29
-rw-r--r--posix/sched_cpufree.c2
-rw-r--r--posix/sched_getaffinity.c2
-rw-r--r--posix/sched_getp.c2
-rw-r--r--posix/sched_gets.c2
-rw-r--r--posix/sched_primax.c3
-rw-r--r--posix/sched_primin.c3
-rw-r--r--posix/sched_rr_gi.c2
-rw-r--r--posix/sched_setaffinity.c2
-rw-r--r--posix/sched_setp.c3
-rw-r--r--posix/sched_sets.c2
-rw-r--r--posix/sched_yield.c2
-rw-r--r--posix/setgid.c2
-rw-r--r--posix/setpgid.c2
-rw-r--r--posix/setpgrp.c2
-rw-r--r--posix/setresgid.c2
-rw-r--r--posix/setresuid.c2
-rw-r--r--posix/setsid.c2
-rw-r--r--posix/setuid.c2
-rw-r--r--posix/sleep.c2
-rw-r--r--posix/spawn.c2
-rw-r--r--posix/spawn.h6
-rw-r--r--posix/spawn_faction_addclose.c6
-rw-r--r--posix/spawn_faction_adddup2.c6
-rw-r--r--posix/spawn_faction_addopen.c9
-rw-r--r--posix/spawn_faction_destroy.c2
-rw-r--r--posix/spawn_faction_init.c2
-rw-r--r--posix/spawn_int.h35
-rw-r--r--posix/spawn_valid_fd.c30
-rw-r--r--posix/spawnattr_destroy.c2
-rw-r--r--posix/spawnattr_getdefault.c2
-rw-r--r--posix/spawnattr_getflags.c2
-rw-r--r--posix/spawnattr_getpgroup.c2
-rw-r--r--posix/spawnattr_getschedparam.c2
-rw-r--r--posix/spawnattr_getschedpolicy.c2
-rw-r--r--posix/spawnattr_getsigmask.c2
-rw-r--r--posix/spawnattr_init.c2
-rw-r--r--posix/spawnattr_setdefault.c2
-rw-r--r--posix/spawnattr_setflags.c3
-rw-r--r--posix/spawnattr_setpgroup.c2
-rw-r--r--posix/spawnattr_setschedparam.c2
-rw-r--r--posix/spawnattr_setschedpolicy.c2
-rw-r--r--posix/spawnattr_setsigmask.c2
-rw-r--r--posix/spawni.c2
-rw-r--r--posix/spawnp.c2
-rw-r--r--posix/sys/times.h6
-rw-r--r--posix/sys/types.h44
-rw-r--r--posix/sys/utsname.h2
-rw-r--r--posix/sys/wait.h90
-rw-r--r--posix/sysconf.c4
-rw-r--r--posix/tar.h2
-rw-r--r--posix/test-errno.c154
-rw-r--r--posix/test-ssize-max.c39
-rw-r--r--posix/times.c2
-rw-r--r--posix/tst-boost.c2
-rw-r--r--posix/tst-chmod.c2
-rw-r--r--posix/tst-dir.c26
-rw-r--r--posix/tst-exec.c52
-rw-r--r--posix/tst-execvp1.c6
-rw-r--r--posix/tst-execvp2.c5
-rw-r--r--posix/tst-execvp3.c5
-rw-r--r--posix/tst-execvp4.c6
-rw-r--r--posix/tst-execvpe1.c20
-rw-r--r--posix/tst-execvpe2.c20
-rw-r--r--posix/tst-execvpe3.c20
-rw-r--r--posix/tst-execvpe4.c20
-rw-r--r--posix/tst-execvpe5.c160
-rw-r--r--posix/tst-execvpe6.c150
-rw-r--r--posix/tst-fexecve.c88
-rw-r--r--posix/tst-fnmatch.c2
-rw-r--r--posix/tst-fnmatch.input69
-rw-r--r--posix/tst-fnmatch3.c2
-rw-r--r--posix/tst-fork.c2
-rw-r--r--posix/tst-getaddrinfo.c2
-rw-r--r--posix/tst-getaddrinfo2.c1
-rw-r--r--posix/tst-getaddrinfo4.c2
-rw-r--r--posix/tst-getaddrinfo5.c3
-rw-r--r--posix/tst-getconf.sh2
-rw-r--r--posix/tst-getopt-cancel.c284
-rw-r--r--posix/tst-getopt_long1.c2
-rw-r--r--posix/tst-glob-tilde.c144
-rw-r--r--posix/tst-glob_lstat_compat.c268
-rw-r--r--posix/tst-glob_symlinks.c138
-rw-r--r--posix/tst-gnuglob-skeleton.c508
-rw-r--r--posix/tst-gnuglob.c493
-rw-r--r--posix/tst-gnuglob64.c25
-rw-r--r--posix/tst-mmap-offset.c91
-rw-r--r--posix/tst-nanosleep.c2
-rw-r--r--posix/tst-nice.c2
-rw-r--r--posix/tst-pathconf.c18
-rw-r--r--posix/tst-pcre.c2
-rw-r--r--posix/tst-posix_fadvise-common.c111
-rw-r--r--posix/tst-posix_fadvise.c25
-rw-r--r--posix/tst-posix_fadvise64.c46
-rw-r--r--posix/tst-posix_spawn-fd.c165
-rw-r--r--posix/tst-posix_spawn-setsid.c95
-rw-r--r--posix/tst-preadwrite-common.c86
-rw-r--r--posix/tst-preadwrite.c89
-rw-r--r--posix/tst-preadwrite64.c42
-rw-r--r--posix/tst-regex.c8
-rw-r--r--posix/tst-regex2.c2
-rw-r--r--posix/tst-regexloc.c9
-rw-r--r--posix/tst-rfc3484-2.c1
-rw-r--r--posix/tst-rfc3484-3.c1
-rw-r--r--posix/tst-rfc3484.c1
-rw-r--r--posix/tst-rxspencer.c2
-rw-r--r--posix/tst-spawn.c100
-rw-r--r--posix/tst-spawn2.c78
-rw-r--r--posix/tst-spawn3.c151
-rw-r--r--posix/tst-spawn4-compat.c77
-rw-r--r--posix/tst-spawn4.c56
-rw-r--r--posix/tst-sysconf-empty-chroot.c95
-rw-r--r--posix/tst-truncate-common.c88
-rw-r--r--posix/tst-truncate.c116
-rw-r--r--posix/tst-truncate64.c23
-rw-r--r--posix/tst-vfork1.c2
-rw-r--r--posix/tst-vfork2.c2
-rw-r--r--posix/tst-vfork3.c190
-rw-r--r--posix/tst-waitid.c2
-rw-r--r--posix/uname-values.h2
-rw-r--r--posix/uname.c2
-rw-r--r--posix/unistd.h63
-rw-r--r--posix/vfork.c2
-rw-r--r--posix/wait.c4
-rw-r--r--posix/wait3.c4
-rw-r--r--posix/wait4.c5
-rw-r--r--posix/waitid.c2
-rw-r--r--posix/waitpid.c2
-rw-r--r--posix/wordexp-test.c10
-rwxr-xr-xposix/wordexp-tst.sh2
-rw-r--r--posix/wordexp.c120
-rw-r--r--posix/wordexp.h2
255 files changed, 7832 insertions, 5162 deletions
diff --git a/posix/Makefile b/posix/Makefile
index f94e023c60..00c62841a2 100644
--- a/posix/Makefile
+++ b/posix/Makefile
@@ -1,4 +1,4 @@
-# Copyright (C) 1991-2016 Free Software Foundation, Inc.
+# Copyright (C) 1991-2018 Free Software Foundation, Inc.
# This file is part of the GNU C Library.
# The GNU C Library is free software; you can redistribute it and/or
@@ -23,13 +23,15 @@ subdir := posix
include ../Makeconfig
headers := sys/utsname.h sys/times.h sys/wait.h sys/types.h unistd.h \
- glob.h regex.h wordexp.h fnmatch.h getopt.h \
+ glob.h regex.h wordexp.h fnmatch.h \
+ getopt.h bits/getopt_core.h bits/getopt_ext.h bits/getopt_posix.h \
bits/types.h bits/typesizes.h bits/pthreadtypes.h \
+ bits/pthreadtypes-arch.h bits/thread-shared-types.h \
bits/posix1_lim.h bits/posix2_lim.h bits/posix_opt.h \
bits/local_lim.h tar.h bits/utsname.h bits/confname.h \
bits/waitflags.h bits/waitstatus.h sys/unistd.h sched.h \
- bits/sched.h re_comp.h wait.h bits/environments.h cpio.h \
- sys/sysmacros.h spawn.h bits/unistd.h
+ bits/sched.h bits/cpu-set.h re_comp.h wait.h bits/environments.h \
+ cpio.h spawn.h bits/unistd.h bits/types/struct_sched_param.h
routines := \
uname \
@@ -43,15 +45,16 @@ routines := \
getpgid setpgid getpgrp bsd-getpgrp setpgrp getsid setsid \
getresuid getresgid setresuid setresgid \
pathconf sysconf fpathconf \
- glob glob64 fnmatch regex \
+ glob glob64 globfree globfree64 glob_pattern_p fnmatch regex \
+ glob-lstat-compat glob64-lstat-compat \
confstr \
- getopt getopt1 getopt_init \
+ getopt getopt1 \
sched_setp sched_getp sched_sets sched_gets sched_yield sched_primax \
sched_primin sched_rr_gi sched_getaffinity sched_setaffinity \
getaddrinfo gai_strerror wordexp \
pread pwrite pread64 pwrite64 \
spawn_faction_init spawn_faction_destroy spawn_faction_addclose \
- spawn_faction_addopen spawn_faction_adddup2 \
+ spawn_faction_addopen spawn_faction_adddup2 spawn_valid_fd \
spawnattr_init spawnattr_destroy \
spawnattr_getdefault spawnattr_setdefault \
spawnattr_getflags spawnattr_setflags \
@@ -62,36 +65,48 @@ routines := \
get_child_max sched_cpucount sched_cpualloc sched_cpufree
aux := init-posix environ
-tests := tstgetopt testfnm runtests runptests \
+tests := test-errno tstgetopt testfnm runtests runptests \
tst-preadwrite tst-preadwrite64 test-vfork regexbug1 \
tst-mmap tst-mmap-offset tst-getaddrinfo tst-truncate \
tst-truncate64 tst-fork tst-fnmatch tst-regexloc tst-dir \
tst-chmod bug-regex1 bug-regex2 bug-regex3 bug-regex4 \
- tst-gnuglob tst-regex bug-regex5 bug-regex6 bug-regex7 \
+ tst-gnuglob tst-gnuglob64 tst-regex bug-regex6 bug-regex7 \
bug-regex8 bug-regex9 bug-regex10 bug-regex11 bug-regex12 \
bug-regex13 bug-regex14 bug-regex15 bug-regex16 \
- bug-regex17 bug-regex18 bug-regex19 bug-regex20 \
+ bug-regex17 bug-regex18 bug-regex19 \
bug-regex21 bug-regex22 bug-regex23 bug-regex24 \
bug-regex25 bug-regex26 bug-regex27 bug-regex28 \
bug-regex29 bug-regex30 bug-regex31 bug-regex32 \
- bug-regex33 tst-nice tst-nanosleep tst-regex2 \
+ tst-nice tst-nanosleep tst-regex2 \
transbug tst-rxspencer tst-pcre tst-boost \
bug-ga1 tst-vfork1 tst-vfork2 tst-vfork3 tst-waitid \
- tst-getaddrinfo2 bug-glob1 bug-glob2 bug-glob3 tst-sysconf \
+ tst-getaddrinfo2 bug-glob2 bug-glob3 tst-sysconf \
tst-execvp1 tst-execvp2 tst-execlp1 tst-execlp2 \
tst-execv1 tst-execv2 tst-execl1 tst-execl2 \
tst-execve1 tst-execve2 tst-execle1 tst-execle2 \
- tst-execvp3 tst-execvp4 tst-rfc3484 tst-rfc3484-2 \
- tst-rfc3484-3 \
+ tst-execvp3 tst-execvp4 \
+ tst-execvpe1 tst-execvpe2 tst-execvpe3 tst-execvpe4 \
+ tst-execvpe5 tst-execvpe6 \
tst-getaddrinfo3 tst-fnmatch2 tst-cpucount tst-cpuset \
bug-getopt1 bug-getopt2 bug-getopt3 bug-getopt4 \
bug-getopt5 tst-getopt_long1 bug-regex34 bug-regex35 \
- tst-pathconf tst-getaddrinfo4 tst-rxspencer-no-utf8 \
- tst-fnmatch3 bug-regex36 tst-getaddrinfo5
-xtests := bug-ga2
+ tst-pathconf tst-rxspencer-no-utf8 \
+ tst-fnmatch3 bug-regex36 \
+ tst-posix_spawn-fd tst-posix_spawn-setsid \
+ tst-posix_fadvise tst-posix_fadvise64 \
+ tst-sysconf-empty-chroot tst-glob_symlinks tst-fexecve \
+ tst-glob-tilde test-ssize-max tst-spawn4 bug-regex37 \
+ bug-regex38
+tests-internal := bug-regex5 bug-regex20 bug-regex33 \
+ tst-rfc3484 tst-rfc3484-2 tst-rfc3484-3 \
+ tst-glob_lstat_compat tst-spawn4-compat
+xtests := bug-ga2 tst-getaddrinfo4 tst-getaddrinfo5
ifeq (yes,$(build-shared))
test-srcs := globtest
-tests += wordexp-test tst-exec tst-spawn
+tests += wordexp-test tst-exec tst-spawn tst-spawn2 tst-spawn3
+endif
+ifeq (yesyes,$(build-shared)$(have-thread-library))
+tests += tst-getopt-cancel
endif
tests-static = tst-exec-static tst-spawn-static
tests += $(tests-static)
@@ -130,7 +145,8 @@ tests-special += $(objpfx)bug-regex2-mem.out $(objpfx)bug-regex14-mem.out \
$(objpfx)tst-rxspencer-no-utf8-mem.out $(objpfx)tst-pcre-mem.out \
$(objpfx)tst-boost-mem.out $(objpfx)tst-getconf.out \
$(objpfx)bug-glob2-mem.out $(objpfx)tst-vfork3-mem.out \
- $(objpfx)tst-fnmatch-mem.out $(objpfx)bug-regex36-mem.out
+ $(objpfx)tst-fnmatch-mem.out $(objpfx)bug-regex36-mem.out \
+ $(objpfx)tst-glob-tilde-mem.out
xtests-special += $(objpfx)bug-ga2-mem.out
endif
@@ -141,11 +157,11 @@ ifeq ($(run-built-tests),yes)
ifeq (yes,$(build-shared))
$(objpfx)globtest.out: globtest.sh $(objpfx)globtest
$(SHELL) $< $(common-objpfx) '$(test-via-rtld-prefix)' \
- '$(test-program-prefix)' '$(test-wrapper-env)'; \
+ '$(test-program-prefix)' '$(test-wrapper-env)' > $@; \
$(evaluate-test)
$(objpfx)wordexp-tst.out: wordexp-tst.sh $(objpfx)wordexp-test
$(SHELL) $< $(common-objpfx) '$(test-program-prefix-before-env)' \
- '$(run-program-env)' '$(test-program-prefix-after-env)'; \
+ '$(run-program-env)' '$(test-program-prefix-after-env)' > $@; \
$(evaluate-test)
endif
@@ -189,32 +205,31 @@ $(objpfx)config-name.h: $(..)scripts/config-uname.sh $(common-objpfx)config.make
'$(config-machine)-$(config-vendor)' > $@.new
mv -f $@.new $@
-CFLAGS-getaddrinfo.c = -DRESOLVER -fexceptions
-CFLAGS-pause.c = -fexceptions -fasynchronous-unwind-tables
-CFLAGS-pread.c = -fexceptions -fasynchronous-unwind-tables
-CFLAGS-pread64.c = -fexceptions -fasynchronous-unwind-tables
-CFLAGS-pwrite.c = -fexceptions -fasynchronous-unwind-tables
-CFLAGS-pwrite64.c = -fexceptions -fasynchronous-unwind-tables
-CFLAGS-sleep.c = -fexceptions
-CFLAGS-wait.c = -fexceptions -fasynchronous-unwind-tables
-CFLAGS-waitid.c = -fexceptions -fasynchronous-unwind-tables
-CFLAGS-waitpid.c = -fexceptions -fasynchronous-unwind-tables
-CFLAGS-getopt.c = -fexceptions
-CFLAGS-wordexp.c = -fexceptions
+CFLAGS-getaddrinfo.c += -DRESOLVER -fexceptions
+CFLAGS-pause.c += -fexceptions -fasynchronous-unwind-tables
+CFLAGS-pread.c += -fexceptions -fasynchronous-unwind-tables
+CFLAGS-pread64.c += -fexceptions -fasynchronous-unwind-tables
+CFLAGS-pwrite.c += -fexceptions -fasynchronous-unwind-tables
+CFLAGS-pwrite64.c += -fexceptions -fasynchronous-unwind-tables
+CFLAGS-sleep.c += -fexceptions
+CFLAGS-wait.c += -fexceptions -fasynchronous-unwind-tables
+CFLAGS-waitid.c += -fexceptions -fasynchronous-unwind-tables
+CFLAGS-waitpid.c += -fexceptions -fasynchronous-unwind-tables
+CFLAGS-getopt.c += -fexceptions
+CFLAGS-wordexp.c += -fexceptions
CFLAGS-wordexp.os = -fomit-frame-pointer
-CFLAGS-sysconf.c = -fexceptions -DGETCONF_DIR='"$(libexecdir)/getconf"'
-CFLAGS-pathconf.c = -fexceptions
-CFLAGS-fpathconf.c = -fexceptions
-CFLAGS-spawn.c = -fexceptions
+CFLAGS-sysconf.c += -fexceptions -DGETCONF_DIR='"$(libexecdir)/getconf"'
+CFLAGS-pathconf.c += -fexceptions
+CFLAGS-fpathconf.c += -fexceptions
+CFLAGS-spawn.c += -fexceptions
CFLAGS-spawn.os = -fomit-frame-pointer
-CFLAGS-spawnp.c = -fexceptions
+CFLAGS-spawnp.c += -fexceptions
CFLAGS-spawnp.os = -fomit-frame-pointer
-CFLAGS-spawni.c = -fexceptions
+CFLAGS-spawni.c += -fexceptions
CFLAGS-spawni.os = -fomit-frame-pointer
-CFLAGS-pause.c = -fexceptions
-CFLAGS-glob.c = $(uses-callbacks) -fexceptions
-CFLAGS-glob64.c = $(uses-callbacks) -fexceptions
-CFLAGS-getconf.c = -DGETCONF_DIR='"$(libexecdir)/getconf"'
+CFLAGS-glob.c += $(uses-callbacks) -fexceptions
+CFLAGS-glob64.c += $(uses-callbacks) -fexceptions
+CFLAGS-getconf.c += -DGETCONF_DIR='"$(libexecdir)/getconf"'
CFLAGS-execve.os = -fomit-frame-pointer
CFLAGS-fexecve.os = -fomit-frame-pointer
CFLAGS-execv.os = -fomit-frame-pointer
@@ -222,12 +237,14 @@ CFLAGS-execle.os = -fomit-frame-pointer
CFLAGS-execl.os = -fomit-frame-pointer
CFLAGS-execvp.os = -fomit-frame-pointer
CFLAGS-execlp.os = -fomit-frame-pointer
+CFLAGS-nanosleep.c += -fexceptions -fasynchronous-unwind-tables
tstgetopt-ARGS = -a -b -cfoobar --required foobar --optional=bazbug \
--none random --col --color --colour
tst-exec-ARGS = -- $(host-test-program-cmd)
tst-exec-static-ARGS = $(tst-exec-ARGS)
+tst-execvpe5-ARGS = -- $(host-test-program-cmd)
tst-spawn-ARGS = -- $(host-test-program-cmd)
tst-spawn-static-ARGS = $(tst-spawn-ARGS)
tst-dir-ARGS = `pwd` `cd $(common-objdir)/$(subdir); pwd` `cd $(common-objdir); pwd` $(objpfx)tst-dir
@@ -240,6 +257,7 @@ tst-pcre-ARGS = PCRE.tests
tst-boost-ARGS = BOOST.tests
bug-glob1-ARGS = "$(objpfx)"
tst-execvp3-ARGS = --test-dir=$(objpfx)
+CFLAGS-tst-spawn3.c += -DOBJPFX=\"$(objpfx)\"
testcases.h: TESTS TESTS2C.sed
LC_ALL=C sed -f TESTS2C.sed < $< > $@T
@@ -249,6 +267,8 @@ ptestcases.h: PTESTS PTESTS2C.sed
LC_ALL=C sed -f PTESTS2C.sed < $< > $@T
mv -f $@T $@
+$(objpfx)tst-getopt-cancel: $(shared-thread-library)
+
test-xfail-annexc = yes
$(objpfx)annexc.out: $(objpfx)annexc
$(dir $<)$(notdir $<) '$(CC)' \
@@ -321,7 +341,7 @@ $(objpfx)tst-boost-mem.out: $(objpfx)tst-boost.out
$(evaluate-test)
$(objpfx)tst-getconf.out: tst-getconf.sh $(objpfx)getconf
- $(SHELL) $< $(common-objpfx) '$(built-program-cmd)'; \
+ $(SHELL) $< $(common-objpfx) '$(built-program-cmd)' > $@; \
$(evaluate-test)
$(objpfx)bug-ga2-mem.out: $(objpfx)bug-ga2.out
@@ -336,6 +356,12 @@ $(objpfx)bug-glob2-mem.out: $(objpfx)bug-glob2.out
$(common-objpfx)malloc/mtrace $(objpfx)bug-glob2.mtrace > $@; \
$(evaluate-test)
+tst-glob-tilde-ENV = MALLOC_TRACE=$(objpfx)tst-glob-tilde.mtrace
+
+$(objpfx)tst-glob-tilde-mem.out: $(objpfx)tst-glob-tilde.out
+ $(common-objpfx)malloc/mtrace $(objpfx)tst-glob-tilde.mtrace > $@; \
+ $(evaluate-test)
+
$(inst_libexecdir)/getconf: $(inst_bindir)/getconf \
$(objpfx)getconf.speclist FORCE
$(addprefix $(..)./scripts/mkinstalldirs ,\
diff --git a/posix/PCRE.tests b/posix/PCRE.tests
index 0fb9cadafc..da63b86637 100644
--- a/posix/PCRE.tests
+++ b/posix/PCRE.tests
@@ -1774,19 +1774,6 @@ No match
0: abcabc
1: abc
-/(a)|\1/
- a
- 0: a
- 1: a
- *** Failers
- 0: a
- 1: a
- ab
- 0: a
- 1: a
- x
-No match
-
/abc/i
ABC
0: ABC
diff --git a/posix/Versions b/posix/Versions
index bb481a505b..cad4c23e8c 100644
--- a/posix/Versions
+++ b/posix/Versions
@@ -134,7 +134,11 @@ libc {
GLIBC_2.11 {
execvpe;
}
+ GLIBC_2.27 {
+ glob; glob64;
+ }
GLIBC_PRIVATE {
__libc_fork; __libc_pread; __libc_pwrite;
+ __nanosleep_nocancel; __pause_nocancel;
}
}
diff --git a/posix/_exit.c b/posix/_exit.c
index e79916f677..9ea1bf52d8 100644
--- a/posix/_exit.c
+++ b/posix/_exit.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/posix/alarm.c b/posix/alarm.c
index 7defa4b97a..dd08de2f26 100644
--- a/posix/alarm.c
+++ b/posix/alarm.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/posix/annexc.c b/posix/annexc.c
index c87363b33c..66768dbe2a 100644
--- a/posix/annexc.c
+++ b/posix/annexc.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1998-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1998-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -26,7 +26,7 @@
#define HEADER_MAX 256
-static const char *macrofile;
+static char macrofile[] = "/tmp/annexc.XXXXXX";
/* <aio.h>. */
static const char *const aio_syms[] =
@@ -657,6 +657,8 @@ main (int argc, char *argv[])
for (h = 0; h < NUMBER_OF_HEADERS; ++h)
result |= check_header (&headers[h], ignore_list);
+ remove (macrofile);
+
/* The test suite should return errors but for now this is not
practical. Give a warning and ask the user to correct the bugs. */
return result;
@@ -712,7 +714,13 @@ get_null_defines (void)
FILE *input;
int first = 1;
- macrofile = tmpnam (NULL);
+ int fd = mkstemp (macrofile);
+ if (fd == -1)
+ {
+ printf ("mkstemp failed: %m\n");
+ exit (1);
+ }
+ close (fd);
command = malloc (sizeof fmt + sizeof "/dev/null" + 2 * strlen (CC)
+ strlen (INC) + strlen (macrofile));
@@ -784,7 +792,6 @@ get_null_defines (void)
}
result[result_len] = NULL;
fclose (input);
- remove (macrofile);
return (const char **) result;
}
@@ -879,7 +886,6 @@ check_header (const struct header *header, const char **except)
result |= 1;
}
fclose (input);
- remove (macrofile);
for (i = 0; i < header->nsyms; ++i)
if (found[i] == 0)
diff --git a/posix/bits/cpu-set.h b/posix/bits/cpu-set.h
new file mode 100644
index 0000000000..c5e919e862
--- /dev/null
+++ b/posix/bits/cpu-set.h
@@ -0,0 +1,124 @@
+/* Definition of the cpu_set_t structure used by the POSIX 1003.1b-1993
+ scheduling interface.
+ Copyright (C) 1996-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _BITS_CPU_SET_H
+#define _BITS_CPU_SET_H 1
+
+#ifndef _SCHED_H
+# error "Never include <bits/cpu-set.h> directly; use <sched.h> instead."
+#endif
+
+/* Size definition for CPU sets. */
+#define __CPU_SETSIZE 1024
+#define __NCPUBITS (8 * sizeof (__cpu_mask))
+
+/* Type for array elements in 'cpu_set_t'. */
+typedef __CPU_MASK_TYPE __cpu_mask;
+
+/* Basic access functions. */
+#define __CPUELT(cpu) ((cpu) / __NCPUBITS)
+#define __CPUMASK(cpu) ((__cpu_mask) 1 << ((cpu) % __NCPUBITS))
+
+/* Data structure to describe CPU mask. */
+typedef struct
+{
+ __cpu_mask __bits[__CPU_SETSIZE / __NCPUBITS];
+} cpu_set_t;
+
+/* Access functions for CPU masks. */
+#if __GNUC_PREREQ (2, 91)
+# define __CPU_ZERO_S(setsize, cpusetp) \
+ do __builtin_memset (cpusetp, '\0', setsize); while (0)
+#else
+# define __CPU_ZERO_S(setsize, cpusetp) \
+ do { \
+ size_t __i; \
+ size_t __imax = (setsize) / sizeof (__cpu_mask); \
+ __cpu_mask *__bits = (cpusetp)->__bits; \
+ for (__i = 0; __i < __imax; ++__i) \
+ __bits[__i] = 0; \
+ } while (0)
+#endif
+#define __CPU_SET_S(cpu, setsize, cpusetp) \
+ (__extension__ \
+ ({ size_t __cpu = (cpu); \
+ __cpu / 8 < (setsize) \
+ ? (((__cpu_mask *) ((cpusetp)->__bits))[__CPUELT (__cpu)] \
+ |= __CPUMASK (__cpu)) \
+ : 0; }))
+#define __CPU_CLR_S(cpu, setsize, cpusetp) \
+ (__extension__ \
+ ({ size_t __cpu = (cpu); \
+ __cpu / 8 < (setsize) \
+ ? (((__cpu_mask *) ((cpusetp)->__bits))[__CPUELT (__cpu)] \
+ &= ~__CPUMASK (__cpu)) \
+ : 0; }))
+#define __CPU_ISSET_S(cpu, setsize, cpusetp) \
+ (__extension__ \
+ ({ size_t __cpu = (cpu); \
+ __cpu / 8 < (setsize) \
+ ? ((((const __cpu_mask *) ((cpusetp)->__bits))[__CPUELT (__cpu)] \
+ & __CPUMASK (__cpu))) != 0 \
+ : 0; }))
+
+#define __CPU_COUNT_S(setsize, cpusetp) \
+ __sched_cpucount (setsize, cpusetp)
+
+#if __GNUC_PREREQ (2, 91)
+# define __CPU_EQUAL_S(setsize, cpusetp1, cpusetp2) \
+ (__builtin_memcmp (cpusetp1, cpusetp2, setsize) == 0)
+#else
+# define __CPU_EQUAL_S(setsize, cpusetp1, cpusetp2) \
+ (__extension__ \
+ ({ const __cpu_mask *__arr1 = (cpusetp1)->__bits; \
+ const __cpu_mask *__arr2 = (cpusetp2)->__bits; \
+ size_t __imax = (setsize) / sizeof (__cpu_mask); \
+ size_t __i; \
+ for (__i = 0; __i < __imax; ++__i) \
+ if (__arr1[__i] != __arr2[__i]) \
+ break; \
+ __i == __imax; }))
+#endif
+
+#define __CPU_OP_S(setsize, destset, srcset1, srcset2, op) \
+ (__extension__ \
+ ({ cpu_set_t *__dest = (destset); \
+ const __cpu_mask *__arr1 = (srcset1)->__bits; \
+ const __cpu_mask *__arr2 = (srcset2)->__bits; \
+ size_t __imax = (setsize) / sizeof (__cpu_mask); \
+ size_t __i; \
+ for (__i = 0; __i < __imax; ++__i) \
+ ((__cpu_mask *) __dest->__bits)[__i] = __arr1[__i] op __arr2[__i]; \
+ __dest; }))
+
+#define __CPU_ALLOC_SIZE(count) \
+ ((((count) + __NCPUBITS - 1) / __NCPUBITS) * sizeof (__cpu_mask))
+#define __CPU_ALLOC(count) __sched_cpualloc (count)
+#define __CPU_FREE(cpuset) __sched_cpufree (cpuset)
+
+__BEGIN_DECLS
+
+extern int __sched_cpucount (size_t __setsize, const cpu_set_t *__setp)
+ __THROW;
+extern cpu_set_t *__sched_cpualloc (size_t __count) __THROW __wur;
+extern void __sched_cpufree (cpu_set_t *__set) __THROW;
+
+__END_DECLS
+
+#endif /* bits/cpu-set.h */
diff --git a/posix/bits/getopt_core.h b/posix/bits/getopt_core.h
new file mode 100644
index 0000000000..a13838faa8
--- /dev/null
+++ b/posix/bits/getopt_core.h
@@ -0,0 +1,96 @@
+/* Declarations for getopt (basic, portable features only).
+ Copyright (C) 1989-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library and is also part of gnulib.
+ Patches to this file should be submitted to both projects.
+
+ 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _GETOPT_CORE_H
+#define _GETOPT_CORE_H 1
+
+/* This header should not be used directly; include getopt.h or
+ unistd.h instead. Unlike most bits headers, it does not have
+ a protective #error, because the guard macro for getopt.h in
+ gnulib is not fixed. */
+
+__BEGIN_DECLS
+
+/* For communication from 'getopt' to the caller.
+ When 'getopt' finds an option that takes an argument,
+ the argument value is returned here.
+ Also, when 'ordering' is RETURN_IN_ORDER,
+ each non-option ARGV-element is returned here. */
+
+extern char *optarg;
+
+/* Index in ARGV of the next element to be scanned.
+ This is used for communication to and from the caller
+ and for communication between successive calls to 'getopt'.
+
+ On entry to 'getopt', zero means this is the first call; initialize.
+
+ When 'getopt' returns -1, this is the index of the first of the
+ non-option elements that the caller should itself scan.
+
+ Otherwise, 'optind' communicates from one call to the next
+ how much of ARGV has been scanned so far. */
+
+extern int optind;
+
+/* Callers store zero here to inhibit the error message 'getopt' prints
+ for unrecognized options. */
+
+extern int opterr;
+
+/* Set to an option character which was unrecognized. */
+
+extern int optopt;
+
+/* Get definitions and prototypes for functions to process the
+ arguments in ARGV (ARGC of them, minus the program name) for
+ options given in OPTS.
+
+ Return the option character from OPTS just read. Return -1 when
+ there are no more options. For unrecognized options, or options
+ missing arguments, 'optopt' is set to the option letter, and '?' is
+ returned.
+
+ The OPTS string is a list of characters which are recognized option
+ letters, optionally followed by colons, specifying that that letter
+ takes an argument, to be placed in 'optarg'.
+
+ If a letter in OPTS is followed by two colons, its argument is
+ optional. This behavior is specific to the GNU 'getopt'.
+
+ The argument '--' causes premature termination of argument
+ scanning, explicitly telling 'getopt' that there are no more
+ options.
+
+ If OPTS begins with '-', then non-option arguments are treated as
+ arguments to the option '\1'. This behavior is specific to the GNU
+ 'getopt'. If OPTS begins with '+', or POSIXLY_CORRECT is set in
+ the environment, then do not permute arguments.
+
+ For standards compliance, the 'argv' argument has the type
+ char *const *, but this is inaccurate; if argument permutation is
+ enabled, the argv array (not the strings it points to) must be
+ writable. */
+
+extern int getopt (int ___argc, char *const *___argv, const char *__shortopts)
+ __THROW __nonnull ((2, 3));
+
+__END_DECLS
+
+#endif /* getopt_core.h */
diff --git a/posix/bits/getopt_ext.h b/posix/bits/getopt_ext.h
new file mode 100644
index 0000000000..b4c68f1748
--- /dev/null
+++ b/posix/bits/getopt_ext.h
@@ -0,0 +1,77 @@
+/* Declarations for getopt (GNU extensions).
+ Copyright (C) 1989-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library and is also part of gnulib.
+ Patches to this file should be submitted to both projects.
+
+ 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _GETOPT_EXT_H
+#define _GETOPT_EXT_H 1
+
+/* This header should not be used directly; include getopt.h instead.
+ Unlike most bits headers, it does not have a protective #error,
+ because the guard macro for getopt.h in gnulib is not fixed. */
+
+__BEGIN_DECLS
+
+/* Describe the long-named options requested by the application.
+ The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
+ of 'struct option' terminated by an element containing a name which is
+ zero.
+
+ The field 'has_arg' is:
+ no_argument (or 0) if the option does not take an argument,
+ required_argument (or 1) if the option requires an argument,
+ optional_argument (or 2) if the option takes an optional argument.
+
+ If the field 'flag' is not NULL, it points to a variable that is set
+ to the value given in the field 'val' when the option is found, but
+ left unchanged if the option is not found.
+
+ To have a long-named option do something other than set an 'int' to
+ a compiled-in constant, such as set a value from 'optarg', set the
+ option's 'flag' field to zero and its 'val' field to a nonzero
+ value (the equivalent single-letter option character, if there is
+ one). For long options that have a zero 'flag' field, 'getopt'
+ returns the contents of the 'val' field. */
+
+struct option
+{
+ const char *name;
+ /* has_arg can't be an enum because some compilers complain about
+ type mismatches in all the code that assumes it is an int. */
+ int has_arg;
+ int *flag;
+ int val;
+};
+
+/* Names for the values of the 'has_arg' field of 'struct option'. */
+
+#define no_argument 0
+#define required_argument 1
+#define optional_argument 2
+
+extern int getopt_long (int ___argc, char *__getopt_argv_const *___argv,
+ const char *__shortopts,
+ const struct option *__longopts, int *__longind)
+ __THROW __nonnull ((2, 3));
+extern int getopt_long_only (int ___argc, char *__getopt_argv_const *___argv,
+ const char *__shortopts,
+ const struct option *__longopts, int *__longind)
+ __THROW __nonnull ((2, 3));
+
+__END_DECLS
+
+#endif /* getopt_ext.h */
diff --git a/posix/bits/getopt_posix.h b/posix/bits/getopt_posix.h
new file mode 100644
index 0000000000..1f90e84cba
--- /dev/null
+++ b/posix/bits/getopt_posix.h
@@ -0,0 +1,51 @@
+/* Declarations for getopt (POSIX compatibility shim).
+ Copyright (C) 1989-2018 Free Software Foundation, Inc.
+ Unlike the bulk of the getopt implementation, this file is NOT part
+ of gnulib.
+
+ 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _GETOPT_POSIX_H
+#define _GETOPT_POSIX_H 1
+
+#if !defined _UNISTD_H && !defined _STDIO_H
+#error "Never include getopt_posix.h directly; use unistd.h instead."
+#endif
+
+#include <bits/getopt_core.h>
+
+__BEGIN_DECLS
+
+#if defined __USE_POSIX2 && !defined __USE_POSIX_IMPLICITLY \
+ && !defined __USE_GNU && !defined _GETOPT_H
+/* GNU getopt has more functionality than POSIX getopt. When we are
+ explicitly conforming to POSIX and not GNU, and getopt.h (which is
+ not part of POSIX) has not been included, the extra functionality
+ is disabled. */
+# ifdef __REDIRECT
+extern int __REDIRECT_NTH (getopt, (int ___argc, char *const *___argv,
+ const char *__shortopts),
+ __posix_getopt);
+# else
+extern int __posix_getopt (int ___argc, char *const *___argv,
+ const char *__shortopts)
+ __THROW __nonnull ((2, 3));
+# define getopt __posix_getopt
+# endif
+#endif
+
+__END_DECLS
+
+#endif /* getopt_posix.h */
diff --git a/posix/bits/posix1_lim.h b/posix/bits/posix1_lim.h
index b0a37bdb0e..18ac47fb2b 100644
--- a/posix/bits/posix1_lim.h
+++ b/posix/bits/posix1_lim.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -24,6 +24,7 @@
#ifndef _BITS_POSIX1_LIM_H
#define _BITS_POSIX1_LIM_H 1
+#include <bits/wordsize.h>
/* These are the standard-mandated minimum values. */
@@ -161,7 +162,14 @@
#ifndef SSIZE_MAX
-# define SSIZE_MAX LONG_MAX
+/* ssize_t is not formally required to be the signed type
+ corresponding to size_t, but it is for all configurations supported
+ by glibc. */
+# if __WORDSIZE == 64 || __WORDSIZE32_SIZE_ULONG
+# define SSIZE_MAX LONG_MAX
+# else
+# define SSIZE_MAX INT_MAX
+# endif
#endif
diff --git a/posix/bits/posix2_lim.h b/posix/bits/posix2_lim.h
index 819af363f9..c460ea266f 100644
--- a/posix/bits/posix2_lim.h
+++ b/posix/bits/posix2_lim.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/posix/bits/types.h b/posix/bits/types.h
new file mode 100644
index 0000000000..5e22ce41bf
--- /dev/null
+++ b/posix/bits/types.h
@@ -0,0 +1,216 @@
+/* bits/types.h -- definitions of __*_t types underlying *_t types.
+ Copyright (C) 2002-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+/*
+ * Never include this file directly; use <sys/types.h> instead.
+ */
+
+#ifndef _BITS_TYPES_H
+#define _BITS_TYPES_H 1
+
+#include <features.h>
+#include <bits/wordsize.h>
+
+/* Convenience types. */
+typedef unsigned char __u_char;
+typedef unsigned short int __u_short;
+typedef unsigned int __u_int;
+typedef unsigned long int __u_long;
+
+/* Fixed-size types, underlying types depend on word size and compiler. */
+typedef signed char __int8_t;
+typedef unsigned char __uint8_t;
+typedef signed short int __int16_t;
+typedef unsigned short int __uint16_t;
+typedef signed int __int32_t;
+typedef unsigned int __uint32_t;
+#if __WORDSIZE == 64
+typedef signed long int __int64_t;
+typedef unsigned long int __uint64_t;
+#else
+__extension__ typedef signed long long int __int64_t;
+__extension__ typedef unsigned long long int __uint64_t;
+#endif
+
+/* Smallest types with at least a given width. */
+typedef __int8_t __int_least8_t;
+typedef __uint8_t __uint_least8_t;
+typedef __int16_t __int_least16_t;
+typedef __uint16_t __uint_least16_t;
+typedef __int32_t __int_least32_t;
+typedef __uint32_t __uint_least32_t;
+typedef __int64_t __int_least64_t;
+typedef __uint64_t __uint_least64_t;
+
+/* quad_t is also 64 bits. */
+#if __WORDSIZE == 64
+typedef long int __quad_t;
+typedef unsigned long int __u_quad_t;
+#else
+__extension__ typedef long long int __quad_t;
+__extension__ typedef unsigned long long int __u_quad_t;
+#endif
+
+/* Largest integral types. */
+#if __WORDSIZE == 64
+typedef long int __intmax_t;
+typedef unsigned long int __uintmax_t;
+#else
+__extension__ typedef long long int __intmax_t;
+__extension__ typedef unsigned long long int __uintmax_t;
+#endif
+
+
+/* The machine-dependent file <bits/typesizes.h> defines __*_T_TYPE
+ macros for each of the OS types we define below. The definitions
+ of those macros must use the following macros for underlying types.
+ We define __S<SIZE>_TYPE and __U<SIZE>_TYPE for the signed and unsigned
+ variants of each of the following integer types on this machine.
+
+ 16 -- "natural" 16-bit type (always short)
+ 32 -- "natural" 32-bit type (always int)
+ 64 -- "natural" 64-bit type (long or long long)
+ LONG32 -- 32-bit type, traditionally long
+ QUAD -- 64-bit type, always long long
+ WORD -- natural type of __WORDSIZE bits (int or long)
+ LONGWORD -- type of __WORDSIZE bits, traditionally long
+
+ We distinguish WORD/LONGWORD, 32/LONG32, and 64/QUAD so that the
+ conventional uses of `long' or `long long' type modifiers match the
+ types we define, even when a less-adorned type would be the same size.
+ This matters for (somewhat) portably writing printf/scanf formats for
+ these types, where using the appropriate l or ll format modifiers can
+ make the typedefs and the formats match up across all GNU platforms. If
+ we used `long' when it's 64 bits where `long long' is expected, then the
+ compiler would warn about the formats not matching the argument types,
+ and the programmer changing them to shut up the compiler would break the
+ program's portability.
+
+ Here we assume what is presently the case in all the GCC configurations
+ we support: long long is always 64 bits, long is always word/address size,
+ and int is always 32 bits. */
+
+#define __S16_TYPE short int
+#define __U16_TYPE unsigned short int
+#define __S32_TYPE int
+#define __U32_TYPE unsigned int
+#define __SLONGWORD_TYPE long int
+#define __ULONGWORD_TYPE unsigned long int
+#if __WORDSIZE == 32
+# define __SQUAD_TYPE __quad_t
+# define __UQUAD_TYPE __u_quad_t
+# define __SWORD_TYPE int
+# define __UWORD_TYPE unsigned int
+# define __SLONG32_TYPE long int
+# define __ULONG32_TYPE unsigned long int
+# define __S64_TYPE __quad_t
+# define __U64_TYPE __u_quad_t
+/* We want __extension__ before typedef's that use nonstandard base types
+ such as `long long' in C89 mode. */
+# define __STD_TYPE __extension__ typedef
+#elif __WORDSIZE == 64
+# define __SQUAD_TYPE long int
+# define __UQUAD_TYPE unsigned long int
+# define __SWORD_TYPE long int
+# define __UWORD_TYPE unsigned long int
+# define __SLONG32_TYPE int
+# define __ULONG32_TYPE unsigned int
+# define __S64_TYPE long int
+# define __U64_TYPE unsigned long int
+/* No need to mark the typedef with __extension__. */
+# define __STD_TYPE typedef
+#else
+# error
+#endif
+#include <bits/typesizes.h> /* Defines __*_T_TYPE macros. */
+
+
+__STD_TYPE __DEV_T_TYPE __dev_t; /* Type of device numbers. */
+__STD_TYPE __UID_T_TYPE __uid_t; /* Type of user identifications. */
+__STD_TYPE __GID_T_TYPE __gid_t; /* Type of group identifications. */
+__STD_TYPE __INO_T_TYPE __ino_t; /* Type of file serial numbers. */
+__STD_TYPE __INO64_T_TYPE __ino64_t; /* Type of file serial numbers (LFS).*/
+__STD_TYPE __MODE_T_TYPE __mode_t; /* Type of file attribute bitmasks. */
+__STD_TYPE __NLINK_T_TYPE __nlink_t; /* Type of file link counts. */
+__STD_TYPE __OFF_T_TYPE __off_t; /* Type of file sizes and offsets. */
+__STD_TYPE __OFF64_T_TYPE __off64_t; /* Type of file sizes and offsets (LFS). */
+__STD_TYPE __PID_T_TYPE __pid_t; /* Type of process identifications. */
+__STD_TYPE __FSID_T_TYPE __fsid_t; /* Type of file system IDs. */
+__STD_TYPE __CLOCK_T_TYPE __clock_t; /* Type of CPU usage counts. */
+__STD_TYPE __RLIM_T_TYPE __rlim_t; /* Type for resource measurement. */
+__STD_TYPE __RLIM64_T_TYPE __rlim64_t; /* Type for resource measurement (LFS). */
+__STD_TYPE __ID_T_TYPE __id_t; /* General type for IDs. */
+__STD_TYPE __TIME_T_TYPE __time_t; /* Seconds since the Epoch. */
+__STD_TYPE __USECONDS_T_TYPE __useconds_t; /* Count of microseconds. */
+__STD_TYPE __SUSECONDS_T_TYPE __suseconds_t; /* Signed count of microseconds. */
+
+__STD_TYPE __DADDR_T_TYPE __daddr_t; /* The type of a disk address. */
+__STD_TYPE __KEY_T_TYPE __key_t; /* Type of an IPC key. */
+
+/* Clock ID used in clock and timer functions. */
+__STD_TYPE __CLOCKID_T_TYPE __clockid_t;
+
+/* Timer ID returned by `timer_create'. */
+__STD_TYPE __TIMER_T_TYPE __timer_t;
+
+/* Type to represent block size. */
+__STD_TYPE __BLKSIZE_T_TYPE __blksize_t;
+
+/* Types from the Large File Support interface. */
+
+/* Type to count number of disk blocks. */
+__STD_TYPE __BLKCNT_T_TYPE __blkcnt_t;
+__STD_TYPE __BLKCNT64_T_TYPE __blkcnt64_t;
+
+/* Type to count file system blocks. */
+__STD_TYPE __FSBLKCNT_T_TYPE __fsblkcnt_t;
+__STD_TYPE __FSBLKCNT64_T_TYPE __fsblkcnt64_t;
+
+/* Type to count file system nodes. */
+__STD_TYPE __FSFILCNT_T_TYPE __fsfilcnt_t;
+__STD_TYPE __FSFILCNT64_T_TYPE __fsfilcnt64_t;
+
+/* Type of miscellaneous file system fields. */
+__STD_TYPE __FSWORD_T_TYPE __fsword_t;
+
+__STD_TYPE __SSIZE_T_TYPE __ssize_t; /* Type of a byte count, or error. */
+
+/* Signed long type used in system calls. */
+__STD_TYPE __SYSCALL_SLONG_TYPE __syscall_slong_t;
+/* Unsigned long type used in system calls. */
+__STD_TYPE __SYSCALL_ULONG_TYPE __syscall_ulong_t;
+
+/* These few don't really vary by system, they always correspond
+ to one of the other defined types. */
+typedef __off64_t __loff_t; /* Type of file sizes and offsets (LFS). */
+typedef char *__caddr_t;
+
+/* Duplicates info from stdint.h but this is used in unistd.h. */
+__STD_TYPE __SWORD_TYPE __intptr_t;
+
+/* Duplicate info from sys/socket.h. */
+__STD_TYPE __U32_TYPE __socklen_t;
+
+/* C99: An integer type that can be accessed as an atomic entity,
+ even in the presence of asynchronous interrupts.
+ It is not currently necessary for this to be machine-specific. */
+typedef int __sig_atomic_t;
+
+#undef __STD_TYPE
+
+#endif /* bits/types.h */
diff --git a/posix/bits/unistd.h b/posix/bits/unistd.h
index 0105f04f20..9a749dccf8 100644
--- a/posix/bits/unistd.h
+++ b/posix/bits/unistd.h
@@ -1,5 +1,5 @@
/* Checking macros for unistd functions.
- Copyright (C) 2005-2016 Free Software Foundation, Inc.
+ Copyright (C) 2005-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -302,7 +302,7 @@ __NTH (ttyname_r (int __fd, char *__buf, size_t __buflen))
}
-#if defined __USE_REENTRANT || defined __USE_POSIX199506
+#ifdef __USE_POSIX199506
extern int __getlogin_r_chk (char *__buf, size_t __buflen, size_t __nreal)
__nonnull ((1));
extern int __REDIRECT (__getlogin_r_alias, (char *__buf, size_t __buflen),
diff --git a/posix/bsd-getpgrp.c b/posix/bsd-getpgrp.c
index 1f86341f7b..195b882711 100644
--- a/posix/bsd-getpgrp.c
+++ b/posix/bsd-getpgrp.c
@@ -1,5 +1,5 @@
/* BSD-compatible versions of getpgrp function.
- Copyright (C) 1991-2016 Free Software Foundation, Inc.
+ Copyright (C) 1991-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/posix/bug-getopt1.c b/posix/bug-getopt1.c
index a47dc7e229..a5a37116d2 100644
--- a/posix/bug-getopt1.c
+++ b/posix/bug-getopt1.c
@@ -1,6 +1,7 @@
/* BZ 11039 */
#include <unistd.h>
#include <stdio.h>
+#include <stdlib.h>
static int
one_test (const char *fmt, int argc, char *argv[], int expected[argc - 1])
@@ -39,12 +40,14 @@ one_test (const char *fmt, int argc, char *argv[], int expected[argc - 1])
static int
do_test (void)
{
- char *fname = tmpnam (NULL);
- if (fname == NULL)
+ char fname[] = "/tmp/bug-getopt1.XXXXXX";
+ int fd = mkstemp (fname);
+ if (fd == -1)
{
- puts ("cannot generate name for temporary file");
+ printf ("mkstemp failed: %m\n");
return 1;
}
+ close (fd);
if (freopen (fname, "w+", stderr) == NULL)
{
diff --git a/posix/bug-getopt2.c b/posix/bug-getopt2.c
index 93c3035ccd..8f92f0c6ee 100644
--- a/posix/bug-getopt2.c
+++ b/posix/bug-getopt2.c
@@ -1,6 +1,7 @@
/* BZ 11039 */
#include <unistd.h>
#include <stdio.h>
+#include <stdlib.h>
static int
one_test (const char *fmt, int argc, char *argv[], int expected[argc - 1])
@@ -37,12 +38,14 @@ one_test (const char *fmt, int argc, char *argv[], int expected[argc - 1])
static int
do_test (void)
{
- char *fname = tmpnam (NULL);
- if (fname == NULL)
+ char fname[] = "/tmp/bug-getopt2.XXXXXX";
+ int fd = mkstemp (fname);
+ if (fd == -1)
{
- puts ("cannot generate name for temporary file");
+ printf ("mkstemp failed: %m\n");
return 1;
}
+ close (fd);
if (freopen (fname, "w+", stderr) == NULL)
{
diff --git a/posix/bug-getopt3.c b/posix/bug-getopt3.c
index c3a8cb225b..45a8d3ec3d 100644
--- a/posix/bug-getopt3.c
+++ b/posix/bug-getopt3.c
@@ -2,6 +2,7 @@
#include <getopt.h>
#include <unistd.h>
#include <stdio.h>
+#include <stdlib.h>
static const struct option opts[] =
{
@@ -48,12 +49,14 @@ one_test (const char *fmt, int argc, char *argv[], int n, int expected[n],
static int
do_test (void)
{
- char *fname = tmpnam (NULL);
- if (fname == NULL)
+ char fname[] = "/tmp/bug-getopt3.XXXXXX";
+ int fd = mkstemp (fname);
+ if (fd == -1)
{
- puts ("cannot generate name for temporary file");
+ printf ("mkstemp failed: %m\n");
return 1;
}
+ close (fd);
if (freopen (fname, "w+", stderr) == NULL)
{
diff --git a/posix/bug-getopt4.c b/posix/bug-getopt4.c
index 1daffd1d34..c5e3c1497a 100644
--- a/posix/bug-getopt4.c
+++ b/posix/bug-getopt4.c
@@ -2,6 +2,7 @@
#include <getopt.h>
#include <unistd.h>
#include <stdio.h>
+#include <stdlib.h>
static const struct option opts[] =
{
@@ -27,20 +28,20 @@ one_test (const char *fmt, int argc, char *argv[], int n, int expected[n])
int c = getopt_long (argc, argv, fmt, opts, NULL);
if (c != expected[i])
{
- printf ("format '%s' test %d failed: expected '%c', got '%c'\n",
- fmt, i, expected[i], c);
+ printf ("%s: format '%s' test %d failed: expected '%c', got '%c'\n",
+ argv[0], fmt, i, expected[i], c);
res = 1;
}
else if (optarg != NULL)
{
- printf ("format '%s' test %d failed: optarg is \"%s\", not NULL\n",
- fmt, i, optarg);
+ printf ("%s: format '%s' test %d failed: optarg is \"%s\", not NULL\n",
+ argv[0], fmt, i, optarg);
res = 1;
}
if (ftell (stderr) != 0)
{
- printf ("format '%s' test %d failed: printed to stderr\n",
- fmt, i);
+ printf ("%s: format '%s' test %d failed: printed to stderr\n",
+ argv[0], fmt, i);
res = 1;
}
}
@@ -52,12 +53,14 @@ one_test (const char *fmt, int argc, char *argv[], int n, int expected[n])
static int
do_test (void)
{
- char *fname = tmpnam (NULL);
- if (fname == NULL)
+ char fname[] = "/tmp/bug-getopt4.XXXXXX";
+ int fd = mkstemp (fname);
+ if (fd == -1)
{
- puts ("cannot generate name for temporary file");
+ printf ("mkstemp failed: %m\n");
return 1;
}
+ close (fd);
if (freopen (fname, "w+", stderr) == NULL)
{
@@ -68,11 +71,11 @@ do_test (void)
remove (fname);
int ret = one_test ("W;", 2,
- (char *[2]) { (char *) "bug-getopt4", (char *) "--a" },
+ (char *[2]) { (char *) "bug-getopt4a", (char *) "--a" },
1, (int [1]) { 'a' });
ret |= one_test ("W;", 3,
- (char *[3]) { (char *) "bug-getopt4", (char *) "-W",
+ (char *[3]) { (char *) "bug-getopt4b", (char *) "-W",
(char *) "a" },
1, (int [1]) { 'a' });
diff --git a/posix/bug-getopt5.c b/posix/bug-getopt5.c
index ed2639d35b..4f67d9b2ec 100644
--- a/posix/bug-getopt5.c
+++ b/posix/bug-getopt5.c
@@ -2,6 +2,7 @@
#include <getopt.h>
#include <unistd.h>
#include <stdio.h>
+#include <stdlib.h>
static const struct option opts[] =
{
@@ -47,12 +48,14 @@ one_test (const char *fmt, int argc, char *argv[], int n, int expected[n])
static int
do_test (void)
{
- char *fname = tmpnam (NULL);
- if (fname == NULL)
+ char fname[] = "/tmp/bug-getopt5.XXXXXX";
+ int fd = mkstemp (fname);
+ if (fd == -1)
{
- puts ("cannot generate name for temporary file");
+ printf ("mkstemp failed: %m\n");
return 1;
}
+ close (fd);
if (freopen (fname, "w+", stderr) == NULL)
{
diff --git a/posix/bug-glob1.c b/posix/bug-glob1.c
deleted file mode 100644
index 05c2da7584..0000000000
--- a/posix/bug-glob1.c
+++ /dev/null
@@ -1,88 +0,0 @@
-/* Test case for globbing dangling symlink. By Ulrich Drepper. */
-#include <errno.h>
-#include <error.h>
-#include <glob.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-
-static void prepare (int argc, char *argv[]);
-#define PREPARE prepare
-static int do_test (void);
-#define TEST_FUNCTION do_test ()
-
-#include "../test-skeleton.c"
-
-
-static char *fname;
-
-static void
-prepare (int argc, char *argv[])
-{
- if (argc < 2)
- error (EXIT_FAILURE, 0, "missing argument");
-
- size_t len = strlen (argv[1]);
- static const char ext[] = "globXXXXXX";
- fname = malloc (len + sizeof (ext));
- if (fname == NULL)
- error (EXIT_FAILURE, errno, "cannot create temp file");
- again:
- strcpy (stpcpy (fname, argv[1]), ext);
- fname = mktemp (fname);
- if (fname == NULL || *fname == '\0')
- error (EXIT_FAILURE, errno, "cannot create temp file name");
- if (symlink ("bug-glob1-does-not-exist", fname) != 0)
- {
- if (errno == EEXIST)
- goto again;
-
- error (EXIT_FAILURE, errno, "cannot create symlink");
- }
- add_temp_file (fname);
-}
-
-
-static int
-do_test (void)
-{
- glob_t gl;
- int retval = 0;
- int e;
-
- e = glob (fname, 0, NULL, &gl);
- if (e == 0)
- {
- printf ("glob(\"%s\") succeeded\n", fname);
- retval = 1;
- }
- globfree (&gl);
-
- size_t fnamelen = strlen (fname);
- char buf[fnamelen + 2];
-
- strcpy (buf, fname);
- buf[fnamelen - 1] = '?';
- e = glob (buf, 0, NULL, &gl);
- if (e == 0)
- {
- printf ("glob(\"%s\") succeeded\n", buf);
- retval = 1;
- }
- globfree (&gl);
-
- strcpy (buf, fname);
- buf[fnamelen] = '*';
- buf[fnamelen + 1] = '\0';
- e = glob (buf, 0, NULL, &gl);
- if (e == 0)
- {
- printf ("glob(\"%s\") succeeded\n", buf);
- retval = 1;
- }
- globfree (&gl);
-
- return retval;
-}
diff --git a/posix/bug-glob2.c b/posix/bug-glob2.c
index ddf5ec913b..417568c043 100644
--- a/posix/bug-glob2.c
+++ b/posix/bug-glob2.c
@@ -1,6 +1,6 @@
/* Test glob memory management.
for the filesystem access functions.
- Copyright (C) 2001-2016 Free Software Foundation, Inc.
+ Copyright (C) 2001-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -40,6 +40,17 @@
# define PRINTF(fmt, args...)
#endif
+#define LONG_NAME \
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
static struct
{
@@ -58,6 +69,7 @@ static struct
{ ".", 3, DT_DIR, 0755 },
{ "..", 3, DT_DIR, 0755 },
{ "a", 3, DT_REG, 0644 },
+ { LONG_NAME, 3, DT_REG, 0644 },
{ "unreadable", 2, DT_DIR, 0111 },
{ ".", 3, DT_DIR, 0111 },
{ "..", 3, DT_DIR, 0755 },
@@ -75,7 +87,7 @@ typedef struct
int level;
int idx;
struct dirent d;
- char room_for_dirent[NAME_MAX];
+ char room_for_dirent[sizeof (LONG_NAME)];
} my_DIR;
@@ -193,23 +205,15 @@ my_readdir (void *gdir)
return NULL;
}
- dir->d.d_ino = dir->idx;
+ dir->d.d_ino = 1; /* glob should not skip this entry. */
-#ifdef _DIRENT_HAVE_D_TYPE
dir->d.d_type = filesystem[dir->idx].type;
-#endif
strcpy (dir->d.d_name, filesystem[dir->idx].name);
-#ifdef _DIRENT_HAVE_D_TYPE
PRINTF ("my_readdir ({ level: %d, idx: %ld }) = { d_ino: %ld, d_type: %d, d_name: \"%s\" }\n",
dir->level, (long int) dir->idx, dir->d.d_ino, dir->d.d_type,
dir->d.d_name);
-#else
- PRINTF ("my_readdir ({ level: %d, idx: %ld }) = { d_ino: %ld, d_name: \"%s\" }\n",
- dir->level, (long int) dir->idx, dir->d.d_ino,
- dir->d.d_name);
-#endif
++dir->idx;
diff --git a/posix/bug-regex10.c b/posix/bug-regex10.c
index 502a1c39b9..8599c606b8 100644
--- a/posix/bug-regex10.c
+++ b/posix/bug-regex10.c
@@ -1,5 +1,5 @@
/* Test for re_match with non-zero start.
- Copyright (C) 2002-2016 Free Software Foundation, Inc.
+ Copyright (C) 2002-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Jakub Jelinek <jakub@redhat.com>, 2002.
diff --git a/posix/bug-regex11.c b/posix/bug-regex11.c
index d3abe73c85..37707e9b92 100644
--- a/posix/bug-regex11.c
+++ b/posix/bug-regex11.c
@@ -1,5 +1,5 @@
/* Regular expression tests.
- Copyright (C) 2002-2016 Free Software Foundation, Inc.
+ Copyright (C) 2002-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Jakub Jelinek <jakub@redhat.com>, 2002.
diff --git a/posix/bug-regex12.c b/posix/bug-regex12.c
index 44a384873f..96ecac870e 100644
--- a/posix/bug-regex12.c
+++ b/posix/bug-regex12.c
@@ -1,5 +1,5 @@
/* Regular expression tests.
- Copyright (C) 2002-2016 Free Software Foundation, Inc.
+ Copyright (C) 2002-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Jakub Jelinek <jakub@redhat.com>, 2002.
diff --git a/posix/bug-regex13.c b/posix/bug-regex13.c
index 7a0ad92c3f..8cbcf98582 100644
--- a/posix/bug-regex13.c
+++ b/posix/bug-regex13.c
@@ -1,5 +1,5 @@
/* Regular expression tests.
- Copyright (C) 2002-2016 Free Software Foundation, Inc.
+ Copyright (C) 2002-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Isamu Hasegawa <isamu@yamato.ibm.com>, 2002.
diff --git a/posix/bug-regex14.c b/posix/bug-regex14.c
index fe12d7ef9c..b2f1bd092c 100644
--- a/posix/bug-regex14.c
+++ b/posix/bug-regex14.c
@@ -1,5 +1,5 @@
/* Tests re_comp and re_exec.
- Copyright (C) 2002-2016 Free Software Foundation, Inc.
+ Copyright (C) 2002-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Isamu Hasegawa <isamu@yamato.ibm.com>, 2002.
diff --git a/posix/bug-regex17.c b/posix/bug-regex17.c
index 8b9edfb3e8..893b9654b8 100644
--- a/posix/bug-regex17.c
+++ b/posix/bug-regex17.c
@@ -1,5 +1,5 @@
/* German regular expression tests.
- Copyright (C) 2002-2016 Free Software Foundation, Inc.
+ Copyright (C) 2002-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Jakub Jelinek <jakub@redhat.com>, 2002.
diff --git a/posix/bug-regex18.c b/posix/bug-regex18.c
index 6902f52b82..3904cfbacf 100644
--- a/posix/bug-regex18.c
+++ b/posix/bug-regex18.c
@@ -1,5 +1,5 @@
/* Turkish regular expression tests.
- Copyright (C) 2002-2016 Free Software Foundation, Inc.
+ Copyright (C) 2002-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Jakub Jelinek <jakub@redhat.com>, 2002.
diff --git a/posix/bug-regex19.c b/posix/bug-regex19.c
index 46d52ba7d8..aca1ddb5c4 100644
--- a/posix/bug-regex19.c
+++ b/posix/bug-regex19.c
@@ -1,5 +1,5 @@
/* Regular expression tests.
- Copyright (C) 2003-2016 Free Software Foundation, Inc.
+ Copyright (C) 2003-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Jakub Jelinek <jakub@redhat.com>, 2003.
diff --git a/posix/bug-regex2.c b/posix/bug-regex2.c
index fe0a7543a1..05e6be95ab 100644
--- a/posix/bug-regex2.c
+++ b/posix/bug-regex2.c
@@ -1,5 +1,5 @@
/* Test for memory handling in regex.
- Copyright (C) 2001-2016 Free Software Foundation, Inc.
+ Copyright (C) 2001-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2001.
diff --git a/posix/bug-regex20.c b/posix/bug-regex20.c
index 70fd3073db..8126a3ce9f 100644
--- a/posix/bug-regex20.c
+++ b/posix/bug-regex20.c
@@ -1,5 +1,5 @@
/* Test for UTF-8 regular expression optimizations.
- Copyright (C) 2003-2016 Free Software Foundation, Inc.
+ Copyright (C) 2003-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Jakub Jelinek <jakub@redhat.com>, 2003.
diff --git a/posix/bug-regex21.c b/posix/bug-regex21.c
index e6a9b6bf0d..a88c551dcd 100644
--- a/posix/bug-regex21.c
+++ b/posix/bug-regex21.c
@@ -1,5 +1,5 @@
/* Test for memory leaks in regcomp.
- Copyright (C) 2003-2016 Free Software Foundation, Inc.
+ Copyright (C) 2003-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Jakub Jelinek <jakub@redhat.com>, 2003.
diff --git a/posix/bug-regex22.c b/posix/bug-regex22.c
index 9884d3c6c4..2c561d8e43 100644
--- a/posix/bug-regex22.c
+++ b/posix/bug-regex22.c
@@ -1,5 +1,5 @@
/* Test re.translate != NULL.
- Copyright (C) 2004-2016 Free Software Foundation, Inc.
+ Copyright (C) 2004-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Jakub Jelinek <jakub@redhat.com>, 2004.
diff --git a/posix/bug-regex23.c b/posix/bug-regex23.c
index 2825f8f0fa..9289727316 100644
--- a/posix/bug-regex23.c
+++ b/posix/bug-regex23.c
@@ -1,5 +1,5 @@
/* Test we don't segfault on invalid UTF-8 sequence.
- Copyright (C) 2004-2016 Free Software Foundation, Inc.
+ Copyright (C) 2004-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Jakub Jelinek <jakub@redhat.com>, 2004.
diff --git a/posix/bug-regex25.c b/posix/bug-regex25.c
index 2b2538e420..f76720ac7a 100644
--- a/posix/bug-regex25.c
+++ b/posix/bug-regex25.c
@@ -1,5 +1,5 @@
/* Test re_search in multibyte locale other than UTF-8.
- Copyright (C) 2006-2016 Free Software Foundation, Inc.
+ Copyright (C) 2006-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Jakub Jelinek <jakub@redhat.com>, 2006.
diff --git a/posix/bug-regex26.c b/posix/bug-regex26.c
index 5cfa2fbe06..02f0aafbf6 100644
--- a/posix/bug-regex26.c
+++ b/posix/bug-regex26.c
@@ -1,5 +1,5 @@
/* Test re_search with dotless i.
- Copyright (C) 2006-2016 Free Software Foundation, Inc.
+ Copyright (C) 2006-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Jakub Jelinek <jakub@redhat.com>, 2006.
diff --git a/posix/bug-regex27.c b/posix/bug-regex27.c
index 8b29863199..f010e545c6 100644
--- a/posix/bug-regex27.c
+++ b/posix/bug-regex27.c
@@ -1,5 +1,5 @@
/* Test REG_NEWLINE.
- Copyright (C) 2007-2016 Free Software Foundation, Inc.
+ Copyright (C) 2007-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Jakub Jelinek <jakub@redhat.com>, 2007.
diff --git a/posix/bug-regex28.c b/posix/bug-regex28.c
index dc1d4ea720..ba263b27c8 100644
--- a/posix/bug-regex28.c
+++ b/posix/bug-regex28.c
@@ -1,5 +1,5 @@
/* Test RE_HAT_LISTS_NOT_NEWLINE and RE_DOT_NEWLINE.
- Copyright (C) 2007-2016 Free Software Foundation, Inc.
+ Copyright (C) 2007-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Jakub Jelinek <jakub@redhat.com>, 2007.
@@ -21,18 +21,22 @@
#include <stdio.h>
#include <string.h>
+#include <support/test-driver.h>
+#include <support/check.h>
+
struct tests
{
const char *regex;
const char *string;
reg_syntax_t syntax;
int retval;
-} tests[] = {
+};
+static const struct tests tests[] = {
#define EGREP RE_SYNTAX_EGREP
#define EGREP_NL (RE_SYNTAX_EGREP | RE_DOT_NEWLINE) & ~RE_HAT_LISTS_NOT_NEWLINE
- { "a.b", "a\nb", EGREP, -1 },
+ { "a.b", "a\nb", EGREP, 0 },
{ "a.b", "a\nb", EGREP_NL, 0 },
- { "a[^x]b", "a\nb", EGREP, -1 },
+ { "a[^x]b", "a\nb", EGREP, 0 },
{ "a[^x]b", "a\nb", EGREP_NL, 0 },
/* While \S and \W are internally handled as [^[:space:]] and [^[:alnum:]_],
RE_HAT_LISTS_NOT_NEWLINE did not make any difference, so ensure
@@ -42,33 +46,33 @@ struct tests
{ "a\\Wb", "a\nb", EGREP, 0 },
{ "a\\Wb", "a\nb", EGREP_NL, 0 }
};
+static const size_t tests_size = sizeof (tests) / sizeof (tests[0]);
-int
-main (void)
+static int
+do_test (void)
{
struct re_pattern_buffer r;
- size_t i;
- int ret = 0;
- for (i = 0; i < sizeof (tests) / sizeof (tests[i]); ++i)
+ for (size_t i = 0; i < tests_size; i++)
{
re_set_syntax (tests[i].syntax);
memset (&r, 0, sizeof (r));
- if (re_compile_pattern (tests[i].regex, strlen (tests[i].regex), &r))
- {
- printf ("re_compile_pattern %zd failed\n", i);
- ret = 1;
- continue;
- }
+ const char *re = re_compile_pattern (tests[i].regex,
+ strlen (tests[i].regex), &r);
+ TEST_VERIFY (re == NULL);
+ if (re != NULL)
+ continue;
+
size_t len = strlen (tests[i].string);
int rv = re_search (&r, tests[i].string, len, 0, len, NULL);
- if (rv != tests[i].retval)
- {
- printf ("re_search %zd unexpected value %d != %d\n",
- i, rv, tests[i].retval);
- ret = 1;
- }
+ TEST_VERIFY (rv == tests[i].retval);
+ if (test_verbose > 0)
+ printf ("info: i=%zu rv=%d expected=%d\n", i, rv, tests[i].retval);
+
regfree (&r);
}
- return ret;
+
+ return 0;
}
+
+#include <support/test-driver.c>
diff --git a/posix/bug-regex3.c b/posix/bug-regex3.c
index 84314058ef..a8616aa3d5 100644
--- a/posix/bug-regex3.c
+++ b/posix/bug-regex3.c
@@ -1,5 +1,5 @@
/* Test for case handling in regex.
- Copyright (C) 2001-2016 Free Software Foundation, Inc.
+ Copyright (C) 2001-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Jakub Jelinek <jakub@redhat.com>, 2001.
diff --git a/posix/bug-regex30.c b/posix/bug-regex30.c
index e1ddf08090..a8f5fd2899 100644
--- a/posix/bug-regex30.c
+++ b/posix/bug-regex30.c
@@ -1,5 +1,5 @@
/* Russian regular expression tests.
- Copyright (C) 2009-2016 Free Software Foundation, Inc.
+ Copyright (C) 2009-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Paolo Bonzini <pbonzini@redhat.com>, 2009.
diff --git a/posix/bug-regex33.c b/posix/bug-regex33.c
index 1a71af02ed..015b73c1d1 100644
--- a/posix/bug-regex33.c
+++ b/posix/bug-regex33.c
@@ -1,5 +1,5 @@
/* Test re_search with multi-byte characters in EUC-JP.
- Copyright (C) 2012-2016 Free Software Foundation, Inc.
+ Copyright (C) 2012-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Stanislav Brabec <sbrabec@suse.cz>, 2012.
@@ -23,7 +23,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include "regex_internal.h"
static int
do_test (void)
@@ -39,8 +38,9 @@ do_test (void)
memset (&r, 0, sizeof (r));
memset (&s, 0, sizeof (s));
- /* The bug cannot be reproduced without initialized fastmap. */
- r.fastmap = malloc (SBC_MAX);
+ /* The bug cannot be reproduced without initialized fastmap (it is SBC_MAX
+ value from regex_internal.h). */
+ r.fastmap = malloc (UCHAR_MAX + 1);
/* 圭 */
re_compile_pattern ("\xb7\xbd", 2, &r);
diff --git a/posix/bug-regex34.c b/posix/bug-regex34.c
index 244bc69a98..4eeb704ee7 100644
--- a/posix/bug-regex34.c
+++ b/posix/bug-regex34.c
@@ -1,5 +1,5 @@
/* Test re_search with multi-byte characters in UTF-8.
- Copyright (C) 2013-2016 Free Software Foundation, Inc.
+ Copyright (C) 2013-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/posix/bug-regex35.c b/posix/bug-regex35.c
index f2a0169eb7..852e2b8a7a 100644
--- a/posix/bug-regex35.c
+++ b/posix/bug-regex35.c
@@ -1,5 +1,5 @@
/* Test regcomp with collating symbols in bracket expressions
- Copyright (C) 2013-2016 Free Software Foundation, Inc.
+ Copyright (C) 2013-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/posix/bug-regex36.c b/posix/bug-regex36.c
index 32a4a57907..d947dc4a64 100644
--- a/posix/bug-regex36.c
+++ b/posix/bug-regex36.c
@@ -1,5 +1,5 @@
/* Test regcomp not leaking memory on parse errors
- Copyright (C) 2014-2016 Free Software Foundation, Inc.
+ Copyright (C) 2014-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/posix/bug-regex37.c b/posix/bug-regex37.c
new file mode 100644
index 0000000000..87a0916914
--- /dev/null
+++ b/posix/bug-regex37.c
@@ -0,0 +1,32 @@
+/* Test regcomp return for invalid expression (BZ #21163).
+ Copyright (C) 2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <regex.h>
+
+#include <support/check.h>
+
+static int
+do_test (void)
+{
+ char const pattern[] = "()*)|\\1)*";
+ regex_t r;
+ TEST_VERIFY_EXIT (regcomp (&r, pattern, REG_EXTENDED) == REG_ESUBREG);
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/posix/bug-regex38.c b/posix/bug-regex38.c
new file mode 100644
index 0000000000..cb0eb7d214
--- /dev/null
+++ b/posix/bug-regex38.c
@@ -0,0 +1,32 @@
+/* Diagnose invalid back-reference in the ERE '()|\1' (BZ #18986).
+ Copyright (C) 2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <regex.h>
+
+#include <support/check.h>
+
+static int
+do_test (void)
+{
+ char const pattern[] = "0|()0|\\1|0";
+ regex_t r;
+ TEST_VERIFY_EXIT (regcomp (&r, pattern, REG_EXTENDED) == REG_ESUBREG);
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/posix/bug-regex4.c b/posix/bug-regex4.c
index 016636a240..54be0c606d 100644
--- a/posix/bug-regex4.c
+++ b/posix/bug-regex4.c
@@ -1,5 +1,5 @@
/* Test for re_search_2.
- Copyright (C) 2001-2016 Free Software Foundation, Inc.
+ Copyright (C) 2001-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Jakub Jelinek <jakub@redhat.com>, 2001.
diff --git a/posix/bug-regex5.c b/posix/bug-regex5.c
index fd18b19df4..573da231e3 100644
--- a/posix/bug-regex5.c
+++ b/posix/bug-regex5.c
@@ -53,9 +53,9 @@ main (void)
printf ("No collating element!\n");
return 1;
}
- else if (found != 4)
+ else if (found != 6)
{
- printf ("expected 4 collating elements, found %d\n", found);
+ printf ("expected 6 collating elements, found %d\n", found);
return 1;
}
diff --git a/posix/bug-regex6.c b/posix/bug-regex6.c
index d932e248d4..af3a9c447d 100644
--- a/posix/bug-regex6.c
+++ b/posix/bug-regex6.c
@@ -1,5 +1,5 @@
/* Test for regexec.
- Copyright (C) 2002-2016 Free Software Foundation, Inc.
+ Copyright (C) 2002-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Jakub Jelinek <jakub@redhat.com>, 2002.
diff --git a/posix/bug-regex7.c b/posix/bug-regex7.c
index a9296b0377..6658606c01 100644
--- a/posix/bug-regex7.c
+++ b/posix/bug-regex7.c
@@ -1,5 +1,5 @@
/* Test for regs allocation in re_search and re_match.
- Copyright (C) 2002-2016 Free Software Foundation, Inc.
+ Copyright (C) 2002-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Stepan Kasal <kasal@math.cas.cz>, 2002.
diff --git a/posix/bug-regex8.c b/posix/bug-regex8.c
index 5c431305c8..ee398039dd 100644
--- a/posix/bug-regex8.c
+++ b/posix/bug-regex8.c
@@ -1,5 +1,5 @@
/* Test for the STOP parameter of re_match_2 and re_search_2.
- Copyright (C) 2002-2016 Free Software Foundation, Inc.
+ Copyright (C) 2002-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Stepan Kasal <kasal@math.cas.cz>, 2002.
diff --git a/posix/bug-regex9.c b/posix/bug-regex9.c
index f5070c61e0..104d797f04 100644
--- a/posix/bug-regex9.c
+++ b/posix/bug-regex9.c
@@ -1,5 +1,5 @@
/* Test for memory handling in regex.
- Copyright (C) 2002-2016 Free Software Foundation, Inc.
+ Copyright (C) 2002-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2001.
diff --git a/posix/confstr.c b/posix/confstr.c
index aab34f2a8b..de4cff76cc 100644
--- a/posix/confstr.c
+++ b/posix/confstr.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/posix/cpio.h b/posix/cpio.h
index 9e712fe258..dc6dc1c551 100644
--- a/posix/cpio.h
+++ b/posix/cpio.h
@@ -1,6 +1,6 @@
/* Extended cpio format from POSIX.1.
This file is part of the GNU C Library.
- Copyright (C) 1992-2016 Free Software Foundation, Inc.
+ Copyright (C) 1992-2018 Free Software Foundation, Inc.
NOTE: The canonical source of this file is maintained with the GNU cpio.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/posix/execl.c b/posix/execl.c
index 102d19d9af..0f0a7db5cb 100644
--- a/posix/execl.c
+++ b/posix/execl.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -16,58 +16,42 @@
<http://www.gnu.org/licenses/>. */
#include <unistd.h>
+#include <errno.h>
#include <stdarg.h>
-#include <stddef.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <stackinfo.h>
-
+#include <sys/param.h>
/* Execute PATH with all arguments after PATH until
a NULL pointer and environment from `environ'. */
int
execl (const char *path, const char *arg, ...)
{
-#define INITIAL_ARGV_MAX 1024
- size_t argv_max = INITIAL_ARGV_MAX;
- const char *initial_argv[INITIAL_ARGV_MAX];
- const char **argv = initial_argv;
- va_list args;
-
- argv[0] = arg;
-
- va_start (args, arg);
- unsigned int i = 0;
- while (argv[i++] != NULL)
+ ptrdiff_t argc;
+ va_list ap;
+ va_start (ap, arg);
+ for (argc = 1; va_arg (ap, const char *); argc++)
{
- if (i == argv_max)
+ if (argc == INT_MAX)
{
- argv_max *= 2;
- const char **nptr = realloc (argv == initial_argv ? NULL : argv,
- argv_max * sizeof (const char *));
- if (nptr == NULL)
- {
- if (argv != initial_argv)
- free (argv);
- va_end (args);
- return -1;
- }
- if (argv == initial_argv)
- /* We have to copy the already filled-in data ourselves. */
- memcpy (nptr, argv, i * sizeof (const char *));
-
- argv = nptr;
+ va_end (ap);
+ errno = E2BIG;
+ return -1;
}
-
- argv[i] = va_arg (args, const char *);
}
- va_end (args);
-
- int ret = __execve (path, (char *const *) argv, __environ);
- if (argv != initial_argv)
- free (argv);
-
- return ret;
+ va_end (ap);
+
+ /* Avoid dynamic memory allocation due two main issues:
+ 1. The function should be async-signal-safe and a running on a signal
+ handler with a fail outcome might lead to malloc bad state.
+ 2. It might be used in a vfork/clone(VFORK) scenario where using
+ malloc also might lead to internal bad state. */
+ ptrdiff_t i;
+ char *argv[argc + 1];
+ va_start (ap, arg);
+ argv[0] = (char *) arg;
+ for (i = 1; i <= argc; i++)
+ argv[i] = va_arg (ap, char *);
+ va_end (ap);
+
+ return __execve (path, argv, __environ);
}
libc_hidden_def (execl)
diff --git a/posix/execle.c b/posix/execle.c
index 8edc03a84a..d25dd423ad 100644
--- a/posix/execle.c
+++ b/posix/execle.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -17,57 +17,43 @@
#include <unistd.h>
#include <stdarg.h>
-#include <stddef.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <stackinfo.h>
+#include <errno.h>
+#include <sys/param.h>
/* Execute PATH with all arguments after PATH until a NULL pointer,
and the argument after that for environment. */
int
execle (const char *path, const char *arg, ...)
{
-#define INITIAL_ARGV_MAX 1024
- size_t argv_max = INITIAL_ARGV_MAX;
- const char *initial_argv[INITIAL_ARGV_MAX];
- const char **argv = initial_argv;
- va_list args;
- argv[0] = arg;
-
- va_start (args, arg);
- unsigned int i = 0;
- while (argv[i++] != NULL)
+ ptrdiff_t argc;
+ va_list ap;
+ va_start (ap, arg);
+ for (argc = 1; va_arg (ap, const char *); argc++)
{
- if (i == argv_max)
+ if (argc == INT_MAX)
{
- argv_max *= 2;
- const char **nptr = realloc (argv == initial_argv ? NULL : argv,
- argv_max * sizeof (const char *));
- if (nptr == NULL)
- {
- if (argv != initial_argv)
- free (argv);
- va_end (args);
- return -1;
- }
- if (argv == initial_argv)
- /* We have to copy the already filled-in data ourselves. */
- memcpy (nptr, argv, i * sizeof (const char *));
-
- argv = nptr;
+ va_end (ap);
+ errno = E2BIG;
+ return -1;
}
-
- argv[i] = va_arg (args, const char *);
}
-
- const char *const *envp = va_arg (args, const char *const *);
- va_end (args);
-
- int ret = __execve (path, (char *const *) argv, (char *const *) envp);
- if (argv != initial_argv)
- free (argv);
-
- return ret;
+ va_end (ap);
+
+ /* Avoid dynamic memory allocation due two main issues:
+ 1. The function should be async-signal-safe and a running on a signal
+ handler with a fail outcome might lead to malloc bad state.
+ 2. It might be used in a vfork/clone(VFORK) scenario where using
+ malloc also might lead to internal bad state. */
+ ptrdiff_t i;
+ char *argv[argc + 1];
+ char **envp;
+ va_start (ap, arg);
+ argv[0] = (char *) arg;
+ for (i = 1; i <= argc; i++)
+ argv[i] = va_arg (ap, char *);
+ envp = va_arg (ap, char **);
+ va_end (ap);
+
+ return __execve (path, argv, envp);
}
libc_hidden_def (execle)
diff --git a/posix/execlp.c b/posix/execlp.c
index 6700994a5b..1e58569c0c 100644
--- a/posix/execlp.c
+++ b/posix/execlp.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -17,11 +17,8 @@
#include <unistd.h>
#include <stdarg.h>
-#include <stddef.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <stackinfo.h>
+#include <errno.h>
+#include <sys/param.h>
/* Execute FILE, searching in the `PATH' environment variable if
it contains no slashes, with all arguments after FILE until a
@@ -29,45 +26,32 @@
int
execlp (const char *file, const char *arg, ...)
{
-#define INITIAL_ARGV_MAX 1024
- size_t argv_max = INITIAL_ARGV_MAX;
- const char *initial_argv[INITIAL_ARGV_MAX];
- const char **argv = initial_argv;
- va_list args;
-
- argv[0] = arg;
-
- va_start (args, arg);
- unsigned int i = 0;
- while (argv[i++] != NULL)
+ ptrdiff_t argc;
+ va_list ap;
+ va_start (ap, arg);
+ for (argc = 1; va_arg (ap, const char *); argc++)
{
- if (i == argv_max)
+ if (argc == INT_MAX)
{
- argv_max *= 2;
- const char **nptr = realloc (argv == initial_argv ? NULL : argv,
- argv_max * sizeof (const char *));
- if (nptr == NULL)
- {
- if (argv != initial_argv)
- free (argv);
- va_end (args);
- return -1;
- }
- if (argv == initial_argv)
- /* We have to copy the already filled-in data ourselves. */
- memcpy (nptr, argv, i * sizeof (const char *));
-
- argv = nptr;
+ va_end (ap);
+ errno = E2BIG;
+ return -1;
}
-
- argv[i] = va_arg (args, const char *);
}
- va_end (args);
-
- int ret = execvp (file, (char *const *) argv);
- if (argv != initial_argv)
- free (argv);
-
- return ret;
+ va_end (ap);
+
+ /* Although posix does not state execlp as an async-safe function
+ it can not use malloc to allocate the arguments since it might
+ be used in a vfork scenario and it may lead to malloc internal
+ bad state. */
+ ptrdiff_t i;
+ char *argv[argc + 1];
+ va_start (ap, arg);
+ argv[0] = (char *) arg;
+ for (i = 1; i <= argc; i++)
+ argv[i] = va_arg (ap, char *);
+ va_end (ap);
+
+ return __execvpe (file, argv, __environ);
}
libc_hidden_def (execlp)
diff --git a/posix/execv.c b/posix/execv.c
index 16c0a02c43..782ade1b1d 100644
--- a/posix/execv.c
+++ b/posix/execv.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/posix/execve.c b/posix/execve.c
index 24d324f027..7ec7a0e1a6 100644
--- a/posix/execve.c
+++ b/posix/execve.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/posix/execvp.c b/posix/execvp.c
index ea3d9d08ab..627d7bcb51 100644
--- a/posix/execvp.c
+++ b/posix/execvp.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/posix/execvpe.c b/posix/execvpe.c
index 61697a74f0..ea67d19fcd 100644
--- a/posix/execvpe.c
+++ b/posix/execvpe.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -15,7 +15,6 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
-#include <alloca.h>
#include <unistd.h>
#include <stdarg.h>
#include <stdbool.h>
@@ -23,194 +22,178 @@
#include <string.h>
#include <errno.h>
#include <paths.h>
+#include <confstr.h>
+#include <sys/param.h>
+#ifndef PATH_MAX
+# ifdef MAXPATHLEN
+# define PATH_MAX MAXPATHLEN
+# else
+# define PATH_MAX 1024
+# endif
+#endif
/* The file is accessible but it is not an executable file. Invoke
the shell to interpret it as a script. */
static void
-internal_function
-scripts_argv (const char *file, char *const argv[], int argc, char **new_argv)
+maybe_script_execute (const char *file, char *const argv[], char *const envp[])
{
- /* Construct an argument list for the shell. */
- new_argv[0] = (char *) _PATH_BSHELL;
- new_argv[1] = (char *) file;
- while (argc > 1)
+ ptrdiff_t argc;
+ for (argc = 0; argv[argc] != NULL; argc++)
{
- new_argv[argc] = argv[argc - 1];
- --argc;
+ if (argc == INT_MAX - 1)
+ {
+ errno = E2BIG;
+ return;
+ }
}
-}
+ /* Construct an argument list for the shell based on original arguments:
+ 1. Empty list (argv = { NULL }, argc = 1 }: new argv will contain 3
+ arguments - default shell, script to execute, and ending NULL.
+ 2. Non empty argument list (argc = { ..., NULL }, argc > 1}: new argv
+ will contain also the default shell and the script to execute. It
+ will also skip the script name in arguments and only copy script
+ arguments. */
+ char *new_argv[argc > 1 ? 2 + argc : 3];
+ new_argv[0] = (char *) _PATH_BSHELL;
+ new_argv[1] = (char *) file;
+ if (argc > 1)
+ memcpy (new_argv + 2, argv + 1, argc * sizeof(char *));
+ else
+ new_argv[2] = NULL;
-/* Execute FILE, searching in the `PATH' environment variable if it contains
- no slashes, with arguments ARGV and environment from ENVP. */
-int
-__execvpe (const char *file, char *const argv[], char *const envp[])
+ /* Execute the shell. */
+ __execve (new_argv[0], new_argv, envp);
+}
+
+static int
+__execvpe_common (const char *file, char *const argv[], char *const envp[],
+ bool exec_script)
{
+ /* We check the simple case first. */
if (*file == '\0')
{
- /* We check the simple case first. */
__set_errno (ENOENT);
return -1;
}
+ /* Don't search when it contains a slash. */
if (strchr (file, '/') != NULL)
{
- /* Don't search when it contains a slash. */
__execve (file, argv, envp);
- if (errno == ENOEXEC)
- {
- /* Count the arguments. */
- int argc = 0;
- while (argv[argc++])
- ;
- size_t len = (argc + 1) * sizeof (char *);
- char **script_argv;
- void *ptr = NULL;
- if (__libc_use_alloca (len))
- script_argv = alloca (len);
- else
- script_argv = ptr = malloc (len);
-
- if (script_argv != NULL)
- {
- scripts_argv (file, argv, argc, script_argv);
- __execve (script_argv[0], script_argv, envp);
-
- free (ptr);
- }
- }
+ if (errno == ENOEXEC && exec_script)
+ maybe_script_execute (file, argv, envp);
+
+ return -1;
}
- else
+
+ const char *path = getenv ("PATH");
+ if (!path)
+ path = CS_PATH;
+ /* Although GLIBC does not enforce NAME_MAX, we set it as the maximum
+ size to avoid unbounded stack allocation. Same applies for
+ PATH_MAX. */
+ size_t file_len = __strnlen (file, NAME_MAX) + 1;
+ size_t path_len = __strnlen (path, PATH_MAX - 1) + 1;
+
+ /* NAME_MAX does not include the terminating null character. */
+ if ((file_len - 1 > NAME_MAX)
+ || !__libc_alloca_cutoff (path_len + file_len + 1))
{
- size_t pathlen;
- size_t alloclen = 0;
- char *path = getenv ("PATH");
- if (path == NULL)
- {
- pathlen = confstr (_CS_PATH, (char *) NULL, 0);
- alloclen = pathlen + 1;
- }
- else
- pathlen = strlen (path);
+ errno = ENAMETOOLONG;
+ return -1;
+ }
- size_t len = strlen (file) + 1;
- alloclen += pathlen + len + 1;
+ const char *subp;
+ bool got_eacces = false;
+ /* The resulting string maximum size would be potentially a entry
+ in PATH plus '/' (path_len + 1) and then the the resulting file name
+ plus '\0' (file_len since it already accounts for the '\0'). */
+ char buffer[path_len + file_len + 1];
+ for (const char *p = path; ; p = subp)
+ {
+ subp = __strchrnul (p, ':');
- char *name;
- char *path_malloc = NULL;
- if (__libc_use_alloca (alloclen))
- name = alloca (alloclen);
- else
+ /* PATH is larger than PATH_MAX and thus potentially larger than
+ the stack allocation. */
+ if (subp - p >= path_len)
{
- path_malloc = name = malloc (alloclen);
- if (name == NULL)
- return -1;
+ /* If there is only one path, bail out. */
+ if (*subp == '\0')
+ break;
+ /* Otherwise skip to next one. */
+ continue;
}
- if (path == NULL)
- {
- /* There is no `PATH' in the environment.
- The default search path is the current directory
- followed by the path `confstr' returns for `_CS_PATH'. */
- path = name + pathlen + len + 1;
- path[0] = ':';
- (void) confstr (_CS_PATH, path + 1, pathlen);
- }
+ /* Use the current path entry, plus a '/' if nonempty, plus the file to
+ execute. */
+ char *pend = mempcpy (buffer, p, subp - p);
+ *pend = '/';
+ memcpy (pend + (p < subp), file, file_len);
- /* Copy the file name at the top. */
- name = (char *) memcpy (name + pathlen + 1, file, len);
- /* And add the slash. */
- *--name = '/';
+ __execve (buffer, argv, envp);
- char **script_argv = NULL;
- void *script_argv_malloc = NULL;
- bool got_eacces = false;
- char *p = path;
- do
+ if (errno == ENOEXEC && exec_script)
+ /* This has O(P*C) behavior, where P is the length of the path and C
+ is the argument count. A better strategy would be allocate the
+ substitute argv and reuse it each time through the loop (so it
+ behaves as O(P+C) instead. */
+ maybe_script_execute (buffer, argv, envp);
+
+ switch (errno)
{
- char *startp;
-
- path = p;
- p = __strchrnul (path, ':');
-
- if (p == path)
- /* Two adjacent colons, or a colon at the beginning or the end
- of `PATH' means to search the current directory. */
- startp = name + 1;
- else
- startp = (char *) memcpy (name - (p - path), path, p - path);
-
- /* Try to execute this name. If it works, execve will not return. */
- __execve (startp, argv, envp);
-
- if (errno == ENOEXEC)
- {
- if (script_argv == NULL)
- {
- /* Count the arguments. */
- int argc = 0;
- while (argv[argc++])
- ;
- size_t arglen = (argc + 1) * sizeof (char *);
- if (__libc_use_alloca (alloclen + arglen))
- script_argv = alloca (arglen);
- else
- script_argv = script_argv_malloc = malloc (arglen);
- if (script_argv == NULL)
- {
- /* A possible EACCES error is not as important as
- the ENOMEM. */
- got_eacces = false;
- break;
- }
- scripts_argv (startp, argv, argc, script_argv);
- }
-
- __execve (script_argv[0], script_argv, envp);
- }
-
- switch (errno)
- {
- case EACCES:
- /* Record the we got a `Permission denied' error. If we end
- up finding no executable we can use, we want to diagnose
- that we did find one but were denied access. */
- got_eacces = true;
- case ENOENT:
- case ESTALE:
- case ENOTDIR:
- /* Those errors indicate the file is missing or not executable
- by us, in which case we want to just try the next path
- directory. */
- case ENODEV:
- case ETIMEDOUT:
- /* Some strange filesystems like AFS return even
- stranger error numbers. They cannot reasonably mean
- anything else so ignore those, too. */
- break;
-
- default:
- /* Some other error means we found an executable file, but
- something went wrong executing it; return the error to our
- caller. */
- return -1;
- }
+ case EACCES:
+ /* Record that we got a 'Permission denied' error. If we end
+ up finding no executable we can use, we want to diagnose
+ that we did find one but were denied access. */
+ got_eacces = true;
+ case ENOENT:
+ case ESTALE:
+ case ENOTDIR:
+ /* Those errors indicate the file is missing or not executable
+ by us, in which case we want to just try the next path
+ directory. */
+ case ENODEV:
+ case ETIMEDOUT:
+ /* Some strange filesystems like AFS return even
+ stranger error numbers. They cannot reasonably mean
+ anything else so ignore those, too. */
+ break;
+
+ default:
+ /* Some other error means we found an executable file, but
+ something went wrong executing it; return the error to our
+ caller. */
+ return -1;
}
- while (*p++ != '\0');
-
- /* We tried every element and none of them worked. */
- if (got_eacces)
- /* At least one failure was due to permissions, so report that
- error. */
- __set_errno (EACCES);
- free (script_argv_malloc);
- free (path_malloc);
+ if (*subp++ == '\0')
+ break;
}
- /* Return the error from the last attempt (probably ENOENT). */
+ /* We tried every element and none of them worked. */
+ if (got_eacces)
+ /* At least one failure was due to permissions, so report that
+ error. */
+ __set_errno (EACCES);
+
return -1;
}
+
+/* Execute FILE, searching in the `PATH' environment variable if it contains
+ no slashes, with arguments ARGV and environment from ENVP. */
+int
+__execvpe (const char *file, char *const argv[], char *const envp[])
+{
+ return __execvpe_common (file, argv, envp, true);
+}
weak_alias (__execvpe, execvpe)
+
+/* Same as __EXECVPE, but does not try to execute NOEXEC files. */
+int
+__execvpex (const char *file, char *const argv[], char *const envp[])
+{
+ return __execvpe_common (file, argv, envp, false);
+}
diff --git a/posix/fexecve.c b/posix/fexecve.c
index dc765c4a02..6cf90b52f4 100644
--- a/posix/fexecve.c
+++ b/posix/fexecve.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1994-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1994-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/posix/flexmember.h b/posix/flexmember.h
new file mode 100644
index 0000000000..2dff5181b6
--- /dev/null
+++ b/posix/flexmember.h
@@ -0,0 +1,45 @@
+/* Sizes of structs with flexible array members.
+
+ Copyright 2016-2018 Free Software Foundation, Inc.
+
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>.
+
+ Written by Paul Eggert. */
+
+#include <stddef.h>
+
+/* Nonzero multiple of alignment of TYPE, suitable for FLEXSIZEOF below.
+ On older platforms without _Alignof, use a pessimistic bound that is
+ safe in practice even if FLEXIBLE_ARRAY_MEMBER is 1.
+ On newer platforms, use _Alignof to get a tighter bound. */
+
+#if !defined __STDC_VERSION__ || __STDC_VERSION__ < 201112
+# define FLEXALIGNOF(type) (sizeof (type) & ~ (sizeof (type) - 1))
+#else
+# define FLEXALIGNOF(type) _Alignof (type)
+#endif
+
+/* Upper bound on the size of a struct of type TYPE with a flexible
+ array member named MEMBER that is followed by N bytes of other data.
+ This is not simply sizeof (TYPE) + N, since it may require
+ alignment on unusually picky C11 platforms, and
+ FLEXIBLE_ARRAY_MEMBER may be 1 on pre-C11 platforms.
+ Yield a value less than N if and only if arithmetic overflow occurs. */
+
+#define FLEXSIZEOF(type, member, n) \
+ ((offsetof (type, member) + FLEXALIGNOF (type) - 1 + (n)) \
+ & ~ (FLEXALIGNOF (type) - 1))
diff --git a/posix/fnmatch.c b/posix/fnmatch.c
index 8bbaaa74b7..a9b762624f 100644
--- a/posix/fnmatch.c
+++ b/posix/fnmatch.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -186,12 +186,6 @@ __wcschrnul (const wchar_t *s, wint_t c)
}
# endif
-# ifndef internal_function
-/* Inside GNU libc we mark some function in a special way. In other
- environments simply ignore the marking. */
-# define internal_function
-# endif
-
/* Note that this evaluates C many times. */
# ifdef _LIBC
# define FOLD(c) ((flags & FNM_CASEFOLD) ? tolower (c) : (c))
diff --git a/posix/fnmatch.h b/posix/fnmatch.h
index fdfaf90ba9..9f03eafbca 100644
--- a/posix/fnmatch.h
+++ b/posix/fnmatch.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/posix/fnmatch_loop.c b/posix/fnmatch_loop.c
index 229904e11d..e298cac5dc 100644
--- a/posix/fnmatch_loop.c
+++ b/posix/fnmatch_loop.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -28,16 +28,13 @@ struct STRUCT
it matches, nonzero if not. */
static int FCT (const CHAR *pattern, const CHAR *string,
const CHAR *string_end, int no_leading_period, int flags,
- struct STRUCT *ends, size_t alloca_used)
- internal_function;
+ struct STRUCT *ends, size_t alloca_used);
static int EXT (INT opt, const CHAR *pattern, const CHAR *string,
const CHAR *string_end, int no_leading_period, int flags,
- size_t alloca_used)
- internal_function;
-static const CHAR *END (const CHAR *patternp) internal_function;
+ size_t alloca_used);
+static const CHAR *END (const CHAR *patternp);
static int
-internal_function
FCT (const CHAR *pattern, const CHAR *string, const CHAR *string_end,
int no_leading_period, int flags, struct STRUCT *ends, size_t alloca_used)
{
@@ -1000,7 +997,6 @@ FCT (const CHAR *pattern, const CHAR *string, const CHAR *string_end,
static const CHAR *
-internal_function
END (const CHAR *pattern)
{
const CHAR *p = pattern;
@@ -1044,7 +1040,6 @@ END (const CHAR *pattern)
static int
-internal_function
EXT (INT opt, const CHAR *pattern, const CHAR *string, const CHAR *string_end,
int no_leading_period, int flags, size_t alloca_used)
{
diff --git a/posix/fork.c b/posix/fork.c
index b19aca3ddc..6f32a783d7 100644
--- a/posix/fork.c
+++ b/posix/fork.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/posix/fpathconf.c b/posix/fpathconf.c
index e0cb59b067..0ee2a4d260 100644
--- a/posix/fpathconf.c
+++ b/posix/fpathconf.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/posix/gai_strerror.c b/posix/gai_strerror.c
index 451130ba44..6463cd187c 100644
--- a/posix/gai_strerror.c
+++ b/posix/gai_strerror.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1996-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1996-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/posix/get_child_max.c b/posix/get_child_max.c
index 48b487e902..0f0a9fffa1 100644
--- a/posix/get_child_max.c
+++ b/posix/get_child_max.c
@@ -1,5 +1,5 @@
/* Get POSIX {CHILD_MAX} run-time limit value. Stub version (no limit).
- Copyright (C) 2006-2016 Free Software Foundation, Inc.
+ Copyright (C) 2006-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/posix/getaddrinfo.c b/posix/getaddrinfo.c
index 205671baf3..0edf77a1a5 100644
--- a/posix/getaddrinfo.c
+++ b/posix/getaddrinfo.c
@@ -1,5 +1,5 @@
/* Stub version of getaddrinfo function.
- Copyright (C) 1996-2016 Free Software Foundation, Inc.
+ Copyright (C) 1996-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/posix/getconf-speclist.c b/posix/getconf-speclist.c
index 3c7500a178..6406dbb3f2 100644
--- a/posix/getconf-speclist.c
+++ b/posix/getconf-speclist.c
@@ -1,5 +1,5 @@
/* List POSIX compilation environments for this libc.
- Copyright (C) 2012-2016 Free Software Foundation, Inc.
+ Copyright (C) 2012-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/posix/getconf.c b/posix/getconf.c
index 3e03396ea7..9f4d6af602 100644
--- a/posix/getconf.c
+++ b/posix/getconf.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
This program is free software; you can redistribute it and/or modify
@@ -29,6 +29,23 @@
#define NEED_SPEC_ARRAY 1
#include <posix-conf-vars.h>
+/* If all of the environments are defined in environments.h, then we don't need
+ to bother with doing a runtime check for a specific environment. */
+#if (defined _SC_V6_ILP32_OFF32 \
+ && defined _SC_V7_LPBIG_OFFBIG \
+ && defined _SC_XBS5_LP64_OFF64 \
+ && defined _SC_V6_LP64_OFF64 \
+ && defined _SC_V7_ILP32_OFFBIG \
+ && defined _SC_V6_LPBIG_OFFBIG \
+ && defined _SC_V7_LP64_OFF64 \
+ && defined _SC_V7_ILP32_OFF32 \
+ && defined _SC_XBS5_LPBIG_OFFBIG \
+ && defined _SC_XBS5_ILP32_OFFBIG \
+ && defined _SC_V6_ILP32_OFFBIG \
+ && defined _SC_XBS5_ILP32_OFF32)
+# define ALL_ENVIRONMENTS_DEFINED 1
+#endif
+
struct conf
{
const char *name;
@@ -469,7 +486,7 @@ main (int argc, char *argv[])
Copyright (C) %s Free Software Foundation, Inc.\n\
This is free software; see the source for copying conditions. There is NO\n\
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
-"), "2016");
+"), "2018");
printf (gettext ("Written by %s.\n"), "Roland McGrath");
return 0;
}
@@ -488,6 +505,24 @@ environment SPEC.\n\n"));
return 0;
}
+#ifdef ALL_ENVIRONMENTS_DEFINED
+ if (argc > 1 && strncmp (argv[1], "-v", 2) == 0)
+ {
+ if (argv[1][2] == '\0')
+ {
+ if (argc < 3)
+ usage ();
+
+ argv += 2;
+ argc -= 2;
+ }
+ else
+ {
+ argv += 1;
+ argc += 1;
+ }
+ }
+#else
const char *getconf_dir = getenv ("GETCONF_DIR") ?: GETCONF_DIR;
size_t getconf_dirlen = strlen (getconf_dir);
@@ -538,42 +573,42 @@ environment SPEC.\n\n"));
switch (specs[i].num)
{
-#ifndef _XBS5_ILP32_OFF32
+# ifndef _XBS5_ILP32_OFF32
case _SC_XBS5_ILP32_OFF32:
-#endif
-#ifndef _XBS5_ILP32_OFFBIG
+# endif
+# ifndef _XBS5_ILP32_OFFBIG
case _SC_XBS5_ILP32_OFFBIG:
-#endif
-#ifndef _XBS5_LP64_OFF64
+# endif
+# ifndef _XBS5_LP64_OFF64
case _SC_XBS5_LP64_OFF64:
-#endif
-#ifndef _XBS5_LPBIG_OFFBIG
+# endif
+# ifndef _XBS5_LPBIG_OFFBIG
case _SC_XBS5_LPBIG_OFFBIG:
-#endif
-#ifndef _POSIX_V6_ILP32_OFF32
+# endif
+# ifndef _POSIX_V6_ILP32_OFF32
case _SC_V6_ILP32_OFF32:
-#endif
-#ifndef _POSIX_V6_ILP32_OFFBIG
+# endif
+# ifndef _POSIX_V6_ILP32_OFFBIG
case _SC_V6_ILP32_OFFBIG:
-#endif
-#ifndef _POSIX_V6_LP64_OFF64
+# endif
+# ifndef _POSIX_V6_LP64_OFF64
case _SC_V6_LP64_OFF64:
-#endif
-#ifndef _POSIX_V6_LPBIG_OFFBIG
+# endif
+# ifndef _POSIX_V6_LPBIG_OFFBIG
case _SC_V6_LPBIG_OFFBIG:
-#endif
-#ifndef _POSIX_V7_ILP32_OFF32
+# endif
+# ifndef _POSIX_V7_ILP32_OFF32
case _SC_V7_ILP32_OFF32:
-#endif
-#ifndef _POSIX_V7_ILP32_OFFBIG
+# endif
+# ifndef _POSIX_V7_ILP32_OFFBIG
case _SC_V7_ILP32_OFFBIG:
-#endif
-#ifndef _POSIX_V7_LP64_OFF64
+# endif
+# ifndef _POSIX_V7_LP64_OFF64
case _SC_V7_LP64_OFF64:
-#endif
-#ifndef _POSIX_V7_LPBIG_OFFBIG
+# endif
+# ifndef _POSIX_V7_LPBIG_OFFBIG
case _SC_V7_LPBIG_OFFBIG:
-#endif
+# endif
{
const char *args[argc + 3];
size_t spec_len = strlen (spec);
@@ -592,6 +627,7 @@ environment SPEC.\n\n"));
break;
}
}
+#endif
if (argc > 1 && strcmp (argv[1], "-a") == 0)
{
diff --git a/posix/getegid.c b/posix/getegid.c
index ac6dd0bec9..bc141152a2 100644
--- a/posix/getegid.c
+++ b/posix/getegid.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/posix/geteuid.c b/posix/geteuid.c
index c84de11cb2..d1b8b03478 100644
--- a/posix/geteuid.c
+++ b/posix/geteuid.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/posix/getgid.c b/posix/getgid.c
index 5e061db76c..1a5ba2bd4e 100644
--- a/posix/getgid.c
+++ b/posix/getgid.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/posix/getgroups.c b/posix/getgroups.c
index 45604ff69d..e6834bc982 100644
--- a/posix/getgroups.c
+++ b/posix/getgroups.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/posix/getopt.c b/posix/getopt.c
index d6459a6f56..4b832208f8 100644
--- a/posix/getopt.c
+++ b/posix/getopt.c
@@ -1,9 +1,7 @@
/* Getopt for GNU.
- NOTE: getopt is part of the C library, so if you don't know what
- "Keep this file name-space clean" means, talk to drepper@gnu.org
- before changing it!
- Copyright (C) 1987-2016 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
+ Copyright (C) 1987-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library and is also part of gnulib.
+ Patches to this file should be submitted to both projects.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -19,102 +17,86 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
-/* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>.
- Ditto for AIX 3.2 and <stdlib.h>. */
-#ifndef _NO_PROTO
-# define _NO_PROTO
-#endif
-
-#ifdef HAVE_CONFIG_H
+#ifndef _LIBC
# include <config.h>
#endif
-#include <stdio.h>
-
-/* Comment out all this code if we are using the GNU C Library, and are not
- actually compiling the library itself. This code is part of the GNU C
- Library, but also included in many other GNU distributions. Compiling
- and linking in this code is a waste when using the GNU C library
- (especially if it is a shared library). Rather than having every GNU
- program understand `configure --with-gnu-libc' and omit the object files,
- it is simpler to just do this in the source for each such file. */
-
-#define GETOPT_INTERFACE_VERSION 2
-#if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2
-# include <gnu-versions.h>
-# if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION
-# define ELIDE_CODE
-# endif
-#endif
-
-#ifndef ELIDE_CODE
-
-
-/* This needs to come after some library #include
- to get __GNU_LIBRARY__ defined. */
-#ifdef __GNU_LIBRARY__
-/* Don't include stdlib.h for non-GNU C libraries because some of them
- contain conflicting prototypes for getopt. */
-# include <stdlib.h>
-# include <unistd.h>
-#endif /* GNU C library. */
+#include "getopt.h"
+#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
-
-#ifdef VMS
-# include <unixlib.h>
-#endif
+#include <unistd.h>
#ifdef _LIBC
+/* When used as part of glibc, error printing must be done differently
+ for standards compliance. getopt is not a cancellation point, so
+ it must not call functions that are, and it is specified by an
+ older standard than stdio locking, so it must not refer to
+ functions in the "user namespace" related to stdio locking.
+ Finally, it must use glibc's internal message translation so that
+ the messages are looked up in the proper text domain. */
# include <libintl.h>
+# define fprintf __fxprintf_nocancel
+# define flockfile(fp) _IO_flockfile (fp)
+# define funlockfile(fp) _IO_funlockfile (fp)
#else
# include "gettext.h"
# define _(msgid) gettext (msgid)
+/* When used standalone, flockfile and funlockfile might not be
+ available. */
+# ifndef _POSIX_THREAD_SAFE_FUNCTIONS
+# define flockfile(fp) /* nop */
+# define funlockfile(fp) /* nop */
+# endif
+/* When used standalone, do not attempt to use alloca. */
+# define __libc_use_alloca(size) 0
+# undef alloca
+# define alloca(size) (abort (), (void *)0)
#endif
-#if defined _LIBC
-# include <wchar.h>
-#endif
-
-#ifndef attribute_hidden
-# define attribute_hidden
-#endif
-
-/* This version of `getopt' appears to the caller like standard Unix `getopt'
- but it behaves differently for the user, since it allows the user
- to intersperse the options with the other arguments.
+/* This implementation of 'getopt' has three modes for handling
+ options interspersed with non-option arguments. It can stop
+ scanning for options at the first non-option argument encountered,
+ as POSIX specifies. It can continue scanning for options after the
+ first non-option argument, but permute 'argv' as it goes so that,
+ after 'getopt' is done, all the options precede all the non-option
+ arguments and 'optind' points to the first non-option argument.
+ Or, it can report non-option arguments as if they were arguments to
+ the option character '\x01'.
+
+ The default behavior of 'getopt_long' is to permute the argument list.
+ When this implementation is used standalone, the default behavior of
+ 'getopt' is to stop at the first non-option argument, but when it is
+ used as part of GNU libc it also permutes the argument list. In both
+ cases, setting the environment variable POSIXLY_CORRECT to any value
+ disables permutation.
+
+ If the first character of the OPTSTRING argument to 'getopt' or
+ 'getopt_long' is '+', both functions will stop at the first
+ non-option argument. If it is '-', both functions will report
+ non-option arguments as arguments to the option character '\x01'. */
- As `getopt' works, it permutes the elements of ARGV so that,
- when it is done, all the options precede everything else. Thus
- all application programs are extended to handle flexible argument order.
-
- Setting the environment variable POSIXLY_CORRECT disables permutation.
- Then the behavior is completely standard.
-
- GNU application programs can use a third alternative mode in which
- they can distinguish the relative order of options and other arguments. */
-
-#include "getopt.h"
#include "getopt_int.h"
-/* For communication from `getopt' to the caller.
- When `getopt' finds an option that takes an argument,
+/* For communication from 'getopt' to the caller.
+ When 'getopt' finds an option that takes an argument,
the argument value is returned here.
- Also, when `ordering' is RETURN_IN_ORDER,
+ Also, when 'ordering' is RETURN_IN_ORDER,
each non-option ARGV-element is returned here. */
char *optarg;
/* Index in ARGV of the next element to be scanned.
This is used for communication to and from the caller
- and for communication between successive calls to `getopt'.
+ and for communication between successive calls to 'getopt'.
- On entry to `getopt', zero means this is the first call; initialize.
+ On entry to 'getopt', zero means this is the first call; initialize.
- When `getopt' returns -1, this is the index of the first of the
+ When 'getopt' returns -1, this is the index of the first of the
non-option elements that the caller should itself scan.
- Otherwise, `optind' communicates from one call to the next
+ Otherwise, 'optind' communicates from one call to the next
how much of ARGV has been scanned so far. */
/* 1003.2 says this must be 1 before any call. */
@@ -134,56 +116,14 @@ int optopt = '?';
/* Keep a global copy of all internal members of getopt_data. */
static struct _getopt_data getopt_data;
-
-#ifndef __GNU_LIBRARY__
-
-/* Avoid depending on library functions or files
- whose names are inconsistent. */
-
-#ifndef getenv
-extern char *getenv ();
-#endif
-
-#endif /* not __GNU_LIBRARY__ */
-
-#ifdef _LIBC
-/* Stored original parameters.
- XXX This is no good solution. We should rather copy the args so
- that we can compare them later. But we must not use malloc(3). */
-extern int __libc_argc;
-extern char **__libc_argv;
-
-/* Bash 2.0 gives us an environment variable containing flags
- indicating ARGV elements that should not be considered arguments. */
-
-# ifdef USE_NONOPTION_FLAGS
-/* Defined in getopt_init.c */
-extern char *__getopt_nonoption_flags;
-# endif
-
-# ifdef USE_NONOPTION_FLAGS
-# define SWAP_FLAGS(ch1, ch2) \
- if (d->__nonoption_flags_len > 0) \
- { \
- char __tmp = __getopt_nonoption_flags[ch1]; \
- __getopt_nonoption_flags[ch1] = __getopt_nonoption_flags[ch2]; \
- __getopt_nonoption_flags[ch2] = __tmp; \
- }
-# else
-# define SWAP_FLAGS(ch1, ch2)
-# endif
-#else /* !_LIBC */
-# define SWAP_FLAGS(ch1, ch2)
-#endif /* _LIBC */
-
/* Exchange two adjacent subsequences of ARGV.
One subsequence is elements [first_nonopt,last_nonopt)
which contains all the non-options that have been skipped so far.
The other is elements [last_nonopt,optind), which contains all
the options processed since those non-options were skipped.
- `first_nonopt' and `last_nonopt' are relocated so that they describe
+ 'first_nonopt' and 'last_nonopt' are relocated so that they describe
the new indices of the non-options in ARGV after they are moved. */
static void
@@ -199,28 +139,6 @@ exchange (char **argv, struct _getopt_data *d)
It leaves the longer segment in the right place overall,
but it consists of two parts that need to be swapped next. */
-#if defined _LIBC && defined USE_NONOPTION_FLAGS
- /* First make sure the handling of the `__getopt_nonoption_flags'
- string can work normally. Our top argument must be in the range
- of the string. */
- if (d->__nonoption_flags_len > 0 && top >= d->__nonoption_flags_max_len)
- {
- /* We must extend the array. The user plays games with us and
- presents new arguments. */
- char *new_str = malloc (top + 1);
- if (new_str == NULL)
- d->__nonoption_flags_len = d->__nonoption_flags_max_len = 0;
- else
- {
- memset (__mempcpy (new_str, __getopt_nonoption_flags,
- d->__nonoption_flags_max_len),
- '\0', top + 1 - d->__nonoption_flags_max_len);
- d->__nonoption_flags_max_len = top + 1;
- __getopt_nonoption_flags = new_str;
- }
- }
-#endif
-
while (top > middle && middle > bottom)
{
if (top - middle > middle - bottom)
@@ -235,7 +153,6 @@ exchange (char **argv, struct _getopt_data *d)
tem = argv[bottom + i];
argv[bottom + i] = argv[top - (middle - bottom) + i];
argv[top - (middle - bottom) + i] = tem;
- SWAP_FLAGS (bottom + i, top - (middle - bottom) + i);
}
/* Exclude the moved bottom segment from further swapping. */
top -= len;
@@ -252,7 +169,6 @@ exchange (char **argv, struct _getopt_data *d)
tem = argv[bottom + i];
argv[bottom + i] = argv[middle + i];
argv[middle + i] = tem;
- SWAP_FLAGS (bottom + i, middle + i);
}
/* Exclude the moved top segment from further swapping. */
bottom += len;
@@ -265,24 +181,216 @@ exchange (char **argv, struct _getopt_data *d)
d->__last_nonopt = d->optind;
}
-/* Initialize the internal data when the first call is made. */
+/* Process the argument starting with d->__nextchar as a long option.
+ d->optind should *not* have been advanced over this argument.
+
+ If the value returned is -1, it was not actually a long option, the
+ state is unchanged, and the argument should be processed as a set
+ of short options (this can only happen when long_only is true).
+ Otherwise, the option (and its argument, if any) have been consumed
+ and the return value is the value to return from _getopt_internal_r. */
+static int
+process_long_option (int argc, char **argv, const char *optstring,
+ const struct option *longopts, int *longind,
+ int long_only, struct _getopt_data *d,
+ int print_errors, const char *prefix)
+{
+ char *nameend;
+ size_t namelen;
+ const struct option *p;
+ const struct option *pfound = NULL;
+ int n_options;
+ int option_index;
+
+ for (nameend = d->__nextchar; *nameend && *nameend != '='; nameend++)
+ /* Do nothing. */ ;
+ namelen = nameend - d->__nextchar;
+
+ /* First look for an exact match, counting the options as a side
+ effect. */
+ for (p = longopts, n_options = 0; p->name; p++, n_options++)
+ if (!strncmp (p->name, d->__nextchar, namelen)
+ && namelen == strlen (p->name))
+ {
+ /* Exact match found. */
+ pfound = p;
+ option_index = n_options;
+ break;
+ }
+
+ if (pfound == NULL)
+ {
+ /* Didn't find an exact match, so look for abbreviations. */
+ unsigned char *ambig_set = NULL;
+ int ambig_malloced = 0;
+ int ambig_fallback = 0;
+ int indfound = -1;
+
+ for (p = longopts, option_index = 0; p->name; p++, option_index++)
+ if (!strncmp (p->name, d->__nextchar, namelen))
+ {
+ if (pfound == NULL)
+ {
+ /* First nonexact match found. */
+ pfound = p;
+ indfound = option_index;
+ }
+ else if (long_only
+ || pfound->has_arg != p->has_arg
+ || pfound->flag != p->flag
+ || pfound->val != p->val)
+ {
+ /* Second or later nonexact match found. */
+ if (!ambig_fallback)
+ {
+ if (!print_errors)
+ /* Don't waste effort tracking the ambig set if
+ we're not going to print it anyway. */
+ ambig_fallback = 1;
+ else if (!ambig_set)
+ {
+ if (__libc_use_alloca (n_options))
+ ambig_set = alloca (n_options);
+ else if ((ambig_set = malloc (n_options)) == NULL)
+ /* Fall back to simpler error message. */
+ ambig_fallback = 1;
+ else
+ ambig_malloced = 1;
+
+ if (ambig_set)
+ {
+ memset (ambig_set, 0, n_options);
+ ambig_set[indfound] = 1;
+ }
+ }
+ if (ambig_set)
+ ambig_set[option_index] = 1;
+ }
+ }
+ }
+
+ if (ambig_set || ambig_fallback)
+ {
+ if (print_errors)
+ {
+ if (ambig_fallback)
+ fprintf (stderr, _("%s: option '%s%s' is ambiguous\n"),
+ argv[0], prefix, d->__nextchar);
+ else
+ {
+ flockfile (stderr);
+ fprintf (stderr,
+ _("%s: option '%s%s' is ambiguous; possibilities:"),
+ argv[0], prefix, d->__nextchar);
+
+ for (option_index = 0; option_index < n_options; option_index++)
+ if (ambig_set[option_index])
+ fprintf (stderr, " '%s%s'",
+ prefix, longopts[option_index].name);
+
+ /* This must use 'fprintf' even though it's only
+ printing a single character, so that it goes through
+ __fxprintf_nocancel when compiled as part of glibc. */
+ fprintf (stderr, "\n");
+ funlockfile (stderr);
+ }
+ }
+ if (ambig_malloced)
+ free (ambig_set);
+ d->__nextchar += strlen (d->__nextchar);
+ d->optind++;
+ d->optopt = 0;
+ return '?';
+ }
+
+ option_index = indfound;
+ }
+
+ if (pfound == NULL)
+ {
+ /* Can't find it as a long option. If this is not getopt_long_only,
+ or the option starts with '--' or is not a valid short option,
+ then it's an error. */
+ if (!long_only || argv[d->optind][1] == '-'
+ || strchr (optstring, *d->__nextchar) == NULL)
+ {
+ if (print_errors)
+ fprintf (stderr, _("%s: unrecognized option '%s%s'\n"),
+ argv[0], prefix, d->__nextchar);
+
+ d->__nextchar = NULL;
+ d->optind++;
+ d->optopt = 0;
+ return '?';
+ }
+
+ /* Otherwise interpret it as a short option. */
+ return -1;
+ }
+
+ /* We have found a matching long option. Consume it. */
+ d->optind++;
+ d->__nextchar = NULL;
+ if (*nameend)
+ {
+ /* Don't test has_arg with >, because some C compilers don't
+ allow it to be used on enums. */
+ if (pfound->has_arg)
+ d->optarg = nameend + 1;
+ else
+ {
+ if (print_errors)
+ fprintf (stderr,
+ _("%s: option '%s%s' doesn't allow an argument\n"),
+ argv[0], prefix, pfound->name);
+
+ d->optopt = pfound->val;
+ return '?';
+ }
+ }
+ else if (pfound->has_arg == 1)
+ {
+ if (d->optind < argc)
+ d->optarg = argv[d->optind++];
+ else
+ {
+ if (print_errors)
+ fprintf (stderr,
+ _("%s: option '%s%s' requires an argument\n"),
+ argv[0], prefix, pfound->name);
+
+ d->optopt = pfound->val;
+ return optstring[0] == ':' ? ':' : '?';
+ }
+ }
+
+ if (longind != NULL)
+ *longind = option_index;
+ if (pfound->flag)
+ {
+ *(pfound->flag) = pfound->val;
+ return 0;
+ }
+ return pfound->val;
+}
+
+/* Initialize internal data upon the first call to getopt. */
static const char *
-_getopt_initialize (int argc, char *const *argv, const char *optstring,
+_getopt_initialize (int argc _GL_UNUSED,
+ char **argv _GL_UNUSED, const char *optstring,
struct _getopt_data *d, int posixly_correct)
{
/* Start processing options with ARGV-element 1 (since ARGV-element 0
is the program name); the sequence of previously skipped
non-option ARGV-elements is empty. */
+ if (d->optind == 0)
+ d->optind = 1;
d->__first_nonopt = d->__last_nonopt = d->optind;
-
d->__nextchar = NULL;
- d->__posixly_correct = posixly_correct | !!getenv ("POSIXLY_CORRECT");
-
/* Determine how to handle the ordering of options and nonoptions. */
-
if (optstring[0] == '-')
{
d->__ordering = RETURN_IN_ORDER;
@@ -293,41 +401,12 @@ _getopt_initialize (int argc, char *const *argv, const char *optstring,
d->__ordering = REQUIRE_ORDER;
++optstring;
}
- else if (d->__posixly_correct)
+ else if (posixly_correct || !!getenv ("POSIXLY_CORRECT"))
d->__ordering = REQUIRE_ORDER;
else
d->__ordering = PERMUTE;
-#if defined _LIBC && defined USE_NONOPTION_FLAGS
- if (!d->__posixly_correct
- && argc == __libc_argc && argv == __libc_argv)
- {
- if (d->__nonoption_flags_max_len == 0)
- {
- if (__getopt_nonoption_flags == NULL
- || __getopt_nonoption_flags[0] == '\0')
- d->__nonoption_flags_max_len = -1;
- else
- {
- const char *orig_str = __getopt_nonoption_flags;
- int len = d->__nonoption_flags_max_len = strlen (orig_str);
- if (d->__nonoption_flags_max_len < argc)
- d->__nonoption_flags_max_len = argc;
- __getopt_nonoption_flags =
- (char *) malloc (d->__nonoption_flags_max_len);
- if (__getopt_nonoption_flags == NULL)
- d->__nonoption_flags_max_len = -1;
- else
- memset (__mempcpy (__getopt_nonoption_flags, orig_str, len),
- '\0', d->__nonoption_flags_max_len - len);
- }
- }
- d->__nonoption_flags_len = d->__nonoption_flags_max_len;
- }
- else
- d->__nonoption_flags_len = 0;
-#endif
-
+ d->__initialized = 1;
return optstring;
}
@@ -336,48 +415,48 @@ _getopt_initialize (int argc, char *const *argv, const char *optstring,
If an element of ARGV starts with '-', and is not exactly "-" or "--",
then it is an option element. The characters of this element
- (aside from the initial '-') are option characters. If `getopt'
+ (aside from the initial '-') are option characters. If 'getopt'
is called repeatedly, it returns successively each of the option characters
from each of the option elements.
- If `getopt' finds another option character, it returns that character,
- updating `optind' and `nextchar' so that the next call to `getopt' can
+ If 'getopt' finds another option character, it returns that character,
+ updating 'optind' and 'nextchar' so that the next call to 'getopt' can
resume the scan with the following option character or ARGV-element.
- If there are no more option characters, `getopt' returns -1.
- Then `optind' is the index in ARGV of the first ARGV-element
+ If there are no more option characters, 'getopt' returns -1.
+ Then 'optind' is the index in ARGV of the first ARGV-element
that is not an option. (The ARGV-elements have been permuted
so that those that are not options now come last.)
OPTSTRING is a string containing the legitimate option characters.
If an option character is seen that is not listed in OPTSTRING,
- return '?' after printing an error message. If you set `opterr' to
+ return '?' after printing an error message. If you set 'opterr' to
zero, the error message is suppressed but we still return '?'.
If a char in OPTSTRING is followed by a colon, that means it wants an arg,
so the following text in the same ARGV-element, or the text of the following
- ARGV-element, is returned in `optarg'. Two colons mean an option that
+ ARGV-element, is returned in 'optarg'. Two colons mean an option that
wants an optional arg; if there is text in the current ARGV-element,
- it is returned in `optarg', otherwise `optarg' is set to zero.
+ it is returned in 'optarg', otherwise 'optarg' is set to zero.
- If OPTSTRING starts with `-' or `+', it requests different methods of
+ If OPTSTRING starts with '-' or '+', it requests different methods of
handling the non-option ARGV-elements.
See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above.
- Long-named options begin with `--' instead of `-'.
+ Long-named options begin with '--' instead of '-'.
Their names may be abbreviated as long as the abbreviation is unique
or is an exact match for some defined option. If they have an
argument, it follows the option name in the same ARGV-element, separated
- from the option name by a `=', or else the in next ARGV-element.
- When `getopt' finds a long-named option, it returns 0 if that option's
- `flag' field is nonzero, the value of the option's `val' field
- if the `flag' field is zero.
+ from the option name by a '=', or else the in next ARGV-element.
+ When 'getopt' finds a long-named option, it returns 0 if that option's
+ 'flag' field is nonzero, the value of the option's 'val' field
+ if the 'flag' field is zero.
The elements of ARGV aren't really const, because we permute them.
But we pretend they're const in the prototype to be compatible
with other systems.
- LONGOPTS is a vector of `struct option' terminated by an
+ LONGOPTS is a vector of 'struct option' terminated by an
element containing a name which is zero.
LONGIND returns the index in LONGOPT of the long-named option found.
@@ -388,7 +467,7 @@ _getopt_initialize (int argc, char *const *argv, const char *optstring,
long-named options. */
int
-_getopt_internal_r (int argc, char *const *argv, const char *optstring,
+_getopt_internal_r (int argc, char **argv, const char *optstring,
const struct option *longopts, int *longind,
int long_only, struct _getopt_data *d, int posixly_correct)
{
@@ -400,29 +479,15 @@ _getopt_internal_r (int argc, char *const *argv, const char *optstring,
d->optarg = NULL;
if (d->optind == 0 || !d->__initialized)
- {
- if (d->optind == 0)
- d->optind = 1; /* Don't scan ARGV[0], the program name. */
- optstring = _getopt_initialize (argc, argv, optstring, d,
- posixly_correct);
- d->__initialized = 1;
- }
+ optstring = _getopt_initialize (argc, argv, optstring, d, posixly_correct);
else if (optstring[0] == '-' || optstring[0] == '+')
optstring++;
+
if (optstring[0] == ':')
print_errors = 0;
- /* Test whether ARGV[optind] points to a non-option argument.
- Either it does not have option syntax, or there is an environment flag
- from the shell indicating it is not an option. The later information
- is only used when the used in the GNU libc. */
-#if defined _LIBC && defined USE_NONOPTION_FLAGS
-# define NONOPTION_P (argv[d->optind][0] != '-' || argv[d->optind][1] == '\0' \
- || (d->optind < d->__nonoption_flags_len \
- && __getopt_nonoption_flags[d->optind] == '1'))
-#else
-# define NONOPTION_P (argv[d->optind][0] != '-' || argv[d->optind][1] == '\0')
-#endif
+ /* Test whether ARGV[optind] points to a non-option argument. */
+#define NONOPTION_P (argv[d->optind][0] != '-' || argv[d->optind][1] == '\0')
if (d->__nextchar == NULL || *d->__nextchar == '\0')
{
@@ -442,7 +507,7 @@ _getopt_internal_r (int argc, char *const *argv, const char *optstring,
if (d->__first_nonopt != d->__last_nonopt
&& d->__last_nonopt != d->optind)
- exchange ((char **) argv, d);
+ exchange (argv, d);
else if (d->__last_nonopt != d->optind)
d->__first_nonopt = d->optind;
@@ -454,7 +519,7 @@ _getopt_internal_r (int argc, char *const *argv, const char *optstring,
d->__last_nonopt = d->optind;
}
- /* The special ARGV-element `--' means premature end of options.
+ /* The special ARGV-element '--' means premature end of options.
Skip it like a null option,
then exchange with previous non-options as if it were an option,
then skip everything else like a non-option. */
@@ -465,7 +530,7 @@ _getopt_internal_r (int argc, char *const *argv, const char *optstring,
if (d->__first_nonopt != d->__last_nonopt
&& d->__last_nonopt != d->optind)
- exchange ((char **) argv, d);
+ exchange (argv, d);
else if (d->__first_nonopt == d->__last_nonopt)
d->__first_nonopt = d->optind;
d->__last_nonopt = argc;
@@ -497,426 +562,79 @@ _getopt_internal_r (int argc, char *const *argv, const char *optstring,
}
/* We have found another option-ARGV-element.
- Skip the initial punctuation. */
-
- d->__nextchar = (argv[d->optind] + 1
- + (longopts != NULL && argv[d->optind][1] == '-'));
- }
-
- /* Decode the current option-ARGV-element. */
-
- /* Check whether the ARGV-element is a long option.
-
- If long_only and the ARGV-element has the form "-f", where f is
- a valid short option, don't consider it an abbreviated form of
- a long option that starts with f. Otherwise there would be no
- way to give the -f short option.
-
- On the other hand, if there's a long option "fubar" and
- the ARGV-element is "-fu", do consider that an abbreviation of
- the long option, just like "--fu", and not "-f" with arg "u".
-
- This distinction seems to be the most useful approach. */
-
- if (longopts != NULL
- && (argv[d->optind][1] == '-'
- || (long_only && (argv[d->optind][2]
- || !strchr (optstring, argv[d->optind][1])))))
- {
- char *nameend;
- unsigned int namelen;
- const struct option *p;
- const struct option *pfound = NULL;
- struct option_list
- {
- const struct option *p;
- struct option_list *next;
- } *ambig_list = NULL;
- int exact = 0;
- int indfound = -1;
- int option_index;
-
- for (nameend = d->__nextchar; *nameend && *nameend != '='; nameend++)
- /* Do nothing. */ ;
- namelen = nameend - d->__nextchar;
-
- /* Test all long options for either exact match
- or abbreviated matches. */
- for (p = longopts, option_index = 0; p->name; p++, option_index++)
- if (!strncmp (p->name, d->__nextchar, namelen))
- {
- if (namelen == (unsigned int) strlen (p->name))
- {
- /* Exact match found. */
- pfound = p;
- indfound = option_index;
- exact = 1;
- break;
- }
- else if (pfound == NULL)
- {
- /* First nonexact match found. */
- pfound = p;
- indfound = option_index;
- }
- else if (long_only
- || pfound->has_arg != p->has_arg
- || pfound->flag != p->flag
- || pfound->val != p->val)
- {
- /* Second or later nonexact match found. */
- struct option_list *newp = alloca (sizeof (*newp));
- newp->p = p;
- newp->next = ambig_list;
- ambig_list = newp;
- }
- }
-
- if (ambig_list != NULL && !exact)
+ Check whether it might be a long option. */
+ if (longopts)
{
- if (print_errors)
+ if (argv[d->optind][1] == '-')
{
- struct option_list first;
- first.p = pfound;
- first.next = ambig_list;
- ambig_list = &first;
-
-#if defined _LIBC
- char *buf = NULL;
- size_t buflen = 0;
-
- FILE *fp = __open_memstream (&buf, &buflen);
- if (fp != NULL)
- {
- fprintf (fp,
- _("%s: option '%s' is ambiguous; possibilities:"),
- argv[0], argv[d->optind]);
-
- do
- {
- fprintf (fp, " '--%s'", ambig_list->p->name);
- ambig_list = ambig_list->next;
- }
- while (ambig_list != NULL);
-
- fputc_unlocked ('\n', fp);
-
- if (__glibc_likely (fclose (fp) != EOF))
- {
- _IO_flockfile (stderr);
-
- int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
- ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL;
-
- __fxprintf (NULL, "%s", buf);
-
- ((_IO_FILE *) stderr)->_flags2 = old_flags2;
- _IO_funlockfile (stderr);
-
- free (buf);
- }
- }
-#else
- fprintf (stderr,
- _("%s: option '%s' is ambiguous; possibilities:"),
- argv[0], argv[d->optind]);
- do
- {
- fprintf (stderr, " '--%s'", ambig_list->p->name);
- ambig_list = ambig_list->next;
- }
- while (ambig_list != NULL);
-
- fputc ('\n', stderr);
-#endif
+ /* "--foo" is always a long option. The special option
+ "--" was handled above. */
+ d->__nextchar = argv[d->optind] + 2;
+ return process_long_option (argc, argv, optstring, longopts,
+ longind, long_only, d,
+ print_errors, "--");
}
- d->__nextchar += strlen (d->__nextchar);
- d->optind++;
- d->optopt = 0;
- return '?';
- }
-
- if (pfound != NULL)
- {
- option_index = indfound;
- d->optind++;
- if (*nameend)
- {
- /* Don't test has_arg with >, because some C compilers don't
- allow it to be used on enums. */
- if (pfound->has_arg)
- d->optarg = nameend + 1;
- else
- {
- if (print_errors)
- {
-#if defined _LIBC
- char *buf;
- int n;
-#endif
-
- if (argv[d->optind - 1][1] == '-')
- {
- /* --option */
-#if defined _LIBC
- n = __asprintf (&buf, _("\
-%s: option '--%s' doesn't allow an argument\n"),
- argv[0], pfound->name);
-#else
- fprintf (stderr, _("\
-%s: option '--%s' doesn't allow an argument\n"),
- argv[0], pfound->name);
-#endif
- }
- else
- {
- /* +option or -option */
-#if defined _LIBC
- n = __asprintf (&buf, _("\
-%s: option '%c%s' doesn't allow an argument\n"),
- argv[0], argv[d->optind - 1][0],
- pfound->name);
-#else
- fprintf (stderr, _("\
-%s: option '%c%s' doesn't allow an argument\n"),
- argv[0], argv[d->optind - 1][0],
- pfound->name);
-#endif
- }
-
-#if defined _LIBC
- if (n >= 0)
- {
- _IO_flockfile (stderr);
-
- int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
- ((_IO_FILE *) stderr)->_flags2
- |= _IO_FLAGS2_NOTCANCEL;
- __fxprintf (NULL, "%s", buf);
+ /* If long_only and the ARGV-element has the form "-f",
+ where f is a valid short option, don't consider it an
+ abbreviated form of a long option that starts with f.
+ Otherwise there would be no way to give the -f short
+ option.
- ((_IO_FILE *) stderr)->_flags2 = old_flags2;
- _IO_funlockfile (stderr);
+ On the other hand, if there's a long option "fubar" and
+ the ARGV-element is "-fu", do consider that an
+ abbreviation of the long option, just like "--fu", and
+ not "-f" with arg "u".
- free (buf);
- }
-#endif
- }
-
- d->__nextchar += strlen (d->__nextchar);
-
- d->optopt = pfound->val;
- return '?';
- }
- }
- else if (pfound->has_arg == 1)
+ This distinction seems to be the most useful approach. */
+ if (long_only && (argv[d->optind][2]
+ || !strchr (optstring, argv[d->optind][1])))
{
- if (d->optind < argc)
- d->optarg = argv[d->optind++];
- else
- {
- if (print_errors)
- {
-#if defined _LIBC
- char *buf;
-
- if (__asprintf (&buf, _("\
-%s: option '--%s' requires an argument\n"),
- argv[0], pfound->name) >= 0)
- {
- _IO_flockfile (stderr);
-
- int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
- ((_IO_FILE *) stderr)->_flags2
- |= _IO_FLAGS2_NOTCANCEL;
-
- __fxprintf (NULL, "%s", buf);
-
- ((_IO_FILE *) stderr)->_flags2 = old_flags2;
- _IO_funlockfile (stderr);
-
- free (buf);
- }
-#else
- fprintf (stderr,
- _("%s: option '--%s' requires an argument\n"),
- argv[0], pfound->name);
-#endif
- }
- d->__nextchar += strlen (d->__nextchar);
- d->optopt = pfound->val;
- return optstring[0] == ':' ? ':' : '?';
- }
- }
- d->__nextchar += strlen (d->__nextchar);
- if (longind != NULL)
- *longind = option_index;
- if (pfound->flag)
- {
- *(pfound->flag) = pfound->val;
- return 0;
+ int code;
+ d->__nextchar = argv[d->optind] + 1;
+ code = process_long_option (argc, argv, optstring, longopts,
+ longind, long_only, d,
+ print_errors, "-");
+ if (code != -1)
+ return code;
}
- return pfound->val;
}
- /* Can't find it as a long option. If this is not getopt_long_only,
- or the option starts with '--' or is not a valid short
- option, then it's an error.
- Otherwise interpret it as a short option. */
- if (!long_only || argv[d->optind][1] == '-'
- || strchr (optstring, *d->__nextchar) == NULL)
- {
- if (print_errors)
- {
-#if defined _LIBC
- char *buf;
- int n;
-#endif
-
- if (argv[d->optind][1] == '-')
- {
- /* --option */
-#if defined _LIBC
- n = __asprintf (&buf, _("%s: unrecognized option '--%s'\n"),
- argv[0], d->__nextchar);
-#else
- fprintf (stderr, _("%s: unrecognized option '--%s'\n"),
- argv[0], d->__nextchar);
-#endif
- }
- else
- {
- /* +option or -option */
-#if defined _LIBC
- n = __asprintf (&buf, _("%s: unrecognized option '%c%s'\n"),
- argv[0], argv[d->optind][0], d->__nextchar);
-#else
- fprintf (stderr, _("%s: unrecognized option '%c%s'\n"),
- argv[0], argv[d->optind][0], d->__nextchar);
-#endif
- }
-
-#if defined _LIBC
- if (n >= 0)
- {
- _IO_flockfile (stderr);
-
- int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
- ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL;
-
- __fxprintf (NULL, "%s", buf);
-
- ((_IO_FILE *) stderr)->_flags2 = old_flags2;
- _IO_funlockfile (stderr);
-
- free (buf);
- }
-#endif
- }
- d->__nextchar = (char *) "";
- d->optind++;
- d->optopt = 0;
- return '?';
- }
+ /* It is not a long option. Skip the initial punctuation. */
+ d->__nextchar = argv[d->optind] + 1;
}
/* Look at and handle the next short option-character. */
{
char c = *d->__nextchar++;
- char *temp = strchr (optstring, c);
+ const char *temp = strchr (optstring, c);
- /* Increment `optind' when we start to process its last character. */
+ /* Increment 'optind' when we start to process its last character. */
if (*d->__nextchar == '\0')
++d->optind;
if (temp == NULL || c == ':' || c == ';')
{
if (print_errors)
- {
-#if defined _LIBC
- char *buf;
- int n;
-#endif
-
-#if defined _LIBC
- n = __asprintf (&buf, _("%s: invalid option -- '%c'\n"),
- argv[0], c);
-#else
- fprintf (stderr, _("%s: invalid option -- '%c'\n"), argv[0], c);
-#endif
-
-#if defined _LIBC
- if (n >= 0)
- {
- _IO_flockfile (stderr);
-
- int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
- ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL;
-
- __fxprintf (NULL, "%s", buf);
-
- ((_IO_FILE *) stderr)->_flags2 = old_flags2;
- _IO_funlockfile (stderr);
-
- free (buf);
- }
-#endif
- }
+ fprintf (stderr, _("%s: invalid option -- '%c'\n"), argv[0], c);
d->optopt = c;
return '?';
}
+
/* Convenience. Treat POSIX -W foo same as long option --foo */
- if (temp[0] == 'W' && temp[1] == ';')
+ if (temp[0] == 'W' && temp[1] == ';' && longopts != NULL)
{
- if (longopts == NULL)
- goto no_longs;
-
- char *nameend;
- const struct option *p;
- const struct option *pfound = NULL;
- int exact = 0;
- int ambig = 0;
- int indfound = 0;
- int option_index;
-
/* This is an option that requires an argument. */
if (*d->__nextchar != '\0')
- {
- d->optarg = d->__nextchar;
- /* If we end this ARGV-element by taking the rest as an arg,
- we must advance to the next element now. */
- d->optind++;
- }
+ d->optarg = d->__nextchar;
else if (d->optind == argc)
{
if (print_errors)
- {
-#if defined _LIBC
- char *buf;
-
- if (__asprintf (&buf,
- _("%s: option requires an argument -- '%c'\n"),
- argv[0], c) >= 0)
- {
- _IO_flockfile (stderr);
-
- int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
- ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL;
-
- __fxprintf (NULL, "%s", buf);
-
- ((_IO_FILE *) stderr)->_flags2 = old_flags2;
- _IO_funlockfile (stderr);
+ fprintf (stderr,
+ _("%s: option requires an argument -- '%c'\n"),
+ argv[0], c);
- free (buf);
- }
-#else
- fprintf (stderr,
- _("%s: option requires an argument -- '%c'\n"),
- argv[0], c);
-#endif
- }
d->optopt = c;
if (optstring[0] == ':')
c = ':';
@@ -925,172 +643,12 @@ _getopt_internal_r (int argc, char *const *argv, const char *optstring,
return c;
}
else
- /* We already incremented `d->optind' once;
- increment it again when taking next ARGV-elt as argument. */
- d->optarg = argv[d->optind++];
-
- /* optarg is now the argument, see if it's in the
- table of longopts. */
-
- for (d->__nextchar = nameend = d->optarg; *nameend && *nameend != '=';
- nameend++)
- /* Do nothing. */ ;
-
- /* Test all long options for either exact match
- or abbreviated matches. */
- for (p = longopts, option_index = 0; p->name; p++, option_index++)
- if (!strncmp (p->name, d->__nextchar, nameend - d->__nextchar))
- {
- if ((unsigned int) (nameend - d->__nextchar) == strlen (p->name))
- {
- /* Exact match found. */
- pfound = p;
- indfound = option_index;
- exact = 1;
- break;
- }
- else if (pfound == NULL)
- {
- /* First nonexact match found. */
- pfound = p;
- indfound = option_index;
- }
- else if (long_only
- || pfound->has_arg != p->has_arg
- || pfound->flag != p->flag
- || pfound->val != p->val)
- /* Second or later nonexact match found. */
- ambig = 1;
- }
- if (ambig && !exact)
- {
- if (print_errors)
- {
-#if defined _LIBC
- char *buf;
+ d->optarg = argv[d->optind];
- if (__asprintf (&buf, _("%s: option '-W %s' is ambiguous\n"),
- argv[0], d->optarg) >= 0)
- {
- _IO_flockfile (stderr);
-
- int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
- ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL;
-
- __fxprintf (NULL, "%s", buf);
-
- ((_IO_FILE *) stderr)->_flags2 = old_flags2;
- _IO_funlockfile (stderr);
-
- free (buf);
- }
-#else
- fprintf (stderr, _("%s: option '-W %s' is ambiguous\n"),
- argv[0], d->optarg);
-#endif
- }
- d->__nextchar += strlen (d->__nextchar);
- d->optind++;
- return '?';
- }
- if (pfound != NULL)
- {
- option_index = indfound;
- if (*nameend)
- {
- /* Don't test has_arg with >, because some C compilers don't
- allow it to be used on enums. */
- if (pfound->has_arg)
- d->optarg = nameend + 1;
- else
- {
- if (print_errors)
- {
-#if defined _LIBC
- char *buf;
-
- if (__asprintf (&buf, _("\
-%s: option '-W %s' doesn't allow an argument\n"),
- argv[0], pfound->name) >= 0)
- {
- _IO_flockfile (stderr);
-
- int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
- ((_IO_FILE *) stderr)->_flags2
- |= _IO_FLAGS2_NOTCANCEL;
-
- __fxprintf (NULL, "%s", buf);
-
- ((_IO_FILE *) stderr)->_flags2 = old_flags2;
- _IO_funlockfile (stderr);
-
- free (buf);
- }
-#else
- fprintf (stderr, _("\
-%s: option '-W %s' doesn't allow an argument\n"),
- argv[0], pfound->name);
-#endif
- }
-
- d->__nextchar += strlen (d->__nextchar);
- return '?';
- }
- }
- else if (pfound->has_arg == 1)
- {
- if (d->optind < argc)
- d->optarg = argv[d->optind++];
- else
- {
- if (print_errors)
- {
-#if defined _LIBC
- char *buf;
-
- if (__asprintf (&buf, _("\
-%s: option '-W %s' requires an argument\n"),
- argv[0], pfound->name) >= 0)
- {
- _IO_flockfile (stderr);
-
- int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
- ((_IO_FILE *) stderr)->_flags2
- |= _IO_FLAGS2_NOTCANCEL;
-
- __fxprintf (NULL, "%s", buf);
-
- ((_IO_FILE *) stderr)->_flags2 = old_flags2;
- _IO_funlockfile (stderr);
-
- free (buf);
- }
-#else
- fprintf (stderr, _("\
-%s: option '-W %s' requires an argument\n"),
- argv[0], pfound->name);
-#endif
- }
- d->__nextchar += strlen (d->__nextchar);
- return optstring[0] == ':' ? ':' : '?';
- }
- }
- else
- d->optarg = NULL;
- d->__nextchar += strlen (d->__nextchar);
- if (longind != NULL)
- *longind = option_index;
- if (pfound->flag)
- {
- *(pfound->flag) = pfound->val;
- return 0;
- }
- return pfound->val;
- }
-
- no_longs:
- d->__nextchar = NULL;
- return 'W'; /* Let the application handle it. */
+ d->__nextchar = d->optarg;
+ d->optarg = NULL;
+ return process_long_option (argc, argv, optstring, longopts, longind,
+ 0 /* long_only */, d, print_errors, "-W ");
}
if (temp[1] == ':')
{
@@ -1119,32 +677,10 @@ _getopt_internal_r (int argc, char *const *argv, const char *optstring,
else if (d->optind == argc)
{
if (print_errors)
- {
-#if defined _LIBC
- char *buf;
+ fprintf (stderr,
+ _("%s: option requires an argument -- '%c'\n"),
+ argv[0], c);
- if (__asprintf (&buf, _("\
-%s: option requires an argument -- '%c'\n"),
- argv[0], c) >= 0)
- {
- _IO_flockfile (stderr);
-
- int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
- ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL;
-
- __fxprintf (NULL, "%s", buf);
-
- ((_IO_FILE *) stderr)->_flags2 = old_flags2;
- _IO_funlockfile (stderr);
-
- free (buf);
- }
-#else
- fprintf (stderr,
- _("%s: option requires an argument -- '%c'\n"),
- argv[0], c);
-#endif
- }
d->optopt = c;
if (optstring[0] == ':')
c = ':';
@@ -1152,7 +688,7 @@ _getopt_internal_r (int argc, char *const *argv, const char *optstring,
c = '?';
}
else
- /* We already incremented `optind' once;
+ /* We already incremented 'optind' once;
increment it again when taking next ARGV-elt as argument. */
d->optarg = argv[d->optind++];
d->__nextchar = NULL;
@@ -1163,7 +699,7 @@ _getopt_internal_r (int argc, char *const *argv, const char *optstring,
}
int
-_getopt_internal (int argc, char *const *argv, const char *optstring,
+_getopt_internal (int argc, char **argv, const char *optstring,
const struct option *longopts, int *longind, int long_only,
int posixly_correct)
{
@@ -1183,32 +719,30 @@ _getopt_internal (int argc, char *const *argv, const char *optstring,
return result;
}
-int
-getopt (int argc, char *const *argv, const char *optstring)
-{
- return _getopt_internal (argc, argv, optstring,
- (const struct option *) 0,
- (int *) 0,
- 0, 0);
-}
+/* glibc gets a LSB-compliant getopt and a POSIX-complaint __posix_getopt.
+ Standalone applications just get a POSIX-compliant getopt.
+ POSIX and LSB both require these functions to take 'char *const *argv'
+ even though this is incorrect (because of the permutation). */
+#define GETOPT_ENTRY(NAME, POSIXLY_CORRECT) \
+ int \
+ NAME (int argc, char *const *argv, const char *optstring) \
+ { \
+ return _getopt_internal (argc, (char **)argv, optstring, \
+ 0, 0, 0, POSIXLY_CORRECT); \
+ }
#ifdef _LIBC
-int
-__posix_getopt (int argc, char *const *argv, const char *optstring)
-{
- return _getopt_internal (argc, argv, optstring,
- (const struct option *) 0,
- (int *) 0,
- 0, 1);
-}
+GETOPT_ENTRY(getopt, 0)
+GETOPT_ENTRY(__posix_getopt, 1)
+#else
+GETOPT_ENTRY(getopt, 1)
#endif
-#endif /* Not ELIDE_CODE. */
#ifdef TEST
/* Compile with -DTEST to make an executable for use in testing
- the above definition of `getopt'. */
+ the above definition of 'getopt'. */
int
main (int argc, char **argv)
diff --git a/posix/getopt.h b/posix/getopt.h
index fab340ac40..afd7f6bf44 100644
--- a/posix/getopt.h
+++ b/posix/getopt.h
@@ -1,6 +1,8 @@
/* Declarations for getopt.
- Copyright (C) 1989-2016 Free Software Foundation, Inc.
+ Copyright (C) 1989-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
+ Unlike the bulk of the getopt implementation, this file is NOT part
+ of gnulib; gnulib also has a getopt.h but it is different.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -17,175 +19,20 @@
<http://www.gnu.org/licenses/>. */
#ifndef _GETOPT_H
+#define _GETOPT_H 1
-#ifndef __need_getopt
-# define _GETOPT_H 1
-#endif
-
-/* If __GNU_LIBRARY__ is not already defined, either we are being used
- standalone, or this is the first header included in the source file.
- If we are being used with glibc, we need to include <features.h>, but
- that does not exist if we are standalone. So: if __GNU_LIBRARY__ is
- not defined, include <ctype.h>, which will pull in <features.h> for us
- if it's from glibc. (Why ctype.h? It's guaranteed to exist and it
- doesn't flood the namespace with stuff the way some other headers do.) */
-#if !defined __GNU_LIBRARY__
-# include <ctype.h>
-#endif
-
-#ifndef __THROW
-# ifndef __GNUC_PREREQ
-# define __GNUC_PREREQ(maj, min) (0)
-# endif
-# if defined __cplusplus && __GNUC_PREREQ (2,8)
-# define __THROW throw ()
-# else
-# define __THROW
-# endif
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* For communication from `getopt' to the caller.
- When `getopt' finds an option that takes an argument,
- the argument value is returned here.
- Also, when `ordering' is RETURN_IN_ORDER,
- each non-option ARGV-element is returned here. */
-
-extern char *optarg;
-
-/* Index in ARGV of the next element to be scanned.
- This is used for communication to and from the caller
- and for communication between successive calls to `getopt'.
-
- On entry to `getopt', zero means this is the first call; initialize.
-
- When `getopt' returns -1, this is the index of the first of the
- non-option elements that the caller should itself scan.
-
- Otherwise, `optind' communicates from one call to the next
- how much of ARGV has been scanned so far. */
-
-extern int optind;
-
-/* Callers store zero here to inhibit the error message `getopt' prints
- for unrecognized options. */
-
-extern int opterr;
-
-/* Set to an option character which was unrecognized. */
-
-extern int optopt;
-
-#ifndef __need_getopt
-/* Describe the long-named options requested by the application.
- The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
- of `struct option' terminated by an element containing a name which is
- zero.
-
- The field `has_arg' is:
- no_argument (or 0) if the option does not take an argument,
- required_argument (or 1) if the option requires an argument,
- optional_argument (or 2) if the option takes an optional argument.
-
- If the field `flag' is not NULL, it points to a variable that is set
- to the value given in the field `val' when the option is found, but
- left unchanged if the option is not found.
-
- To have a long-named option do something other than set an `int' to
- a compiled-in constant, such as set a value from `optarg', set the
- option's `flag' field to zero and its `val' field to a nonzero
- value (the equivalent single-letter option character, if there is
- one). For long options that have a zero `flag' field, `getopt'
- returns the contents of the `val' field. */
-
-struct option
-{
- const char *name;
- /* has_arg can't be an enum because some compilers complain about
- type mismatches in all the code that assumes it is an int. */
- int has_arg;
- int *flag;
- int val;
-};
-
-/* Names for the values of the `has_arg' field of `struct option'. */
-
-# define no_argument 0
-# define required_argument 1
-# define optional_argument 2
-#endif /* need getopt */
-
-
-/* Get definitions and prototypes for functions to process the
- arguments in ARGV (ARGC of them, minus the program name) for
- options given in OPTS.
-
- Return the option character from OPTS just read. Return -1 when
- there are no more options. For unrecognized options, or options
- missing arguments, `optopt' is set to the option letter, and '?' is
- returned.
-
- The OPTS string is a list of characters which are recognized option
- letters, optionally followed by colons, specifying that that letter
- takes an argument, to be placed in `optarg'.
-
- If a letter in OPTS is followed by two colons, its argument is
- optional. This behavior is specific to the GNU `getopt'.
-
- The argument `--' causes premature termination of argument
- scanning, explicitly telling `getopt' that there are no more
- options.
-
- If OPTS begins with `--', then non-option arguments are treated as
- arguments to the option '\0'. This behavior is specific to the GNU
- `getopt'. */
-
-#ifdef __GNU_LIBRARY__
-/* Many other libraries have conflicting prototypes for getopt, with
- differences in the consts, in stdlib.h. To avoid compilation
- errors, only prototype getopt for the GNU C library. */
-extern int getopt (int ___argc, char *const *___argv, const char *__shortopts)
- __THROW;
-
-# if defined __need_getopt && defined __USE_POSIX2 \
- && !defined __USE_POSIX_IMPLICITLY && !defined __USE_GNU
-/* The GNU getopt has more functionality than the standard version. The
- additional functionality can be disable at runtime. This redirection
- helps to also do this at runtime. */
-# ifdef __REDIRECT
- extern int __REDIRECT_NTH (getopt, (int ___argc, char *const *___argv,
- const char *__shortopts),
- __posix_getopt);
-# else
-extern int __posix_getopt (int ___argc, char *const *___argv,
- const char *__shortopts) __THROW;
-# define getopt __posix_getopt
-# endif
-# endif
-#else /* not __GNU_LIBRARY__ */
-extern int getopt ();
-#endif /* __GNU_LIBRARY__ */
-
-#ifndef __need_getopt
-extern int getopt_long (int ___argc, char *const *___argv,
- const char *__shortopts,
- const struct option *__longopts, int *__longind)
- __THROW;
-extern int getopt_long_only (int ___argc, char *const *___argv,
- const char *__shortopts,
- const struct option *__longopts, int *__longind)
- __THROW;
-
-#endif
+#include <features.h>
-#ifdef __cplusplus
-}
+/* The type of the 'argv' argument to getopt_long and getopt_long_only
+ is properly 'char **', since both functions may write to the array
+ (in order to move all the options to the beginning). However, for
+ compatibility with old versions of LSB, glibc has to use 'char *const *'
+ instead. */
+#ifndef __getopt_argv_const
+# define __getopt_argv_const const
#endif
-/* Make sure we later can get all the definitions and declarations. */
-#undef __need_getopt
+#include <bits/getopt_core.h>
+#include <bits/getopt_ext.h>
#endif /* getopt.h */
diff --git a/posix/getopt1.c b/posix/getopt1.c
index ad8ce700b4..f3f274f4f3 100644
--- a/posix/getopt1.c
+++ b/posix/getopt1.c
@@ -1,6 +1,7 @@
/* getopt_long and getopt_long_only entry points for GNU getopt.
- Copyright (C) 1987-2016 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
+ Copyright (C) 1987-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library and is also part of gnulib.
+ Patches to this file should be submitted to both projects.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -16,57 +17,23 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
+#ifndef _LIBC
+# include <config.h>
#endif
-#ifdef _LIBC
-# include <getopt.h>
-#else
-# include "getopt.h"
-#endif
+#include "getopt.h"
#include "getopt_int.h"
-#include <stdio.h>
-
-/* Comment out all this code if we are using the GNU C Library, and are not
- actually compiling the library itself. This code is part of the GNU C
- Library, but also included in many other GNU distributions. Compiling
- and linking in this code is a waste when using the GNU C library
- (especially if it is a shared library). Rather than having every GNU
- program understand `configure --with-gnu-libc' and omit the object files,
- it is simpler to just do this in the source for each such file. */
-
-#define GETOPT_INTERFACE_VERSION 2
-#if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2
-#include <gnu-versions.h>
-#if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION
-#define ELIDE_CODE
-#endif
-#endif
-
-#ifndef ELIDE_CODE
-
-
-/* This needs to come after some library #include
- to get __GNU_LIBRARY__ defined. */
-#ifdef __GNU_LIBRARY__
-#include <stdlib.h>
-#endif
-
-#ifndef NULL
-#define NULL 0
-#endif
-
int
-getopt_long (int argc, char *const *argv, const char *options,
+getopt_long (int argc, char *__getopt_argv_const *argv, const char *options,
const struct option *long_options, int *opt_index)
{
- return _getopt_internal (argc, argv, options, long_options, opt_index, 0, 0);
+ return _getopt_internal (argc, (char **) argv, options, long_options,
+ opt_index, 0, 0);
}
int
-_getopt_long_r (int argc, char *const *argv, const char *options,
+_getopt_long_r (int argc, char **argv, const char *options,
const struct option *long_options, int *opt_index,
struct _getopt_data *d)
{
@@ -80,14 +47,16 @@ _getopt_long_r (int argc, char *const *argv, const char *options,
instead. */
int
-getopt_long_only (int argc, char *const *argv, const char *options,
+getopt_long_only (int argc, char *__getopt_argv_const *argv,
+ const char *options,
const struct option *long_options, int *opt_index)
{
- return _getopt_internal (argc, argv, options, long_options, opt_index, 1, 0);
+ return _getopt_internal (argc, (char **) argv, options, long_options,
+ opt_index, 1, 0);
}
int
-_getopt_long_only_r (int argc, char *const *argv, const char *options,
+_getopt_long_only_r (int argc, char **argv, const char *options,
const struct option *long_options, int *opt_index,
struct _getopt_data *d)
{
@@ -95,11 +64,11 @@ _getopt_long_only_r (int argc, char *const *argv, const char *options,
1, d, 0);
}
-#endif /* Not ELIDE_CODE. */
#ifdef TEST
#include <stdio.h>
+#include <stdlib.h>
int
main (int argc, char **argv)
@@ -111,7 +80,7 @@ main (int argc, char **argv)
{
int this_option_optind = optind ? optind : 1;
int option_index = 0;
- static struct option long_options[] =
+ static const struct option long_options[] =
{
{"add", 1, 0, 0},
{"append", 0, 0, 0},
@@ -161,11 +130,11 @@ main (int argc, char **argv)
break;
case 'c':
- printf ("option c with value `%s'\n", optarg);
+ printf ("option c with value '%s'\n", optarg);
break;
case 'd':
- printf ("option d with value `%s'\n", optarg);
+ printf ("option d with value '%s'\n", optarg);
break;
case '?':
diff --git a/posix/getopt_init.c b/posix/getopt_init.c
deleted file mode 100644
index 7692ca9b0b..0000000000
--- a/posix/getopt_init.c
+++ /dev/null
@@ -1,74 +0,0 @@
-/* Perform additional initialization for getopt functions in GNU libc.
- Copyright (C) 1997-2016 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
- Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
-
- 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, see
- <http://www.gnu.org/licenses/>. */
-
-#ifdef USE_NONOPTION_FLAGS
-/* Attention: this file is *not* necessary when the GNU getopt functions
- are used outside the GNU libc. Some additional functionality of the
- getopt functions in GNU libc require this additional work. */
-
-#include <getopt.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/types.h>
-
-#include <_itoa.h>
-
-/* Variable to synchronize work. */
-char *__getopt_nonoption_flags;
-
-
-/* Remove the environment variable "_<PID>_GNU_nonoption_argv_flags_" if
- it is still available. If the getopt functions are also used in the
- application it does not exist anymore since it was saved for the use
- in getopt. */
-void
-__getopt_clean_environment (char **env)
-{
- /* Bash 2.0 puts a special variable in the environment for each
- command it runs, specifying which ARGV elements are the results
- of file name wildcard expansion and therefore should not be
- considered as options. */
- static const char envvar_tail[] = "_GNU_nonoption_argv_flags_=";
- char var[50];
- char *cp, **ep;
- size_t len;
-
- /* Construct the "_<PID>_GNU_nonoption_argv_flags_=" string. We must
- not use `sprintf'. */
- cp = memcpy (&var[sizeof (var) - sizeof (envvar_tail)], envvar_tail,
- sizeof (envvar_tail));
- cp = _itoa_word (__getpid (), cp, 10, 0);
- /* Note: we omit adding the leading '_' since we explicitly test for
- it before calling strncmp. */
- len = (var + sizeof (var) - 1) - cp;
-
- for (ep = env; *ep != NULL; ++ep)
- if ((*ep)[0] == '_'
- && __builtin_expect (strncmp (*ep + 1, cp, len) == 0, 0))
- {
- /* Found it. Store this pointer and move later ones back. */
- char **dp = ep;
- __getopt_nonoption_flags = &(*ep)[len];
- do
- dp[0] = dp[1];
- while (*dp++);
- /* Continue the loop in case the name appears again. */
- }
-}
-#endif /* USE_NONOPTION_FLAGS */
diff --git a/posix/getopt_int.h b/posix/getopt_int.h
index 514a1beba4..502250388d 100644
--- a/posix/getopt_int.h
+++ b/posix/getopt_int.h
@@ -1,6 +1,7 @@
/* Internal declarations for getopt.
- Copyright (C) 1989-2016 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
+ Copyright (C) 1989-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library and is also part of gnulib.
+ Patches to this file should be submitted to both projects.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -19,15 +20,43 @@
#ifndef _GETOPT_INT_H
#define _GETOPT_INT_H 1
-extern int _getopt_internal (int ___argc, char *const *___argv,
+#include <getopt.h>
+
+extern int _getopt_internal (int ___argc, char **___argv,
const char *__shortopts,
- const struct option *__longopts, int *__longind,
- int __long_only, int posixly_correct);
+ const struct option *__longopts, int *__longind,
+ int __long_only, int __posixly_correct);
/* Reentrant versions which can handle parsing multiple argument
vectors at the same time. */
+/* Describe how to deal with options that follow non-option ARGV-elements.
+
+ REQUIRE_ORDER means don't recognize them as options; stop option
+ processing when the first non-option is seen. This is what POSIX
+ specifies should happen.
+
+ PERMUTE means permute the contents of ARGV as we scan, so that
+ eventually all the non-options are at the end. This allows options
+ to be given in any order, even with programs that were not written
+ to expect this.
+
+ RETURN_IN_ORDER is an option available to programs that were
+ written to expect options and other ARGV-elements in any order
+ and that care about the ordering of the two. We describe each
+ non-option ARGV-element as if it were the argument of an option
+ with character code 1.
+
+ The special argument '--' forces an end of option-scanning regardless
+ of the value of 'ordering'. In the case of RETURN_IN_ORDER, only
+ '--' can cause 'getopt' to return -1 with 'optind' != ARGC. */
+
+enum __ord
+ {
+ REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
+ };
+
/* Data type for reentrant functions. */
struct _getopt_data
{
@@ -52,75 +81,35 @@ struct _getopt_data
by advancing to the next ARGV-element. */
char *__nextchar;
- /* Describe how to deal with options that follow non-option ARGV-elements.
-
- If the caller did not specify anything,
- the default is REQUIRE_ORDER if the environment variable
- POSIXLY_CORRECT is defined, PERMUTE otherwise.
-
- REQUIRE_ORDER means don't recognize them as options;
- stop option processing when the first non-option is seen.
- This is what Unix does.
- This mode of operation is selected by either setting the environment
- variable POSIXLY_CORRECT, or using `+' as the first character
- of the list of option characters.
-
- PERMUTE is the default. We permute the contents of ARGV as we
- scan, so that eventually all the non-options are at the end.
- This allows options to be given in any order, even with programs
- that were not written to expect this.
-
- RETURN_IN_ORDER is an option available to programs that were
- written to expect options and other ARGV-elements in any order
- and that care about the ordering of the two. We describe each
- non-option ARGV-element as if it were the argument of an option
- with character code 1. Using `-' as the first character of the
- list of option characters selects this mode of operation.
-
- The special argument `--' forces an end of option-scanning regardless
- of the value of `ordering'. In the case of RETURN_IN_ORDER, only
- `--' can cause `getopt' to return -1 with `optind' != ARGC. */
-
- enum
- {
- REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
- } __ordering;
-
- /* If the POSIXLY_CORRECT environment variable is set. */
- int __posixly_correct;
-
+ /* See __ord above. */
+ enum __ord __ordering;
/* Handle permutation of arguments. */
/* Describe the part of ARGV that contains non-options that have
- been skipped. `first_nonopt' is the index in ARGV of the first
- of them; `last_nonopt' is the index after the last of them. */
+ been skipped. 'first_nonopt' is the index in ARGV of the first
+ of them; 'last_nonopt' is the index after the last of them. */
int __first_nonopt;
int __last_nonopt;
-
-#if defined _LIBC && defined USE_NONOPTION_FLAGS
- int __nonoption_flags_max_len;
- int __nonoption_flags_len;
-# endif
};
/* The initializer is necessary to set OPTIND and OPTERR to their
default values and to clear the initialization flag. */
#define _GETOPT_DATA_INITIALIZER { 1, 1 }
-extern int _getopt_internal_r (int ___argc, char *const *___argv,
+extern int _getopt_internal_r (int ___argc, char **___argv,
const char *__shortopts,
const struct option *__longopts, int *__longind,
int __long_only, struct _getopt_data *__data,
- int posixly_correct);
+ int __posixly_correct);
-extern int _getopt_long_r (int ___argc, char *const *___argv,
+extern int _getopt_long_r (int ___argc, char **___argv,
const char *__shortopts,
const struct option *__longopts, int *__longind,
struct _getopt_data *__data);
-extern int _getopt_long_only_r (int ___argc, char *const *___argv,
+extern int _getopt_long_only_r (int ___argc, char **___argv,
const char *__shortopts,
const struct option *__longopts,
int *__longind,
diff --git a/posix/getpgid.c b/posix/getpgid.c
index 6052d1cfd2..0670073199 100644
--- a/posix/getpgid.c
+++ b/posix/getpgid.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/posix/getpgrp.c b/posix/getpgrp.c
index 200834d7f4..ff07d55394 100644
--- a/posix/getpgrp.c
+++ b/posix/getpgrp.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/posix/getpid.c b/posix/getpid.c
index c1c8ed6672..e1123d60c1 100644
--- a/posix/getpid.c
+++ b/posix/getpid.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/posix/getppid.c b/posix/getppid.c
index dbbe86a2e3..824f83cc94 100644
--- a/posix/getppid.c
+++ b/posix/getppid.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/posix/getresgid.c b/posix/getresgid.c
index 291df032a1..977fefbdd7 100644
--- a/posix/getresgid.c
+++ b/posix/getresgid.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/posix/getresuid.c b/posix/getresuid.c
index af8a1a8b26..b1f7d2650b 100644
--- a/posix/getresuid.c
+++ b/posix/getresuid.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/posix/getsid.c b/posix/getsid.c
index 8e40706bb7..60d14bbf5a 100644
--- a/posix/getsid.c
+++ b/posix/getsid.c
@@ -1,5 +1,5 @@
/* getsid -- Return session ID of a process. Stub version.
- Copyright (C) 1995-2016 Free Software Foundation, Inc.
+ Copyright (C) 1995-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/posix/getuid.c b/posix/getuid.c
index 6affa2a9ee..5656c7c0a6 100644
--- a/posix/getuid.c
+++ b/posix/getuid.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/posix/glob-lstat-compat.c b/posix/glob-lstat-compat.c
new file mode 100644
index 0000000000..f78b02f909
--- /dev/null
+++ b/posix/glob-lstat-compat.c
@@ -0,0 +1,36 @@
+/* Compat glob which does not use gl_lstat for GLOB_ALTDIRFUNC.
+ Copyright (C) 2017-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <shlib-compat.h>
+
+#if SHLIB_COMPAT(libc, GLIBC_2_0, GLIBC_2_27)
+
+# include <glob.h>
+
+# define __glob(pattern, flags, errfunc, pglob) \
+ __glob_lstat_compat (pattern, flags, errfunc, pglob)
+
+# define GLOB_ATTRIBUTE attribute_compat_text_section
+
+/* Avoid calling gl_lstat with GLOB_ALTDIRFUNC. */
+# define GLOB_NO_LSTAT
+
+# include <posix/glob.c>
+
+compat_symbol (libc, __glob_lstat_compat, glob, GLIBC_2_0);
+#endif
diff --git a/posix/glob.c b/posix/glob.c
index 0c04c3ccfd..8444b2f79e 100644
--- a/posix/glob.c
+++ b/posix/glob.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -15,142 +15,29 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
#include <glob.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
+#include <stdbool.h>
#include <stddef.h>
-
-/* Outcomment the following line for production quality code. */
-/* #define NDEBUG 1 */
+#include <stdint.h>
#include <assert.h>
+#include <unistd.h>
-#include <stdio.h> /* Needed on stupid SunOS for assert. */
-
-#if !defined _LIBC || !defined GLOB_ONLY_P
-#if defined HAVE_UNISTD_H || defined _LIBC
-# include <unistd.h>
-# ifndef POSIX
-# ifdef _POSIX_VERSION
-# define POSIX
-# endif
-# endif
+#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+# define WINDOWS32
#endif
-#include <pwd.h>
-
-#if defined HAVE_STDINT_H || defined _LIBC
-# include <stdint.h>
-#elif !defined UINTPTR_MAX
-# define UINTPTR_MAX (~((size_t) 0))
+#ifndef WINDOWS32
+# include <pwd.h>
#endif
#include <errno.h>
-#ifndef __set_errno
-# define __set_errno(val) errno = (val)
-#endif
-
-#if defined HAVE_DIRENT_H || defined __GNU_LIBRARY__
-# include <dirent.h>
-# define NAMLEN(dirent) strlen((dirent)->d_name)
-#else
-# define dirent direct
-# define NAMLEN(dirent) (dirent)->d_namlen
-# ifdef HAVE_SYS_NDIR_H
-# include <sys/ndir.h>
-# endif
-# ifdef HAVE_SYS_DIR_H
-# include <sys/dir.h>
-# endif
-# ifdef HAVE_NDIR_H
-# include <ndir.h>
-# endif
-# ifdef HAVE_VMSDIR_H
-# include "vmsdir.h"
-# endif /* HAVE_VMSDIR_H */
-#endif
-
-
-/* In GNU systems, <dirent.h> defines this macro for us. */
-#ifdef _D_NAMLEN
-# undef NAMLEN
-# define NAMLEN(d) _D_NAMLEN(d)
-#endif
-
-/* When used in the GNU libc the symbol _DIRENT_HAVE_D_TYPE is available
- if the `d_type' member for `struct dirent' is available.
- HAVE_STRUCT_DIRENT_D_TYPE plays the same role in GNULIB. */
-#if defined _DIRENT_HAVE_D_TYPE || defined HAVE_STRUCT_DIRENT_D_TYPE
-/* True if the directory entry D must be of type T. */
-# define DIRENT_MUST_BE(d, t) ((d)->d_type == (t))
-
-/* True if the directory entry D might be a symbolic link. */
-# define DIRENT_MIGHT_BE_SYMLINK(d) \
- ((d)->d_type == DT_UNKNOWN || (d)->d_type == DT_LNK)
-
-/* True if the directory entry D might be a directory. */
-# define DIRENT_MIGHT_BE_DIR(d) \
- ((d)->d_type == DT_DIR || DIRENT_MIGHT_BE_SYMLINK (d))
-
-#else /* !HAVE_D_TYPE */
-# define DIRENT_MUST_BE(d, t) false
-# define DIRENT_MIGHT_BE_SYMLINK(d) true
-# define DIRENT_MIGHT_BE_DIR(d) true
-#endif /* HAVE_D_TYPE */
-
-/* If the system has the `struct dirent64' type we use it internally. */
-#if defined _LIBC && !defined COMPILE_GLOB64
-# if defined HAVE_DIRENT_H || defined __GNU_LIBRARY__
-# define CONVERT_D_NAMLEN(d64, d32)
-# else
-# define CONVERT_D_NAMLEN(d64, d32) \
- (d64)->d_namlen = (d32)->d_namlen;
-# endif
-
-# if (defined POSIX || defined WINDOWS32) && !defined __GNU_LIBRARY__
-# define CONVERT_D_INO(d64, d32)
-# else
-# define CONVERT_D_INO(d64, d32) \
- (d64)->d_ino = (d32)->d_ino;
-# endif
-
-# ifdef _DIRENT_HAVE_D_TYPE
-# define CONVERT_D_TYPE(d64, d32) \
- (d64)->d_type = (d32)->d_type;
-# else
-# define CONVERT_D_TYPE(d64, d32)
-# endif
-
-# define CONVERT_DIRENT_DIRENT64(d64, d32) \
- memcpy ((d64)->d_name, (d32)->d_name, NAMLEN (d32) + 1); \
- CONVERT_D_NAMLEN (d64, d32) \
- CONVERT_D_INO (d64, d32) \
- CONVERT_D_TYPE (d64, d32)
-#endif
-
-
-#if (defined POSIX || defined WINDOWS32) && !defined __GNU_LIBRARY__
-/* Posix does not require that the d_ino field be present, and some
- systems do not provide it. */
-# define REAL_DIR_ENTRY(dp) 1
-#else
-# define REAL_DIR_ENTRY(dp) (dp->d_ino != 0)
-#endif /* POSIX */
-
+#include <dirent.h>
#include <stdlib.h>
#include <string.h>
-
-/* NAME_MAX is usually defined in <dirent.h> or <limits.h>. */
-#include <limits.h>
-#ifndef NAME_MAX
-# define NAME_MAX (sizeof (((struct dirent *) 0)->d_name))
-#endif
-
#include <alloca.h>
#ifdef _LIBC
@@ -161,57 +48,204 @@
# define opendir(name) __opendir (name)
# define readdir(str) __readdir64 (str)
# define getpwnam_r(name, bufp, buf, len, res) \
- __getpwnam_r (name, bufp, buf, len, res)
+ __getpwnam_r (name, bufp, buf, len, res)
+# ifndef __lstat64
+# define __lstat64(fname, buf) __lxstat64 (_STAT_VER, fname, buf)
+# endif
# ifndef __stat64
# define __stat64(fname, buf) __xstat64 (_STAT_VER, fname, buf)
# endif
# define struct_stat64 struct stat64
+# define FLEXIBLE_ARRAY_MEMBER
+# include <shlib-compat.h>
#else /* !_LIBC */
-# include "getlogin_r.h"
-# include "mempcpy.h"
-# include "stat-macros.h"
-# include "strdup.h"
-# define __stat64(fname, buf) stat (fname, buf)
-# define struct_stat64 struct stat
-# define __stat(fname, buf) stat (fname, buf)
-# define __alloca alloca
-# define __readdir readdir
-# define __readdir64 readdir64
-# define __glob_pattern_p glob_pattern_p
+# define __glob glob
+# define __getlogin_r(buf, len) getlogin_r (buf, len)
+# define __lstat64(fname, buf) lstat (fname, buf)
+# define __stat64(fname, buf) stat (fname, buf)
+# define __fxstatat64(_, d, f, st, flag) fstatat (d, f, st, flag)
+# define struct_stat64 struct stat
+# ifndef __MVS__
+# define __alloca alloca
+# endif
+# define __readdir readdir
+# define COMPILE_GLOB64
#endif /* _LIBC */
#include <fnmatch.h>
-#ifdef _SC_GETPW_R_SIZE_MAX
-# define GETPW_R_SIZE_MAX() sysconf (_SC_GETPW_R_SIZE_MAX)
+#include <flexmember.h>
+#include <glob_internal.h>
+#include <scratch_buffer.h>
+
+static const char *next_brace_sub (const char *begin, int flags) __THROWNL;
+
+typedef uint_fast8_t dirent_type;
+
+#if !defined _LIBC && !defined HAVE_STRUCT_DIRENT_D_TYPE
+/* Any distinct values will do here.
+ Undef any existing macros out of the way. */
+# undef DT_UNKNOWN
+# undef DT_DIR
+# undef DT_LNK
+# define DT_UNKNOWN 0
+# define DT_DIR 1
+# define DT_LNK 2
+#endif
+
+/* A representation of a directory entry which does not depend on the
+ layout of struct dirent, or the size of ino_t. */
+struct readdir_result
+{
+ const char *name;
+#if defined _DIRENT_HAVE_D_TYPE || defined HAVE_STRUCT_DIRENT_D_TYPE
+ dirent_type type;
+#endif
+};
+
+/* Initialize and return type member of struct readdir_result. */
+static dirent_type
+readdir_result_type (struct readdir_result d)
+{
+#if defined _DIRENT_HAVE_D_TYPE || defined HAVE_STRUCT_DIRENT_D_TYPE
+# define D_TYPE_TO_RESULT(source) (source)->d_type,
+ return d.type;
#else
-# define GETPW_R_SIZE_MAX() (-1)
+# define D_TYPE_TO_RESULT(source)
+ return DT_UNKNOWN;
+#endif
+}
+
+/* Construct an initializer for a struct readdir_result object from a
+ struct dirent *. No copy of the name is made. */
+#define READDIR_RESULT_INITIALIZER(source) \
+ { \
+ source->d_name, \
+ D_TYPE_TO_RESULT (source) \
+ }
+
+/* Call gl_readdir on STREAM. This macro can be overridden to reduce
+ type safety if an old interface version needs to be supported. */
+#ifndef GL_READDIR
+# define GL_READDIR(pglob, stream) ((pglob)->gl_readdir (stream))
+#endif
+
+/* Extract name and type from directory entry. No copy of the name is
+ made. If SOURCE is NULL, result name is NULL. Keep in sync with
+ convert_dirent64 below. */
+static struct readdir_result
+convert_dirent (const struct dirent *source)
+{
+ if (source == NULL)
+ {
+ struct readdir_result result = { NULL, };
+ return result;
+ }
+ struct readdir_result result = READDIR_RESULT_INITIALIZER (source);
+ return result;
+}
+
+#ifndef COMPILE_GLOB64
+/* Like convert_dirent, but works on struct dirent64 instead. Keep in
+ sync with convert_dirent above. */
+static struct readdir_result
+convert_dirent64 (const struct dirent64 *source)
+{
+ if (source == NULL)
+ {
+ struct readdir_result result = { NULL, };
+ return result;
+ }
+ struct readdir_result result = READDIR_RESULT_INITIALIZER (source);
+ return result;
+}
+#endif
+
+#ifndef _LIBC
+/* The results of opendir() in this file are not used with dirfd and fchdir,
+ and we do not leak fds to any single-threaded code that could use stdio,
+ therefore save some unnecessary recursion in fchdir.c and opendir_safer.c.
+ FIXME - if the kernel ever adds support for multi-thread safety for
+ avoiding standard fds, then we should use opendir_safer. */
+# ifdef GNULIB_defined_opendir
+# undef opendir
+# endif
+# ifdef GNULIB_defined_closedir
+# undef closedir
+# endif
+
+/* Just use malloc. */
+# define __libc_use_alloca(n) false
+# define alloca_account(len, avar) ((void) (len), (void) (avar), (void *) 0)
+# define extend_alloca_account(buf, len, newlen, avar) \
+ ((void) (buf), (void) (len), (void) (newlen), (void) (avar), (void *) 0)
#endif
-#ifdef _SC_LOGIN_NAME_MAX
-# define GET_LOGIN_NAME_MAX() sysconf (_SC_LOGIN_NAME_MAX)
+
+static int
+glob_lstat (glob_t *pglob, int flags, const char *fullname)
+{
+/* Use on glob-lstat-compat.c to provide a compat symbol which does not
+ use lstat / gl_lstat. */
+#ifdef GLOB_NO_LSTAT
+# define GL_LSTAT gl_stat
+# define LSTAT64 __stat64
#else
-# define GET_LOGIN_NAME_MAX() (-1)
+# define GL_LSTAT gl_lstat
+# define LSTAT64 __lstat64
#endif
-
-static const char *next_brace_sub (const char *begin, int flags) __THROWNL;
-#endif /* !defined _LIBC || !defined GLOB_ONLY_P */
+ union
+ {
+ struct stat st;
+ struct_stat64 st64;
+ } ust;
+ return (__glibc_unlikely (flags & GLOB_ALTDIRFUNC)
+ ? pglob->GL_LSTAT (fullname, &ust.st)
+ : LSTAT64 (fullname, &ust.st64));
+}
+
+/* Set *R = A + B. Return true if the answer is mathematically
+ incorrect due to overflow; in this case, *R is the low order
+ bits of the correct answer. */
-#ifndef attribute_hidden
-# define attribute_hidden
+static bool
+size_add_wrapv (size_t a, size_t b, size_t *r)
+{
+#if 5 <= __GNUC__ && !defined __ICC
+ return __builtin_add_overflow (a, b, r);
+#else
+ *r = a + b;
+ return *r < a;
#endif
+}
+
+static bool
+glob_use_alloca (size_t alloca_used, size_t len)
+{
+ size_t size;
+ return (!size_add_wrapv (alloca_used, len, &size)
+ && __libc_use_alloca (size));
+}
static int glob_in_dir (const char *pattern, const char *directory,
int flags, int (*errfunc) (const char *, int),
glob_t *pglob, size_t alloca_used);
-extern int __glob_pattern_type (const char *pattern, int quote)
- attribute_hidden;
-
-#if !defined _LIBC || !defined GLOB_ONLY_P
static int prefix_array (const char *prefix, char **array, size_t n) __THROWNL;
static int collated_compare (const void *, const void *) __THROWNL;
+/* Return true if FILENAME is a directory or a symbolic link to a directory.
+ Use FLAGS and PGLOB to resolve the filename. */
+static bool
+is_dir (char const *filename, int flags, glob_t const *pglob)
+{
+ struct stat st;
+ struct_stat64 st64;
+ return (__glibc_unlikely (flags & GLOB_ALTDIRFUNC)
+ ? pglob->gl_stat (filename, &st) == 0 && S_ISDIR (st.st_mode)
+ : __stat64 (filename, &st64) == 0 && S_ISDIR (st64.st_mode));
+}
+
/* Find the end of the sub-pattern in a brace expression. */
static const char *
next_brace_sub (const char *cp, int flags)
@@ -236,22 +270,22 @@ next_brace_sub (const char *cp, int flags)
return *cp != '\0' ? cp : NULL;
}
-#endif /* !defined _LIBC || !defined GLOB_ONLY_P */
+#ifndef GLOB_ATTRIBUTE
+# define GLOB_ATTRIBUTE
+#endif
/* Do glob searching for PATTERN, placing results in PGLOB.
The bits defined above may be set in FLAGS.
If a directory cannot be opened or read and ERRFUNC is not nil,
it is called with the pathname that caused the error, and the
- `errno' value from the failing call; if it returns non-zero
- `glob' returns GLOB_ABORTED; if it returns zero, the error is ignored.
+ 'errno' value from the failing call; if it returns non-zero
+ 'glob' returns GLOB_ABORTED; if it returns zero, the error is ignored.
If memory cannot be allocated for PGLOB, GLOB_NOSPACE is returned.
- Otherwise, `glob' returns zero. */
+ Otherwise, 'glob' returns zero. */
int
-#ifdef GLOB_ATTRIBUTE
GLOB_ATTRIBUTE
-#endif
-glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
- glob_t *pglob)
+__glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
+ glob_t *pglob)
{
const char *filename;
char *dirname = NULL;
@@ -263,9 +297,7 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
int malloc_dirname = 0;
glob_t dirs;
int retval = 0;
-#ifdef _LIBC
size_t alloca_used = 0;
-#endif
if (pattern == NULL || pglob == NULL || (flags & ~__GLOB_FLAGS) != 0)
{
@@ -279,10 +311,32 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
flags |= GLOB_ONLYDIR;
if (!(flags & GLOB_DOOFFS))
- /* Have to do this so `globfree' knows where to start freeing. It
+ /* Have to do this so 'globfree' knows where to start freeing. It
also makes all the code that uses gl_offs simpler. */
pglob->gl_offs = 0;
+ if (!(flags & GLOB_APPEND))
+ {
+ pglob->gl_pathc = 0;
+ if (!(flags & GLOB_DOOFFS))
+ pglob->gl_pathv = NULL;
+ else
+ {
+ size_t i;
+
+ if (pglob->gl_offs >= ~((size_t) 0) / sizeof (char *))
+ return GLOB_NOSPACE;
+
+ pglob->gl_pathv = (char **) malloc ((pglob->gl_offs + 1)
+ * sizeof (char *));
+ if (pglob->gl_pathv == NULL)
+ return GLOB_NOSPACE;
+
+ for (i = 0; i <= pglob->gl_offs; ++i)
+ pglob->gl_pathv[i] = NULL;
+ }
+ }
+
if (flags & GLOB_BRACE)
{
const char *begin;
@@ -321,23 +375,14 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
size_t rest_len;
char *onealt;
size_t pattern_len = strlen (pattern) - 1;
-#ifdef _LIBC
- int alloca_onealt = __libc_use_alloca (alloca_used + pattern_len);
+ int alloca_onealt = glob_use_alloca (alloca_used, pattern_len);
if (alloca_onealt)
onealt = alloca_account (pattern_len, alloca_used);
else
-#endif
{
- onealt = (char *) malloc (pattern_len);
+ onealt = malloc (pattern_len);
if (onealt == NULL)
- {
- if (!(flags & GLOB_APPEND))
- {
- pglob->gl_pathc = 0;
- pglob->gl_pathv = NULL;
- }
- return GLOB_NOSPACE;
- }
+ return GLOB_NOSPACE;
}
/* We know the prefix for all sub-patterns. */
@@ -348,13 +393,12 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
next = next_brace_sub (begin + 1, flags);
if (next == NULL)
{
- /* It is an illegal expression. */
+ /* It is an invalid expression. */
illegal_brace:
-#ifdef _LIBC
if (__glibc_unlikely (!alloca_onealt))
-#endif
free (onealt);
- return glob (pattern, flags & ~GLOB_BRACE, errfunc, pglob);
+ flags &= ~GLOB_BRACE;
+ goto no_brace;
}
/* Now find the end of the whole brace expression. */
@@ -375,14 +419,6 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
points past the final }. We will accumulate result names from
recursive runs for each brace alternative in the buffer using
GLOB_APPEND. */
-
- if (!(flags & GLOB_APPEND))
- {
- /* This call is to set a new vector, so clear out the
- vector so we can append to it. */
- pglob->gl_pathc = 0;
- pglob->gl_pathv = NULL;
- }
firstc = pglob->gl_pathc;
p = begin + 1;
@@ -393,16 +429,15 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
/* Construct the new glob expression. */
mempcpy (mempcpy (alt_start, p, next - p), rest, rest_len);
- result = glob (onealt,
- ((flags & ~(GLOB_NOCHECK | GLOB_NOMAGIC))
- | GLOB_APPEND), errfunc, pglob);
+ result = __glob (onealt,
+ ((flags & ~(GLOB_NOCHECK | GLOB_NOMAGIC))
+ | GLOB_APPEND),
+ errfunc, pglob);
/* If we got an error, return it. */
if (result && result != GLOB_NOMATCH)
{
-#ifdef _LIBC
if (__glibc_unlikely (!alloca_onealt))
-#endif
free (onealt);
if (!(flags & GLOB_APPEND))
{
@@ -421,9 +456,7 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
assert (next != NULL);
}
-#ifdef _LIBC
if (__glibc_unlikely (!alloca_onealt))
-#endif
free (onealt);
if (pglob->gl_pathc != firstc)
@@ -434,40 +467,21 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
}
}
- if (!(flags & GLOB_APPEND))
- {
- pglob->gl_pathc = 0;
- if (!(flags & GLOB_DOOFFS))
- pglob->gl_pathv = NULL;
- else
- {
- size_t i;
-
- if (pglob->gl_offs >= ~((size_t) 0) / sizeof (char *))
- return GLOB_NOSPACE;
-
- pglob->gl_pathv = (char **) malloc ((pglob->gl_offs + 1)
- * sizeof (char *));
- if (pglob->gl_pathv == NULL)
- return GLOB_NOSPACE;
-
- for (i = 0; i <= pglob->gl_offs; ++i)
- pglob->gl_pathv[i] = NULL;
- }
- }
-
+ no_brace:
oldcount = pglob->gl_pathc + pglob->gl_offs;
/* Find the filename. */
filename = strrchr (pattern, '/');
+
#if defined __MSDOS__ || defined WINDOWS32
- /* The case of "d:pattern". Since `:' is not allowed in
+ /* The case of "d:pattern". Since ':' is not allowed in
file names, we can safely assume that wherever it
happens in pattern, it signals the filename part. This
is so we could some day support patterns like "[a-z]:foo". */
if (filename == NULL)
filename = strchr (pattern, ':');
#endif /* __MSDOS__ || WINDOWS32 */
+
dirname_modified = 0;
if (filename == NULL)
{
@@ -492,11 +506,7 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
}
filename = pattern;
-#ifdef _AMIGA
- dirname = (char *) "";
-#else
dirname = (char *) ".";
-#endif
dirlen = 0;
}
}
@@ -520,22 +530,21 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
char *drive_spec;
++dirlen;
- drive_spec = (char *) __alloca (dirlen + 1);
+ drive_spec = __alloca (dirlen + 1);
*((char *) mempcpy (drive_spec, pattern, dirlen)) = '\0';
/* For now, disallow wildcards in the drive spec, to
prevent infinite recursion in glob. */
if (__glob_pattern_p (drive_spec, !(flags & GLOB_NOESCAPE)))
return GLOB_NOMATCH;
- /* If this is "d:pattern", we need to copy `:' to DIRNAME
+ /* If this is "d:pattern", we need to copy ':' to DIRNAME
as well. If it's "d:/pattern", don't remove the slash
from "d:/", since "d:" and "d:/" are not the same.*/
}
#endif
-#ifdef _LIBC
- if (__libc_use_alloca (alloca_used + dirlen + 1))
+
+ if (glob_use_alloca (alloca_used, dirlen + 1))
newp = alloca_account (dirlen + 1, alloca_used);
else
-#endif
{
newp = malloc (dirlen + 1);
if (newp == NULL)
@@ -546,14 +555,17 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
dirname = newp;
++filename;
- if (filename[0] == '\0'
#if defined __MSDOS__ || defined WINDOWS32
- && dirname[dirlen - 1] != ':'
- && (dirlen < 3 || dirname[dirlen - 2] != ':'
- || dirname[dirlen - 1] != '/')
+ bool drive_root = (dirlen > 1
+ && (dirname[dirlen - 1] == ':'
+ || (dirlen > 2 && dirname[dirlen - 2] == ':'
+ && dirname[dirlen - 1] == '/')));
+#else
+ bool drive_root = false;
#endif
- && dirlen > 1)
- /* "pattern/". Expand "pattern", appending slashes. */
+
+ if (filename[0] == '\0' && dirlen > 1 && !drive_root)
+ /* "pattern/". Expand "pattern", appending slashes. */
{
int orig_flags = flags;
if (!(flags & GLOB_NOESCAPE) && dirname[dirlen - 1] == '\\')
@@ -569,7 +581,7 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
flags &= ~(GLOB_NOCHECK | GLOB_NOMAGIC);
}
}
- int val = glob (dirname, flags | GLOB_MARK, errfunc, pglob);
+ int val = __glob (dirname, flags | GLOB_MARK, errfunc, pglob);
if (val == 0)
pglob->gl_flags = ((pglob->gl_flags & ~GLOB_MARK)
| (flags & GLOB_MARK));
@@ -586,7 +598,6 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
}
}
-#ifndef VMS
if ((flags & (GLOB_TILDE|GLOB_TILDE_CHECK)) && dirname[0] == '~')
{
if (dirname[1] == '\0' || dirname[1] == '/'
@@ -596,134 +607,85 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
/* Look up home directory. */
char *home_dir = getenv ("HOME");
int malloc_home_dir = 0;
-# ifdef _AMIGA
- if (home_dir == NULL || home_dir[0] == '\0')
- home_dir = "SYS:";
-# else
-# ifdef WINDOWS32
- if (home_dir == NULL || home_dir[0] == '\0')
- home_dir = "c:/users/default"; /* poor default */
-# else
if (home_dir == NULL || home_dir[0] == '\0')
{
- int success;
- char *name;
- size_t buflen = GET_LOGIN_NAME_MAX () + 1;
-
- if (buflen == 0)
- /* `sysconf' does not support _SC_LOGIN_NAME_MAX. Try
- a moderate value. */
- buflen = 20;
- name = alloca_account (buflen, alloca_used);
-
- success = __getlogin_r (name, buflen) == 0;
- if (success)
+#ifdef WINDOWS32
+ /* Windows NT defines HOMEDRIVE and HOMEPATH. But give
+ preference to HOME, because the user can change HOME. */
+ const char *home_drive = getenv ("HOMEDRIVE");
+ const char *home_path = getenv ("HOMEPATH");
+
+ if (home_drive != NULL && home_path != NULL)
{
- struct passwd *p;
-# if defined HAVE_GETPWNAM_R || defined _LIBC
- long int pwbuflen = GETPW_R_SIZE_MAX ();
- char *pwtmpbuf;
- struct passwd pwbuf;
- int malloc_pwtmpbuf = 0;
- int save = errno;
-
-# ifndef _LIBC
- if (pwbuflen == -1)
- /* `sysconf' does not support _SC_GETPW_R_SIZE_MAX.
- Try a moderate value. */
- pwbuflen = 1024;
-# endif
- if (__libc_use_alloca (alloca_used + pwbuflen))
- pwtmpbuf = alloca_account (pwbuflen, alloca_used);
- else
- {
- pwtmpbuf = malloc (pwbuflen);
- if (pwtmpbuf == NULL)
- {
- retval = GLOB_NOSPACE;
- goto out;
- }
- malloc_pwtmpbuf = 1;
- }
+ size_t home_drive_len = strlen (home_drive);
+ size_t home_path_len = strlen (home_path);
+ char *mem = alloca (home_drive_len + home_path_len + 1);
- while (getpwnam_r (name, &pwbuf, pwtmpbuf, pwbuflen, &p)
- != 0)
+ memcpy (mem, home_drive, home_drive_len);
+ memcpy (mem + home_drive_len, home_path, home_path_len + 1);
+ home_dir = mem;
+ }
+ else
+ home_dir = "c:/users/default"; /* poor default */
+#else
+ int err;
+ struct passwd *p;
+ struct passwd pwbuf;
+ struct scratch_buffer s;
+ scratch_buffer_init (&s);
+ while (true)
+ {
+ p = NULL;
+ err = __getlogin_r (s.data, s.length);
+ if (err == 0)
{
- if (errno != ERANGE)
- {
- p = NULL;
- break;
- }
-
- if (!malloc_pwtmpbuf
- && __libc_use_alloca (alloca_used
- + 2 * pwbuflen))
- pwtmpbuf = extend_alloca_account (pwtmpbuf, pwbuflen,
- 2 * pwbuflen,
- alloca_used);
- else
- {
- char *newp = realloc (malloc_pwtmpbuf
- ? pwtmpbuf : NULL,
- 2 * pwbuflen);
- if (newp == NULL)
- {
- if (__glibc_unlikely (malloc_pwtmpbuf))
- free (pwtmpbuf);
- retval = GLOB_NOSPACE;
- goto out;
- }
- pwtmpbuf = newp;
- pwbuflen = 2 * pwbuflen;
- malloc_pwtmpbuf = 1;
- }
- __set_errno (save);
+# if defined HAVE_GETPWNAM_R || defined _LIBC
+ size_t ssize = strlen (s.data) + 1;
+ char *sdata = s.data;
+ err = getpwnam_r (sdata, &pwbuf, sdata + ssize,
+ s.length - ssize, &p);
+# else
+ p = getpwnam (s.data);
+ if (p == NULL)
+ err = errno;
+# endif
}
-# else
- p = getpwnam (name);
-# endif
- if (p != NULL)
+ if (err != ERANGE)
+ break;
+ if (!scratch_buffer_grow (&s))
{
- if (!malloc_pwtmpbuf)
- home_dir = p->pw_dir;
- else
- {
- size_t home_dir_len = strlen (p->pw_dir) + 1;
- if (__libc_use_alloca (alloca_used + home_dir_len))
- home_dir = alloca_account (home_dir_len,
- alloca_used);
- else
- {
- home_dir = malloc (home_dir_len);
- if (home_dir == NULL)
- {
- free (pwtmpbuf);
- retval = GLOB_NOSPACE;
- goto out;
- }
- malloc_home_dir = 1;
- }
- memcpy (home_dir, p->pw_dir, home_dir_len);
-
- free (pwtmpbuf);
- }
+ retval = GLOB_NOSPACE;
+ goto out;
}
}
+ if (err == 0)
+ {
+ home_dir = strdup (p->pw_dir);
+ malloc_home_dir = 1;
+ }
+ scratch_buffer_free (&s);
+ if (err == 0 && home_dir == NULL)
+ {
+ retval = GLOB_NOSPACE;
+ goto out;
+ }
+#endif /* WINDOWS32 */
}
if (home_dir == NULL || home_dir[0] == '\0')
{
+ if (__glibc_unlikely (malloc_home_dir))
+ free (home_dir);
if (flags & GLOB_TILDE_CHECK)
{
- if (__glibc_unlikely (malloc_home_dir))
- free (home_dir);
retval = GLOB_NOMATCH;
goto out;
}
else
- home_dir = (char *) "~"; /* No luck. */
+ {
+ home_dir = (char *) "~"; /* No luck. */
+ malloc_home_dir = 0;
+ }
}
-# endif /* WINDOWS32 */
-# endif
/* Now construct the full directory. */
if (dirname[1] == '\0')
{
@@ -738,8 +700,7 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
{
char *newp;
size_t home_len = strlen (home_dir);
- int use_alloca = __libc_use_alloca (alloca_used
- + home_len + dirlen);
+ int use_alloca = glob_use_alloca (alloca_used, home_len + dirlen);
if (use_alloca)
newp = alloca_account (home_len + dirlen, alloca_used);
else
@@ -763,12 +724,15 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
dirname = newp;
dirlen += home_len - 1;
malloc_dirname = !use_alloca;
+
+ if (__glibc_unlikely (malloc_home_dir))
+ free (home_dir);
}
dirname_modified = 1;
}
-# if !defined _AMIGA && !defined WINDOWS32
else
{
+#ifndef WINDOWS32
char *end_name = strchr (dirname, '/');
char *user_name;
int malloc_user_name = 0;
@@ -790,7 +754,7 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
else
{
char *newp;
- if (__libc_use_alloca (alloca_used + (end_name - dirname)))
+ if (glob_use_alloca (alloca_used, end_name - dirname))
newp = alloca_account (end_name - dirname, alloca_used);
else
{
@@ -807,11 +771,11 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
char *p = mempcpy (newp, dirname + 1,
unescape - dirname - 1);
char *q = unescape;
- while (*q != '\0')
+ while (q != end_name)
{
if (*q == '\\')
{
- if (q[1] == '\0')
+ if (q + 1 == end_name)
{
/* "~fo\\o\\" unescape to user_name "foo\\",
but "~fo\\o\\/" unescape to user_name
@@ -827,7 +791,7 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
*p = '\0';
}
else
- *((char *) mempcpy (newp, dirname + 1, end_name - dirname))
+ *((char *) mempcpy (newp, dirname + 1, end_name - dirname - 1))
= '\0';
user_name = newp;
}
@@ -835,60 +799,21 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
/* Look up specific user's home directory. */
{
struct passwd *p;
+ struct scratch_buffer pwtmpbuf;
+ scratch_buffer_init (&pwtmpbuf);
+
# if defined HAVE_GETPWNAM_R || defined _LIBC
- long int buflen = GETPW_R_SIZE_MAX ();
- char *pwtmpbuf;
- int malloc_pwtmpbuf = 0;
struct passwd pwbuf;
- int save = errno;
-
-# ifndef _LIBC
- if (buflen == -1)
- /* `sysconf' does not support _SC_GETPW_R_SIZE_MAX. Try a
- moderate value. */
- buflen = 1024;
-# endif
- if (__libc_use_alloca (alloca_used + buflen))
- pwtmpbuf = alloca_account (buflen, alloca_used);
- else
+
+ while (getpwnam_r (user_name, &pwbuf,
+ pwtmpbuf.data, pwtmpbuf.length, &p)
+ == ERANGE)
{
- pwtmpbuf = malloc (buflen);
- if (pwtmpbuf == NULL)
+ if (!scratch_buffer_grow (&pwtmpbuf))
{
- nomem_getpw:
- if (__glibc_unlikely (malloc_user_name))
- free (user_name);
retval = GLOB_NOSPACE;
goto out;
}
- malloc_pwtmpbuf = 1;
- }
-
- while (getpwnam_r (user_name, &pwbuf, pwtmpbuf, buflen, &p) != 0)
- {
- if (errno != ERANGE)
- {
- p = NULL;
- break;
- }
- if (!malloc_pwtmpbuf
- && __libc_use_alloca (alloca_used + 2 * buflen))
- pwtmpbuf = extend_alloca_account (pwtmpbuf, buflen,
- 2 * buflen, alloca_used);
- else
- {
- char *newp = realloc (malloc_pwtmpbuf ? pwtmpbuf : NULL,
- 2 * buflen);
- if (newp == NULL)
- {
- if (__glibc_unlikely (malloc_pwtmpbuf))
- free (pwtmpbuf);
- goto nomem_getpw;
- }
- pwtmpbuf = newp;
- malloc_pwtmpbuf = 1;
- }
- __set_errno (save);
}
# else
p = getpwnam (user_name);
@@ -902,12 +827,13 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
{
size_t home_len = strlen (p->pw_dir);
size_t rest_len = end_name == NULL ? 0 : strlen (end_name);
+ char *d;
if (__glibc_unlikely (malloc_dirname))
free (dirname);
malloc_dirname = 0;
- if (__libc_use_alloca (alloca_used + home_len + rest_len + 1))
+ if (glob_use_alloca (alloca_used, home_len + rest_len + 1))
dirname = alloca_account (home_len + rest_len + 1,
alloca_used);
else
@@ -915,97 +841,87 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
dirname = malloc (home_len + rest_len + 1);
if (dirname == NULL)
{
- if (__glibc_unlikely (malloc_pwtmpbuf))
- free (pwtmpbuf);
+ scratch_buffer_free (&pwtmpbuf);
retval = GLOB_NOSPACE;
goto out;
}
malloc_dirname = 1;
}
- *((char *) mempcpy (mempcpy (dirname, p->pw_dir, home_len),
- end_name, rest_len)) = '\0';
+ d = mempcpy (dirname, p->pw_dir, home_len);
+ if (end_name != NULL)
+ d = mempcpy (d, end_name, rest_len);
+ *d = '\0';
dirlen = home_len + rest_len;
dirname_modified = 1;
-
- if (__glibc_unlikely (malloc_pwtmpbuf))
- free (pwtmpbuf);
}
else
{
- if (__glibc_unlikely (malloc_pwtmpbuf))
- free (pwtmpbuf);
-
if (flags & GLOB_TILDE_CHECK)
- /* We have to regard it as an error if we cannot find the
- home directory. */
- return GLOB_NOMATCH;
+ {
+ /* We have to regard it as an error if we cannot find the
+ home directory. */
+ retval = GLOB_NOMATCH;
+ goto out;
+ }
}
+ scratch_buffer_free (&pwtmpbuf);
}
+#endif /* !WINDOWS32 */
}
-# endif /* Not Amiga && not WINDOWS32. */
}
-#endif /* Not VMS. */
/* Now test whether we looked for "~" or "~NAME". In this case we
can give the answer now. */
if (filename == NULL)
{
- struct stat st;
- struct_stat64 st64;
-
- /* Return the directory if we don't check for error or if it exists. */
- if ((flags & GLOB_NOCHECK)
- || (((__builtin_expect (flags & GLOB_ALTDIRFUNC, 0))
- ? ((*pglob->gl_stat) (dirname, &st) == 0
- && S_ISDIR (st.st_mode))
- : (__stat64 (dirname, &st64) == 0 && S_ISDIR (st64.st_mode)))))
- {
- size_t newcount = pglob->gl_pathc + pglob->gl_offs;
- char **new_gl_pathv;
-
- if (newcount > UINTPTR_MAX - (1 + 1)
- || newcount + 1 + 1 > ~((size_t) 0) / sizeof (char *))
- {
- nospace:
- free (pglob->gl_pathv);
- pglob->gl_pathv = NULL;
- pglob->gl_pathc = 0;
- return GLOB_NOSPACE;
- }
+ size_t newcount = pglob->gl_pathc + pglob->gl_offs;
+ char **new_gl_pathv;
- new_gl_pathv
- = (char **) realloc (pglob->gl_pathv,
- (newcount + 1 + 1) * sizeof (char *));
- if (new_gl_pathv == NULL)
- goto nospace;
- pglob->gl_pathv = new_gl_pathv;
+ if (newcount > SIZE_MAX / sizeof (char *) - 2)
+ {
+ nospace:
+ free (pglob->gl_pathv);
+ pglob->gl_pathv = NULL;
+ pglob->gl_pathc = 0;
+ retval = GLOB_NOSPACE;
+ goto out;
+ }
- if (flags & GLOB_MARK)
- {
- char *p;
- pglob->gl_pathv[newcount] = malloc (dirlen + 2);
- if (pglob->gl_pathv[newcount] == NULL)
- goto nospace;
- p = mempcpy (pglob->gl_pathv[newcount], dirname, dirlen);
- p[0] = '/';
- p[1] = '\0';
- }
- else
- {
- pglob->gl_pathv[newcount] = strdup (dirname);
- if (pglob->gl_pathv[newcount] == NULL)
- goto nospace;
- }
- pglob->gl_pathv[++newcount] = NULL;
- ++pglob->gl_pathc;
- pglob->gl_flags = flags;
+ new_gl_pathv = realloc (pglob->gl_pathv,
+ (newcount + 2) * sizeof (char *));
+ if (new_gl_pathv == NULL)
+ goto nospace;
+ pglob->gl_pathv = new_gl_pathv;
- return 0;
- }
+ if (flags & GLOB_MARK && is_dir (dirname, flags, pglob))
+ {
+ char *p;
+ pglob->gl_pathv[newcount] = malloc (dirlen + 2);
+ if (pglob->gl_pathv[newcount] == NULL)
+ goto nospace;
+ p = mempcpy (pglob->gl_pathv[newcount], dirname, dirlen);
+ p[0] = '/';
+ p[1] = '\0';
+ if (__glibc_unlikely (malloc_dirname))
+ free (dirname);
+ }
+ else
+ {
+ if (__glibc_unlikely (malloc_dirname))
+ pglob->gl_pathv[newcount] = dirname;
+ else
+ {
+ pglob->gl_pathv[newcount] = strdup (dirname);
+ if (pglob->gl_pathv[newcount] == NULL)
+ goto nospace;
+ }
+ }
+ pglob->gl_pathv[++newcount] = NULL;
+ ++pglob->gl_pathc;
+ pglob->gl_flags = flags;
- /* Not found. */
- return GLOB_NOMATCH;
+ return 0;
}
meta = __glob_pattern_type (dirname, !(flags & GLOB_NOESCAPE));
@@ -1014,7 +930,7 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
[ which we handle the same, using fnmatch. Broken unterminated
pattern bracket expressions ought to be rare enough that it is
not worth special casing them, fnmatch will do the right thing. */
- if (meta & 5)
+ if (meta & (GLOBPAT_SPECIAL | GLOBPAT_BRACKET))
{
/* The directory name contains metacharacters, so we
have to glob for the directory, and then glob for
@@ -1043,15 +959,17 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
dirs.gl_lstat = pglob->gl_lstat;
}
- status = glob (dirname,
- ((flags & (GLOB_ERR | GLOB_NOESCAPE
- | GLOB_ALTDIRFUNC))
- | GLOB_NOSORT | GLOB_ONLYDIR),
- errfunc, &dirs);
+ status = __glob (dirname,
+ ((flags & (GLOB_ERR | GLOB_NOESCAPE | GLOB_ALTDIRFUNC))
+ | GLOB_NOSORT | GLOB_ONLYDIR),
+ errfunc, &dirs);
if (status != 0)
{
if ((flags & GLOB_NOCHECK) == 0 || status != GLOB_NOMATCH)
- return status;
+ {
+ retval = status;
+ goto out;
+ }
goto no_matches;
}
@@ -1062,19 +980,6 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
{
size_t old_pathc;
-#ifdef SHELL
- {
- /* Make globbing interruptible in the bash shell. */
- extern int interrupt_state;
-
- if (interrupt_state)
- {
- globfree (&dirs);
- return GLOB_ABORTED;
- }
- }
-#endif /* SHELL. */
-
old_pathc = pglob->gl_pathc;
status = glob_in_dir (filename, dirs.gl_pathv[i],
((flags | GLOB_APPEND)
@@ -1089,7 +994,8 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
globfree (&dirs);
globfree (pglob);
pglob->gl_pathc = 0;
- return status;
+ retval = status;
+ goto out;
}
/* Stick the directory on the front of each name. */
@@ -1100,13 +1006,14 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
globfree (&dirs);
globfree (pglob);
pglob->gl_pathc = 0;
- return GLOB_NOSPACE;
+ retval = GLOB_NOSPACE;
+ goto out;
}
}
flags |= GLOB_MAGCHAR;
- /* We have ignored the GLOB_NOCHECK flag in the `glob_in_dir' calls.
+ /* We have ignored the GLOB_NOCHECK flag in the 'glob_in_dir' calls.
But if we have not found any matching entry and the GLOB_NOCHECK
flag was set we must return the input pattern itself. */
if (pglob->gl_pathc + pglob->gl_offs == oldcount)
@@ -1118,28 +1025,28 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
size_t newcount = pglob->gl_pathc + pglob->gl_offs;
char **new_gl_pathv;
- if (newcount > UINTPTR_MAX - 2
- || newcount + 2 > ~((size_t) 0) / sizeof (char *))
+ if (newcount > SIZE_MAX / sizeof (char *) - 2)
{
nospace2:
globfree (&dirs);
- return GLOB_NOSPACE;
+ retval = GLOB_NOSPACE;
+ goto out;
}
- new_gl_pathv = (char **) realloc (pglob->gl_pathv,
- (newcount + 2)
- * sizeof (char *));
+ new_gl_pathv = realloc (pglob->gl_pathv,
+ (newcount + 2) * sizeof (char *));
if (new_gl_pathv == NULL)
goto nospace2;
pglob->gl_pathv = new_gl_pathv;
- pglob->gl_pathv[newcount] = __strdup (pattern);
+ pglob->gl_pathv[newcount] = strdup (pattern);
if (pglob->gl_pathv[newcount] == NULL)
{
globfree (&dirs);
globfree (pglob);
pglob->gl_pathc = 0;
- return GLOB_NOSPACE;
+ retval = GLOB_NOSPACE;
+ goto out;
}
++pglob->gl_pathc;
@@ -1151,7 +1058,8 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
else
{
globfree (&dirs);
- return GLOB_NOMATCH;
+ retval = GLOB_NOMATCH;
+ goto out;
}
}
@@ -1162,7 +1070,7 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
size_t old_pathc = pglob->gl_pathc;
int orig_flags = flags;
- if (meta & 2)
+ if (meta & GLOBPAT_BACKSLASH)
{
char *p = strchr (dirname, '\\'), *q;
/* We need to unescape the dirname string. It is certainly
@@ -1197,7 +1105,8 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
flags = orig_flags;
goto no_matches;
}
- return status;
+ retval = status;
+ goto out;
}
if (dirlen > 0)
@@ -1209,7 +1118,8 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
{
globfree (pglob);
pglob->gl_pathc = 0;
- return GLOB_NOSPACE;
+ retval = GLOB_NOSPACE;
+ goto out;
}
}
}
@@ -1218,15 +1128,9 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
{
/* Append slashes to directory names. */
size_t i;
- struct stat st;
- struct_stat64 st64;
for (i = oldcount; i < pglob->gl_pathc + pglob->gl_offs; ++i)
- if ((__builtin_expect (flags & GLOB_ALTDIRFUNC, 0)
- ? ((*pglob->gl_stat) (pglob->gl_pathv[i], &st) == 0
- && S_ISDIR (st.st_mode))
- : (__stat64 (pglob->gl_pathv[i], &st64) == 0
- && S_ISDIR (st64.st_mode))))
+ if (is_dir (pglob->gl_pathv[i], flags, pglob))
{
size_t len = strlen (pglob->gl_pathv[i]) + 2;
char *new = realloc (pglob->gl_pathv[i], len);
@@ -1234,7 +1138,8 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
{
globfree (pglob);
pglob->gl_pathc = 0;
- return GLOB_NOSPACE;
+ retval = GLOB_NOSPACE;
+ goto out;
}
strcpy (&new[len - 2], "/");
pglob->gl_pathv[i] = new;
@@ -1255,28 +1160,9 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
return retval;
}
-#if defined _LIBC && !defined glob
-libc_hidden_def (glob)
-#endif
-
-
-#if !defined _LIBC || !defined GLOB_ONLY_P
-
-/* Free storage allocated in PGLOB by a previous `glob' call. */
-void
-globfree (glob_t *pglob)
-{
- if (pglob->gl_pathv != NULL)
- {
- size_t i;
- for (i = 0; i < pglob->gl_pathc; ++i)
- free (pglob->gl_pathv[pglob->gl_offs + i]);
- free (pglob->gl_pathv);
- pglob->gl_pathv = NULL;
- }
-}
-#if defined _LIBC && !defined globfree
-libc_hidden_def (globfree)
+#if defined _LIBC && !defined __glob
+versioned_symbol (libc, __glob, glob, GLIBC_2_27);
+libc_hidden_ver (__glob, glob)
#endif
@@ -1284,8 +1170,8 @@ libc_hidden_def (globfree)
static int
collated_compare (const void *a, const void *b)
{
- const char *const s1 = *(const char *const * const) a;
- const char *const s2 = *(const char *const * const) b;
+ char *const *ps1 = a; char *s1 = *ps1;
+ char *const *ps2 = b; char *s2 = *ps2;
if (s1 == s2)
return 0;
@@ -1306,28 +1192,24 @@ prefix_array (const char *dirname, char **array, size_t n)
{
size_t i;
size_t dirlen = strlen (dirname);
-#if defined __MSDOS__ || defined WINDOWS32
- int sep_char = '/';
-# define DIRSEP_CHAR sep_char
-#else
-# define DIRSEP_CHAR '/'
-#endif
+ char dirsep_char = '/';
if (dirlen == 1 && dirname[0] == '/')
/* DIRNAME is just "/", so normal prepending would get us "//foo".
We want "/foo" instead, so don't prepend any chars from DIRNAME. */
dirlen = 0;
+
#if defined __MSDOS__ || defined WINDOWS32
- else if (dirlen > 1)
+ if (dirlen > 1)
{
if (dirname[dirlen - 1] == '/' && dirname[dirlen - 2] == ':')
/* DIRNAME is "d:/". Don't prepend the slash from DIRNAME. */
--dirlen;
else if (dirname[dirlen - 1] == ':')
{
- /* DIRNAME is "d:". Use `:' instead of `/'. */
+ /* DIRNAME is "d:". Use ':' instead of '/'. */
--dirlen;
- sep_char = ':';
+ dirsep_char = ':';
}
}
#endif
@@ -1335,7 +1217,7 @@ prefix_array (const char *dirname, char **array, size_t n)
for (i = 0; i < n; ++i)
{
size_t eltlen = strlen (array[i]) + 1;
- char *new = (char *) malloc (dirlen + 1 + eltlen);
+ char *new = malloc (dirlen + 1 + eltlen);
if (new == NULL)
{
while (i > 0)
@@ -1345,7 +1227,7 @@ prefix_array (const char *dirname, char **array, size_t n)
{
char *endp = mempcpy (new, dirname, dirlen);
- *endp++ = DIRSEP_CHAR;
+ *endp++ = dirsep_char;
mempcpy (endp, array[i], eltlen);
}
free (array[i]);
@@ -1355,103 +1237,7 @@ prefix_array (const char *dirname, char **array, size_t n)
return 0;
}
-
-/* We must not compile this function twice. */
-#if !defined _LIBC || !defined NO_GLOB_PATTERN_P
-int
-__glob_pattern_type (const char *pattern, int quote)
-{
- const char *p;
- int ret = 0;
-
- for (p = pattern; *p != '\0'; ++p)
- switch (*p)
- {
- case '?':
- case '*':
- return 1;
-
- case '\\':
- if (quote)
- {
- if (p[1] != '\0')
- ++p;
- ret |= 2;
- }
- break;
-
- case '[':
- ret |= 4;
- break;
-
- case ']':
- if (ret & 4)
- return 1;
- break;
- }
-
- return ret;
-}
-
-/* Return nonzero if PATTERN contains any metacharacters.
- Metacharacters can be quoted with backslashes if QUOTE is nonzero. */
-int
-__glob_pattern_p (const char *pattern, int quote)
-{
- return __glob_pattern_type (pattern, quote) == 1;
-}
-# ifdef _LIBC
-weak_alias (__glob_pattern_p, glob_pattern_p)
-# endif
-#endif
-
-#endif /* !GLOB_ONLY_P */
-
-
-/* We put this in a separate function mainly to allow the memory
- allocated with alloca to be recycled. */
-#if !defined _LIBC || !defined GLOB_ONLY_P
-static int
-__attribute_noinline__
-link_exists2_p (const char *dir, size_t dirlen, const char *fname,
- glob_t *pglob
-# ifndef _LIBC
- , int flags
-# endif
- )
-{
- size_t fnamelen = strlen (fname);
- char *fullname = (char *) __alloca (dirlen + 1 + fnamelen + 1);
- struct stat st;
-# ifndef _LIBC
- struct_stat64 st64;
-# endif
-
- mempcpy (mempcpy (mempcpy (fullname, dir, dirlen), "/", 1),
- fname, fnamelen + 1);
-
-# ifdef _LIBC
- return (*pglob->gl_stat) (fullname, &st) == 0;
-# else
- return ((__builtin_expect (flags & GLOB_ALTDIRFUNC, 0)
- ? (*pglob->gl_stat) (fullname, &st)
- : __stat64 (fullname, &st64)) == 0);
-# endif
-}
-# ifdef _LIBC
-# define link_exists_p(dfd, dirname, dirnamelen, fname, pglob, flags) \
- (__builtin_expect (flags & GLOB_ALTDIRFUNC, 0) \
- ? link_exists2_p (dirname, dirnamelen, fname, pglob) \
- : ({ struct stat64 st64; \
- __fxstatat64 (_STAT_VER, dfd, fname, &st64, 0) == 0; }))
-# else
-# define link_exists_p(dfd, dirname, dirnamelen, fname, pglob, flags) \
- link_exists2_p (dirname, dirnamelen, fname, pglob, flags)
-# endif
-#endif
-
-
-/* Like `glob', but PATTERN is a final pathname component,
+/* Like 'glob', but PATTERN is a final pathname component,
and matches are searched for in DIRECTORY.
The GLOB_NOSORT bit in FLAGS is ignored. No sorting is ever done.
The GLOB_APPEND flag is assumed to be set (always appends). */
@@ -1462,52 +1248,47 @@ glob_in_dir (const char *pattern, const char *directory, int flags,
{
size_t dirlen = strlen (directory);
void *stream = NULL;
- struct globnames
- {
- struct globnames *next;
- size_t count;
- char *name[64];
- };
-#define INITIAL_COUNT sizeof (init_names.name) / sizeof (init_names.name[0])
- struct globnames init_names;
- struct globnames *names = &init_names;
- struct globnames *names_alloca = &init_names;
+# define GLOBNAMES_MEMBERS(nnames) \
+ struct globnames *next; size_t count; char *name[nnames];
+ struct globnames { GLOBNAMES_MEMBERS (FLEXIBLE_ARRAY_MEMBER) };
+ struct { GLOBNAMES_MEMBERS (64) } init_names_buf;
+ struct globnames *init_names = (struct globnames *) &init_names_buf;
+ struct globnames *names = init_names;
+ struct globnames *names_alloca = init_names;
size_t nfound = 0;
size_t cur = 0;
int meta;
int save;
+ int result;
- alloca_used += sizeof (init_names);
+ alloca_used += sizeof init_names_buf;
- init_names.next = NULL;
- init_names.count = INITIAL_COUNT;
+ init_names->next = NULL;
+ init_names->count = ((sizeof init_names_buf
+ - offsetof (struct globnames, name))
+ / sizeof init_names->name[0]);
meta = __glob_pattern_type (pattern, !(flags & GLOB_NOESCAPE));
- if (meta == 0 && (flags & (GLOB_NOCHECK|GLOB_NOMAGIC)))
+ if (meta == GLOBPAT_NONE && (flags & (GLOB_NOCHECK|GLOB_NOMAGIC)))
{
/* We need not do any tests. The PATTERN contains no meta
characters and we must not return an error therefore the
result will always contain exactly one name. */
flags |= GLOB_NOCHECK;
}
- else if (meta == 0)
+ else if (meta == GLOBPAT_NONE)
{
- /* Since we use the normal file functions we can also use stat()
- to verify the file is there. */
- union
- {
- struct stat st;
- struct_stat64 st64;
- } ust;
size_t patlen = strlen (pattern);
- int alloca_fullname = __libc_use_alloca (alloca_used
- + dirlen + 1 + patlen + 1);
+ size_t fullsize;
+ bool alloca_fullname
+ = (! size_add_wrapv (dirlen + 1, patlen + 1, &fullsize)
+ && glob_use_alloca (alloca_used, fullsize));
char *fullname;
if (alloca_fullname)
- fullname = alloca_account (dirlen + 1 + patlen + 1, alloca_used);
+ fullname = alloca_account (fullsize, alloca_used);
else
{
- fullname = malloc (dirlen + 1 + patlen + 1);
+ fullname = malloc (fullsize);
if (fullname == NULL)
return GLOB_NOSPACE;
}
@@ -1515,9 +1296,8 @@ glob_in_dir (const char *pattern, const char *directory, int flags,
mempcpy (mempcpy (mempcpy (fullname, directory, dirlen),
"/", 1),
pattern, patlen + 1);
- if ((__builtin_expect (flags & GLOB_ALTDIRFUNC, 0)
- ? (*pglob->gl_stat) (fullname, &ust.st)
- : __stat64 (fullname, &ust.st64)) == 0)
+ if (glob_lstat (pglob, flags, fullname) == 0
+ || errno == EOVERFLOW)
/* We found this file to be existing. Now tell the rest
of the function to copy this name into the result. */
flags |= GLOB_NOCHECK;
@@ -1539,97 +1319,67 @@ glob_in_dir (const char *pattern, const char *directory, int flags,
}
else
{
-#ifdef _LIBC
- int dfd = (__builtin_expect (flags & GLOB_ALTDIRFUNC, 0)
- ? -1 : dirfd ((DIR *) stream));
-#endif
int fnm_flags = ((!(flags & GLOB_PERIOD) ? FNM_PERIOD : 0)
- | ((flags & GLOB_NOESCAPE) ? FNM_NOESCAPE : 0)
-#if defined _AMIGA || defined VMS
- | FNM_CASEFOLD
-#endif
- );
+ | ((flags & GLOB_NOESCAPE) ? FNM_NOESCAPE : 0));
flags |= GLOB_MAGCHAR;
while (1)
{
- const char *name;
- size_t len;
-#if defined _LIBC && !defined COMPILE_GLOB64
- struct dirent64 *d;
- union
- {
- struct dirent64 d64;
- char room [offsetof (struct dirent64, d_name[0])
- + NAME_MAX + 1];
- }
- d64buf;
-
- if (__glibc_unlikely (flags & GLOB_ALTDIRFUNC))
- {
- struct dirent *d32 = (*pglob->gl_readdir) (stream);
- if (d32 != NULL)
- {
- CONVERT_DIRENT_DIRENT64 (&d64buf.d64, d32);
- d = &d64buf.d64;
- }
- else
- d = NULL;
- }
- else
- d = __readdir64 (stream);
+ struct readdir_result d;
+ {
+ if (__builtin_expect (flags & GLOB_ALTDIRFUNC, 0))
+ d = convert_dirent (GL_READDIR (pglob, stream));
+ else
+ {
+#ifdef COMPILE_GLOB64
+ d = convert_dirent (__readdir (stream));
#else
- struct dirent *d = (__builtin_expect (flags & GLOB_ALTDIRFUNC, 0)
- ? ((struct dirent *)
- (*pglob->gl_readdir) (stream))
- : __readdir (stream));
+ d = convert_dirent64 (__readdir64 (stream));
#endif
- if (d == NULL)
+ }
+ }
+ if (d.name == NULL)
break;
- if (! REAL_DIR_ENTRY (d))
- continue;
/* If we shall match only directories use the information
provided by the dirent call if possible. */
- if ((flags & GLOB_ONLYDIR) && !DIRENT_MIGHT_BE_DIR (d))
- continue;
-
- name = d->d_name;
+ if (flags & GLOB_ONLYDIR)
+ switch (readdir_result_type (d))
+ {
+ case DT_DIR: case DT_LNK: case DT_UNKNOWN: break;
+ default: continue;
+ }
- if (fnmatch (pattern, name, fnm_flags) == 0)
+ if (fnmatch (pattern, d.name, fnm_flags) == 0)
{
- /* If the file we found is a symlink we have to
- make sure the target file exists. */
- if (!DIRENT_MIGHT_BE_SYMLINK (d)
- || link_exists_p (dfd, directory, dirlen, name, pglob,
- flags))
+ if (cur == names->count)
{
- if (cur == names->count)
- {
- struct globnames *newnames;
- size_t count = names->count * 2;
- size_t size = (sizeof (struct globnames)
- + ((count - INITIAL_COUNT)
- * sizeof (char *)));
- if (__libc_use_alloca (alloca_used + size))
- newnames = names_alloca
- = alloca_account (size, alloca_used);
- else if ((newnames = malloc (size))
- == NULL)
- goto memory_error;
- newnames->count = count;
- newnames->next = names;
- names = newnames;
- cur = 0;
- }
- len = NAMLEN (d);
- names->name[cur] = (char *) malloc (len + 1);
- if (names->name[cur] == NULL)
+ struct globnames *newnames;
+ size_t count = names->count * 2;
+ size_t nameoff = offsetof (struct globnames, name);
+ size_t size = FLEXSIZEOF (struct globnames, name,
+ count * sizeof (char *));
+ if ((SIZE_MAX - nameoff) / 2 / sizeof (char *)
+ < names->count)
+ goto memory_error;
+ if (glob_use_alloca (alloca_used, size))
+ newnames = names_alloca
+ = alloca_account (size, alloca_used);
+ else if ((newnames = malloc (size))
+ == NULL)
goto memory_error;
- *((char *) mempcpy (names->name[cur++], name, len))
- = '\0';
- ++nfound;
+ newnames->count = count;
+ newnames->next = names;
+ names = newnames;
+ cur = 0;
}
+ names->name[cur] = strdup (d.name);
+ if (names->name[cur] == NULL)
+ goto memory_error;
+ ++cur;
+ ++nfound;
+ if (SIZE_MAX - pglob->gl_offs <= nfound)
+ goto memory_error;
}
}
}
@@ -1639,29 +1389,27 @@ glob_in_dir (const char *pattern, const char *directory, int flags,
{
size_t len = strlen (pattern);
nfound = 1;
- names->name[cur] = (char *) malloc (len + 1);
+ names->name[cur] = malloc (len + 1);
if (names->name[cur] == NULL)
goto memory_error;
*((char *) mempcpy (names->name[cur++], pattern, len)) = '\0';
}
- int result = GLOB_NOMATCH;
+ result = GLOB_NOMATCH;
if (nfound != 0)
{
+ char **new_gl_pathv;
result = 0;
- if (pglob->gl_pathc > UINTPTR_MAX - pglob->gl_offs
- || pglob->gl_pathc + pglob->gl_offs > UINTPTR_MAX - nfound
- || pglob->gl_pathc + pglob->gl_offs + nfound > UINTPTR_MAX - 1
- || (pglob->gl_pathc + pglob->gl_offs + nfound + 1
- > UINTPTR_MAX / sizeof (char *)))
+ if (SIZE_MAX / sizeof (char *) - pglob->gl_pathc
+ < pglob->gl_offs + nfound + 1)
goto memory_error;
- char **new_gl_pathv;
new_gl_pathv
- = (char **) realloc (pglob->gl_pathv,
- (pglob->gl_pathc + pglob->gl_offs + nfound + 1)
- * sizeof (char *));
+ = realloc (pglob->gl_pathv,
+ (pglob->gl_pathc + pglob->gl_offs + nfound + 1)
+ * sizeof (char *));
+
if (new_gl_pathv == NULL)
{
memory_error:
@@ -1677,7 +1425,7 @@ glob_in_dir (const char *pattern, const char *directory, int flags,
and this is the block assigned to OLD here. */
if (names == NULL)
{
- assert (old == &init_names);
+ assert (old == init_names);
break;
}
cur = names->count;
@@ -1703,7 +1451,7 @@ glob_in_dir (const char *pattern, const char *directory, int flags,
and this is the block assigned to OLD here. */
if (names == NULL)
{
- assert (old == &init_names);
+ assert (old == init_names);
break;
}
cur = names->count;
diff --git a/posix/glob.h b/posix/glob.h
index e4548f6f75..b0d034b72d 100644
--- a/posix/glob.h
+++ b/posix/glob.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -25,7 +25,7 @@ __BEGIN_DECLS
/* We need `size_t' for the following definitions. */
#ifndef __size_t
typedef __SIZE_TYPE__ __size_t;
-# if defined __USE_XOPEN || __USE_XOPEN2K8
+# if defined __USE_XOPEN || defined __USE_XOPEN2K8
typedef __SIZE_TYPE__ size_t;
# endif
#else
diff --git a/posix/glob64-lstat-compat.c b/posix/glob64-lstat-compat.c
new file mode 100644
index 0000000000..fe7b3e0bdc
--- /dev/null
+++ b/posix/glob64-lstat-compat.c
@@ -0,0 +1,36 @@
+/* Compat glob which does not use gl_lstat for GLOB_ALTDIRFUNC.
+ Copyright (C) 2017-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <shlib-compat.h>
+
+#if SHLIB_COMPAT(libc, GLIBC_2_0, GLIBC_2_27)
+
+# include <glob.h>
+
+# define glob(pattern, flags, errfunc, pglob) \
+ __glob64_lstat_compat (pattern, flags, errfunc, pglob)
+
+# define GLOB_ATTRIBUTE attribute_compat_text_section
+
+/* Avoid calling gl_lstat with GLOB_ALTDIRFUNC. */
+# define GLOB_NO_LSTAT
+
+# include <posix/glob64.c>
+
+compat_symbol (libc, __glob64_lstat_compat, glob64, GLIBC_2_0);
+#endif
diff --git a/posix/glob64.c b/posix/glob64.c
index a5f5a7f9e2..6285a22fa8 100644
--- a/posix/glob64.c
+++ b/posix/glob64.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1998-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1998-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -20,6 +20,10 @@
#include <glob.h>
#include <errno.h>
+#ifdef GLOB_ATTRIBUTE
+# define GLOB_ATTRIBUTE
+#endif
+
/* Do glob searching for PATTERN, placing results in PGLOB.
The bits defined above may be set in FLAGS.
If a directory cannot be opened or read and ERRFUNC is not nil,
@@ -29,6 +33,7 @@
If memory cannot be allocated for PGLOB, GLOB_NOSPACE is returned.
Otherwise, `glob' returns zero. */
int
+GLOB_ATTRIBUTE
glob64 (const char *pattern, int flags,
int (*errfunc) (const char *, int), glob64_t *pglob)
{
@@ -43,10 +48,4 @@ glob64 (const char *pattern, int flags,
}
libc_hidden_def (glob64)
-void
-globfree64 (glob64_t *pglob)
-{
-}
-libc_hidden_def (globfree64)
-
stub_warning (glob64)
diff --git a/posix/glob_internal.h b/posix/glob_internal.h
new file mode 100644
index 0000000000..46a5f138ae
--- /dev/null
+++ b/posix/glob_internal.h
@@ -0,0 +1,65 @@
+/* Shared definition for glob and glob_pattern_p.
+ Copyright (C) 2017-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef GLOB_INTERNAL_H
+# define GLOB_INTERNAL_H
+
+enum
+{
+ GLOBPAT_NONE = 0x0,
+ GLOBPAT_SPECIAL = 0x1,
+ GLOBPAT_BACKSLASH = 0x2,
+ GLOBPAT_BRACKET = 0x4
+};
+
+static inline int
+__glob_pattern_type (const char *pattern, int quote)
+{
+ const char *p;
+ int ret = GLOBPAT_NONE;
+
+ for (p = pattern; *p != '\0'; ++p)
+ switch (*p)
+ {
+ case '?':
+ case '*':
+ return GLOBPAT_SPECIAL;
+
+ case '\\':
+ if (quote)
+ {
+ if (p[1] != '\0')
+ ++p;
+ ret |= GLOBPAT_BACKSLASH;
+ }
+ break;
+
+ case '[':
+ ret |= GLOBPAT_BRACKET;
+ break;
+
+ case ']':
+ if (ret & 4)
+ return GLOBPAT_SPECIAL;
+ break;
+ }
+
+ return ret;
+}
+
+#endif /* GLOB_INTERNAL_H */
diff --git a/posix/glob_pattern_p.c b/posix/glob_pattern_p.c
new file mode 100644
index 0000000000..0f72d186c8
--- /dev/null
+++ b/posix/glob_pattern_p.c
@@ -0,0 +1,33 @@
+/* Return nonzero if PATTERN contains any metacharacters.
+ Copyright (C) 2017-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _LIBC
+# include <config.h>
+#endif
+
+#include <glob.h>
+#include "glob_internal.h"
+
+/* Return nonzero if PATTERN contains any metacharacters.
+ Metacharacters can be quoted with backslashes if QUOTE is nonzero. */
+int
+__glob_pattern_p (const char *pattern, int quote)
+{
+ return __glob_pattern_type (pattern, quote) == GLOBPAT_SPECIAL;
+}
+weak_alias (__glob_pattern_p, glob_pattern_p)
diff --git a/posix/globfree.c b/posix/globfree.c
new file mode 100644
index 0000000000..19d2a8e83b
--- /dev/null
+++ b/posix/globfree.c
@@ -0,0 +1,41 @@
+/* Frees the dynamically allocated storage from an earlier call to glob.
+ Copyright (C) 2017-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _LIBC
+# include <config.h>
+#endif
+
+#include <glob.h>
+#include <stdlib.h>
+
+/* Free storage allocated in PGLOB by a previous `glob' call. */
+void
+globfree (glob_t *pglob)
+{
+ if (pglob->gl_pathv != NULL)
+ {
+ size_t i;
+ for (i = 0; i < pglob->gl_pathc; ++i)
+ free (pglob->gl_pathv[pglob->gl_offs + i]);
+ free (pglob->gl_pathv);
+ pglob->gl_pathv = NULL;
+ }
+}
+#ifndef globfree
+libc_hidden_def (globfree)
+#endif
diff --git a/posix/globfree64.c b/posix/globfree64.c
new file mode 100644
index 0000000000..eea942a607
--- /dev/null
+++ b/posix/globfree64.c
@@ -0,0 +1,31 @@
+/* Frees the dynamically allocated storage from an earlier call to glob.
+ Copyright (C) 2017-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _LIBC
+# include <config.h>
+#endif
+
+#include <glob.h>
+#include <stdlib.h>
+
+/* Free storage allocated in PGLOB by a previous `glob' call. */
+void
+globfree64 (glob64_t *pglob)
+{
+}
+libc_hidden_def (globfree64)
diff --git a/posix/globtest.c b/posix/globtest.c
index e1b2073950..7a8ccc4b59 100644
--- a/posix/globtest.c
+++ b/posix/globtest.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1997-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1997-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/posix/globtest.sh b/posix/globtest.sh
index 73fe11bd76..7f91e810f3 100755
--- a/posix/globtest.sh
+++ b/posix/globtest.sh
@@ -1,6 +1,6 @@
#!/bin/bash
# Test for glob(3).
-# Copyright (C) 1997-2016 Free Software Foundation, Inc.
+# Copyright (C) 1997-2018 Free Software Foundation, Inc.
# This file is part of the GNU C Library.
# The GNU C Library is free software; you can redistribute it and/or
@@ -47,7 +47,12 @@ testout=${common_objpfx}posix/globtest-out
rm -rf $testdir $testout
mkdir $testdir
-trap 'chmod 777 $testdir/noread; rm -fr $testdir $testout' 1 2 3 15
+cleanup() {
+ chmod 777 $testdir/noread
+ rm -fr $testdir $testout
+}
+
+trap cleanup 0 HUP INT QUIT TERM
echo 1 > $testdir/file1
echo 2 > $testdir/file2
@@ -794,9 +799,23 @@ if test $failed -ne 0; then
result=1
fi
+# Test GLOB_BRACE and GLIB_DOOFFS with malloc checking
+failed=0
+${test_wrapper_env} \
+MALLOC_PERTURB_=65 \
+${test_via_rtld_prefix} \
+${common_objpfx}posix/globtest -b -o "$testdir" "file{1,2}" > $testout || failed=1
+cat <<"EOF" | $CMP - $testout >> $logfile || failed=1
+`abc'
+`file1'
+`file2'
+EOF
+if test $failed -ne 0; then
+ echo "GLOB_BRACE+GLOB_DOOFFS test failed" >> $logfile
+ result=1
+fi
+
if test $result -eq 0; then
- chmod 777 $testdir/noread
- rm -fr $testdir $testout
echo "All OK." > $logfile
fi
diff --git a/posix/group_member.c b/posix/group_member.c
index fa8da58802..27795a5dc9 100644
--- a/posix/group_member.c
+++ b/posix/group_member.c
@@ -1,5 +1,5 @@
/* `group_member' -- test if process is in a given group.
- Copyright (C) 1995-2016 Free Software Foundation, Inc.
+ Copyright (C) 1995-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/posix/nanosleep.c b/posix/nanosleep.c
index fe68ce3d57..3f13a1db48 100644
--- a/posix/nanosleep.c
+++ b/posix/nanosleep.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1996-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1996-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -29,5 +29,5 @@ __nanosleep (const struct timespec *requested_time,
}
stub_warning (nanosleep)
-libc_hidden_def (__nanosleep)
+hidden_def (__nanosleep)
weak_alias (__nanosleep, nanosleep)
diff --git a/posix/pathconf.c b/posix/pathconf.c
index 4f02f0ff80..f4bc7eb257 100644
--- a/posix/pathconf.c
+++ b/posix/pathconf.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/posix/pause.c b/posix/pause.c
index 567817ecc5..0ce286b76b 100644
--- a/posix/pause.c
+++ b/posix/pause.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/posix/posix-conf-vars.h b/posix/posix-conf-vars.h
index 3df0b8dd29..20c9a5f4d6 100644
--- a/posix/posix-conf-vars.h
+++ b/posix/posix-conf-vars.h
@@ -1,6 +1,6 @@
/* Macros to check if a POSIX configuration variable is defined or set.
- Copyright (C) 1991-2016 Free Software Foundation, Inc.
+ Copyright (C) 1991-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/posix/posix-envs.def b/posix/posix-envs.def
index f6aad17438..0f6c29a3c7 100644
--- a/posix/posix-envs.def
+++ b/posix/posix-envs.def
@@ -1,5 +1,5 @@
/* Handle POSIX compilation environments that may or may not be present.
- Copyright (C) 2012-2016 Free Software Foundation, Inc.
+ Copyright (C) 2012-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/posix/posix_madvise.c b/posix/posix_madvise.c
index cc84c9732c..f789a9a862 100644
--- a/posix/posix_madvise.c
+++ b/posix/posix_madvise.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1994-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1994-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -23,7 +23,7 @@
for the region starting at ADDR and extending LEN bytes. */
int
-posix_madvise (__ptr_t addr, size_t len, int advice)
+posix_madvise (void *addr, size_t len, int advice)
{
return ENOSYS;
}
diff --git a/posix/pread.c b/posix/pread.c
index 3179eee9ef..2da5743f28 100644
--- a/posix/pread.c
+++ b/posix/pread.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/posix/pread64.c b/posix/pread64.c
index f34fcaa9df..e13917e9c0 100644
--- a/posix/pread64.c
+++ b/posix/pread64.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -40,5 +40,6 @@ __libc_pread64 (int fd, void *buf, size_t nbytes, off64_t offset)
return -1;
}
strong_alias (__libc_pread64, __pread64)
+libc_hidden_def (__pread64)
weak_alias (__libc_pread64, pread64)
stub_warning (pread64)
diff --git a/posix/pwrite.c b/posix/pwrite.c
index 9b09f1ccc1..35b7130377 100644
--- a/posix/pwrite.c
+++ b/posix/pwrite.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/posix/pwrite64.c b/posix/pwrite64.c
index a2a9e47d87..04b3b094ff 100644
--- a/posix/pwrite64.c
+++ b/posix/pwrite64.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/posix/re_comp.h b/posix/re_comp.h
index 1537125250..d011b26e02 100644
--- a/posix/re_comp.h
+++ b/posix/re_comp.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 1996-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1996-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/posix/regcomp.c b/posix/regcomp.c
index b6126b7b98..545d188468 100644
--- a/posix/regcomp.c
+++ b/posix/regcomp.c
@@ -1,5 +1,5 @@
/* Extended regular expression matching and search library.
- Copyright (C) 2002-2016 Free Software Foundation, Inc.
+ Copyright (C) 2002-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Isamu Hasegawa <isamu@yamato.ibm.com>.
@@ -15,9 +15,7 @@
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
- <http://www.gnu.org/licenses/>. */
-
-#include <stdint.h>
+ <https://www.gnu.org/licenses/>. */
#ifdef _LIBC
# include <locale/weight.h>
@@ -51,31 +49,31 @@ static bin_tree_t *lower_subexp (reg_errcode_t *err, regex_t *preg,
static reg_errcode_t calc_first (void *extra, bin_tree_t *node);
static reg_errcode_t calc_next (void *extra, bin_tree_t *node);
static reg_errcode_t link_nfa_nodes (void *extra, bin_tree_t *node);
-static int duplicate_node (re_dfa_t *dfa, int org_idx, unsigned int constraint);
-static int search_duplicated_node (const re_dfa_t *dfa, int org_node,
+static Idx duplicate_node (re_dfa_t *dfa, Idx org_idx, unsigned int constraint);
+static Idx search_duplicated_node (const re_dfa_t *dfa, Idx org_node,
unsigned int constraint);
static reg_errcode_t calc_eclosure (re_dfa_t *dfa);
static reg_errcode_t calc_eclosure_iter (re_node_set *new_set, re_dfa_t *dfa,
- int node, int root);
+ Idx node, bool root);
static reg_errcode_t calc_inveclosure (re_dfa_t *dfa);
-static int fetch_number (re_string_t *input, re_token_t *token,
+static Idx fetch_number (re_string_t *input, re_token_t *token,
reg_syntax_t syntax);
static int peek_token (re_token_t *token, re_string_t *input,
- reg_syntax_t syntax) internal_function;
+ reg_syntax_t syntax);
static bin_tree_t *parse (re_string_t *regexp, regex_t *preg,
reg_syntax_t syntax, reg_errcode_t *err);
static bin_tree_t *parse_reg_exp (re_string_t *regexp, regex_t *preg,
re_token_t *token, reg_syntax_t syntax,
- int nest, reg_errcode_t *err);
+ Idx nest, reg_errcode_t *err);
static bin_tree_t *parse_branch (re_string_t *regexp, regex_t *preg,
re_token_t *token, reg_syntax_t syntax,
- int nest, reg_errcode_t *err);
+ Idx nest, reg_errcode_t *err);
static bin_tree_t *parse_expression (re_string_t *regexp, regex_t *preg,
re_token_t *token, reg_syntax_t syntax,
- int nest, reg_errcode_t *err);
+ Idx nest, reg_errcode_t *err);
static bin_tree_t *parse_sub_exp (re_string_t *regexp, regex_t *preg,
re_token_t *token, reg_syntax_t syntax,
- int nest, reg_errcode_t *err);
+ Idx nest, reg_errcode_t *err);
static bin_tree_t *parse_dup_op (bin_tree_t *dup_elem, re_string_t *regexp,
re_dfa_t *dfa, re_token_t *token,
reg_syntax_t syntax, reg_errcode_t *err);
@@ -87,34 +85,34 @@ static reg_errcode_t parse_bracket_element (bracket_elem_t *elem,
re_token_t *token, int token_len,
re_dfa_t *dfa,
reg_syntax_t syntax,
- int accept_hyphen);
+ bool accept_hyphen);
static reg_errcode_t parse_bracket_symbol (bracket_elem_t *elem,
re_string_t *regexp,
re_token_t *token);
#ifdef RE_ENABLE_I18N
static reg_errcode_t build_equiv_class (bitset_t sbcset,
re_charset_t *mbcset,
- int *equiv_class_alloc,
+ Idx *equiv_class_alloc,
const unsigned char *name);
static reg_errcode_t build_charclass (RE_TRANSLATE_TYPE trans,
bitset_t sbcset,
re_charset_t *mbcset,
- int *char_class_alloc,
- const unsigned char *class_name,
+ Idx *char_class_alloc,
+ const char *class_name,
reg_syntax_t syntax);
#else /* not RE_ENABLE_I18N */
static reg_errcode_t build_equiv_class (bitset_t sbcset,
const unsigned char *name);
static reg_errcode_t build_charclass (RE_TRANSLATE_TYPE trans,
bitset_t sbcset,
- const unsigned char *class_name,
+ const char *class_name,
reg_syntax_t syntax);
#endif /* not RE_ENABLE_I18N */
static bin_tree_t *build_charclass_op (re_dfa_t *dfa,
RE_TRANSLATE_TYPE trans,
- const unsigned char *class_name,
- const unsigned char *extra,
- int non_match, reg_errcode_t *err);
+ const char *class_name,
+ const char *extra,
+ bool non_match, reg_errcode_t *err);
static bin_tree_t *create_tree (re_dfa_t *dfa,
bin_tree_t *left, bin_tree_t *right,
re_token_type_t type);
@@ -131,7 +129,7 @@ static reg_errcode_t mark_opt_subexp (void *extra, bin_tree_t *node);
POSIX doesn't require that we do anything for REG_NOERROR,
but why not be nice? */
-const char __re_error_msgid[] attribute_hidden =
+static const char __re_error_msgid[] =
{
#define REG_NOERROR_IDX 0
gettext_noop ("Success") /* REG_NOERROR */
@@ -155,9 +153,9 @@ const char __re_error_msgid[] attribute_hidden =
gettext_noop ("Invalid back reference") /* REG_ESUBREG */
"\0"
#define REG_EBRACK_IDX (REG_ESUBREG_IDX + sizeof "Invalid back reference")
- gettext_noop ("Unmatched [ or [^") /* REG_EBRACK */
+ gettext_noop ("Unmatched [, [^, [:, [., or [=") /* REG_EBRACK */
"\0"
-#define REG_EPAREN_IDX (REG_EBRACK_IDX + sizeof "Unmatched [ or [^")
+#define REG_EPAREN_IDX (REG_EBRACK_IDX + sizeof "Unmatched [, [^, [:, [., or [=")
gettext_noop ("Unmatched ( or \\(") /* REG_EPAREN */
"\0"
#define REG_EBRACE_IDX (REG_EPAREN_IDX + sizeof "Unmatched ( or \\(")
@@ -185,7 +183,7 @@ const char __re_error_msgid[] attribute_hidden =
gettext_noop ("Unmatched ) or \\)") /* REG_ERPAREN */
};
-const size_t __re_error_msgid_idx[] attribute_hidden =
+static const size_t __re_error_msgid_idx[] =
{
REG_NOERROR_IDX,
REG_NOMATCH_IDX,
@@ -269,7 +267,7 @@ weak_alias (__re_set_syntax, re_set_syntax)
int
re_compile_fastmap (struct re_pattern_buffer *bufp)
{
- re_dfa_t *dfa = (re_dfa_t *) bufp->buffer;
+ re_dfa_t *dfa = bufp->buffer;
char *fastmap = bufp->fastmap;
memset (fastmap, '\0', sizeof (char) * SBC_MAX);
@@ -303,12 +301,12 @@ static void
re_compile_fastmap_iter (regex_t *bufp, const re_dfastate_t *init_state,
char *fastmap)
{
- re_dfa_t *dfa = (re_dfa_t *) bufp->buffer;
- int node_cnt;
- int icase = (dfa->mb_cur_max == 1 && (bufp->syntax & RE_ICASE));
+ re_dfa_t *dfa = bufp->buffer;
+ Idx node_cnt;
+ bool icase = (dfa->mb_cur_max == 1 && (bufp->syntax & RE_ICASE));
for (node_cnt = 0; node_cnt < init_state->nodes.nelem; ++node_cnt)
{
- int node = init_state->nodes.elems[node_cnt];
+ Idx node = init_state->nodes.elems[node_cnt];
re_token_type_t type = dfa->nodes[node].type;
if (type == CHARACTER)
@@ -317,7 +315,8 @@ re_compile_fastmap_iter (regex_t *bufp, const re_dfastate_t *init_state,
#ifdef RE_ENABLE_I18N
if ((bufp->syntax & RE_ICASE) && dfa->mb_cur_max > 1)
{
- unsigned char *buf = alloca (dfa->mb_cur_max), *p;
+ unsigned char buf[MB_LEN_MAX];
+ unsigned char *p;
wchar_t wc;
mbstate_t state;
@@ -332,7 +331,7 @@ re_compile_fastmap_iter (regex_t *bufp, const re_dfastate_t *init_state,
&state) == p - buf
&& (__wcrtomb ((char *) buf, __towlower (wc), &state)
!= (size_t) -1))
- re_set_fastmap (fastmap, 0, buf[0]);
+ re_set_fastmap (fastmap, false, buf[0]);
}
#endif
}
@@ -352,7 +351,7 @@ re_compile_fastmap_iter (regex_t *bufp, const re_dfastate_t *init_state,
else if (type == COMPLEX_BRACKET)
{
re_charset_t *cset = dfa->nodes[node].opr.mbcset;
- int i;
+ Idx i;
# ifdef _LIBC
/* See if we have to try all bytes which start multiple collation
@@ -465,7 +464,7 @@ re_compile_fastmap_iter (regex_t *bufp, const re_dfastate_t *init_state,
the return codes and their meanings.) */
int
-regcomp (regex_t *__restrict preg, const char *__restrict pattern, int cflags)
+regcomp (regex_t *_Restrict_ preg, const char *_Restrict_ pattern, int cflags)
{
reg_errcode_t ret;
reg_syntax_t syntax = ((cflags & REG_EXTENDED) ? RE_SYNTAX_POSIX_EXTENDED
@@ -517,6 +516,7 @@ regcomp (regex_t *__restrict preg, const char *__restrict pattern, int cflags)
return (int) ret;
}
#ifdef _LIBC
+libc_hidden_def (__regcomp)
weak_alias (__regcomp, regcomp)
#endif
@@ -524,7 +524,7 @@ weak_alias (__regcomp, regcomp)
from either regcomp or regexec. We don't use PREG here. */
size_t
-regerror (int errcode, const regex_t *__restrict preg, char *__restrict errbuf,
+regerror (int errcode, const regex_t *_Restrict_ preg, char *_Restrict_ errbuf,
size_t errbuf_size)
{
const char *msg;
@@ -545,17 +545,13 @@ regerror (int errcode, const regex_t *__restrict preg, char *__restrict errbuf,
if (BE (errbuf_size != 0, 1))
{
+ size_t cpy_size = msg_size;
if (BE (msg_size > errbuf_size, 0))
{
-#if defined HAVE_MEMPCPY || defined _LIBC
- *((char *) __mempcpy (errbuf, msg, errbuf_size - 1)) = '\0';
-#else
- memcpy (errbuf, msg, errbuf_size - 1);
- errbuf[errbuf_size - 1] = 0;
-#endif
+ cpy_size = errbuf_size - 1;
+ errbuf[cpy_size] = '\0';
}
- else
- memcpy (errbuf, msg, msg_size);
+ memcpy (errbuf, msg, cpy_size);
}
return msg_size;
@@ -573,7 +569,23 @@ weak_alias (__regerror, regerror)
static const bitset_t utf8_sb_map =
{
/* Set the first 128 bits. */
+# if defined __GNUC__ && !defined __STRICT_ANSI__
[0 ... 0x80 / BITSET_WORD_BITS - 1] = BITSET_WORD_MAX
+# else
+# if 4 * BITSET_WORD_BITS < ASCII_CHARS
+# error "bitset_word_t is narrower than 32 bits"
+# elif 3 * BITSET_WORD_BITS < ASCII_CHARS
+ BITSET_WORD_MAX, BITSET_WORD_MAX, BITSET_WORD_MAX,
+# elif 2 * BITSET_WORD_BITS < ASCII_CHARS
+ BITSET_WORD_MAX, BITSET_WORD_MAX,
+# elif 1 * BITSET_WORD_BITS < ASCII_CHARS
+ BITSET_WORD_MAX,
+# endif
+ (BITSET_WORD_MAX
+ >> (SBC_MAX % BITSET_WORD_BITS == 0
+ ? 0
+ : BITSET_WORD_BITS - SBC_MAX % BITSET_WORD_BITS))
+# endif
};
#endif
@@ -581,7 +593,7 @@ static const bitset_t utf8_sb_map =
static void
free_dfa_content (re_dfa_t *dfa)
{
- int i, j;
+ Idx i, j;
if (dfa->nodes)
for (i = 0; i < dfa->nodes_len; ++i)
@@ -631,9 +643,12 @@ free_dfa_content (re_dfa_t *dfa)
void
regfree (regex_t *preg)
{
- re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
+ re_dfa_t *dfa = preg->buffer;
if (BE (dfa != NULL, 1))
- free_dfa_content (dfa);
+ {
+ lock_fini (dfa->lock);
+ free_dfa_content (dfa);
+ }
preg->buffer = NULL;
preg->allocated = 0;
@@ -644,6 +659,7 @@ regfree (regex_t *preg)
preg->translate = NULL;
}
#ifdef _LIBC
+libc_hidden_def (__regfree)
weak_alias (__regfree, regfree)
#endif
@@ -685,7 +701,7 @@ re_comp (const char *s)
if (re_comp_buf.fastmap == NULL)
{
- re_comp_buf.fastmap = (char *) malloc (SBC_MAX);
+ re_comp_buf.fastmap = re_malloc (char, SBC_MAX);
if (re_comp_buf.fastmap == NULL)
return (char *) gettext (__re_error_msgid
+ __re_error_msgid_idx[(int) REG_ESPACE]);
@@ -702,7 +718,7 @@ re_comp (const char *s)
if (!ret)
return NULL;
- /* Yes, we're discarding `const' here if !HAVE_LIBINTL. */
+ /* Yes, we're discarding 'const' here if !HAVE_LIBINTL. */
return (char *) gettext (__re_error_msgid + __re_error_msgid_idx[(int) ret]);
}
@@ -737,7 +753,7 @@ re_compile_internal (regex_t *preg, const char * pattern, size_t length,
preg->regs_allocated = REGS_UNALLOCATED;
/* Initialize the dfa. */
- dfa = (re_dfa_t *) preg->buffer;
+ dfa = preg->buffer;
if (BE (preg->allocated < sizeof (re_dfa_t), 0))
{
/* If zero allocated, but buffer is non-null, try to realloc
@@ -748,11 +764,13 @@ re_compile_internal (regex_t *preg, const char * pattern, size_t length,
if (dfa == NULL)
return REG_ESPACE;
preg->allocated = sizeof (re_dfa_t);
- preg->buffer = (unsigned char *) dfa;
+ preg->buffer = dfa;
}
preg->used = sizeof (re_dfa_t);
err = init_dfa (dfa, length);
+ if (BE (err == REG_NOERROR && lock_init (dfa->lock) != 0, 0))
+ err = REG_ESPACE;
if (BE (err != REG_NOERROR, 0))
{
free_dfa_content (dfa);
@@ -766,15 +784,14 @@ re_compile_internal (regex_t *preg, const char * pattern, size_t length,
strncpy (dfa->re_str, pattern, length + 1);
#endif
- __libc_lock_init (dfa->lock);
-
err = re_string_construct (&regexp, pattern, length, preg->translate,
- syntax & RE_ICASE, dfa);
+ (syntax & RE_ICASE) != 0, dfa);
if (BE (err != REG_NOERROR, 0))
{
re_compile_internal_free_return:
free_workarea_compile (preg);
re_string_destruct (&regexp);
+ lock_fini (dfa->lock);
free_dfa_content (dfa);
preg->buffer = NULL;
preg->allocated = 0;
@@ -807,6 +824,7 @@ re_compile_internal (regex_t *preg, const char * pattern, size_t length,
if (BE (err != REG_NOERROR, 0))
{
+ lock_fini (dfa->lock);
free_dfa_content (dfa);
preg->buffer = NULL;
preg->allocated = 0;
@@ -821,18 +839,32 @@ re_compile_internal (regex_t *preg, const char * pattern, size_t length,
static reg_errcode_t
init_dfa (re_dfa_t *dfa, size_t pat_len)
{
- unsigned int table_size;
+ __re_size_t table_size;
#ifndef _LIBC
- char *codeset_name;
+ const char *codeset_name;
#endif
+#ifdef RE_ENABLE_I18N
+ size_t max_i18n_object_size = MAX (sizeof (wchar_t), sizeof (wctype_t));
+#else
+ size_t max_i18n_object_size = 0;
+#endif
+ size_t max_object_size =
+ MAX (sizeof (struct re_state_table_entry),
+ MAX (sizeof (re_token_t),
+ MAX (sizeof (re_node_set),
+ MAX (sizeof (regmatch_t),
+ max_i18n_object_size))));
memset (dfa, '\0', sizeof (re_dfa_t));
/* Force allocation of str_tree_storage the first time. */
dfa->str_tree_storage_idx = BIN_TREE_STORAGE_SIZE;
- /* Avoid overflows. */
- if (pat_len == SIZE_MAX)
+ /* Avoid overflows. The extra "/ 2" is for the table_size doubling
+ calculation below, and for similar doubling calculations
+ elsewhere. And it's <= rather than <, because some of the
+ doubling calculations add 1 afterwards. */
+ if (BE (MIN (IDX_MAX, SIZE_MAX / max_object_size) / 2 <= pat_len, 0))
return REG_ESPACE;
dfa->nodes_alloc = pat_len + 1;
@@ -854,22 +886,11 @@ init_dfa (re_dfa_t *dfa, size_t pat_len)
dfa->map_notascii = (_NL_CURRENT_WORD (LC_CTYPE, _NL_CTYPE_MAP_TO_NONASCII)
!= 0);
#else
-# ifdef HAVE_LANGINFO_CODESET
codeset_name = nl_langinfo (CODESET);
-# else
- codeset_name = getenv ("LC_ALL");
- if (codeset_name == NULL || codeset_name[0] == '\0')
- codeset_name = getenv ("LC_CTYPE");
- if (codeset_name == NULL || codeset_name[0] == '\0')
- codeset_name = getenv ("LANG");
- if (codeset_name == NULL)
- codeset_name = "";
- else if (strchr (codeset_name, '.') != NULL)
- codeset_name = strchr (codeset_name, '.') + 1;
-# endif
-
- if (strcasecmp (codeset_name, "UTF-8") == 0
- || strcasecmp (codeset_name, "UTF8") == 0)
+ if ((codeset_name[0] == 'U' || codeset_name[0] == 'u')
+ && (codeset_name[1] == 'T' || codeset_name[1] == 't')
+ && (codeset_name[2] == 'F' || codeset_name[2] == 'f')
+ && strcmp (codeset_name + 3 + (codeset_name[3] == '-'), "8") == 0)
dfa->is_utf8 = 1;
/* We check exhaustively in the loop below if this charset is a
@@ -916,34 +937,37 @@ init_dfa (re_dfa_t *dfa, size_t pat_len)
character used by some operators like "\<", "\>", etc. */
static void
-internal_function
init_word_char (re_dfa_t *dfa)
{
- dfa->word_ops_used = 1;
int i = 0;
+ int j;
int ch = 0;
+ dfa->word_ops_used = 1;
if (BE (dfa->map_notascii == 0, 1))
{
- if (sizeof (dfa->word_char[0]) == 8)
- {
- /* The extra temporaries here avoid "implicitly truncated"
- warnings in the case when this is dead code, i.e. 32-bit. */
- const uint64_t wc0 = UINT64_C (0x03ff000000000000);
- const uint64_t wc1 = UINT64_C (0x07fffffe87fffffe);
- dfa->word_char[0] = wc0;
- dfa->word_char[1] = wc1;
+ /* Avoid uint32_t and uint64_t as some non-GCC platforms lack
+ them, an issue when this code is used in Gnulib. */
+ bitset_word_t bits0 = 0x00000000;
+ bitset_word_t bits1 = 0x03ff0000;
+ bitset_word_t bits2 = 0x87fffffe;
+ bitset_word_t bits3 = 0x07fffffe;
+ if (BITSET_WORD_BITS == 64)
+ {
+ /* Pacify gcc -Woverflow on 32-bit platformns. */
+ dfa->word_char[0] = bits1 << 31 << 1 | bits0;
+ dfa->word_char[1] = bits3 << 31 << 1 | bits2;
i = 2;
}
- else if (sizeof (dfa->word_char[0]) == 4)
+ else if (BITSET_WORD_BITS == 32)
{
- dfa->word_char[0] = UINT32_C (0x00000000);
- dfa->word_char[1] = UINT32_C (0x03ff0000);
- dfa->word_char[2] = UINT32_C (0x87fffffe);
- dfa->word_char[3] = UINT32_C (0x07fffffe);
+ dfa->word_char[0] = bits0;
+ dfa->word_char[1] = bits1;
+ dfa->word_char[2] = bits2;
+ dfa->word_char[3] = bits3;
i = 4;
}
else
- abort ();
+ goto general_case;
ch = 128;
if (BE (dfa->is_utf8, 1))
@@ -953,8 +977,9 @@ init_word_char (re_dfa_t *dfa)
}
}
+ general_case:
for (; i < BITSET_WORDS; ++i)
- for (int j = 0; j < BITSET_WORD_BITS; ++j, ++ch)
+ for (j = 0; j < BITSET_WORD_BITS; ++j, ++ch)
if (isalnum (ch) || ch == '_')
dfa->word_char[i] |= (bitset_word_t) 1 << j;
}
@@ -964,7 +989,7 @@ init_word_char (re_dfa_t *dfa)
static void
free_workarea_compile (regex_t *preg)
{
- re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
+ re_dfa_t *dfa = preg->buffer;
bin_tree_storage_t *storage, *next;
for (storage = dfa->str_tree_storage; storage; storage = next)
{
@@ -983,7 +1008,7 @@ free_workarea_compile (regex_t *preg)
static reg_errcode_t
create_initial_state (re_dfa_t *dfa)
{
- int first, i;
+ Idx first, i;
reg_errcode_t err;
re_node_set init_nodes;
@@ -1002,10 +1027,10 @@ create_initial_state (re_dfa_t *dfa)
if (dfa->nbackref > 0)
for (i = 0; i < init_nodes.nelem; ++i)
{
- int node_idx = init_nodes.elems[i];
+ Idx node_idx = init_nodes.elems[i];
re_token_type_t type = dfa->nodes[node_idx].type;
- int clexp_idx;
+ Idx clexp_idx;
if (type != OP_BACK_REF)
continue;
for (clexp_idx = 0; clexp_idx < init_nodes.nelem; ++clexp_idx)
@@ -1021,14 +1046,13 @@ create_initial_state (re_dfa_t *dfa)
if (type == OP_BACK_REF)
{
- int dest_idx = dfa->edests[node_idx].elems[0];
+ Idx dest_idx = dfa->edests[node_idx].elems[0];
if (!re_node_set_contains (&init_nodes, dest_idx))
{
- reg_errcode_t err = re_node_set_merge (&init_nodes,
- dfa->eclosures
- + dest_idx);
- if (err != REG_NOERROR)
- return err;
+ reg_errcode_t merge_err
+ = re_node_set_merge (&init_nodes, dfa->eclosures + dest_idx);
+ if (merge_err != REG_NOERROR)
+ return merge_err;
i = 0;
}
}
@@ -1069,14 +1093,17 @@ create_initial_state (re_dfa_t *dfa)
static void
optimize_utf8 (re_dfa_t *dfa)
{
- int node, i, mb_chars = 0, has_period = 0;
+ Idx node;
+ int i;
+ bool mb_chars = false;
+ bool has_period = false;
for (node = 0; node < dfa->nodes_len; ++node)
switch (dfa->nodes[node].type)
{
case CHARACTER:
- if (dfa->nodes[node].opr.c >= 0x80)
- mb_chars = 1;
+ if (dfa->nodes[node].opr.c >= ASCII_CHARS)
+ mb_chars = true;
break;
case ANCHOR:
switch (dfa->nodes[node].opr.ctx_type)
@@ -1094,7 +1121,7 @@ optimize_utf8 (re_dfa_t *dfa)
}
break;
case OP_PERIOD:
- has_period = 1;
+ has_period = true;
break;
case OP_BACK_REF:
case OP_ALT:
@@ -1106,11 +1133,18 @@ optimize_utf8 (re_dfa_t *dfa)
case COMPLEX_BRACKET:
return;
case SIMPLE_BRACKET:
- /* Just double check. The non-ASCII range starts at 0x80. */
- assert (0x80 % BITSET_WORD_BITS == 0);
- for (i = 0x80 / BITSET_WORD_BITS; i < BITSET_WORDS; ++i)
- if (dfa->nodes[node].opr.sbcset[i])
- return;
+ /* Just double check. */
+ {
+ int rshift = (ASCII_CHARS % BITSET_WORD_BITS == 0
+ ? 0
+ : BITSET_WORD_BITS - ASCII_CHARS % BITSET_WORD_BITS);
+ for (i = ASCII_CHARS / BITSET_WORD_BITS; i < BITSET_WORDS; ++i)
+ {
+ if (dfa->nodes[node].opr.sbcset[i] >> rshift != 0)
+ return;
+ rshift = 0;
+ }
+ }
break;
default:
abort ();
@@ -1120,7 +1154,7 @@ optimize_utf8 (re_dfa_t *dfa)
for (node = 0; node < dfa->nodes_len; ++node)
{
if (dfa->nodes[node].type == CHARACTER
- && dfa->nodes[node].opr.c >= 0x80)
+ && dfa->nodes[node].opr.c >= ASCII_CHARS)
dfa->nodes[node].mb_partial = 0;
else if (dfa->nodes[node].type == OP_PERIOD)
dfa->nodes[node].type = OP_UTF8_PERIOD;
@@ -1139,22 +1173,22 @@ optimize_utf8 (re_dfa_t *dfa)
static reg_errcode_t
analyze (regex_t *preg)
{
- re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
+ re_dfa_t *dfa = preg->buffer;
reg_errcode_t ret;
/* Allocate arrays. */
- dfa->nexts = re_malloc (int, dfa->nodes_alloc);
- dfa->org_indices = re_malloc (int, dfa->nodes_alloc);
+ dfa->nexts = re_malloc (Idx, dfa->nodes_alloc);
+ dfa->org_indices = re_malloc (Idx, dfa->nodes_alloc);
dfa->edests = re_malloc (re_node_set, dfa->nodes_alloc);
dfa->eclosures = re_malloc (re_node_set, dfa->nodes_alloc);
if (BE (dfa->nexts == NULL || dfa->org_indices == NULL || dfa->edests == NULL
|| dfa->eclosures == NULL, 0))
return REG_ESPACE;
- dfa->subexp_map = re_malloc (int, preg->re_nsub);
+ dfa->subexp_map = re_malloc (Idx, preg->re_nsub);
if (dfa->subexp_map != NULL)
{
- int i;
+ Idx i;
for (i = 0; i < preg->re_nsub; i++)
dfa->subexp_map[i] = i;
preorder (dfa->str_tree, optimize_subexps, dfa);
@@ -1163,7 +1197,7 @@ analyze (regex_t *preg)
break;
if (i == preg->re_nsub)
{
- free (dfa->subexp_map);
+ re_free (dfa->subexp_map);
dfa->subexp_map = NULL;
}
}
@@ -1279,7 +1313,7 @@ optimize_subexps (void *extra, bin_tree_t *node)
else if (node->token.type == SUBEXP
&& node->left && node->left->token.type == SUBEXP)
{
- int other_idx = node->left->token.opr.idx;
+ Idx other_idx = node->left->token.opr.idx;
node->left = node->left->left;
if (node->left)
@@ -1287,7 +1321,7 @@ optimize_subexps (void *extra, bin_tree_t *node)
dfa->subexp_map[other_idx] = dfa->subexp_map[node->token.opr.idx];
if (other_idx < BITSET_WORD_BITS)
- dfa->used_bkref_map &= ~((bitset_word_t) 1 << other_idx);
+ dfa->used_bkref_map &= ~((bitset_word_t) 1 << other_idx);
}
return REG_NOERROR;
@@ -1320,7 +1354,7 @@ lower_subexps (void *extra, bin_tree_t *node)
static bin_tree_t *
lower_subexp (reg_errcode_t *err, regex_t *preg, bin_tree_t *node)
{
- re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
+ re_dfa_t *dfa = preg->buffer;
bin_tree_t *body = node->left;
bin_tree_t *op, *cls, *tree1, *tree;
@@ -1403,7 +1437,7 @@ static reg_errcode_t
link_nfa_nodes (void *extra, bin_tree_t *node)
{
re_dfa_t *dfa = (re_dfa_t *) extra;
- int idx = node->node_idx;
+ Idx idx = node->node_idx;
reg_errcode_t err = REG_NOERROR;
switch (node->token.type)
@@ -1418,7 +1452,7 @@ link_nfa_nodes (void *extra, bin_tree_t *node)
case OP_DUP_ASTERISK:
case OP_ALT:
{
- int left, right;
+ Idx left, right;
dfa->has_plural_match = 1;
if (node->left != NULL)
left = node->left->first->node_idx;
@@ -1460,15 +1494,15 @@ link_nfa_nodes (void *extra, bin_tree_t *node)
to their own constraint. */
static reg_errcode_t
-internal_function
-duplicate_node_closure (re_dfa_t *dfa, int top_org_node, int top_clone_node,
- int root_node, unsigned int init_constraint)
+duplicate_node_closure (re_dfa_t *dfa, Idx top_org_node, Idx top_clone_node,
+ Idx root_node, unsigned int init_constraint)
{
- int org_node, clone_node, ret;
+ Idx org_node, clone_node;
+ bool ok;
unsigned int constraint = init_constraint;
for (org_node = top_org_node, clone_node = top_clone_node;;)
{
- int org_dest, clone_dest;
+ Idx org_dest, clone_dest;
if (dfa->nodes[org_node].type == OP_BACK_REF)
{
/* If the back reference epsilon-transit, its destination must
@@ -1481,8 +1515,8 @@ duplicate_node_closure (re_dfa_t *dfa, int top_org_node, int top_clone_node,
if (BE (clone_dest == -1, 0))
return REG_ESPACE;
dfa->nexts[clone_node] = dfa->nexts[org_node];
- ret = re_node_set_insert (dfa->edests + clone_node, clone_dest);
- if (BE (ret < 0, 0))
+ ok = re_node_set_insert (dfa->edests + clone_node, clone_dest);
+ if (BE (! ok, 0))
return REG_ESPACE;
}
else if (dfa->edests[org_node].nelem == 0)
@@ -1500,12 +1534,12 @@ duplicate_node_closure (re_dfa_t *dfa, int top_org_node, int top_clone_node,
org_dest = dfa->edests[org_node].elems[0];
re_node_set_empty (dfa->edests + clone_node);
/* If the node is root_node itself, it means the epsilon closure
- has a loop. Then tie it to the destination of the root_node. */
+ has a loop. Then tie it to the destination of the root_node. */
if (org_node == root_node && clone_node != org_node)
{
- ret = re_node_set_insert (dfa->edests + clone_node, org_dest);
- if (BE (ret < 0, 0))
- return REG_ESPACE;
+ ok = re_node_set_insert (dfa->edests + clone_node, org_dest);
+ if (BE (! ok, 0))
+ return REG_ESPACE;
break;
}
/* In case the node has another constraint, append it. */
@@ -1513,8 +1547,8 @@ duplicate_node_closure (re_dfa_t *dfa, int top_org_node, int top_clone_node,
clone_dest = duplicate_node (dfa, org_dest, constraint);
if (BE (clone_dest == -1, 0))
return REG_ESPACE;
- ret = re_node_set_insert (dfa->edests + clone_node, clone_dest);
- if (BE (ret < 0, 0))
+ ok = re_node_set_insert (dfa->edests + clone_node, clone_dest);
+ if (BE (! ok, 0))
return REG_ESPACE;
}
else /* dfa->edests[org_node].nelem == 2 */
@@ -1532,8 +1566,8 @@ duplicate_node_closure (re_dfa_t *dfa, int top_org_node, int top_clone_node,
clone_dest = duplicate_node (dfa, org_dest, constraint);
if (BE (clone_dest == -1, 0))
return REG_ESPACE;
- ret = re_node_set_insert (dfa->edests + clone_node, clone_dest);
- if (BE (ret < 0, 0))
+ ok = re_node_set_insert (dfa->edests + clone_node, clone_dest);
+ if (BE (! ok, 0))
return REG_ESPACE;
err = duplicate_node_closure (dfa, org_dest, clone_dest,
root_node, constraint);
@@ -1544,8 +1578,8 @@ duplicate_node_closure (re_dfa_t *dfa, int top_org_node, int top_clone_node,
{
/* There is a duplicated node which satisfies the constraint,
use it to avoid infinite loop. */
- ret = re_node_set_insert (dfa->edests + clone_node, clone_dest);
- if (BE (ret < 0, 0))
+ ok = re_node_set_insert (dfa->edests + clone_node, clone_dest);
+ if (BE (! ok, 0))
return REG_ESPACE;
}
@@ -1553,8 +1587,8 @@ duplicate_node_closure (re_dfa_t *dfa, int top_org_node, int top_clone_node,
clone_dest = duplicate_node (dfa, org_dest, constraint);
if (BE (clone_dest == -1, 0))
return REG_ESPACE;
- ret = re_node_set_insert (dfa->edests + clone_node, clone_dest);
- if (BE (ret < 0, 0))
+ ok = re_node_set_insert (dfa->edests + clone_node, clone_dest);
+ if (BE (! ok, 0))
return REG_ESPACE;
}
org_node = org_dest;
@@ -1566,11 +1600,11 @@ duplicate_node_closure (re_dfa_t *dfa, int top_org_node, int top_clone_node,
/* Search for a node which is duplicated from the node ORG_NODE, and
satisfies the constraint CONSTRAINT. */
-static int
-search_duplicated_node (const re_dfa_t *dfa, int org_node,
+static Idx
+search_duplicated_node (const re_dfa_t *dfa, Idx org_node,
unsigned int constraint)
{
- int idx;
+ Idx idx;
for (idx = dfa->nodes_len - 1; dfa->nodes[idx].duplicated && idx > 0; --idx)
{
if (org_node == dfa->org_indices[idx]
@@ -1584,10 +1618,10 @@ search_duplicated_node (const re_dfa_t *dfa, int org_node,
Return the index of the new node, or -1 if insufficient storage is
available. */
-static int
-duplicate_node (re_dfa_t *dfa, int org_idx, unsigned int constraint)
+static Idx
+duplicate_node (re_dfa_t *dfa, Idx org_idx, unsigned int constraint)
{
- int dup_idx = re_dfa_add_node (dfa, dfa->nodes[org_idx]);
+ Idx dup_idx = re_dfa_add_node (dfa, dfa->nodes[org_idx]);
if (BE (dup_idx != -1, 1))
{
dfa->nodes[dup_idx].constraint = constraint;
@@ -1603,17 +1637,18 @@ duplicate_node (re_dfa_t *dfa, int org_idx, unsigned int constraint)
static reg_errcode_t
calc_inveclosure (re_dfa_t *dfa)
{
- int src, idx, ret;
+ Idx src, idx;
+ bool ok;
for (idx = 0; idx < dfa->nodes_len; ++idx)
re_node_set_init_empty (dfa->inveclosures + idx);
for (src = 0; src < dfa->nodes_len; ++src)
{
- int *elems = dfa->eclosures[src].elems;
+ Idx *elems = dfa->eclosures[src].elems;
for (idx = 0; idx < dfa->eclosures[src].nelem; ++idx)
{
- ret = re_node_set_insert_last (dfa->inveclosures + elems[idx], src);
- if (BE (ret == -1, 0))
+ ok = re_node_set_insert_last (dfa->inveclosures + elems[idx], src);
+ if (BE (! ok, 0))
return REG_ESPACE;
}
}
@@ -1626,11 +1661,12 @@ calc_inveclosure (re_dfa_t *dfa)
static reg_errcode_t
calc_eclosure (re_dfa_t *dfa)
{
- int node_idx, incomplete;
+ Idx node_idx;
+ bool incomplete;
#ifdef DEBUG
assert (dfa->nodes_len > 0);
#endif
- incomplete = 0;
+ incomplete = false;
/* For each nodes, calculate epsilon closure. */
for (node_idx = 0; ; ++node_idx)
{
@@ -1640,7 +1676,7 @@ calc_eclosure (re_dfa_t *dfa)
{
if (!incomplete)
break;
- incomplete = 0;
+ incomplete = false;
node_idx = 0;
}
@@ -1652,13 +1688,13 @@ calc_eclosure (re_dfa_t *dfa)
if (dfa->eclosures[node_idx].nelem != 0)
continue;
/* Calculate epsilon closure of 'node_idx'. */
- err = calc_eclosure_iter (&eclosure_elem, dfa, node_idx, 1);
+ err = calc_eclosure_iter (&eclosure_elem, dfa, node_idx, true);
if (BE (err != REG_NOERROR, 0))
return err;
if (dfa->eclosures[node_idx].nelem == 0)
{
- incomplete = 1;
+ incomplete = true;
re_node_set_free (&eclosure_elem);
}
}
@@ -1668,13 +1704,13 @@ calc_eclosure (re_dfa_t *dfa)
/* Calculate epsilon closure of NODE. */
static reg_errcode_t
-calc_eclosure_iter (re_node_set *new_set, re_dfa_t *dfa, int node, int root)
+calc_eclosure_iter (re_node_set *new_set, re_dfa_t *dfa, Idx node, bool root)
{
reg_errcode_t err;
- int i;
+ Idx i;
re_node_set eclosure;
- int ret;
- int incomplete = 0;
+ bool ok;
+ bool incomplete = false;
err = re_node_set_alloc (&eclosure, dfa->edests[node].nelem + 1);
if (BE (err != REG_NOERROR, 0))
return err;
@@ -1700,19 +1736,19 @@ calc_eclosure_iter (re_node_set *new_set, re_dfa_t *dfa, int node, int root)
for (i = 0; i < dfa->edests[node].nelem; ++i)
{
re_node_set eclosure_elem;
- int edest = dfa->edests[node].elems[i];
- /* If calculating the epsilon closure of `edest' is in progress,
+ Idx edest = dfa->edests[node].elems[i];
+ /* If calculating the epsilon closure of 'edest' is in progress,
return intermediate result. */
if (dfa->eclosures[edest].nelem == -1)
{
- incomplete = 1;
+ incomplete = true;
continue;
}
- /* If we haven't calculated the epsilon closure of `edest' yet,
+ /* If we haven't calculated the epsilon closure of 'edest' yet,
calculate now. Otherwise use calculated epsilon closure. */
if (dfa->eclosures[edest].nelem == 0)
{
- err = calc_eclosure_iter (&eclosure_elem, dfa, edest, 0);
+ err = calc_eclosure_iter (&eclosure_elem, dfa, edest, false);
if (BE (err != REG_NOERROR, 0))
return err;
}
@@ -1726,14 +1762,14 @@ calc_eclosure_iter (re_node_set *new_set, re_dfa_t *dfa, int node, int root)
the epsilon closure of this node is also incomplete. */
if (dfa->eclosures[edest].nelem == 0)
{
- incomplete = 1;
+ incomplete = true;
re_node_set_free (&eclosure_elem);
}
}
/* An epsilon closure includes itself. */
- ret = re_node_set_insert (&eclosure, node);
- if (BE (ret < 0, 0))
+ ok = re_node_set_insert (&eclosure, node);
+ if (BE (! ok, 0))
return REG_ESPACE;
if (incomplete && !root)
dfa->eclosures[node].nelem = 0;
@@ -1749,7 +1785,6 @@ calc_eclosure_iter (re_node_set *new_set, re_dfa_t *dfa, int node, int root)
We must not use this function inside bracket expressions. */
static void
-internal_function
fetch_token (re_token_t *result, re_string_t *input, reg_syntax_t syntax)
{
re_string_skip_bytes (input, peek_token (result, input, syntax));
@@ -1759,7 +1794,6 @@ fetch_token (re_token_t *result, re_string_t *input, reg_syntax_t syntax)
We must not use this function inside bracket expressions. */
static int
-internal_function
peek_token (re_token_t *token, re_string_t *input, reg_syntax_t syntax)
{
unsigned char c;
@@ -1998,7 +2032,6 @@ peek_token (re_token_t *token, re_string_t *input, reg_syntax_t syntax)
We must not use this function out of bracket expressions. */
static int
-internal_function
peek_token_bracket (re_token_t *token, re_string_t *input, reg_syntax_t syntax)
{
unsigned char c;
@@ -2045,16 +2078,18 @@ peek_token_bracket (re_token_t *token, re_string_t *input, reg_syntax_t syntax)
case '.':
token->type = OP_OPEN_COLL_ELEM;
break;
+
case '=':
token->type = OP_OPEN_EQUIV_CLASS;
break;
+
case ':':
if (syntax & RE_CHAR_CLASSES)
{
token->type = OP_OPEN_CHAR_CLASS;
break;
}
- /* else fall through. */
+ FALLTHROUGH;
default:
token->type = CHARACTER;
token->opr.c = c;
@@ -2098,7 +2133,7 @@ static bin_tree_t *
parse (re_string_t *regexp, regex_t *preg, reg_syntax_t syntax,
reg_errcode_t *err)
{
- re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
+ re_dfa_t *dfa = preg->buffer;
bin_tree_t *tree, *eor, *root;
re_token_t current_token;
dfa->syntax = syntax;
@@ -2130,10 +2165,11 @@ parse (re_string_t *regexp, regex_t *preg, reg_syntax_t syntax,
static bin_tree_t *
parse_reg_exp (re_string_t *regexp, regex_t *preg, re_token_t *token,
- reg_syntax_t syntax, int nest, reg_errcode_t *err)
+ reg_syntax_t syntax, Idx nest, reg_errcode_t *err)
{
- re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
+ re_dfa_t *dfa = preg->buffer;
bin_tree_t *tree, *branch = NULL;
+ bitset_word_t initial_bkref_map = dfa->completed_bkref_map;
tree = parse_branch (regexp, preg, token, syntax, nest, err);
if (BE (*err != REG_NOERROR && tree == NULL, 0))
return NULL;
@@ -2144,6 +2180,8 @@ parse_reg_exp (re_string_t *regexp, regex_t *preg, re_token_t *token,
if (token->type != OP_ALT && token->type != END_OF_RE
&& (nest == 0 || token->type != OP_CLOSE_SUBEXP))
{
+ bitset_word_t accumulated_bkref_map = dfa->completed_bkref_map;
+ dfa->completed_bkref_map = initial_bkref_map;
branch = parse_branch (regexp, preg, token, syntax, nest, err);
if (BE (*err != REG_NOERROR && branch == NULL, 0))
{
@@ -2151,6 +2189,7 @@ parse_reg_exp (re_string_t *regexp, regex_t *preg, re_token_t *token,
postorder (tree, free_tree, NULL);
return NULL;
}
+ dfa->completed_bkref_map |= accumulated_bkref_map;
}
else
branch = NULL;
@@ -2175,10 +2214,10 @@ parse_reg_exp (re_string_t *regexp, regex_t *preg, re_token_t *token,
static bin_tree_t *
parse_branch (re_string_t *regexp, regex_t *preg, re_token_t *token,
- reg_syntax_t syntax, int nest, reg_errcode_t *err)
+ reg_syntax_t syntax, Idx nest, reg_errcode_t *err)
{
- bin_tree_t *tree, *exp;
- re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
+ bin_tree_t *tree, *expr;
+ re_dfa_t *dfa = preg->buffer;
tree = parse_expression (regexp, preg, token, syntax, nest, err);
if (BE (*err != REG_NOERROR && tree == NULL, 0))
return NULL;
@@ -2186,19 +2225,19 @@ parse_branch (re_string_t *regexp, regex_t *preg, re_token_t *token,
while (token->type != OP_ALT && token->type != END_OF_RE
&& (nest == 0 || token->type != OP_CLOSE_SUBEXP))
{
- exp = parse_expression (regexp, preg, token, syntax, nest, err);
- if (BE (*err != REG_NOERROR && exp == NULL, 0))
+ expr = parse_expression (regexp, preg, token, syntax, nest, err);
+ if (BE (*err != REG_NOERROR && expr == NULL, 0))
{
if (tree != NULL)
postorder (tree, free_tree, NULL);
return NULL;
}
- if (tree != NULL && exp != NULL)
+ if (tree != NULL && expr != NULL)
{
- bin_tree_t *newtree = create_tree (dfa, tree, exp, CONCAT);
+ bin_tree_t *newtree = create_tree (dfa, tree, expr, CONCAT);
if (newtree == NULL)
{
- postorder (exp, free_tree, NULL);
+ postorder (expr, free_tree, NULL);
postorder (tree, free_tree, NULL);
*err = REG_ESPACE;
return NULL;
@@ -2206,8 +2245,8 @@ parse_branch (re_string_t *regexp, regex_t *preg, re_token_t *token,
tree = newtree;
}
else if (tree == NULL)
- tree = exp;
- /* Otherwise exp == NULL, we don't need to create new tree. */
+ tree = expr;
+ /* Otherwise expr == NULL, we don't need to create new tree. */
}
return tree;
}
@@ -2220,9 +2259,9 @@ parse_branch (re_string_t *regexp, regex_t *preg, re_token_t *token,
static bin_tree_t *
parse_expression (re_string_t *regexp, regex_t *preg, re_token_t *token,
- reg_syntax_t syntax, int nest, reg_errcode_t *err)
+ reg_syntax_t syntax, Idx nest, reg_errcode_t *err)
{
- re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
+ re_dfa_t *dfa = preg->buffer;
bin_tree_t *tree;
switch (token->type)
{
@@ -2252,16 +2291,19 @@ parse_expression (re_string_t *regexp, regex_t *preg, re_token_t *token,
}
#endif
break;
+
case OP_OPEN_SUBEXP:
tree = parse_sub_exp (regexp, preg, token, syntax, nest + 1, err);
if (BE (*err != REG_NOERROR && tree == NULL, 0))
return NULL;
break;
+
case OP_OPEN_BRACKET:
tree = parse_bracket_exp (regexp, dfa, token, syntax, err);
if (BE (*err != REG_NOERROR && tree == NULL, 0))
return NULL;
break;
+
case OP_BACK_REF:
if (!BE (dfa->completed_bkref_map & (1 << token->opr.idx), 1))
{
@@ -2278,13 +2320,14 @@ parse_expression (re_string_t *regexp, regex_t *preg, re_token_t *token,
++dfa->nbackref;
dfa->has_mb_node = 1;
break;
+
case OP_OPEN_DUP_NUM:
if (syntax & RE_CONTEXT_INVALID_DUP)
{
*err = REG_BADRPT;
return NULL;
}
- /* FALLTHROUGH */
+ FALLTHROUGH;
case OP_DUP_ASTERISK:
case OP_DUP_PLUS:
case OP_DUP_QUESTION:
@@ -2298,7 +2341,7 @@ parse_expression (re_string_t *regexp, regex_t *preg, re_token_t *token,
fetch_token (token, regexp, syntax);
return parse_expression (regexp, preg, token, syntax, nest, err);
}
- /* else fall through */
+ FALLTHROUGH;
case OP_CLOSE_SUBEXP:
if ((token->type == OP_CLOSE_SUBEXP) &&
!(syntax & RE_UNMATCHED_RIGHT_PAREN_ORD))
@@ -2306,7 +2349,7 @@ parse_expression (re_string_t *regexp, regex_t *preg, re_token_t *token,
*err = REG_ERPAREN;
return NULL;
}
- /* else fall through */
+ FALLTHROUGH;
case OP_CLOSE_DUP_NUM:
/* We treat it as a normal character. */
@@ -2321,6 +2364,7 @@ parse_expression (re_string_t *regexp, regex_t *preg, re_token_t *token,
return NULL;
}
break;
+
case ANCHOR:
if ((token->opr.ctx_type
& (WORD_DELIM | NOT_WORD_DELIM | WORD_FIRST | WORD_LAST))
@@ -2365,6 +2409,7 @@ parse_expression (re_string_t *regexp, regex_t *preg, re_token_t *token,
it must not be "<ANCHOR(^)><REPEAT(*)>". */
fetch_token (token, regexp, syntax);
return tree;
+
case OP_PERIOD:
tree = create_token_tree (dfa, NULL, NULL, token);
if (BE (tree == NULL, 0))
@@ -2375,30 +2420,35 @@ parse_expression (re_string_t *regexp, regex_t *preg, re_token_t *token,
if (dfa->mb_cur_max > 1)
dfa->has_mb_node = 1;
break;
+
case OP_WORD:
case OP_NOTWORD:
tree = build_charclass_op (dfa, regexp->trans,
- (const unsigned char *) "alnum",
- (const unsigned char *) "_",
+ "alnum",
+ "_",
token->type == OP_NOTWORD, err);
if (BE (*err != REG_NOERROR && tree == NULL, 0))
return NULL;
break;
+
case OP_SPACE:
case OP_NOTSPACE:
tree = build_charclass_op (dfa, regexp->trans,
- (const unsigned char *) "space",
- (const unsigned char *) "",
+ "space",
+ "",
token->type == OP_NOTSPACE, err);
if (BE (*err != REG_NOERROR && tree == NULL, 0))
return NULL;
break;
+
case OP_ALT:
case END_OF_RE:
return NULL;
+
case BACK_SLASH:
*err = REG_EESCAPE;
return NULL;
+
default:
/* Must not happen? */
#ifdef DEBUG
@@ -2411,7 +2461,8 @@ parse_expression (re_string_t *regexp, regex_t *preg, re_token_t *token,
while (token->type == OP_DUP_ASTERISK || token->type == OP_DUP_PLUS
|| token->type == OP_DUP_QUESTION || token->type == OP_OPEN_DUP_NUM)
{
- bin_tree_t *dup_tree = parse_dup_op (tree, regexp, dfa, token, syntax, err);
+ bin_tree_t *dup_tree = parse_dup_op (tree, regexp, dfa, token,
+ syntax, err);
if (BE (*err != REG_NOERROR && dup_tree == NULL, 0))
{
if (tree != NULL)
@@ -2443,9 +2494,9 @@ parse_expression (re_string_t *regexp, regex_t *preg, re_token_t *token,
static bin_tree_t *
parse_sub_exp (re_string_t *regexp, regex_t *preg, re_token_t *token,
- reg_syntax_t syntax, int nest, reg_errcode_t *err)
+ reg_syntax_t syntax, Idx nest, reg_errcode_t *err)
{
- re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
+ re_dfa_t *dfa = preg->buffer;
bin_tree_t *tree;
size_t cur_nsub;
cur_nsub = preg->re_nsub++;
@@ -2488,7 +2539,7 @@ parse_dup_op (bin_tree_t *elem, re_string_t *regexp, re_dfa_t *dfa,
re_token_t *token, reg_syntax_t syntax, reg_errcode_t *err)
{
bin_tree_t *tree = NULL, *old_tree = NULL;
- int i, start, end, start_idx = re_string_cur_idx (regexp);
+ Idx i, start, end, start_idx = re_string_cur_idx (regexp);
re_token_t start_token = *token;
if (token->type == OP_OPEN_DUP_NUM)
@@ -2534,12 +2585,19 @@ parse_dup_op (bin_tree_t *elem, re_string_t *regexp, re_dfa_t *dfa,
return elem;
}
- if (BE ((end != -1 && start > end) || token->type != OP_CLOSE_DUP_NUM, 0))
+ if (BE ((end != -1 && start > end)
+ || token->type != OP_CLOSE_DUP_NUM, 0))
{
/* First number greater than second. */
*err = REG_BADBR;
return NULL;
}
+
+ if (BE (RE_DUP_MAX < (end == -1 ? start : end), 0))
+ {
+ *err = REG_ESIZE;
+ return NULL;
+ }
}
else
{
@@ -2582,26 +2640,31 @@ parse_dup_op (bin_tree_t *elem, re_string_t *regexp, re_dfa_t *dfa,
old_tree = NULL;
if (elem->token.type == SUBEXP)
- postorder (elem, mark_opt_subexp, (void *) (long) elem->token.opr.idx);
+ {
+ uintptr_t subidx = elem->token.opr.idx;
+ postorder (elem, mark_opt_subexp, (void *) subidx);
+ }
- tree = create_tree (dfa, elem, NULL, (end == -1 ? OP_DUP_ASTERISK : OP_ALT));
+ tree = create_tree (dfa, elem, NULL,
+ (end == -1 ? OP_DUP_ASTERISK : OP_ALT));
if (BE (tree == NULL, 0))
goto parse_dup_op_espace;
/* This loop is actually executed only when end != -1,
to rewrite <re>{0,n} as (<re>(<re>...<re>?)?)?... We have
already created the start+1-th copy. */
- for (i = start + 2; i <= end; ++i)
- {
- elem = duplicate_tree (elem, dfa);
- tree = create_tree (dfa, tree, elem, CONCAT);
- if (BE (elem == NULL || tree == NULL, 0))
- goto parse_dup_op_espace;
-
- tree = create_tree (dfa, tree, NULL, OP_ALT);
- if (BE (tree == NULL, 0))
- goto parse_dup_op_espace;
- }
+ if (TYPE_SIGNED (Idx) || end != -1)
+ for (i = start + 2; i <= end; ++i)
+ {
+ elem = duplicate_tree (elem, dfa);
+ tree = create_tree (dfa, tree, elem, CONCAT);
+ if (BE (elem == NULL || tree == NULL, 0))
+ goto parse_dup_op_espace;
+
+ tree = create_tree (dfa, tree, NULL, OP_ALT);
+ if (BE (tree == NULL, 0))
+ goto parse_dup_op_espace;
+ }
if (old_tree)
tree = create_tree (dfa, old_tree, tree, CONCAT);
@@ -2618,6 +2681,19 @@ parse_dup_op (bin_tree_t *elem, re_string_t *regexp, re_dfa_t *dfa,
#define BRACKET_NAME_BUF_SIZE 32
#ifndef _LIBC
+
+# ifdef RE_ENABLE_I18N
+/* Convert the byte B to the corresponding wide character. In a
+ unibyte locale, treat B as itself if it is an encoding error.
+ In a multibyte locale, return WEOF if B is an encoding error. */
+static wint_t
+parse_byte (unsigned char b, re_charset_t *mbcset)
+{
+ wint_t wc = __btowc (b);
+ return wc == WEOF && !mbcset ? b : wc;
+}
+#endif
+
/* Local function for parse_bracket_exp only used in case of NOT _LIBC.
Build the range expression which starts from START_ELEM, and ends
at END_ELEM. The result are written to MBCSET and SBCSET.
@@ -2626,13 +2702,18 @@ parse_dup_op (bin_tree_t *elem, re_string_t *regexp, re_dfa_t *dfa,
update it. */
static reg_errcode_t
-internal_function
# ifdef RE_ENABLE_I18N
-build_range_exp (bitset_t sbcset, re_charset_t *mbcset, int *range_alloc,
- bracket_elem_t *start_elem, bracket_elem_t *end_elem)
+build_range_exp (const reg_syntax_t syntax,
+ bitset_t sbcset,
+ re_charset_t *mbcset,
+ Idx *range_alloc,
+ const bracket_elem_t *start_elem,
+ const bracket_elem_t *end_elem)
# else /* not RE_ENABLE_I18N */
-build_range_exp (bitset_t sbcset, bracket_elem_t *start_elem,
- bracket_elem_t *end_elem)
+build_range_exp (const reg_syntax_t syntax,
+ bitset_t sbcset,
+ const bracket_elem_t *start_elem,
+ const bracket_elem_t *end_elem)
# endif /* not RE_ENABLE_I18N */
{
unsigned int start_ch, end_ch;
@@ -2655,7 +2736,6 @@ build_range_exp (bitset_t sbcset, bracket_elem_t *start_elem,
wchar_t wc;
wint_t start_wc;
wint_t end_wc;
- wchar_t cmp_buf[6] = {L'\0', L'\0', L'\0', L'\0', L'\0', L'\0'};
start_ch = ((start_elem->type == SB_CHAR) ? start_elem->opr.ch
: ((start_elem->type == COLL_SYM) ? start_elem->opr.name[0]
@@ -2664,14 +2744,12 @@ build_range_exp (bitset_t sbcset, bracket_elem_t *start_elem,
: ((end_elem->type == COLL_SYM) ? end_elem->opr.name[0]
: 0));
start_wc = ((start_elem->type == SB_CHAR || start_elem->type == COLL_SYM)
- ? __btowc (start_ch) : start_elem->opr.wch);
+ ? parse_byte (start_ch, mbcset) : start_elem->opr.wch);
end_wc = ((end_elem->type == SB_CHAR || end_elem->type == COLL_SYM)
- ? __btowc (end_ch) : end_elem->opr.wch);
+ ? parse_byte (end_ch, mbcset) : end_elem->opr.wch);
if (start_wc == WEOF || end_wc == WEOF)
return REG_ECOLLATE;
- cmp_buf[0] = start_wc;
- cmp_buf[4] = end_wc;
- if (__wcscoll (cmp_buf, cmp_buf + 4) > 0)
+ else if (BE ((syntax & RE_NO_EMPTY_RANGES) && start_wc > end_wc, 0))
return REG_ERANGE;
/* Got valid collation sequence values, add them as a new entry.
@@ -2686,7 +2764,7 @@ build_range_exp (bitset_t sbcset, bracket_elem_t *start_elem,
{
/* There is not enough space, need realloc. */
wchar_t *new_array_start, *new_array_end;
- int new_nranges;
+ Idx new_nranges;
/* +1 in case of mbcset->nranges is 0. */
new_nranges = 2 * mbcset->nranges + 1;
@@ -2698,7 +2776,11 @@ build_range_exp (bitset_t sbcset, bracket_elem_t *start_elem,
new_nranges);
if (BE (new_array_start == NULL || new_array_end == NULL, 0))
- return REG_ESPACE;
+ {
+ re_free (new_array_start);
+ re_free (new_array_end);
+ return REG_ESPACE;
+ }
mbcset->range_starts = new_array_start;
mbcset->range_ends = new_array_end;
@@ -2712,9 +2794,7 @@ build_range_exp (bitset_t sbcset, bracket_elem_t *start_elem,
/* Build the table for single byte characters. */
for (wc = 0; wc < SBC_MAX; ++wc)
{
- cmp_buf[2] = wc;
- if (__wcscoll (cmp_buf, cmp_buf + 2) <= 0
- && __wcscoll (cmp_buf + 2, cmp_buf + 4) <= 0)
+ if (start_wc <= wc && wc <= end_wc)
bitset_set (sbcset, wc);
}
}
@@ -2747,10 +2827,9 @@ build_range_exp (bitset_t sbcset, bracket_elem_t *start_elem,
pointer argument since we may update it. */
static reg_errcode_t
-internal_function
# ifdef RE_ENABLE_I18N
build_collating_symbol (bitset_t sbcset, re_charset_t *mbcset,
- int *coll_sym_alloc, const unsigned char *name)
+ Idx *coll_sym_alloc, const unsigned char *name)
# else /* not RE_ENABLE_I18N */
build_collating_symbol (bitset_t sbcset, const unsigned char *name)
# endif /* not RE_ENABLE_I18N */
@@ -2896,6 +2975,7 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token,
0))
return REG_ERANGE;
+ /* FIXME: Implement rational ranges here, too. */
start_collseq = lookup_collation_sequence_value (start_elem);
end_collseq = lookup_collation_sequence_value (end_elem);
/* Check start/end collation sequence values. */
@@ -2916,7 +2996,7 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token,
/* There is not enough space, need realloc. */
uint32_t *new_array_start;
uint32_t *new_array_end;
- int new_nranges;
+ Idx new_nranges;
/* +1 in case of mbcset->nranges is 0. */
new_nranges = 2 * mbcset->nranges + 1;
@@ -2963,7 +3043,7 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token,
auto inline reg_errcode_t
__attribute__ ((always_inline))
build_collating_symbol (bitset_t sbcset, re_charset_t *mbcset,
- int *coll_sym_alloc, const unsigned char *name)
+ Idx *coll_sym_alloc, const unsigned char *name)
{
int32_t elem, idx;
size_t name_len = strlen ((const char *) name);
@@ -2993,7 +3073,7 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token,
{
/* Not enough, realloc it. */
/* +1 in case of mbcset->ncoll_syms is 0. */
- int new_coll_sym_alloc = 2 * mbcset->ncoll_syms + 1;
+ Idx new_coll_sym_alloc = 2 * mbcset->ncoll_syms + 1;
/* Use realloc since mbcset->coll_syms is NULL
if *alloc == 0. */
int32_t *new_coll_syms = re_realloc (mbcset->coll_syms, int32_t,
@@ -3023,13 +3103,13 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token,
re_bitset_ptr_t sbcset;
#ifdef RE_ENABLE_I18N
re_charset_t *mbcset;
- int coll_sym_alloc = 0, range_alloc = 0, mbchar_alloc = 0;
- int equiv_class_alloc = 0, char_class_alloc = 0;
+ Idx coll_sym_alloc = 0, range_alloc = 0, mbchar_alloc = 0;
+ Idx equiv_class_alloc = 0, char_class_alloc = 0;
#endif /* not RE_ENABLE_I18N */
- int non_match = 0;
+ bool non_match = false;
bin_tree_t *work_tree;
int token_len;
- int first_round = 1;
+ bool first_round = true;
#ifdef _LIBC
collseqmb = (const unsigned char *)
_NL_CURRENT (LC_COLLATE, _NL_COLLATE_COLLSEQMB);
@@ -3076,7 +3156,7 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token,
#ifdef RE_ENABLE_I18N
mbcset->non_match = 1;
#endif /* not RE_ENABLE_I18N */
- non_match = 1;
+ non_match = true;
if (syntax & RE_HAT_LISTS_NOT_NEWLINE)
bitset_set (sbcset, '\n');
re_string_skip_bytes (regexp, token_len); /* Skip a token. */
@@ -3098,7 +3178,8 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token,
unsigned char start_name_buf[BRACKET_NAME_BUF_SIZE];
unsigned char end_name_buf[BRACKET_NAME_BUF_SIZE];
reg_errcode_t ret;
- int token_len2 = 0, is_range_exp = 0;
+ int token_len2 = 0;
+ bool is_range_exp = false;
re_token_t token2;
start_elem.opr.name = start_name_buf;
@@ -3110,7 +3191,7 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token,
*err = ret;
goto parse_bracket_exp_free_return;
}
- first_round = 0;
+ first_round = false;
/* Get information about the next token. We need it in any case. */
token_len = peek_token_bracket (token, regexp, syntax);
@@ -3139,16 +3220,16 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token,
token->type = CHARACTER;
}
else
- is_range_exp = 1;
+ is_range_exp = true;
}
}
- if (is_range_exp == 1)
+ if (is_range_exp == true)
{
end_elem.opr.name = end_name_buf;
end_elem.type = COLL_SYM;
ret = parse_bracket_element (&end_elem, regexp, &token2, token_len2,
- dfa, syntax, 1);
+ dfa, syntax, true);
if (BE (ret != REG_NOERROR, 0))
{
*err = ret;
@@ -3162,11 +3243,11 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token,
&start_elem, &end_elem);
#else
# ifdef RE_ENABLE_I18N
- *err = build_range_exp (sbcset,
+ *err = build_range_exp (syntax, sbcset,
dfa->mb_cur_max > 1 ? mbcset : NULL,
&range_alloc, &start_elem, &end_elem);
# else
- *err = build_range_exp (sbcset, &start_elem, &end_elem);
+ *err = build_range_exp (syntax, sbcset, &start_elem, &end_elem);
# endif
#endif /* RE_ENABLE_I18N */
if (BE (*err != REG_NOERROR, 0))
@@ -3221,7 +3302,8 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token,
#ifdef RE_ENABLE_I18N
mbcset, &char_class_alloc,
#endif /* RE_ENABLE_I18N */
- start_elem.opr.name, syntax);
+ (const char *) start_elem.opr.name,
+ syntax);
if (BE (*err != REG_NOERROR, 0))
goto parse_bracket_exp_free_return;
break;
@@ -3318,7 +3400,7 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token,
static reg_errcode_t
parse_bracket_element (bracket_elem_t *elem, re_string_t *regexp,
re_token_t *token, int token_len, re_dfa_t *dfa,
- reg_syntax_t syntax, int accept_hyphen)
+ reg_syntax_t syntax, bool accept_hyphen)
{
#ifdef RE_ENABLE_I18N
int cur_char_size;
@@ -3405,7 +3487,7 @@ parse_bracket_symbol (bracket_elem_t *elem, re_string_t *regexp,
static reg_errcode_t
#ifdef RE_ENABLE_I18N
build_equiv_class (bitset_t sbcset, re_charset_t *mbcset,
- int *equiv_class_alloc, const unsigned char *name)
+ Idx *equiv_class_alloc, const unsigned char *name)
#else /* not RE_ENABLE_I18N */
build_equiv_class (bitset_t sbcset, const unsigned char *name)
#endif /* not RE_ENABLE_I18N */
@@ -3434,7 +3516,7 @@ build_equiv_class (bitset_t sbcset, const unsigned char *name)
/* This isn't a valid character. */
return REG_ECOLLATE;
- /* Build single byte matcing table for this equivalence class. */
+ /* Build single byte matching table for this equivalence class. */
len = weights[idx1 & 0xffffff];
for (ch = 0; ch < SBC_MAX; ++ch)
{
@@ -3449,25 +3531,17 @@ build_equiv_class (bitset_t sbcset, const unsigned char *name)
continue;
/* Compare only if the length matches and the collation rule
index is the same. */
- if (len == weights[idx2 & 0xffffff] && (idx1 >> 24) == (idx2 >> 24))
- {
- int cnt = 0;
-
- while (cnt <= len &&
- weights[(idx1 & 0xffffff) + 1 + cnt]
- == weights[(idx2 & 0xffffff) + 1 + cnt])
- ++cnt;
-
- if (cnt > len)
- bitset_set (sbcset, ch);
- }
+ if (len == weights[idx2 & 0xffffff] && (idx1 >> 24) == (idx2 >> 24)
+ && memcmp (weights + (idx1 & 0xffffff) + 1,
+ weights + (idx2 & 0xffffff) + 1, len) == 0)
+ bitset_set (sbcset, ch);
}
/* Check whether the array has enough space. */
if (BE (*equiv_class_alloc == mbcset->nequiv_classes, 0))
{
/* Not enough, realloc it. */
/* +1 in case of mbcset->nequiv_classes is 0. */
- int new_equiv_class_alloc = 2 * mbcset->nequiv_classes + 1;
+ Idx new_equiv_class_alloc = 2 * mbcset->nequiv_classes + 1;
/* Use realloc since the array is NULL if *alloc == 0. */
int32_t *new_equiv_classes = re_realloc (mbcset->equiv_classes,
int32_t,
@@ -3498,15 +3572,15 @@ build_equiv_class (bitset_t sbcset, const unsigned char *name)
static reg_errcode_t
#ifdef RE_ENABLE_I18N
build_charclass (RE_TRANSLATE_TYPE trans, bitset_t sbcset,
- re_charset_t *mbcset, int *char_class_alloc,
- const unsigned char *class_name, reg_syntax_t syntax)
+ re_charset_t *mbcset, Idx *char_class_alloc,
+ const char *class_name, reg_syntax_t syntax)
#else /* not RE_ENABLE_I18N */
build_charclass (RE_TRANSLATE_TYPE trans, bitset_t sbcset,
- const unsigned char *class_name, reg_syntax_t syntax)
+ const char *class_name, reg_syntax_t syntax)
#endif /* not RE_ENABLE_I18N */
{
int i;
- const char *name = (const char *) class_name;
+ const char *name = class_name;
/* In case of REG_ICASE "upper" and "lower" match the both of
upper and lower cases. */
@@ -3520,7 +3594,7 @@ build_charclass (RE_TRANSLATE_TYPE trans, bitset_t sbcset,
{
/* Not enough, realloc it. */
/* +1 in case of mbcset->nchar_classes is 0. */
- int new_char_class_alloc = 2 * mbcset->nchar_classes + 1;
+ Idx new_char_class_alloc = 2 * mbcset->nchar_classes + 1;
/* Use realloc since array is NULL if *alloc == 0. */
wctype_t *new_char_classes = re_realloc (mbcset->char_classes, wctype_t,
new_char_class_alloc);
@@ -3537,13 +3611,13 @@ build_charclass (RE_TRANSLATE_TYPE trans, bitset_t sbcset,
if (BE (trans != NULL, 0)) \
{ \
for (i = 0; i < SBC_MAX; ++i) \
- if (ctype_func (i)) \
+ if (ctype_func (i)) \
bitset_set (sbcset, trans[i]); \
} \
else \
{ \
for (i = 0; i < SBC_MAX; ++i) \
- if (ctype_func (i)) \
+ if (ctype_func (i)) \
bitset_set (sbcset, i); \
} \
} while (0)
@@ -3580,40 +3654,35 @@ build_charclass (RE_TRANSLATE_TYPE trans, bitset_t sbcset,
static bin_tree_t *
build_charclass_op (re_dfa_t *dfa, RE_TRANSLATE_TYPE trans,
- const unsigned char *class_name,
- const unsigned char *extra, int non_match,
+ const char *class_name,
+ const char *extra, bool non_match,
reg_errcode_t *err)
{
re_bitset_ptr_t sbcset;
#ifdef RE_ENABLE_I18N
re_charset_t *mbcset;
- int alloc = 0;
+ Idx alloc = 0;
#endif /* not RE_ENABLE_I18N */
reg_errcode_t ret;
re_token_t br_token;
bin_tree_t *tree;
sbcset = (re_bitset_ptr_t) calloc (sizeof (bitset_t), 1);
-#ifdef RE_ENABLE_I18N
- mbcset = (re_charset_t *) calloc (sizeof (re_charset_t), 1);
-#endif /* RE_ENABLE_I18N */
-
-#ifdef RE_ENABLE_I18N
- if (BE (sbcset == NULL || mbcset == NULL, 0))
-#else /* not RE_ENABLE_I18N */
if (BE (sbcset == NULL, 0))
-#endif /* not RE_ENABLE_I18N */
{
*err = REG_ESPACE;
return NULL;
}
-
- if (non_match)
- {
#ifdef RE_ENABLE_I18N
- mbcset->non_match = 1;
-#endif /* not RE_ENABLE_I18N */
+ mbcset = (re_charset_t *) calloc (sizeof (re_charset_t), 1);
+ if (BE (mbcset == NULL, 0))
+ {
+ re_free (sbcset);
+ *err = REG_ESPACE;
+ return NULL;
}
+ mbcset->non_match = non_match;
+#endif /* RE_ENABLE_I18N */
/* We don't care the syntax in this case. */
ret = build_charclass (trans, sbcset,
@@ -3646,6 +3715,9 @@ build_charclass_op (re_dfa_t *dfa, RE_TRANSLATE_TYPE trans,
#endif
/* Build a tree for simple bracket. */
+#if defined GCC_LINT || defined lint
+ memset (&br_token, 0, sizeof br_token);
+#endif
br_token.type = SIMPLE_BRACKET;
br_token.opr.sbcset = sbcset;
tree = create_token_tree (dfa, NULL, NULL, &br_token);
@@ -3687,14 +3759,15 @@ build_charclass_op (re_dfa_t *dfa, RE_TRANSLATE_TYPE trans,
}
/* This is intended for the expressions like "a{1,3}".
- Fetch a number from `input', and return the number.
- Return -1, if the number field is empty like "{,1}".
- Return -2, If an error is occured. */
+ Fetch a number from 'input', and return the number.
+ Return -1 if the number field is empty like "{,1}".
+ Return RE_DUP_MAX + 1 if the number field is too large.
+ Return -2 if an error occurred. */
-static int
+static Idx
fetch_number (re_string_t *input, re_token_t *token, reg_syntax_t syntax)
{
- int num = -1;
+ Idx num = -1;
unsigned char c;
while (1)
{
@@ -3705,8 +3778,10 @@ fetch_number (re_string_t *input, re_token_t *token, reg_syntax_t syntax)
if (token->type == OP_CLOSE_DUP_NUM || c == ',')
break;
num = ((token->type != CHARACTER || c < '0' || '9' < c || num == -2)
- ? -2 : ((num == -1) ? c - '0' : num * 10 + c - '0'));
- num = (num > RE_DUP_MAX) ? -2 : num;
+ ? -2
+ : num == -1
+ ? c - '0'
+ : MIN (RE_DUP_MAX + 1, num * 10 + c - '0'));
}
return num;
}
@@ -3736,6 +3811,9 @@ create_tree (re_dfa_t *dfa, bin_tree_t *left, bin_tree_t *right,
re_token_type_t type)
{
re_token_t t;
+#if defined GCC_LINT || defined lint
+ memset (&t, 0, sizeof t);
+#endif
t.type = type;
return create_token_tree (dfa, left, right, &t);
}
@@ -3780,7 +3858,7 @@ create_token_tree (re_dfa_t *dfa, bin_tree_t *left, bin_tree_t *right,
static reg_errcode_t
mark_opt_subexp (void *extra, bin_tree_t *node)
{
- int idx = (int) (long) extra;
+ Idx idx = (uintptr_t) extra;
if (node->token.type == SUBEXP && node->token.opr.idx == idx)
node->token.opt_subexp = 1;
diff --git a/posix/regex.c b/posix/regex.c
index d4cfbe5c6f..d6591e8670 100644
--- a/posix/regex.c
+++ b/posix/regex.c
@@ -1,5 +1,5 @@
/* Extended regular expression matching and search library.
- Copyright (C) 2002-2016 Free Software Foundation, Inc.
+ Copyright (C) 2002-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Isamu Hasegawa <isamu@yamato.ibm.com>.
@@ -15,14 +15,22 @@
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
- <http://www.gnu.org/licenses/>. */
+ <https://www.gnu.org/licenses/>. */
-#ifdef HAVE_CONFIG_H
-#include "config.h"
+#ifndef _LIBC
+# include <config.h>
+
+# if (__GNUC__ == 4 && 6 <= __GNUC_MINOR__) || 4 < __GNUC__
+# pragma GCC diagnostic ignored "-Wsuggest-attribute=pure"
+# endif
+# if (__GNUC__ == 4 && 3 <= __GNUC_MINOR__) || 4 < __GNUC__
+# pragma GCC diagnostic ignored "-Wold-style-definition"
+# pragma GCC diagnostic ignored "-Wtype-limits"
+# endif
#endif
-/* Make sure noone compiles this code with a C++ compiler. */
-#ifdef __cplusplus
+/* Make sure no one compiles this code with a C++ compiler. */
+#if defined __cplusplus && defined _LIBC
# error "This is C code, use a C compiler"
#endif
@@ -56,9 +64,6 @@
#undefs RE_DUP_MAX and sets it to the right value. */
#include <limits.h>
-/* This header defines the MIN and MAX macros. */
-#include <sys/param.h>
-
#include <regex.h>
#include "regex_internal.h"
diff --git a/posix/regex.h b/posix/regex.h
index 90f0851790..32933bc6d5 100644
--- a/posix/regex.h
+++ b/posix/regex.h
@@ -1,6 +1,6 @@
/* Definitions for data structures and routines for the regular
expression library.
- Copyright (C) 1985, 1989-2016 Free Software Foundation, Inc.
+ Copyright (C) 1985, 1989-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -15,7 +15,7 @@
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
- <http://www.gnu.org/licenses/>. */
+ <https://www.gnu.org/licenses/>. */
#ifndef _REGEX_H
#define _REGEX_H 1
@@ -27,6 +27,36 @@
extern "C" {
#endif
+/* Define __USE_GNU to declare GNU extensions that violate the
+ POSIX name space rules. */
+#ifdef _GNU_SOURCE
+# define __USE_GNU 1
+#endif
+
+#ifdef _REGEX_LARGE_OFFSETS
+
+/* Use types and values that are wide enough to represent signed and
+ unsigned byte offsets in memory. This currently works only when
+ the regex code is used outside of the GNU C library; it is not yet
+ supported within glibc itself, and glibc users should not define
+ _REGEX_LARGE_OFFSETS. */
+
+/* The type of object sizes. */
+typedef size_t __re_size_t;
+
+/* The type of object sizes, in places where the traditional code
+ uses unsigned long int. */
+typedef size_t __re_long_size_t;
+
+#else
+
+/* The traditional GNU regex implementation mishandles strings longer
+ than INT_MAX. */
+typedef unsigned int __re_size_t;
+typedef unsigned long int __re_long_size_t;
+
+#endif
+
/* The following two types have to be signed and unsigned integer type
wide enough to hold a value of a pointer. For most ANSI compilers
ptrdiff_t and size_t should be likely OK. Still size of these two
@@ -108,9 +138,9 @@ typedef unsigned long int reg_syntax_t;
If not set, newline is literal. */
# define RE_NEWLINE_ALT (RE_LIMITED_OPS << 1)
-/* If this bit is set, then `{...}' defines an interval, and \{ and \}
+/* If this bit is set, then '{...}' defines an interval, and \{ and \}
are literals.
- If not set, then `\{...\}' defines an interval. */
+ If not set, then '\{...\}' defines an interval. */
# define RE_NO_BK_BRACES (RE_NEWLINE_ALT << 1)
/* If this bit is set, (...) defines a group, and \( and \) are literals.
@@ -165,8 +195,8 @@ typedef unsigned long int reg_syntax_t;
whether ^ should be special. */
# define RE_CARET_ANCHORS_HERE (RE_ICASE << 1)
-/* If this bit is set, then \{ cannot be first in an bre or
- immediately after an alternation or begin-group operator. */
+/* If this bit is set, then \{ cannot be first in a regex or
+ immediately after an alternation, open-group or \} operator. */
# define RE_CONTEXT_INVALID_DUP (RE_CARET_ANCHORS_HERE << 1)
/* If this bit is set, then no_sub will be set to 1 during
@@ -185,9 +215,9 @@ extern reg_syntax_t re_syntax_options;
(The [[[ comments delimit what gets put into the Texinfo file, so
don't delete them!) */
/* [[[begin syntaxes]]] */
-#define RE_SYNTAX_EMACS 0
+# define RE_SYNTAX_EMACS 0
-#define RE_SYNTAX_AWK \
+# define RE_SYNTAX_AWK \
(RE_BACKSLASH_ESCAPE_IN_LISTS | RE_DOT_NOT_NULL \
| RE_NO_BK_PARENS | RE_NO_BK_REFS \
| RE_NO_BK_VBAR | RE_NO_EMPTY_RANGES \
@@ -195,52 +225,49 @@ extern reg_syntax_t re_syntax_options;
| RE_CHAR_CLASSES \
| RE_UNMATCHED_RIGHT_PAREN_ORD | RE_NO_GNU_OPS)
-#define RE_SYNTAX_GNU_AWK \
+# define RE_SYNTAX_GNU_AWK \
((RE_SYNTAX_POSIX_EXTENDED | RE_BACKSLASH_ESCAPE_IN_LISTS \
| RE_INVALID_INTERVAL_ORD) \
& ~(RE_DOT_NOT_NULL | RE_CONTEXT_INDEP_OPS \
| RE_CONTEXT_INVALID_OPS ))
-#define RE_SYNTAX_POSIX_AWK \
+# define RE_SYNTAX_POSIX_AWK \
(RE_SYNTAX_POSIX_EXTENDED | RE_BACKSLASH_ESCAPE_IN_LISTS \
| RE_INTERVALS | RE_NO_GNU_OPS \
| RE_INVALID_INTERVAL_ORD)
-#define RE_SYNTAX_GREP \
- (RE_BK_PLUS_QM | RE_CHAR_CLASSES \
- | RE_HAT_LISTS_NOT_NEWLINE | RE_INTERVALS \
- | RE_NEWLINE_ALT)
+# define RE_SYNTAX_GREP \
+ ((RE_SYNTAX_POSIX_BASIC | RE_NEWLINE_ALT) \
+ & ~(RE_CONTEXT_INVALID_DUP | RE_DOT_NOT_NULL))
-#define RE_SYNTAX_EGREP \
- (RE_CHAR_CLASSES | RE_CONTEXT_INDEP_ANCHORS \
- | RE_CONTEXT_INDEP_OPS | RE_HAT_LISTS_NOT_NEWLINE \
- | RE_NEWLINE_ALT | RE_NO_BK_PARENS \
- | RE_NO_BK_VBAR)
+# define RE_SYNTAX_EGREP \
+ ((RE_SYNTAX_POSIX_EXTENDED | RE_INVALID_INTERVAL_ORD | RE_NEWLINE_ALT) \
+ & ~(RE_CONTEXT_INVALID_OPS | RE_DOT_NOT_NULL))
-#define RE_SYNTAX_POSIX_EGREP \
- (RE_SYNTAX_EGREP | RE_INTERVALS | RE_NO_BK_BRACES \
- | RE_INVALID_INTERVAL_ORD)
+/* POSIX grep -E behavior is no longer incompatible with GNU. */
+# define RE_SYNTAX_POSIX_EGREP \
+ RE_SYNTAX_EGREP
/* P1003.2/D11.2, section 4.20.7.1, lines 5078ff. */
-#define RE_SYNTAX_ED RE_SYNTAX_POSIX_BASIC
+# define RE_SYNTAX_ED RE_SYNTAX_POSIX_BASIC
-#define RE_SYNTAX_SED RE_SYNTAX_POSIX_BASIC
+# define RE_SYNTAX_SED RE_SYNTAX_POSIX_BASIC
/* Syntax bits common to both basic and extended POSIX regex syntax. */
-#define _RE_SYNTAX_POSIX_COMMON \
+# define _RE_SYNTAX_POSIX_COMMON \
(RE_CHAR_CLASSES | RE_DOT_NEWLINE | RE_DOT_NOT_NULL \
| RE_INTERVALS | RE_NO_EMPTY_RANGES)
-#define RE_SYNTAX_POSIX_BASIC \
+# define RE_SYNTAX_POSIX_BASIC \
(_RE_SYNTAX_POSIX_COMMON | RE_BK_PLUS_QM | RE_CONTEXT_INVALID_DUP)
/* Differs from ..._POSIX_BASIC only in that RE_BK_PLUS_QM becomes
RE_LIMITED_OPS, i.e., \? \+ \| are not recognized. Actually, this
isn't minimal, since other operators, such as \`, aren't disabled. */
-#define RE_SYNTAX_POSIX_MINIMAL_BASIC \
+# define RE_SYNTAX_POSIX_MINIMAL_BASIC \
(_RE_SYNTAX_POSIX_COMMON | RE_LIMITED_OPS)
-#define RE_SYNTAX_POSIX_EXTENDED \
+# define RE_SYNTAX_POSIX_EXTENDED \
(_RE_SYNTAX_POSIX_COMMON | RE_CONTEXT_INDEP_ANCHORS \
| RE_CONTEXT_INDEP_OPS | RE_NO_BK_BRACES \
| RE_NO_BK_PARENS | RE_NO_BK_VBAR \
@@ -248,25 +275,35 @@ extern reg_syntax_t re_syntax_options;
/* Differs from ..._POSIX_EXTENDED in that RE_CONTEXT_INDEP_OPS is
removed and RE_NO_BK_REFS is added. */
-#define RE_SYNTAX_POSIX_MINIMAL_EXTENDED \
+# define RE_SYNTAX_POSIX_MINIMAL_EXTENDED \
(_RE_SYNTAX_POSIX_COMMON | RE_CONTEXT_INDEP_ANCHORS \
| RE_CONTEXT_INVALID_OPS | RE_NO_BK_BRACES \
| RE_NO_BK_PARENS | RE_NO_BK_REFS \
| RE_NO_BK_VBAR | RE_UNMATCHED_RIGHT_PAREN_ORD)
/* [[[end syntaxes]]] */
-
-/* Maximum number of duplicates an interval can allow. Some systems
- (erroneously) define this in other header files, but we want our
+
+/* Maximum number of duplicates an interval can allow. POSIX-conforming
+ systems might define this in <limits.h>, but we want our
value, so remove any previous define. */
+# ifdef _REGEX_INCLUDE_LIMITS_H
+# include <limits.h>
+# endif
# ifdef RE_DUP_MAX
# undef RE_DUP_MAX
# endif
-/* If sizeof(int) == 2, then ((1 << 15) - 1) overflows. */
+
+/* RE_DUP_MAX is 2**15 - 1 because an earlier implementation stored
+ the counter as a 2-byte signed integer. This is no longer true, so
+ RE_DUP_MAX could be increased to (INT_MAX / 10 - 1), or to
+ ((SIZE_MAX - 9) / 10) if _REGEX_LARGE_OFFSETS is defined.
+ However, there would be a huge performance problem if someone
+ actually used a pattern like a\{214748363\}, so RE_DUP_MAX retains
+ its historical value. */
# define RE_DUP_MAX (0x7fff)
#endif
-/* POSIX `cflags' bits (i.e., information for `regcomp'). */
+/* POSIX 'cflags' bits (i.e., information for 'regcomp'). */
/* If this bit is set, then use extended regular expression syntax.
If not set, then use basic regular expression syntax. */
@@ -274,19 +311,19 @@ extern reg_syntax_t re_syntax_options;
/* If this bit is set, then ignore case when matching.
If not set, then case is significant. */
-#define REG_ICASE (REG_EXTENDED << 1)
+#define REG_ICASE (1 << 1)
/* If this bit is set, then anchors do not match at newline
characters in the string.
If not set, then anchors do match at newlines. */
-#define REG_NEWLINE (REG_ICASE << 1)
+#define REG_NEWLINE (1 << 2)
/* If this bit is set, then report only success or fail in regexec.
If not set, then returns differ between not matching and errors. */
-#define REG_NOSUB (REG_NEWLINE << 1)
+#define REG_NOSUB (1 << 3)
-/* POSIX `eflags' bits (i.e., information for regexec). */
+/* POSIX 'eflags' bits (i.e., information for regexec). */
/* If this bit is set, then the beginning-of-line operator doesn't match
the beginning of the string (presumably because it's not the
@@ -304,41 +341,60 @@ extern reg_syntax_t re_syntax_options;
/* If any error codes are removed, changed, or added, update the
- `re_error_msg' table in regex.c. */
+ '__re_error_msgid' table in regcomp.c. */
+
typedef enum
{
-#if defined _XOPEN_SOURCE || defined __USE_XOPEN2K
- REG_ENOSYS = -1, /* This will never happen for this implementation. */
-#endif
-
- REG_NOERROR = 0, /* Success. */
- REG_NOMATCH, /* Didn't find a match (for regexec). */
+ _REG_ENOSYS = -1, /* This will never happen for this implementation. */
+ _REG_NOERROR = 0, /* Success. */
+ _REG_NOMATCH, /* Didn't find a match (for regexec). */
/* POSIX regcomp return error codes. (In the order listed in the
standard.) */
- REG_BADPAT, /* Invalid pattern. */
- REG_ECOLLATE, /* Inalid collating element. */
- REG_ECTYPE, /* Invalid character class name. */
- REG_EESCAPE, /* Trailing backslash. */
- REG_ESUBREG, /* Invalid back reference. */
- REG_EBRACK, /* Unmatched left bracket. */
- REG_EPAREN, /* Parenthesis imbalance. */
- REG_EBRACE, /* Unmatched \{. */
- REG_BADBR, /* Invalid contents of \{\}. */
- REG_ERANGE, /* Invalid range end. */
- REG_ESPACE, /* Ran out of memory. */
- REG_BADRPT, /* No preceding re for repetition op. */
+ _REG_BADPAT, /* Invalid pattern. */
+ _REG_ECOLLATE, /* Invalid collating element. */
+ _REG_ECTYPE, /* Invalid character class name. */
+ _REG_EESCAPE, /* Trailing backslash. */
+ _REG_ESUBREG, /* Invalid back reference. */
+ _REG_EBRACK, /* Unmatched left bracket. */
+ _REG_EPAREN, /* Parenthesis imbalance. */
+ _REG_EBRACE, /* Unmatched \{. */
+ _REG_BADBR, /* Invalid contents of \{\}. */
+ _REG_ERANGE, /* Invalid range end. */
+ _REG_ESPACE, /* Ran out of memory. */
+ _REG_BADRPT, /* No preceding re for repetition op. */
/* Error codes we've added. */
- REG_EEND, /* Premature end. */
- REG_ESIZE, /* Compiled pattern bigger than 2^16 bytes. */
- REG_ERPAREN /* Unmatched ) or \); not returned from regcomp. */
+ _REG_EEND, /* Premature end. */
+ _REG_ESIZE, /* Too large (e.g., repeat count too large). */
+ _REG_ERPAREN /* Unmatched ) or \); not returned from regcomp. */
} reg_errcode_t;
+
+#if defined _XOPEN_SOURCE || defined __USE_XOPEN2K
+# define REG_ENOSYS _REG_ENOSYS
+#endif
+#define REG_NOERROR _REG_NOERROR
+#define REG_NOMATCH _REG_NOMATCH
+#define REG_BADPAT _REG_BADPAT
+#define REG_ECOLLATE _REG_ECOLLATE
+#define REG_ECTYPE _REG_ECTYPE
+#define REG_EESCAPE _REG_EESCAPE
+#define REG_ESUBREG _REG_ESUBREG
+#define REG_EBRACK _REG_EBRACK
+#define REG_EPAREN _REG_EPAREN
+#define REG_EBRACE _REG_EBRACE
+#define REG_BADBR _REG_BADBR
+#define REG_ERANGE _REG_ERANGE
+#define REG_ESPACE _REG_ESPACE
+#define REG_BADRPT _REG_BADRPT
+#define REG_EEND _REG_EEND
+#define REG_ESIZE _REG_ESIZE
+#define REG_ERPAREN _REG_ERPAREN
/* This data structure represents a compiled pattern. Before calling
- the pattern compiler, the fields `buffer', `allocated', `fastmap',
- and `translate' can be set. After the pattern has been compiled,
- the fields `re_nsub', `not_bol' and `not_eol' are available. All
+ the pattern compiler, the fields 'buffer', 'allocated', 'fastmap',
+ and 'translate' can be set. After the pattern has been compiled,
+ the fields 're_nsub', 'not_bol' and 'not_eol' are available. All
other fields are private to the regex routines. */
#ifndef RE_TRANSLATE_TYPE
@@ -356,16 +412,15 @@ typedef enum
struct re_pattern_buffer
{
- /* Space that holds the compiled pattern. It is declared as
- `unsigned char *' because its elements are sometimes used as
- array indexes. */
- unsigned char *__REPB_PREFIX(buffer);
+ /* Space that holds the compiled pattern. The type
+ 'struct re_dfa_t' is private and is not declared here. */
+ struct re_dfa_t *__REPB_PREFIX(buffer);
- /* Number of bytes to which `buffer' points. */
- unsigned long int __REPB_PREFIX(allocated);
+ /* Number of bytes to which 'buffer' points. */
+ __re_long_size_t __REPB_PREFIX(allocated);
- /* Number of bytes actually used in `buffer'. */
- unsigned long int __REPB_PREFIX(used);
+ /* Number of bytes actually used in 'buffer'. */
+ __re_long_size_t __REPB_PREFIX(used);
/* Syntax setting with which the pattern was compiled. */
reg_syntax_t __REPB_PREFIX(syntax);
@@ -385,13 +440,13 @@ struct re_pattern_buffer
size_t re_nsub;
/* Zero if this pattern cannot match the empty string, one else.
- Well, in truth it's used only in `re_search_2', to see whether or
+ Well, in truth it's used only in 're_search_2', to see whether or
not we should use the fastmap, so we don't set this absolutely
- perfectly; see `re_compile_fastmap' (the `duplicate' case). */
+ perfectly; see 're_compile_fastmap' (the "duplicate" case). */
unsigned __REPB_PREFIX(can_be_null) : 1;
- /* If REGS_UNALLOCATED, allocate space in the `regs' structure
- for `max (RE_NREGS, re_nsub + 1)' groups.
+ /* If REGS_UNALLOCATED, allocate space in the 'regs' structure
+ for 'max (RE_NREGS, re_nsub + 1)' groups.
If REGS_REALLOCATE, reallocate space if necessary.
If REGS_FIXED, use what's there. */
#ifdef __USE_GNU
@@ -401,11 +456,11 @@ struct re_pattern_buffer
#endif
unsigned __REPB_PREFIX(regs_allocated) : 2;
- /* Set to zero when `regex_compile' compiles a pattern; set to one
- by `re_compile_fastmap' if it updates the fastmap. */
+ /* Set to zero when 're_compile_pattern' compiles a pattern; set to
+ one by 're_compile_fastmap' if it updates the fastmap. */
unsigned __REPB_PREFIX(fastmap_accurate) : 1;
- /* If set, `re_match_2' does not return information about
+ /* If set, 're_match_2' does not return information about
subexpressions. */
unsigned __REPB_PREFIX(no_sub) : 1;
@@ -423,7 +478,17 @@ struct re_pattern_buffer
typedef struct re_pattern_buffer regex_t;
/* Type for byte offsets within the string. POSIX mandates this. */
+#ifdef _REGEX_LARGE_OFFSETS
+/* POSIX 1003.1-2008 requires that regoff_t be at least as wide as
+ ptrdiff_t and ssize_t. We don't know of any hosts where ptrdiff_t
+ is wider than ssize_t, so ssize_t is safe. ptrdiff_t is not
+ visible here, so use ssize_t. */
+typedef ssize_t regoff_t;
+#else
+/* The traditional GNU regex implementation mishandles strings longer
+ than INT_MAX. */
typedef int regoff_t;
+#endif
#ifdef __USE_GNU
@@ -431,15 +496,15 @@ typedef int regoff_t;
regex.texinfo for a full description of what registers match. */
struct re_registers
{
- unsigned num_regs;
+ __re_size_t num_regs;
regoff_t *start;
regoff_t *end;
};
-/* If `regs_allocated' is REGS_UNALLOCATED in the pattern buffer,
- `re_match_2' returns information about at least this many registers
- the first time a `regs' structure is passed. */
+/* If 'regs_allocated' is REGS_UNALLOCATED in the pattern buffer,
+ 're_match_2' returns information about at least this many registers
+ the first time a 'regs' structure is passed. */
# ifndef RE_NREGS
# define RE_NREGS 30
# endif
@@ -447,7 +512,7 @@ struct re_registers
/* POSIX specification for registers. Aside from the different names than
- `re_registers', POSIX uses an array of structures, instead of a
+ 're_registers', POSIX uses an array of structures, instead of a
structure of arrays. */
typedef struct
{
@@ -459,17 +524,17 @@ typedef struct
#ifdef __USE_GNU
/* Sets the current default syntax to SYNTAX, and return the old syntax.
- You can also simply assign to the `re_syntax_options' variable. */
+ You can also simply assign to the 're_syntax_options' variable. */
extern reg_syntax_t re_set_syntax (reg_syntax_t __syntax);
/* Compile the regular expression PATTERN, with length LENGTH
- and syntax given by the global `re_syntax_options', into the buffer
+ and syntax given by the global 're_syntax_options', into the buffer
BUFFER. Return NULL if successful, and an error string if not.
- To free the allocated storage, you must call `regfree' on BUFFER.
- Note that the translate table must either have been initialised by
- `regcomp', with a malloc'ed value, or set to NULL before calling
- `regfree'. */
+ To free the allocated storage, you must call 'regfree' on BUFFER.
+ Note that the translate table must either have been initialized by
+ 'regcomp', with a malloc'ed value, or set to NULL before calling
+ 'regfree'. */
extern const char *re_compile_pattern (const char *__pattern, size_t __length,
struct re_pattern_buffer *__buffer);
@@ -485,47 +550,52 @@ extern int re_compile_fastmap (struct re_pattern_buffer *__buffer);
characters. Return the starting position of the match, -1 for no
match, or -2 for an internal error. Also return register
information in REGS (if REGS and BUFFER->no_sub are nonzero). */
-extern int re_search (struct re_pattern_buffer *__buffer, const char *__string,
- int __length, int __start, int __range,
- struct re_registers *__regs);
+extern regoff_t re_search (struct re_pattern_buffer *__buffer,
+ const char *__String, regoff_t __length,
+ regoff_t __start, regoff_t __range,
+ struct re_registers *__regs);
-/* Like `re_search', but search in the concatenation of STRING1 and
+/* Like 're_search', but search in the concatenation of STRING1 and
STRING2. Also, stop searching at index START + STOP. */
-extern int re_search_2 (struct re_pattern_buffer *__buffer,
- const char *__string1, int __length1,
- const char *__string2, int __length2, int __start,
- int __range, struct re_registers *__regs, int __stop);
+extern regoff_t re_search_2 (struct re_pattern_buffer *__buffer,
+ const char *__string1, regoff_t __length1,
+ const char *__string2, regoff_t __length2,
+ regoff_t __start, regoff_t __range,
+ struct re_registers *__regs,
+ regoff_t __stop);
-/* Like `re_search', but return how many characters in STRING the regexp
+/* Like 're_search', but return how many characters in STRING the regexp
in BUFFER matched, starting at position START. */
-extern int re_match (struct re_pattern_buffer *__buffer, const char *__string,
- int __length, int __start, struct re_registers *__regs);
+extern regoff_t re_match (struct re_pattern_buffer *__buffer,
+ const char *__String, regoff_t __length,
+ regoff_t __start, struct re_registers *__regs);
-/* Relates to `re_match' as `re_search_2' relates to `re_search'. */
-extern int re_match_2 (struct re_pattern_buffer *__buffer,
- const char *__string1, int __length1,
- const char *__string2, int __length2, int __start,
- struct re_registers *__regs, int __stop);
+/* Relates to 're_match' as 're_search_2' relates to 're_search'. */
+extern regoff_t re_match_2 (struct re_pattern_buffer *__buffer,
+ const char *__string1, regoff_t __length1,
+ const char *__string2, regoff_t __length2,
+ regoff_t __start, struct re_registers *__regs,
+ regoff_t __stop);
/* Set REGS to hold NUM_REGS registers, storing them in STARTS and
ENDS. Subsequent matches using BUFFER and REGS will use this memory
for recording register information. STARTS and ENDS must be
- allocated with malloc, and must each be at least `NUM_REGS * sizeof
+ allocated with malloc, and must each be at least 'NUM_REGS * sizeof
(regoff_t)' bytes long.
If NUM_REGS == 0, then subsequent matches should allocate their own
register data.
Unless this function is called, the first search or match using
- PATTERN_BUFFER will allocate its own register data, without
+ BUFFER will allocate its own register data, without
freeing the old data. */
extern void re_set_registers (struct re_pattern_buffer *__buffer,
struct re_registers *__regs,
- unsigned int __num_regs,
+ __re_size_t __num_regs,
regoff_t *__starts, regoff_t *__ends);
#endif /* Use GNU */
@@ -537,39 +607,46 @@ extern int re_exec (const char *);
# endif
#endif
-/* GCC 2.95 and later have "__restrict"; C99 compilers have
- "restrict", and "configure" may have defined "restrict". */
-#ifndef __restrict
-# if ! (2 < __GNUC__ || (2 == __GNUC__ && 95 <= __GNUC_MINOR__))
-# if defined restrict || 199901L <= __STDC_VERSION__
-# define __restrict restrict
-# else
-# define __restrict
-# endif
+/* For plain 'restrict', use glibc's __restrict if defined.
+ Otherwise, GCC 2.95 and later have "__restrict"; C99 compilers have
+ "restrict", and "configure" may have defined "restrict".
+ Other compilers use __restrict, __restrict__, and _Restrict, and
+ 'configure' might #define 'restrict' to those words, so pick a
+ different name. */
+#ifndef _Restrict_
+# if defined __restrict || 2 < __GNUC__ + (95 <= __GNUC_MINOR__)
+# define _Restrict_ __restrict
+# elif 199901L <= __STDC_VERSION__ || defined restrict
+# define _Restrict_ restrict
+# else
+# define _Restrict_
# endif
#endif
-/* gcc 3.1 and up support the [restrict] syntax. */
-#ifndef __restrict_arr
-# if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)) \
- && !defined __GNUG__
-# define __restrict_arr __restrict
+/* For [restrict], use glibc's __restrict_arr if available.
+ Otherwise, GCC 3.1 (not in C++ mode) and C99 support [restrict]. */
+#ifndef _Restrict_arr_
+# ifdef __restrict_arr
+# define _Restrict_arr_ __restrict_arr
+# elif ((199901L <= __STDC_VERSION__ || 3 < __GNUC__ + (1 <= __GNUC_MINOR__)) \
+ && !defined __GNUG__)
+# define _Restrict_arr_ _Restrict_
# else
-# define __restrict_arr
+# define _Restrict_arr_
# endif
#endif
/* POSIX compatibility. */
-extern int regcomp (regex_t *__restrict __preg,
- const char *__restrict __pattern,
+extern int regcomp (regex_t *_Restrict_ __preg,
+ const char *_Restrict_ __pattern,
int __cflags);
-extern int regexec (const regex_t *__restrict __preg,
- const char *__restrict __string, size_t __nmatch,
- regmatch_t __pmatch[__restrict_arr],
+extern int regexec (const regex_t *_Restrict_ __preg,
+ const char *_Restrict_ __String, size_t __nmatch,
+ regmatch_t __pmatch[_Restrict_arr_],
int __eflags);
-extern size_t regerror (int __errcode, const regex_t *__restrict __preg,
- char *__restrict __errbuf, size_t __errbuf_size);
+extern size_t regerror (int __errcode, const regex_t *_Restrict_ __preg,
+ char *_Restrict_ __errbuf, size_t __errbuf_size);
extern void regfree (regex_t *__preg);
diff --git a/posix/regex_internal.c b/posix/regex_internal.c
index 16865d85d2..7f0083b918 100644
--- a/posix/regex_internal.c
+++ b/posix/regex_internal.c
@@ -1,5 +1,5 @@
/* Extended regular expression matching and search library.
- Copyright (C) 2002-2016 Free Software Foundation, Inc.
+ Copyright (C) 2002-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Isamu Hasegawa <isamu@yamato.ibm.com>.
@@ -15,19 +15,29 @@
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
- <http://www.gnu.org/licenses/>. */
+ <https://www.gnu.org/licenses/>. */
-static void re_string_construct_common (const char *str, int len,
+static void re_string_construct_common (const char *str, Idx len,
re_string_t *pstr,
- RE_TRANSLATE_TYPE trans, int icase,
- const re_dfa_t *dfa) internal_function;
+ RE_TRANSLATE_TYPE trans, bool icase,
+ const re_dfa_t *dfa);
static re_dfastate_t *create_ci_newstate (const re_dfa_t *dfa,
const re_node_set *nodes,
- unsigned int hash) internal_function;
+ re_hashval_t hash);
static re_dfastate_t *create_cd_newstate (const re_dfa_t *dfa,
const re_node_set *nodes,
unsigned int context,
- unsigned int hash) internal_function;
+ re_hashval_t hash);
+static reg_errcode_t re_string_realloc_buffers (re_string_t *pstr,
+ Idx new_buf_len);
+#ifdef RE_ENABLE_I18N
+static void build_wcs_buffer (re_string_t *pstr);
+static reg_errcode_t build_wcs_upper_buffer (re_string_t *pstr);
+#endif /* RE_ENABLE_I18N */
+static void build_upper_buffer (re_string_t *pstr);
+static void re_string_translate_buffer (re_string_t *pstr);
+static unsigned int re_string_context_at (const re_string_t *input, Idx idx,
+ int eflags) __attribute__ ((pure));
/* Functions for string operation. */
@@ -35,12 +45,12 @@ static re_dfastate_t *create_cd_newstate (const re_dfa_t *dfa,
re_string_reconstruct before using the object. */
static reg_errcode_t
-internal_function __attribute_warn_unused_result__
-re_string_allocate (re_string_t *pstr, const char *str, int len, int init_len,
- RE_TRANSLATE_TYPE trans, int icase, const re_dfa_t *dfa)
+__attribute_warn_unused_result__
+re_string_allocate (re_string_t *pstr, const char *str, Idx len, Idx init_len,
+ RE_TRANSLATE_TYPE trans, bool icase, const re_dfa_t *dfa)
{
reg_errcode_t ret;
- int init_buf_len;
+ Idx init_buf_len;
/* Ensure at least one character fits into the buffers. */
if (init_len < dfa->mb_cur_max)
@@ -63,9 +73,9 @@ re_string_allocate (re_string_t *pstr, const char *str, int len, int init_len,
/* This function allocate the buffers, and initialize them. */
static reg_errcode_t
-internal_function __attribute_warn_unused_result__
-re_string_construct (re_string_t *pstr, const char *str, int len,
- RE_TRANSLATE_TYPE trans, int icase, const re_dfa_t *dfa)
+__attribute_warn_unused_result__
+re_string_construct (re_string_t *pstr, const char *str, Idx len,
+ RE_TRANSLATE_TYPE trans, bool icase, const re_dfa_t *dfa)
{
reg_errcode_t ret;
memset (pstr, '\0', sizeof (re_string_t));
@@ -126,8 +136,8 @@ re_string_construct (re_string_t *pstr, const char *str, int len,
/* Helper functions for re_string_allocate, and re_string_construct. */
static reg_errcode_t
-internal_function __attribute_warn_unused_result__
-re_string_realloc_buffers (re_string_t *pstr, int new_buf_len)
+__attribute_warn_unused_result__
+re_string_realloc_buffers (re_string_t *pstr, Idx new_buf_len)
{
#ifdef RE_ENABLE_I18N
if (pstr->mb_cur_max > 1)
@@ -135,8 +145,8 @@ re_string_realloc_buffers (re_string_t *pstr, int new_buf_len)
wint_t *new_wcs;
/* Avoid overflow in realloc. */
- const size_t max_object_size = MAX (sizeof (wint_t), sizeof (int));
- if (BE (SIZE_MAX / max_object_size < new_buf_len, 0))
+ const size_t max_object_size = MAX (sizeof (wint_t), sizeof (Idx));
+ if (BE (MIN (IDX_MAX, SIZE_MAX / max_object_size) < new_buf_len, 0))
return REG_ESPACE;
new_wcs = re_realloc (pstr->wcs, wint_t, new_buf_len);
@@ -145,7 +155,7 @@ re_string_realloc_buffers (re_string_t *pstr, int new_buf_len)
pstr->wcs = new_wcs;
if (pstr->offsets != NULL)
{
- int *new_offsets = re_realloc (pstr->offsets, int, new_buf_len);
+ Idx *new_offsets = re_realloc (pstr->offsets, Idx, new_buf_len);
if (BE (new_offsets == NULL, 0))
return REG_ESPACE;
pstr->offsets = new_offsets;
@@ -166,16 +176,15 @@ re_string_realloc_buffers (re_string_t *pstr, int new_buf_len)
static void
-internal_function
-re_string_construct_common (const char *str, int len, re_string_t *pstr,
- RE_TRANSLATE_TYPE trans, int icase,
+re_string_construct_common (const char *str, Idx len, re_string_t *pstr,
+ RE_TRANSLATE_TYPE trans, bool icase,
const re_dfa_t *dfa)
{
pstr->raw_mbs = (const unsigned char *) str;
pstr->len = len;
pstr->raw_len = len;
pstr->trans = trans;
- pstr->icase = icase ? 1 : 0;
+ pstr->icase = icase;
pstr->mbs_allocated = (trans != NULL || icase);
pstr->mb_cur_max = dfa->mb_cur_max;
pstr->is_utf8 = dfa->is_utf8;
@@ -198,7 +207,6 @@ re_string_construct_common (const char *str, int len, re_string_t *pstr,
built and starts from PSTR->VALID_LEN. */
static void
-internal_function
build_wcs_buffer (re_string_t *pstr)
{
#ifdef _LIBC
@@ -208,7 +216,7 @@ build_wcs_buffer (re_string_t *pstr)
unsigned char buf[64];
#endif
mbstate_t prev_st;
- int byte_idx, end_idx, remain_len;
+ Idx byte_idx, end_idx, remain_len;
size_t mbclen;
/* Build the buffers from pstr->valid_len to either pstr->len or
@@ -267,11 +275,11 @@ build_wcs_buffer (re_string_t *pstr)
but for REG_ICASE. */
static reg_errcode_t
-internal_function __attribute_warn_unused_result__
+__attribute_warn_unused_result__
build_wcs_upper_buffer (re_string_t *pstr)
{
mbstate_t prev_st;
- int src_idx, byte_idx, end_idx, remain_len;
+ Idx src_idx, byte_idx, end_idx, remain_len;
size_t mbclen;
#ifdef _LIBC
char buf[MB_LEN_MAX];
@@ -309,14 +317,13 @@ build_wcs_upper_buffer (re_string_t *pstr)
mbclen = __mbrtowc (&wc,
((const char *) pstr->raw_mbs + pstr->raw_mbs_idx
+ byte_idx), remain_len, &pstr->cur_state);
- if (BE (mbclen + 2 > 2, 1))
+ if (BE (mbclen < (size_t) -2, 1))
{
- wchar_t wcu = wc;
- if (__iswlower (wc))
+ wchar_t wcu = __towupper (wc);
+ if (wcu != wc)
{
size_t mbcdlen;
- wcu = __towupper (wc);
mbcdlen = __wcrtomb (buf, wcu, &prev_st);
if (BE (mbclen == mbcdlen, 1))
memcpy (pstr->mbs + byte_idx, buf, mbclen);
@@ -379,14 +386,13 @@ build_wcs_upper_buffer (re_string_t *pstr)
else
p = (const char *) pstr->raw_mbs + pstr->raw_mbs_idx + src_idx;
mbclen = __mbrtowc (&wc, p, remain_len, &pstr->cur_state);
- if (BE (mbclen + 2 > 2, 1))
+ if (BE (mbclen < (size_t) -2, 1))
{
- wchar_t wcu = wc;
- if (__iswlower (wc))
+ wchar_t wcu = __towupper (wc);
+ if (wcu != wc)
{
size_t mbcdlen;
- wcu = __towupper (wc);
mbcdlen = __wcrtomb ((char *) buf, wcu, &prev_st);
if (BE (mbclen == mbcdlen, 1))
memcpy (pstr->mbs + byte_idx, buf, mbclen);
@@ -402,7 +408,7 @@ build_wcs_upper_buffer (re_string_t *pstr)
if (pstr->offsets == NULL)
{
- pstr->offsets = re_malloc (int, pstr->bufs_len);
+ pstr->offsets = re_malloc (Idx, pstr->bufs_len);
if (pstr->offsets == NULL)
return REG_ESPACE;
@@ -485,12 +491,11 @@ build_wcs_upper_buffer (re_string_t *pstr)
/* Skip characters until the index becomes greater than NEW_RAW_IDX.
Return the index. */
-static int
-internal_function
-re_string_skip_chars (re_string_t *pstr, int new_raw_idx, wint_t *last_wc)
+static Idx
+re_string_skip_chars (re_string_t *pstr, Idx new_raw_idx, wint_t *last_wc)
{
mbstate_t prev_st;
- int rawbuf_idx;
+ Idx rawbuf_idx;
size_t mbclen;
wint_t wc = WEOF;
@@ -499,11 +504,11 @@ re_string_skip_chars (re_string_t *pstr, int new_raw_idx, wint_t *last_wc)
rawbuf_idx < new_raw_idx;)
{
wchar_t wc2;
- int remain_len = pstr->raw_len - rawbuf_idx;
+ Idx remain_len = pstr->raw_len - rawbuf_idx;
prev_st = pstr->cur_state;
mbclen = __mbrtowc (&wc2, (const char *) pstr->raw_mbs + rawbuf_idx,
remain_len, &pstr->cur_state);
- if (BE ((ssize_t) mbclen <= 0, 0))
+ if (BE (mbclen == (size_t) -2 || mbclen == (size_t) -1 || mbclen == 0, 0))
{
/* We treat these cases as a single byte character. */
if (mbclen == 0 || remain_len == 0)
@@ -514,7 +519,7 @@ re_string_skip_chars (re_string_t *pstr, int new_raw_idx, wint_t *last_wc)
pstr->cur_state = prev_st;
}
else
- wc = (wint_t) wc2;
+ wc = wc2;
/* Then proceed the next character. */
rawbuf_idx += mbclen;
}
@@ -527,10 +532,9 @@ re_string_skip_chars (re_string_t *pstr, int new_raw_idx, wint_t *last_wc)
This function is used in case of REG_ICASE. */
static void
-internal_function
build_upper_buffer (re_string_t *pstr)
{
- int char_idx, end_idx;
+ Idx char_idx, end_idx;
end_idx = (pstr->bufs_len > pstr->len) ? pstr->len : pstr->bufs_len;
for (char_idx = pstr->valid_len; char_idx < end_idx; ++char_idx)
@@ -538,10 +542,7 @@ build_upper_buffer (re_string_t *pstr)
int ch = pstr->raw_mbs[pstr->raw_mbs_idx + char_idx];
if (BE (pstr->trans != NULL, 0))
ch = pstr->trans[ch];
- if (islower (ch))
- pstr->mbs[char_idx] = toupper (ch);
- else
- pstr->mbs[char_idx] = ch;
+ pstr->mbs[char_idx] = toupper (ch);
}
pstr->valid_len = char_idx;
pstr->valid_raw_len = char_idx;
@@ -550,10 +551,9 @@ build_upper_buffer (re_string_t *pstr)
/* Apply TRANS to the buffer in PSTR. */
static void
-internal_function
re_string_translate_buffer (re_string_t *pstr)
{
- int buf_idx, end_idx;
+ Idx buf_idx, end_idx;
end_idx = (pstr->bufs_len > pstr->len) ? pstr->len : pstr->bufs_len;
for (buf_idx = pstr->valid_len; buf_idx < end_idx; ++buf_idx)
@@ -571,11 +571,14 @@ re_string_translate_buffer (re_string_t *pstr)
convert to upper case in case of REG_ICASE, apply translation. */
static reg_errcode_t
-internal_function __attribute_warn_unused_result__
-re_string_reconstruct (re_string_t *pstr, int idx, int eflags)
+__attribute_warn_unused_result__
+re_string_reconstruct (re_string_t *pstr, Idx idx, int eflags)
{
- int offset = idx - pstr->raw_mbs_idx;
- if (BE (offset < 0, 0))
+ Idx offset;
+
+ if (BE (pstr->raw_mbs_idx <= idx, 0))
+ offset = idx - pstr->raw_mbs_idx;
+ else
{
/* Reset buffer. */
#ifdef RE_ENABLE_I18N
@@ -604,7 +607,7 @@ re_string_reconstruct (re_string_t *pstr, int idx, int eflags)
#ifdef RE_ENABLE_I18N
if (BE (pstr->offsets_needed, 0))
{
- int low = 0, high = pstr->valid_len, mid;
+ Idx low = 0, high = pstr->valid_len, mid;
do
{
mid = (high + low) / 2;
@@ -686,10 +689,10 @@ re_string_reconstruct (re_string_t *pstr, int idx, int eflags)
}
else
{
+#ifdef RE_ENABLE_I18N
/* No, skip all characters until IDX. */
- int prev_valid_len = pstr->valid_len;
+ Idx prev_valid_len = pstr->valid_len;
-#ifdef RE_ENABLE_I18N
if (BE (pstr->offsets_needed, 0))
{
pstr->len = pstr->raw_len - idx + offset;
@@ -701,7 +704,7 @@ re_string_reconstruct (re_string_t *pstr, int idx, int eflags)
#ifdef RE_ENABLE_I18N
if (pstr->mb_cur_max > 1)
{
- int wcs_idx;
+ Idx wcs_idx;
wint_t wc = WEOF;
if (pstr->is_utf8)
@@ -731,7 +734,7 @@ re_string_reconstruct (re_string_t *pstr, int idx, int eflags)
{
mbstate_t cur_state;
wchar_t wc2;
- int mlen = raw + pstr->len - p;
+ Idx mlen = raw + pstr->len - p;
unsigned char buf[6];
size_t mbclen;
@@ -831,10 +834,11 @@ re_string_reconstruct (re_string_t *pstr, int idx, int eflags)
}
static unsigned char
-internal_function __attribute ((pure))
-re_string_peek_byte_case (const re_string_t *pstr, int idx)
+__attribute__ ((pure))
+re_string_peek_byte_case (const re_string_t *pstr, Idx idx)
{
- int ch, off;
+ int ch;
+ Idx off;
/* Handle the common (easiest) cases first. */
if (BE (!pstr->mbs_allocated, 1))
@@ -867,7 +871,6 @@ re_string_peek_byte_case (const re_string_t *pstr, int idx)
}
static unsigned char
-internal_function
re_string_fetch_byte_case (re_string_t *pstr)
{
if (BE (!pstr->mbs_allocated, 1))
@@ -876,7 +879,8 @@ re_string_fetch_byte_case (re_string_t *pstr)
#ifdef RE_ENABLE_I18N
if (pstr->offsets_needed)
{
- int off, ch;
+ Idx off;
+ int ch;
/* For tr_TR.UTF-8 [[:islower:]] there is
[[: CAPITAL LETTER I WITH DOT lower:]] in mbs. Skip
@@ -904,7 +908,6 @@ re_string_fetch_byte_case (re_string_t *pstr)
}
static void
-internal_function
re_string_destruct (re_string_t *pstr)
{
#ifdef RE_ENABLE_I18N
@@ -918,8 +921,7 @@ re_string_destruct (re_string_t *pstr)
/* Return the context at IDX in INPUT. */
static unsigned int
-internal_function
-re_string_context_at (const re_string_t *input, int idx, int eflags)
+re_string_context_at (const re_string_t *input, Idx idx, int eflags)
{
int c;
if (BE (idx < 0, 0))
@@ -933,7 +935,7 @@ re_string_context_at (const re_string_t *input, int idx, int eflags)
if (input->mb_cur_max > 1)
{
wint_t wc;
- int wc_idx = idx;
+ Idx wc_idx = idx;
while(input->wcs[wc_idx] == WEOF)
{
#if defined DEBUG && DEBUG
@@ -963,24 +965,24 @@ re_string_context_at (const re_string_t *input, int idx, int eflags)
/* Functions for set operation. */
static reg_errcode_t
-internal_function __attribute_warn_unused_result__
-re_node_set_alloc (re_node_set *set, int size)
+__attribute_warn_unused_result__
+re_node_set_alloc (re_node_set *set, Idx size)
{
set->alloc = size;
set->nelem = 0;
- set->elems = re_malloc (int, size);
- if (BE (set->elems == NULL, 0))
+ set->elems = re_malloc (Idx, size);
+ if (BE (set->elems == NULL, 0) && (MALLOC_0_IS_NONNULL || size != 0))
return REG_ESPACE;
return REG_NOERROR;
}
static reg_errcode_t
-internal_function __attribute_warn_unused_result__
-re_node_set_init_1 (re_node_set *set, int elem)
+__attribute_warn_unused_result__
+re_node_set_init_1 (re_node_set *set, Idx elem)
{
set->alloc = 1;
set->nelem = 1;
- set->elems = re_malloc (int, 1);
+ set->elems = re_malloc (Idx, 1);
if (BE (set->elems == NULL, 0))
{
set->alloc = set->nelem = 0;
@@ -991,11 +993,11 @@ re_node_set_init_1 (re_node_set *set, int elem)
}
static reg_errcode_t
-internal_function __attribute_warn_unused_result__
-re_node_set_init_2 (re_node_set *set, int elem1, int elem2)
+__attribute_warn_unused_result__
+re_node_set_init_2 (re_node_set *set, Idx elem1, Idx elem2)
{
set->alloc = 2;
- set->elems = re_malloc (int, 2);
+ set->elems = re_malloc (Idx, 2);
if (BE (set->elems == NULL, 0))
return REG_ESPACE;
if (elem1 == elem2)
@@ -1021,20 +1023,20 @@ re_node_set_init_2 (re_node_set *set, int elem1, int elem2)
}
static reg_errcode_t
-internal_function __attribute_warn_unused_result__
+__attribute_warn_unused_result__
re_node_set_init_copy (re_node_set *dest, const re_node_set *src)
{
dest->nelem = src->nelem;
if (src->nelem > 0)
{
dest->alloc = dest->nelem;
- dest->elems = re_malloc (int, dest->alloc);
+ dest->elems = re_malloc (Idx, dest->alloc);
if (BE (dest->elems == NULL, 0))
{
dest->alloc = dest->nelem = 0;
return REG_ESPACE;
}
- memcpy (dest->elems, src->elems, src->nelem * sizeof (int));
+ memcpy (dest->elems, src->elems, src->nelem * sizeof (Idx));
}
else
re_node_set_init_empty (dest);
@@ -1046,11 +1048,11 @@ re_node_set_init_copy (re_node_set *dest, const re_node_set *src)
Note: We assume dest->elems is NULL, when dest->alloc is 0. */
static reg_errcode_t
-internal_function __attribute_warn_unused_result__
+__attribute_warn_unused_result__
re_node_set_add_intersect (re_node_set *dest, const re_node_set *src1,
const re_node_set *src2)
{
- int i1, i2, is, id, delta, sbase;
+ Idx i1, i2, is, id, delta, sbase;
if (src1->nelem == 0 || src2->nelem == 0)
return REG_NOERROR;
@@ -1058,8 +1060,8 @@ re_node_set_add_intersect (re_node_set *dest, const re_node_set *src1,
conservative estimate. */
if (src1->nelem + src2->nelem + dest->nelem > dest->alloc)
{
- int new_alloc = src1->nelem + src2->nelem + dest->alloc;
- int *new_elems = re_realloc (dest->elems, int, new_alloc);
+ Idx new_alloc = src1->nelem + src2->nelem + dest->alloc;
+ Idx *new_elems = re_realloc (dest->elems, Idx, new_alloc);
if (BE (new_elems == NULL, 0))
return REG_ESPACE;
dest->elems = new_elems;
@@ -1081,7 +1083,7 @@ re_node_set_add_intersect (re_node_set *dest, const re_node_set *src1,
--id;
if (id < 0 || dest->elems[id] != src1->elems[i1])
- dest->elems[--sbase] = src1->elems[i1];
+ dest->elems[--sbase] = src1->elems[i1];
if (--i1 < 0 || --i2 < 0)
break;
@@ -1128,7 +1130,7 @@ re_node_set_add_intersect (re_node_set *dest, const re_node_set *src1,
}
/* Copy remaining SRC elements. */
- memcpy (dest->elems, dest->elems + sbase, delta * sizeof (int));
+ memcpy (dest->elems, dest->elems + sbase, delta * sizeof (Idx));
return REG_NOERROR;
}
@@ -1137,15 +1139,15 @@ re_node_set_add_intersect (re_node_set *dest, const re_node_set *src1,
DEST. Return value indicate the error code or REG_NOERROR if succeeded. */
static reg_errcode_t
-internal_function __attribute_warn_unused_result__
+__attribute_warn_unused_result__
re_node_set_init_union (re_node_set *dest, const re_node_set *src1,
const re_node_set *src2)
{
- int i1, i2, id;
+ Idx i1, i2, id;
if (src1 != NULL && src1->nelem > 0 && src2 != NULL && src2->nelem > 0)
{
dest->alloc = src1->nelem + src2->nelem;
- dest->elems = re_malloc (int, dest->alloc);
+ dest->elems = re_malloc (Idx, dest->alloc);
if (BE (dest->elems == NULL, 0))
return REG_ESPACE;
}
@@ -1173,13 +1175,13 @@ re_node_set_init_union (re_node_set *dest, const re_node_set *src1,
if (i1 < src1->nelem)
{
memcpy (dest->elems + id, src1->elems + i1,
- (src1->nelem - i1) * sizeof (int));
+ (src1->nelem - i1) * sizeof (Idx));
id += src1->nelem - i1;
}
else if (i2 < src2->nelem)
{
memcpy (dest->elems + id, src2->elems + i2,
- (src2->nelem - i2) * sizeof (int));
+ (src2->nelem - i2) * sizeof (Idx));
id += src2->nelem - i2;
}
dest->nelem = id;
@@ -1190,16 +1192,16 @@ re_node_set_init_union (re_node_set *dest, const re_node_set *src1,
DEST. Return value indicate the error code or REG_NOERROR if succeeded. */
static reg_errcode_t
-internal_function __attribute_warn_unused_result__
+__attribute_warn_unused_result__
re_node_set_merge (re_node_set *dest, const re_node_set *src)
{
- int is, id, sbase, delta;
+ Idx is, id, sbase, delta;
if (src == NULL || src->nelem == 0)
return REG_NOERROR;
if (dest->alloc < 2 * src->nelem + dest->nelem)
{
- int new_alloc = 2 * (src->nelem + dest->alloc);
- int *new_buffer = re_realloc (dest->elems, int, new_alloc);
+ Idx new_alloc = 2 * (src->nelem + dest->alloc);
+ Idx *new_buffer = re_realloc (dest->elems, Idx, new_alloc);
if (BE (new_buffer == NULL, 0))
return REG_ESPACE;
dest->elems = new_buffer;
@@ -1209,7 +1211,7 @@ re_node_set_merge (re_node_set *dest, const re_node_set *src)
if (BE (dest->nelem == 0, 0))
{
dest->nelem = src->nelem;
- memcpy (dest->elems, src->elems, src->nelem * sizeof (int));
+ memcpy (dest->elems, src->elems, src->nelem * sizeof (Idx));
return REG_NOERROR;
}
@@ -1230,7 +1232,7 @@ re_node_set_merge (re_node_set *dest, const re_node_set *src)
{
/* If DEST is exhausted, the remaining items of SRC must be unique. */
sbase -= is + 1;
- memcpy (dest->elems + sbase, src->elems, (is + 1) * sizeof (int));
+ memcpy (dest->elems + sbase, src->elems, (is + 1) * sizeof (Idx));
}
id = dest->nelem - 1;
@@ -1259,7 +1261,7 @@ re_node_set_merge (re_node_set *dest, const re_node_set *src)
{
/* Copy remaining SRC elements. */
memcpy (dest->elems, dest->elems + sbase,
- delta * sizeof (int));
+ delta * sizeof (Idx));
break;
}
}
@@ -1270,38 +1272,33 @@ re_node_set_merge (re_node_set *dest, const re_node_set *src)
/* Insert the new element ELEM to the re_node_set* SET.
SET should not already have ELEM.
- return -1 if an error is occured, return 1 otherwise. */
+ Return true if successful. */
-static int
-internal_function __attribute_warn_unused_result__
-re_node_set_insert (re_node_set *set, int elem)
+static bool
+__attribute_warn_unused_result__
+re_node_set_insert (re_node_set *set, Idx elem)
{
- int idx;
+ Idx idx;
/* In case the set is empty. */
if (set->alloc == 0)
- {
- if (BE (re_node_set_init_1 (set, elem) == REG_NOERROR, 1))
- return 1;
- else
- return -1;
- }
+ return BE (re_node_set_init_1 (set, elem) == REG_NOERROR, 1);
if (BE (set->nelem, 0) == 0)
{
/* We already guaranteed above that set->alloc != 0. */
set->elems[0] = elem;
++set->nelem;
- return 1;
+ return true;
}
/* Realloc if we need. */
if (set->alloc == set->nelem)
{
- int *new_elems;
+ Idx *new_elems;
set->alloc = set->alloc * 2;
- new_elems = re_realloc (set->elems, int, set->alloc);
+ new_elems = re_realloc (set->elems, Idx, set->alloc);
if (BE (new_elems == NULL, 0))
- return -1;
+ return false;
set->elems = new_elems;
}
@@ -1322,56 +1319,56 @@ re_node_set_insert (re_node_set *set, int elem)
/* Insert the new element. */
set->elems[idx] = elem;
++set->nelem;
- return 1;
+ return true;
}
/* Insert the new element ELEM to the re_node_set* SET.
SET should not already have any element greater than or equal to ELEM.
- Return -1 if an error is occured, return 1 otherwise. */
+ Return true if successful. */
-static int
-internal_function __attribute_warn_unused_result__
-re_node_set_insert_last (re_node_set *set, int elem)
+static bool
+__attribute_warn_unused_result__
+re_node_set_insert_last (re_node_set *set, Idx elem)
{
/* Realloc if we need. */
if (set->alloc == set->nelem)
{
- int *new_elems;
+ Idx *new_elems;
set->alloc = (set->alloc + 1) * 2;
- new_elems = re_realloc (set->elems, int, set->alloc);
+ new_elems = re_realloc (set->elems, Idx, set->alloc);
if (BE (new_elems == NULL, 0))
- return -1;
+ return false;
set->elems = new_elems;
}
/* Insert the new element. */
set->elems[set->nelem++] = elem;
- return 1;
+ return true;
}
/* Compare two node sets SET1 and SET2.
- return 1 if SET1 and SET2 are equivalent, return 0 otherwise. */
+ Return true if SET1 and SET2 are equivalent. */
-static int
-internal_function __attribute ((pure))
+static bool
+__attribute__ ((pure))
re_node_set_compare (const re_node_set *set1, const re_node_set *set2)
{
- int i;
+ Idx i;
if (set1 == NULL || set2 == NULL || set1->nelem != set2->nelem)
- return 0;
+ return false;
for (i = set1->nelem ; --i >= 0 ; )
if (set1->elems[i] != set2->elems[i])
- return 0;
- return 1;
+ return false;
+ return true;
}
/* Return (idx + 1) if SET contains the element ELEM, return 0 otherwise. */
-static int
-internal_function __attribute ((pure))
-re_node_set_contains (const re_node_set *set, int elem)
+static Idx
+__attribute__ ((pure))
+re_node_set_contains (const re_node_set *set, Idx elem)
{
- unsigned int idx, right, mid;
+ __re_size_t idx, right, mid;
if (set->nelem <= 0)
return 0;
@@ -1390,8 +1387,7 @@ re_node_set_contains (const re_node_set *set, int elem)
}
static void
-internal_function
-re_node_set_remove_at (re_node_set *set, int idx)
+re_node_set_remove_at (re_node_set *set, Idx idx)
{
if (idx < 0 || idx >= set->nelem)
return;
@@ -1402,38 +1398,42 @@ re_node_set_remove_at (re_node_set *set, int idx)
/* Add the token TOKEN to dfa->nodes, and return the index of the token.
- Or return -1, if an error will be occured. */
+ Or return -1 if an error occurred. */
-static int
-internal_function
+static Idx
re_dfa_add_node (re_dfa_t *dfa, re_token_t token)
{
- int type = token.type;
if (BE (dfa->nodes_len >= dfa->nodes_alloc, 0))
{
size_t new_nodes_alloc = dfa->nodes_alloc * 2;
- int *new_nexts, *new_indices;
+ Idx *new_nexts, *new_indices;
re_node_set *new_edests, *new_eclosures;
re_token_t *new_nodes;
/* Avoid overflows in realloc. */
const size_t max_object_size = MAX (sizeof (re_token_t),
MAX (sizeof (re_node_set),
- sizeof (int)));
- if (BE (SIZE_MAX / max_object_size < new_nodes_alloc, 0))
+ sizeof (Idx)));
+ if (BE (MIN (IDX_MAX, SIZE_MAX / max_object_size) < new_nodes_alloc, 0))
return -1;
new_nodes = re_realloc (dfa->nodes, re_token_t, new_nodes_alloc);
if (BE (new_nodes == NULL, 0))
return -1;
dfa->nodes = new_nodes;
- new_nexts = re_realloc (dfa->nexts, int, new_nodes_alloc);
- new_indices = re_realloc (dfa->org_indices, int, new_nodes_alloc);
+ new_nexts = re_realloc (dfa->nexts, Idx, new_nodes_alloc);
+ new_indices = re_realloc (dfa->org_indices, Idx, new_nodes_alloc);
new_edests = re_realloc (dfa->edests, re_node_set, new_nodes_alloc);
new_eclosures = re_realloc (dfa->eclosures, re_node_set, new_nodes_alloc);
if (BE (new_nexts == NULL || new_indices == NULL
|| new_edests == NULL || new_eclosures == NULL, 0))
- return -1;
+ {
+ re_free (new_nexts);
+ re_free (new_indices);
+ re_free (new_edests);
+ re_free (new_eclosures);
+ return -1;
+ }
dfa->nexts = new_nexts;
dfa->org_indices = new_indices;
dfa->edests = new_edests;
@@ -1444,7 +1444,8 @@ re_dfa_add_node (re_dfa_t *dfa, re_token_t token)
dfa->nodes[dfa->nodes_len].constraint = 0;
#ifdef RE_ENABLE_I18N
dfa->nodes[dfa->nodes_len].accept_mb =
- (type == OP_PERIOD && dfa->mb_cur_max > 1) || type == COMPLEX_BRACKET;
+ ((token.type == OP_PERIOD && dfa->mb_cur_max > 1)
+ || token.type == COMPLEX_BRACKET);
#endif
dfa->nexts[dfa->nodes_len] = -1;
re_node_set_init_empty (dfa->edests + dfa->nodes_len);
@@ -1452,12 +1453,11 @@ re_dfa_add_node (re_dfa_t *dfa, re_token_t token)
return dfa->nodes_len++;
}
-static inline unsigned int
-internal_function
+static re_hashval_t
calc_state_hash (const re_node_set *nodes, unsigned int context)
{
- unsigned int hash = nodes->nelem + context;
- int i;
+ re_hashval_t hash = nodes->nelem + context;
+ Idx i;
for (i = 0 ; i < nodes->nelem ; i++)
hash += nodes->elems[i];
return hash;
@@ -1473,14 +1473,18 @@ calc_state_hash (const re_node_set *nodes, unsigned int context)
optimization. */
static re_dfastate_t *
-internal_function __attribute_warn_unused_result__
+__attribute_warn_unused_result__
re_acquire_state (reg_errcode_t *err, const re_dfa_t *dfa,
const re_node_set *nodes)
{
- unsigned int hash;
+ re_hashval_t hash;
re_dfastate_t *new_state;
struct re_state_table_entry *spot;
- int i;
+ Idx i;
+#if defined GCC_LINT || defined lint
+ /* Suppress bogus uninitialized-variable warnings. */
+ *err = REG_NOERROR;
+#endif
if (BE (nodes->nelem == 0, 0))
{
*err = REG_NOERROR;
@@ -1517,14 +1521,18 @@ re_acquire_state (reg_errcode_t *err, const re_dfa_t *dfa,
optimization. */
static re_dfastate_t *
-internal_function __attribute_warn_unused_result__
+__attribute_warn_unused_result__
re_acquire_state_context (reg_errcode_t *err, const re_dfa_t *dfa,
const re_node_set *nodes, unsigned int context)
{
- unsigned int hash;
+ re_hashval_t hash;
re_dfastate_t *new_state;
struct re_state_table_entry *spot;
- int i;
+ Idx i;
+#if defined GCC_LINT || defined lint
+ /* Suppress bogus uninitialized-variable warnings. */
+ *err = REG_NOERROR;
+#endif
if (nodes->nelem == 0)
{
*err = REG_NOERROR;
@@ -1541,7 +1549,7 @@ re_acquire_state_context (reg_errcode_t *err, const re_dfa_t *dfa,
&& re_node_set_compare (state->entrance_nodes, nodes))
return state;
}
- /* There are no appropriate state in `dfa', create the new one. */
+ /* There are no appropriate state in 'dfa', create the new one. */
new_state = create_cd_newstate (dfa, nodes, context, hash);
if (BE (new_state == NULL, 0))
*err = REG_ESPACE;
@@ -1556,11 +1564,11 @@ re_acquire_state_context (reg_errcode_t *err, const re_dfa_t *dfa,
static reg_errcode_t
__attribute_warn_unused_result__
register_state (const re_dfa_t *dfa, re_dfastate_t *newstate,
- unsigned int hash)
+ re_hashval_t hash)
{
struct re_state_table_entry *spot;
reg_errcode_t err;
- int i;
+ Idx i;
newstate->hash = hash;
err = re_node_set_alloc (&newstate->non_eps_nodes, newstate->nodes.nelem);
@@ -1568,16 +1576,16 @@ register_state (const re_dfa_t *dfa, re_dfastate_t *newstate,
return REG_ESPACE;
for (i = 0; i < newstate->nodes.nelem; i++)
{
- int elem = newstate->nodes.elems[i];
+ Idx elem = newstate->nodes.elems[i];
if (!IS_EPSILON_NODE (dfa->nodes[elem].type))
- if (re_node_set_insert_last (&newstate->non_eps_nodes, elem) < 0)
+ if (! re_node_set_insert_last (&newstate->non_eps_nodes, elem))
return REG_ESPACE;
}
spot = dfa->state_table + (hash & dfa->state_hash_mask);
if (BE (spot->alloc <= spot->num, 0))
{
- int new_alloc = 2 * spot->num + 2;
+ Idx new_alloc = 2 * spot->num + 2;
re_dfastate_t **new_array = re_realloc (spot->array, re_dfastate_t *,
new_alloc);
if (BE (new_array == NULL, 0))
@@ -1605,15 +1613,15 @@ free_state (re_dfastate_t *state)
re_free (state);
}
-/* Create the new state which is independ of contexts.
+/* Create the new state which is independent of contexts.
Return the new state if succeeded, otherwise return NULL. */
static re_dfastate_t *
-internal_function __attribute_warn_unused_result__
+__attribute_warn_unused_result__
create_ci_newstate (const re_dfa_t *dfa, const re_node_set *nodes,
- unsigned int hash)
+ re_hashval_t hash)
{
- int i;
+ Idx i;
reg_errcode_t err;
re_dfastate_t *newstate;
@@ -1659,11 +1667,11 @@ create_ci_newstate (const re_dfa_t *dfa, const re_node_set *nodes,
Return the new state if succeeded, otherwise return NULL. */
static re_dfastate_t *
-internal_function __attribute_warn_unused_result__
+__attribute_warn_unused_result__
create_cd_newstate (const re_dfa_t *dfa, const re_node_set *nodes,
- unsigned int context, unsigned int hash)
+ unsigned int context, re_hashval_t hash)
{
- int i, nctx_nodes = 0;
+ Idx i, nctx_nodes = 0;
reg_errcode_t err;
re_dfastate_t *newstate;
diff --git a/posix/regex_internal.h b/posix/regex_internal.h
index 02e040bd73..3b836ed206 100644
--- a/posix/regex_internal.h
+++ b/posix/regex_internal.h
@@ -1,5 +1,5 @@
/* Extended regular expression matching and search library.
- Copyright (C) 2002-2016 Free Software Foundation, Inc.
+ Copyright (C) 2002-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Isamu Hasegawa <isamu@yamato.ibm.com>.
@@ -15,7 +15,7 @@
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
- <http://www.gnu.org/licenses/>. */
+ <https://www.gnu.org/licenses/>. */
#ifndef _REGEX_INTERNAL_H
#define _REGEX_INTERNAL_H 1
@@ -26,35 +26,78 @@
#include <stdlib.h>
#include <string.h>
-#if defined HAVE_LANGINFO_H || defined HAVE_LANGINFO_CODESET || defined _LIBC
-# include <langinfo.h>
-#endif
-#if defined HAVE_LOCALE_H || defined _LIBC
-# include <locale.h>
+#include <langinfo.h>
+#include <locale.h>
+#include <wchar.h>
+#include <wctype.h>
+#include <stdbool.h>
+#include <stdint.h>
+
+/* Properties of integers. Although Gnulib has intprops.h, glibc does
+ without for now. */
+#ifndef _LIBC
+# include "intprops.h"
+#else
+/* True if the real type T is signed. */
+# define TYPE_SIGNED(t) (! ((t) 0 < (t) -1))
+
+/* True if adding the nonnegative Idx values A and B would overflow.
+ If false, set *R to A + B. A, B, and R may be evaluated more than
+ once, or zero times. Although this is not a full implementation of
+ Gnulib INT_ADD_WRAPV, it is good enough for glibc regex code.
+ FIXME: This implementation is a fragile stopgap, and this file would
+ be simpler and more robust if intprops.h were migrated into glibc. */
+# define INT_ADD_WRAPV(a, b, r) \
+ (IDX_MAX - (a) < (b) ? true : (*(r) = (a) + (b), false))
#endif
-#if defined HAVE_WCHAR_H || defined _LIBC
-# include <wchar.h>
-#endif /* HAVE_WCHAR_H || _LIBC */
-#if defined HAVE_WCTYPE_H || defined _LIBC
-# include <wctype.h>
-#endif /* HAVE_WCTYPE_H || _LIBC */
-#if defined HAVE_STDBOOL_H || defined _LIBC
-# include <stdbool.h>
-#endif /* HAVE_STDBOOL_H || _LIBC */
-#if defined HAVE_STDINT_H || defined _LIBC
-# include <stdint.h>
-#endif /* HAVE_STDINT_H || _LIBC */
-#if defined _LIBC
+
+#ifdef _LIBC
# include <libc-lock.h>
+# define lock_define(name) __libc_lock_define (, name)
+# define lock_init(lock) (__libc_lock_init (lock), 0)
+# define lock_fini(lock) ((void) 0)
+# define lock_lock(lock) __libc_lock_lock (lock)
+# define lock_unlock(lock) __libc_lock_unlock (lock)
+#elif defined GNULIB_LOCK && !defined USE_UNLOCKED_IO
+# include "glthread/lock.h"
+ /* Use gl_lock_define if empty macro arguments are known to work.
+ Otherwise, fall back on less-portable substitutes. */
+# if ((defined __GNUC__ && !defined __STRICT_ANSI__) \
+ || (defined __STDC_VERSION__ && 199901L <= __STDC_VERSION__))
+# define lock_define(name) gl_lock_define (, name)
+# elif USE_POSIX_THREADS
+# define lock_define(name) pthread_mutex_t name;
+# elif USE_PTH_THREADS
+# define lock_define(name) pth_mutex_t name;
+# elif USE_SOLARIS_THREADS
+# define lock_define(name) mutex_t name;
+# elif USE_WINDOWS_THREADS
+# define lock_define(name) gl_lock_t name;
+# else
+# define lock_define(name)
+# endif
+# define lock_init(lock) glthread_lock_init (&(lock))
+# define lock_fini(lock) glthread_lock_destroy (&(lock))
+# define lock_lock(lock) glthread_lock_lock (&(lock))
+# define lock_unlock(lock) glthread_lock_unlock (&(lock))
+#elif defined GNULIB_PTHREAD && !defined USE_UNLOCKED_IO
+# include <pthread.h>
+# define lock_define(name) pthread_mutex_t name;
+# define lock_init(lock) pthread_mutex_init (&(lock), 0)
+# define lock_fini(lock) pthread_mutex_destroy (&(lock))
+# define lock_lock(lock) pthread_mutex_lock (&(lock))
+# define lock_unlock(lock) pthread_mutex_unlock (&(lock))
#else
-# define __libc_lock_define(CLASS,NAME)
-# define __libc_lock_init(NAME) do { } while (0)
-# define __libc_lock_lock(NAME) do { } while (0)
-# define __libc_lock_unlock(NAME) do { } while (0)
+# define lock_define(name)
+# define lock_init(lock) 0
+# define lock_fini(lock) ((void) 0)
+ /* The 'dfa' avoids an "unused variable 'dfa'" warning from GCC. */
+# define lock_lock(lock) ((void) dfa)
+# define lock_unlock(lock) ((void) 0)
#endif
/* In case that the system doesn't have isblank(). */
-#if !defined _LIBC && !defined HAVE_ISBLANK && !defined isblank
+#if !defined _LIBC && ! (defined isblank || (HAVE_ISBLANK && HAVE_DECL_ISBLANK))
# define isblank(ch) ((ch) == ' ' || (ch) == '\t')
#endif
@@ -75,6 +118,7 @@
__dcgettext (_libc_intl_domainname, msgid, LC_MESSAGES)
# endif
#else
+# undef gettext
# define gettext(msgid) (msgid)
#endif
@@ -84,23 +128,17 @@
# define gettext_noop(String) String
#endif
-/* For loser systems without the definition. */
-#ifndef SIZE_MAX
-# define SIZE_MAX ((size_t) -1)
-#endif
-
#if (defined MB_CUR_MAX && HAVE_WCTYPE_H && HAVE_ISWCTYPE) || _LIBC
# define RE_ENABLE_I18N
#endif
-#if __GNUC__ >= 3
-# define BE(expr, val) __builtin_expect (expr, val)
-#else
-# define BE(expr, val) (expr)
-#endif
+#define BE(expr, val) __builtin_expect (expr, val)
-/* Number of single byte character. */
-#define SBC_MAX 256
+/* Number of ASCII characters. */
+#define ASCII_CHARS 0x80
+
+/* Number of single byte characters. */
+#define SBC_MAX (UCHAR_MAX + 1)
#define COLL_ELEM_LEN_MAX 8
@@ -110,11 +148,15 @@
/* Rename to standard API for using out of glibc. */
#ifndef _LIBC
+# undef __wctype
+# undef __iswctype
# define __wctype wctype
+# define __iswalnum iswalnum
# define __iswctype iswctype
+# define __towlower towlower
+# define __towupper towupper
# define __btowc btowc
# define __mbrtowc mbrtowc
-# define __mempcpy mempcpy
# define __wcrtomb wcrtomb
# define __regfree regfree
# define attribute_hidden
@@ -124,32 +166,70 @@
# define __attribute__(arg)
#endif
-extern const char __re_error_msgid[] attribute_hidden;
-extern const size_t __re_error_msgid_idx[] attribute_hidden;
+#ifndef SSIZE_MAX
+# define SSIZE_MAX ((ssize_t) (SIZE_MAX / 2))
+#endif
+
+/* The type of indexes into strings. This is signed, not size_t,
+ since the API requires indexes to fit in regoff_t anyway, and using
+ signed integers makes the code a bit smaller and presumably faster.
+ The traditional GNU regex implementation uses int for indexes.
+ The POSIX-compatible implementation uses a possibly-wider type.
+ The name 'Idx' is three letters to minimize the hassle of
+ reindenting a lot of regex code that formerly used 'int'. */
+typedef regoff_t Idx;
+#ifdef _REGEX_LARGE_OFFSETS
+# define IDX_MAX SSIZE_MAX
+#else
+# define IDX_MAX INT_MAX
+#endif
+
+/* A hash value, suitable for computing hash tables. */
+typedef __re_size_t re_hashval_t;
/* An integer used to represent a set of bits. It must be unsigned,
and must be at least as wide as unsigned int. */
typedef unsigned long int bitset_word_t;
/* All bits set in a bitset_word_t. */
#define BITSET_WORD_MAX ULONG_MAX
-/* Number of bits in a bitset_word_t. */
-#define BITSET_WORD_BITS (sizeof (bitset_word_t) * CHAR_BIT)
-/* Number of bitset_word_t in a bit_set. */
-#define BITSET_WORDS (SBC_MAX / BITSET_WORD_BITS)
+
+/* Number of bits in a bitset_word_t. For portability to hosts with
+ padding bits, do not use '(sizeof (bitset_word_t) * CHAR_BIT)';
+ instead, deduce it directly from BITSET_WORD_MAX. Avoid
+ greater-than-32-bit integers and unconditional shifts by more than
+ 31 bits, as they're not portable. */
+#if BITSET_WORD_MAX == 0xffffffffUL
+# define BITSET_WORD_BITS 32
+#elif BITSET_WORD_MAX >> 31 >> 4 == 1
+# define BITSET_WORD_BITS 36
+#elif BITSET_WORD_MAX >> 31 >> 16 == 1
+# define BITSET_WORD_BITS 48
+#elif BITSET_WORD_MAX >> 31 >> 28 == 1
+# define BITSET_WORD_BITS 60
+#elif BITSET_WORD_MAX >> 31 >> 31 >> 1 == 1
+# define BITSET_WORD_BITS 64
+#elif BITSET_WORD_MAX >> 31 >> 31 >> 9 == 1
+# define BITSET_WORD_BITS 72
+#elif BITSET_WORD_MAX >> 31 >> 31 >> 31 >> 31 >> 3 == 1
+# define BITSET_WORD_BITS 128
+#elif BITSET_WORD_MAX >> 31 >> 31 >> 31 >> 31 >> 31 >> 31 >> 31 >> 31 >> 7 == 1
+# define BITSET_WORD_BITS 256
+#elif BITSET_WORD_MAX >> 31 >> 31 >> 31 >> 31 >> 31 >> 31 >> 31 >> 31 >> 7 > 1
+# define BITSET_WORD_BITS 257 /* any value > SBC_MAX will do here */
+# if BITSET_WORD_BITS <= SBC_MAX
+# error "Invalid SBC_MAX"
+# endif
+#else
+# error "Add case for new bitset_word_t size"
+#endif
+
+/* Number of bitset_word_t values in a bitset_t. */
+#define BITSET_WORDS ((SBC_MAX + BITSET_WORD_BITS - 1) / BITSET_WORD_BITS)
+
typedef bitset_word_t bitset_t[BITSET_WORDS];
typedef bitset_word_t *re_bitset_ptr_t;
typedef const bitset_word_t *re_const_bitset_ptr_t;
-#define bitset_set(set,i) \
- (set[i / BITSET_WORD_BITS] |= (bitset_word_t) 1 << i % BITSET_WORD_BITS)
-#define bitset_clear(set,i) \
- (set[i / BITSET_WORD_BITS] &= ~((bitset_word_t) 1 << i % BITSET_WORD_BITS))
-#define bitset_contain(set,i) \
- (set[i / BITSET_WORD_BITS] & ((bitset_word_t) 1 << i % BITSET_WORD_BITS))
-#define bitset_empty(set) memset (set, '\0', sizeof (bitset_t))
-#define bitset_set_all(set) memset (set, '\xff', sizeof (bitset_t))
-#define bitset_copy(dest,src) memcpy (dest, src, sizeof (bitset_t))
-
#define PREV_WORD_CONSTRAINT 0x0001
#define PREV_NOTWORD_CONSTRAINT 0x0002
#define NEXT_WORD_CONSTRAINT 0x0004
@@ -177,9 +257,9 @@ typedef enum
typedef struct
{
- int alloc;
- int nelem;
- int *elems;
+ Idx alloc;
+ Idx nelem;
+ Idx *elems;
} re_node_set;
typedef enum
@@ -265,19 +345,19 @@ typedef struct
unsigned int non_match : 1;
/* # of multibyte characters. */
- int nmbchars;
+ Idx nmbchars;
/* # of collating symbols. */
- int ncoll_syms;
+ Idx ncoll_syms;
/* # of equivalence classes. */
- int nequiv_classes;
+ Idx nequiv_classes;
/* # of range expressions. */
- int nranges;
+ Idx nranges;
/* # of character classes. */
- int nchar_classes;
+ Idx nchar_classes;
} re_charset_t;
#endif /* RE_ENABLE_I18N */
@@ -290,10 +370,10 @@ typedef struct
#ifdef RE_ENABLE_I18N
re_charset_t *mbcset; /* for COMPLEX_BRACKET */
#endif /* RE_ENABLE_I18N */
- int idx; /* for BACK_REF */
+ Idx idx; /* for BACK_REF */
re_context_type ctx_type; /* for ANCHOR */
} opr;
-#if __GNUC__ >= 2
+#if __GNUC__ >= 2 && !defined __STRICT_ANSI__
re_token_type_t type : 8;
#else
re_token_type_t type;
@@ -324,30 +404,30 @@ struct re_string_t
#ifdef RE_ENABLE_I18N
/* Store the wide character string which is corresponding to MBS. */
wint_t *wcs;
- int *offsets;
+ Idx *offsets;
mbstate_t cur_state;
#endif
/* Index in RAW_MBS. Each character mbs[i] corresponds to
raw_mbs[raw_mbs_idx + i]. */
- int raw_mbs_idx;
+ Idx raw_mbs_idx;
/* The length of the valid characters in the buffers. */
- int valid_len;
+ Idx valid_len;
/* The corresponding number of bytes in raw_mbs array. */
- int valid_raw_len;
+ Idx valid_raw_len;
/* The length of the buffers MBS and WCS. */
- int bufs_len;
+ Idx bufs_len;
/* The index in MBS, which is updated by re_string_fetch_byte. */
- int cur_idx;
+ Idx cur_idx;
/* length of RAW_MBS array. */
- int raw_len;
+ Idx raw_len;
/* This is RAW_LEN - RAW_MBS_IDX + VALID_LEN - VALID_RAW_LEN. */
- int len;
+ Idx len;
/* End of the buffer may be shorter than its length in the cases such
as re_match_2, re_search_2. Then, we use STOP for end of the buffer
instead of LEN. */
- int raw_stop;
+ Idx raw_stop;
/* This is RAW_STOP - RAW_MBS_IDX adjusted through OFFSETS. */
- int stop;
+ Idx stop;
/* The context of mbs[0]. We store the context independently, since
the context of mbs[0] may be different from raw_mbs[0], which is
@@ -357,7 +437,7 @@ struct re_string_t
RE_TRANSLATE_TYPE trans;
/* Copy of re_dfa_t's word_char. */
re_const_bitset_ptr_t word_char;
- /* 1 if REG_ICASE. */
+ /* true if REG_ICASE. */
unsigned char icase;
unsigned char is_utf8;
unsigned char map_notascii;
@@ -374,28 +454,9 @@ struct re_dfa_t;
typedef struct re_dfa_t re_dfa_t;
#ifndef _LIBC
-# ifdef __i386__
-# define internal_function __attribute__ ((regparm (3), stdcall))
-# else
-# define internal_function
-# endif
+# define IS_IN(libc) false
#endif
-#if IS_IN (libc)
-static reg_errcode_t re_string_realloc_buffers (re_string_t *pstr,
- int new_buf_len)
- internal_function;
-# ifdef RE_ENABLE_I18N
-static void build_wcs_buffer (re_string_t *pstr) internal_function;
-static reg_errcode_t build_wcs_upper_buffer (re_string_t *pstr)
- internal_function;
-# endif /* RE_ENABLE_I18N */
-static void build_upper_buffer (re_string_t *pstr) internal_function;
-static void re_string_translate_buffer (re_string_t *pstr) internal_function;
-static unsigned int re_string_context_at (const re_string_t *input, int idx,
- int eflags)
- internal_function __attribute__ ((pure));
-#endif
#define re_string_peek_byte(pstr, offset) \
((pstr)->mbs[(pstr)->cur_idx + offset])
#define re_string_fetch_byte(pstr) \
@@ -413,7 +474,9 @@ static unsigned int re_string_context_at (const re_string_t *input, int idx,
#define re_string_skip_bytes(pstr,idx) ((pstr)->cur_idx += (idx))
#define re_string_set_index(pstr,idx) ((pstr)->cur_idx = (idx))
-#include <alloca.h>
+#if defined _LIBC || HAVE_ALLOCA
+# include <alloca.h>
+#endif
#ifndef _LIBC
# if HAVE_ALLOCA
@@ -425,9 +488,24 @@ static unsigned int re_string_context_at (const re_string_t *input, int idx,
# else
/* alloca is implemented with malloc, so just use malloc. */
# define __libc_use_alloca(n) 0
+# undef alloca
+# define alloca(n) malloc (n)
# endif
#endif
+#ifdef _LIBC
+# define MALLOC_0_IS_NONNULL 1
+#elif !defined MALLOC_0_IS_NONNULL
+# define MALLOC_0_IS_NONNULL 0
+#endif
+
+#ifndef MAX
+# define MAX(a,b) ((a) < (b) ? (b) : (a))
+#endif
+#ifndef MIN
+# define MIN(a,b) ((a) < (b) ? (a) : (b))
+#endif
+
#define re_malloc(t,n) ((t *) malloc ((n) * sizeof (t)))
#define re_realloc(p,t,n) ((t *) realloc (p, (n) * sizeof (t)))
#define re_free(p) free (p)
@@ -442,9 +520,9 @@ struct bin_tree_t
re_token_t token;
- /* `node_idx' is the index in dfa->nodes, if `type' == 0.
- Otherwise `type' indicate the type of this node. */
- int node_idx;
+ /* 'node_idx' is the index in dfa->nodes, if 'type' == 0.
+ Otherwise 'type' indicate the type of this node. */
+ Idx node_idx;
};
typedef struct bin_tree_t bin_tree_t;
@@ -488,7 +566,7 @@ typedef struct bin_tree_storage_t bin_tree_storage_t;
struct re_dfastate_t
{
- unsigned int hash;
+ re_hashval_t hash;
re_node_set nodes;
re_node_set non_eps_nodes;
re_node_set inveclosure;
@@ -496,9 +574,9 @@ struct re_dfastate_t
struct re_dfastate_t **trtable, **word_trtable;
unsigned int context : 4;
unsigned int halt : 1;
- /* If this state can accept `multi byte'.
+ /* If this state can accept "multi byte".
Note that we refer to multibyte characters, and multi character
- collating elements as `multi byte'. */
+ collating elements as "multi byte". */
unsigned int accept_mb : 1;
/* If this state has backreference node(s). */
unsigned int has_backref : 1;
@@ -508,8 +586,8 @@ typedef struct re_dfastate_t re_dfastate_t;
struct re_state_table_entry
{
- int num;
- int alloc;
+ Idx num;
+ Idx alloc;
re_dfastate_t **array;
};
@@ -517,8 +595,8 @@ struct re_state_table_entry
typedef struct
{
- int next_idx;
- int alloc;
+ Idx next_idx;
+ Idx alloc;
re_dfastate_t **array;
} state_array_t;
@@ -526,8 +604,8 @@ typedef struct
typedef struct
{
- int node;
- int str_idx; /* The position NODE match at. */
+ Idx node;
+ Idx str_idx; /* The position NODE match at. */
state_array_t path;
} re_sub_match_last_t;
@@ -537,20 +615,20 @@ typedef struct
typedef struct
{
- int str_idx;
- int node;
+ Idx str_idx;
+ Idx node;
state_array_t *path;
- int alasts; /* Allocation size of LASTS. */
- int nlasts; /* The number of LASTS. */
+ Idx alasts; /* Allocation size of LASTS. */
+ Idx nlasts; /* The number of LASTS. */
re_sub_match_last_t **lasts;
} re_sub_match_top_t;
struct re_backref_cache_entry
{
- int node;
- int str_idx;
- int subexp_from;
- int subexp_to;
+ Idx node;
+ Idx str_idx;
+ Idx subexp_from;
+ Idx subexp_to;
char more;
char unused;
unsigned short int eps_reachable_subexps_map;
@@ -568,18 +646,18 @@ typedef struct
/* EFLAGS of the argument of regexec. */
int eflags;
/* Where the matching ends. */
- int match_last;
- int last_node;
+ Idx match_last;
+ Idx last_node;
/* The state log used by the matcher. */
re_dfastate_t **state_log;
- int state_log_top;
+ Idx state_log_top;
/* Back reference cache. */
- int nbkref_ents;
- int abkref_ents;
+ Idx nbkref_ents;
+ Idx abkref_ents;
struct re_backref_cache_entry *bkref_ents;
int max_mb_elem_len;
- int nsub_tops;
- int asub_tops;
+ Idx nsub_tops;
+ Idx asub_tops;
re_sub_match_top_t **sub_tops;
} re_match_context_t;
@@ -587,23 +665,23 @@ typedef struct
{
re_dfastate_t **sifted_states;
re_dfastate_t **limited_states;
- int last_node;
- int last_str_idx;
+ Idx last_node;
+ Idx last_str_idx;
re_node_set limits;
} re_sift_context_t;
struct re_fail_stack_ent_t
{
- int idx;
- int node;
+ Idx idx;
+ Idx node;
regmatch_t *regs;
re_node_set eps_via_nodes;
};
struct re_fail_stack_t
{
- int num;
- int alloc;
+ Idx num;
+ Idx alloc;
struct re_fail_stack_ent_t *stack;
};
@@ -612,8 +690,8 @@ struct re_dfa_t
re_token_t *nodes;
size_t nodes_alloc;
size_t nodes_len;
- int *nexts;
- int *org_indices;
+ Idx *nexts;
+ Idx *org_indices;
re_node_set *edests;
re_node_set *eclosures;
re_node_set *inveclosures;
@@ -627,10 +705,10 @@ struct re_dfa_t
re_bitset_ptr_t sb_char;
int str_tree_storage_idx;
- /* number of subexpressions `re_nsub' is in regex_t. */
- unsigned int state_hash_mask;
- int init_node;
- int nbackref; /* The number of backreference in this dfa. */
+ /* number of subexpressions 're_nsub' is in regex_t. */
+ re_hashval_t state_hash_mask;
+ Idx init_node;
+ Idx nbackref; /* The number of backreference in this dfa. */
/* Bitmap expressing which backreference is used. */
bitset_word_t used_bkref_map;
@@ -647,11 +725,11 @@ struct re_dfa_t
int mb_cur_max;
bitset_t word_char;
reg_syntax_t syntax;
- int *subexp_map;
+ Idx *subexp_map;
#ifdef DEBUG
char* re_str;
#endif
- __libc_lock_define (, lock)
+ lock_define (lock)
};
#define re_node_set_init_empty(set) memset (set, '\0', sizeof (re_node_set))
@@ -682,16 +760,60 @@ typedef struct
} bracket_elem_t;
-/* Inline functions for bitset operation. */
-static void __attribute__ ((unused))
+/* Functions for bitset_t operation. */
+
+static inline void
+bitset_set (bitset_t set, Idx i)
+{
+ set[i / BITSET_WORD_BITS] |= (bitset_word_t) 1 << i % BITSET_WORD_BITS;
+}
+
+static inline void
+bitset_clear (bitset_t set, Idx i)
+{
+ set[i / BITSET_WORD_BITS] &= ~ ((bitset_word_t) 1 << i % BITSET_WORD_BITS);
+}
+
+static inline bool
+bitset_contain (const bitset_t set, Idx i)
+{
+ return (set[i / BITSET_WORD_BITS] >> i % BITSET_WORD_BITS) & 1;
+}
+
+static inline void
+bitset_empty (bitset_t set)
+{
+ memset (set, '\0', sizeof (bitset_t));
+}
+
+static inline void
+bitset_set_all (bitset_t set)
+{
+ memset (set, -1, sizeof (bitset_word_t) * (SBC_MAX / BITSET_WORD_BITS));
+ if (SBC_MAX % BITSET_WORD_BITS != 0)
+ set[BITSET_WORDS - 1] =
+ ((bitset_word_t) 1 << SBC_MAX % BITSET_WORD_BITS) - 1;
+}
+
+static inline void
+bitset_copy (bitset_t dest, const bitset_t src)
+{
+ memcpy (dest, src, sizeof (bitset_t));
+}
+
+static inline void
bitset_not (bitset_t set)
{
int bitset_i;
- for (bitset_i = 0; bitset_i < BITSET_WORDS; ++bitset_i)
+ for (bitset_i = 0; bitset_i < SBC_MAX / BITSET_WORD_BITS; ++bitset_i)
set[bitset_i] = ~set[bitset_i];
+ if (SBC_MAX % BITSET_WORD_BITS != 0)
+ set[BITSET_WORDS - 1] =
+ ((((bitset_word_t) 1 << SBC_MAX % BITSET_WORD_BITS) - 1)
+ & ~set[BITSET_WORDS - 1]);
}
-static void __attribute__ ((unused))
+static inline void
bitset_merge (bitset_t dest, const bitset_t src)
{
int bitset_i;
@@ -699,7 +821,7 @@ bitset_merge (bitset_t dest, const bitset_t src)
dest[bitset_i] |= src[bitset_i];
}
-static void __attribute__ ((unused))
+static inline void
bitset_mask (bitset_t dest, const bitset_t src)
{
int bitset_i;
@@ -708,10 +830,10 @@ bitset_mask (bitset_t dest, const bitset_t src)
}
#ifdef RE_ENABLE_I18N
-/* Inline functions for re_string. */
+/* Functions for re_string. */
static int
-internal_function __attribute__ ((pure, unused))
-re_string_char_size_at (const re_string_t *pstr, int idx)
+__attribute__ ((pure, unused))
+re_string_char_size_at (const re_string_t *pstr, Idx idx)
{
int byte_idx;
if (pstr->mb_cur_max == 1)
@@ -723,24 +845,23 @@ re_string_char_size_at (const re_string_t *pstr, int idx)
}
static wint_t
-internal_function __attribute__ ((pure, unused))
-re_string_wchar_at (const re_string_t *pstr, int idx)
+__attribute__ ((pure, unused))
+re_string_wchar_at (const re_string_t *pstr, Idx idx)
{
if (pstr->mb_cur_max == 1)
return (wint_t) pstr->mbs[idx];
return (wint_t) pstr->wcs[idx];
}
-# if IS_IN (libc)
-# ifdef _LIBC
-# include <locale/weight.h>
-# endif
+# ifdef _LIBC
+# include <locale/weight.h>
+# endif
static int
-internal_function __attribute__ ((pure, unused))
-re_string_elem_size_at (const re_string_t *pstr, int idx)
+__attribute__ ((pure, unused))
+re_string_elem_size_at (const re_string_t *pstr, Idx idx)
{
-# ifdef _LIBC
+# ifdef _LIBC
const unsigned char *p, *extra;
const int32_t *table, *indirect;
uint_fast32_t nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
@@ -757,10 +878,34 @@ re_string_elem_size_at (const re_string_t *pstr, int idx)
return p - pstr->mbs - idx;
}
else
-# endif /* _LIBC */
+# endif /* _LIBC */
return 1;
}
-# endif
#endif /* RE_ENABLE_I18N */
+#ifndef __GNUC_PREREQ
+# if defined __GNUC__ && defined __GNUC_MINOR__
+# define __GNUC_PREREQ(maj, min) \
+ ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
+# else
+# define __GNUC_PREREQ(maj, min) 0
+# endif
+#endif
+
+#if __GNUC_PREREQ (3,4)
+# undef __attribute_warn_unused_result__
+# define __attribute_warn_unused_result__ \
+ __attribute__ ((__warn_unused_result__))
+#else
+# define __attribute_warn_unused_result__ /* empty */
+#endif
+
+#ifndef FALLTHROUGH
+# if __GNUC__ < 7
+# define FALLTHROUGH ((void) 0)
+# else
+# define FALLTHROUGH __attribute__ ((__fallthrough__))
+# endif
+#endif
+
#endif /* _REGEX_INTERNAL_H */
diff --git a/posix/regexec.c b/posix/regexec.c
index ec46c3a514..73644c2341 100644
--- a/posix/regexec.c
+++ b/posix/regexec.c
@@ -1,5 +1,5 @@
/* Extended regular expression matching and search library.
- Copyright (C) 2002-2016 Free Software Foundation, Inc.
+ Copyright (C) 2002-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Isamu Hasegawa <isamu@yamato.ibm.com>.
@@ -15,192 +15,162 @@
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
- <http://www.gnu.org/licenses/>. */
-
-#include <stdint.h>
+ <https://www.gnu.org/licenses/>. */
static reg_errcode_t match_ctx_init (re_match_context_t *cache, int eflags,
- int n) internal_function;
-static void match_ctx_clean (re_match_context_t *mctx) internal_function;
-static void match_ctx_free (re_match_context_t *cache) internal_function;
-static reg_errcode_t match_ctx_add_entry (re_match_context_t *cache, int node,
- int str_idx, int from, int to)
- internal_function;
-static int search_cur_bkref_entry (const re_match_context_t *mctx, int str_idx)
- internal_function;
-static reg_errcode_t match_ctx_add_subtop (re_match_context_t *mctx, int node,
- int str_idx) internal_function;
+ Idx n);
+static void match_ctx_clean (re_match_context_t *mctx);
+static void match_ctx_free (re_match_context_t *cache);
+static reg_errcode_t match_ctx_add_entry (re_match_context_t *cache, Idx node,
+ Idx str_idx, Idx from, Idx to);
+static Idx search_cur_bkref_entry (const re_match_context_t *mctx, Idx str_idx);
+static reg_errcode_t match_ctx_add_subtop (re_match_context_t *mctx, Idx node,
+ Idx str_idx);
static re_sub_match_last_t * match_ctx_add_sublast (re_sub_match_top_t *subtop,
- int node, int str_idx)
- internal_function;
+ Idx node, Idx str_idx);
static void sift_ctx_init (re_sift_context_t *sctx, re_dfastate_t **sifted_sts,
- re_dfastate_t **limited_sts, int last_node,
- int last_str_idx)
- internal_function;
+ re_dfastate_t **limited_sts, Idx last_node,
+ Idx last_str_idx);
static reg_errcode_t re_search_internal (const regex_t *preg,
- const char *string, int length,
- int start, int range, int stop,
+ const char *string, Idx length,
+ Idx start, Idx last_start, Idx stop,
size_t nmatch, regmatch_t pmatch[],
- int eflags) internal_function;
-static int re_search_2_stub (struct re_pattern_buffer *bufp,
- const char *string1, int length1,
- const char *string2, int length2,
- int start, int range, struct re_registers *regs,
- int stop, int ret_len) internal_function;
-static int re_search_stub (struct re_pattern_buffer *bufp,
- const char *string, int length, int start,
- int range, int stop, struct re_registers *regs,
- int ret_len) internal_function;
+ int eflags);
+static regoff_t re_search_2_stub (struct re_pattern_buffer *bufp,
+ const char *string1, Idx length1,
+ const char *string2, Idx length2,
+ Idx start, regoff_t range,
+ struct re_registers *regs,
+ Idx stop, bool ret_len);
+static regoff_t re_search_stub (struct re_pattern_buffer *bufp,
+ const char *string, Idx length, Idx start,
+ regoff_t range, Idx stop,
+ struct re_registers *regs,
+ bool ret_len);
static unsigned re_copy_regs (struct re_registers *regs, regmatch_t *pmatch,
- int nregs, int regs_allocated) internal_function;
-static reg_errcode_t prune_impossible_nodes (re_match_context_t *mctx)
- internal_function;
-static int check_matching (re_match_context_t *mctx, int fl_longest_match,
- int *p_match_first) internal_function;
-static int check_halt_state_context (const re_match_context_t *mctx,
- const re_dfastate_t *state, int idx)
- internal_function;
+ Idx nregs, int regs_allocated);
+static reg_errcode_t prune_impossible_nodes (re_match_context_t *mctx);
+static Idx check_matching (re_match_context_t *mctx, bool fl_longest_match,
+ Idx *p_match_first);
+static Idx check_halt_state_context (const re_match_context_t *mctx,
+ const re_dfastate_t *state, Idx idx);
static void update_regs (const re_dfa_t *dfa, regmatch_t *pmatch,
- regmatch_t *prev_idx_match, int cur_node,
- int cur_idx, int nmatch) internal_function;
+ regmatch_t *prev_idx_match, Idx cur_node,
+ Idx cur_idx, Idx nmatch);
static reg_errcode_t push_fail_stack (struct re_fail_stack_t *fs,
- int str_idx, int dest_node, int nregs,
+ Idx str_idx, Idx dest_node, Idx nregs,
regmatch_t *regs,
- re_node_set *eps_via_nodes)
- internal_function;
+ re_node_set *eps_via_nodes);
static reg_errcode_t set_regs (const regex_t *preg,
const re_match_context_t *mctx,
size_t nmatch, regmatch_t *pmatch,
- int fl_backtrack) internal_function;
-static reg_errcode_t free_fail_stack_return (struct re_fail_stack_t *fs)
- internal_function;
+ bool fl_backtrack);
+static reg_errcode_t free_fail_stack_return (struct re_fail_stack_t *fs);
#ifdef RE_ENABLE_I18N
static int sift_states_iter_mb (const re_match_context_t *mctx,
re_sift_context_t *sctx,
- int node_idx, int str_idx, int max_str_idx)
- internal_function;
+ Idx node_idx, Idx str_idx, Idx max_str_idx);
#endif /* RE_ENABLE_I18N */
static reg_errcode_t sift_states_backward (const re_match_context_t *mctx,
- re_sift_context_t *sctx)
- internal_function;
+ re_sift_context_t *sctx);
static reg_errcode_t build_sifted_states (const re_match_context_t *mctx,
- re_sift_context_t *sctx, int str_idx,
- re_node_set *cur_dest)
- internal_function;
+ re_sift_context_t *sctx, Idx str_idx,
+ re_node_set *cur_dest);
static reg_errcode_t update_cur_sifted_state (const re_match_context_t *mctx,
re_sift_context_t *sctx,
- int str_idx,
- re_node_set *dest_nodes)
- internal_function;
+ Idx str_idx,
+ re_node_set *dest_nodes);
static reg_errcode_t add_epsilon_src_nodes (const re_dfa_t *dfa,
re_node_set *dest_nodes,
- const re_node_set *candidates)
- internal_function;
-static int check_dst_limits (const re_match_context_t *mctx,
- re_node_set *limits,
- int dst_node, int dst_idx, int src_node,
- int src_idx) internal_function;
+ const re_node_set *candidates);
+static bool check_dst_limits (const re_match_context_t *mctx,
+ const re_node_set *limits,
+ Idx dst_node, Idx dst_idx, Idx src_node,
+ Idx src_idx);
static int check_dst_limits_calc_pos_1 (const re_match_context_t *mctx,
- int boundaries, int subexp_idx,
- int from_node, int bkref_idx)
- internal_function;
+ int boundaries, Idx subexp_idx,
+ Idx from_node, Idx bkref_idx);
static int check_dst_limits_calc_pos (const re_match_context_t *mctx,
- int limit, int subexp_idx,
- int node, int str_idx,
- int bkref_idx) internal_function;
+ Idx limit, Idx subexp_idx,
+ Idx node, Idx str_idx,
+ Idx bkref_idx);
static reg_errcode_t check_subexp_limits (const re_dfa_t *dfa,
re_node_set *dest_nodes,
const re_node_set *candidates,
re_node_set *limits,
struct re_backref_cache_entry *bkref_ents,
- int str_idx) internal_function;
+ Idx str_idx);
static reg_errcode_t sift_states_bkref (const re_match_context_t *mctx,
re_sift_context_t *sctx,
- int str_idx, const re_node_set *candidates)
- internal_function;
+ Idx str_idx, const re_node_set *candidates);
static reg_errcode_t merge_state_array (const re_dfa_t *dfa,
re_dfastate_t **dst,
- re_dfastate_t **src, int num)
- internal_function;
+ re_dfastate_t **src, Idx num);
static re_dfastate_t *find_recover_state (reg_errcode_t *err,
- re_match_context_t *mctx) internal_function;
+ re_match_context_t *mctx);
static re_dfastate_t *transit_state (reg_errcode_t *err,
re_match_context_t *mctx,
- re_dfastate_t *state) internal_function;
+ re_dfastate_t *state);
static re_dfastate_t *merge_state_with_log (reg_errcode_t *err,
re_match_context_t *mctx,
- re_dfastate_t *next_state)
- internal_function;
+ re_dfastate_t *next_state);
static reg_errcode_t check_subexp_matching_top (re_match_context_t *mctx,
re_node_set *cur_nodes,
- int str_idx) internal_function;
+ Idx str_idx);
#if 0
static re_dfastate_t *transit_state_sb (reg_errcode_t *err,
re_match_context_t *mctx,
- re_dfastate_t *pstate)
- internal_function;
+ re_dfastate_t *pstate);
#endif
#ifdef RE_ENABLE_I18N
static reg_errcode_t transit_state_mb (re_match_context_t *mctx,
- re_dfastate_t *pstate)
- internal_function;
+ re_dfastate_t *pstate);
#endif /* RE_ENABLE_I18N */
static reg_errcode_t transit_state_bkref (re_match_context_t *mctx,
- const re_node_set *nodes)
- internal_function;
+ const re_node_set *nodes);
static reg_errcode_t get_subexp (re_match_context_t *mctx,
- int bkref_node, int bkref_str_idx)
- internal_function;
+ Idx bkref_node, Idx bkref_str_idx);
static reg_errcode_t get_subexp_sub (re_match_context_t *mctx,
const re_sub_match_top_t *sub_top,
re_sub_match_last_t *sub_last,
- int bkref_node, int bkref_str)
- internal_function;
-static int find_subexp_node (const re_dfa_t *dfa, const re_node_set *nodes,
- int subexp_idx, int type) internal_function;
+ Idx bkref_node, Idx bkref_str);
+static Idx find_subexp_node (const re_dfa_t *dfa, const re_node_set *nodes,
+ Idx subexp_idx, int type);
static reg_errcode_t check_arrival (re_match_context_t *mctx,
- state_array_t *path, int top_node,
- int top_str, int last_node, int last_str,
- int type) internal_function;
+ state_array_t *path, Idx top_node,
+ Idx top_str, Idx last_node, Idx last_str,
+ int type);
static reg_errcode_t check_arrival_add_next_nodes (re_match_context_t *mctx,
- int str_idx,
+ Idx str_idx,
re_node_set *cur_nodes,
- re_node_set *next_nodes)
- internal_function;
+ re_node_set *next_nodes);
static reg_errcode_t check_arrival_expand_ecl (const re_dfa_t *dfa,
re_node_set *cur_nodes,
- int ex_subexp, int type)
- internal_function;
+ Idx ex_subexp, int type);
static reg_errcode_t check_arrival_expand_ecl_sub (const re_dfa_t *dfa,
re_node_set *dst_nodes,
- int target, int ex_subexp,
- int type) internal_function;
+ Idx target, Idx ex_subexp,
+ int type);
static reg_errcode_t expand_bkref_cache (re_match_context_t *mctx,
- re_node_set *cur_nodes, int cur_str,
- int subexp_num, int type)
- internal_function;
-static int build_trtable (const re_dfa_t *dfa,
- re_dfastate_t *state) internal_function;
+ re_node_set *cur_nodes, Idx cur_str,
+ Idx subexp_num, int type);
+static bool build_trtable (const re_dfa_t *dfa, re_dfastate_t *state);
#ifdef RE_ENABLE_I18N
-static int check_node_accept_bytes (const re_dfa_t *dfa, int node_idx,
- const re_string_t *input, int idx)
- internal_function;
+static int check_node_accept_bytes (const re_dfa_t *dfa, Idx node_idx,
+ const re_string_t *input, Idx idx);
# ifdef _LIBC
static unsigned int find_collation_sequence_value (const unsigned char *mbs,
- size_t name_len)
- internal_function;
+ size_t name_len);
# endif /* _LIBC */
#endif /* RE_ENABLE_I18N */
-static int group_nodes_into_DFAstates (const re_dfa_t *dfa,
+static Idx group_nodes_into_DFAstates (const re_dfa_t *dfa,
const re_dfastate_t *state,
re_node_set *states_node,
- bitset_t *states_ch) internal_function;
-static int check_node_accept (const re_match_context_t *mctx,
- const re_token_t *node, int idx)
- internal_function;
-static reg_errcode_t extend_buffers (re_match_context_t *mctx, int min_len)
- internal_function;
+ bitset_t *states_ch);
+static bool check_node_accept (const re_match_context_t *mctx,
+ const re_token_t *node, Idx idx);
+static reg_errcode_t extend_buffers (re_match_context_t *mctx, int min_len);
/* Entry point for POSIX code. */
@@ -208,23 +178,23 @@ static reg_errcode_t extend_buffers (re_match_context_t *mctx, int min_len)
string STRING.
If NMATCH is zero or REG_NOSUB was set in the cflags argument to
- `regcomp', we ignore PMATCH. Otherwise, we assume PMATCH has at
+ 'regcomp', we ignore PMATCH. Otherwise, we assume PMATCH has at
least NMATCH elements, and we set them to the offsets of the
corresponding matched substrings.
- EFLAGS specifies `execution flags' which affect matching: if
+ EFLAGS specifies "execution flags" which affect matching: if
REG_NOTBOL is set, then ^ does not match at the beginning of the
string; if REG_NOTEOL is set, then $ does not match at the end.
We return 0 if we find a match and REG_NOMATCH if not. */
int
-regexec (const regex_t *__restrict preg, const char *__restrict string,
+regexec (const regex_t *_Restrict_ preg, const char *_Restrict_ string,
size_t nmatch, regmatch_t pmatch[], int eflags)
{
reg_errcode_t err;
- int start, length;
- re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
+ Idx start, length;
+ re_dfa_t *dfa = preg->buffer;
if (eflags & ~(REG_NOTBOL | REG_NOTEOL | REG_STARTEND))
return REG_BADPAT;
@@ -240,18 +210,20 @@ regexec (const regex_t *__restrict preg, const char *__restrict string,
length = strlen (string);
}
- __libc_lock_lock (dfa->lock);
+ lock_lock (dfa->lock);
if (preg->no_sub)
- err = re_search_internal (preg, string, length, start, length - start,
+ err = re_search_internal (preg, string, length, start, length,
length, 0, NULL, eflags);
else
- err = re_search_internal (preg, string, length, start, length - start,
+ err = re_search_internal (preg, string, length, start, length,
length, nmatch, pmatch, eflags);
- __libc_lock_unlock (dfa->lock);
+ lock_unlock (dfa->lock);
return err != REG_NOERROR;
}
#ifdef _LIBC
+libc_hidden_def (__regexec)
+
# include <shlib-compat.h>
versioned_symbol (libc, __regexec, regexec, GLIBC_2_3_4);
@@ -260,8 +232,8 @@ __typeof__ (__regexec) __compat_regexec;
int
attribute_compat_text_section
-__compat_regexec (const regex_t *__restrict preg,
- const char *__restrict string, size_t nmatch,
+__compat_regexec (const regex_t *_Restrict_ preg,
+ const char *_Restrict_ string, size_t nmatch,
regmatch_t pmatch[], int eflags)
{
return regexec (preg, string, nmatch, pmatch,
@@ -292,7 +264,7 @@ compat_symbol (libc, __compat_regexec, regexec, GLIBC_2_0);
concerned.
If REGS is not NULL, and BUFP->no_sub is not set, the offsets of the match
- and all groups is stroed in REGS. (For the "_2" variants, the offsets are
+ and all groups is stored in REGS. (For the "_2" variants, the offsets are
computed relative to the concatenation, not relative to the individual
strings.)
@@ -300,63 +272,65 @@ compat_symbol (libc, __compat_regexec, regexec, GLIBC_2_0);
return the position of the start of the match. Return value -1 means no
match was found and -2 indicates an internal error. */
-int
-re_match (struct re_pattern_buffer *bufp, const char *string, int length,
- int start, struct re_registers *regs)
+regoff_t
+re_match (struct re_pattern_buffer *bufp, const char *string, Idx length,
+ Idx start, struct re_registers *regs)
{
- return re_search_stub (bufp, string, length, start, 0, length, regs, 1);
+ return re_search_stub (bufp, string, length, start, 0, length, regs, true);
}
#ifdef _LIBC
weak_alias (__re_match, re_match)
#endif
-int
-re_search (struct re_pattern_buffer *bufp, const char *string, int length,
- int start, int range, struct re_registers *regs)
+regoff_t
+re_search (struct re_pattern_buffer *bufp, const char *string, Idx length,
+ Idx start, regoff_t range, struct re_registers *regs)
{
- return re_search_stub (bufp, string, length, start, range, length, regs, 0);
+ return re_search_stub (bufp, string, length, start, range, length, regs,
+ false);
}
#ifdef _LIBC
weak_alias (__re_search, re_search)
#endif
-int
-re_match_2 (struct re_pattern_buffer *bufp, const char *string1, int length1,
- const char *string2, int length2, int start,
- struct re_registers *regs, int stop)
+regoff_t
+re_match_2 (struct re_pattern_buffer *bufp, const char *string1, Idx length1,
+ const char *string2, Idx length2, Idx start,
+ struct re_registers *regs, Idx stop)
{
return re_search_2_stub (bufp, string1, length1, string2, length2,
- start, 0, regs, stop, 1);
+ start, 0, regs, stop, true);
}
#ifdef _LIBC
weak_alias (__re_match_2, re_match_2)
#endif
-int
-re_search_2 (struct re_pattern_buffer *bufp, const char *string1, int length1,
- const char *string2, int length2, int start, int range,
- struct re_registers *regs, int stop)
+regoff_t
+re_search_2 (struct re_pattern_buffer *bufp, const char *string1, Idx length1,
+ const char *string2, Idx length2, Idx start, regoff_t range,
+ struct re_registers *regs, Idx stop)
{
return re_search_2_stub (bufp, string1, length1, string2, length2,
- start, range, regs, stop, 0);
+ start, range, regs, stop, false);
}
#ifdef _LIBC
weak_alias (__re_search_2, re_search_2)
#endif
-static int
-internal_function
+static regoff_t
re_search_2_stub (struct re_pattern_buffer *bufp, const char *string1,
- int length1, const char *string2, int length2, int start,
- int range, struct re_registers *regs,
- int stop, int ret_len)
+ Idx length1, const char *string2, Idx length2, Idx start,
+ regoff_t range, struct re_registers *regs,
+ Idx stop, bool ret_len)
{
const char *str;
- int rval;
- int len = length1 + length2;
+ regoff_t rval;
+ Idx len;
char *s = NULL;
- if (BE (length1 < 0 || length2 < 0 || stop < 0 || len < length1, 0))
+ if (BE ((length1 < 0 || length2 < 0 || stop < 0
+ || INT_ADD_WRAPV (length1, length2, &len)),
+ 0))
return -2;
/* Concatenate the strings. */
@@ -380,43 +354,45 @@ re_search_2_stub (struct re_pattern_buffer *bufp, const char *string1,
else
str = string1;
- rval = re_search_stub (bufp, str, len, start, range, stop, regs, ret_len);
+ rval = re_search_stub (bufp, str, len, start, range, stop, regs,
+ ret_len);
re_free (s);
return rval;
}
/* The parameters have the same meaning as those of re_search.
Additional parameters:
- If RET_LEN is nonzero the length of the match is returned (re_match style);
+ If RET_LEN is true the length of the match is returned (re_match style);
otherwise the position of the match is returned. */
-static int
-internal_function
-re_search_stub (struct re_pattern_buffer *bufp, const char *string, int length,
- int start, int range, int stop, struct re_registers *regs,
- int ret_len)
+static regoff_t
+re_search_stub (struct re_pattern_buffer *bufp, const char *string, Idx length,
+ Idx start, regoff_t range, Idx stop, struct re_registers *regs,
+ bool ret_len)
{
reg_errcode_t result;
regmatch_t *pmatch;
- int nregs, rval;
+ Idx nregs;
+ regoff_t rval;
int eflags = 0;
- re_dfa_t *dfa = (re_dfa_t *) bufp->buffer;
+ re_dfa_t *dfa = bufp->buffer;
+ Idx last_start = start + range;
/* Check for out-of-range. */
if (BE (start < 0 || start > length, 0))
return -1;
- if (BE (start + range > length, 0))
- range = length - start;
- else if (BE (start + range < 0, 0))
- range = -start;
+ if (BE (length < last_start || (0 <= range && last_start < start), 0))
+ last_start = length;
+ else if (BE (last_start < 0 || (range < 0 && start <= last_start), 0))
+ last_start = 0;
- __libc_lock_lock (dfa->lock);
+ lock_lock (dfa->lock);
eflags |= (bufp->not_bol) ? REG_NOTBOL : 0;
eflags |= (bufp->not_eol) ? REG_NOTEOL : 0;
/* Compile fastmap if we haven't yet. */
- if (range > 0 && bufp->fastmap != NULL && !bufp->fastmap_accurate)
+ if (start < last_start && bufp->fastmap != NULL && !bufp->fastmap_accurate)
re_compile_fastmap (bufp);
if (BE (bufp->no_sub, 0))
@@ -425,8 +401,8 @@ re_search_stub (struct re_pattern_buffer *bufp, const char *string, int length,
/* We need at least 1 register. */
if (regs == NULL)
nregs = 1;
- else if (BE (bufp->regs_allocated == REGS_FIXED &&
- regs->num_regs < bufp->re_nsub + 1, 0))
+ else if (BE (bufp->regs_allocated == REGS_FIXED
+ && regs->num_regs <= bufp->re_nsub, 0))
{
nregs = regs->num_regs;
if (BE (nregs < 1, 0))
@@ -445,14 +421,14 @@ re_search_stub (struct re_pattern_buffer *bufp, const char *string, int length,
goto out;
}
- result = re_search_internal (bufp, string, length, start, range, stop,
+ result = re_search_internal (bufp, string, length, start, last_start, stop,
nregs, pmatch, eflags);
rval = 0;
- /* I hope we needn't fill ther regs with -1's when no match was found. */
+ /* I hope we needn't fill their regs with -1's when no match was found. */
if (result != REG_NOERROR)
- rval = -1;
+ rval = result == REG_NOMATCH ? -1 : -2;
else if (regs != NULL)
{
/* If caller wants register contents data back, copy them. */
@@ -474,19 +450,18 @@ re_search_stub (struct re_pattern_buffer *bufp, const char *string, int length,
}
re_free (pmatch);
out:
- __libc_lock_unlock (dfa->lock);
+ lock_unlock (dfa->lock);
return rval;
}
static unsigned
-internal_function
-re_copy_regs (struct re_registers *regs, regmatch_t *pmatch, int nregs,
+re_copy_regs (struct re_registers *regs, regmatch_t *pmatch, Idx nregs,
int regs_allocated)
{
int rval = REGS_REALLOCATE;
- int i;
- int need_regs = nregs + 1;
- /* We need one extra element beyond `num_regs' for the `-1' marker GNU code
+ Idx i;
+ Idx need_regs = nregs + 1;
+ /* We need one extra element beyond 'num_regs' for the '-1' marker GNU code
uses. */
/* Have the register data arrays been allocated? */
@@ -559,7 +534,7 @@ re_copy_regs (struct re_registers *regs, regmatch_t *pmatch, int nregs,
void
re_set_registers (struct re_pattern_buffer *bufp, struct re_registers *regs,
- unsigned num_regs, regoff_t *starts, regoff_t *ends)
+ __re_size_t num_regs, regoff_t *starts, regoff_t *ends)
{
if (num_regs)
{
@@ -572,7 +547,7 @@ re_set_registers (struct re_pattern_buffer *bufp, struct re_registers *regs,
{
bufp->regs_allocated = REGS_UNALLOCATED;
regs->num_regs = 0;
- regs->start = regs->end = (regoff_t *) 0;
+ regs->start = regs->end = NULL;
}
}
#ifdef _LIBC
@@ -597,32 +572,38 @@ re_exec (const char *s)
/* Searches for a compiled pattern PREG in the string STRING, whose
length is LENGTH. NMATCH, PMATCH, and EFLAGS have the same
- mingings with regexec. START, and RANGE have the same meanings
- with re_search.
+ meaning as with regexec. LAST_START is START + RANGE, where
+ START and RANGE have the same meaning as with re_search.
Return REG_NOERROR if we find a match, and REG_NOMATCH if not,
otherwise return the error code.
Note: We assume front end functions already check ranges.
- (START + RANGE >= 0 && START + RANGE <= LENGTH) */
+ (0 <= LAST_START && LAST_START <= LENGTH) */
static reg_errcode_t
-__attribute_warn_unused_result__ internal_function
-re_search_internal (const regex_t *preg, const char *string, int length,
- int start, int range, int stop, size_t nmatch,
+__attribute_warn_unused_result__
+re_search_internal (const regex_t *preg, const char *string, Idx length,
+ Idx start, Idx last_start, Idx stop, size_t nmatch,
regmatch_t pmatch[], int eflags)
{
reg_errcode_t err;
- const re_dfa_t *dfa = (const re_dfa_t *) preg->buffer;
- int left_lim, right_lim, incr;
- int fl_longest_match, match_first, match_kind, match_last = -1;
- int extra_nmatch;
- int sb, ch;
+ const re_dfa_t *dfa = preg->buffer;
+ Idx left_lim, right_lim;
+ int incr;
+ bool fl_longest_match;
+ int match_kind;
+ Idx match_first;
+ Idx match_last = -1;
+ Idx extra_nmatch;
+ bool sb;
+ int ch;
#if defined _LIBC || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L)
re_match_context_t mctx = { .dfa = dfa };
#else
re_match_context_t mctx;
#endif
- char *fastmap = (preg->fastmap != NULL && preg->fastmap_accurate
- && range && !preg->can_be_null) ? preg->fastmap : NULL;
+ char *fastmap = ((preg->fastmap != NULL && preg->fastmap_accurate
+ && start != last_start && !preg->can_be_null)
+ ? preg->fastmap : NULL);
RE_TRANSLATE_TYPE t = preg->translate;
#if !(defined _LIBC || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L))
@@ -641,7 +622,7 @@ re_search_internal (const regex_t *preg, const char *string, int length,
#ifdef DEBUG
/* We assume front-end functions already check them. */
- assert (start + range >= 0 && start + range <= length);
+ assert (0 <= last_start && last_start <= length);
#endif
/* If initial states with non-begbuf contexts have no elements,
@@ -652,16 +633,17 @@ re_search_internal (const regex_t *preg, const char *string, int length,
&& (dfa->init_state_nl->nodes.nelem == 0
|| !preg->newline_anchor))
{
- if (start != 0 && start + range != 0)
- return REG_NOMATCH;
- start = range = 0;
+ if (start != 0 && last_start != 0)
+ return REG_NOMATCH;
+ start = last_start = 0;
}
/* We must check the longest matching, if nmatch > 0. */
fl_longest_match = (nmatch != 0 || dfa->nbackref);
err = re_string_allocate (&mctx.input, string, length, dfa->nodes_len + 1,
- preg->translate, preg->syntax & RE_ICASE, dfa);
+ preg->translate, (preg->syntax & RE_ICASE) != 0,
+ dfa);
if (BE (err != REG_NOERROR, 0))
goto free_return;
mctx.input.stop = stop;
@@ -679,7 +661,8 @@ re_search_internal (const regex_t *preg, const char *string, int length,
if (nmatch > 1 || dfa->has_mb_node)
{
/* Avoid overflow. */
- if (BE (SIZE_MAX / sizeof (re_dfastate_t *) <= mctx.input.bufs_len, 0))
+ if (BE ((MIN (IDX_MAX, SIZE_MAX / sizeof (re_dfastate_t *))
+ <= mctx.input.bufs_len), 0))
{
err = REG_ESPACE;
goto free_return;
@@ -699,15 +682,15 @@ re_search_internal (const regex_t *preg, const char *string, int length,
mctx.input.tip_context = (eflags & REG_NOTBOL) ? CONTEXT_BEGBUF
: CONTEXT_NEWLINE | CONTEXT_BEGBUF;
- /* Check incrementally whether of not the input string match. */
- incr = (range < 0) ? -1 : 1;
- left_lim = (range < 0) ? start + range : start;
- right_lim = (range < 0) ? start : start + range;
+ /* Check incrementally whether the input string matches. */
+ incr = (last_start < start) ? -1 : 1;
+ left_lim = (last_start < start) ? last_start : start;
+ right_lim = (last_start < start) ? start : last_start;
sb = dfa->mb_cur_max == 1;
match_kind =
(fastmap
? ((sb || !(preg->syntax & RE_ICASE || t) ? 4 : 0)
- | (range >= 0 ? 2 : 0)
+ | (start <= last_start ? 2 : 0)
| (t != NULL ? 1 : 0))
: 8);
@@ -774,8 +757,8 @@ re_search_internal (const regex_t *preg, const char *string, int length,
{
/* If MATCH_FIRST is out of the valid range, reconstruct the
buffers. */
- unsigned int offset = match_first - mctx.input.raw_mbs_idx;
- if (BE (offset >= (unsigned int) mctx.input.valid_raw_len, 0))
+ __re_size_t offset = match_first - mctx.input.raw_mbs_idx;
+ if (BE (offset >= (__re_size_t) mctx.input.valid_raw_len, 0))
{
err = re_string_reconstruct (&mctx.input, match_first,
eflags);
@@ -817,7 +800,7 @@ re_search_internal (const regex_t *preg, const char *string, int length,
/* We assume that the matching starts from 0. */
mctx.state_log_top = mctx.nbkref_ents = mctx.max_mb_elem_len = 0;
match_last = check_matching (&mctx, fl_longest_match,
- range >= 0 ? &match_first : NULL);
+ start <= last_start ? &match_first : NULL);
if (match_last != -1)
{
if (BE (match_last == -2, 0))
@@ -860,7 +843,7 @@ re_search_internal (const regex_t *preg, const char *string, int length,
/* Set pmatch[] if we need. */
if (nmatch > 0)
{
- int reg_idx;
+ Idx reg_idx;
/* Initialize registers. */
for (reg_idx = 1; reg_idx < nmatch; ++reg_idx)
@@ -869,6 +852,9 @@ re_search_internal (const regex_t *preg, const char *string, int length,
/* Set the points where matching start/end. */
pmatch[0].rm_so = 0;
pmatch[0].rm_eo = mctx.match_last;
+ /* FIXME: This function should fail if mctx.match_last exceeds
+ the maximum possible regoff_t value. We need a new error
+ code REG_OVERFLOW. */
if (!preg->no_sub && nmatch > 1)
{
@@ -878,7 +864,7 @@ re_search_internal (const regex_t *preg, const char *string, int length,
goto free_return;
}
- /* At last, add the offset to the each registers, since we slided
+ /* At last, add the offset to each register, since we slid
the buffers so that we could assume that the matching starts
from 0. */
for (reg_idx = 0; reg_idx < nmatch; ++reg_idx)
@@ -928,11 +914,11 @@ re_search_internal (const regex_t *preg, const char *string, int length,
}
static reg_errcode_t
-internal_function __attribute_warn_unused_result__
+__attribute_warn_unused_result__
prune_impossible_nodes (re_match_context_t *mctx)
{
const re_dfa_t *const dfa = mctx->dfa;
- int halt_node, match_last;
+ Idx halt_node, match_last;
reg_errcode_t ret;
re_dfastate_t **sifted_states;
re_dfastate_t **lim_states = NULL;
@@ -944,7 +930,7 @@ prune_impossible_nodes (re_match_context_t *mctx)
halt_node = mctx->last_node;
/* Avoid overflow. */
- if (BE (SIZE_MAX / sizeof (re_dfastate_t *) <= match_last, 0))
+ if (BE (MIN (IDX_MAX, SIZE_MAX / sizeof (re_dfastate_t *)) <= match_last, 0))
return REG_ESPACE;
sifted_states = re_malloc (re_dfastate_t *, match_last + 1);
@@ -1024,9 +1010,9 @@ prune_impossible_nodes (re_match_context_t *mctx)
since initial states may have constraints like "\<", "^", etc.. */
static inline re_dfastate_t *
-__attribute ((always_inline)) internal_function
+__attribute__ ((always_inline))
acquire_init_state_context (reg_errcode_t *err, const re_match_context_t *mctx,
- int idx)
+ Idx idx)
{
const re_dfa_t *const dfa = mctx->dfa;
if (dfa->init_state->has_constraint)
@@ -1057,27 +1043,27 @@ acquire_init_state_context (reg_errcode_t *err, const re_match_context_t *mctx,
}
/* Check whether the regular expression match input string INPUT or not,
- and return the index where the matching end, return -1 if not match,
- or return -2 in case of an error.
+ and return the index where the matching end. Return -1 if
+ there is no match, and return -2 in case of an error.
FL_LONGEST_MATCH means we want the POSIX longest matching.
If P_MATCH_FIRST is not NULL, and the match fails, it is set to the
next place where we may want to try matching.
- Note that the matcher assume that the maching starts from the current
+ Note that the matcher assumes that the matching starts from the current
index of the buffer. */
-static int
-internal_function __attribute_warn_unused_result__
-check_matching (re_match_context_t *mctx, int fl_longest_match,
- int *p_match_first)
+static Idx
+__attribute_warn_unused_result__
+check_matching (re_match_context_t *mctx, bool fl_longest_match,
+ Idx *p_match_first)
{
const re_dfa_t *const dfa = mctx->dfa;
reg_errcode_t err;
- int match = 0;
- int match_last = -1;
- int cur_str_idx = re_string_cur_idx (&mctx->input);
+ Idx match = 0;
+ Idx match_last = -1;
+ Idx cur_str_idx = re_string_cur_idx (&mctx->input);
re_dfastate_t *cur_state;
- int at_init_state = p_match_first != NULL;
- int next_start_idx = cur_str_idx;
+ bool at_init_state = p_match_first != NULL;
+ Idx next_start_idx = cur_str_idx;
err = REG_NOERROR;
cur_state = acquire_init_state_context (&err, mctx, cur_str_idx);
@@ -1096,7 +1082,7 @@ check_matching (re_match_context_t *mctx, int fl_longest_match,
later. E.g. Processing back references. */
if (BE (dfa->nbackref, 0))
{
- at_init_state = 0;
+ at_init_state = false;
err = check_subexp_matching_top (mctx, &cur_state->nodes, 0);
if (BE (err != REG_NOERROR, 0))
return err;
@@ -1129,7 +1115,7 @@ check_matching (re_match_context_t *mctx, int fl_longest_match,
while (!re_string_eoi (&mctx->input))
{
re_dfastate_t *old_state = cur_state;
- int next_char_idx = re_string_cur_idx (&mctx->input) + 1;
+ Idx next_char_idx = re_string_cur_idx (&mctx->input) + 1;
if ((BE (next_char_idx >= mctx->input.bufs_len, 0)
&& mctx->input.bufs_len < mctx->input.len)
@@ -1167,7 +1153,7 @@ check_matching (re_match_context_t *mctx, int fl_longest_match,
if (old_state == cur_state)
next_start_idx = next_char_idx;
else
- at_init_state = 0;
+ at_init_state = false;
}
if (cur_state->halt)
@@ -1198,31 +1184,29 @@ check_matching (re_match_context_t *mctx, int fl_longest_match,
/* Check NODE match the current context. */
-static int
-internal_function
-check_halt_node_context (const re_dfa_t *dfa, int node, unsigned int context)
+static bool
+check_halt_node_context (const re_dfa_t *dfa, Idx node, unsigned int context)
{
re_token_type_t type = dfa->nodes[node].type;
unsigned int constraint = dfa->nodes[node].constraint;
if (type != END_OF_RE)
- return 0;
+ return false;
if (!constraint)
- return 1;
+ return true;
if (NOT_SATISFY_NEXT_CONSTRAINT (constraint, context))
- return 0;
- return 1;
+ return false;
+ return true;
}
/* Check the halt state STATE match the current context.
Return 0 if not match, if the node, STATE has, is a halt node and
match the context, return the node. */
-static int
-internal_function
+static Idx
check_halt_state_context (const re_match_context_t *mctx,
- const re_dfastate_t *state, int idx)
+ const re_dfastate_t *state, Idx idx)
{
- int i;
+ Idx i;
unsigned int context;
#ifdef DEBUG
assert (state->halt);
@@ -1236,32 +1220,33 @@ check_halt_state_context (const re_match_context_t *mctx,
/* Compute the next node to which "NFA" transit from NODE("NFA" is a NFA
corresponding to the DFA).
- Return the destination node, and update EPS_VIA_NODES, return -1 in case
- of errors. */
+ Return the destination node, and update EPS_VIA_NODES;
+ return -1 in case of errors. */
-static int
-internal_function
-proceed_next_node (const re_match_context_t *mctx, int nregs, regmatch_t *regs,
- int *pidx, int node, re_node_set *eps_via_nodes,
+static Idx
+proceed_next_node (const re_match_context_t *mctx, Idx nregs, regmatch_t *regs,
+ Idx *pidx, Idx node, re_node_set *eps_via_nodes,
struct re_fail_stack_t *fs)
{
const re_dfa_t *const dfa = mctx->dfa;
- int i, err;
+ Idx i;
+ bool ok;
if (IS_EPSILON_NODE (dfa->nodes[node].type))
{
re_node_set *cur_nodes = &mctx->state_log[*pidx]->nodes;
re_node_set *edests = &dfa->edests[node];
- int dest_node;
- err = re_node_set_insert (eps_via_nodes, node);
- if (BE (err < 0, 0))
+ Idx dest_node;
+ ok = re_node_set_insert (eps_via_nodes, node);
+ if (BE (! ok, 0))
return -2;
- /* Pick up a valid destination, or return -1 if none is found. */
+ /* Pick up a valid destination, or return -1 if none
+ is found. */
for (dest_node = -1, i = 0; i < edests->nelem; ++i)
{
- int candidate = edests->elems[i];
+ Idx candidate = edests->elems[i];
if (!re_node_set_contains (cur_nodes, candidate))
continue;
- if (dest_node == -1)
+ if (dest_node == -1)
dest_node = candidate;
else
@@ -1285,7 +1270,7 @@ proceed_next_node (const re_match_context_t *mctx, int nregs, regmatch_t *regs,
}
else
{
- int naccepted = 0;
+ Idx naccepted = 0;
re_token_type_t type = dfa->nodes[node].type;
#ifdef RE_ENABLE_I18N
@@ -1295,7 +1280,7 @@ proceed_next_node (const re_match_context_t *mctx, int nregs, regmatch_t *regs,
#endif /* RE_ENABLE_I18N */
if (type == OP_BACK_REF)
{
- int subexp_idx = dfa->nodes[node].opr.idx + 1;
+ Idx subexp_idx = dfa->nodes[node].opr.idx + 1;
naccepted = regs[subexp_idx].rm_eo - regs[subexp_idx].rm_so;
if (fs != NULL)
{
@@ -1312,9 +1297,9 @@ proceed_next_node (const re_match_context_t *mctx, int nregs, regmatch_t *regs,
if (naccepted == 0)
{
- int dest_node;
- err = re_node_set_insert (eps_via_nodes, node);
- if (BE (err < 0, 0))
+ Idx dest_node;
+ ok = re_node_set_insert (eps_via_nodes, node);
+ if (BE (! ok, 0))
return -2;
dest_node = dfa->edests[node].elems[0];
if (re_node_set_contains (&mctx->state_log[*pidx]->nodes,
@@ -1326,7 +1311,7 @@ proceed_next_node (const re_match_context_t *mctx, int nregs, regmatch_t *regs,
if (naccepted != 0
|| check_node_accept (mctx, dfa->nodes + node, *pidx))
{
- int dest_node = dfa->nexts[node];
+ Idx dest_node = dfa->nexts[node];
*pidx = (naccepted == 0) ? *pidx + 1 : *pidx + naccepted;
if (fs && (*pidx > mctx->match_last || mctx->state_log[*pidx] == NULL
|| !re_node_set_contains (&mctx->state_log[*pidx]->nodes,
@@ -1340,17 +1325,17 @@ proceed_next_node (const re_match_context_t *mctx, int nregs, regmatch_t *regs,
}
static reg_errcode_t
-internal_function __attribute_warn_unused_result__
-push_fail_stack (struct re_fail_stack_t *fs, int str_idx, int dest_node,
- int nregs, regmatch_t *regs, re_node_set *eps_via_nodes)
+__attribute_warn_unused_result__
+push_fail_stack (struct re_fail_stack_t *fs, Idx str_idx, Idx dest_node,
+ Idx nregs, regmatch_t *regs, re_node_set *eps_via_nodes)
{
reg_errcode_t err;
- int num = fs->num++;
+ Idx num = fs->num++;
if (fs->num == fs->alloc)
{
struct re_fail_stack_ent_t *new_array;
- new_array = realloc (fs->stack, (sizeof (struct re_fail_stack_ent_t)
- * fs->alloc * 2));
+ new_array = re_realloc (fs->stack, struct re_fail_stack_ent_t,
+ fs->alloc * 2);
if (new_array == NULL)
return REG_ESPACE;
fs->alloc *= 2;
@@ -1366,12 +1351,11 @@ push_fail_stack (struct re_fail_stack_t *fs, int str_idx, int dest_node,
return err;
}
-static int
-internal_function
-pop_fail_stack (struct re_fail_stack_t *fs, int *pidx, int nregs,
+static Idx
+pop_fail_stack (struct re_fail_stack_t *fs, Idx *pidx, Idx nregs,
regmatch_t *regs, re_node_set *eps_via_nodes)
{
- int num = --fs->num;
+ Idx num = --fs->num;
assert (num >= 0);
*pidx = fs->stack[num].idx;
memcpy (regs, fs->stack[num].regs, sizeof (regmatch_t) * nregs);
@@ -1387,17 +1371,17 @@ pop_fail_stack (struct re_fail_stack_t *fs, int *pidx, int nregs,
pmatch[i].rm_so == pmatch[i].rm_eo == -1 for 0 < i < nmatch. */
static reg_errcode_t
-internal_function __attribute_warn_unused_result__
+__attribute_warn_unused_result__
set_regs (const regex_t *preg, const re_match_context_t *mctx, size_t nmatch,
- regmatch_t *pmatch, int fl_backtrack)
+ regmatch_t *pmatch, bool fl_backtrack)
{
- const re_dfa_t *dfa = (const re_dfa_t *) preg->buffer;
- int idx, cur_node;
+ const re_dfa_t *dfa = preg->buffer;
+ Idx idx, cur_node;
re_node_set eps_via_nodes;
struct re_fail_stack_t *fs;
struct re_fail_stack_t fs_body = { 0, 2, NULL };
regmatch_t *prev_idx_match;
- int prev_idx_match_malloced = 0;
+ bool prev_idx_match_malloced = false;
#ifdef DEBUG
assert (nmatch > 1);
@@ -1426,7 +1410,7 @@ set_regs (const regex_t *preg, const re_match_context_t *mctx, size_t nmatch,
free_fail_stack_return (fs);
return REG_ESPACE;
}
- prev_idx_match_malloced = 1;
+ prev_idx_match_malloced = true;
}
memcpy (prev_idx_match, pmatch, sizeof (regmatch_t) * nmatch);
@@ -1436,7 +1420,7 @@ set_regs (const regex_t *preg, const re_match_context_t *mctx, size_t nmatch,
if (idx == pmatch[0].rm_eo && cur_node == mctx->last_node)
{
- int reg_idx;
+ Idx reg_idx;
if (fs)
{
for (reg_idx = 0; reg_idx < nmatch; ++reg_idx)
@@ -1494,12 +1478,11 @@ set_regs (const regex_t *preg, const re_match_context_t *mctx, size_t nmatch,
}
static reg_errcode_t
-internal_function
free_fail_stack_return (struct re_fail_stack_t *fs)
{
if (fs)
{
- int fs_idx;
+ Idx fs_idx;
for (fs_idx = 0; fs_idx < fs->num; ++fs_idx)
{
re_node_set_free (&fs->stack[fs_idx].eps_via_nodes);
@@ -1511,14 +1494,13 @@ free_fail_stack_return (struct re_fail_stack_t *fs)
}
static void
-internal_function
update_regs (const re_dfa_t *dfa, regmatch_t *pmatch,
- regmatch_t *prev_idx_match, int cur_node, int cur_idx, int nmatch)
+ regmatch_t *prev_idx_match, Idx cur_node, Idx cur_idx, Idx nmatch)
{
int type = dfa->nodes[cur_node].type;
if (type == OP_OPEN_SUBEXP)
{
- int reg_num = dfa->nodes[cur_node].opr.idx + 1;
+ Idx reg_num = dfa->nodes[cur_node].opr.idx + 1;
/* We are at the first node of this sub expression. */
if (reg_num < nmatch)
@@ -1529,7 +1511,7 @@ update_regs (const re_dfa_t *dfa, regmatch_t *pmatch,
}
else if (type == OP_CLOSE_SUBEXP)
{
- int reg_num = dfa->nodes[cur_node].opr.idx + 1;
+ Idx reg_num = dfa->nodes[cur_node].opr.idx + 1;
if (reg_num < nmatch)
{
/* We are at the last node of this sub expression. */
@@ -1563,32 +1545,31 @@ update_regs (const re_dfa_t *dfa, regmatch_t *pmatch,
and sift the nodes in each states according to the following rules.
Updated state_log will be wrote to STATE_LOG.
- Rules: We throw away the Node `a' in the STATE_LOG[STR_IDX] if...
+ Rules: We throw away the Node 'a' in the STATE_LOG[STR_IDX] if...
1. When STR_IDX == MATCH_LAST(the last index in the state_log):
- If `a' isn't the LAST_NODE and `a' can't epsilon transit to
- the LAST_NODE, we throw away the node `a'.
- 2. When 0 <= STR_IDX < MATCH_LAST and `a' accepts
- string `s' and transit to `b':
+ If 'a' isn't the LAST_NODE and 'a' can't epsilon transit to
+ the LAST_NODE, we throw away the node 'a'.
+ 2. When 0 <= STR_IDX < MATCH_LAST and 'a' accepts
+ string 's' and transit to 'b':
i. If 'b' isn't in the STATE_LOG[STR_IDX+strlen('s')], we throw
- away the node `a'.
+ away the node 'a'.
ii. If 'b' is in the STATE_LOG[STR_IDX+strlen('s')] but 'b' is
- thrown away, we throw away the node `a'.
+ thrown away, we throw away the node 'a'.
3. When 0 <= STR_IDX < MATCH_LAST and 'a' epsilon transit to 'b':
i. If 'b' isn't in the STATE_LOG[STR_IDX], we throw away the
- node `a'.
+ node 'a'.
ii. If 'b' is in the STATE_LOG[STR_IDX] but 'b' is thrown away,
- we throw away the node `a'. */
+ we throw away the node 'a'. */
#define STATE_NODE_CONTAINS(state,node) \
((state) != NULL && re_node_set_contains (&(state)->nodes, node))
static reg_errcode_t
-internal_function
sift_states_backward (const re_match_context_t *mctx, re_sift_context_t *sctx)
{
reg_errcode_t err;
int null_cnt = 0;
- int str_idx = sctx->last_str_idx;
+ Idx str_idx = sctx->last_str_idx;
re_node_set cur_dest;
#ifdef DEBUG
@@ -1641,33 +1622,33 @@ sift_states_backward (const re_match_context_t *mctx, re_sift_context_t *sctx)
}
static reg_errcode_t
-internal_function __attribute_warn_unused_result__
+__attribute_warn_unused_result__
build_sifted_states (const re_match_context_t *mctx, re_sift_context_t *sctx,
- int str_idx, re_node_set *cur_dest)
+ Idx str_idx, re_node_set *cur_dest)
{
const re_dfa_t *const dfa = mctx->dfa;
const re_node_set *cur_src = &mctx->state_log[str_idx]->non_eps_nodes;
- int i;
+ Idx i;
/* Then build the next sifted state.
- We build the next sifted state on `cur_dest', and update
- `sifted_states[str_idx]' with `cur_dest'.
+ We build the next sifted state on 'cur_dest', and update
+ 'sifted_states[str_idx]' with 'cur_dest'.
Note:
- `cur_dest' is the sifted state from `state_log[str_idx + 1]'.
- `cur_src' points the node_set of the old `state_log[str_idx]'
+ 'cur_dest' is the sifted state from 'state_log[str_idx + 1]'.
+ 'cur_src' points the node_set of the old 'state_log[str_idx]'
(with the epsilon nodes pre-filtered out). */
for (i = 0; i < cur_src->nelem; i++)
{
- int prev_node = cur_src->elems[i];
+ Idx prev_node = cur_src->elems[i];
int naccepted = 0;
- int ret;
+ bool ok;
#ifdef DEBUG
re_token_type_t type = dfa->nodes[prev_node].type;
assert (!IS_EPSILON_NODE (type));
#endif
#ifdef RE_ENABLE_I18N
- /* If the node may accept `multi byte'. */
+ /* If the node may accept "multi byte". */
if (dfa->nodes[prev_node].accept_mb)
naccepted = sift_states_iter_mb (mctx, sctx, prev_node,
str_idx, sctx->last_str_idx);
@@ -1686,14 +1667,14 @@ build_sifted_states (const re_match_context_t *mctx, re_sift_context_t *sctx,
if (sctx->limits.nelem)
{
- int to_idx = str_idx + naccepted;
+ Idx to_idx = str_idx + naccepted;
if (check_dst_limits (mctx, &sctx->limits,
dfa->nexts[prev_node], to_idx,
prev_node, str_idx))
continue;
}
- ret = re_node_set_insert (cur_dest, prev_node);
- if (BE (ret == -1, 0))
+ ok = re_node_set_insert (cur_dest, prev_node);
+ if (BE (! ok, 0))
return REG_ESPACE;
}
@@ -1703,10 +1684,9 @@ build_sifted_states (const re_match_context_t *mctx, re_sift_context_t *sctx,
/* Helper functions. */
static reg_errcode_t
-internal_function
-clean_state_log_if_needed (re_match_context_t *mctx, int next_state_log_idx)
+clean_state_log_if_needed (re_match_context_t *mctx, Idx next_state_log_idx)
{
- int top = mctx->state_log_top;
+ Idx top = mctx->state_log_top;
if ((next_state_log_idx >= mctx->input.bufs_len
&& mctx->input.bufs_len < mctx->input.len)
@@ -1729,11 +1709,10 @@ clean_state_log_if_needed (re_match_context_t *mctx, int next_state_log_idx)
}
static reg_errcode_t
-internal_function
merge_state_array (const re_dfa_t *dfa, re_dfastate_t **dst,
- re_dfastate_t **src, int num)
+ re_dfastate_t **src, Idx num)
{
- int st_idx;
+ Idx st_idx;
reg_errcode_t err;
for (st_idx = 0; st_idx < num; ++st_idx)
{
@@ -1756,9 +1735,8 @@ merge_state_array (const re_dfa_t *dfa, re_dfastate_t **dst,
}
static reg_errcode_t
-internal_function
update_cur_sifted_state (const re_match_context_t *mctx,
- re_sift_context_t *sctx, int str_idx,
+ re_sift_context_t *sctx, Idx str_idx,
re_node_set *dest_nodes)
{
const re_dfa_t *const dfa = mctx->dfa;
@@ -1804,12 +1782,12 @@ update_cur_sifted_state (const re_match_context_t *mctx,
}
static reg_errcode_t
-internal_function __attribute_warn_unused_result__
+__attribute_warn_unused_result__
add_epsilon_src_nodes (const re_dfa_t *dfa, re_node_set *dest_nodes,
const re_node_set *candidates)
{
reg_errcode_t err = REG_NOERROR;
- int i;
+ Idx i;
re_dfastate_t *state = re_acquire_state (&err, dfa, dest_nodes);
if (BE (err != REG_NOERROR, 0))
@@ -1833,24 +1811,23 @@ add_epsilon_src_nodes (const re_dfa_t *dfa, re_node_set *dest_nodes,
}
static reg_errcode_t
-internal_function
-sub_epsilon_src_nodes (const re_dfa_t *dfa, int node, re_node_set *dest_nodes,
+sub_epsilon_src_nodes (const re_dfa_t *dfa, Idx node, re_node_set *dest_nodes,
const re_node_set *candidates)
{
- int ecl_idx;
+ Idx ecl_idx;
reg_errcode_t err;
re_node_set *inv_eclosure = dfa->inveclosures + node;
re_node_set except_nodes;
re_node_set_init_empty (&except_nodes);
for (ecl_idx = 0; ecl_idx < inv_eclosure->nelem; ++ecl_idx)
{
- int cur_node = inv_eclosure->elems[ecl_idx];
+ Idx cur_node = inv_eclosure->elems[ecl_idx];
if (cur_node == node)
continue;
if (IS_EPSILON_NODE (dfa->nodes[cur_node].type))
{
- int edst1 = dfa->edests[cur_node].elems[0];
- int edst2 = ((dfa->edests[cur_node].nelem > 1)
+ Idx edst1 = dfa->edests[cur_node].elems[0];
+ Idx edst2 = ((dfa->edests[cur_node].nelem > 1)
? dfa->edests[cur_node].elems[1] : -1);
if ((!re_node_set_contains (inv_eclosure, edst1)
&& re_node_set_contains (dest_nodes, edst1))
@@ -1870,10 +1847,10 @@ sub_epsilon_src_nodes (const re_dfa_t *dfa, int node, re_node_set *dest_nodes,
}
for (ecl_idx = 0; ecl_idx < inv_eclosure->nelem; ++ecl_idx)
{
- int cur_node = inv_eclosure->elems[ecl_idx];
+ Idx cur_node = inv_eclosure->elems[ecl_idx];
if (!re_node_set_contains (&except_nodes, cur_node))
{
- int idx = re_node_set_contains (dest_nodes, cur_node) - 1;
+ Idx idx = re_node_set_contains (dest_nodes, cur_node) - 1;
re_node_set_remove_at (dest_nodes, idx);
}
}
@@ -1881,19 +1858,18 @@ sub_epsilon_src_nodes (const re_dfa_t *dfa, int node, re_node_set *dest_nodes,
return REG_NOERROR;
}
-static int
-internal_function
-check_dst_limits (const re_match_context_t *mctx, re_node_set *limits,
- int dst_node, int dst_idx, int src_node, int src_idx)
+static bool
+check_dst_limits (const re_match_context_t *mctx, const re_node_set *limits,
+ Idx dst_node, Idx dst_idx, Idx src_node, Idx src_idx)
{
const re_dfa_t *const dfa = mctx->dfa;
- int lim_idx, src_pos, dst_pos;
+ Idx lim_idx, src_pos, dst_pos;
- int dst_bkref_idx = search_cur_bkref_entry (mctx, dst_idx);
- int src_bkref_idx = search_cur_bkref_entry (mctx, src_idx);
+ Idx dst_bkref_idx = search_cur_bkref_entry (mctx, dst_idx);
+ Idx src_bkref_idx = search_cur_bkref_entry (mctx, src_idx);
for (lim_idx = 0; lim_idx < limits->nelem; ++lim_idx)
{
- int subexp_idx;
+ Idx subexp_idx;
struct re_backref_cache_entry *ent;
ent = mctx->bkref_ents + limits->elems[lim_idx];
subexp_idx = dfa->nodes[ent->node].opr.idx;
@@ -1912,25 +1888,24 @@ check_dst_limits (const re_match_context_t *mctx, re_node_set *limits,
if (src_pos == dst_pos)
continue; /* This is unrelated limitation. */
else
- return 1;
+ return true;
}
- return 0;
+ return false;
}
static int
-internal_function
check_dst_limits_calc_pos_1 (const re_match_context_t *mctx, int boundaries,
- int subexp_idx, int from_node, int bkref_idx)
+ Idx subexp_idx, Idx from_node, Idx bkref_idx)
{
const re_dfa_t *const dfa = mctx->dfa;
const re_node_set *eclosures = dfa->eclosures + from_node;
- int node_idx;
+ Idx node_idx;
/* Else, we are on the boundary: examine the nodes on the epsilon
closure. */
for (node_idx = 0; node_idx < eclosures->nelem; ++node_idx)
{
- int node = eclosures->elems[node_idx];
+ Idx node = eclosures->elems[node_idx];
switch (dfa->nodes[node].type)
{
case OP_BACK_REF:
@@ -1939,7 +1914,8 @@ check_dst_limits_calc_pos_1 (const re_match_context_t *mctx, int boundaries,
struct re_backref_cache_entry *ent = mctx->bkref_ents + bkref_idx;
do
{
- int dst, cpos;
+ Idx dst;
+ int cpos;
if (ent->node != node)
continue;
@@ -1999,10 +1975,9 @@ check_dst_limits_calc_pos_1 (const re_match_context_t *mctx, int boundaries,
}
static int
-internal_function
-check_dst_limits_calc_pos (const re_match_context_t *mctx, int limit,
- int subexp_idx, int from_node, int str_idx,
- int bkref_idx)
+check_dst_limits_calc_pos (const re_match_context_t *mctx, Idx limit,
+ Idx subexp_idx, Idx from_node, Idx str_idx,
+ Idx bkref_idx)
{
struct re_backref_cache_entry *lim = mctx->bkref_ents + limit;
int boundaries;
@@ -2029,17 +2004,16 @@ check_dst_limits_calc_pos (const re_match_context_t *mctx, int limit,
which are against limitations from DEST_NODES. */
static reg_errcode_t
-internal_function
check_subexp_limits (const re_dfa_t *dfa, re_node_set *dest_nodes,
const re_node_set *candidates, re_node_set *limits,
- struct re_backref_cache_entry *bkref_ents, int str_idx)
+ struct re_backref_cache_entry *bkref_ents, Idx str_idx)
{
reg_errcode_t err;
- int node_idx, lim_idx;
+ Idx node_idx, lim_idx;
for (lim_idx = 0; lim_idx < limits->nelem; ++lim_idx)
{
- int subexp_idx;
+ Idx subexp_idx;
struct re_backref_cache_entry *ent;
ent = bkref_ents + limits->elems[lim_idx];
@@ -2049,11 +2023,11 @@ check_subexp_limits (const re_dfa_t *dfa, re_node_set *dest_nodes,
subexp_idx = dfa->nodes[ent->node].opr.idx;
if (ent->subexp_to == str_idx)
{
- int ops_node = -1;
- int cls_node = -1;
+ Idx ops_node = -1;
+ Idx cls_node = -1;
for (node_idx = 0; node_idx < dest_nodes->nelem; ++node_idx)
{
- int node = dest_nodes->elems[node_idx];
+ Idx node = dest_nodes->elems[node_idx];
re_token_type_t type = dfa->nodes[node].type;
if (type == OP_OPEN_SUBEXP
&& subexp_idx == dfa->nodes[node].opr.idx)
@@ -2077,7 +2051,7 @@ check_subexp_limits (const re_dfa_t *dfa, re_node_set *dest_nodes,
if (cls_node >= 0)
for (node_idx = 0; node_idx < dest_nodes->nelem; ++node_idx)
{
- int node = dest_nodes->elems[node_idx];
+ Idx node = dest_nodes->elems[node_idx];
if (!re_node_set_contains (dfa->inveclosures + node,
cls_node)
&& !re_node_set_contains (dfa->eclosures + node,
@@ -2097,7 +2071,7 @@ check_subexp_limits (const re_dfa_t *dfa, re_node_set *dest_nodes,
{
for (node_idx = 0; node_idx < dest_nodes->nelem; ++node_idx)
{
- int node = dest_nodes->elems[node_idx];
+ Idx node = dest_nodes->elems[node_idx];
re_token_type_t type = dfa->nodes[node].type;
if (type == OP_CLOSE_SUBEXP || type == OP_OPEN_SUBEXP)
{
@@ -2117,15 +2091,15 @@ check_subexp_limits (const re_dfa_t *dfa, re_node_set *dest_nodes,
}
static reg_errcode_t
-internal_function __attribute_warn_unused_result__
+__attribute_warn_unused_result__
sift_states_bkref (const re_match_context_t *mctx, re_sift_context_t *sctx,
- int str_idx, const re_node_set *candidates)
+ Idx str_idx, const re_node_set *candidates)
{
const re_dfa_t *const dfa = mctx->dfa;
reg_errcode_t err;
- int node_idx, node;
+ Idx node_idx, node;
re_sift_context_t local_sctx;
- int first_idx = search_cur_bkref_entry (mctx, str_idx);
+ Idx first_idx = search_cur_bkref_entry (mctx, str_idx);
if (first_idx == -1)
return REG_NOERROR;
@@ -2134,7 +2108,7 @@ sift_states_bkref (const re_match_context_t *mctx, re_sift_context_t *sctx,
for (node_idx = 0; node_idx < candidates->nelem; ++node_idx)
{
- int enabled_idx;
+ Idx enabled_idx;
re_token_type_t type;
struct re_backref_cache_entry *entry;
node = candidates->elems[node_idx];
@@ -2149,10 +2123,10 @@ sift_states_bkref (const re_match_context_t *mctx, re_sift_context_t *sctx,
enabled_idx = first_idx;
do
{
- int subexp_len;
- int to_idx;
- int dst_node;
- int ret;
+ Idx subexp_len;
+ Idx to_idx;
+ Idx dst_node;
+ bool ok;
re_dfastate_t *cur_state;
if (entry->node != node)
@@ -2178,8 +2152,8 @@ sift_states_bkref (const re_match_context_t *mctx, re_sift_context_t *sctx,
}
local_sctx.last_node = node;
local_sctx.last_str_idx = str_idx;
- ret = re_node_set_insert (&local_sctx.limits, enabled_idx);
- if (BE (ret < 0, 0))
+ ok = re_node_set_insert (&local_sctx.limits, enabled_idx);
+ if (BE (! ok, 0))
{
err = REG_ESPACE;
goto free_return;
@@ -2217,23 +2191,22 @@ sift_states_bkref (const re_match_context_t *mctx, re_sift_context_t *sctx,
#ifdef RE_ENABLE_I18N
static int
-internal_function
sift_states_iter_mb (const re_match_context_t *mctx, re_sift_context_t *sctx,
- int node_idx, int str_idx, int max_str_idx)
+ Idx node_idx, Idx str_idx, Idx max_str_idx)
{
const re_dfa_t *const dfa = mctx->dfa;
int naccepted;
- /* Check the node can accept `multi byte'. */
+ /* Check the node can accept "multi byte". */
naccepted = check_node_accept_bytes (dfa, node_idx, &mctx->input, str_idx);
if (naccepted > 0 && str_idx + naccepted <= max_str_idx &&
!STATE_NODE_CONTAINS (sctx->sifted_states[str_idx + naccepted],
dfa->nexts[node_idx]))
- /* The node can't accept the `multi byte', or the
+ /* The node can't accept the "multi byte", or the
destination was already thrown away, then the node
- could't accept the current input `multi byte'. */
+ could't accept the current input "multi byte". */
naccepted = 0;
/* Otherwise, it is sure that the node could accept
- `naccepted' bytes input. */
+ 'naccepted' bytes input. */
return naccepted;
}
#endif /* RE_ENABLE_I18N */
@@ -2247,7 +2220,7 @@ sift_states_iter_mb (const re_match_context_t *mctx, re_sift_context_t *sctx,
update the destination of STATE_LOG. */
static re_dfastate_t *
-internal_function __attribute_warn_unused_result__
+__attribute_warn_unused_result__
transit_state (reg_errcode_t *err, re_match_context_t *mctx,
re_dfastate_t *state)
{
@@ -2304,13 +2277,12 @@ transit_state (reg_errcode_t *err, re_match_context_t *mctx,
}
/* Update the state_log if we need */
-re_dfastate_t *
-internal_function
+static re_dfastate_t *
merge_state_with_log (reg_errcode_t *err, re_match_context_t *mctx,
re_dfastate_t *next_state)
{
const re_dfa_t *const dfa = mctx->dfa;
- int cur_idx = re_string_cur_idx (&mctx->input);
+ Idx cur_idx = re_string_cur_idx (&mctx->input);
if (cur_idx > mctx->state_log_top)
{
@@ -2383,15 +2355,14 @@ merge_state_with_log (reg_errcode_t *err, re_match_context_t *mctx,
/* Skip bytes in the input that correspond to part of a
multi-byte match, then look in the log for a state
from which to restart matching. */
-re_dfastate_t *
-internal_function
+static re_dfastate_t *
find_recover_state (reg_errcode_t *err, re_match_context_t *mctx)
{
re_dfastate_t *cur_state;
do
{
- int max = mctx->state_log_top;
- int cur_str_idx = re_string_cur_idx (&mctx->input);
+ Idx max = mctx->state_log_top;
+ Idx cur_str_idx = re_string_cur_idx (&mctx->input);
do
{
@@ -2412,15 +2383,14 @@ find_recover_state (reg_errcode_t *err, re_match_context_t *mctx)
/* From the node set CUR_NODES, pick up the nodes whose types are
OP_OPEN_SUBEXP and which have corresponding back references in the regular
expression. And register them to use them later for evaluating the
- correspoding back references. */
+ corresponding back references. */
static reg_errcode_t
-internal_function
check_subexp_matching_top (re_match_context_t *mctx, re_node_set *cur_nodes,
- int str_idx)
+ Idx str_idx)
{
const re_dfa_t *const dfa = mctx->dfa;
- int node_idx;
+ Idx node_idx;
reg_errcode_t err;
/* TODO: This isn't efficient.
@@ -2430,7 +2400,7 @@ check_subexp_matching_top (re_match_context_t *mctx, re_node_set *cur_nodes,
E.g. RE: (a){2} */
for (node_idx = 0; node_idx < cur_nodes->nelem; ++node_idx)
{
- int node = cur_nodes->elems[node_idx];
+ Idx node = cur_nodes->elems[node_idx];
if (dfa->nodes[node].type == OP_OPEN_SUBEXP
&& dfa->nodes[node].opr.idx < BITSET_WORD_BITS
&& (dfa->used_bkref_map
@@ -2455,7 +2425,7 @@ transit_state_sb (reg_errcode_t *err, re_match_context_t *mctx,
const re_dfa_t *const dfa = mctx->dfa;
re_node_set next_nodes;
re_dfastate_t *next_state;
- int node_cnt, cur_str_idx = re_string_cur_idx (&mctx->input);
+ Idx node_cnt, cur_str_idx = re_string_cur_idx (&mctx->input);
unsigned int context;
*err = re_node_set_alloc (&next_nodes, state->nodes.nelem + 1);
@@ -2463,7 +2433,7 @@ transit_state_sb (reg_errcode_t *err, re_match_context_t *mctx,
return NULL;
for (node_cnt = 0; node_cnt < state->nodes.nelem; ++node_cnt)
{
- int cur_node = state->nodes.elems[node_cnt];
+ Idx cur_node = state->nodes.elems[node_cnt];
if (check_node_accept (mctx, dfa->nodes + cur_node, cur_str_idx))
{
*err = re_node_set_merge (&next_nodes,
@@ -2488,18 +2458,18 @@ transit_state_sb (reg_errcode_t *err, re_match_context_t *mctx,
#ifdef RE_ENABLE_I18N
static reg_errcode_t
-internal_function
transit_state_mb (re_match_context_t *mctx, re_dfastate_t *pstate)
{
const re_dfa_t *const dfa = mctx->dfa;
reg_errcode_t err;
- int i;
+ Idx i;
for (i = 0; i < pstate->nodes.nelem; ++i)
{
re_node_set dest_nodes, *new_nodes;
- int cur_node_idx = pstate->nodes.elems[i];
- int naccepted, dest_idx;
+ Idx cur_node_idx = pstate->nodes.elems[i];
+ int naccepted;
+ Idx dest_idx;
unsigned int context;
re_dfastate_t *dest_state;
@@ -2522,7 +2492,7 @@ transit_state_mb (re_match_context_t *mctx, re_dfastate_t *pstate)
if (naccepted == 0)
continue;
- /* The node can accepts `naccepted' bytes. */
+ /* The node can accepts 'naccepted' bytes. */
dest_idx = re_string_cur_idx (&mctx->input) + naccepted;
mctx->max_mb_elem_len = ((mctx->max_mb_elem_len < naccepted) ? naccepted
: mctx->max_mb_elem_len);
@@ -2558,23 +2528,22 @@ transit_state_mb (re_match_context_t *mctx, re_dfastate_t *pstate)
#endif /* RE_ENABLE_I18N */
static reg_errcode_t
-internal_function
transit_state_bkref (re_match_context_t *mctx, const re_node_set *nodes)
{
const re_dfa_t *const dfa = mctx->dfa;
reg_errcode_t err;
- int i;
- int cur_str_idx = re_string_cur_idx (&mctx->input);
+ Idx i;
+ Idx cur_str_idx = re_string_cur_idx (&mctx->input);
for (i = 0; i < nodes->nelem; ++i)
{
- int dest_str_idx, prev_nelem, bkc_idx;
- int node_idx = nodes->elems[i];
+ Idx dest_str_idx, prev_nelem, bkc_idx;
+ Idx node_idx = nodes->elems[i];
unsigned int context;
const re_token_t *node = dfa->nodes + node_idx;
re_node_set *new_dest_nodes;
- /* Check whether `node' is a backreference or not. */
+ /* Check whether 'node' is a backreference or not. */
if (node->type != OP_BACK_REF)
continue;
@@ -2586,21 +2555,21 @@ transit_state_bkref (re_match_context_t *mctx, const re_node_set *nodes)
continue;
}
- /* `node' is a backreference.
+ /* 'node' is a backreference.
Check the substring which the substring matched. */
bkc_idx = mctx->nbkref_ents;
err = get_subexp (mctx, node_idx, cur_str_idx);
if (BE (err != REG_NOERROR, 0))
goto free_return;
- /* And add the epsilon closures (which is `new_dest_nodes') of
+ /* And add the epsilon closures (which is 'new_dest_nodes') of
the backreference to appropriate state_log. */
#ifdef DEBUG
assert (dfa->nexts[node_idx] != -1);
#endif
for (; bkc_idx < mctx->nbkref_ents; ++bkc_idx)
{
- int subexp_len;
+ Idx subexp_len;
re_dfastate_t *dest_state;
struct re_backref_cache_entry *bkref_ent;
bkref_ent = mctx->bkref_ents + bkc_idx;
@@ -2617,7 +2586,7 @@ transit_state_bkref (re_match_context_t *mctx, const re_node_set *nodes)
dest_state = mctx->state_log[dest_str_idx];
prev_nelem = ((mctx->state_log[cur_str_idx] == NULL) ? 0
: mctx->state_log[cur_str_idx]->nodes.nelem);
- /* Add `new_dest_node' to state_log. */
+ /* Add 'new_dest_node' to state_log. */
if (dest_state == NULL)
{
mctx->state_log[dest_str_idx]
@@ -2672,14 +2641,14 @@ transit_state_bkref (re_match_context_t *mctx, const re_node_set *nodes)
delay these checking for prune_impossible_nodes(). */
static reg_errcode_t
-internal_function __attribute_warn_unused_result__
-get_subexp (re_match_context_t *mctx, int bkref_node, int bkref_str_idx)
+__attribute_warn_unused_result__
+get_subexp (re_match_context_t *mctx, Idx bkref_node, Idx bkref_str_idx)
{
const re_dfa_t *const dfa = mctx->dfa;
- int subexp_num, sub_top_idx;
+ Idx subexp_num, sub_top_idx;
const char *buf = (const char *) re_string_get_buffer (&mctx->input);
/* Return if we have already checked BKREF_NODE at BKREF_STR_IDX. */
- int cache_idx = search_cur_bkref_entry (mctx, bkref_str_idx);
+ Idx cache_idx = search_cur_bkref_entry (mctx, bkref_str_idx);
if (cache_idx != -1)
{
const struct re_backref_cache_entry *entry
@@ -2698,7 +2667,7 @@ get_subexp (re_match_context_t *mctx, int bkref_node, int bkref_str_idx)
reg_errcode_t err;
re_sub_match_top_t *sub_top = mctx->sub_tops[sub_top_idx];
re_sub_match_last_t *sub_last;
- int sub_last_idx, sl_str, bkref_str_off;
+ Idx sub_last_idx, sl_str, bkref_str_off;
if (dfa->nodes[sub_top->node].opr.idx != subexp_num)
continue; /* It isn't related. */
@@ -2709,7 +2678,7 @@ get_subexp (re_match_context_t *mctx, int bkref_node, int bkref_str_idx)
evaluated. */
for (sub_last_idx = 0; sub_last_idx < sub_top->nlasts; ++sub_last_idx)
{
- int sl_str_diff;
+ regoff_t sl_str_diff;
sub_last = sub_top->lasts[sub_last_idx];
sl_str_diff = sub_last->str_idx - sl_str;
/* The matched string by the sub expression match with the substring
@@ -2755,7 +2724,8 @@ get_subexp (re_match_context_t *mctx, int bkref_node, int bkref_str_idx)
/* Then, search for the other last nodes of the sub expression. */
for (; sl_str <= bkref_str_idx; ++sl_str)
{
- int cls_node, sl_str_off;
+ Idx cls_node;
+ regoff_t sl_str_off;
const re_node_set *nodes;
sl_str_off = sl_str - sub_top->str_idx;
/* The matched string by the sub expression match with the substring
@@ -2821,12 +2791,11 @@ get_subexp (re_match_context_t *mctx, int bkref_node, int bkref_str_idx)
and SUB_LAST. */
static reg_errcode_t
-internal_function
get_subexp_sub (re_match_context_t *mctx, const re_sub_match_top_t *sub_top,
- re_sub_match_last_t *sub_last, int bkref_node, int bkref_str)
+ re_sub_match_last_t *sub_last, Idx bkref_node, Idx bkref_str)
{
reg_errcode_t err;
- int to_idx;
+ Idx to_idx;
/* Can the subexpression arrive the back reference? */
err = check_arrival (mctx, &sub_last->path, sub_last->node,
sub_last->str_idx, bkref_node, bkref_str,
@@ -2849,15 +2818,14 @@ get_subexp_sub (re_match_context_t *mctx, const re_sub_match_top_t *sub_top,
nodes.
E.g. RE: (a){2} */
-static int
-internal_function
+static Idx
find_subexp_node (const re_dfa_t *dfa, const re_node_set *nodes,
- int subexp_idx, int type)
+ Idx subexp_idx, int type)
{
- int cls_idx;
+ Idx cls_idx;
for (cls_idx = 0; cls_idx < nodes->nelem; ++cls_idx)
{
- int cls_node = nodes->elems[cls_idx];
+ Idx cls_node = nodes->elems[cls_idx];
const re_token_t *node = dfa->nodes + cls_node;
if (node->type == type
&& node->opr.idx == subexp_idx)
@@ -2872,13 +2840,13 @@ find_subexp_node (const re_dfa_t *dfa, const re_node_set *nodes,
Return REG_NOERROR if it can arrive, or REG_NOMATCH otherwise. */
static reg_errcode_t
-internal_function __attribute_warn_unused_result__
-check_arrival (re_match_context_t *mctx, state_array_t *path, int top_node,
- int top_str, int last_node, int last_str, int type)
+__attribute_warn_unused_result__
+check_arrival (re_match_context_t *mctx, state_array_t *path, Idx top_node,
+ Idx top_str, Idx last_node, Idx last_str, int type)
{
const re_dfa_t *const dfa = mctx->dfa;
reg_errcode_t err = REG_NOERROR;
- int subexp_num, backup_cur_idx, str_idx, null_cnt;
+ Idx subexp_num, backup_cur_idx, str_idx, null_cnt;
re_dfastate_t *cur_state = NULL;
re_node_set *cur_nodes, next_nodes;
re_dfastate_t **backup_state_log;
@@ -2889,20 +2857,24 @@ check_arrival (re_match_context_t *mctx, state_array_t *path, int top_node,
if (BE (path->alloc < last_str + mctx->max_mb_elem_len + 1, 0))
{
re_dfastate_t **new_array;
- int old_alloc = path->alloc;
- path->alloc += last_str + mctx->max_mb_elem_len + 1;
- new_array = re_realloc (path->array, re_dfastate_t *, path->alloc);
+ Idx old_alloc = path->alloc;
+ Idx incr_alloc = last_str + mctx->max_mb_elem_len + 1;
+ Idx new_alloc;
+ if (BE (IDX_MAX - old_alloc < incr_alloc, 0))
+ return REG_ESPACE;
+ new_alloc = old_alloc + incr_alloc;
+ if (BE (SIZE_MAX / sizeof (re_dfastate_t *) < new_alloc, 0))
+ return REG_ESPACE;
+ new_array = re_realloc (path->array, re_dfastate_t *, new_alloc);
if (BE (new_array == NULL, 0))
- {
- path->alloc = old_alloc;
- return REG_ESPACE;
- }
+ return REG_ESPACE;
path->array = new_array;
+ path->alloc = new_alloc;
memset (new_array + old_alloc, '\0',
sizeof (re_dfastate_t *) * (path->alloc - old_alloc));
}
- str_idx = path->next_idx ?: top_str;
+ str_idx = path->next_idx ? path->next_idx : top_str;
/* Temporary modify MCTX. */
backup_state_log = mctx->state_log;
@@ -3033,26 +3005,28 @@ check_arrival (re_match_context_t *mctx, state_array_t *path, int top_node,
Can't we unify them? */
static reg_errcode_t
-internal_function __attribute_warn_unused_result__
-check_arrival_add_next_nodes (re_match_context_t *mctx, int str_idx,
+__attribute_warn_unused_result__
+check_arrival_add_next_nodes (re_match_context_t *mctx, Idx str_idx,
re_node_set *cur_nodes, re_node_set *next_nodes)
{
const re_dfa_t *const dfa = mctx->dfa;
- int result;
- int cur_idx;
+ bool ok;
+ Idx cur_idx;
+#ifdef RE_ENABLE_I18N
reg_errcode_t err = REG_NOERROR;
+#endif
re_node_set union_set;
re_node_set_init_empty (&union_set);
for (cur_idx = 0; cur_idx < cur_nodes->nelem; ++cur_idx)
{
int naccepted = 0;
- int cur_node = cur_nodes->elems[cur_idx];
+ Idx cur_node = cur_nodes->elems[cur_idx];
#ifdef DEBUG
re_token_type_t type = dfa->nodes[cur_node].type;
assert (!IS_EPSILON_NODE (type));
#endif
#ifdef RE_ENABLE_I18N
- /* If the node may accept `multi byte'. */
+ /* If the node may accept "multi byte". */
if (dfa->nodes[cur_node].accept_mb)
{
naccepted = check_node_accept_bytes (dfa, cur_node, &mctx->input,
@@ -3060,8 +3034,8 @@ check_arrival_add_next_nodes (re_match_context_t *mctx, int str_idx,
if (naccepted > 1)
{
re_dfastate_t *dest_state;
- int next_node = dfa->nexts[cur_node];
- int next_idx = str_idx + naccepted;
+ Idx next_node = dfa->nexts[cur_node];
+ Idx next_idx = str_idx + naccepted;
dest_state = mctx->state_log[next_idx];
re_node_set_empty (&union_set);
if (dest_state)
@@ -3073,8 +3047,8 @@ check_arrival_add_next_nodes (re_match_context_t *mctx, int str_idx,
return err;
}
}
- result = re_node_set_insert (&union_set, next_node);
- if (BE (result < 0, 0))
+ ok = re_node_set_insert (&union_set, next_node);
+ if (BE (! ok, 0))
{
re_node_set_free (&union_set);
return REG_ESPACE;
@@ -3093,8 +3067,8 @@ check_arrival_add_next_nodes (re_match_context_t *mctx, int str_idx,
if (naccepted
|| check_node_accept (mctx, dfa->nodes + cur_node, str_idx))
{
- result = re_node_set_insert (next_nodes, dfa->nexts[cur_node]);
- if (BE (result < 0, 0))
+ ok = re_node_set_insert (next_nodes, dfa->nexts[cur_node]);
+ if (BE (! ok, 0))
{
re_node_set_free (&union_set);
return REG_ESPACE;
@@ -3112,12 +3086,11 @@ check_arrival_add_next_nodes (re_match_context_t *mctx, int str_idx,
*/
static reg_errcode_t
-internal_function
check_arrival_expand_ecl (const re_dfa_t *dfa, re_node_set *cur_nodes,
- int ex_subexp, int type)
+ Idx ex_subexp, int type)
{
reg_errcode_t err;
- int idx, outside_node;
+ Idx idx, outside_node;
re_node_set new_nodes;
#ifdef DEBUG
assert (cur_nodes->nelem);
@@ -3130,7 +3103,7 @@ check_arrival_expand_ecl (const re_dfa_t *dfa, re_node_set *cur_nodes,
for (idx = 0; idx < cur_nodes->nelem; ++idx)
{
- int cur_node = cur_nodes->elems[idx];
+ Idx cur_node = cur_nodes->elems[idx];
const re_node_set *eclosure = dfa->eclosures + cur_node;
outside_node = find_subexp_node (dfa, eclosure, ex_subexp, type);
if (outside_node == -1)
@@ -3165,33 +3138,34 @@ check_arrival_expand_ecl (const re_dfa_t *dfa, re_node_set *cur_nodes,
problematic append it to DST_NODES. */
static reg_errcode_t
-internal_function __attribute_warn_unused_result__
+__attribute_warn_unused_result__
check_arrival_expand_ecl_sub (const re_dfa_t *dfa, re_node_set *dst_nodes,
- int target, int ex_subexp, int type)
+ Idx target, Idx ex_subexp, int type)
{
- int cur_node;
+ Idx cur_node;
for (cur_node = target; !re_node_set_contains (dst_nodes, cur_node);)
{
- int err;
+ bool ok;
if (dfa->nodes[cur_node].type == type
&& dfa->nodes[cur_node].opr.idx == ex_subexp)
{
if (type == OP_CLOSE_SUBEXP)
{
- err = re_node_set_insert (dst_nodes, cur_node);
- if (BE (err == -1, 0))
+ ok = re_node_set_insert (dst_nodes, cur_node);
+ if (BE (! ok, 0))
return REG_ESPACE;
}
break;
}
- err = re_node_set_insert (dst_nodes, cur_node);
- if (BE (err == -1, 0))
+ ok = re_node_set_insert (dst_nodes, cur_node);
+ if (BE (! ok, 0))
return REG_ESPACE;
if (dfa->edests[cur_node].nelem == 0)
break;
if (dfa->edests[cur_node].nelem == 2)
{
+ reg_errcode_t err;
err = check_arrival_expand_ecl_sub (dfa, dst_nodes,
dfa->edests[cur_node].elems[1],
ex_subexp, type);
@@ -3209,13 +3183,13 @@ check_arrival_expand_ecl_sub (const re_dfa_t *dfa, re_node_set *dst_nodes,
in MCTX->BKREF_ENTS. */
static reg_errcode_t
-internal_function __attribute_warn_unused_result__
+__attribute_warn_unused_result__
expand_bkref_cache (re_match_context_t *mctx, re_node_set *cur_nodes,
- int cur_str, int subexp_num, int type)
+ Idx cur_str, Idx subexp_num, int type)
{
const re_dfa_t *const dfa = mctx->dfa;
reg_errcode_t err;
- int cache_idx_start = search_cur_bkref_entry (mctx, cur_str);
+ Idx cache_idx_start = search_cur_bkref_entry (mctx, cur_str);
struct re_backref_cache_entry *ent;
if (cache_idx_start == -1)
@@ -3225,7 +3199,7 @@ expand_bkref_cache (re_match_context_t *mctx, re_node_set *cur_nodes,
ent = mctx->bkref_ents + cache_idx_start;
do
{
- int to_idx, next_node;
+ Idx to_idx, next_node;
/* Is this entry ENT is appropriate? */
if (!re_node_set_contains (cur_nodes, ent->node))
@@ -3263,14 +3237,14 @@ expand_bkref_cache (re_match_context_t *mctx, re_node_set *cur_nodes,
next_node = dfa->nexts[ent->node];
if (mctx->state_log[to_idx])
{
- int ret;
+ bool ok;
if (re_node_set_contains (&mctx->state_log[to_idx]->nodes,
next_node))
continue;
err = re_node_set_init_copy (&union_set,
&mctx->state_log[to_idx]->nodes);
- ret = re_node_set_insert (&union_set, next_node);
- if (BE (err != REG_NOERROR || ret < 0, 0))
+ ok = re_node_set_insert (&union_set, next_node);
+ if (BE (err != REG_NOERROR || ! ok, 0))
{
re_node_set_free (&union_set);
err = err != REG_NOERROR ? err : REG_ESPACE;
@@ -3295,18 +3269,19 @@ expand_bkref_cache (re_match_context_t *mctx, re_node_set *cur_nodes,
}
/* Build transition table for the state.
- Return 1 if succeeded, otherwise return NULL. */
+ Return true if successful. */
-static int
-internal_function
+static bool
build_trtable (const re_dfa_t *dfa, re_dfastate_t *state)
{
reg_errcode_t err;
- int i, j, ch, need_word_trtable = 0;
+ Idx i, j;
+ int ch;
+ bool need_word_trtable = false;
bitset_word_t elem, mask;
bool dests_node_malloced = false;
bool dest_states_malloced = false;
- int ndests; /* Number of the destination states from `state'. */
+ Idx ndests; /* Number of the destination states from 'state'. */
re_dfastate_t **trtable;
re_dfastate_t **dest_states = NULL, **dest_states_word, **dest_states_nl;
re_node_set follows, *dests_node;
@@ -3320,8 +3295,8 @@ build_trtable (const re_dfa_t *dfa, re_dfastate_t *state)
} *dests_alloc;
/* We build DFA states which corresponds to the destination nodes
- from `state'. `dests_node[i]' represents the nodes which i-th
- destination state contains, and `dests_ch[i]' represents the
+ from 'state'. 'dests_node[i]' represents the nodes which i-th
+ destination state contains, and 'dests_ch[i]' represents the
characters which i-th destination state accepts. */
if (__libc_use_alloca (sizeof (struct dests_alloc)))
dests_alloc = (struct dests_alloc *) alloca (sizeof (struct dests_alloc));
@@ -3329,32 +3304,32 @@ build_trtable (const re_dfa_t *dfa, re_dfastate_t *state)
{
dests_alloc = re_malloc (struct dests_alloc, 1);
if (BE (dests_alloc == NULL, 0))
- return 0;
+ return false;
dests_node_malloced = true;
}
dests_node = dests_alloc->dests_node;
dests_ch = dests_alloc->dests_ch;
- /* Initialize transiton table. */
+ /* Initialize transition table. */
state->word_trtable = state->trtable = NULL;
- /* At first, group all nodes belonging to `state' into several
+ /* At first, group all nodes belonging to 'state' into several
destinations. */
ndests = group_nodes_into_DFAstates (dfa, state, dests_node, dests_ch);
if (BE (ndests <= 0, 0))
{
if (dests_node_malloced)
- free (dests_alloc);
- /* Return 0 in case of an error, 1 otherwise. */
+ re_free (dests_alloc);
+ /* Return false in case of an error, true otherwise. */
if (ndests == 0)
{
state->trtable = (re_dfastate_t **)
calloc (sizeof (re_dfastate_t *), SBC_MAX);
- if (BE (state->trtable == NULL, 0))
- return 0;
- return 1;
+ if (BE (state->trtable == NULL, 0))
+ return false;
+ return true;
}
- return 0;
+ return false;
}
err = re_node_set_alloc (&follows, ndests + 1);
@@ -3374,19 +3349,18 @@ build_trtable (const re_dfa_t *dfa, re_dfastate_t *state)
alloca (ndests * 3 * sizeof (re_dfastate_t *));
else
{
- dest_states = (re_dfastate_t **)
- malloc (ndests * 3 * sizeof (re_dfastate_t *));
+ dest_states = re_malloc (re_dfastate_t *, ndests * 3);
if (BE (dest_states == NULL, 0))
{
out_free:
if (dest_states_malloced)
- free (dest_states);
+ re_free (dest_states);
re_node_set_free (&follows);
for (i = 0; i < ndests; ++i)
re_node_set_free (dests_node + i);
if (dests_node_malloced)
- free (dests_alloc);
- return 0;
+ re_free (dests_alloc);
+ return false;
}
dest_states_malloced = true;
}
@@ -3397,7 +3371,7 @@ out_free:
/* Then build the states for all destinations. */
for (i = 0; i < ndests; ++i)
{
- int next_node;
+ Idx next_node;
re_node_set_empty (&follows);
/* Merge the follows of this destination states. */
for (j = 0; j < dests_node[i].nelem; ++j)
@@ -3423,13 +3397,13 @@ out_free:
goto out_free;
if (dest_states[i] != dest_states_word[i] && dfa->mb_cur_max > 1)
- need_word_trtable = 1;
+ need_word_trtable = true;
dest_states_nl[i] = re_acquire_state_context (&err, dfa, &follows,
CONTEXT_NEWLINE);
if (BE (dest_states_nl[i] == NULL && err != REG_NOERROR, 0))
goto out_free;
- }
+ }
else
{
dest_states_word[i] = dest_states[i];
@@ -3516,16 +3490,16 @@ out_free:
}
if (dest_states_malloced)
- free (dest_states);
+ re_free (dest_states);
re_node_set_free (&follows);
for (i = 0; i < ndests; ++i)
re_node_set_free (dests_node + i);
if (dests_node_malloced)
- free (dests_alloc);
+ re_free (dests_alloc);
- return 1;
+ return true;
}
/* Group all nodes belonging to STATE into several destinations.
@@ -3533,21 +3507,20 @@ out_free:
to DESTS_NODE[i] and set the characters accepted by the destination
to DEST_CH[i]. This function return the number of destinations. */
-static int
-internal_function
+static Idx
group_nodes_into_DFAstates (const re_dfa_t *dfa, const re_dfastate_t *state,
re_node_set *dests_node, bitset_t *dests_ch)
{
reg_errcode_t err;
- int result;
- int i, j, k;
- int ndests; /* Number of the destinations from `state'. */
+ bool ok;
+ Idx i, j, k;
+ Idx ndests; /* Number of the destinations from 'state'. */
bitset_t accepts; /* Characters a node can accept. */
const re_node_set *cur_nodes = &state->nodes;
bitset_empty (accepts);
ndests = 0;
- /* For all the nodes belonging to `state', */
+ /* For all the nodes belonging to 'state', */
for (i = 0; i < cur_nodes->nelem; ++i)
{
re_token_t *node = &dfa->nodes[cur_nodes->elems[i]];
@@ -3577,7 +3550,10 @@ group_nodes_into_DFAstates (const re_dfa_t *dfa, const re_dfastate_t *state,
#ifdef RE_ENABLE_I18N
else if (type == OP_UTF8_PERIOD)
{
- memset (accepts, '\xff', sizeof (bitset_t) / 2);
+ if (ASCII_CHARS % BITSET_WORD_BITS == 0)
+ memset (accepts, -1, ASCII_CHARS / CHAR_BIT);
+ else
+ bitset_merge (accepts, utf8_sb_map);
if (!(dfa->syntax & RE_DOT_NEWLINE))
bitset_clear (accepts, '\n');
if (dfa->syntax & RE_DOT_NOT_NULL)
@@ -3587,7 +3563,7 @@ group_nodes_into_DFAstates (const re_dfa_t *dfa, const re_dfastate_t *state,
else
continue;
- /* Check the `accepts' and sift the characters which are not
+ /* Check the 'accepts' and sift the characters which are not
match it the context. */
if (constraint)
{
@@ -3646,7 +3622,7 @@ group_nodes_into_DFAstates (const re_dfa_t *dfa, const re_dfastate_t *state,
}
}
- /* Then divide `accepts' into DFA states, or create a new
+ /* Then divide 'accepts' into DFA states, or create a new
state. Above, we make sure that accepts is not empty. */
for (j = 0; j < ndests; ++j)
{
@@ -3659,7 +3635,7 @@ group_nodes_into_DFAstates (const re_dfa_t *dfa, const re_dfastate_t *state,
if (type == CHARACTER && !bitset_contain (dests_ch[j], node->opr.c))
continue;
- /* Enumerate the intersection set of this state and `accepts'. */
+ /* Enumerate the intersection set of this state and 'accepts'. */
has_intersec = 0;
for (k = 0; k < BITSET_WORDS; ++k)
has_intersec |= intersec[k] = accepts[k] & dests_ch[j][k];
@@ -3667,7 +3643,7 @@ group_nodes_into_DFAstates (const re_dfa_t *dfa, const re_dfastate_t *state,
if (!has_intersec)
continue;
- /* Then check if this state is a subset of `accepts'. */
+ /* Then check if this state is a subset of 'accepts'. */
not_subset = not_consumed = 0;
for (k = 0; k < BITSET_WORDS; ++k)
{
@@ -3675,8 +3651,8 @@ group_nodes_into_DFAstates (const re_dfa_t *dfa, const re_dfastate_t *state,
not_consumed |= accepts[k] = accepts[k] & ~dests_ch[j][k];
}
- /* If this state isn't a subset of `accepts', create a
- new group state, which has the `remains'. */
+ /* If this state isn't a subset of 'accepts', create a
+ new group state, which has the 'remains'. */
if (not_subset)
{
bitset_copy (dests_ch[ndests], remains);
@@ -3688,8 +3664,8 @@ group_nodes_into_DFAstates (const re_dfa_t *dfa, const re_dfastate_t *state,
}
/* Put the position in the current group. */
- result = re_node_set_insert (&dests_node[j], cur_nodes->elems[i]);
- if (BE (result < 0, 0))
+ ok = re_node_set_insert (&dests_node[j], cur_nodes->elems[i]);
+ if (BE (! ok, 0))
goto error_return;
/* If all characters are consumed, go to next node. */
@@ -3715,7 +3691,7 @@ group_nodes_into_DFAstates (const re_dfa_t *dfa, const re_dfastate_t *state,
}
#ifdef RE_ENABLE_I18N
-/* Check how many bytes the node `dfa->nodes[node_idx]' accepts.
+/* Check how many bytes the node 'dfa->nodes[node_idx]' accepts.
Return the number of the bytes the node accepts.
STR_IDX is the current index of the input string.
@@ -3728,13 +3704,12 @@ group_nodes_into_DFAstates (const re_dfa_t *dfa, const re_dfastate_t *state,
# endif
static int
-internal_function
-check_node_accept_bytes (const re_dfa_t *dfa, int node_idx,
- const re_string_t *input, int str_idx)
+check_node_accept_bytes (const re_dfa_t *dfa, Idx node_idx,
+ const re_string_t *input, Idx str_idx)
{
const re_token_t *node = dfa->nodes + node_idx;
int char_len, elem_len;
- int i;
+ Idx i;
if (BE (node->type == OP_UTF8_PERIOD, 0))
{
@@ -3813,7 +3788,7 @@ check_node_accept_bytes (const re_dfa_t *dfa, int node_idx,
# ifdef _LIBC
const unsigned char *pin
= ((const unsigned char *) re_string_get_buffer (input) + str_idx);
- int j;
+ Idx j;
uint32_t nrules;
# endif /* _LIBC */
int match_len = 0;
@@ -3881,6 +3856,7 @@ check_node_accept_bytes (const re_dfa_t *dfa, int node_idx,
in_collseq = find_collation_sequence_value (pin, elem_len);
}
/* match with range expression? */
+ /* FIXME: Implement rational ranges here, too. */
for (i = 0; i < cset->nranges; ++i)
if (cset->range_starts[i] <= in_collseq
&& in_collseq <= cset->range_ends[i])
@@ -3902,48 +3878,36 @@ check_node_accept_bytes (const re_dfa_t *dfa, int node_idx,
indirect = (const int32_t *)
_NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTMB);
int32_t idx = findidx (table, indirect, extra, &cp, elem_len);
+ int32_t rule = idx >> 24;
+ idx &= 0xffffff;
if (idx > 0)
- for (i = 0; i < cset->nequiv_classes; ++i)
- {
- int32_t equiv_class_idx = cset->equiv_classes[i];
- size_t weight_len = weights[idx & 0xffffff];
- if (weight_len == weights[equiv_class_idx & 0xffffff]
- && (idx >> 24) == (equiv_class_idx >> 24))
- {
- int cnt = 0;
-
- idx &= 0xffffff;
- equiv_class_idx &= 0xffffff;
-
- while (cnt <= weight_len
- && (weights[equiv_class_idx + 1 + cnt]
- == weights[idx + 1 + cnt]))
- ++cnt;
- if (cnt > weight_len)
- {
- match_len = elem_len;
- goto check_node_accept_bytes_match;
- }
- }
- }
+ {
+ size_t weight_len = weights[idx];
+ for (i = 0; i < cset->nequiv_classes; ++i)
+ {
+ int32_t equiv_class_idx = cset->equiv_classes[i];
+ int32_t equiv_class_rule = equiv_class_idx >> 24;
+ equiv_class_idx &= 0xffffff;
+ if (weights[equiv_class_idx] == weight_len
+ && equiv_class_rule == rule
+ && memcmp (weights + idx + 1,
+ weights + equiv_class_idx + 1,
+ weight_len) == 0)
+ {
+ match_len = elem_len;
+ goto check_node_accept_bytes_match;
+ }
+ }
+ }
}
}
else
# endif /* _LIBC */
{
/* match with range expression? */
-#if __GNUC__ >= 2
- wchar_t cmp_buf[] = {L'\0', L'\0', wc, L'\0', L'\0', L'\0'};
-#else
- wchar_t cmp_buf[] = {L'\0', L'\0', L'\0', L'\0', L'\0', L'\0'};
- cmp_buf[2] = wc;
-#endif
for (i = 0; i < cset->nranges; ++i)
{
- cmp_buf[0] = cset->range_starts[i];
- cmp_buf[4] = cset->range_ends[i];
- if (__wcscoll (cmp_buf, cmp_buf + 2) <= 0
- && __wcscoll (cmp_buf + 2, cmp_buf + 4) <= 0)
+ if (cset->range_starts[i] <= wc && wc <= cset->range_ends[i])
{
match_len = char_len;
goto check_node_accept_bytes_match;
@@ -3966,7 +3930,6 @@ check_node_accept_bytes (const re_dfa_t *dfa, int node_idx,
# ifdef _LIBC
static unsigned int
-internal_function
find_collation_sequence_value (const unsigned char *mbs, size_t mbs_len)
{
uint32_t nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
@@ -3991,7 +3954,8 @@ find_collation_sequence_value (const unsigned char *mbs, size_t mbs_len)
for (idx = 0; idx < extrasize;)
{
- int mbs_cnt, found = 0;
+ int mbs_cnt;
+ bool found = false;
int32_t elem_mbs_len;
/* Skip the name of collating element name. */
idx = idx + extra[idx] + 1;
@@ -4003,7 +3967,7 @@ find_collation_sequence_value (const unsigned char *mbs, size_t mbs_len)
break;
if (mbs_cnt == elem_mbs_len)
/* Found the entry. */
- found = 1;
+ found = true;
}
/* Skip the byte sequence of the collating element. */
idx += elem_mbs_len;
@@ -4028,10 +3992,9 @@ find_collation_sequence_value (const unsigned char *mbs, size_t mbs_len)
/* Check whether the node accepts the byte which is IDX-th
byte of the INPUT. */
-static int
-internal_function
+static bool
check_node_accept (const re_match_context_t *mctx, const re_token_t *node,
- int idx)
+ Idx idx)
{
unsigned char ch;
ch = re_string_byte_at (&mctx->input, idx);
@@ -4039,28 +4002,28 @@ check_node_accept (const re_match_context_t *mctx, const re_token_t *node,
{
case CHARACTER:
if (node->opr.c != ch)
- return 0;
+ return false;
break;
case SIMPLE_BRACKET:
if (!bitset_contain (node->opr.sbcset, ch))
- return 0;
+ return false;
break;
#ifdef RE_ENABLE_I18N
case OP_UTF8_PERIOD:
- if (ch >= 0x80)
- return 0;
- /* FALLTHROUGH */
+ if (ch >= ASCII_CHARS)
+ return false;
+ FALLTHROUGH;
#endif
case OP_PERIOD:
if ((ch == '\n' && !(mctx->dfa->syntax & RE_DOT_NEWLINE))
|| (ch == '\0' && (mctx->dfa->syntax & RE_DOT_NOT_NULL)))
- return 0;
+ return false;
break;
default:
- return 0;
+ return false;
}
if (node->constraint)
@@ -4070,26 +4033,27 @@ check_node_accept (const re_match_context_t *mctx, const re_token_t *node,
unsigned int context = re_string_context_at (&mctx->input, idx,
mctx->eflags);
if (NOT_SATISFY_NEXT_CONSTRAINT (node->constraint, context))
- return 0;
+ return false;
}
- return 1;
+ return true;
}
/* Extend the buffers, if the buffers have run out. */
static reg_errcode_t
-internal_function __attribute_warn_unused_result__
+__attribute_warn_unused_result__
extend_buffers (re_match_context_t *mctx, int min_len)
{
reg_errcode_t ret;
re_string_t *pstr = &mctx->input;
/* Avoid overflow. */
- if (BE (INT_MAX / 2 / sizeof (re_dfastate_t *) <= pstr->bufs_len, 0))
+ if (BE (MIN (IDX_MAX, SIZE_MAX / sizeof (re_dfastate_t *)) / 2
+ <= pstr->bufs_len, 0))
return REG_ESPACE;
- /* Double the lengthes of the buffers, but allocate at least MIN_LEN. */
+ /* Double the lengths of the buffers, but allocate at least MIN_LEN. */
ret = re_string_realloc_buffers (pstr,
MAX (min_len,
MIN (pstr->len, pstr->bufs_len * 2)));
@@ -4144,13 +4108,20 @@ extend_buffers (re_match_context_t *mctx, int min_len)
/* Initialize MCTX. */
static reg_errcode_t
-internal_function __attribute_warn_unused_result__
-match_ctx_init (re_match_context_t *mctx, int eflags, int n)
+__attribute_warn_unused_result__
+match_ctx_init (re_match_context_t *mctx, int eflags, Idx n)
{
mctx->eflags = eflags;
mctx->match_last = -1;
if (n > 0)
{
+ /* Avoid overflow. */
+ size_t max_object_size =
+ MAX (sizeof (struct re_backref_cache_entry),
+ sizeof (re_sub_match_top_t *));
+ if (BE (MIN (IDX_MAX, SIZE_MAX / max_object_size) < n, 0))
+ return REG_ESPACE;
+
mctx->bkref_ents = re_malloc (struct re_backref_cache_entry, n);
mctx->sub_tops = re_malloc (re_sub_match_top_t *, n);
if (BE (mctx->bkref_ents == NULL || mctx->sub_tops == NULL, 0))
@@ -4172,13 +4143,12 @@ match_ctx_init (re_match_context_t *mctx, int eflags, int n)
of the input, or changes the input string. */
static void
-internal_function
match_ctx_clean (re_match_context_t *mctx)
{
- int st_idx;
+ Idx st_idx;
for (st_idx = 0; st_idx < mctx->nsub_tops; ++st_idx)
{
- int sl_idx;
+ Idx sl_idx;
re_sub_match_top_t *top = mctx->sub_tops[st_idx];
for (sl_idx = 0; sl_idx < top->nlasts; ++sl_idx)
{
@@ -4192,7 +4162,7 @@ match_ctx_clean (re_match_context_t *mctx)
re_free (top->path->array);
re_free (top->path);
}
- free (top);
+ re_free (top);
}
mctx->nsub_tops = 0;
@@ -4202,7 +4172,6 @@ match_ctx_clean (re_match_context_t *mctx)
/* Free all the memory associated with MCTX. */
static void
-internal_function
match_ctx_free (re_match_context_t *mctx)
{
/* First, free all the memory associated with MCTX->SUB_TOPS. */
@@ -4217,9 +4186,9 @@ match_ctx_free (re_match_context_t *mctx)
*/
static reg_errcode_t
-internal_function __attribute_warn_unused_result__
-match_ctx_add_entry (re_match_context_t *mctx, int node, int str_idx, int from,
- int to)
+__attribute_warn_unused_result__
+match_ctx_add_entry (re_match_context_t *mctx, Idx node, Idx str_idx, Idx from,
+ Idx to)
{
if (mctx->nbkref_ents >= mctx->abkref_ents)
{
@@ -4254,7 +4223,7 @@ match_ctx_add_entry (re_match_context_t *mctx, int node, int str_idx, int from,
A backreference does not epsilon-transition unless it is empty, so set
to all zeros if FROM != TO. */
mctx->bkref_ents[mctx->nbkref_ents].eps_reachable_subexps_map
- = (from == to ? ~0 : 0);
+ = (from == to ? -1 : 0);
mctx->bkref_ents[mctx->nbkref_ents++].more = 0;
if (mctx->max_mb_elem_len < to - from)
@@ -4262,14 +4231,13 @@ match_ctx_add_entry (re_match_context_t *mctx, int node, int str_idx, int from,
return REG_NOERROR;
}
-/* Search for the first entry which has the same str_idx, or -1 if none is
+/* Return the first entry with the same str_idx, or -1 if none is
found. Note that MCTX->BKREF_ENTS is already sorted by MCTX->STR_IDX. */
-static int
-internal_function
-search_cur_bkref_entry (const re_match_context_t *mctx, int str_idx)
+static Idx
+search_cur_bkref_entry (const re_match_context_t *mctx, Idx str_idx)
{
- int left, right, mid, last;
+ Idx left, right, mid, last;
last = right = mctx->nbkref_ents;
for (left = 0; left < right;)
{
@@ -4289,8 +4257,8 @@ search_cur_bkref_entry (const re_match_context_t *mctx, int str_idx)
at STR_IDX. */
static reg_errcode_t
-internal_function __attribute_warn_unused_result__
-match_ctx_add_subtop (re_match_context_t *mctx, int node, int str_idx)
+__attribute_warn_unused_result__
+match_ctx_add_subtop (re_match_context_t *mctx, Idx node, Idx str_idx)
{
#ifdef DEBUG
assert (mctx->sub_tops != NULL);
@@ -4298,7 +4266,7 @@ match_ctx_add_subtop (re_match_context_t *mctx, int node, int str_idx)
#endif
if (BE (mctx->nsub_tops == mctx->asub_tops, 0))
{
- int new_asub_tops = mctx->asub_tops * 2;
+ Idx new_asub_tops = mctx->asub_tops * 2;
re_sub_match_top_t **new_array = re_realloc (mctx->sub_tops,
re_sub_match_top_t *,
new_asub_tops);
@@ -4319,13 +4287,12 @@ match_ctx_add_subtop (re_match_context_t *mctx, int node, int str_idx)
at STR_IDX, whose corresponding OP_OPEN_SUBEXP is SUB_TOP. */
static re_sub_match_last_t *
-internal_function
-match_ctx_add_sublast (re_sub_match_top_t *subtop, int node, int str_idx)
+match_ctx_add_sublast (re_sub_match_top_t *subtop, Idx node, Idx str_idx)
{
re_sub_match_last_t *new_entry;
if (BE (subtop->nlasts == subtop->alasts, 0))
{
- int new_alasts = 2 * subtop->alasts + 1;
+ Idx new_alasts = 2 * subtop->alasts + 1;
re_sub_match_last_t **new_array = re_realloc (subtop->lasts,
re_sub_match_last_t *,
new_alasts);
@@ -4346,9 +4313,8 @@ match_ctx_add_sublast (re_sub_match_top_t *subtop, int node, int str_idx)
}
static void
-internal_function
sift_ctx_init (re_sift_context_t *sctx, re_dfastate_t **sifted_sts,
- re_dfastate_t **limited_sts, int last_node, int last_str_idx)
+ re_dfastate_t **limited_sts, Idx last_node, Idx last_str_idx)
{
sctx->sifted_states = sifted_sts;
sctx->limited_states = limited_sts;
diff --git a/posix/runptests.c b/posix/runptests.c
index c60d8e532a..cc8512b297 100644
--- a/posix/runptests.c
+++ b/posix/runptests.c
@@ -1,5 +1,5 @@
/* POSIX regex testsuite from IEEE 2003.2.
- Copyright (C) 1998-2016 Free Software Foundation, Inc.
+ Copyright (C) 1998-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
diff --git a/posix/sched.h b/posix/sched.h
index 253c963053..619b3b3a81 100644
--- a/posix/sched.h
+++ b/posix/sched.h
@@ -1,5 +1,5 @@
/* Definitions for POSIX 1003.1b-1993 (aka POSIX.4) scheduling interface.
- Copyright (C) 1996-2016 Free Software Foundation, Inc.
+ Copyright (C) 1996-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -25,24 +25,27 @@
#include <bits/types.h>
#define __need_size_t
+#define __need_NULL
#include <stddef.h>
-#ifdef __USE_XOPEN2K
-# define __need_time_t
-# define __need_timespec
+#include <bits/types/time_t.h>
+#include <bits/types/struct_timespec.h>
+#ifndef __USE_XOPEN2K
+# include <time.h>
#endif
-#include <time.h>
#ifndef __pid_t_defined
typedef __pid_t pid_t;
# define __pid_t_defined
#endif
-
/* Get system specific constant and data structure definitions. */
#include <bits/sched.h>
-/* Define the real names for the elements of `struct sched_param'. */
-#define sched_priority __sched_priority
+#include <bits/cpu-set.h>
+
+/* Backward compatibility. */
+#define sched_priority sched_priority
+#define __sched_priority sched_priority
__BEGIN_DECLS
diff --git a/posix/sched_cpualloc.c b/posix/sched_cpualloc.c
index 0c79ffbade..e14c926812 100644
--- a/posix/sched_cpualloc.c
+++ b/posix/sched_cpualloc.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2007-2016 Free Software Foundation, Inc.
+/* Copyright (C) 2007-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/posix/sched_cpucount.c b/posix/sched_cpucount.c
index e100269cbd..1853a400bf 100644
--- a/posix/sched_cpucount.c
+++ b/posix/sched_cpucount.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2007-2016 Free Software Foundation, Inc.
+/* Copyright (C) 2007-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -15,7 +15,6 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
-#include <limits.h>
#include <sched.h>
@@ -36,22 +35,16 @@ __sched_cpucount (size_t setsize, const cpu_set_t *setp)
if (l == 0)
continue;
-# if LONG_BIT > 32
- l = (l & 0x5555555555555555ul) + ((l >> 1) & 0x5555555555555555ul);
- l = (l & 0x3333333333333333ul) + ((l >> 2) & 0x3333333333333333ul);
- l = (l & 0x0f0f0f0f0f0f0f0ful) + ((l >> 4) & 0x0f0f0f0f0f0f0f0ful);
- l = (l & 0x00ff00ff00ff00fful) + ((l >> 8) & 0x00ff00ff00ff00fful);
- l = (l & 0x0000ffff0000fffful) + ((l >> 16) & 0x0000ffff0000fffful);
- l = (l & 0x00000000fffffffful) + ((l >> 32) & 0x00000000fffffffful);
-# else
- l = (l & 0x55555555ul) + ((l >> 1) & 0x55555555ul);
- l = (l & 0x33333333ul) + ((l >> 2) & 0x33333333ul);
- l = (l & 0x0f0f0f0ful) + ((l >> 4) & 0x0f0f0f0ful);
- l = (l & 0x00ff00fful) + ((l >> 8) & 0x00ff00fful);
- l = (l & 0x0000fffful) + ((l >> 16) & 0x0000fffful);
-# endif
-
- s += l;
+ _Static_assert (sizeof (l) == sizeof (unsigned int)
+ || sizeof (l) == sizeof (unsigned long)
+ || sizeof (l) == sizeof (unsigned long long),
+ "sizeof (__cpu_mask");
+ if (sizeof (__cpu_mask) == sizeof (unsigned int))
+ s += __builtin_popcount (l);
+ else if (sizeof (__cpu_mask) == sizeof (unsigned long))
+ s += __builtin_popcountl (l);
+ else
+ s += __builtin_popcountll (l);
#endif
}
diff --git a/posix/sched_cpufree.c b/posix/sched_cpufree.c
index db7286e637..0544f66183 100644
--- a/posix/sched_cpufree.c
+++ b/posix/sched_cpufree.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2007-2016 Free Software Foundation, Inc.
+/* Copyright (C) 2007-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/posix/sched_getaffinity.c b/posix/sched_getaffinity.c
index cf4d1b7bf2..8ad1417b1d 100644
--- a/posix/sched_getaffinity.c
+++ b/posix/sched_getaffinity.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002-2016 Free Software Foundation, Inc.
+/* Copyright (C) 2002-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/posix/sched_getp.c b/posix/sched_getp.c
index cae502188e..fc62564a28 100644
--- a/posix/sched_getp.c
+++ b/posix/sched_getp.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1996-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1996-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/posix/sched_gets.c b/posix/sched_gets.c
index 1b145efb6c..dc8c2766e0 100644
--- a/posix/sched_gets.c
+++ b/posix/sched_gets.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1996-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1996-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/posix/sched_primax.c b/posix/sched_primax.c
index 97cd9c09ed..387896a7d3 100644
--- a/posix/sched_primax.c
+++ b/posix/sched_primax.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1996-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1996-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -26,6 +26,7 @@ __sched_get_priority_max (int algorithm)
__set_errno (ENOSYS);
return -1;
}
+libc_hidden_def (__sched_get_priority_max)
stub_warning (sched_get_priority_max)
weak_alias (__sched_get_priority_max, sched_get_priority_max)
diff --git a/posix/sched_primin.c b/posix/sched_primin.c
index 7e2bfda9f6..e57536ba15 100644
--- a/posix/sched_primin.c
+++ b/posix/sched_primin.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1996-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1996-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -26,6 +26,7 @@ __sched_get_priority_min (int algorithm)
__set_errno (ENOSYS);
return -1;
}
+libc_hidden_def (__sched_get_priority_min)
stub_warning (sched_get_priority_min)
weak_alias (__sched_get_priority_min, sched_get_priority_min)
diff --git a/posix/sched_rr_gi.c b/posix/sched_rr_gi.c
index 1b32864488..e22371c301 100644
--- a/posix/sched_rr_gi.c
+++ b/posix/sched_rr_gi.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1996-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1996-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/posix/sched_setaffinity.c b/posix/sched_setaffinity.c
index f97f6a3f47..e21b75a26e 100644
--- a/posix/sched_setaffinity.c
+++ b/posix/sched_setaffinity.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002-2016 Free Software Foundation, Inc.
+/* Copyright (C) 2002-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/posix/sched_setp.c b/posix/sched_setp.c
index cde7b6003e..0e53e09c5c 100644
--- a/posix/sched_setp.c
+++ b/posix/sched_setp.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1996-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1996-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -29,4 +29,5 @@ __sched_setparam (pid_t pid, const struct sched_param *param)
}
stub_warning (sched_setparam)
+libc_hidden_def (__sched_setparam)
weak_alias (__sched_setparam, sched_setparam)
diff --git a/posix/sched_sets.c b/posix/sched_sets.c
index 69b39e98ec..556ed9a7bd 100644
--- a/posix/sched_sets.c
+++ b/posix/sched_sets.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1996-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1996-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/posix/sched_yield.c b/posix/sched_yield.c
index 7dd21ef7d1..6e39ce413e 100644
--- a/posix/sched_yield.c
+++ b/posix/sched_yield.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1996-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1996-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/posix/setgid.c b/posix/setgid.c
index 03e9030029..782614aebf 100644
--- a/posix/setgid.c
+++ b/posix/setgid.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/posix/setpgid.c b/posix/setpgid.c
index 753ac9ac22..5bdf7cc044 100644
--- a/posix/setpgid.c
+++ b/posix/setpgid.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/posix/setpgrp.c b/posix/setpgrp.c
index 9877824a04..5900f8b921 100644
--- a/posix/setpgrp.c
+++ b/posix/setpgrp.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1996-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1996-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/posix/setresgid.c b/posix/setresgid.c
index a371ea3f94..7f617619d8 100644
--- a/posix/setresgid.c
+++ b/posix/setresgid.c
@@ -1,5 +1,5 @@
/* setresgid -- set real group ID, effective group ID, and saved-set group ID
- Copyright (C) 2002-2016 Free Software Foundation, Inc.
+ Copyright (C) 2002-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/posix/setresuid.c b/posix/setresuid.c
index 29f526b9d7..0f3e1e8dbe 100644
--- a/posix/setresuid.c
+++ b/posix/setresuid.c
@@ -1,5 +1,5 @@
/* setresuid -- set real user ID, effective user ID, and saved-set user ID
- Copyright (C) 2002-2016 Free Software Foundation, Inc.
+ Copyright (C) 2002-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/posix/setsid.c b/posix/setsid.c
index 52e073a34b..c365c6dd49 100644
--- a/posix/setsid.c
+++ b/posix/setsid.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/posix/setuid.c b/posix/setuid.c
index e8b0f255a7..531a384ff4 100644
--- a/posix/setuid.c
+++ b/posix/setuid.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/posix/sleep.c b/posix/sleep.c
index 447510e411..48fd8e15ae 100644
--- a/posix/sleep.c
+++ b/posix/sleep.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/posix/spawn.c b/posix/spawn.c
index 562602d102..51f67b2755 100644
--- a/posix/spawn.c
+++ b/posix/spawn.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000-2016 Free Software Foundation, Inc.
+/* Copyright (C) 2000-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/posix/spawn.h b/posix/spawn.h
index f46e8c22c8..aafb27611c 100644
--- a/posix/spawn.h
+++ b/posix/spawn.h
@@ -1,5 +1,5 @@
/* Definitions for POSIX spawn interface.
- Copyright (C) 2000-2016 Free Software Foundation, Inc.
+ Copyright (C) 2000-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -21,9 +21,8 @@
#include <features.h>
#include <sched.h>
-#define __need_sigset_t
-#include <signal.h>
#include <sys/types.h>
+#include <bits/types/sigset_t.h>
/* Data structure to contain attributes for thread creation. */
@@ -59,6 +58,7 @@ typedef struct
#define POSIX_SPAWN_SETSCHEDULER 0x20
#ifdef __USE_GNU
# define POSIX_SPAWN_USEVFORK 0x40
+# define POSIX_SPAWN_SETSID 0x80
#endif
diff --git a/posix/spawn_faction_addclose.c b/posix/spawn_faction_addclose.c
index 1a4a2f2457..21081e19b5 100644
--- a/posix/spawn_faction_addclose.c
+++ b/posix/spawn_faction_addclose.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000-2016 Free Software Foundation, Inc.
+/* Copyright (C) 2000-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -27,11 +27,9 @@ int
posix_spawn_file_actions_addclose (posix_spawn_file_actions_t *file_actions,
int fd)
{
- int maxfd = __sysconf (_SC_OPEN_MAX);
struct __spawn_action *rec;
- /* Test for the validity of the file descriptor. */
- if (fd < 0 || fd >= maxfd)
+ if (!__spawn_valid_fd (fd))
return EBADF;
/* Allocate more memory if needed. */
diff --git a/posix/spawn_faction_adddup2.c b/posix/spawn_faction_adddup2.c
index 8beee1099b..363bc29ae5 100644
--- a/posix/spawn_faction_adddup2.c
+++ b/posix/spawn_faction_adddup2.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000-2016 Free Software Foundation, Inc.
+/* Copyright (C) 2000-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -27,11 +27,9 @@ int
posix_spawn_file_actions_adddup2 (posix_spawn_file_actions_t *file_actions,
int fd, int newfd)
{
- int maxfd = __sysconf (_SC_OPEN_MAX);
struct __spawn_action *rec;
- /* Test for the validity of the file descriptor. */
- if (fd < 0 || newfd < 0 || fd >= maxfd || newfd >= maxfd)
+ if (!__spawn_valid_fd (fd) || !__spawn_valid_fd (newfd))
return EBADF;
/* Allocate more memory if needed. */
diff --git a/posix/spawn_faction_addopen.c b/posix/spawn_faction_addopen.c
index 36cde06fb2..9f9c01faad 100644
--- a/posix/spawn_faction_addopen.c
+++ b/posix/spawn_faction_addopen.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000-2016 Free Software Foundation, Inc.
+/* Copyright (C) 2000-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -16,7 +16,6 @@
<http://www.gnu.org/licenses/>. */
#include <errno.h>
-#include <spawn.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
@@ -30,14 +29,12 @@ posix_spawn_file_actions_addopen (posix_spawn_file_actions_t *file_actions,
int fd, const char *path, int oflag,
mode_t mode)
{
- int maxfd = __sysconf (_SC_OPEN_MAX);
struct __spawn_action *rec;
- /* Test for the validity of the file descriptor. */
- if (fd < 0 || fd >= maxfd)
+ if (!__spawn_valid_fd (fd))
return EBADF;
- char *path_copy = strdup (path);
+ char *path_copy = __strdup (path);
if (path_copy == NULL)
return ENOMEM;
diff --git a/posix/spawn_faction_destroy.c b/posix/spawn_faction_destroy.c
index 33fab8f1c5..46061ee347 100644
--- a/posix/spawn_faction_destroy.c
+++ b/posix/spawn_faction_destroy.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000-2016 Free Software Foundation, Inc.
+/* Copyright (C) 2000-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/posix/spawn_faction_init.c b/posix/spawn_faction_init.c
index 7744f5d563..ddb42e6a77 100644
--- a/posix/spawn_faction_init.c
+++ b/posix/spawn_faction_init.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000-2016 Free Software Foundation, Inc.
+/* Copyright (C) 2000-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/posix/spawn_int.h b/posix/spawn_int.h
index 861e3b47bb..171f67c649 100644
--- a/posix/spawn_int.h
+++ b/posix/spawn_int.h
@@ -1,3 +1,27 @@
+/* Internal definitions for posix_spawn functionality.
+ Copyright (C) 2000-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _SPAWN_INT_H
+#define _SPAWN_INT_H
+
+#include <spawn.h>
+#include <stdbool.h>
+
/* Data structure to contain the action information. */
struct __spawn_action
{
@@ -33,9 +57,16 @@ struct __spawn_action
#define SPAWN_XFLAGS_TRY_SHELL 0x2
extern int __posix_spawn_file_actions_realloc (posix_spawn_file_actions_t *
- file_actions);
+ file_actions)
+ attribute_hidden;
extern int __spawni (pid_t *pid, const char *path,
const posix_spawn_file_actions_t *file_actions,
const posix_spawnattr_t *attrp, char *const argv[],
- char *const envp[], int xflags);
+ char *const envp[], int xflags) attribute_hidden;
+
+/* Return true if FD falls into the range valid for file descriptors.
+ The check in this form is mandated by POSIX. */
+bool __spawn_valid_fd (int fd) attribute_hidden;
+
+#endif /* _SPAWN_INT_H */
diff --git a/posix/spawn_valid_fd.c b/posix/spawn_valid_fd.c
new file mode 100644
index 0000000000..81824ef23e
--- /dev/null
+++ b/posix/spawn_valid_fd.c
@@ -0,0 +1,30 @@
+/* File descriptor validity check for posix_spawn file actions.
+ Copyright (C) 2000-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include "spawn_int.h"
+
+#include <unistd.h>
+
+bool
+__spawn_valid_fd (int fd)
+{
+ long maxfd = __sysconf (_SC_OPEN_MAX);
+ return __glibc_likely (fd >= 0)
+ && (__glibc_unlikely (maxfd < 0) /* No limit set. */
+ || __glibc_likely (fd < maxfd));
+}
diff --git a/posix/spawnattr_destroy.c b/posix/spawnattr_destroy.c
index a2e3b79b2f..603e00fffe 100644
--- a/posix/spawnattr_destroy.c
+++ b/posix/spawnattr_destroy.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000-2016 Free Software Foundation, Inc.
+/* Copyright (C) 2000-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/posix/spawnattr_getdefault.c b/posix/spawnattr_getdefault.c
index 118029513b..bd6a5e653f 100644
--- a/posix/spawnattr_getdefault.c
+++ b/posix/spawnattr_getdefault.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000-2016 Free Software Foundation, Inc.
+/* Copyright (C) 2000-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/posix/spawnattr_getflags.c b/posix/spawnattr_getflags.c
index 8bf916b746..899eadff96 100644
--- a/posix/spawnattr_getflags.c
+++ b/posix/spawnattr_getflags.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000-2016 Free Software Foundation, Inc.
+/* Copyright (C) 2000-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/posix/spawnattr_getpgroup.c b/posix/spawnattr_getpgroup.c
index bfc7315db0..052aa2f52f 100644
--- a/posix/spawnattr_getpgroup.c
+++ b/posix/spawnattr_getpgroup.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000-2016 Free Software Foundation, Inc.
+/* Copyright (C) 2000-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/posix/spawnattr_getschedparam.c b/posix/spawnattr_getschedparam.c
index ccf6e42417..73897249b0 100644
--- a/posix/spawnattr_getschedparam.c
+++ b/posix/spawnattr_getschedparam.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000-2016 Free Software Foundation, Inc.
+/* Copyright (C) 2000-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/posix/spawnattr_getschedpolicy.c b/posix/spawnattr_getschedpolicy.c
index dad48bfa40..d314adb91a 100644
--- a/posix/spawnattr_getschedpolicy.c
+++ b/posix/spawnattr_getschedpolicy.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000-2016 Free Software Foundation, Inc.
+/* Copyright (C) 2000-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/posix/spawnattr_getsigmask.c b/posix/spawnattr_getsigmask.c
index c443f85008..091946b6bf 100644
--- a/posix/spawnattr_getsigmask.c
+++ b/posix/spawnattr_getsigmask.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000-2016 Free Software Foundation, Inc.
+/* Copyright (C) 2000-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/posix/spawnattr_init.c b/posix/spawnattr_init.c
index 25f29d5b35..bab464e62b 100644
--- a/posix/spawnattr_init.c
+++ b/posix/spawnattr_init.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000-2016 Free Software Foundation, Inc.
+/* Copyright (C) 2000-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/posix/spawnattr_setdefault.c b/posix/spawnattr_setdefault.c
index 1a0f147847..c77cda59be 100644
--- a/posix/spawnattr_setdefault.c
+++ b/posix/spawnattr_setdefault.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000-2016 Free Software Foundation, Inc.
+/* Copyright (C) 2000-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/posix/spawnattr_setflags.c b/posix/spawnattr_setflags.c
index 37c69f34a5..cf9a60181d 100644
--- a/posix/spawnattr_setflags.c
+++ b/posix/spawnattr_setflags.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000-2016 Free Software Foundation, Inc.
+/* Copyright (C) 2000-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -25,6 +25,7 @@
| POSIX_SPAWN_SETSIGMASK \
| POSIX_SPAWN_SETSCHEDPARAM \
| POSIX_SPAWN_SETSCHEDULER \
+ | POSIX_SPAWN_SETSID \
| POSIX_SPAWN_USEVFORK)
/* Store flags in the attribute structure. */
diff --git a/posix/spawnattr_setpgroup.c b/posix/spawnattr_setpgroup.c
index 3650954a4c..63f13ae9ba 100644
--- a/posix/spawnattr_setpgroup.c
+++ b/posix/spawnattr_setpgroup.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000-2016 Free Software Foundation, Inc.
+/* Copyright (C) 2000-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/posix/spawnattr_setschedparam.c b/posix/spawnattr_setschedparam.c
index 5187806ee3..b5e4a7ecb6 100644
--- a/posix/spawnattr_setschedparam.c
+++ b/posix/spawnattr_setschedparam.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000-2016 Free Software Foundation, Inc.
+/* Copyright (C) 2000-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/posix/spawnattr_setschedpolicy.c b/posix/spawnattr_setschedpolicy.c
index b8c505fd71..cfc46c06bb 100644
--- a/posix/spawnattr_setschedpolicy.c
+++ b/posix/spawnattr_setschedpolicy.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000-2016 Free Software Foundation, Inc.
+/* Copyright (C) 2000-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/posix/spawnattr_setsigmask.c b/posix/spawnattr_setsigmask.c
index 3d3fee19fd..7ae81ad470 100644
--- a/posix/spawnattr_setsigmask.c
+++ b/posix/spawnattr_setsigmask.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000-2016 Free Software Foundation, Inc.
+/* Copyright (C) 2000-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/posix/spawni.c b/posix/spawni.c
index 40aefc03fa..3c99f09705 100644
--- a/posix/spawni.c
+++ b/posix/spawni.c
@@ -1,5 +1,5 @@
/* Guts of POSIX spawn interface. Stub version.
- Copyright (C) 2001-2016 Free Software Foundation, Inc.
+ Copyright (C) 2001-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/posix/spawnp.c b/posix/spawnp.c
index 2f8dfaae72..b26a5318b3 100644
--- a/posix/spawnp.c
+++ b/posix/spawnp.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000-2016 Free Software Foundation, Inc.
+/* Copyright (C) 2000-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/posix/sys/times.h b/posix/sys/times.h
index a877d1490d..d2db5689a2 100644
--- a/posix/sys/times.h
+++ b/posix/sys/times.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -24,9 +24,7 @@
#include <features.h>
-#define __need_clock_t
-#include <time.h>
-
+#include <bits/types/clock_t.h>
__BEGIN_DECLS
diff --git a/posix/sys/types.h b/posix/sys/types.h
index a7285671bf..db524d6cd1 100644
--- a/posix/sys/types.h
+++ b/posix/sys/types.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -39,9 +39,8 @@ typedef __u_quad_t u_quad_t;
typedef __fsid_t fsid_t;
# define __u_char_defined
# endif
-#endif
-
typedef __loff_t loff_t;
+#endif
#ifndef __ino_t_defined
# ifndef __USE_FILE_OFFSET64
@@ -124,12 +123,11 @@ typedef __key_t key_t;
#endif
#if defined __USE_XOPEN || defined __USE_XOPEN2K8
-# define __need_clock_t
+# include <bits/types/clock_t.h>
#endif
-#define __need_time_t
-#define __need_timer_t
-#define __need_clockid_t
-#include <time.h>
+#include <bits/types/clockid_t.h>
+#include <bits/types/time_t.h>
+#include <bits/types/timer_t.h>
#ifdef __USE_XOPEN
# ifndef __useconds_t_defined
@@ -154,22 +152,11 @@ typedef unsigned int uint;
/* These size-specific names are used by some of the inet code. */
-#if !__GNUC_PREREQ (2, 7)
+#include <bits/stdint-intn.h>
-/* These types are defined by the ISO C99 header <inttypes.h>. */
-# ifndef __int8_t_defined
-# define __int8_t_defined
-typedef char int8_t;
-typedef short int int16_t;
-typedef int int32_t;
-# if __WORDSIZE == 64
-typedef long int int64_t;
-# else
-__extension__ typedef long long int int64_t;
-# endif
-# endif
+#if !__GNUC_PREREQ (2, 7)
-/* But these were defined by ISO C without the first `_'. */
+/* These were defined by ISO C without the first `_'. */
typedef unsigned char u_int8_t;
typedef unsigned short int u_int16_t;
typedef unsigned int u_int32_t;
@@ -184,19 +171,9 @@ typedef int register_t;
#else
/* For GCC 2.7 and later, we can use specific type-size attributes. */
-# define __intN_t(N, MODE) \
- typedef int int##N##_t __attribute__ ((__mode__ (MODE)))
# define __u_intN_t(N, MODE) \
typedef unsigned int u_int##N##_t __attribute__ ((__mode__ (MODE)))
-# ifndef __int8_t_defined
-# define __int8_t_defined
-__intN_t (8, __QI__);
-__intN_t (16, __HI__);
-__intN_t (32, __SI__);
-__intN_t (64, __DI__);
-# endif
-
__u_intN_t (8, __QI__);
__u_intN_t (16, __HI__);
__u_intN_t (32, __SI__);
@@ -217,9 +194,6 @@ typedef int register_t __attribute__ ((__mode__ (__word__)));
/* It also defines `fd_set' and the FD_* macros for `select'. */
# include <sys/select.h>
-
-/* BSD defines these symbols, so we follow. */
-# include <sys/sysmacros.h>
#endif /* Use misc. */
diff --git a/posix/sys/utsname.h b/posix/sys/utsname.h
index 05682a16f7..4f7b16da64 100644
--- a/posix/sys/utsname.h
+++ b/posix/sys/utsname.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/posix/sys/wait.h b/posix/sys/wait.h
index a673b414b5..efd6c09020 100644
--- a/posix/sys/wait.h
+++ b/posix/sys/wait.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -26,7 +26,21 @@
__BEGIN_DECLS
-#include <signal.h>
+#include <bits/types.h>
+#ifndef __pid_t_defined
+typedef __pid_t pid_t;
+# define __pid_t_defined
+#endif
+
+#if defined __USE_XOPEN_EXTENDED || defined __USE_XOPEN2K8
+# include <signal.h>
+#endif
+
+#if defined __USE_XOPEN_EXTENDED && !defined __USE_XOPEN2K8
+/* Some older standards require the contents of struct rusage to be
+ defined here. */
+# include <bits/types/struct_rusage.h>
+#endif
/* These macros could also be defined in <stdlib.h>. */
#if !defined _STDLIB_H || (!defined __USE_XOPEN && !defined __USE_XOPEN2K8)
@@ -34,68 +48,29 @@ __BEGIN_DECLS
bits to `waitpid', `wait3', and `wait4'. */
# include <bits/waitflags.h>
-# ifdef __USE_MISC
-
-/* Lots of hair to allow traditional BSD use of `union wait'
- as well as POSIX.1 use of `int' for the status word. */
-
-# if defined __GNUC__ && !defined __cplusplus
-# define __WAIT_INT(status) \
- (__extension__ (((union { __typeof(status) __in; int __i; }) \
- { .__in = (status) }).__i))
-# else
-# define __WAIT_INT(status) (*(const int *) &(status))
-# endif
-
-/* This is the type of the argument to `wait'. The funky union
- causes redeclarations with either `int *' or `union wait *' to be
- allowed without complaint. __WAIT_STATUS_DEFN is the type used in
- the actual function definitions. */
-
-# if !defined __GNUC__ || __GNUC__ < 2 || defined __cplusplus
-# define __WAIT_STATUS void *
-# define __WAIT_STATUS_DEFN void *
-# else
-/* This works in GCC 2.6.1 and later. */
-typedef union
- {
- union wait *__uptr;
- int *__iptr;
- } __WAIT_STATUS __attribute__ ((__transparent_union__));
-# define __WAIT_STATUS_DEFN int *
-# endif
-
-# else /* Don't use misc. */
-
-# define __WAIT_INT(status) (status)
-# define __WAIT_STATUS int *
-# define __WAIT_STATUS_DEFN int *
-
-# endif /* Use misc. */
-
/* This will define all the `__W*' macros. */
# include <bits/waitstatus.h>
-# define WEXITSTATUS(status) __WEXITSTATUS (__WAIT_INT (status))
-# define WTERMSIG(status) __WTERMSIG (__WAIT_INT (status))
-# define WSTOPSIG(status) __WSTOPSIG (__WAIT_INT (status))
-# define WIFEXITED(status) __WIFEXITED (__WAIT_INT (status))
-# define WIFSIGNALED(status) __WIFSIGNALED (__WAIT_INT (status))
-# define WIFSTOPPED(status) __WIFSTOPPED (__WAIT_INT (status))
+# define WEXITSTATUS(status) __WEXITSTATUS (status)
+# define WTERMSIG(status) __WTERMSIG (status)
+# define WSTOPSIG(status) __WSTOPSIG (status)
+# define WIFEXITED(status) __WIFEXITED (status)
+# define WIFSIGNALED(status) __WIFSIGNALED (status)
+# define WIFSTOPPED(status) __WIFSTOPPED (status)
# ifdef __WIFCONTINUED
-# define WIFCONTINUED(status) __WIFCONTINUED (__WAIT_INT (status))
+# define WIFCONTINUED(status) __WIFCONTINUED (status)
# endif
#endif /* <stdlib.h> not included. */
#ifdef __USE_MISC
# define WCOREFLAG __WCOREFLAG
-# define WCOREDUMP(status) __WCOREDUMP (__WAIT_INT (status))
+# define WCOREDUMP(status) __WCOREDUMP (status)
# define W_EXITCODE(ret, sig) __W_EXITCODE (ret, sig)
# define W_STOPCODE(sig) __W_STOPCODE (sig)
#endif
/* The following values are used by the `waitid' function. */
-#if defined __USE_XOPEN || defined __USE_XOPEN2K8
+#if defined __USE_XOPEN_EXTENDED || defined __USE_XOPEN2K8
typedef enum
{
P_ALL, /* Wait for any child. */
@@ -110,7 +85,7 @@ typedef enum
This function is a cancellation point and therefore not marked with
__THROW. */
-extern __pid_t wait (__WAIT_STATUS __stat_loc);
+extern __pid_t wait (int *__stat_loc);
#ifdef __USE_MISC
/* Special values for the PID argument to `waitpid' and `wait4'. */
@@ -135,15 +110,13 @@ extern __pid_t wait (__WAIT_STATUS __stat_loc);
__THROW. */
extern __pid_t waitpid (__pid_t __pid, int *__stat_loc, int __options);
-#if defined __USE_XOPEN || defined __USE_XOPEN2K8
+#if defined __USE_XOPEN_EXTENDED || defined __USE_XOPEN2K8
# ifndef __id_t_defined
-# include <bits/types.h>
typedef __id_t id_t;
# define __id_t_defined
# endif
-# define __need_siginfo_t
-# include <bits/siginfo.h>
+# include <bits/types/siginfo_t.h>
/* Wait for a childing matching IDTYPE and ID to change the status and
place appropriate information in *INFOP.
@@ -160,7 +133,8 @@ extern int waitid (idtype_t __idtype, __id_t __id, siginfo_t *__infop,
int __options);
#endif
-#if defined __USE_MISC || defined __USE_XOPEN_EXTENDED
+#if defined __USE_MISC \
+ || (defined __USE_XOPEN_EXTENDED && !defined __USE_XOPEN2K)
/* This being here makes the prototypes valid whether or not
we have already included <sys/resource.h> to define `struct rusage'. */
struct rusage;
@@ -170,13 +144,13 @@ struct rusage;
nil, store information about the child's resource usage there. If the
WUNTRACED bit is set in OPTIONS, return status for stopped children;
otherwise don't. */
-extern __pid_t wait3 (__WAIT_STATUS __stat_loc, int __options,
+extern __pid_t wait3 (int *__stat_loc, int __options,
struct rusage * __usage) __THROWNL;
#endif
#ifdef __USE_MISC
/* PID is like waitpid. Other args are like wait3. */
-extern __pid_t wait4 (__pid_t __pid, __WAIT_STATUS __stat_loc, int __options,
+extern __pid_t wait4 (__pid_t __pid, int *__stat_loc, int __options,
struct rusage *__usage) __THROWNL;
#endif /* Use misc. */
diff --git a/posix/sysconf.c b/posix/sysconf.c
index 01d9283bf5..09ebd95a98 100644
--- a/posix/sysconf.c
+++ b/posix/sysconf.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -37,7 +37,7 @@ __sysconf (int name)
return -1;
case _SC_TZNAME_MAX:
- return MAX (__tzname_max (), _POSIX_TZNAME_MAX);
+ return -1;
case _SC_CHARCLASS_NAME_MAX:
#ifdef CHARCLASS_NAME_MAX
diff --git a/posix/tar.h b/posix/tar.h
index 321c19e640..4e7364239a 100644
--- a/posix/tar.h
+++ b/posix/tar.h
@@ -1,5 +1,5 @@
/* Extended tar format from POSIX.1.
- Copyright (C) 1992-2016 Free Software Foundation, Inc.
+ Copyright (C) 1992-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Written by David J. MacKenzie.
diff --git a/posix/test-errno.c b/posix/test-errno.c
new file mode 100644
index 0000000000..8c43ae9bc5
--- /dev/null
+++ b/posix/test-errno.c
@@ -0,0 +1,154 @@
+/* Test that failing system calls do set errno to the correct value.
+
+ Copyright (C) 2017-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <limits.h>
+#include <grp.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/types.h>
+#include <sys/statfs.h>
+#include <sys/mman.h>
+#include <sys/uio.h>
+#include <unistd.h>
+#include <netinet/in.h>
+
+/* This is not an exhaustive test: only system calls that can be
+ persuaded to fail with a consistent error code and no side effects
+ are included. Usually these are failures due to invalid arguments,
+ with errno code EBADF or EINVAL. The order of argument checks is
+ unspecified, so we must take care to provide arguments that only
+ allow _one_ failure mode.
+
+ Note that all system calls that can fail with EFAULT are permitted
+ to deliver a SIGSEGV signal instead, so we avoid supplying invalid
+ pointers in general, and we do not attempt to test system calls
+ that can only fail with EFAULT (e.g. gettimeofday, gethostname).
+
+ Also note that root-only system calls (e.g. acct, reboot) may, when
+ the test is run as an unprivileged user, fail due to insufficient
+ privileges before bothering to do argument checks, so those are not
+ tested either.
+
+ Also, system calls that take enum or a set of flags as argument is
+ not tested if POSIX doesn't specify exact binary values for all
+ flags, and so any value passed to flags may become valid.
+
+ Some tests assume "/bin/sh" names a file that exists and is not a
+ directory. */
+
+#define test_wrp_rv(rtype, prtype, experr, syscall, ...) \
+ (__extension__ ({ \
+ errno = 0xdead; \
+ rtype ret = syscall (__VA_ARGS__); \
+ int err = errno; \
+ int fail; \
+ if (ret == (rtype) -1 && err == experr) \
+ fail = 0; \
+ else \
+ { \
+ fail = 1; \
+ if (ret != (rtype) -1) \
+ printf ("FAIL: " #syscall ": didn't fail as expected" \
+ " (return "prtype")\n", ret); \
+ else if (err == 0xdead) \
+ puts("FAIL: " #syscall ": didn't update errno\n"); \
+ else if (err != experr) \
+ printf ("FAIL: " #syscall \
+ ": errno is: %d (%s) expected: %d (%s)\n", \
+ err, strerror (err), experr, strerror (experr)); \
+ } \
+ fail; \
+ }))
+
+#define test_wrp(experr, syscall, ...) \
+ test_wrp_rv(int, "%d", experr, syscall, __VA_ARGS__)
+
+static int
+do_test (void)
+{
+ size_t pagesize = sysconf (_SC_PAGESIZE);
+ struct statfs sfs;
+ struct sockaddr sa;
+ socklen_t sl;
+ char buf[1];
+ struct iovec iov[1] = { { buf, 1 } };
+ struct sockaddr_in sin;
+ sin.sin_family = AF_INET;
+ sin.sin_port = htons (1026);
+ sin.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
+ struct msghdr msg;
+ memset(&msg, 0, sizeof msg);
+ msg.msg_iov = iov;
+ msg.msg_iovlen = 1;
+
+ int fails = 0;
+ fails |= test_wrp (EBADF, accept, -1, &sa, &sl);
+ fails |= test_wrp (EINVAL, access, "/", -1);
+ fails |= test_wrp (EBADF, bind, -1, (struct sockaddr *)&sin, sizeof sin);
+ fails |= test_wrp (ENOTDIR, chdir, "/bin/sh");
+ fails |= test_wrp (EBADF, close, -1);
+ fails |= test_wrp (EBADF, connect, -1, (struct sockaddr *)&sin, sizeof sin);
+ fails |= test_wrp (EBADF, dup, -1);
+ fails |= test_wrp (EBADF, dup2, -1, -1);
+ fails |= test_wrp (EBADF, fchdir, -1);
+ fails |= test_wrp (EBADF, fchmod, -1, 0);
+ fails |= test_wrp (EBADF, fcntl, -1, 0);
+ fails |= test_wrp (EBADF, fstatfs, -1, &sfs);
+ fails |= test_wrp (EBADF, fsync, -1);
+ fails |= test_wrp (EBADF, ftruncate, -1, 0);
+ fails |= test_wrp (EINVAL, getgroups, -1, 0);
+ fails |= test_wrp (EBADF, getpeername, -1, &sa, &sl);
+ fails |= test_wrp (EBADF, getsockname, -1, &sa, &sl);
+ fails |= test_wrp (EBADF, getsockopt, -1, 0, 0, buf, &sl);
+ fails |= test_wrp (EBADF, ioctl, -1, TIOCNOTTY);
+ fails |= test_wrp (EBADF, listen, -1, 1);
+ fails |= test_wrp (EBADF, lseek, -1, 0, 0);
+ fails |= test_wrp (EINVAL, madvise, (void *) -1, -1, 0);
+ fails |= test_wrp_rv (void *, "%p", EBADF,
+ mmap, 0, pagesize, PROT_READ, MAP_PRIVATE, -1, 0);
+ fails |= test_wrp (EINVAL, mprotect, (void *) -1, pagesize, -1);
+ fails |= test_wrp (EINVAL, msync, (void *) -1, pagesize, -1);
+ fails |= test_wrp (EINVAL, munmap, (void *) -1, 0);
+ fails |= test_wrp (EISDIR, open, "/bin", EISDIR, O_WRONLY);
+ fails |= test_wrp (EBADF, read, -1, buf, 1);
+ fails |= test_wrp (EINVAL, readlink, "/", buf, -1);
+ fails |= test_wrp (EBADF, readv, -1, iov, 1);
+ fails |= test_wrp (EBADF, recv, -1, buf, 1, 0);
+ fails |= test_wrp (EBADF, recvfrom, -1, buf, 1, 0, &sa, &sl);
+ fails |= test_wrp (EBADF, recvmsg, -1, &msg, 0);
+ fails |= test_wrp (EINVAL, select, -1, 0, 0, 0, 0);
+ fails |= test_wrp (EBADF, send, -1, buf, 1, 0);
+ fails |= test_wrp (EBADF, sendmsg, -1, &msg, 0);
+ fails |= test_wrp (EBADF, sendto, -1, buf, 1, 0, &sa, sl);
+ fails |= test_wrp (EBADF, setsockopt, -1, 0, 0, buf, sizeof (*buf));
+ fails |= test_wrp (EBADF, shutdown, -1, SHUT_RD);
+ fails |= test_wrp (EBADF, write, -1, "Hello", sizeof ("Hello") );
+ fails |= test_wrp (EBADF, writev, -1, iov, 1 );
+
+ return fails;
+}
+
+#include "support/test-driver.c"
diff --git a/posix/test-ssize-max.c b/posix/test-ssize-max.c
new file mode 100644
index 0000000000..7cfd090aef
--- /dev/null
+++ b/posix/test-ssize-max.c
@@ -0,0 +1,39 @@
+/* Test SSIZE_MAX value and type.
+ Copyright (C) 2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <limits.h>
+#include <sys/types.h>
+
+/* Test SSIZE_MAX has type ssize_t. */
+ssize_t x;
+extern __typeof (SSIZE_MAX) x;
+
+/* Test the value of SSIZE_MAX. */
+_Static_assert (SSIZE_MAX == (sizeof (ssize_t) == sizeof (int)
+ ? INT_MAX
+ : LONG_MAX),
+ "value of SSIZE_MAX");
+
+static int
+do_test (void)
+{
+ /* This is a compilation test. */
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/posix/times.c b/posix/times.c
index f22dc3b9f6..df6297bf97 100644
--- a/posix/times.c
+++ b/posix/times.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/posix/tst-boost.c b/posix/tst-boost.c
index 9e9007530b..a3b1851c6e 100644
--- a/posix/tst-boost.c
+++ b/posix/tst-boost.c
@@ -1,5 +1,5 @@
/* Regular expression tests.
- Copyright (C) 2003-2016 Free Software Foundation, Inc.
+ Copyright (C) 2003-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Jakub Jelinek <jakub@redhat.com>, 2003.
diff --git a/posix/tst-chmod.c b/posix/tst-chmod.c
index 17d68688be..611a007822 100644
--- a/posix/tst-chmod.c
+++ b/posix/tst-chmod.c
@@ -1,5 +1,5 @@
/* Test for chmod functions.
- Copyright (C) 2000-2016 Free Software Foundation, Inc.
+ Copyright (C) 2000-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 2000.
diff --git a/posix/tst-dir.c b/posix/tst-dir.c
index 8897f8e06d..794275dc4c 100644
--- a/posix/tst-dir.c
+++ b/posix/tst-dir.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000-2016 Free Software Foundation, Inc.
+/* Copyright (C) 2000-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2000.
@@ -26,7 +26,7 @@
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
-
+#include <libc-diag.h>
/* We expect four arguments:
- source directory name
@@ -149,10 +149,8 @@ main (int argc, char *argv[])
while ((d = readdir64 (dir1)) != NULL)
{
-#ifdef _DIRENT_HAVE_D_TYPE
if (d->d_type != DT_UNKNOWN && d->d_type != DT_REG)
continue;
-#endif
if (d->d_ino == st2.st_ino)
{
@@ -234,10 +232,8 @@ main (int argc, char *argv[])
while ((d = readdir64 (dir2)) != NULL)
{
-#ifdef _DIRENT_HAVE_D_TYPE
if (d->d_type != DT_UNKNOWN && d->d_type != DT_DIR)
continue;
-#endif
if (d->d_ino == st2.st_ino)
{
@@ -319,14 +315,16 @@ main (int argc, char *argv[])
exit (1);
}
+ /* The test below covers the deprecated readdir64_r function. */
+ DIAG_PUSH_NEEDS_COMMENT;
+ DIAG_IGNORE_NEEDS_COMMENT (4.9, "-Wdeprecated-declarations");
+
/* Try to find the new directory. */
rewinddir (dir1);
while (readdir64_r (dir1, &direntbuf.d, &d) == 0 && d != NULL)
{
-#ifdef _DIRENT_HAVE_D_TYPE
if (d->d_type != DT_UNKNOWN && d->d_type != DT_DIR)
continue;
-#endif
if (d->d_ino == st1.st_ino)
{
@@ -351,6 +349,8 @@ main (int argc, char *argv[])
}
}
+ DIAG_POP_NEEDS_COMMENT;
+
if (d == NULL)
{
printf ("haven't found new directory \"%s\"\n", buf);
@@ -439,6 +439,10 @@ main (int argc, char *argv[])
result = 1;
}
+ /* The test below covers the deprecated readdir64_r function. */
+ DIAG_PUSH_NEEDS_COMMENT;
+ DIAG_IGNORE_NEEDS_COMMENT (4.9, "-Wdeprecated-declarations");
+
/* We now should have a directory and a file in the new directory. */
rewinddir (dir2);
while (readdir64_r (dir2, &direntbuf.d, &d) == 0 && d != NULL)
@@ -447,13 +451,11 @@ main (int argc, char *argv[])
|| strcmp (d->d_name, "..") == 0
|| strcmp (d->d_name, "another-dir") == 0)
{
-#ifdef _DIRENT_HAVE_D_TYPE
if (d->d_type != DT_UNKNOWN && d->d_type != DT_DIR)
{
printf ("d_type for \"%s\" is wrong\n", d->d_name);
result = 1;
}
-#endif
if (stat64 (d->d_name, &st3) < 0)
{
printf ("cannot stat \"%s\" is wrong\n", d->d_name);
@@ -467,13 +469,11 @@ main (int argc, char *argv[])
}
else if (strcmp (d->d_name, "and-a-file") == 0)
{
-#ifdef _DIRENT_HAVE_D_TYPE
if (d->d_type != DT_UNKNOWN && d->d_type != DT_REG)
{
printf ("d_type for \"%s\" is wrong\n", d->d_name);
result = 1;
}
-#endif
if (stat64 (d->d_name, &st3) < 0)
{
printf ("cannot stat \"%s\" is wrong\n", d->d_name);
@@ -492,6 +492,8 @@ main (int argc, char *argv[])
}
}
+ DIAG_POP_NEEDS_COMMENT;
+
if (stat64 ("does-not-exist", &st1) >= 0)
{
puts ("stat for unexisting file did not fail");
diff --git a/posix/tst-exec.c b/posix/tst-exec.c
index b0b04b5b9a..fe8f0f1e77 100644
--- a/posix/tst-exec.c
+++ b/posix/tst-exec.c
@@ -1,5 +1,5 @@
/* Tests for exec.
- Copyright (C) 2000-2016 Free Software Foundation, Inc.
+ Copyright (C) 2000-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 2000.
@@ -47,6 +47,10 @@ extern int do_test (int argc, char *argv[]);
static char *name1;
static char *name2;
+/* File descriptors for these temporary files. */
+static int temp_fd1 = -1;
+static int temp_fd2 = -1;
+
/* The contents of our files. */
static const char fd1string[] = "This file should get closed";
static const char fd2string[] = "This file should stay opened";
@@ -56,18 +60,14 @@ static const char fd2string[] = "This file should stay opened";
void
do_prepare (int argc, char *argv[])
{
- size_t name_len;
-
- name_len = strlen (test_dir);
- name1 = malloc (name_len + sizeof ("/execXXXXXX"));
- mempcpy (mempcpy (name1, test_dir, name_len),
- "/execXXXXXX", sizeof ("/execXXXXXX"));
- add_temp_file (name1);
-
- name2 = malloc (name_len + sizeof ("/execXXXXXX"));
- mempcpy (mempcpy (name2, test_dir, name_len),
- "/execXXXXXX", sizeof ("/execXXXXXX"));
- add_temp_file (name2);
+ /* We must not open any files in the restart case. */
+ if (restart)
+ return;
+
+ temp_fd1 = create_temp_file ("exec", &name1);
+ temp_fd2 = create_temp_file ("exec", &name2);
+ if (temp_fd1 < 0 || temp_fd2 < 0)
+ exit (1);
}
@@ -120,8 +120,6 @@ int
do_test (int argc, char *argv[])
{
pid_t pid;
- int fd1;
- int fd2;
int flags;
int status;
@@ -151,26 +149,18 @@ do_test (int argc, char *argv[])
/* Prepare the test. We are creating two files: one which file descriptor
will be marked with FD_CLOEXEC, another which is not. */
- /* Open our test files. */
- fd1 = mkstemp (name1);
- if (fd1 == -1)
- error (EXIT_FAILURE, errno, "cannot open test file `%s'", name1);
- fd2 = mkstemp (name2);
- if (fd2 == -1)
- error (EXIT_FAILURE, errno, "cannot open test file `%s'", name2);
-
/* Set the bit. */
- flags = fcntl (fd1, F_GETFD, 0);
+ flags = fcntl (temp_fd1, F_GETFD, 0);
if (flags < 0)
error (EXIT_FAILURE, errno, "cannot get flags");
flags |= FD_CLOEXEC;
- if (fcntl (fd1, F_SETFD, flags) < 0)
+ if (fcntl (temp_fd1, F_SETFD, flags) < 0)
error (EXIT_FAILURE, errno, "cannot set flags");
/* Write something in the files. */
- if (write (fd1, fd1string, strlen (fd1string)) != strlen (fd1string))
+ if (write (temp_fd1, fd1string, strlen (fd1string)) != strlen (fd1string))
error (EXIT_FAILURE, errno, "cannot write to first file");
- if (write (fd2, fd2string, strlen (fd2string)) != strlen (fd2string))
+ if (write (temp_fd2, fd2string, strlen (fd2string)) != strlen (fd2string))
error (EXIT_FAILURE, errno, "cannot write to second file");
/* We want to test the `exec' function. To do this we restart the program
@@ -181,8 +171,8 @@ do_test (int argc, char *argv[])
char fd1name[18];
char fd2name[18];
- snprintf (fd1name, sizeof fd1name, "%d", fd1);
- snprintf (fd2name, sizeof fd2name, "%d", fd2);
+ snprintf (fd1name, sizeof fd1name, "%d", temp_fd1);
+ snprintf (fd2name, sizeof fd2name, "%d", temp_fd2);
/* This is the child. Construct the command line. */
if (argc == 5)
@@ -205,9 +195,5 @@ do_test (int argc, char *argv[])
error (EXIT_FAILURE, 0, "Child terminated incorrectly");
status = WEXITSTATUS (status);
- /* Remove the test files. */
- unlink (name1);
- unlink (name2);
-
return status;
}
diff --git a/posix/tst-execvp1.c b/posix/tst-execvp1.c
index ecc673d124..8b718485d0 100644
--- a/posix/tst-execvp1.c
+++ b/posix/tst-execvp1.c
@@ -3,6 +3,10 @@
#include <stdlib.h>
#include <unistd.h>
+#ifndef EXECVP
+# define EXECVP(file, argv) execvp (file, argv)
+#endif
+
static int
do_test (void)
{
@@ -19,7 +23,7 @@ do_test (void)
char *argv[] = { (char *) "does-not-exist", NULL };
errno = 0;
- execvp (argv[0], argv);
+ EXECVP (argv[0], argv);
if (errno != ENOENT)
{
diff --git a/posix/tst-execvp2.c b/posix/tst-execvp2.c
index 7e0f5d882c..440dfab438 100644
--- a/posix/tst-execvp2.c
+++ b/posix/tst-execvp2.c
@@ -14,6 +14,9 @@ static int do_test (void);
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"
+#ifndef EXECVP
+# define EXECVP(file, argv) execvp (file, argv)
+#endif
static char *copy;
@@ -70,7 +73,7 @@ do_test (void)
char *argv[] = { basename (copy), NULL };
errno = 0;
- execvp (argv[0], argv);
+ EXECVP (argv[0], argv);
if (errno != EACCES)
{
diff --git a/posix/tst-execvp3.c b/posix/tst-execvp3.c
index 5ebc87952d..02a937c2da 100644
--- a/posix/tst-execvp3.c
+++ b/posix/tst-execvp3.c
@@ -12,6 +12,9 @@ static int do_test (void);
#include "../test-skeleton.c"
+#ifndef EXECVP
+# define EXECVP(file, argv) execvp (file, argv)
+#endif
static char *fname;
@@ -35,7 +38,7 @@ do_test (void)
}
char *argv[] = { fname, NULL };
- execvp (basename (fname), argv);
+ EXECVP (basename (fname), argv);
/* If we come here, the execvp call failed. */
return 1;
diff --git a/posix/tst-execvp4.c b/posix/tst-execvp4.c
index 531fab227b..589a56018f 100644
--- a/posix/tst-execvp4.c
+++ b/posix/tst-execvp4.c
@@ -5,6 +5,10 @@
#include <unistd.h>
#include <sys/stat.h>
+#ifndef EXECVP
+# define EXECVP(file, argv) execvp (file, argv)
+#endif
+
static int
do_test (void)
{
@@ -27,7 +31,7 @@ do_test (void)
unsetenv ("PATH");
char *argv[] = { buf + 9, NULL };
- execvp (argv[0], argv);
+ EXECVP (argv[0], argv);
return 0;
}
diff --git a/posix/tst-execvpe1.c b/posix/tst-execvpe1.c
new file mode 100644
index 0000000000..bf529dd438
--- /dev/null
+++ b/posix/tst-execvpe1.c
@@ -0,0 +1,20 @@
+/* Check ENOENT failure for execvpe.
+ Copyright (C) 2016-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#define EXECVP(file, argv) execvpe (file, argv, NULL)
+#include <posix/tst-execvp1.c>
diff --git a/posix/tst-execvpe2.c b/posix/tst-execvpe2.c
new file mode 100644
index 0000000000..439cde9ffa
--- /dev/null
+++ b/posix/tst-execvpe2.c
@@ -0,0 +1,20 @@
+/* Check EACCES for execvpe.
+ Copyright (C) 2016-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#define EXECVP(file, argv) execvpe (file, argv, NULL)
+#include <posix/tst-execvp2.c>
diff --git a/posix/tst-execvpe3.c b/posix/tst-execvpe3.c
new file mode 100644
index 0000000000..d50615acb8
--- /dev/null
+++ b/posix/tst-execvpe3.c
@@ -0,0 +1,20 @@
+/* Check script execution without shebang for execvpe.
+ Copyright (C) 2016-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#define EXECVP(file, argv) execvpe (file, argv, NULL)
+#include <posix/tst-execvp3.c>
diff --git a/posix/tst-execvpe4.c b/posix/tst-execvpe4.c
new file mode 100644
index 0000000000..96f8ea94df
--- /dev/null
+++ b/posix/tst-execvpe4.c
@@ -0,0 +1,20 @@
+/* Check unexistent binary for execvpe.
+ Copyright (C) 2016-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#define EXECVP(file, argv) execvpe (file, argv, NULL)
+#include <posix/tst-execvp4.c>
diff --git a/posix/tst-execvpe5.c b/posix/tst-execvpe5.c
new file mode 100644
index 0000000000..044ceecacb
--- /dev/null
+++ b/posix/tst-execvpe5.c
@@ -0,0 +1,160 @@
+/* General tests for execpve.
+ Copyright (C) 2016-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <wait.h>
+
+
+/* Nonzero if the program gets called via `exec'. */
+static int restart;
+
+
+#define CMDLINE_OPTIONS \
+ { "restart", no_argument, &restart, 1 },
+
+/* Prototype for our test function. */
+extern void do_prepare (int argc, char *argv[]);
+extern int do_test (int argc, char *argv[]);
+
+#include "../test-skeleton.c"
+
+#define EXECVPE_KEY "EXECVPE_ENV"
+#define EXECVPE_VALUE "execvpe_test"
+
+
+static int
+handle_restart (void)
+{
+ /* First check if only one variable is passed on execvpe. */
+ int env_count = 0;
+ for (char **e = environ; *e != NULL; ++e)
+ if (++env_count == INT_MAX)
+ {
+ printf ("Environment variable number overflow");
+ exit (EXIT_FAILURE);
+ }
+ if (env_count != 1)
+ {
+ printf ("Wrong number of environment variables");
+ exit (EXIT_FAILURE);
+ }
+
+ /* Check if the combinarion os "EXECVPE_ENV=execvpe_test" */
+ const char *env = getenv (EXECVPE_KEY);
+ if (env == NULL)
+ {
+ printf ("Test environment variable not found");
+ exit (EXIT_FAILURE);
+ }
+
+ if (strncmp (env, EXECVPE_VALUE, sizeof (EXECVPE_VALUE)))
+ {
+ printf ("Test environment variable with wrong value");
+ exit (EXIT_FAILURE);
+ }
+
+ return 0;
+}
+
+
+int
+do_test (int argc, char *argv[])
+{
+ pid_t pid;
+ int status;
+
+ /* We must have
+ - one or four parameters left if called initially
+ + path for ld.so optional
+ + "--library-path" optional
+ + the library path optional
+ + the application name
+
+ if --enable-hardcoded-path-in-tests is used, just
+ + the application name
+ */
+
+ if (restart)
+ {
+ if (argc != 1)
+ {
+ printf ("Wrong number of arguments (%d) in restart\n", argc);
+ exit (EXIT_FAILURE);
+ }
+
+ return handle_restart ();
+ }
+
+ if (argc != 2 && argc != 5)
+ {
+ printf ("Wrong number of arguments (%d)\n", argc);
+ exit (EXIT_FAILURE);
+ }
+
+ /* We want to test the `execvpe' function. To do this we restart the
+ program with an additional parameter. */
+ pid = fork ();
+ if (pid == 0)
+ {
+ /* This is the child. Construct the command line. */
+
+ /* We cast here to char* because the test itself does not modify neither
+ the argument nor the environment list. */
+ char *envs[] = { (char*)(EXECVPE_KEY "=" EXECVPE_VALUE), NULL };
+ if (argc == 5)
+ {
+ char *args[] = { argv[1], argv[2], argv[3], argv[4],
+ (char *) "--direct", (char *) "--restart", NULL };
+ execvpe (args[0], args, envs);
+ }
+ else
+ {
+ char *args[] = { argv[0],
+ (char *) "--direct", (char *) "--restart", NULL };
+ execvpe (args[0], args, envs);
+ }
+
+ puts ("Cannot exec");
+ exit (EXIT_FAILURE);
+ }
+ else if (pid == (pid_t) -1)
+ {
+ puts ("Cannot fork");
+ return 1;
+ }
+
+ /* Wait for the child. */
+ if (waitpid (pid, &status, 0) != pid)
+ {
+ puts ("Wrong child");
+ return 1;
+ }
+
+ if (WTERMSIG (status) != 0)
+ {
+ puts ("Child terminated incorrectly");
+ return 1;
+ }
+ status = WEXITSTATUS (status);
+
+ return status;
+}
diff --git a/posix/tst-execvpe6.c b/posix/tst-execvpe6.c
new file mode 100644
index 0000000000..8073aeaf36
--- /dev/null
+++ b/posix/tst-execvpe6.c
@@ -0,0 +1,150 @@
+/* Check execvpe script argument handling.
+ Copyright (C) 2016-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/param.h>
+
+static char *fname1;
+static char *fname2;
+static char *logname;
+
+static void do_prepare (void);
+#define PREPARE(argc, argv) do_prepare ()
+static int do_test (void);
+#define TEST_FUNCTION do_test ()
+
+#include "../test-skeleton.c"
+
+static void
+do_prepare (void)
+{
+ int logfd = create_temp_file ("logfile", &logname);
+ close (logfd);
+
+ int fd1 = create_temp_file ("testscript", &fname1);
+ dprintf (fd1, "echo foo $1 $2 $3 > %s\n", logname);
+ fchmod (fd1, 0700);
+ close (fd1);
+
+ int fd2 = create_temp_file ("testscript", &fname2);
+ dprintf (fd2, "echo foo > %s\n", logname);
+ fchmod (fd2, 0700);
+ close (fd2);
+}
+
+static int
+run_script (const char *fname, char *args[])
+{
+ /* We want to test the `execvpe' function. To do this we restart the
+ program with an additional parameter. */
+ int status;
+ pid_t pid = fork ();
+ if (pid == 0)
+ {
+ execvpe (fname, args, NULL);
+
+ puts ("Cannot exec");
+ exit (EXIT_FAILURE);
+ }
+ else if (pid == (pid_t) -1)
+ {
+ puts ("Cannot fork");
+ return 1;
+ }
+
+ /* Wait for the child. */
+ if (waitpid (pid, &status, 0) != pid)
+ {
+ puts ("Wrong child");
+ return 1;
+ }
+
+ if (WTERMSIG (status) != 0)
+ {
+ puts ("Child terminated incorrectly");
+ return 1;
+ }
+
+ return 0;
+}
+
+static int
+check_output (const char *expected)
+{
+ /* Check log output. */
+ FILE *arq = fopen (logname, "r");
+ if (arq == NULL)
+ {
+ puts ("Error opening output file");
+ return 1;
+ }
+
+ char line[128];
+ if (fgets (line, sizeof (line), arq) == NULL)
+ {
+ puts ("Error reading output file");
+ return 1;
+ }
+ fclose (arq);
+
+ if (strcmp (line, expected) != 0)
+ {
+ puts ("Output file different than expected");
+ return 1;
+ }
+
+ return 0;
+}
+
+static int
+do_test (void)
+{
+ if (setenv ("PATH", test_dir, 1) != 0)
+ {
+ puts ("setenv failed");
+ return 1;
+ }
+
+ /* First check resulting script run with some arguments results in correct
+ output file. */
+ char *args1[] = { fname1, (char*) "1", (char *) "2", (char *) "3", NULL };
+ if (run_script (fname1,args1))
+ return 1;
+ if (check_output ("foo 1 2 3\n"))
+ return 1;
+
+ /* Same as before but with an expected empty argument list. */
+ char *args2[] = { fname2, NULL };
+ if (run_script (fname2, args2))
+ return 1;
+ if (check_output ("foo\n"))
+ return 1;
+
+ /* Same as before but with an empty argument list. */
+ char *args3[] = { NULL };
+ if (run_script (fname2, args3))
+ return 1;
+ if (check_output ("foo\n"))
+ return 1;
+
+ return 0;
+}
diff --git a/posix/tst-fexecve.c b/posix/tst-fexecve.c
new file mode 100644
index 0000000000..be4a09bf63
--- /dev/null
+++ b/posix/tst-fexecve.c
@@ -0,0 +1,88 @@
+/* Copyright (C) 2017-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/wait.h>
+
+#include <support/check.h>
+
+/* Try executing "/bin/sh -c true", using FD opened on /bin/sh. */
+static int
+try_fexecve (int fd)
+{
+ pid_t pid = fork ();
+
+ if (pid == 0)
+ {
+ static const char *const argv[] = {
+ "/bin/sh", "-c", "true", NULL
+ };
+ fexecve (fd, (char *const *) argv, environ);
+ _exit (errno);
+ }
+ if (pid < 0)
+ FAIL_RET ("fork failed: %m");
+
+ pid_t termpid;
+ int status;
+ termpid = TEMP_FAILURE_RETRY (waitpid (pid, &status, 0));
+ if (termpid == -1)
+ FAIL_RET ("waitpid failed: %m");
+ if (termpid != pid)
+ FAIL_RET ("waitpid returned %ld != %ld",
+ (long int) termpid, (long int) pid);
+ if (!WIFEXITED (status))
+ FAIL_RET ("child hasn't exited normally");
+
+ /* If fexecve is unimplemented mark this test as UNSUPPORTED. */
+ if (WEXITSTATUS (status) == ENOSYS)
+ FAIL_UNSUPPORTED ("fexecve is unimplemented");
+
+ if (WEXITSTATUS (status) != 0)
+ {
+ errno = WEXITSTATUS (status);
+ FAIL_RET ("fexecve failed: %m");
+ }
+ return 0;
+}
+
+static int
+do_test (void)
+{
+ int fd;
+ int ret;
+
+ fd = open ("/bin/sh", O_RDONLY);
+ if (fd < 0)
+ FAIL_UNSUPPORTED ("/bin/sh cannot be opened: %m");
+ ret = try_fexecve (fd);
+ close (fd);
+
+#ifdef O_PATH
+ fd = open ("/bin/sh", O_RDONLY | O_PATH);
+ if (fd < 0)
+ FAIL_UNSUPPORTED ("/bin/sh cannot be opened (O_PATH): %m");
+ ret |= try_fexecve (fd);
+ close (fd);
+#endif
+
+ return ret;
+}
+
+#include <support/test-driver.c>
diff --git a/posix/tst-fnmatch.c b/posix/tst-fnmatch.c
index f1e6455ba8..99d6ea1dc8 100644
--- a/posix/tst-fnmatch.c
+++ b/posix/tst-fnmatch.c
@@ -1,5 +1,5 @@
/* Tests for fnmatch function.
- Copyright (C) 2000-2016 Free Software Foundation, Inc.
+ Copyright (C) 2000-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/posix/tst-fnmatch.input b/posix/tst-fnmatch.input
index 96853cb75d..dc2ca8d01a 100644
--- a/posix/tst-fnmatch.input
+++ b/posix/tst-fnmatch.input
@@ -1,5 +1,5 @@
# Tests for fnmatch.
-# Copyright (C) 2000-2016 Free Software Foundation, Inc.
+# Copyright (C) 2000-2018 Free Software Foundation, Inc.
# This file is part of the GNU C Library.
# Contributes by Ulrich Drepper <drepper@redhat.com>.
#
@@ -23,6 +23,63 @@
# wording describing the situations to be tested. It does not specify
# any specific tests. I.e., the tests below are in no case sufficient.
# They are hopefully necessary, though.
+#
+# See:
+#
+# http://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_xbd_chap09.html
+#
+# > RE Bracket Expression
+# >
+# > Range expressions are, historically, an integral part of REs.
+# > However, the requirements of "natural language behavior" and
+# > portability do conflict. In the POSIX locale, ranges must be treated
+# > according to the collating sequence and include such characters that
+# > fall within the range based on that collating sequence, regardless
+# > of character values. In other locales, ranges have unspecified behavior.
+# > ...
+# > The current standard leaves unspecified the behavior of a range
+# > expression outside the POSIX locale. This makes it clearer that
+# > conforming applications should avoid range expressions outside the
+# > POSIX locale, and it allows implementations and compatible user-mode
+# > matchers to interpret range expressions using native order, CEO,
+# > collation sequence, or other, more advanced techniques. The concerns
+# > which led to this change were raised in IEEE PASC interpretation
+# > 1003.2 #43 and others, and related to ambiguities in the
+# > specification of how multi-character collating elements should be
+# > handled in range expressions. These ambiguities had led to multiple
+# > interpretations of the specification, in conflicting ways, which led
+# > to varying implementations. As noted above, efforts were made to
+# > resolve the differences, but no solution has been found that would
+# > be specific enough to allow for portable software while not
+# > invalidating existing implementations.
+#
+# Therefore, using [a-z] does not make much sense except in the C/POSIX locale.
+# The new iso14651_t1_common lists upper case and lower case Latin characters
+# in a different order than the old one which causes surprising results
+# for example in the de_DE locale: [a-z] now includes A because A comes
+# after a in iso14651_t1_common but does not include Z because that comes
+# after z in iso14651_t1_common.
+#
+# This lead to several bugs and problems with user scripts that do not
+# expect [a-z] to match uppercase characters.
+#
+# See the following bugs:
+# https://sourceware.org/bugzilla/show_bug.cgi?id=23393
+# https://sourceware.org/bugzilla/show_bug.cgi?id=23420
+#
+# No consensus exists on how best to handle the changes so the
+# iso14651_t1_common collation element order (CEO) has been changed to
+# deinterlace the a-z and A-Z regions.
+#
+# With the deinterlacing commit ac3a3b4b0d561d776b60317d6a926050c8541655
+# could be reverted to re-test the correct non-interleaved expectations.
+#
+# Please note that despite the region being deinterlaced, the ordering
+# of collation remains the same. In glibc we implement CEO and because of
+# that we can reorder the elements to reorder ranges without impacting
+# collation which depends on weights. The collation element ordering
+# could have been changed to include just a-z, A-Z, and 0-9 in three
+# distinct blocks, but this needs more discussion by the community.
# B.6 004(C)
C "!#%+,-./01234567889" "!#%+,-./01234567889" 0
@@ -510,6 +567,16 @@ de_DE.ISO-8859-1 "ba" "[[.a.]]a" NOMATCH
# And with a multibyte character set.
+en_US.UTF-8 "a" "[a-z]" 0
+en_US.UTF-8 "z" "[a-z]" 0
+en_US.UTF-8 "A" "[a-z]" NOMATCH
+en_US.UTF-8 "Z" "[a-z]" NOMATCH
+en_US.UTF-8 "a" "[A-Z]" NOMATCH
+en_US.UTF-8 "z" "[A-Z]" NOMATCH
+en_US.UTF-8 "A" "[A-Z]" 0
+en_US.UTF-8 "Z" "[A-Z]" 0
+en_US.UTF-8 "0" "[0-9]" 0
+en_US.UTF-8 "9" "[0-9]" 0
de_DE.UTF-8 "a" "[a-z]" 0
de_DE.UTF-8 "z" "[a-z]" 0
de_DE.UTF-8 "ä" "[a-z]" 0
diff --git a/posix/tst-fnmatch3.c b/posix/tst-fnmatch3.c
index 82ea001b56..ea1df76623 100644
--- a/posix/tst-fnmatch3.c
+++ b/posix/tst-fnmatch3.c
@@ -1,5 +1,5 @@
/* Test for fnmatch not reading past the end of the pattern.
- Copyright (C) 2014-2016 Free Software Foundation, Inc.
+ Copyright (C) 2014-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/posix/tst-fork.c b/posix/tst-fork.c
index 893c024e47..eb5c5442b1 100644
--- a/posix/tst-fork.c
+++ b/posix/tst-fork.c
@@ -1,5 +1,5 @@
/* Tests for fork.
- Copyright (C) 2000-2016 Free Software Foundation, Inc.
+ Copyright (C) 2000-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 2000.
diff --git a/posix/tst-getaddrinfo.c b/posix/tst-getaddrinfo.c
index 1ddaf18b16..1632f1c3a5 100644
--- a/posix/tst-getaddrinfo.c
+++ b/posix/tst-getaddrinfo.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1999-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1999-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/posix/tst-getaddrinfo2.c b/posix/tst-getaddrinfo2.c
index 13edca0a34..d8be4a8e8f 100644
--- a/posix/tst-getaddrinfo2.c
+++ b/posix/tst-getaddrinfo2.c
@@ -2,6 +2,7 @@
#include <errno.h>
#include <netdb.h>
#include <unistd.h>
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
diff --git a/posix/tst-getaddrinfo4.c b/posix/tst-getaddrinfo4.c
index 5a20d0e64f..dc9e423448 100644
--- a/posix/tst-getaddrinfo4.c
+++ b/posix/tst-getaddrinfo4.c
@@ -1,5 +1,5 @@
/* Test getaddrinfo return value, [BZ #15339].
- Copyright (C) 2013-2016 Free Software Foundation, Inc.
+ Copyright (C) 2013-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/posix/tst-getaddrinfo5.c b/posix/tst-getaddrinfo5.c
index 7ad49ecf36..f36121e87c 100644
--- a/posix/tst-getaddrinfo5.c
+++ b/posix/tst-getaddrinfo5.c
@@ -1,5 +1,5 @@
/* Test host lookup with double dots at the end, [BZ #16469].
- Copyright (C) 2014-2016 Free Software Foundation, Inc.
+ Copyright (C) 2014-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -19,6 +19,7 @@
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
+#include <stdio.h>
#include <string.h>
static int
diff --git a/posix/tst-getconf.sh b/posix/tst-getconf.sh
index 95d11f59ec..b1c5dc8a87 100644
--- a/posix/tst-getconf.sh
+++ b/posix/tst-getconf.sh
@@ -1,6 +1,6 @@
#!/bin/sh
# Test for getconf(1).
-# Copyright (C) 2001-2016 Free Software Foundation, Inc.
+# Copyright (C) 2001-2018 Free Software Foundation, Inc.
# This file is part of the GNU C Library.
# The GNU C Library is free software; you can redistribute it and/or
diff --git a/posix/tst-getopt-cancel.c b/posix/tst-getopt-cancel.c
new file mode 100644
index 0000000000..3c25a8e7c2
--- /dev/null
+++ b/posix/tst-getopt-cancel.c
@@ -0,0 +1,284 @@
+/* Copyright (C) 2017-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+/* fprintf is a cancellation point, but getopt is not supposed to be a
+ cancellation point, even when it prints error messages. */
+
+/* Note: getopt.h must be included first in this file, so we get the
+ GNU getopt rather than the POSIX one. */
+#include <getopt.h>
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <fcntl.h>
+#include <pthread.h>
+#include <unistd.h>
+
+#include <support/support.h>
+#include <support/temp_file.h>
+#include <support/xthread.h>
+
+static bool
+check_stderr (bool expect_errmsg, FILE *stderr_trapped)
+{
+ static char *lineptr = 0;
+ static size_t linesz = 0;
+
+ bool got_errmsg = false;
+ rewind (stderr_trapped);
+ while (getline (&lineptr, &linesz, stderr_trapped) > 0)
+ {
+ got_errmsg = true;
+ fputs (lineptr, stdout);
+ }
+ rewind (stderr_trapped);
+ ftruncate (fileno (stderr_trapped), 0);
+ return got_errmsg == expect_errmsg;
+}
+
+struct test_short
+{
+ const char *label;
+ const char *opts;
+ const char *const argv[8];
+ int argc;
+ bool expect_errmsg;
+};
+
+struct test_long
+{
+ const char *label;
+ const char *opts;
+ const struct option longopts[4];
+ const char *const argv[8];
+ int argc;
+ bool expect_errmsg;
+};
+
+#define DEFINE_TEST_DRIVER(test_type, getopt_call) \
+ struct test_type##_tdata \
+ { \
+ pthread_mutex_t *sync; \
+ const struct test_type *tcase; \
+ bool ok; \
+ }; \
+ \
+ static void * \
+ test_type##_threadproc (void *data) \
+ { \
+ struct test_type##_tdata *tdata = data; \
+ const struct test_type *tc = tdata->tcase; \
+ \
+ xpthread_mutex_lock (tdata->sync); \
+ xpthread_mutex_unlock (tdata->sync); \
+ \
+ /* At this point, this thread has a cancellation pending. \
+ We should still be able to get all the way through a getopt \
+ loop without being cancelled. \
+ Setting optind to 0 forces getopt to reinitialize itself. */ \
+ optind = 0; \
+ opterr = 1; \
+ optopt = 0; \
+ while (getopt_call != -1) \
+ ; \
+ tdata->ok = true; \
+ \
+ pthread_testcancel(); \
+ return 0; \
+ } \
+ \
+ static bool \
+ do_##test_type (const struct test_type *tcase, FILE *stderr_trapped) \
+ { \
+ pthread_mutex_t sync; \
+ struct test_type##_tdata tdata; \
+ \
+ printf("begin: %s\n", tcase->label); \
+ \
+ xpthread_mutex_init (&sync, 0); \
+ xpthread_mutex_lock (&sync); \
+ \
+ tdata.sync = &sync; \
+ tdata.tcase = tcase; \
+ tdata.ok = false; \
+ \
+ pthread_t thr = xpthread_create (0, test_type##_threadproc, \
+ (void *)&tdata); \
+ xpthread_cancel (thr); \
+ xpthread_mutex_unlock (&sync); \
+ void *rv = xpthread_join (thr); \
+ \
+ xpthread_mutex_destroy (&sync); \
+ \
+ bool ok = true; \
+ if (!check_stderr (tcase->expect_errmsg, stderr_trapped)) \
+ { \
+ ok = false; \
+ printf("FAIL: %s: stderr not as expected\n", tcase->label); \
+ } \
+ if (!tdata.ok) \
+ { \
+ ok = false; \
+ printf("FAIL: %s: did not complete loop\n", tcase->label); \
+ } \
+ if (rv != PTHREAD_CANCELED) \
+ { \
+ ok = false; \
+ printf("FAIL: %s: thread was not cancelled\n", tcase->label); \
+ } \
+ if (ok) \
+ printf ("pass: %s\n", tcase->label); \
+ return ok; \
+ }
+
+DEFINE_TEST_DRIVER (test_short,
+ getopt (tc->argc, (char *const *)tc->argv, tc->opts))
+DEFINE_TEST_DRIVER (test_long,
+ getopt_long (tc->argc, (char *const *)tc->argv,
+ tc->opts, tc->longopts, 0))
+
+/* Caution: all option strings must begin with a '+' or '-' so that
+ getopt does not attempt to permute the argument vector (which is in
+ read-only memory). */
+const struct test_short tests_short[] = {
+ { "no errors",
+ "+ab:c", { "program", "-ac", "-b", "x", 0 }, 4, false },
+ { "invalid option",
+ "+ab:c", { "program", "-d", 0 }, 2, true },
+ { "missing argument",
+ "+ab:c", { "program", "-b", 0 }, 2, true },
+ { 0 }
+};
+
+const struct test_long tests_long[] = {
+ { "no errors (long)",
+ "+ab:c", { { "alpha", no_argument, 0, 'a' },
+ { "bravo", required_argument, 0, 'b' },
+ { "charlie", no_argument, 0, 'c' },
+ { 0 } },
+ { "program", "-a", "--charlie", "--bravo=x", 0 }, 4, false },
+
+ { "invalid option (long)",
+ "+ab:c", { { "alpha", no_argument, 0, 'a' },
+ { "bravo", required_argument, 0, 'b' },
+ { "charlie", no_argument, 0, 'c' },
+ { 0 } },
+ { "program", "-a", "--charlie", "--dingo", 0 }, 4, true },
+
+ { "unwanted argument",
+ "+ab:c", { { "alpha", no_argument, 0, 'a' },
+ { "bravo", required_argument, 0, 'b' },
+ { "charlie", no_argument, 0, 'c' },
+ { 0 } },
+ { "program", "-a", "--charlie=dingo", "--bravo=x", 0 }, 4, true },
+
+ { "missing argument",
+ "+ab:c", { { "alpha", no_argument, 0, 'a' },
+ { "bravo", required_argument, 0, 'b' },
+ { "charlie", no_argument, 0, 'c' },
+ { 0 } },
+ { "program", "-a", "--charlie", "--bravo", 0 }, 4, true },
+
+ { "ambiguous options",
+ "+uvw", { { "veni", no_argument, 0, 'u' },
+ { "vedi", no_argument, 0, 'v' },
+ { "veci", no_argument, 0, 'w' } },
+ { "program", "--ve", 0 }, 2, true },
+
+ { "no errors (long W)",
+ "+ab:cW;", { { "alpha", no_argument, 0, 'a' },
+ { "bravo", required_argument, 0, 'b' },
+ { "charlie", no_argument, 0, 'c' },
+ { 0 } },
+ { "program", "-a", "-W", "charlie", "-W", "bravo=x", 0 }, 6, false },
+
+ { "missing argument (W itself)",
+ "+ab:cW;", { { "alpha", no_argument, 0, 'a' },
+ { "bravo", required_argument, 0, 'b' },
+ { "charlie", no_argument, 0, 'c' },
+ { 0 } },
+ { "program", "-a", "-W", "charlie", "-W", 0 }, 5, true },
+
+ { "missing argument (W longopt)",
+ "+ab:cW;", { { "alpha", no_argument, 0, 'a' },
+ { "bravo", required_argument, 0, 'b' },
+ { "charlie", no_argument, 0, 'c' },
+ { 0 } },
+ { "program", "-a", "-W", "charlie", "-W", "bravo", 0 }, 6, true },
+
+ { "unwanted argument (W longopt)",
+ "+ab:cW;", { { "alpha", no_argument, 0, 'a' },
+ { "bravo", required_argument, 0, 'b' },
+ { "charlie", no_argument, 0, 'c' },
+ { 0 } },
+ { "program", "-a", "-W", "charlie=dingo", "-W", "bravo=x", 0 }, 6, true },
+
+ { "ambiguous options (W)",
+ "+uvwW;", { { "veni", no_argument, 0, 'u' },
+ { "vedi", no_argument, 0, 'v' },
+ { "veci", no_argument, 0, 'w' } },
+ { "program", "-W", "ve", 0 }, 3, true },
+
+ { 0 }
+};
+
+static int
+do_test (void)
+{
+ int stderr_trap = create_temp_file ("stderr", 0);
+ if (stderr_trap < 0)
+ {
+ perror ("create_temp_file");
+ return 1;
+ }
+ FILE *stderr_trapped = fdopen(stderr_trap, "r+");
+ if (!stderr_trapped)
+ {
+ perror ("fdopen");
+ return 1;
+ }
+ int old_stderr = dup (fileno (stderr));
+ if (old_stderr < 0)
+ {
+ perror ("dup");
+ return 1;
+ }
+ if (dup2 (stderr_trap, 2) < 0)
+ {
+ perror ("dup2");
+ return 1;
+ }
+ rewind (stderr);
+
+ bool success = true;
+
+ for (const struct test_short *tcase = tests_short; tcase->label; tcase++)
+ success = do_test_short (tcase, stderr_trapped) && success;
+
+ for (const struct test_long *tcase = tests_long; tcase->label; tcase++)
+ success = do_test_long (tcase, stderr_trapped) && success;
+
+ dup2 (old_stderr, 2);
+ close (old_stderr);
+ fclose (stderr_trapped);
+
+ return success ? 0 : 1;
+}
+
+#include <support/test-driver.c>
diff --git a/posix/tst-getopt_long1.c b/posix/tst-getopt_long1.c
index 3895ebd99b..6d8ef02ca4 100644
--- a/posix/tst-getopt_long1.c
+++ b/posix/tst-getopt_long1.c
@@ -56,7 +56,7 @@ do_test (void)
printf ("message = \"%s\"\n", line);
static const char expected[] = "\
-program: option '--on' is ambiguous; possibilities: '--one' '--onto' '--one-one'\n";
+program: option '--on' is ambiguous; possibilities: '--one' '--one-one' '--onto'\n";
return c != '?' || strcmp (line, expected) != 0;
}
diff --git a/posix/tst-glob-tilde.c b/posix/tst-glob-tilde.c
new file mode 100644
index 0000000000..853b6896fe
--- /dev/null
+++ b/posix/tst-glob-tilde.c
@@ -0,0 +1,144 @@
+/* Check for GLOB_TIDLE heap allocation issues (bugs 22320, 22325, 22332).
+ Copyright (C) 2017-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <glob.h>
+#include <mcheck.h>
+#include <nss.h>
+#include <pwd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <support/check.h>
+#include <support/support.h>
+
+/* Flag which indicates whether to pass the GLOB_ONLYDIR flag. */
+static int do_onlydir;
+
+/* Flag which indicates whether to pass the GLOB_NOCHECK flag. */
+static int do_nocheck;
+
+/* Flag which indicates whether to pass the GLOB_MARK flag. */
+static int do_mark;
+
+/* Flag which indicates whether to pass the GLOB_NOESCAPE flag. */
+static int do_noescape;
+
+static void
+one_test (const char *prefix, const char *middle, const char *suffix)
+{
+ char *pattern = xasprintf ("%s%s%s", prefix, middle, suffix);
+ int flags = GLOB_TILDE;
+ if (do_onlydir)
+ flags |= GLOB_ONLYDIR;
+ if (do_nocheck)
+ flags |= GLOB_NOCHECK;
+ if (do_mark)
+ flags |= GLOB_MARK;
+ if (do_noescape)
+ flags |= GLOB_NOESCAPE;
+ glob_t gl;
+ /* This glob call might result in crashes or memory leaks. */
+ if (glob (pattern, flags, NULL, &gl) == 0)
+ globfree (&gl);
+ free (pattern);
+}
+
+enum
+ {
+ /* The largest base being tested. */
+ largest_base_size = 500000,
+
+ /* The actual size is the base size plus a variable whose absolute
+ value is not greater than this. This helps malloc to trigger
+ overflows. */
+ max_size_skew = 16,
+
+ /* The maximum string length supported by repeating_string
+ below. */
+ repeat_size = largest_base_size + max_size_skew,
+ };
+
+/* Used to construct strings which repeat a single character 'x'. */
+static char *repeat;
+
+/* Return a string of SIZE characters. */
+const char *
+repeating_string (int size)
+{
+ TEST_VERIFY (size >= 0);
+ TEST_VERIFY (size <= repeat_size);
+ const char *repeated_shifted = repeat + repeat_size - size;
+ TEST_VERIFY (strlen (repeated_shifted) == size);
+ return repeated_shifted;
+}
+
+static int
+do_test (void)
+{
+ /* Avoid network-based NSS modules and initialize nss_files with a
+ dummy lookup. This has to come before mtrace because NSS does
+ not free all memory. */
+ __nss_configure_lookup ("passwd", "files");
+ (void) getpwnam ("root");
+
+ mtrace ();
+
+ repeat = xmalloc (repeat_size + 1);
+ memset (repeat, 'x', repeat_size);
+ repeat[repeat_size] = '\0';
+
+ /* These numbers control the size of the user name. The values
+ cover the minimum (0), a typical size (8), a large
+ stack-allocated size (100000), and a somewhat large
+ heap-allocated size (largest_base_size). */
+ static const int base_sizes[] = { 0, 8, 100, 100000, largest_base_size, -1 };
+
+ for (do_onlydir = 0; do_onlydir < 2; ++do_onlydir)
+ for (do_nocheck = 0; do_nocheck < 2; ++do_nocheck)
+ for (do_mark = 0; do_mark < 2; ++do_mark)
+ for (do_noescape = 0; do_noescape < 2; ++do_noescape)
+ for (int base_idx = 0; base_sizes[base_idx] >= 0; ++base_idx)
+ {
+ for (int size_skew = -max_size_skew; size_skew <= max_size_skew;
+ ++size_skew)
+ {
+ int size = base_sizes[base_idx] + size_skew;
+ if (size < 0)
+ continue;
+
+ const char *user_name = repeating_string (size);
+ one_test ("~", user_name, "/a/b");
+ one_test ("~", user_name, "x\\x\\x////x\\a");
+ }
+
+ const char *user_name = repeating_string (base_sizes[base_idx]);
+ one_test ("~", user_name, "");
+ one_test ("~", user_name, "/");
+ one_test ("~", user_name, "/a");
+ one_test ("~", user_name, "/*/*");
+ one_test ("~", user_name, "\\/");
+ one_test ("/~", user_name, "");
+ one_test ("*/~", user_name, "/a/b");
+ }
+
+ free (repeat);
+
+ return 0;
+}
+
+#define TIMEOUT 200
+#include <support/test-driver.c>
diff --git a/posix/tst-glob_lstat_compat.c b/posix/tst-glob_lstat_compat.c
new file mode 100644
index 0000000000..22cd1f02f9
--- /dev/null
+++ b/posix/tst-glob_lstat_compat.c
@@ -0,0 +1,268 @@
+/* Test glob compat symbol which avoid call GLOB_ALTDIRFUNC/gl_lstat.
+ Copyright (C) 2017-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <glob.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <stdio.h>
+
+#include <shlib-compat.h>
+#include <support/check.h>
+#include <support/temp_file.h>
+
+#if TEST_COMPAT (libc, GLIBC_2_0, GLIBC_2_27)
+
+__typeof (glob) glob;
+/* On alpha glob exists in version GLIBC_2_0, GLIBC_2_1, and GLIBC_2_27.
+ This test needs to access the version prior to GLIBC_2_27, which is
+ GLIBC_2_1 on alpha, GLIBC_2_0 elsewhere. */
+# ifdef __alpha__
+compat_symbol_reference (libc, glob, glob, GLIBC_2_1);
+# else
+compat_symbol_reference (libc, glob, glob, GLIBC_2_0);
+# endif
+
+/* Compat glob should not call gl_lstat since for some old binaries it
+ might be unitialized (for instance GNUmake). Check if it is indeed
+ not called. */
+static bool stat_called;
+static bool lstat_called;
+
+static struct
+{
+ const char *name;
+ int level;
+ int type;
+} filesystem[] =
+{
+ { ".", 1, DT_DIR },
+ { "..", 1, DT_DIR },
+ { "dir1lev1", 1, DT_UNKNOWN },
+ { ".", 2, DT_DIR },
+ { "..", 2, DT_DIR },
+ { "file1lev2", 2, DT_REG },
+ { "file2lev2", 2, DT_REG },
+};
+static const size_t nfiles = sizeof (filesystem) / sizeof (filesystem [0]);
+
+typedef struct
+{
+ int level;
+ int idx;
+ struct dirent d;
+ char room_for_dirent[NAME_MAX];
+} my_DIR;
+
+static long int
+find_file (const char *s)
+{
+ int level = 1;
+ long int idx = 0;
+
+ while (s[0] == '/')
+ {
+ if (s[1] == '\0')
+ {
+ s = ".";
+ break;
+ }
+ ++s;
+ }
+
+ if (strcmp (s, ".") == 0)
+ return 0;
+
+ if (s[0] == '.' && s[1] == '/')
+ s += 2;
+
+ while (*s != '\0')
+ {
+ char *endp = strchrnul (s, '/');
+
+ while (idx < nfiles && filesystem[idx].level >= level)
+ {
+ if (filesystem[idx].level == level
+ && memcmp (s, filesystem[idx].name, endp - s) == 0
+ && filesystem[idx].name[endp - s] == '\0')
+ break;
+ ++idx;
+ }
+
+ if (idx == nfiles || filesystem[idx].level < level)
+ {
+ errno = ENOENT;
+ return -1;
+ }
+
+ if (*endp == '\0')
+ return idx + 1;
+
+ if (filesystem[idx].type != DT_DIR
+ && (idx + 1 >= nfiles
+ || filesystem[idx].level >= filesystem[idx + 1].level))
+ {
+ errno = ENOTDIR;
+ return -1;
+ }
+
+ ++idx;
+
+ s = endp + 1;
+ ++level;
+ }
+
+ errno = ENOENT;
+ return -1;
+}
+
+static void *
+my_opendir (const char *s)
+{
+ long int idx = find_file (s);
+ if (idx == -1 || filesystem[idx].type != DT_DIR)
+ return NULL;
+
+ my_DIR *dir = malloc (sizeof (my_DIR));
+ if (dir == NULL)
+ FAIL_EXIT1 ("cannot allocate directory handle");
+
+ dir->level = filesystem[idx].level;
+ dir->idx = idx;
+
+ return dir;
+}
+
+static struct dirent *
+my_readdir (void *gdir)
+{
+ my_DIR *dir = gdir;
+
+ if (dir->idx == -1)
+ return NULL;
+
+ while (dir->idx < nfiles && filesystem[dir->idx].level > dir->level)
+ ++dir->idx;
+
+ if (dir->idx == nfiles || filesystem[dir->idx].level < dir->level)
+ {
+ dir->idx = -1;
+ return NULL;
+ }
+
+ dir->d.d_ino = 1; /* glob should not skip this entry. */
+
+ dir->d.d_type = filesystem[dir->idx].type;
+
+ strcpy (dir->d.d_name, filesystem[dir->idx].name);
+
+ ++dir->idx;
+
+ return &dir->d;
+}
+
+static void
+my_closedir (void *dir)
+{
+ free (dir);
+}
+
+static int
+my_stat (const char *name, struct stat *st)
+{
+ stat_called = true;
+
+ long int idx = find_file (name);
+ if (idx == -1)
+ return -1;
+
+ memset (st, '\0', sizeof (*st));
+
+ if (filesystem[idx].type == DT_UNKNOWN)
+ st->st_mode = DTTOIF (idx + 1 < nfiles
+ && filesystem[idx].level < filesystem[idx + 1].level
+ ? DT_DIR : DT_REG) | 0777;
+ else
+ st->st_mode = DTTOIF (filesystem[idx].type) | 0777;
+ return 0;
+}
+
+static int
+my_lstat (const char *name, struct stat *st)
+{
+ lstat_called = true;
+
+ long int idx = find_file (name);
+ if (idx == -1)
+ return -1;
+
+ memset (st, '\0', sizeof (*st));
+
+ if (filesystem[idx].type == DT_UNKNOWN)
+ st->st_mode = DTTOIF (idx + 1 < nfiles
+ && filesystem[idx].level < filesystem[idx + 1].level
+ ? DT_DIR : DT_REG) | 0777;
+ else
+ st->st_mode = DTTOIF (filesystem[idx].type) | 0777;
+ return 0;
+}
+
+static int
+do_test (void)
+{
+ glob_t gl;
+
+ memset (&gl, '\0', sizeof (gl));
+
+ gl.gl_closedir = my_closedir;
+ gl.gl_readdir = my_readdir;
+ gl.gl_opendir = my_opendir;
+ gl.gl_lstat = my_lstat;
+ gl.gl_stat = my_stat;
+
+ int flags = GLOB_ALTDIRFUNC;
+
+ stat_called = false;
+ lstat_called = false;
+
+ TEST_VERIFY_EXIT (glob ("*/file1lev2", flags, NULL, &gl) == 0);
+ TEST_VERIFY_EXIT (gl.gl_pathc == 1);
+ TEST_VERIFY_EXIT (strcmp (gl.gl_pathv[0], "dir1lev1/file1lev2") == 0);
+
+ TEST_VERIFY_EXIT (stat_called == true);
+ TEST_VERIFY_EXIT (lstat_called == false);
+
+ return 0;
+}
+
+#else /* TEST_COMPAT (libc, GLIBC_2_0, GLIBC_2_27) */
+
+static int
+do_test (void)
+{
+ return 77;
+}
+#endif
+
+#include <support/test-driver.c>
diff --git a/posix/tst-glob_symlinks.c b/posix/tst-glob_symlinks.c
new file mode 100644
index 0000000000..df3baa8757
--- /dev/null
+++ b/posix/tst-glob_symlinks.c
@@ -0,0 +1,138 @@
+/* Test glob danglin symlink match (BZ #866).
+ Copyright (C) 2017-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <limits.h>
+#include <stddef.h>
+#include <glob.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <support/check.h>
+#include <support/temp_file.h>
+
+static void do_prepare (int argc, char *argv[]);
+#define PREPARE do_prepare
+static int do_test (void);
+#include <support/test-driver.c>
+
+/* Maximum number of symlink calls for create_link function. */
+#define MAX_CREATE_LINK_TRIES 10
+
+static void
+create_link (const char *base, const char *fname, char *linkname,
+ size_t linknamesize)
+{
+ int ntries = 0;
+ while (1)
+ {
+ snprintf (linkname, linknamesize, "%s/%s%02d", test_dir, base,
+ ntries);
+ if (symlink (fname, linkname) == 0)
+ break;
+ if (errno != EEXIST)
+ FAIL_EXIT1 ("symlink failed: %m");
+ if (ntries++ == MAX_CREATE_LINK_TRIES)
+ FAIL_EXIT1 ("symlink failed with EEXIST too many times");
+ }
+ add_temp_file (linkname);
+}
+
+#ifndef PATH_MAX
+# define PATH_MAX 1024
+#endif
+static char valid_link[PATH_MAX];
+static char dangling_link[PATH_MAX];
+static char dangling_dir[PATH_MAX];
+
+static void
+do_prepare (int argc, char *argv[])
+{
+ char *fname;
+
+ create_temp_file ("tst-glob_symlinks.", &fname);
+
+ /* Create an existing symlink. */
+ create_link ("valid-symlink-tst-glob_symlinks", fname, valid_link,
+ sizeof valid_link);
+
+ /* Create a dangling symlink to a file. */
+ int fd = create_temp_file ("dangling-tst-glob_file", &fname);
+ TEST_VERIFY_EXIT (close (fd) == 0);
+ /* It throws a warning at process end due 'add_temp_file' trying to
+ unlink it again. */
+ TEST_VERIFY_EXIT (unlink (fname) == 0);
+ create_link ("dangling-symlink-file-tst-glob", fname, dangling_link,
+ sizeof dangling_link);
+
+ /* Create a dangling symlink to a directory. */
+ char tmpdir[PATH_MAX];
+ snprintf (tmpdir, sizeof tmpdir, "%s/dangling-tst-glob_folder.XXXXXX",
+ test_dir);
+ TEST_VERIFY_EXIT (mkdtemp (tmpdir) != NULL);
+ create_link ("dangling-symlink-dir-tst-glob", tmpdir, dangling_dir,
+ sizeof dangling_dir);
+ TEST_VERIFY_EXIT (rmdir (tmpdir) == 0);
+}
+
+static int
+do_test (void)
+{
+ char buf[PATH_MAX + 1];
+ glob_t gl;
+
+ TEST_VERIFY_EXIT (glob (valid_link, 0, NULL, &gl) == 0);
+ TEST_VERIFY_EXIT (gl.gl_pathc == 1);
+ TEST_VERIFY_EXIT (strcmp (gl.gl_pathv[0], valid_link) == 0);
+ globfree (&gl);
+
+ TEST_VERIFY_EXIT (glob (dangling_link, 0, NULL, &gl) == 0);
+ TEST_VERIFY_EXIT (gl.gl_pathc == 1);
+ TEST_VERIFY_EXIT (strcmp (gl.gl_pathv[0], dangling_link) == 0);
+ globfree (&gl);
+
+ TEST_VERIFY_EXIT (glob (dangling_dir, 0, NULL, &gl) == 0);
+ TEST_VERIFY_EXIT (gl.gl_pathc == 1);
+ TEST_VERIFY_EXIT (strcmp (gl.gl_pathv[0], dangling_dir) == 0);
+ globfree (&gl);
+
+ snprintf (buf, sizeof buf, "%s", dangling_link);
+ buf[strlen(buf) - 1] = '?';
+ TEST_VERIFY_EXIT (glob (buf, 0, NULL, &gl) == 0);
+ TEST_VERIFY_EXIT (gl.gl_pathc == 1);
+ TEST_VERIFY_EXIT (strcmp (gl.gl_pathv[0], dangling_link) == 0);
+ globfree (&gl);
+
+ /* glob should handle dangling symbol as normal file, so <file>? should
+ return an empty string. */
+ snprintf (buf, sizeof buf, "%s?", dangling_link);
+ TEST_VERIFY_EXIT (glob (buf, 0, NULL, &gl) != 0);
+ globfree (&gl);
+
+ snprintf (buf, sizeof buf, "%s*", dangling_link);
+ TEST_VERIFY_EXIT (glob (buf, 0, NULL, &gl) == 0);
+ TEST_VERIFY_EXIT (gl.gl_pathc == 1);
+ TEST_VERIFY_EXIT (strcmp (gl.gl_pathv[0], dangling_link) == 0);
+ globfree (&gl);
+
+ return 0;
+}
diff --git a/posix/tst-gnuglob-skeleton.c b/posix/tst-gnuglob-skeleton.c
new file mode 100644
index 0000000000..0e5c87e6db
--- /dev/null
+++ b/posix/tst-gnuglob-skeleton.c
@@ -0,0 +1,508 @@
+/* Template for tests of the GNU extension GLOB_ALTDIRFUNC.
+ Copyright (C) 2001-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@redhat.com>, 2001.
+
+ 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, see
+ <http://www.gnu.org/licenses/>. */
+
+/* To use this skeleton, the following macros need to be defined
+ before inclusion of this file:
+
+ GLOB_FUNC The glob function to test (glob or glob64)
+ GLOB_TYPE The glob type expected by the function (glob_t, glob64_t)
+ GLOBFREE_FUNC The corresponding deallocation function
+ DIRENT_STRUCT The struct tag of the dirent type
+ STAT_STRUCT The struct tag of the stat type
+*/
+
+#include <dirent.h>
+#include <errno.h>
+#include <error.h>
+#include <glob.h>
+#include <mcheck.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <support/test-driver.h>
+
+
+static struct
+{
+ const char *name;
+ int level;
+ int type;
+} filesystem[] =
+{
+ { ".", 1, DT_DIR },
+ { "..", 1, DT_DIR },
+ { "file1lev1", 1, DT_REG },
+ { "file2lev1", 1, DT_UNKNOWN },
+ { "dir1lev1", 1, DT_UNKNOWN },
+ { ".", 2, DT_DIR },
+ { "..", 2, DT_DIR },
+ { "file1lev2", 2, DT_REG },
+ { "dir1lev2", 2, DT_DIR },
+ { ".", 3, DT_DIR },
+ { "..", 3, DT_DIR },
+ { "dir2lev2", 2, DT_DIR },
+ { ".", 3, DT_DIR },
+ { "..", 3, DT_DIR },
+ { ".foo", 3, DT_REG },
+ { "dir1lev3", 3, DT_DIR },
+ { ".", 4, DT_DIR },
+ { "..", 4, DT_DIR },
+ { "file1lev4", 4, DT_REG },
+ { "file1lev3", 3, DT_REG },
+ { "file2lev3", 3, DT_REG },
+ { "file2lev2", 2, DT_REG },
+ { "file3lev2", 2, DT_REG },
+ { "dir3lev2", 2, DT_DIR },
+ { ".", 3, DT_DIR },
+ { "..", 3, DT_DIR },
+ { "file3lev3", 3, DT_REG },
+ { "file4lev3", 3, DT_REG },
+ { "dir2lev1", 1, DT_DIR },
+ { ".", 2, DT_DIR },
+ { "..", 2, DT_DIR },
+ { "dir1lev2", 2, DT_UNKNOWN },
+ { ".", 3, DT_DIR },
+ { "..", 3, DT_DIR },
+ { ".foo", 3, DT_REG },
+ { ".dir", 3, DT_DIR },
+ { ".", 4, DT_DIR },
+ { "..", 4, DT_DIR },
+ { "hidden", 4, DT_REG }
+};
+#define nfiles (sizeof (filesystem) / sizeof (filesystem[0]))
+
+
+typedef struct
+{
+ int level;
+ int idx;
+ struct DIRENT_STRUCT d;
+ char room_for_dirent[NAME_MAX];
+} my_DIR;
+
+
+static long int
+find_file (const char *s)
+{
+ int level = 1;
+ long int idx = 0;
+
+ while (s[0] == '/')
+ {
+ if (s[1] == '\0')
+ {
+ s = ".";
+ break;
+ }
+ ++s;
+ }
+
+ if (strcmp (s, ".") == 0)
+ return 0;
+
+ if (s[0] == '.' && s[1] == '/')
+ s += 2;
+
+ while (*s != '\0')
+ {
+ char *endp = strchrnul (s, '/');
+
+ if (test_verbose> 0)
+ printf ("info: looking for %.*s, level %d\n",
+ (int) (endp - s), s, level);
+
+ while (idx < nfiles && filesystem[idx].level >= level)
+ {
+ if (filesystem[idx].level == level
+ && memcmp (s, filesystem[idx].name, endp - s) == 0
+ && filesystem[idx].name[endp - s] == '\0')
+ break;
+ ++idx;
+ }
+
+ if (idx == nfiles || filesystem[idx].level < level)
+ {
+ errno = ENOENT;
+ return -1;
+ }
+
+ if (*endp == '\0')
+ return idx + 1;
+
+ if (filesystem[idx].type != DT_DIR
+ && (idx + 1 >= nfiles
+ || filesystem[idx].level >= filesystem[idx + 1].level))
+ {
+ errno = ENOTDIR;
+ return -1;
+ }
+
+ ++idx;
+
+ s = endp + 1;
+ ++level;
+ }
+
+ errno = ENOENT;
+ return -1;
+}
+
+
+static void *
+my_opendir (const char *s)
+{
+ long int idx = find_file (s);
+ my_DIR *dir;
+
+
+ if (idx == -1 || filesystem[idx].type != DT_DIR)
+ {
+ if (test_verbose > 0)
+ printf ("info: my_opendir(\"%s\") == NULL\n", s);
+ return NULL;
+ }
+
+ dir = (my_DIR *) malloc (sizeof (my_DIR));
+ if (dir == NULL)
+ error (EXIT_FAILURE, errno, "cannot allocate directory handle");
+
+ dir->level = filesystem[idx].level;
+ dir->idx = idx;
+
+ if (test_verbose > 0)
+ printf ("info: my_opendir(\"%s\") == { level: %d, idx: %ld }\n",
+ s, filesystem[idx].level, idx);
+
+ return dir;
+}
+
+
+static struct DIRENT_STRUCT *
+my_readdir (void *gdir)
+{
+ my_DIR *dir = gdir;
+
+ if (dir->idx == -1)
+ {
+ if (test_verbose > 0)
+ printf ("info: my_readdir ({ level: %d, idx: %ld }) = NULL\n",
+ dir->level, (long int) dir->idx);
+ return NULL;
+ }
+
+ while (dir->idx < nfiles && filesystem[dir->idx].level > dir->level)
+ ++dir->idx;
+
+ if (dir->idx == nfiles || filesystem[dir->idx].level < dir->level)
+ {
+ dir->idx = -1;
+ if (test_verbose > 0)
+ printf ("info: my_readdir ({ level: %d, idx: %ld }) = NULL\n",
+ dir->level, (long int) dir->idx);
+ return NULL;
+ }
+
+ dir->d.d_ino = 1; /* glob should not skip this entry. */
+
+ dir->d.d_type = filesystem[dir->idx].type;
+
+ strcpy (dir->d.d_name, filesystem[dir->idx].name);
+
+ if (test_verbose > 0)
+ printf ("info: my_readdir ({ level: %d, idx: %ld })"
+ " = { d_ino: %lld, d_type: %d, d_name: \"%s\" }\n",
+ dir->level, (long int) dir->idx,
+ (long long) dir->d.d_ino, dir->d.d_type,
+ dir->d.d_name);
+
+ ++dir->idx;
+
+ return &dir->d;
+}
+
+
+static void
+my_closedir (void *dir)
+{
+ if (test_verbose > 0)
+ printf ("info: my_closedir ()\n");
+ free (dir);
+}
+
+
+/* We use this function for lstat as well since we don't have any. */
+static int
+my_stat (const char *name, struct STAT_STRUCT *st)
+{
+ long int idx = find_file (name);
+
+ if (idx == -1)
+ {
+ if (test_verbose > 0)
+ printf ("info: my_stat (\"%s\", ...) = -1 (%s)\n",
+ name, strerror (errno));
+ return -1;
+ }
+
+ memset (st, '\0', sizeof (*st));
+
+ if (filesystem[idx].type == DT_UNKNOWN)
+ st->st_mode = DTTOIF (idx + 1 < nfiles
+ && filesystem[idx].level < filesystem[idx + 1].level
+ ? DT_DIR : DT_REG) | 0777;
+ else
+ st->st_mode = DTTOIF (filesystem[idx].type) | 0777;
+
+ if (test_verbose > 0)
+ printf ("info: my_stat (\"%s\", { st_mode: %o }) = 0\n", name, st->st_mode);
+
+ return 0;
+}
+
+
+static const char *glob_errstring[] =
+{
+ [GLOB_NOSPACE] = "out of memory",
+ [GLOB_ABORTED] = "read error",
+ [GLOB_NOMATCH] = "no matches found"
+};
+#define nglob_errstring (sizeof (glob_errstring) / sizeof (glob_errstring[0]))
+
+
+static const char *
+flagstr (int flags)
+{
+ static const char *const strs[] =
+ {
+ "GLOB_ERR", "GLOB_MARK", "GLOB_NOSORT", "GLOB_DOOFSS", "GLOB_NOCHECK",
+ "GLOB_APPEND", "GLOB_NOESCAPE", "GLOB_PERIOD", "GLOB_MAGCHAR",
+ "GLOB_ALTDIRFUNC", "GLOB_BRACE", "GLOB_NOMAGIC", "GLOB_TILDE",
+ "GLOB_ONLYDIR", "GLOB_TILDECHECK"
+ };
+#define nstrs (sizeof (strs) / sizeof (strs[0]))
+ static char buf[100];
+ char *cp = buf;
+ int cnt;
+
+ for (cnt = 0; cnt < nstrs; ++cnt)
+ if (flags & (1 << cnt))
+ {
+ flags &= ~(1 << cnt);
+ if (cp != buf)
+ *cp++ = '|';
+ cp = stpcpy (cp, strs[cnt]);
+ }
+
+ if (flags != 0)
+ {
+ if (cp != buf)
+ *cp++ = '|';
+ sprintf (cp, "%#x", flags);
+ }
+
+ return buf;
+#undef nstrs
+}
+
+
+static const char *
+errstr (int val)
+{
+ static const char *const strs[] =
+ {
+ [GLOB_NOSPACE] = "GLOB_NOSPACE",
+ [GLOB_ABORTED] = "GLOB_ABORTED",
+ [GLOB_NOMATCH] = "GLOB_NOMATCH",
+ [GLOB_NOSYS] = "GLOB_NOSYS"
+ };
+#define nstrs (sizeof (strs) / sizeof (strs[0]))
+ static char buf[100];
+ if (val < 0 || val >= nstrs || strs[val] == NULL)
+ {
+ snprintf (buf, sizeof (buf), "GLOB_??? (%d)", val);
+ return buf;
+ }
+ return strs[val];
+#undef nstrs
+}
+
+
+static int
+test_result (const char *fmt, int flags, GLOB_TYPE *gl, const char *str[])
+{
+ size_t cnt;
+ int result = 0;
+
+ printf ("results for glob (\"%s\", %s)\n", fmt, flagstr (flags));
+ for (cnt = 0; cnt < gl->gl_pathc && str[cnt] != NULL; ++cnt)
+ {
+ int ok = strcmp (gl->gl_pathv[cnt], str[cnt]) == 0;
+ const char *errstr = "";
+
+ if (! ok)
+ {
+ size_t inner;
+
+ for (inner = 0; str[inner] != NULL; ++inner)
+ if (strcmp (gl->gl_pathv[cnt], str[inner]) == 0)
+ break;
+
+ if (str[inner] == NULL)
+ errstr = ok ? "" : " *** WRONG";
+ else
+ errstr = ok ? "" : " * wrong position";
+
+ result = 1;
+ }
+
+ printf (" %s%s\n", gl->gl_pathv[cnt], errstr);
+ }
+ puts ("");
+
+ if (str[cnt] != NULL || cnt < gl->gl_pathc)
+ {
+ puts (" *** incorrect number of entries");
+ result = 1;
+ }
+
+ return result;
+}
+
+
+static int
+do_test (void)
+{
+ GLOB_TYPE gl;
+ int errval;
+ int result = 0;
+ const char *fmt;
+ int flags;
+
+ mtrace ();
+
+ memset (&gl, '\0', sizeof (gl));
+
+ gl.gl_closedir = my_closedir;
+ gl.gl_readdir = my_readdir;
+ gl.gl_opendir = my_opendir;
+ gl.gl_lstat = my_stat;
+ gl.gl_stat = my_stat;
+
+#define test(a, b, r, c...) \
+ fmt = a; \
+ flags = GLOB_ALTDIRFUNC | b; \
+ errval = GLOB_FUNC (fmt, flags, NULL, &gl); \
+ if (errval != r) \
+ { \
+ if (r == 0) \
+ printf ("glob (\"%s\", %s) failed: %s\n", fmt, flagstr (flags), \
+ errval >= 0 && errval < nglob_errstring \
+ ? glob_errstring[errval] : "???"); \
+ else \
+ printf ("glob (\"%s\", %s) did not fail\n", fmt, flagstr (flags)); \
+ result = 1; \
+ } \
+ else if (r == 0) \
+ result |= test_result (fmt, flags, &gl, (const char *[]) { c, NULL }); \
+ else \
+ printf ("result for glob (\"%s\", %s) = %s\n\n", fmt, flagstr (flags), \
+ errstr (errval))
+
+ test ("*/*/*", 0, 0,
+ "dir1lev1/dir2lev2/dir1lev3",
+ "dir1lev1/dir2lev2/file1lev3",
+ "dir1lev1/dir2lev2/file2lev3",
+ "dir1lev1/dir3lev2/file3lev3",
+ "dir1lev1/dir3lev2/file4lev3");
+
+ test ("*/*/*", GLOB_PERIOD, 0,
+ "dir1lev1/dir1lev2/.",
+ "dir1lev1/dir1lev2/..",
+ "dir1lev1/dir2lev2/.",
+ "dir1lev1/dir2lev2/..",
+ "dir1lev1/dir2lev2/.foo",
+ "dir1lev1/dir2lev2/dir1lev3",
+ "dir1lev1/dir2lev2/file1lev3",
+ "dir1lev1/dir2lev2/file2lev3",
+ "dir1lev1/dir3lev2/.",
+ "dir1lev1/dir3lev2/..",
+ "dir1lev1/dir3lev2/file3lev3",
+ "dir1lev1/dir3lev2/file4lev3",
+ "dir2lev1/dir1lev2/.",
+ "dir2lev1/dir1lev2/..",
+ "dir2lev1/dir1lev2/.dir",
+ "dir2lev1/dir1lev2/.foo");
+
+ test ("*/*/.*", 0, 0,
+ "dir1lev1/dir1lev2/.",
+ "dir1lev1/dir1lev2/..",
+ "dir1lev1/dir2lev2/.",
+ "dir1lev1/dir2lev2/..",
+ "dir1lev1/dir2lev2/.foo",
+ "dir1lev1/dir3lev2/.",
+ "dir1lev1/dir3lev2/..",
+ "dir2lev1/dir1lev2/.",
+ "dir2lev1/dir1lev2/..",
+ "dir2lev1/dir1lev2/.dir",
+ "dir2lev1/dir1lev2/.foo");
+
+ test ("*1*/*2*/.*", 0, 0,
+ "dir1lev1/dir1lev2/.",
+ "dir1lev1/dir1lev2/..",
+ "dir1lev1/dir2lev2/.",
+ "dir1lev1/dir2lev2/..",
+ "dir1lev1/dir2lev2/.foo",
+ "dir1lev1/dir3lev2/.",
+ "dir1lev1/dir3lev2/..",
+ "dir2lev1/dir1lev2/.",
+ "dir2lev1/dir1lev2/..",
+ "dir2lev1/dir1lev2/.dir",
+ "dir2lev1/dir1lev2/.foo");
+
+ test ("*1*/*1*/.*", 0, 0,
+ "dir1lev1/dir1lev2/.",
+ "dir1lev1/dir1lev2/..",
+ "dir2lev1/dir1lev2/.",
+ "dir2lev1/dir1lev2/..",
+ "dir2lev1/dir1lev2/.dir",
+ "dir2lev1/dir1lev2/.foo");
+
+ test ("\\/*", 0, 0,
+ "/dir1lev1",
+ "/dir2lev1",
+ "/file1lev1",
+ "/file2lev1");
+
+ test ("*/*/", 0 , 0,
+ "dir1lev1/dir1lev2/",
+ "dir1lev1/dir2lev2/",
+ "dir1lev1/dir3lev2/",
+ "dir2lev1/dir1lev2/");
+
+ test ("", 0, GLOB_NOMATCH, NULL);
+
+ test ("", GLOB_NOCHECK, 0, "");
+
+ GLOBFREE_FUNC (&gl);
+
+ return result;
+}
+
+#include <support/test-driver.c>
diff --git a/posix/tst-gnuglob.c b/posix/tst-gnuglob.c
index 992b997db9..a02aa8990c 100644
--- a/posix/tst-gnuglob.c
+++ b/posix/tst-gnuglob.c
@@ -1,8 +1,6 @@
-/* Test the GNU extensions in glob which allow the user to provide callbacks
- for the filesystem access functions.
- Copyright (C) 2001-2016 Free Software Foundation, Inc.
+/* Test glob with GLOB_ALTDIRFUNC.
+ Copyright (C) 2017-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
- Contributed by Ulrich Drepper <drepper@redhat.com>, 2001.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -18,485 +16,10 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
-#include <dirent.h>
-#include <errno.h>
-#include <error.h>
-#include <glob.h>
-#include <mcheck.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/stat.h>
+#define GLOB_FUNC glob
+#define GLOB_TYPE glob_t
+#define GLOBFREE_FUNC globfree
+#define DIRENT_STRUCT dirent
+#define STAT_STRUCT stat
-
-// #define DEBUG
-#ifdef DEBUG
-# define PRINTF(fmt, args...) printf (fmt, ##args)
-#else
-# define PRINTF(fmt, args...)
-#endif
-
-
-static struct
-{
- const char *name;
- int level;
- int type;
-} filesystem[] =
-{
- { ".", 1, DT_DIR },
- { "..", 1, DT_DIR },
- { "file1lev1", 1, DT_REG },
- { "file2lev1", 1, DT_UNKNOWN },
- { "dir1lev1", 1, DT_UNKNOWN },
- { ".", 2, DT_DIR },
- { "..", 2, DT_DIR },
- { "file1lev2", 2, DT_REG },
- { "dir1lev2", 2, DT_DIR },
- { ".", 3, DT_DIR },
- { "..", 3, DT_DIR },
- { "dir2lev2", 2, DT_DIR },
- { ".", 3, DT_DIR },
- { "..", 3, DT_DIR },
- { ".foo", 3, DT_REG },
- { "dir1lev3", 3, DT_DIR },
- { ".", 4, DT_DIR },
- { "..", 4, DT_DIR },
- { "file1lev4", 4, DT_REG },
- { "file1lev3", 3, DT_REG },
- { "file2lev3", 3, DT_REG },
- { "file2lev2", 2, DT_REG },
- { "file3lev2", 2, DT_REG },
- { "dir3lev2", 2, DT_DIR },
- { ".", 3, DT_DIR },
- { "..", 3, DT_DIR },
- { "file3lev3", 3, DT_REG },
- { "file4lev3", 3, DT_REG },
- { "dir2lev1", 1, DT_DIR },
- { ".", 2, DT_DIR },
- { "..", 2, DT_DIR },
- { "dir1lev2", 2, DT_UNKNOWN },
- { ".", 3, DT_DIR },
- { "..", 3, DT_DIR },
- { ".foo", 3, DT_REG },
- { ".dir", 3, DT_DIR },
- { ".", 4, DT_DIR },
- { "..", 4, DT_DIR },
- { "hidden", 4, DT_REG }
-};
-#define nfiles (sizeof (filesystem) / sizeof (filesystem[0]))
-
-
-typedef struct
-{
- int level;
- int idx;
- struct dirent d;
- char room_for_dirent[NAME_MAX];
-} my_DIR;
-
-
-static long int
-find_file (const char *s)
-{
- int level = 1;
- long int idx = 0;
-
- while (s[0] == '/')
- {
- if (s[1] == '\0')
- {
- s = ".";
- break;
- }
- ++s;
- }
-
- if (strcmp (s, ".") == 0)
- return 0;
-
- if (s[0] == '.' && s[1] == '/')
- s += 2;
-
- while (*s != '\0')
- {
- char *endp = strchrnul (s, '/');
-
- PRINTF ("looking for %.*s, level %d\n", (int) (endp - s), s, level);
-
- while (idx < nfiles && filesystem[idx].level >= level)
- {
- if (filesystem[idx].level == level
- && memcmp (s, filesystem[idx].name, endp - s) == 0
- && filesystem[idx].name[endp - s] == '\0')
- break;
- ++idx;
- }
-
- if (idx == nfiles || filesystem[idx].level < level)
- {
- errno = ENOENT;
- return -1;
- }
-
- if (*endp == '\0')
- return idx + 1;
-
- if (filesystem[idx].type != DT_DIR
- && (idx + 1 >= nfiles
- || filesystem[idx].level >= filesystem[idx + 1].level))
- {
- errno = ENOTDIR;
- return -1;
- }
-
- ++idx;
-
- s = endp + 1;
- ++level;
- }
-
- errno = ENOENT;
- return -1;
-}
-
-
-static void *
-my_opendir (const char *s)
-{
- long int idx = find_file (s);
- my_DIR *dir;
-
-
- if (idx == -1 || filesystem[idx].type != DT_DIR)
- {
- PRINTF ("my_opendir(\"%s\") == NULL\n", s);
- return NULL;
- }
-
- dir = (my_DIR *) malloc (sizeof (my_DIR));
- if (dir == NULL)
- error (EXIT_FAILURE, errno, "cannot allocate directory handle");
-
- dir->level = filesystem[idx].level;
- dir->idx = idx;
-
- PRINTF ("my_opendir(\"%s\") == { level: %d, idx: %ld }\n",
- s, filesystem[idx].level, idx);
-
- return dir;
-}
-
-
-static struct dirent *
-my_readdir (void *gdir)
-{
- my_DIR *dir = gdir;
-
- if (dir->idx == -1)
- {
- PRINTF ("my_readdir ({ level: %d, idx: %ld }) = NULL\n",
- dir->level, (long int) dir->idx);
- return NULL;
- }
-
- while (dir->idx < nfiles && filesystem[dir->idx].level > dir->level)
- ++dir->idx;
-
- if (dir->idx == nfiles || filesystem[dir->idx].level < dir->level)
- {
- dir->idx = -1;
- PRINTF ("my_readdir ({ level: %d, idx: %ld }) = NULL\n",
- dir->level, (long int) dir->idx);
- return NULL;
- }
-
- dir->d.d_ino = dir->idx;
-
-#ifdef _DIRENT_HAVE_D_TYPE
- dir->d.d_type = filesystem[dir->idx].type;
-#endif
-
- strcpy (dir->d.d_name, filesystem[dir->idx].name);
-
-#ifdef _DIRENT_HAVE_D_TYPE
- PRINTF ("my_readdir ({ level: %d, idx: %ld }) = { d_ino: %ld, d_type: %d, d_name: \"%s\" }\n",
- dir->level, (long int) dir->idx, dir->d.d_ino, dir->d.d_type,
- dir->d.d_name);
-#else
- PRINTF ("my_readdir ({ level: %d, idx: %ld }) = { d_ino: %ld, d_name: \"%s\" }\n",
- dir->level, (long int) dir->idx, dir->d.d_ino,
- dir->d.d_name);
-#endif
-
- ++dir->idx;
-
- return &dir->d;
-}
-
-
-static void
-my_closedir (void *dir)
-{
- PRINTF ("my_closedir ()\n");
- free (dir);
-}
-
-
-/* We use this function for lstat as well since we don't have any. */
-static int
-my_stat (const char *name, struct stat *st)
-{
- long int idx = find_file (name);
-
- if (idx == -1)
- {
- PRINTF ("my_stat (\"%s\", ...) = -1 (%s)\n", name, strerror (errno));
- return -1;
- }
-
- memset (st, '\0', sizeof (*st));
-
- if (filesystem[idx].type == DT_UNKNOWN)
- st->st_mode = DTTOIF (idx + 1 < nfiles
- && filesystem[idx].level < filesystem[idx + 1].level
- ? DT_DIR : DT_REG) | 0777;
- else
- st->st_mode = DTTOIF (filesystem[idx].type) | 0777;
-
- PRINTF ("my_stat (\"%s\", { st_mode: %o }) = 0\n", name, st->st_mode);
-
- return 0;
-}
-
-
-static const char *glob_errstring[] =
-{
- [GLOB_NOSPACE] = "out of memory",
- [GLOB_ABORTED] = "read error",
- [GLOB_NOMATCH] = "no matches found"
-};
-#define nglob_errstring (sizeof (glob_errstring) / sizeof (glob_errstring[0]))
-
-
-static const char *
-flagstr (int flags)
-{
- static const char *const strs[] =
- {
- "GLOB_ERR", "GLOB_MARK", "GLOB_NOSORT", "GLOB_DOOFSS", "GLOB_NOCHECK",
- "GLOB_APPEND", "GLOB_NOESCAPE", "GLOB_PERIOD", "GLOB_MAGCHAR",
- "GLOB_ALTDIRFUNC", "GLOB_BRACE", "GLOB_NOMAGIC", "GLOB_TILDE",
- "GLOB_ONLYDIR", "GLOB_TILDECHECK"
- };
-#define nstrs (sizeof (strs) / sizeof (strs[0]))
- static char buf[100];
- char *cp = buf;
- int cnt;
-
- for (cnt = 0; cnt < nstrs; ++cnt)
- if (flags & (1 << cnt))
- {
- flags &= ~(1 << cnt);
- if (cp != buf)
- *cp++ = '|';
- cp = stpcpy (cp, strs[cnt]);
- }
-
- if (flags != 0)
- {
- if (cp != buf)
- *cp++ = '|';
- sprintf (cp, "%#x", flags);
- }
-
- return buf;
-#undef nstrs
-}
-
-
-static const char *
-errstr (int val)
-{
- static const char *const strs[] =
- {
- [GLOB_NOSPACE] = "GLOB_NOSPACE",
- [GLOB_ABORTED] = "GLOB_ABORTED",
- [GLOB_NOMATCH] = "GLOB_NOMATCH",
- [GLOB_NOSYS] = "GLOB_NOSYS"
- };
-#define nstrs (sizeof (strs) / sizeof (strs[0]))
- static char buf[100];
- if (val < 0 || val >= nstrs || strs[val] == NULL)
- {
- snprintf (buf, sizeof (buf), "GLOB_??? (%d)", val);
- return buf;
- }
- return strs[val];
-#undef nstrs
-}
-
-
-static int
-test_result (const char *fmt, int flags, glob_t *gl, const char *str[])
-{
- size_t cnt;
- int result = 0;
-
- printf ("results for glob (\"%s\", %s)\n", fmt, flagstr (flags));
- for (cnt = 0; cnt < gl->gl_pathc && str[cnt] != NULL; ++cnt)
- {
- int ok = strcmp (gl->gl_pathv[cnt], str[cnt]) == 0;
- const char *errstr = "";
-
- if (! ok)
- {
- size_t inner;
-
- for (inner = 0; str[inner] != NULL; ++inner)
- if (strcmp (gl->gl_pathv[cnt], str[inner]) == 0)
- break;
-
- if (str[inner] == NULL)
- errstr = ok ? "" : " *** WRONG";
- else
- errstr = ok ? "" : " * wrong position";
-
- result = 1;
- }
-
- printf (" %s%s\n", gl->gl_pathv[cnt], errstr);
- }
- puts ("");
-
- if (str[cnt] != NULL || cnt < gl->gl_pathc)
- {
- puts (" *** incorrect number of entries");
- result = 1;
- }
-
- return result;
-}
-
-
-static int
-do_test (void)
-{
- glob_t gl;
- int errval;
- int result = 0;
- const char *fmt;
- int flags;
-
- mtrace ();
-
- memset (&gl, '\0', sizeof (gl));
-
- gl.gl_closedir = my_closedir;
- gl.gl_readdir = my_readdir;
- gl.gl_opendir = my_opendir;
- gl.gl_lstat = my_stat;
- gl.gl_stat = my_stat;
-
-#define test(a, b, r, c...) \
- fmt = a; \
- flags = GLOB_ALTDIRFUNC | b; \
- errval = glob (fmt, flags, NULL, &gl); \
- if (errval != r) \
- { \
- if (r == 0) \
- printf ("glob (\"%s\", %s) failed: %s\n", fmt, flagstr (flags), \
- errval >= 0 && errval < nglob_errstring \
- ? glob_errstring[errval] : "???"); \
- else \
- printf ("glob (\"%s\", %s) did not fail\n", fmt, flagstr (flags)); \
- result = 1; \
- } \
- else if (r == 0) \
- result |= test_result (fmt, flags, &gl, (const char *[]) { c, NULL }); \
- else \
- printf ("result for glob (\"%s\", %s) = %s\n\n", fmt, flagstr (flags), \
- errstr (errval))
-
- test ("*/*/*", 0, 0,
- "dir1lev1/dir2lev2/dir1lev3",
- "dir1lev1/dir2lev2/file1lev3",
- "dir1lev1/dir2lev2/file2lev3",
- "dir1lev1/dir3lev2/file3lev3",
- "dir1lev1/dir3lev2/file4lev3");
-
- test ("*/*/*", GLOB_PERIOD, 0,
- "dir1lev1/dir1lev2/.",
- "dir1lev1/dir1lev2/..",
- "dir1lev1/dir2lev2/.",
- "dir1lev1/dir2lev2/..",
- "dir1lev1/dir2lev2/.foo",
- "dir1lev1/dir2lev2/dir1lev3",
- "dir1lev1/dir2lev2/file1lev3",
- "dir1lev1/dir2lev2/file2lev3",
- "dir1lev1/dir3lev2/.",
- "dir1lev1/dir3lev2/..",
- "dir1lev1/dir3lev2/file3lev3",
- "dir1lev1/dir3lev2/file4lev3",
- "dir2lev1/dir1lev2/.",
- "dir2lev1/dir1lev2/..",
- "dir2lev1/dir1lev2/.dir",
- "dir2lev1/dir1lev2/.foo");
-
- test ("*/*/.*", 0, 0,
- "dir1lev1/dir1lev2/.",
- "dir1lev1/dir1lev2/..",
- "dir1lev1/dir2lev2/.",
- "dir1lev1/dir2lev2/..",
- "dir1lev1/dir2lev2/.foo",
- "dir1lev1/dir3lev2/.",
- "dir1lev1/dir3lev2/..",
- "dir2lev1/dir1lev2/.",
- "dir2lev1/dir1lev2/..",
- "dir2lev1/dir1lev2/.dir",
- "dir2lev1/dir1lev2/.foo");
-
- test ("*1*/*2*/.*", 0, 0,
- "dir1lev1/dir1lev2/.",
- "dir1lev1/dir1lev2/..",
- "dir1lev1/dir2lev2/.",
- "dir1lev1/dir2lev2/..",
- "dir1lev1/dir2lev2/.foo",
- "dir1lev1/dir3lev2/.",
- "dir1lev1/dir3lev2/..",
- "dir2lev1/dir1lev2/.",
- "dir2lev1/dir1lev2/..",
- "dir2lev1/dir1lev2/.dir",
- "dir2lev1/dir1lev2/.foo");
-
- test ("*1*/*1*/.*", 0, 0,
- "dir1lev1/dir1lev2/.",
- "dir1lev1/dir1lev2/..",
- "dir2lev1/dir1lev2/.",
- "dir2lev1/dir1lev2/..",
- "dir2lev1/dir1lev2/.dir",
- "dir2lev1/dir1lev2/.foo");
-
- test ("\\/*", 0, 0,
- "/dir1lev1",
- "/dir2lev1",
- "/file1lev1",
- "/file2lev1");
-
- test ("*/*/", 0 , 0,
- "dir1lev1/dir1lev2/",
- "dir1lev1/dir2lev2/",
- "dir1lev1/dir3lev2/",
- "dir2lev1/dir1lev2/");
-
- test ("", 0, GLOB_NOMATCH, NULL);
-
- test ("", GLOB_NOCHECK, 0, "");
-
- globfree (&gl);
-
- return result;
-}
-
-#define TEST_FUNCTION do_test ()
-#include "../test-skeleton.c"
+#include "tst-gnuglob-skeleton.c"
diff --git a/posix/tst-gnuglob64.c b/posix/tst-gnuglob64.c
new file mode 100644
index 0000000000..2d6f1ecc06
--- /dev/null
+++ b/posix/tst-gnuglob64.c
@@ -0,0 +1,25 @@
+/* Test glob64 with GLOB_ALTDIRFUNC.
+ Copyright (C) 2017-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#define GLOB_FUNC glob64
+#define GLOB_TYPE glob64_t
+#define GLOBFREE_FUNC globfree64
+#define DIRENT_STRUCT dirent64
+#define STAT_STRUCT stat64
+
+#include "tst-gnuglob-skeleton.c"
diff --git a/posix/tst-mmap-offset.c b/posix/tst-mmap-offset.c
index 53e78559c2..92ea794c5a 100644
--- a/posix/tst-mmap-offset.c
+++ b/posix/tst-mmap-offset.c
@@ -1,6 +1,6 @@
-/* BZ #18877 mmap offset test.
+/* BZ #18877 and #21270 mmap offset test.
- Copyright (C) 2015-2016 Free Software Foundation, Inc.
+ Copyright (C) 2015-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -17,22 +17,42 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
+#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+#include <errno.h>
#include <sys/mman.h>
-static int
-printmsg (int rc, const char *msg)
+#include <support/check.h>
+
+static int fd;
+static long int page_shift;
+static char fname[] = "/tmp/tst-mmap-offset-XXXXXX";
+
+static void
+do_prepare (int argc, char **argv)
{
- printf ("%s failed: %m\n", msg);
- return rc;
+ fd = mkstemp64 (fname);
+ if (fd < 0)
+ FAIL_EXIT1 ("mkstemp failed");
+
+ if (unlink (fname))
+ FAIL_EXIT1 ("unlink failed");
+
+ long sz = sysconf(_SC_PAGESIZE);
+ if (sz == -1)
+ sz = 4096L;
+ page_shift = ffs (sz) - 1;
}
+#define PREPARE do_prepare
+
+
/* Check if negative offsets are handled correctly by mmap. */
static int
-do_test (void)
+do_test_bz18877 (void)
{
const int prot = PROT_READ | PROT_WRITE;
const int flags = MAP_SHARED;
@@ -40,22 +60,13 @@ do_test (void)
const unsigned long offset = 0xace00000;
const unsigned long size = offset + length;
void *addr;
- int fd;
- char fname[] = "tst-mmap-offset-XXXXXX";
-
- fd = mkstemp64 (fname);
- if (fd < 0)
- return printmsg (1, "mkstemp");
-
- if (unlink (fname))
- return printmsg (1, "unlink");
if (ftruncate64 (fd, size))
- return printmsg (0, "ftruncate64");
+ FAIL_RET ("ftruncate64 failed");
addr = mmap (NULL, length, prot, flags, fd, offset);
if (MAP_FAILED == addr)
- return printmsg (1, "mmap");
+ FAIL_RET ("mmap failed");
/* This memcpy is likely to SIGBUS if mmap has messed up with offset. */
memcpy (addr, fname, sizeof (fname));
@@ -63,5 +74,45 @@ do_test (void)
return 0;
}
-#define TEST_FUNCTION do_test ()
-#include "../test-skeleton.c"
+/* Check if invalid offset are handled correctly by mmap. */
+static int
+do_test_bz21270 (void)
+{
+ /* For architectures with sizeof (off_t) < sizeof (off64_t) mmap is
+ implemented with __SYS_mmap2 syscall and the offset is represented in
+ multiples of page size. For offset larger than
+ '1 << (page_shift + 8 * sizeof (off_t))' (that is, 1<<44 on system with
+ page size of 4096 bytes) the system call silently truncates the offset.
+ For this case glibc mmap implementation returns EINVAL. */
+ const int prot = PROT_READ | PROT_WRITE;
+ const int flags = MAP_SHARED;
+ const int64_t offset = 1ULL << (page_shift + 8 * sizeof (uint32_t));
+ const size_t length = 4096;
+
+ void *addr = mmap64 (NULL, length, prot, flags, fd, offset);
+ if (sizeof (off_t) < sizeof (off64_t))
+ {
+ if ((addr != MAP_FAILED) && (errno != EINVAL))
+ FAIL_RET ("mmap succeed");
+ }
+ else
+ {
+ if (addr == MAP_FAILED)
+ FAIL_RET ("mmap failed");
+ }
+
+ return 0;
+}
+
+int
+do_test (void)
+{
+ int ret = 0;
+
+ ret += do_test_bz18877 ();
+ ret += do_test_bz21270 ();
+
+ return ret;
+}
+
+#include <support/test-driver.c>
diff --git a/posix/tst-nanosleep.c b/posix/tst-nanosleep.c
index bf118ed208..a7d6a01826 100644
--- a/posix/tst-nanosleep.c
+++ b/posix/tst-nanosleep.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2003-2016 Free Software Foundation, Inc.
+/* Copyright (C) 2003-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/posix/tst-nice.c b/posix/tst-nice.c
index b6aca42753..624843340b 100644
--- a/posix/tst-nice.c
+++ b/posix/tst-nice.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2003-2016 Free Software Foundation, Inc.
+/* Copyright (C) 2003-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/posix/tst-pathconf.c b/posix/tst-pathconf.c
index 949fc65428..26650f2517 100644
--- a/posix/tst-pathconf.c
+++ b/posix/tst-pathconf.c
@@ -1,5 +1,5 @@
/* Test that values of pathconf and fpathconf are consistent for a file.
- Copyright (C) 2013-2016 Free Software Foundation, Inc.
+ Copyright (C) 2013-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -21,6 +21,7 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+#include <sys/stat.h>
static void prepare (void);
@@ -41,12 +42,7 @@ prepare (void)
static const char dir_name[] = "/tst-pathconf.XXXXXX";
size_t dirbuflen = test_dir_len + sizeof (dir_name);
- dirbuf = malloc (dirbuflen);
- if (dirbuf == NULL)
- {
- puts ("Out of memory");
- exit (1);
- }
+ dirbuf = xmalloc (dirbuflen);
snprintf (dirbuf, dirbuflen, "%s%s", test_dir, dir_name);
if (mkdtemp (dirbuf) == NULL)
@@ -73,7 +69,7 @@ do_test (void)
static const char *fifo_name = "some-fifo";
size_t filenamelen = strlen (dirbuf) + strlen (fifo_name) + 2;
- char *filename = malloc (filenamelen);
+ char *filename = xmalloc (filenamelen);
snprintf (filename, filenamelen, "%s/%s", dirbuf, fifo_name);
@@ -166,11 +162,5 @@ out_nofifo:
ret = 1;
}
- if (rmdir (dirbuf) != 0)
- {
- printf ("Could not remove directory (%s)\n", strerror (errno));
- ret = 1;
- }
-
return ret;
}
diff --git a/posix/tst-pcre.c b/posix/tst-pcre.c
index 20788ca919..b6fe495a69 100644
--- a/posix/tst-pcre.c
+++ b/posix/tst-pcre.c
@@ -1,5 +1,5 @@
/* Regular expression tests.
- Copyright (C) 2003-2016 Free Software Foundation, Inc.
+ Copyright (C) 2003-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Jakub Jelinek <jakub@redhat.com>, 2003.
diff --git a/posix/tst-posix_fadvise-common.c b/posix/tst-posix_fadvise-common.c
new file mode 100644
index 0000000000..d42dde4846
--- /dev/null
+++ b/posix/tst-posix_fadvise-common.c
@@ -0,0 +1,111 @@
+/* Common posix_fadvise tests definitions.
+ Copyright (C) 2016-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <support/support.h>
+#include <support/check.h>
+#include <support/temp_file.h>
+
+static char *temp_filename;
+static int temp_fd;
+static char fifoname[] = "/tmp/tst-posix_fadvise-fifo-XXXXXX";
+static int fifofd;
+
+static void
+do_prepare (int argc, char **argv)
+{
+ temp_fd = create_temp_file ("tst-posix_fadvise.", &temp_filename);
+ if (temp_fd == -1)
+ FAIL_EXIT1 ("cannot create temporary file: %m");
+
+ if (mktemp (fifoname) == NULL)
+ FAIL_EXIT1 ("cannot generate temp file name: %m");
+ add_temp_file (fifoname);
+
+ if (mkfifo (fifoname, S_IWUSR | S_IRUSR) != 0)
+ FAIL_EXIT1 ("cannot create fifo: %m");
+
+ fifofd = open (fifoname, O_RDONLY | O_NONBLOCK);
+ if (fifofd == -1)
+ FAIL_EXIT1 ("cannot open fifo: %m");
+}
+
+/* Effectivelly testing posix_fadvise is hard because side effects are not
+ observed without checking either performance or any kernel specific
+ supplied information. Also, the syscall is meant to be an advisory,
+ so the kernel is free to use this information in any way it deems fit,
+ including ignoring it.
+
+ This test check for some invalid returned operation to check argument
+ passing and if implementation follows POSIX error definition. */
+static int
+do_test_common (void)
+{
+ /* Add some data to file and ensure it is written to disk. */
+#define BLK_SIZE 2048
+ char buffer[BLK_SIZE] = { 0xcd };
+ ssize_t ret;
+
+ if ((ret = write (temp_fd, buffer, BLK_SIZE)) != BLK_SIZE)
+ FAIL_EXIT1 ("write returned %zd different than expected %d",
+ ret, BLK_SIZE);
+
+ if (fsync (temp_fd) != 0)
+ FAIL_EXIT1 ("fsync failed");
+
+ /* Test passing an invalid fd. */
+ if (posix_fadvise (-1, 0, 0, POSIX_FADV_NORMAL) != EBADF)
+ FAIL_EXIT1 ("posix_fadvise with invalid fd did not return EBADF");
+
+ /* Test passing an invalid operation. */
+ if (posix_fadvise (temp_fd, 0, 0, -1) != EINVAL)
+ FAIL_EXIT1 ("posix_fadvise with invalid advise did not return EINVAL");
+
+ /* Test passing a FIFO fd. */
+ if (posix_fadvise (fifofd, 0, 0, POSIX_FADV_NORMAL) != ESPIPE)
+ FAIL_EXIT1 ("posix_advise with PIPE fd did not return ESPIPE");
+
+ /* Default fadvise on all file starting at initial position. */
+ if (posix_fadvise (temp_fd, 0, 0, POSIX_FADV_NORMAL) != 0)
+ FAIL_EXIT1 ("default posix_fadvise failed");
+
+ if (posix_fadvise (temp_fd, 0, 2 * BLK_SIZE, POSIX_FADV_NORMAL) != 0)
+ FAIL_EXIT1 ("posix_fadvise failed (offset = 0, len = %d) failed",
+ BLK_SIZE);
+
+ if (posix_fadvise (temp_fd, 2 * BLK_SIZE, 0, POSIX_FADV_NORMAL) != 0)
+ FAIL_EXIT1 ("posix_fadvise failed (offset = %d, len = 0) failed",
+ BLK_SIZE);
+
+ return 0;
+}
+
+#define PREPARE do_prepare
+
+/* This function is defined by the individual tests. */
+static int do_test (void);
+
+#include <support/test-driver.c>
diff --git a/posix/tst-posix_fadvise.c b/posix/tst-posix_fadvise.c
new file mode 100644
index 0000000000..1b9f4b0bf1
--- /dev/null
+++ b/posix/tst-posix_fadvise.c
@@ -0,0 +1,25 @@
+/* Basic posix_fadvise tests.
+ Copyright (C) 2016-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include "tst-posix_fadvise-common.c"
+
+static int
+do_test (void)
+{
+ return do_test_common ();
+}
diff --git a/posix/tst-posix_fadvise64.c b/posix/tst-posix_fadvise64.c
new file mode 100644
index 0000000000..82fbaed23e
--- /dev/null
+++ b/posix/tst-posix_fadvise64.c
@@ -0,0 +1,46 @@
+/* Basic posix_fadvise64 tests.
+ Copyright (C) 2016-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#define _FILE_OFFSET_BITS 64
+#include "tst-posix_fadvise-common.c"
+
+static int
+do_test (void)
+{
+ int ret = do_test_common ();
+ if (ret == 1)
+ return 1;
+
+ /* Test passing a negative length. The compat fadvise64 might use
+ off64_t for size argument passing, so using -1 for len without
+ _FILE_OFFSET_BITS might not trigger the length issue. */
+ if (posix_fadvise (temp_fd, 0, -1, POSIX_FADV_NORMAL) != EINVAL)
+ FAIL_EXIT1 ("posix_fadvise with negative length did not return EINVAL");
+
+ /* Check with some offset values larger than 32-bits. */
+ off_t offset = UINT32_MAX + 2048LL;
+ if (posix_fadvise (temp_fd, 0, offset, POSIX_FADV_NORMAL) != 0)
+ FAIL_EXIT1 ("posix_fadvise failed (offset = 0, len = %zd) failed",
+ (ssize_t)offset);
+
+ if (posix_fadvise (temp_fd, offset, 0, POSIX_FADV_NORMAL) != 0)
+ FAIL_EXIT1 ("posix_fadvise failed (offset = %zd, len = 0) failed",
+ (ssize_t)offset);
+
+ return 0;
+}
diff --git a/posix/tst-posix_spawn-fd.c b/posix/tst-posix_spawn-fd.c
new file mode 100644
index 0000000000..ca9acc30a2
--- /dev/null
+++ b/posix/tst-posix_spawn-fd.c
@@ -0,0 +1,165 @@
+/* Test that spawn file action functions work without file limit.
+ Copyright (C) 2016-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <spawn.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <sys/resource.h>
+#include <unistd.h>
+
+/* _SC_OPEN_MAX value. */
+static long maxfd;
+
+/* A positive but unused file descriptor, used for testing
+ purposes. */
+static int invalid_fd;
+
+/* Indicate that errors have been encountered. */
+static bool errors;
+
+static posix_spawn_file_actions_t actions;
+
+static void
+one_test (const char *name, int (*func) (int), int fd,
+ bool expect_success)
+{
+ int ret = func (fd);
+ if (expect_success)
+ {
+ if (ret != 0)
+ {
+ errno = ret;
+ printf ("error: posix_spawn_file_actions_%s (%d): %m\n", name, fd);
+ errors = true;
+ }
+ }
+ else if (ret != EBADF)
+ {
+ if (ret == 0)
+ printf ("error: posix_spawn_file_actions_%s (%d):"
+ " unexpected success\n", name, fd);
+ else
+ {
+ errno = ret;
+ printf ("error: posix_spawn_file_actions_%s (%d): %m\n", name, fd);
+ }
+ errors = true;
+ }
+}
+
+static void
+all_tests (const char *name, int (*func) (int))
+{
+ one_test (name, func, 0, true);
+ one_test (name, func, invalid_fd, true);
+ one_test (name, func, -1, false);
+ one_test (name, func, -2, false);
+ if (maxfd >= 0)
+ one_test (name, func, maxfd, false);
+}
+
+static int
+addopen (int fd)
+{
+ return posix_spawn_file_actions_addopen
+ (&actions, fd, "/dev/null", O_RDONLY, 0);
+}
+
+static int
+adddup2 (int fd)
+{
+ return posix_spawn_file_actions_adddup2 (&actions, fd, 1);
+}
+
+static int
+adddup2_reverse (int fd)
+{
+ return posix_spawn_file_actions_adddup2 (&actions, 1, fd);
+}
+
+static int
+addclose (int fd)
+{
+ return posix_spawn_file_actions_addclose (&actions, fd);
+}
+
+static void
+all_functions (void)
+{
+ all_tests ("addopen", addopen);
+ all_tests ("adddup2", adddup2);
+ all_tests ("adddup2", adddup2_reverse);
+ all_tests ("adddup2", addclose);
+}
+
+static int
+do_test (void)
+{
+ /* Try to eliminate the file descriptor limit. */
+ {
+ struct rlimit limit;
+ if (getrlimit (RLIMIT_NOFILE, &limit) < 0)
+ {
+ printf ("error: getrlimit: %m\n");
+ return 1;
+ }
+ limit.rlim_cur = RLIM_INFINITY;
+ if (setrlimit (RLIMIT_NOFILE, &limit) < 0)
+ printf ("warning: setrlimit: %m\n");
+ }
+
+ maxfd = sysconf (_SC_OPEN_MAX);
+ printf ("info: _SC_OPEN_MAX: %ld\n", maxfd);
+
+ invalid_fd = dup (0);
+ if (invalid_fd < 0)
+ {
+ printf ("error: dup: %m\n");
+ return 1;
+ }
+ if (close (invalid_fd) < 0)
+ {
+ printf ("error: close: %m\n");
+ return 1;
+ }
+
+ int ret = posix_spawn_file_actions_init (&actions);
+ if (ret != 0)
+ {
+ errno = ret;
+ printf ("error: posix_spawn_file_actions_init: %m\n");
+ return 1;
+ }
+
+ all_functions ();
+
+ ret = posix_spawn_file_actions_destroy (&actions);
+ if (ret != 0)
+ {
+ errno = ret;
+ printf ("error: posix_spawn_file_actions_destroy: %m\n");
+ return 1;
+ }
+
+ return errors;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/posix/tst-posix_spawn-setsid.c b/posix/tst-posix_spawn-setsid.c
new file mode 100644
index 0000000000..17de482a69
--- /dev/null
+++ b/posix/tst-posix_spawn-setsid.c
@@ -0,0 +1,95 @@
+/* Test posix_spawn setsid attribute.
+ Copyright (C) 2017-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <spawn.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <sys/resource.h>
+#include <unistd.h>
+
+#include <support/check.h>
+
+static void
+do_test_setsid (bool test_setsid)
+{
+ pid_t sid, child_sid;
+ int res;
+
+ /* Current session ID. */
+ sid = getsid(0);
+ if (sid == (pid_t) -1)
+ FAIL_EXIT1 ("getsid (0): %m");
+
+ posix_spawnattr_t attrp;
+ /* posix_spawnattr_init should not fail (it basically memset the
+ attribute). */
+ posix_spawnattr_init (&attrp);
+ if (test_setsid)
+ {
+ res = posix_spawnattr_setflags (&attrp, POSIX_SPAWN_SETSID);
+ if (res != 0)
+ {
+ errno = res;
+ FAIL_EXIT1 ("posix_spawnattr_setflags: %m");
+ }
+ }
+
+ /* Program to run. */
+ char *args[2] = { (char *) "true", NULL };
+ pid_t child;
+
+ res = posix_spawnp (&child, "true", NULL, &attrp, args, environ);
+ /* posix_spawnattr_destroy is noop. */
+ posix_spawnattr_destroy (&attrp);
+
+ if (res != 0)
+ {
+ errno = res;
+ FAIL_EXIT1 ("posix_spawnp: %m");
+ }
+
+ /* Child should have a different session ID than parent. */
+ child_sid = getsid (child);
+
+ if (child_sid == (pid_t) -1)
+ FAIL_EXIT1 ("getsid (%i): %m", child);
+
+ if (test_setsid)
+ {
+ if (child_sid == sid)
+ FAIL_EXIT1 ("child session ID matched parent one");
+ }
+ else
+ {
+ if (child_sid != sid)
+ FAIL_EXIT1 ("child session ID did not match parent one");
+ }
+}
+
+static int
+do_test (void)
+{
+ do_test_setsid (false);
+ do_test_setsid (true);
+
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/posix/tst-preadwrite-common.c b/posix/tst-preadwrite-common.c
new file mode 100644
index 0000000000..9e7f020ff0
--- /dev/null
+++ b/posix/tst-preadwrite-common.c
@@ -0,0 +1,86 @@
+/* Common definitions for pread and pwrite.
+ Copyright (C) 2016-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <error.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/stat.h>
+
+static void do_prepare (void);
+#define PREPARE(argc, argv) do_prepare ()
+static int do_test (void);
+#define TEST_FUNCTION do_test ()
+
+/* We might need a bit longer timeout. */
+#define TIMEOUT 20 /* sec */
+
+/* This defines the `main' function and some more. */
+#include <test-skeleton.c>
+
+/* These are for the temporary file we generate. */
+static char *name;
+static int fd;
+
+static void
+do_prepare (void)
+{
+ fd = create_temp_file ("tst-preadwrite.", &name);
+ if (fd == -1)
+ error (EXIT_FAILURE, errno, "cannot create temporary file");
+}
+
+
+static ssize_t
+do_test_with_offset (off_t offset)
+{
+ char buf[1000];
+ char res[1000];
+ int i;
+ ssize_t ret;
+
+ memset (buf, '\0', sizeof (buf));
+ memset (res, '\xff', sizeof (res));
+
+ if (write (fd, buf, sizeof (buf)) != sizeof (buf))
+ error (EXIT_FAILURE, errno, "during write");
+
+ for (i = 100; i < 200; ++i)
+ buf[i] = i;
+ ret = pwrite (fd, buf + 100, 100, offset + 100);
+ if (ret == -1)
+ error (EXIT_FAILURE, errno, "during pwrite");
+
+ for (i = 450; i < 600; ++i)
+ buf[i] = i;
+ ret = pwrite (fd, buf + 450, 150, offset + 450);
+ if (ret == -1)
+ error (EXIT_FAILURE, errno, "during pwrite");
+
+ ret = pread (fd, res, sizeof (buf) - 50, offset + 50);
+ if (ret == -1)
+ error (EXIT_FAILURE, errno, "during pread");
+
+ if (memcmp (buf + 50, res, ret) != 0)
+ {
+ printf ("error: read of pread != write of pwrite\n");
+ return -1;
+ }
+
+ return ret;
+}
diff --git a/posix/tst-preadwrite.c b/posix/tst-preadwrite.c
index b7c1658811..043c207f1c 100644
--- a/posix/tst-preadwrite.c
+++ b/posix/tst-preadwrite.c
@@ -1,7 +1,6 @@
/* Tests for pread and pwrite.
- Copyright (C) 1998-2016 Free Software Foundation, Inc.
+ Copyright (C) 1998-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
- Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -17,88 +16,10 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
-#include <errno.h>
-#include <error.h>
-#include <string.h>
-#include <unistd.h>
+#include "tst-preadwrite-common.c"
-
-/* Allow testing of the 64-bit versions as well. */
-#ifndef PREAD
-# define PREAD pread
-# define PWRITE pwrite
-#endif
-
-#define STRINGIFY(s) STRINGIFY2 (s)
-#define STRINGIFY2(s) #s
-
-/* Prototype for our test function. */
-extern void do_prepare (int argc, char *argv[]);
-extern int do_test (int argc, char *argv[]);
-
-/* We have a preparation function. */
-#define PREPARE do_prepare
-
-/* We might need a bit longer timeout. */
-#define TIMEOUT 20 /* sec */
-
-/* This defines the `main' function and some more. */
-#include <test-skeleton.c>
-
-/* These are for the temporary file we generate. */
-char *name;
-int fd;
-
-void
-do_prepare (int argc, char *argv[])
-{
- size_t name_len;
-
-#define FNAME FNAME2(TRUNCATE)
-#define FNAME2(s) "/" STRINGIFY(s) "XXXXXX"
-
- name_len = strlen (test_dir);
- name = malloc (name_len + sizeof (FNAME));
- if (name == NULL)
- error (EXIT_FAILURE, errno, "cannot allocate file name");
- mempcpy (mempcpy (name, test_dir, name_len), FNAME, sizeof (FNAME));
- add_temp_file (name);
-
- /* Open our test file. */
- fd = mkstemp (name);
- if (fd == -1)
- error (EXIT_FAILURE, errno, "cannot open test file `%s'", name);
-}
-
-
-int
-do_test (int argc, char *argv[])
+static int
+do_test (void)
{
- char buf[1000];
- char res[1000];
- int i;
-
- memset (buf, '\0', sizeof (buf));
- memset (res, '\xff', sizeof (res));
-
- if (write (fd, buf, sizeof (buf)) != sizeof (buf))
- error (EXIT_FAILURE, errno, "during write");
-
- for (i = 100; i < 200; ++i)
- buf[i] = i;
- if (PWRITE (fd, buf + 100, 100, 100) != 100)
- error (EXIT_FAILURE, errno, "during %s", STRINGIFY (PWRITE));
-
- for (i = 450; i < 600; ++i)
- buf[i] = i;
- if (PWRITE (fd, buf + 450, 150, 450) != 150)
- error (EXIT_FAILURE, errno, "during %s", STRINGIFY (PWRITE));
-
- if (PREAD (fd, res, sizeof (buf) - 50, 50) != sizeof (buf) - 50)
- error (EXIT_FAILURE, errno, "during %s", STRINGIFY (PREAD));
-
- close (fd);
- unlink (name);
-
- return memcmp (buf + 50, res, sizeof (buf) - 50);
+ return do_test_with_offset (0) == -1;
}
diff --git a/posix/tst-preadwrite64.c b/posix/tst-preadwrite64.c
index 27425be342..2a684e9d2f 100644
--- a/posix/tst-preadwrite64.c
+++ b/posix/tst-preadwrite64.c
@@ -1,7 +1,6 @@
/* Tests for pread64 and pwrite64.
- Copyright (C) 2000-2016 Free Software Foundation, Inc.
+ Copyright (C) 2000-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
- Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -17,7 +16,40 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
-#define PREAD pread64
-#define PWRITE pwrite64
+#define _FILE_OFFSET_BITS 64
+#include "tst-preadwrite-common.c"
-#include "tst-preadwrite.c"
+static int
+do_test (void)
+{
+ ssize_t ret;
+
+ ret = do_test_with_offset (0);
+ if (ret == -1)
+ return 1;
+
+ /* Create a sparse file larger than 4GB to check if offset is handled
+ correctly in p{write,read}64. */
+ off_t base_offset = UINT32_MAX + 2048LL;
+ ret = do_test_with_offset (base_offset);
+ if (ret == -1)
+ return 1;
+
+ struct stat st;
+ if (fstat (fd, &st) == -1)
+ {
+ printf ("error: fstat on temporary file failed: %m");
+ return 1;
+ }
+
+ /* The file size should >= base_offset plus bytes read. */
+ off_t expected_value = base_offset + ret;
+ if (st.st_size < expected_value)
+ {
+ printf ("error: file size less than expected (%jd > %jd)\n",
+ (intmax_t) expected_value, (intmax_t) st.st_size);
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/posix/tst-regex.c b/posix/tst-regex.c
index 9a41ff8a8f..17d8ea7691 100644
--- a/posix/tst-regex.c
+++ b/posix/tst-regex.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2016 Free Software Foundation, Inc.
+/* Copyright (C) 2001-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -15,9 +15,6 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
-#include <spawn.h>
-#include "spawn_int.h"
-
#include <assert.h>
#include <errno.h>
#include <error.h>
@@ -26,6 +23,7 @@
#include <iconv.h>
#include <locale.h>
#include <mcheck.h>
+#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -69,7 +67,7 @@ do_test (void)
mtrace ();
/* Make the content of the file available in memory. */
- file = "../ChangeLog.8";
+ file = "../ChangeLog.old/ChangeLog.8";
fd = open (file, O_RDONLY);
if (fd == -1)
error (EXIT_FAILURE, errno, "cannot open %s", basename (file));
diff --git a/posix/tst-regex2.c b/posix/tst-regex2.c
index 0d82c2acdd..5e624cb5c2 100644
--- a/posix/tst-regex2.c
+++ b/posix/tst-regex2.c
@@ -33,7 +33,7 @@ do_test (void)
"((((((((((.?))))))))))((((((((((.?))))))))))((((((((((.?))))))))))"
"((((((((((.?))))))))))Log\\.13" };
- int fd = open ("../ChangeLog.14", O_RDONLY);
+ int fd = open ("../ChangeLog.old/ChangeLog.14", O_RDONLY);
if (fd < 0)
{
printf ("Couldn't open ChangeLog.14: %m\n");
diff --git a/posix/tst-regexloc.c b/posix/tst-regexloc.c
index b67fbb6b8c..3ed3b68a1a 100644
--- a/posix/tst-regexloc.c
+++ b/posix/tst-regexloc.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2016 Free Software Foundation, Inc.
+/* Copyright (C) 2001-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -15,9 +15,6 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
-#include <spawn.h>
-#include "spawn_int.h"
-
#include <sys/types.h>
#include <regex.h>
#include <locale.h>
@@ -32,6 +29,10 @@ do_test (void)
if (setlocale (LC_ALL, "de_DE.ISO-8859-1") == NULL)
puts ("cannot set locale");
+ /* Range expressions in non-POSIX locales are unspecified, but
+ for now in glibc we maintain lowercase/uppercase distinction
+ in our collation element order (but not in collation weights
+ which means strcoll_l still collates as expected). */
else if (regcomp (&re, "[a-f]*", 0) != REG_NOERROR)
puts ("cannot compile expression \"[a-f]*\"");
else if (regexec (&re, "abcdefCDEF", 1, mat, 0) == REG_NOMATCH)
diff --git a/posix/tst-rfc3484-2.c b/posix/tst-rfc3484-2.c
index ee9281394b..8c64ac59ff 100644
--- a/posix/tst-rfc3484-2.c
+++ b/posix/tst-rfc3484-2.c
@@ -60,7 +60,6 @@ _res_hconf_init (void)
service_user *__nss_hosts_database attribute_hidden;
-
/* This is the beginning of the real test code. The above defines
(among other things) the function rfc3484_sort. */
diff --git a/posix/tst-rfc3484-3.c b/posix/tst-rfc3484-3.c
index c987366e4e..1c61aaf844 100644
--- a/posix/tst-rfc3484-3.c
+++ b/posix/tst-rfc3484-3.c
@@ -60,7 +60,6 @@ _res_hconf_init (void)
service_user *__nss_hosts_database attribute_hidden;
-
/* This is the beginning of the real test code. The above defines
(among other things) the function rfc3484_sort. */
diff --git a/posix/tst-rfc3484.c b/posix/tst-rfc3484.c
index 73c4dffcf5..8f45848e44 100644
--- a/posix/tst-rfc3484.c
+++ b/posix/tst-rfc3484.c
@@ -60,7 +60,6 @@ _res_hconf_init (void)
service_user *__nss_hosts_database attribute_hidden;
-
/* This is the beginning of the real test code. The above defines
(among other things) the function rfc3484_sort. */
diff --git a/posix/tst-rxspencer.c b/posix/tst-rxspencer.c
index dba40e1476..9d597ef3e9 100644
--- a/posix/tst-rxspencer.c
+++ b/posix/tst-rxspencer.c
@@ -1,5 +1,5 @@
/* Regular expression tests.
- Copyright (C) 2003-2016 Free Software Foundation, Inc.
+ Copyright (C) 2003-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Jakub Jelinek <jakub@redhat.com>, 2003.
diff --git a/posix/tst-spawn.c b/posix/tst-spawn.c
index 68f435789f..7c785c430c 100644
--- a/posix/tst-spawn.c
+++ b/posix/tst-spawn.c
@@ -1,5 +1,5 @@
/* Tests for spawn.
- Copyright (C) 2000-2016 Free Software Foundation, Inc.
+ Copyright (C) 2000-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 2000.
@@ -23,9 +23,10 @@
#include <spawn.h>
#include <stdlib.h>
#include <string.h>
-#include <unistd.h>
#include <wait.h>
#include <sys/param.h>
+#include <support/check.h>
+#include <support/xunistd.h>
/* Nonzero if the program gets called via `exec'. */
@@ -50,6 +51,11 @@ static char *name1;
static char *name2;
static char *name3;
+/* Descriptors for the temporary files. */
+static int temp_fd1 = -1;
+static int temp_fd2 = -1;
+static int temp_fd3 = -1;
+
/* The contents of our files. */
static const char fd1string[] = "This file should get closed";
static const char fd2string[] = "This file should stay opened";
@@ -60,23 +66,15 @@ static const char fd3string[] = "This file will be opened";
void
do_prepare (int argc, char *argv[])
{
- size_t name_len;
-
- name_len = strlen (test_dir);
- name1 = (char *) malloc (name_len + sizeof ("/spawnXXXXXX"));
- mempcpy (mempcpy (name1, test_dir, name_len),
- "/spawnXXXXXX", sizeof ("/spawnXXXXXX"));
- add_temp_file (name1);
-
- name2 = (char *) malloc (name_len + sizeof ("/spawnXXXXXX"));
- mempcpy (mempcpy (name2, test_dir, name_len),
- "/spawnXXXXXX", sizeof ("/spawnXXXXXX"));
- add_temp_file (name2);
-
- name3 = (char *) malloc (name_len + sizeof ("/spawnXXXXXX"));
- mempcpy (mempcpy (name3, test_dir, name_len),
- "/spawnXXXXXX", sizeof ("/spawnXXXXXX"));
- add_temp_file (name3);
+ /* We must not open any files in the restart case. */
+ if (restart)
+ return;
+
+ temp_fd1 = create_temp_file ("spawn", &name1);
+ temp_fd2 = create_temp_file ("spawn", &name2);
+ temp_fd3 = create_temp_file ("spawn", &name3);
+ if (temp_fd1 < 0 || temp_fd2 < 0 || temp_fd3 < 0)
+ exit (1);
}
@@ -158,9 +156,6 @@ int
do_test (int argc, char *argv[])
{
pid_t pid;
- int fd1;
- int fd2;
- int fd3;
int fd4;
int status;
posix_spawn_file_actions_t actions;
@@ -194,53 +189,42 @@ do_test (int argc, char *argv[])
/* Prepare the test. We are creating two files: one which file descriptor
will be marked with FD_CLOEXEC, another which is not. */
- /* Open our test files. */
- fd1 = mkstemp (name1);
- if (fd1 == -1)
- error (EXIT_FAILURE, errno, "cannot open test file `%s'", name1);
- fd2 = mkstemp (name2);
- if (fd2 == -1)
- error (EXIT_FAILURE, errno, "cannot open test file `%s'", name2);
- fd3 = mkstemp (name3);
- if (fd3 == -1)
- error (EXIT_FAILURE, errno, "cannot open test file `%s'", name3);
-
/* Write something in the files. */
- if (write (fd1, fd1string, strlen (fd1string)) != strlen (fd1string))
+ if (write (temp_fd1, fd1string, strlen (fd1string)) != strlen (fd1string))
error (EXIT_FAILURE, errno, "cannot write to first file");
- if (write (fd2, fd2string, strlen (fd2string)) != strlen (fd2string))
+ if (write (temp_fd2, fd2string, strlen (fd2string)) != strlen (fd2string))
error (EXIT_FAILURE, errno, "cannot write to second file");
- if (write (fd3, fd3string, strlen (fd3string)) != strlen (fd3string))
+ if (write (temp_fd3, fd3string, strlen (fd3string)) != strlen (fd3string))
error (EXIT_FAILURE, errno, "cannot write to third file");
/* Close the third file. It'll be opened by `spawn'. */
- close (fd3);
+ close (temp_fd3);
/* Tell `spawn' what to do. */
if (posix_spawn_file_actions_init (&actions) != 0)
error (EXIT_FAILURE, errno, "posix_spawn_file_actions_init");
- /* Close `fd1'. */
- if (posix_spawn_file_actions_addclose (&actions, fd1) != 0)
+ /* Close `temp_fd1'. */
+ if (posix_spawn_file_actions_addclose (&actions, temp_fd1) != 0)
error (EXIT_FAILURE, errno, "posix_spawn_file_actions_addclose");
/* We want to open the third file. */
name3_copy = strdup (name3);
if (name3_copy == NULL)
error (EXIT_FAILURE, errno, "strdup");
- if (posix_spawn_file_actions_addopen (&actions, fd3, name3_copy,
+ if (posix_spawn_file_actions_addopen (&actions, temp_fd3, name3_copy,
O_RDONLY, 0666) != 0)
error (EXIT_FAILURE, errno, "posix_spawn_file_actions_addopen");
/* Overwrite the name to check that a copy has been made. */
memset (name3_copy, 'X', strlen (name3_copy));
/* We dup the second descriptor. */
- fd4 = MAX (2, MAX (fd1, MAX (fd2, fd3))) + 1;
- if (posix_spawn_file_actions_adddup2 (&actions, fd2, fd4) != 0)
+ fd4 = MAX (2, MAX (temp_fd1, MAX (temp_fd2, temp_fd3))) + 1;
+ if (posix_spawn_file_actions_adddup2 (&actions, temp_fd2, fd4) != 0)
error (EXIT_FAILURE, errno, "posix_spawn_file_actions_adddup2");
/* Now spawn the process. */
- snprintf (fd1name, sizeof fd1name, "%d", fd1);
- snprintf (fd2name, sizeof fd2name, "%d", fd2);
- snprintf (fd3name, sizeof fd3name, "%d", fd3);
+ snprintf (fd1name, sizeof fd1name, "%d", temp_fd1);
+ snprintf (fd2name, sizeof fd2name, "%d", temp_fd2);
+ snprintf (fd3name, sizeof fd3name, "%d", temp_fd3);
snprintf (fd4name, sizeof fd4name, "%d", fd4);
for (i = 0; i < (argc == (restart ? 6 : 5) ? 4 : 1); i++)
@@ -257,23 +241,25 @@ do_test (int argc, char *argv[])
if (posix_spawn (&pid, argv[1], &actions, NULL, spargv, environ) != 0)
error (EXIT_FAILURE, errno, "posix_spawn");
+ /* Same test but with a NULL pid argument. */
+ if (posix_spawn (NULL, argv[1], &actions, NULL, spargv, environ) != 0)
+ error (EXIT_FAILURE, errno, "posix_spawn");
+
/* Cleanup. */
if (posix_spawn_file_actions_destroy (&actions) != 0)
error (EXIT_FAILURE, errno, "posix_spawn_file_actions_destroy");
free (name3_copy);
- /* Wait for the child. */
- if (waitpid (pid, &status, 0) != pid)
- error (EXIT_FAILURE, errno, "wrong child");
+ /* Wait for the children. */
+ TEST_VERIFY (xwaitpid (pid, &status, 0) == pid);
+ TEST_VERIFY (WIFEXITED (status));
+ TEST_VERIFY (!WIFSIGNALED (status));
+ TEST_VERIFY (WEXITSTATUS (status) == 0);
- if (WTERMSIG (status) != 0)
- error (EXIT_FAILURE, 0, "Child terminated incorrectly");
- status = WEXITSTATUS (status);
+ xwaitpid (-1, &status, 0);
+ TEST_VERIFY (WIFEXITED (status));
+ TEST_VERIFY (!WIFSIGNALED (status));
+ TEST_VERIFY (WEXITSTATUS (status) == 0);
- /* Remove the test files. */
- unlink (name1);
- unlink (name2);
- unlink (name3);
-
- return status;
+ return 0;
}
diff --git a/posix/tst-spawn2.c b/posix/tst-spawn2.c
new file mode 100644
index 0000000000..fc63cc1e75
--- /dev/null
+++ b/posix/tst-spawn2.c
@@ -0,0 +1,78 @@
+/* Further tests for spawn in case of invalid binary paths.
+ Copyright (C) 2016-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <spawn.h>
+#include <error.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/wait.h>
+#include <stdio.h>
+
+#include <support/check.h>
+
+int
+do_test (void)
+{
+ /* Check if posix_spawn correctly returns an error and an invalid pid
+ by trying to spawn an invalid binary. */
+
+ const char *program = "/path/to/invalid/binary";
+ char * const args[] = { 0 };
+ pid_t pid = -1;
+
+ int ret = posix_spawn (&pid, program, 0, 0, args, environ);
+ if (ret != ENOENT)
+ {
+ errno = ret;
+ FAIL_EXIT1 ("posix_spawn: %m");
+ }
+
+ /* POSIX states the value returned on pid variable in case of an error
+ is not specified. GLIBC will update the value iff the child
+ execution is successful. */
+ if (pid != -1)
+ FAIL_EXIT1 ("posix_spawn returned pid != -1 (%i)", (int) pid);
+
+ /* Check if no child is actually created. */
+ ret = waitpid (-1, NULL, 0);
+ if (ret != -1 || errno != ECHILD)
+ FAIL_EXIT1 ("waitpid: %m)");
+
+ /* Same as before, but with posix_spawnp. */
+ char *args2[] = { (char*) program, 0 };
+
+ ret = posix_spawnp (&pid, args2[0], 0, 0, args2, environ);
+ if (ret != ENOENT)
+ {
+ errno = ret;
+ FAIL_EXIT1 ("posix_spawnp: %m");
+ }
+
+ if (pid != -1)
+ FAIL_EXIT1 ("posix_spawnp returned pid != -1 (%i)", (int) pid);
+
+ ret = waitpid (-1, NULL, 0);
+ if (ret != -1 || errno != ECHILD)
+ FAIL_EXIT1 ("waitpid: %m)");
+
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/posix/tst-spawn3.c b/posix/tst-spawn3.c
new file mode 100644
index 0000000000..b60a783dd4
--- /dev/null
+++ b/posix/tst-spawn3.c
@@ -0,0 +1,151 @@
+/* Check posix_spawn add file actions.
+ Copyright (C) 2016-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <stdio.h>
+#include <spawn.h>
+#include <error.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/wait.h>
+#include <sys/resource.h>
+#include <fcntl.h>
+#include <paths.h>
+
+#include <support/check.h>
+#include <support/temp_file.h>
+
+static int
+do_test (void)
+{
+ /* The test checks if posix_spawn open file action close the file descriptor
+ before opening a new one in case the input file descriptor is already
+ opened. It does by exhausting all file descriptors on the process before
+ issue posix_spawn. It then issues a posix_spawn for '/bin/sh echo $$'
+ and add two rules:
+
+ 1. Redirect stdout to a temporary filepath
+ 2. Redirect stderr to stdout
+
+ If the implementation does not close the file 1. will fail with
+ EMFILE. */
+
+ struct rlimit rl;
+ int max_fd = 24;
+ int ret;
+
+ /* Set maximum number of file descriptor to a low value to avoid open
+ too many files in environments where RLIMIT_NOFILE is large and to
+ limit the array size to track the opened file descriptors. */
+
+ if (getrlimit (RLIMIT_NOFILE, &rl) == -1)
+ FAIL_EXIT1 ("getrlimit (RLIMIT_NOFILE): %m");
+
+ max_fd = (rl.rlim_cur < max_fd ? rl.rlim_cur : max_fd);
+ rl.rlim_cur = max_fd;
+
+ if (setrlimit (RLIMIT_NOFILE, &rl) == 1)
+ FAIL_EXIT1 ("setrlimit (RLIMIT_NOFILE): %m");
+
+ /* Exhauste the file descriptor limit with temporary files. */
+ int files[max_fd];
+ int nfiles = 0;
+ for (;;)
+ {
+ int fd = create_temp_file ("tst-spawn3.", NULL);
+ if (fd == -1)
+ {
+ if (errno != EMFILE)
+ FAIL_EXIT1 ("create_temp_file: %m");
+ break;
+ }
+ files[nfiles++] = fd;
+ }
+
+ posix_spawn_file_actions_t a;
+ if (posix_spawn_file_actions_init (&a) != 0)
+ FAIL_EXIT1 ("posix_spawn_file_actions_init");
+
+ /* Executes a /bin/sh echo $$ 2>&1 > ${objpfx}tst-spawn3.pid . */
+ const char pidfile[] = OBJPFX "tst-spawn3.pid";
+ if (posix_spawn_file_actions_addopen (&a, STDOUT_FILENO, pidfile, O_WRONLY |
+ O_CREAT | O_TRUNC, 0644) != 0)
+ FAIL_EXIT1 ("posix_spawn_file_actions_addopen");
+
+ if (posix_spawn_file_actions_adddup2 (&a, STDOUT_FILENO, STDERR_FILENO) != 0)
+ FAIL_EXIT1 ("posix_spawn_file_actions_adddup2");
+
+ /* Since execve (called by posix_spawn) might require to open files to
+ actually execute the shell script, setup to close the temporary file
+ descriptors. */
+ for (int i=0; i<nfiles; i++)
+ {
+ if (posix_spawn_file_actions_addclose (&a, files[i]))
+ FAIL_EXIT1 ("posix_spawn_file_actions_addclose");
+ }
+
+ char *spawn_argv[] = { (char *) _PATH_BSHELL, (char *) "-c",
+ (char *) "echo $$", NULL };
+ pid_t pid;
+ if ((ret = posix_spawn (&pid, _PATH_BSHELL, &a, NULL, spawn_argv, NULL))
+ != 0)
+ {
+ errno = ret;
+ FAIL_EXIT1 ("posix_spawn: %m");
+ }
+
+ int status;
+ int err = waitpid (pid, &status, 0);
+ if (err != pid)
+ FAIL_EXIT1 ("waitpid: %m");
+
+ /* Close the temporary files descriptor so it can check posix_spawn
+ output. */
+ for (int i=0; i<nfiles; i++)
+ {
+ if (close (files[i]))
+ FAIL_EXIT1 ("close: %m");
+ }
+
+ int pidfd = open (pidfile, O_RDONLY);
+ if (pidfd == -1)
+ FAIL_EXIT1 ("open: %m");
+
+ char buf[64];
+ ssize_t n;
+ if ((n = read (pidfd, buf, sizeof (buf))) < 0)
+ FAIL_EXIT1 ("read: %m");
+
+ unlink (pidfile);
+
+ /* We only expect to read the PID. */
+ char *endp;
+ long int rpid = strtol (buf, &endp, 10);
+ if (*endp != '\n')
+ FAIL_EXIT1 ("*endp != \'n\'");
+ if (endp == buf)
+ FAIL_EXIT1 ("read empty line");
+
+ if (rpid != pid)
+ FAIL_EXIT1 ("found \"%s\", expected pid %ld\n", buf, (long int) pid);
+
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/posix/tst-spawn4-compat.c b/posix/tst-spawn4-compat.c
new file mode 100644
index 0000000000..11f654b913
--- /dev/null
+++ b/posix/tst-spawn4-compat.c
@@ -0,0 +1,77 @@
+/* Check if posix_spawn does handle correctly ENOEXEC files.
+ Copyright (C) 2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <spawn.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+
+#include <support/xunistd.h>
+#include <support/check.h>
+#include <support/temp_file.h>
+
+#include <shlib-compat.h>
+#if TEST_COMPAT (libc, GLIBC_2_0, GLIBC_2_15)
+
+compat_symbol_reference (libc, posix_spawn, posix_spawn, GLIBC_2_2);
+compat_symbol_reference (libc, posix_spawnp, posix_spawnp, GLIBC_2_2);
+
+static int
+do_test (void)
+{
+ char *scriptname;
+ int fd = create_temp_file ("tst-spawn4.", &scriptname);
+ TEST_VERIFY_EXIT (fd >= 0);
+
+ const char script[] = "exit 65";
+ xwrite (fd, script, sizeof (script) - 1);
+ xclose (fd);
+
+ TEST_VERIFY_EXIT (chmod (scriptname, 0x775) == 0);
+
+ pid_t pid;
+ int status;
+
+ /* For compat symbol it verifies that trying to issued a shell script
+ without a shebang is correctly executed. */
+ status = posix_spawn (&pid, scriptname, NULL, NULL, (char *[]) { 0 },
+ (char *[]) { 0 });
+ TEST_VERIFY_EXIT (status == 0);
+
+ TEST_VERIFY_EXIT (waitpid (pid, &status, 0) == pid);
+ TEST_VERIFY_EXIT (WIFEXITED (status) == 1 && WEXITSTATUS (status) == 65);
+
+ status = posix_spawnp (&pid, scriptname, NULL, NULL, (char *[]) { 0 },
+ (char *[]) { 0 });
+ TEST_VERIFY_EXIT (status == 0);
+
+ TEST_VERIFY_EXIT (waitpid (pid, &status, 0) == pid);
+ TEST_VERIFY_EXIT (WIFEXITED (status) == 1 && WEXITSTATUS (status) == 65);
+
+ return 0;
+}
+#else
+static int
+do_test (void)
+{
+ return 77;
+}
+#endif
+
+#include <support/test-driver.c>
diff --git a/posix/tst-spawn4.c b/posix/tst-spawn4.c
new file mode 100644
index 0000000000..e4a1fa3f00
--- /dev/null
+++ b/posix/tst-spawn4.c
@@ -0,0 +1,56 @@
+/* Check if posix_spawn does handle correctly ENOEXEC files.
+ Copyright (C) 2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <spawn.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/stat.h>
+
+#include <support/xunistd.h>
+#include <support/check.h>
+#include <support/temp_file.h>
+
+static int
+do_test (void)
+{
+ char *scriptname;
+ int fd = create_temp_file ("tst-spawn4.", &scriptname);
+ TEST_VERIFY_EXIT (fd >= 0);
+
+ const char script[] = "echo it should not happen";
+ xwrite (fd, script, sizeof (script) - 1);
+ xclose (fd);
+
+ TEST_VERIFY_EXIT (chmod (scriptname, 0x775) == 0);
+
+ pid_t pid;
+ int status;
+
+ /* Check if scripts without shebang are correctly not executed. */
+ status = posix_spawn (&pid, scriptname, NULL, NULL, (char *[]) { 0 },
+ (char *[]) { 0 });
+ TEST_VERIFY_EXIT (status == ENOEXEC);
+
+ status = posix_spawnp (&pid, scriptname, NULL, NULL, (char *[]) { 0 },
+ (char *[]) { 0 });
+ TEST_VERIFY_EXIT (status == ENOEXEC);
+
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/posix/tst-sysconf-empty-chroot.c b/posix/tst-sysconf-empty-chroot.c
new file mode 100644
index 0000000000..0295c475e5
--- /dev/null
+++ b/posix/tst-sysconf-empty-chroot.c
@@ -0,0 +1,95 @@
+/* Test sysconf with an empty chroot.
+ Copyright (C) 2017-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <support/check.h>
+#include <support/namespace.h>
+#include <support/support.h>
+#include <support/temp_file.h>
+#include <support/test-driver.h>
+#include <support/xunistd.h>
+#include <unistd.h>
+
+/* Check for an SMP system in a forked process, so that the parent
+ process does not cache the value. */
+static void
+is_smp_callback (void *closure)
+{
+ bool *result = closure;
+
+ long cpus = sysconf (_SC_NPROCESSORS_ONLN);
+ TEST_VERIFY_EXIT (cpus > 0);
+ *result = cpus != 1;
+}
+
+static bool
+is_smp (void)
+{
+ bool *result = support_shared_allocate (sizeof (*result));
+ support_isolate_in_subprocess (is_smp_callback, result);
+ bool result_copy = *result;
+ support_shared_free (result);
+ return result_copy;
+}
+
+static char *path_chroot;
+
+/* Prepare an empty directory, to be used as a chroot. */
+static void
+prepare (int argc, char **argv)
+{
+ path_chroot = xasprintf ("%s/tst-resolv-res_init-XXXXXX", test_dir);
+ if (mkdtemp (path_chroot) == NULL)
+ FAIL_EXIT1 ("mkdtemp (\"%s\"): %m", path_chroot);
+ add_temp_file (path_chroot);
+}
+
+/* The actual test. Run it in a subprocess, so that the test harness
+ can remove the temporary directory in --direct mode. */
+static void
+chroot_callback (void *closure)
+{
+ xchroot (path_chroot);
+ long cpus = sysconf (_SC_NPROCESSORS_ONLN);
+ printf ("info: sysconf (_SC_NPROCESSORS_ONLN) in chroot: %ld\n", cpus);
+ TEST_VERIFY (cpus > 0);
+ TEST_VERIFY (cpus != 1);
+ _exit (0);
+}
+
+static int
+do_test (void)
+{
+ if (!is_smp ())
+ {
+ printf ("warning: test not supported on uniprocessor system\n");
+ return EXIT_UNSUPPORTED;
+ }
+
+ support_become_root ();
+ if (!support_can_chroot ())
+ return EXIT_UNSUPPORTED;
+
+ support_isolate_in_subprocess (chroot_callback, NULL);
+
+ return 0;
+}
+
+#define PREPARE prepare
+#include <support/test-driver.c>
diff --git a/posix/tst-truncate-common.c b/posix/tst-truncate-common.c
new file mode 100644
index 0000000000..f9fb6d155d
--- /dev/null
+++ b/posix/tst-truncate-common.c
@@ -0,0 +1,88 @@
+/* Common f{truncate} tests definitions.
+ Copyright (C) 2016-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+static void do_prepare (void);
+#define PREPARE(argc, argv) do_prepare ()
+static int do_test (void);
+#define TEST_FUNCTION do_test ()
+
+#include <test-skeleton.c>
+
+static char *temp_filename;
+static int temp_fd;
+
+static void
+do_prepare (void)
+{
+ temp_fd = create_temp_file ("tst-trucate.", &temp_filename);
+ if (temp_fd == -1)
+ {
+ printf ("cannot create temporary file: %m\n");
+ exit (1);
+ }
+}
+
+#define FAIL(str) \
+ do { printf ("error: %s (line %d)\n", str, __LINE__); return 1; } while (0)
+
+static int
+do_test_with_offset (off_t offset)
+{
+ struct stat st;
+ char buf[1000];
+
+ memset (buf, 0xcf, sizeof (buf));
+
+ if (pwrite (temp_fd, buf, sizeof (buf), offset) != sizeof (buf))
+ FAIL ("write failed");
+ if (fstat (temp_fd, &st) < 0 || st.st_size != (offset + sizeof (buf)))
+ FAIL ("initial size wrong");
+
+ if (ftruncate (temp_fd, offset + 800) < 0)
+ FAIL ("size reduction with ftruncate failed");
+ if (fstat (temp_fd, &st) < 0 || st.st_size != (offset + 800))
+ FAIL ("size after reduction with ftruncate is incorrect");
+
+ /* The following test covers more than POSIX. POSIX does not require
+ that ftruncate() can increase the file size. But we are testing
+ Unix systems. */
+ if (ftruncate (temp_fd, offset + 1200) < 0)
+ FAIL ("size increate with ftruncate failed");
+ if (fstat (temp_fd, &st) < 0 || st.st_size != (offset + 1200))
+ FAIL ("size after increase is incorrect");
+
+ if (truncate (temp_filename, offset + 800) < 0)
+ FAIL ("size reduction with truncate failed");
+ if (fstat (temp_fd, &st) < 0 || st.st_size != (offset + 800))
+ FAIL ("size after reduction with truncate incorrect");
+
+ /* The following test covers more than POSIX. POSIX does not require
+ that truncate() can increase the file size. But we are testing
+ Unix systems. */
+ if (truncate (temp_filename, (offset + 1200)) < 0)
+ FAIL ("size increase with truncate failed");
+ if (fstat (temp_fd, &st) < 0 || st.st_size != (offset + 1200))
+ FAIL ("size increase with truncate is incorrect");
+
+ return 0;
+}
diff --git a/posix/tst-truncate.c b/posix/tst-truncate.c
index 8f5957f417..258337e6a6 100644
--- a/posix/tst-truncate.c
+++ b/posix/tst-truncate.c
@@ -1,5 +1,5 @@
/* Tests for ftruncate and truncate.
- Copyright (C) 2000-2016 Free Software Foundation, Inc.
+ Copyright (C) 2000-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 2000.
@@ -17,116 +17,10 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
-#include <errno.h>
-#include <error.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/stat.h>
+#include "tst-truncate-common.c"
-
-/* Allow testing of the 64-bit versions as well. */
-#ifndef TRUNCATE
-# define TRUNCATE truncate
-# define FTRUNCATE ftruncate
-#endif
-
-#define STRINGIFY(s) STRINGIFY2 (s)
-#define STRINGIFY2(s) #s
-
-/* Prototype for our test function. */
-extern void do_prepare (int argc, char *argv[]);
-extern int do_test (int argc, char *argv[]);
-
-/* We have a preparation function. */
-#define PREPARE do_prepare
-
-/* We might need a bit longer timeout. */
-#define TIMEOUT 20 /* sec */
-
-/* This defines the `main' function and some more. */
-#include <test-skeleton.c>
-
-/* These are for the temporary file we generate. */
-char *name;
-int fd;
-
-void
-do_prepare (int argc, char *argv[])
+static int
+do_test (void)
{
- size_t name_len;
-
-#define FNAME FNAME2(TRUNCATE)
-#define FNAME2(s) "/" STRINGIFY(s) "XXXXXX"
-
- name_len = strlen (test_dir);
- name = malloc (name_len + sizeof (FNAME));
- mempcpy (mempcpy (name, test_dir, name_len), FNAME, sizeof (FNAME));
- add_temp_file (name);
-
- /* Open our test file. */
- fd = mkstemp (name);
- if (fd == -1)
- error (EXIT_FAILURE, errno, "cannot open test file `%s'", name);
-}
-
-
-int
-do_test (int argc, char *argv[])
-{
- struct stat st;
- char buf[1000];
-
- memset (buf, '\0', sizeof (buf));
-
- if (write (fd, buf, sizeof (buf)) != sizeof (buf))
- error (EXIT_FAILURE, errno, "during write");
-
- if (fstat (fd, &st) < 0 || st.st_size != sizeof (buf))
- error (EXIT_FAILURE, 0, "initial size wrong");
-
-
- if (FTRUNCATE (fd, 800) < 0)
- error (EXIT_FAILURE, errno, "size reduction with %s failed",
- STRINGIFY (FTRUNCATE));
-
- if (fstat (fd, &st) < 0 || st.st_size != 800)
- error (EXIT_FAILURE, 0, "size after reduction with %s incorrect",
- STRINGIFY (FTRUNCATE));
-
- /* The following test covers more than POSIX. POSIX does not require
- that ftruncate() can increase the file size. But we are testing
- Unix systems. */
- if (FTRUNCATE (fd, 1200) < 0)
- error (EXIT_FAILURE, errno, "size increase with %s failed",
- STRINGIFY (FTRUNCATE));
-
- if (fstat (fd, &st) < 0 || st.st_size != 1200)
- error (EXIT_FAILURE, 0, "size after increase with %s incorrect",
- STRINGIFY (FTRUNCATE));
-
-
- if (TRUNCATE (name, 800) < 0)
- error (EXIT_FAILURE, errno, "size reduction with %s failed",
- STRINGIFY (TRUNCATE));
-
- if (fstat (fd, &st) < 0 || st.st_size != 800)
- error (EXIT_FAILURE, 0, "size after reduction with %s incorrect",
- STRINGIFY (TRUNCATE));
-
- /* The following test covers more than POSIX. POSIX does not require
- that truncate() can increase the file size. But we are testing
- Unix systems. */
- if (TRUNCATE (name, 1200) < 0)
- error (EXIT_FAILURE, errno, "size increase with %s failed",
- STRINGIFY (TRUNCATE));
-
- if (fstat (fd, &st) < 0 || st.st_size != 1200)
- error (EXIT_FAILURE, 0, "size after increase with %s incorrect",
- STRINGIFY (TRUNCATE));
-
-
- close (fd);
- unlink (name);
-
- return 0;
+ return do_test_with_offset (0);
}
diff --git a/posix/tst-truncate64.c b/posix/tst-truncate64.c
index 64eb0a4bd5..bfb3bf7818 100644
--- a/posix/tst-truncate64.c
+++ b/posix/tst-truncate64.c
@@ -1,5 +1,5 @@
/* Tests for ftruncate64 and truncate64.
- Copyright (C) 2000-2016 Free Software Foundation, Inc.
+ Copyright (C) 2000-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 2000.
@@ -17,7 +17,22 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
-#define TRUNCATE truncate64
-#define FTRUNCATE ftruncate64
+#define _FILE_OFFSET_BITS 64
+#include "tst-truncate-common.c"
-#include "tst-truncate.c"
+static int
+do_test (void)
+{
+ int ret;
+
+ ret = do_test_with_offset (0);
+ if (ret == -1)
+ return -1;
+
+ off_t base_offset = UINT32_MAX + 512LL;
+ ret = do_test_with_offset (base_offset);
+ if (ret == -1)
+ return 1;
+
+ return 0;
+}
diff --git a/posix/tst-vfork1.c b/posix/tst-vfork1.c
index a31cfc1753..2236ab1b2b 100644
--- a/posix/tst-vfork1.c
+++ b/posix/tst-vfork1.c
@@ -1,5 +1,5 @@
/* Test for vfork functions.
- Copyright (C) 2004-2016 Free Software Foundation, Inc.
+ Copyright (C) 2004-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2004.
diff --git a/posix/tst-vfork2.c b/posix/tst-vfork2.c
index 7733926eb4..92997d8fd8 100644
--- a/posix/tst-vfork2.c
+++ b/posix/tst-vfork2.c
@@ -1,5 +1,5 @@
/* Test for vfork functions.
- Copyright (C) 2004-2016 Free Software Foundation, Inc.
+ Copyright (C) 2004-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2004.
diff --git a/posix/tst-vfork3.c b/posix/tst-vfork3.c
index 05edc5a217..0449b2486a 100644
--- a/posix/tst-vfork3.c
+++ b/posix/tst-vfork3.c
@@ -1,5 +1,5 @@
/* Test for vfork functions.
- Copyright (C) 2007-2016 Free Software Foundation, Inc.
+ Copyright (C) 2007-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Jakub Jelinek <jakub@redhat.com>, 2007.
@@ -23,6 +23,7 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+#include <sys/stat.h>
#include <sys/wait.h>
static int do_test (void);
@@ -33,84 +34,67 @@ char *tmpdirname;
#define PREPARE(argc, argv) do_prepare ()
#include "../test-skeleton.c"
-static int
-do_test (void)
+static void
+run_script (const char *script, char *const argv[])
{
- mtrace ();
-
- const char *path = getenv ("PATH");
- if (path == NULL)
- path = "/bin";
- char pathbuf[strlen (tmpdirname) + 1 + strlen (path) + 1];
- strcpy (stpcpy (stpcpy (pathbuf, tmpdirname), ":"), path);
- if (setenv ("PATH", pathbuf, 1) < 0)
- {
- puts ("setenv failed");
- return 1;
- }
-
- size_t i;
- char *argv[3] = { (char *) "script1.sh", (char *) "1", NULL };
- for (i = 0; i < 5; i++)
+ for (size_t i = 0; i < 5; i++)
{
pid_t pid = vfork ();
if (pid < 0)
- {
- printf ("vfork failed: %m\n");
- return 1;
- }
+ FAIL_EXIT1 ("vfork failed: %m");
else if (pid == 0)
{
- execvp ("script1.sh", argv);
+ execvp (script, argv);
_exit (errno);
}
+
int status;
if (TEMP_FAILURE_RETRY (waitpid (pid, &status, 0)) != pid)
- {
- puts ("waitpid failed");
- return 1;
- }
+ FAIL_EXIT1 ("waitpid failed");
else if (status != 0)
{
if (WIFEXITED (status))
- printf ("script1.sh failed with status %d\n",
- WEXITSTATUS (status));
+ FAIL_EXIT1 ("%s failed with status %d\n", script,
+ WEXITSTATUS (status));
else
- printf ("script1.sh kill by signal %d\n",
- WTERMSIG (status));
- return 1;
+ FAIL_EXIT1 ("%s killed by signal %d\n", script,
+ WTERMSIG (status));
}
}
+}
- argv[0] = (char *) "script2.sh";
- argv[1] = (char *) "2";
- for (i = 0; i < 5; i++)
+static int
+do_test (void)
+{
+ mtrace ();
+
+ const char *path = getenv ("PATH");
+ if (path == NULL)
+ path = "/bin";
+ char pathbuf[strlen (tmpdirname) + 1 + strlen (path) + 1];
+ strcpy (stpcpy (stpcpy (pathbuf, tmpdirname), ":"), path);
+ if (setenv ("PATH", pathbuf, 1) < 0)
{
- pid_t pid = vfork ();
- if (pid < 0)
- {
- printf ("vfork failed: %m\n");
- return 1;
- }
- else if (pid == 0)
- {
- execvp ("script2.sh", argv);
- _exit (errno);
- }
- int status;
- if (TEMP_FAILURE_RETRY (waitpid (pid, &status, 0)) != pid)
- {
- puts ("waitpid failed");
- return 1;
- }
- else if (status != 0)
- {
- printf ("script2.sh failed with status %d\n", status);
- return 1;
- }
+ puts ("setenv failed");
+ return 1;
}
- for (i = 0; i < 5; i++)
+ /* Although manual states first argument should be the script name itself,
+ current execv{p,e} implementation allows it. */
+ char *argv00[] = { NULL };
+ run_script ("script0.sh", argv00);
+
+ char *argv01[] = { (char*) "script0.sh", NULL };
+ run_script ("script0.sh", argv01);
+
+ char *argv1[] = { (char *) "script1.sh", (char *) "1", NULL };
+ run_script ("script1.sh", argv1);
+
+ char *argv2[] = { (char *) "script2.sh", (char *) "2", NULL };
+ run_script ("script2.sh", argv2);
+
+ /* Same as before but with execlp. */
+ for (size_t i = 0; i < 5; i++)
{
pid_t pid = vfork ();
if (pid < 0)
@@ -137,87 +121,55 @@ do_test (void)
}
unsetenv ("PATH");
- argv[0] = (char *) "echo";
- argv[1] = (char *) "script 4";
- for (i = 0; i < 5; i++)
- {
- pid_t pid = vfork ();
- if (pid < 0)
- {
- printf ("vfork failed: %m\n");
- return 1;
- }
- else if (pid == 0)
- {
- execvp ("echo", argv);
- _exit (errno);
- }
- int status;
- if (TEMP_FAILURE_RETRY (waitpid (pid, &status, 0)) != pid)
- {
- puts ("waitpid failed");
- return 1;
- }
- else if (status != 0)
- {
- printf ("echo failed with status %d\n", status);
- return 1;
- }
- }
+ char *argv4[] = { (char *) "echo", (char *) "script 4", NULL };
+ run_script ("echo", argv4);
return 0;
}
static void
+create_script (const char *script, const char *contents, size_t size)
+{
+ int fd = open (script, O_WRONLY | O_CREAT, 0700);
+ if (fd < 0
+ || TEMP_FAILURE_RETRY (write (fd, contents, size)) != size
+ || fchmod (fd, S_IRUSR | S_IXUSR) < 0)
+ FAIL_EXIT1 ("could not write %s\n", script);
+ close (fd);
+}
+
+static void
do_prepare (void)
{
size_t len = strlen (test_dir) + sizeof ("/tst-vfork3.XXXXXX");
tmpdirname = malloc (len);
- char *script1 = malloc (len + sizeof "/script1.sh");
- char *script2 = malloc (len + sizeof "/script2.sh");
- if (tmpdirname == NULL || script1 == NULL || script2 == NULL)
- {
- puts ("out of memory");
- exit (1);
- }
+ if (tmpdirname == NULL)
+ FAIL_EXIT1 ("out of memory");
strcpy (stpcpy (tmpdirname, test_dir), "/tst-vfork3.XXXXXX");
tmpdirname = mkdtemp (tmpdirname);
if (tmpdirname == NULL)
- {
- puts ("could not create temporary directory");
- exit (1);
- }
+ FAIL_EXIT1 ("could not create temporary directory");
+ char script0[len + sizeof "/script0.sh"];
+ char script1[len + sizeof "/script1.sh"];
+ char script2[len + sizeof "/script2.sh"];
+
+ strcpy (stpcpy (script0, tmpdirname), "/script0.sh");
strcpy (stpcpy (script1, tmpdirname), "/script1.sh");
strcpy (stpcpy (script2, tmpdirname), "/script2.sh");
- /* Need to make sure tmpdirname is at the end of the linked list. */
- add_temp_file (script1);
add_temp_file (tmpdirname);
+ add_temp_file (script0);
+ add_temp_file (script1);
add_temp_file (script2);
+ const char content0[] = "#!/bin/sh\necho empty\n";
+ create_script (script0, content0, sizeof content0);
+
const char content1[] = "#!/bin/sh\necho script $1\n";
- int fd = open (script1, O_WRONLY | O_CREAT, 0700);
- if (fd < 0
- || TEMP_FAILURE_RETRY (write (fd, content1, sizeof content1))
- != sizeof content1
- || fchmod (fd, S_IRUSR | S_IXUSR) < 0)
- {
- printf ("Could not write %s\n", script1);
- exit (1);
- }
- close (fd);
+ create_script (script1, content1, sizeof content1);
const char content2[] = "echo script $1\n";
- fd = open (script2, O_WRONLY | O_CREAT, 0700);
- if (fd < 0
- || TEMP_FAILURE_RETRY (write (fd, content2, sizeof content2))
- != sizeof content2
- || fchmod (fd, S_IRUSR | S_IXUSR) < 0)
- {
- printf ("Could not write %s\n", script2);
- exit (1);
- }
- close (fd);
+ create_script (script2, content2, sizeof content2);
}
diff --git a/posix/tst-waitid.c b/posix/tst-waitid.c
index e6507a02d8..4af8761afc 100644
--- a/posix/tst-waitid.c
+++ b/posix/tst-waitid.c
@@ -1,5 +1,5 @@
/* Tests for waitid.
- Copyright (C) 2004-2016 Free Software Foundation, Inc.
+ Copyright (C) 2004-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/posix/uname-values.h b/posix/uname-values.h
index 73d8472219..1055d1ce5b 100644
--- a/posix/uname-values.h
+++ b/posix/uname-values.h
@@ -1,5 +1,5 @@
/* Constant values for the uname function to return. Generic version.
- Copyright (C) 2015-2016 Free Software Foundation, Inc.
+ Copyright (C) 2015-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/posix/uname.c b/posix/uname.c
index b0dec649fc..0420404553 100644
--- a/posix/uname.c
+++ b/posix/uname.c
@@ -1,5 +1,5 @@
/* uname -- Report basic information about the system. Generic version.
- Copyright (C) 1991-2016 Free Software Foundation, Inc.
+ Copyright (C) 1991-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/posix/unistd.h b/posix/unistd.h
index 405638ce79..a8cf28b5e7 100644
--- a/posix/unistd.h
+++ b/posix/unistd.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -107,9 +107,6 @@ __BEGIN_DECLS
/* The X/Open Unix extensions are available. */
#define _XOPEN_UNIX 1
-/* Encryption is present. */
-#define _XOPEN_CRYPT 1
-
/* The enhanced internationalization capabilities according to XPG4.2
are present. */
#define _XOPEN_ENH_I18N 1
@@ -781,8 +778,7 @@ extern int ttyname_r (int __fd, char *__buf, size_t __buflen)
with a terminal, zero if not. */
extern int isatty (int __fd) __THROW;
-#if defined __USE_MISC \
- || (defined __USE_XOPEN_EXTENDED && !defined __USE_UNIX98)
+#ifdef __USE_MISC
/* Return the index into the active-logins file (utmp) for
the controlling terminal. */
extern int ttyslot (void) __THROW;
@@ -850,7 +846,7 @@ extern int tcsetpgrp (int __fd, __pid_t __pgrp_id) __THROW;
This function is a possible cancellation point and therefore not
marked with __THROW. */
extern char *getlogin (void);
-#if defined __USE_REENTRANT || defined __USE_POSIX199506
+#ifdef __USE_POSIX199506
/* Return at most NAME_LEN characters of the login name of the user in NAME.
If it cannot be determined or some other error occurred, return the error
code. Otherwise return 0.
@@ -870,12 +866,11 @@ extern int setlogin (const char *__name) __THROW __nonnull ((1));
/* Get definitions and prototypes for functions to process the
arguments in ARGV (ARGC of them, minus the program name) for
options given in OPTS. */
-# define __need_getopt
-# include <getopt.h>
+# include <bits/getopt_posix.h>
#endif
-#if defined __USE_UNIX98 || defined __USE_XOPEN2K
+#if defined __USE_XOPEN_EXTENDED || defined __USE_XOPEN2K
/* Put the name of the current host in no more than LEN bytes of NAME.
The result is null-terminated if LEN is large enough for the full
name and the terminator. */
@@ -1107,7 +1102,12 @@ extern int lockf64 (int __fd, int __cmd, __off64_t __len) __wur;
do __result = (long int) (expression); \
while (__result == -1L && errno == EINTR); \
__result; }))
-#endif
+
+/* Copy LENGTH bytes from INFD to OUTFD. */
+ssize_t copy_file_range (int __infd, __off64_t *__pinoff,
+ int __outfd, __off64_t *__poutoff,
+ size_t __length, unsigned int __flags);
+#endif /* __USE_GNU */
#if defined __USE_POSIX199309 || defined __USE_UNIX98
/* Synchronize at least the data part of a file with the underlying
@@ -1115,20 +1115,17 @@ extern int lockf64 (int __fd, int __cmd, __off64_t __len) __wur;
extern int fdatasync (int __fildes);
#endif /* Use POSIX199309 */
-
-/* XPG4.2 specifies that prototypes for the encryption functions must
- be defined here. */
-#ifdef __USE_XOPEN
-/* Encrypt at most 8 characters from KEY using salt to perturb DES. */
+#ifdef __USE_MISC
+/* One-way hash PHRASE, returning a string suitable for storage in the
+ user database. SALT selects the one-way function to use, and
+ ensures that no two users' hashes are the same, even if they use
+ the same passphrase. The return value points to static storage
+ which will be overwritten by the next call to crypt. */
extern char *crypt (const char *__key, const char *__salt)
__THROW __nonnull ((1, 2));
+#endif
-/* Encrypt data in BLOCK in place if EDFLAG is zero; otherwise decrypt
- block in place. */
-extern void encrypt (char *__glibc_block, int __edflag)
- __THROW __nonnull ((1));
-
-
+#ifdef __USE_XOPEN
/* Swab pairs bytes in the first N bytes of the area pointed to by
FROM and copy the result to TO. The value of TO must not be in the
range [FROM - N + 1, FROM - 1]. If N is odd the first byte in FROM
@@ -1138,14 +1135,32 @@ extern void swab (const void *__restrict __from, void *__restrict __to,
#endif
-/* The Single Unix specification demands this prototype to be here.
- It is also found in <stdio.h>. */
+/* Prior to Issue 6, the Single Unix Specification required these
+ prototypes to appear in this header. They are also found in
+ <stdio.h>. */
#if defined __USE_XOPEN && !defined __USE_XOPEN2K
/* Return the name of the controlling terminal. */
extern char *ctermid (char *__s) __THROW;
+
+/* Return the name of the current user. */
+extern char *cuserid (char *__s);
#endif
+/* Unix98 requires this function to be declared here. In other
+ standards it is in <pthread.h>. */
+#if defined __USE_UNIX98 && !defined __USE_XOPEN2K
+extern int pthread_atfork (void (*__prepare) (void),
+ void (*__parent) (void),
+ void (*__child) (void)) __THROW;
+#endif
+
+#ifdef __USE_MISC
+/* Write LENGTH bytes of randomness starting at BUFFER. Return 0 on
+ success or -1 on error. */
+int getentropy (void *__buffer, size_t __length) __wur;
+#endif
+
/* Define some macros helping to catch buffer overflows. */
#if __USE_FORTIFY_LEVEL > 0 && defined __fortify_function
# include <bits/unistd.h>
diff --git a/posix/vfork.c b/posix/vfork.c
index 84d33bc917..d4e76ad21e 100644
--- a/posix/vfork.c
+++ b/posix/vfork.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1992-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1992-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/posix/wait.c b/posix/wait.c
index 3abf30e675..379ab3267b 100644
--- a/posix/wait.c
+++ b/posix/wait.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -21,7 +21,7 @@
/* Wait for a child to die. When one does, put its status in *STAT_LOC
and return its process ID. For errors, return (pid_t) -1. */
__pid_t
-__wait (__WAIT_STATUS_DEFN stat_loc)
+__wait (int *stat_loc)
{
__set_errno (ENOSYS);
return -1;
diff --git a/posix/wait3.c b/posix/wait3.c
index 356839aef8..640ff05278 100644
--- a/posix/wait3.c
+++ b/posix/wait3.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -25,7 +25,7 @@
there. If the WUNTRACED bit is set in OPTIONS, return status for stopped
children; otherwise don't. */
pid_t
-__wait3 (__WAIT_STATUS_DEFN stat_loc, int options, struct rusage *usage)
+__wait3 (int *stat_loc, int options, struct rusage *usage)
{
if ((options & ~(WNOHANG|WUNTRACED)) != 0)
{
diff --git a/posix/wait4.c b/posix/wait4.c
index e5b03766f6..ab276c1955 100644
--- a/posix/wait4.c
+++ b/posix/wait4.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -20,8 +20,7 @@
#include <errno.h>
pid_t
-__wait4 (__pid_t pid, __WAIT_STATUS stat_loc, int options,
- struct rusage *usage)
+__wait4 (__pid_t pid, int *stat_loc, int options, struct rusage *usage)
{
__set_errno (ENOSYS);
return (pid_t) -1;
diff --git a/posix/waitid.c b/posix/waitid.c
index d213fff94d..5acee85983 100644
--- a/posix/waitid.c
+++ b/posix/waitid.c
@@ -1,5 +1,5 @@
/* Stub version of waitid.
- Copyright (C) 1997-2016 Free Software Foundation, Inc.
+ Copyright (C) 1997-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
diff --git a/posix/waitpid.c b/posix/waitpid.c
index 0105ea317d..9a31175699 100644
--- a/posix/waitpid.c
+++ b/posix/waitpid.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/posix/wordexp-test.c b/posix/wordexp-test.c
index 9e2f1b68de..cc29840355 100644
--- a/posix/wordexp-test.c
+++ b/posix/wordexp-test.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1997-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1997-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -22,20 +22,20 @@
#include <unistd.h>
#include <pwd.h>
#include <stdio.h>
+#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <wordexp.h>
-#include <libc-internal.h>
+#include <libc-pointer-arith.h>
+#include <dso_handle.h>
#define IFS " \n\t"
-extern void *__dso_handle __attribute__ ((__weak__, __visibility__ ("hidden")));
extern int __register_atfork (void (*) (void), void (*) (void), void (*) (void), void *);
static int __app_register_atfork (void (*prepare) (void), void (*parent) (void), void (*child) (void))
{
- return __register_atfork (prepare, parent, child,
- &__dso_handle == NULL ? NULL : __dso_handle);
+ return __register_atfork (prepare, parent, child, __dso_handle);
}
/* Number of forks seen. */
diff --git a/posix/wordexp-tst.sh b/posix/wordexp-tst.sh
index c52825b470..c6b6eb14ef 100755
--- a/posix/wordexp-tst.sh
+++ b/posix/wordexp-tst.sh
@@ -1,6 +1,6 @@
#!/bin/sh
# Test for wordexp(3).
-# Copyright (C) 1998-2016 Free Software Foundation, Inc.
+# Copyright (C) 1998-2018 Free Software Foundation, Inc.
# This file is part of the GNU C Library.
# The GNU C Library is free software; you can redistribute it and/or
diff --git a/posix/wordexp.c b/posix/wordexp.c
index ecc76156db..7548e0329f 100644
--- a/posix/wordexp.c
+++ b/posix/wordexp.c
@@ -1,5 +1,5 @@
/* POSIX.2 wordexp implementation.
- Copyright (C) 1997-2016 Free Software Foundation, Inc.
+ Copyright (C) 1997-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Tim Waugh <tim@cyberelk.demon.co.uk>.
@@ -17,7 +17,6 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
-#include <alloca.h>
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
@@ -41,6 +40,7 @@
#include <wchar.h>
#include <wordexp.h>
#include <kernel-features.h>
+#include <scratch_buffer.h>
#include <libc-lock.h>
#include <_itoa.h>
@@ -64,19 +64,16 @@ extern char **__libc_argv attribute_hidden;
static int parse_dollars (char **word, size_t *word_length, size_t *max_length,
const char *words, size_t *offset, int flags,
wordexp_t *pwordexp, const char *ifs,
- const char *ifs_white, int quoted)
- internal_function;
+ const char *ifs_white, int quoted);
static int parse_backtick (char **word, size_t *word_length,
size_t *max_length, const char *words,
size_t *offset, int flags, wordexp_t *pwordexp,
- const char *ifs, const char *ifs_white)
- internal_function;
+ const char *ifs, const char *ifs_white);
static int parse_dquote (char **word, size_t *word_length, size_t *max_length,
const char *words, size_t *offset, int flags,
wordexp_t *pwordexp, const char *ifs,
- const char *ifs_white)
- internal_function;
-static int eval_expr (char *expr, long int *result) internal_function;
+ const char *ifs_white);
+static int eval_expr (char *expr, long int *result);
/* The w_*() functions manipulate word lists. */
@@ -117,7 +114,6 @@ w_addchar (char *buffer, size_t *actlen, size_t *maxlen, char ch)
}
static char *
-internal_function
w_addmem (char *buffer, size_t *actlen, size_t *maxlen, const char *str,
size_t len)
{
@@ -144,7 +140,6 @@ w_addmem (char *buffer, size_t *actlen, size_t *maxlen, const char *str,
}
static char *
-internal_function
w_addstr (char *buffer, size_t *actlen, size_t *maxlen, const char *str)
/* (lengths exclude trailing zero) */
{
@@ -159,7 +154,6 @@ w_addstr (char *buffer, size_t *actlen, size_t *maxlen, const char *str)
}
static int
-internal_function
w_addword (wordexp_t *pwordexp, char *word)
{
/* Add a word to the wordlist */
@@ -200,7 +194,6 @@ no_space:
*/
static int
-internal_function
parse_backslash (char **word, size_t *word_length, size_t *max_length,
const char *words, size_t *offset)
{
@@ -229,7 +222,6 @@ parse_backslash (char **word, size_t *word_length, size_t *max_length,
}
static int
-internal_function
parse_qtd_backslash (char **word, size_t *word_length, size_t *max_length,
const char *words, size_t *offset)
{
@@ -272,7 +264,6 @@ parse_qtd_backslash (char **word, size_t *word_length, size_t *max_length,
}
static int
-internal_function
parse_tilde (char **word, size_t *word_length, size_t *max_length,
const char *words, size_t *offset, size_t wordc)
{
@@ -308,12 +299,7 @@ parse_tilde (char **word, size_t *word_length, size_t *max_length,
if (i == 1 + *offset)
{
/* Tilde appears on its own */
- uid_t uid;
- struct passwd pwd, *tpwd;
- int buflen = 1000;
char* home;
- char* buffer;
- int result;
/* POSIX.2 says ~ expands to $HOME and if HOME is unset the
results are unspecified. We do a lookup on the uid if
@@ -328,25 +314,38 @@ parse_tilde (char **word, size_t *word_length, size_t *max_length,
}
else
{
- uid = __getuid ();
- buffer = __alloca (buflen);
-
- while ((result = __getpwuid_r (uid, &pwd, buffer, buflen, &tpwd)) != 0
+ struct passwd pwd, *tpwd;
+ uid_t uid = __getuid ();
+ int result;
+ struct scratch_buffer tmpbuf;
+ scratch_buffer_init (&tmpbuf);
+
+ while ((result = __getpwuid_r (uid, &pwd,
+ tmpbuf.data, tmpbuf.length,
+ &tpwd)) != 0
&& errno == ERANGE)
- buffer = extend_alloca (buffer, buflen, buflen + 1000);
+ if (!scratch_buffer_grow (&tmpbuf))
+ return WRDE_NOSPACE;
if (result == 0 && tpwd != NULL && pwd.pw_dir != NULL)
{
*word = w_addstr (*word, word_length, max_length, pwd.pw_dir);
if (*word == NULL)
- return WRDE_NOSPACE;
+ {
+ scratch_buffer_free (&tmpbuf);
+ return WRDE_NOSPACE;
+ }
}
else
{
*word = w_addchar (*word, word_length, max_length, '~');
if (*word == NULL)
- return WRDE_NOSPACE;
+ {
+ scratch_buffer_free (&tmpbuf);
+ return WRDE_NOSPACE;
+ }
}
+ scratch_buffer_free (&tmpbuf);
}
}
else
@@ -354,13 +353,15 @@ parse_tilde (char **word, size_t *word_length, size_t *max_length,
/* Look up user name in database to get home directory */
char *user = strndupa (&words[1 + *offset], i - (1 + *offset));
struct passwd pwd, *tpwd;
- int buflen = 1000;
- char* buffer = __alloca (buflen);
int result;
+ struct scratch_buffer tmpbuf;
+ scratch_buffer_init (&tmpbuf);
- while ((result = __getpwnam_r (user, &pwd, buffer, buflen, &tpwd)) != 0
+ while ((result = __getpwnam_r (user, &pwd, tmpbuf.data, tmpbuf.length,
+ &tpwd)) != 0
&& errno == ERANGE)
- buffer = extend_alloca (buffer, buflen, buflen + 1000);
+ if (!scratch_buffer_grow (&tmpbuf))
+ return WRDE_NOSPACE;
if (result == 0 && tpwd != NULL && pwd.pw_dir)
*word = w_addstr (*word, word_length, max_length, pwd.pw_dir);
@@ -372,6 +373,8 @@ parse_tilde (char **word, size_t *word_length, size_t *max_length,
*word = w_addstr (*word, word_length, max_length, user);
}
+ scratch_buffer_free (&tmpbuf);
+
*offset = i - 1;
}
return *word ? 0 : WRDE_NOSPACE;
@@ -379,7 +382,6 @@ parse_tilde (char **word, size_t *word_length, size_t *max_length,
static int
-internal_function
do_parse_glob (const char *glob_word, char **word, size_t *word_length,
size_t *max_length, wordexp_t *pwordexp, const char *ifs,
const char *ifs_white)
@@ -436,7 +438,6 @@ do_parse_glob (const char *glob_word, char **word, size_t *word_length,
}
static int
-internal_function
parse_glob (char **word, size_t *word_length, size_t *max_length,
const char *words, size_t *offset, int flags,
wordexp_t *pwordexp, const char *ifs, const char *ifs_white)
@@ -532,7 +533,6 @@ tidy_up:
}
static int
-internal_function
parse_squote (char **word, size_t *word_length, size_t *max_length,
const char *words, size_t *offset)
{
@@ -554,7 +554,6 @@ parse_squote (char **word, size_t *word_length, size_t *max_length,
/* Functions to evaluate an arithmetic expression */
static int
-internal_function
eval_expr_val (char **expr, long int *result)
{
char *digit;
@@ -589,7 +588,6 @@ eval_expr_val (char **expr, long int *result)
}
static int
-internal_function
eval_expr_multdiv (char **expr, long int *result)
{
long int arg;
@@ -630,7 +628,6 @@ eval_expr_multdiv (char **expr, long int *result)
}
static int
-internal_function
eval_expr (char *expr, long int *result)
{
long int arg;
@@ -667,7 +664,6 @@ eval_expr (char *expr, long int *result)
}
static int
-internal_function
parse_arith (char **word, size_t *word_length, size_t *max_length,
const char *words, size_t *offset, int flags, int bracket)
{
@@ -817,7 +813,7 @@ parse_arith (char **word, size_t *word_length, size_t *max_length,
/* Function called by child process in exec_comm() */
static inline void
-internal_function __attribute__ ((always_inline))
+__attribute__ ((always_inline))
exec_comm_child (char *comm, int *fildes, int showerr, int noexec)
{
const char *args[4] = { _PATH_BSHELL, "-c", comm, NULL };
@@ -833,15 +829,8 @@ exec_comm_child (char *comm, int *fildes, int showerr, int noexec)
__close (fildes[1]);
}
else
- {
-#ifdef O_CLOEXEC
- /* Reset the close-on-exec flag (if necessary). */
-# ifndef __ASSUME_PIPE2
- if (__have_pipe2 > 0)
-# endif
- __fcntl (fildes[1], F_SETFD, 0);
-#endif
- }
+ /* Reset the close-on-exec flag (if necessary). */
+ __fcntl (fildes[1], F_SETFD, 0);
/* Redirect stderr to /dev/null if we have to. */
if (showerr == 0)
@@ -860,7 +849,7 @@ exec_comm_child (char *comm, int *fildes, int showerr, int noexec)
if (__builtin_expect (__fxstat64 (_STAT_VER, STDERR_FILENO, &st), 0) != 0
|| __builtin_expect (S_ISCHR (st.st_mode), 1) == 0
#if defined DEV_NULL_MAJOR && defined DEV_NULL_MINOR
- || st.st_rdev != makedev (DEV_NULL_MAJOR, DEV_NULL_MINOR)
+ || st.st_rdev != __gnu_dev_makedev (DEV_NULL_MAJOR, DEV_NULL_MINOR)
#endif
)
/* It's not the /dev/null device. Stop right here. The
@@ -882,7 +871,6 @@ exec_comm_child (char *comm, int *fildes, int showerr, int noexec)
/* Function to execute a command and retrieve the results */
/* pwordexp contains NULL if field-splitting is forbidden */
static int
-internal_function
exec_comm (char *comm, char **word, size_t *word_length, size_t *max_length,
int flags, wordexp_t *pwordexp, const char *ifs,
const char *ifs_white)
@@ -905,31 +893,8 @@ exec_comm (char *comm, char **word, size_t *word_length, size_t *max_length,
if (!comm || !*comm)
return 0;
-#ifdef O_CLOEXEC
-# ifndef __ASSUME_PIPE2
- if (__have_pipe2 >= 0)
-# endif
- {
- int r = __pipe2 (fildes, O_CLOEXEC);
-# ifndef __ASSUME_PIPE2
- if (__have_pipe2 == 0)
- __have_pipe2 = r != -1 || errno != ENOSYS ? 1 : -1;
-
- if (__have_pipe2 > 0)
-# endif
- if (r < 0)
- /* Bad */
- return WRDE_NOSPACE;
- }
-#endif
-#ifndef __ASSUME_PIPE2
-# ifdef O_CLOEXEC
- if (__have_pipe2 < 0)
-# endif
- if (__pipe (fildes) < 0)
- /* Bad */
- return WRDE_NOSPACE;
-#endif
+ if (__pipe2 (fildes, O_CLOEXEC) < 0)
+ return WRDE_NOSPACE;
again:
if ((pid = __fork ()) < 0)
@@ -1139,7 +1104,6 @@ no_space:
}
static int
-internal_function
parse_comm (char **word, size_t *word_length, size_t *max_length,
const char *words, size_t *offset, int flags, wordexp_t *pwordexp,
const char *ifs, const char *ifs_white)
@@ -1227,7 +1191,6 @@ parse_comm (char **word, size_t *word_length, size_t *max_length,
(memchr (char_set "", ch, sizeof (char_set) - 1) != NULL)
static int
-internal_function
parse_param (char **word, size_t *word_length, size_t *max_length,
const char *words, size_t *offset, int flags, wordexp_t *pwordexp,
const char *ifs, const char *ifs_white, int quoted)
@@ -2056,7 +2019,6 @@ do_error:
#undef CHAR_IN_SET
static int
-internal_function
parse_dollars (char **word, size_t *word_length, size_t *max_length,
const char *words, size_t *offset, int flags,
wordexp_t *pwordexp, const char *ifs, const char *ifs_white,
@@ -2115,7 +2077,6 @@ parse_dollars (char **word, size_t *word_length, size_t *max_length,
}
static int
-internal_function
parse_backtick (char **word, size_t *word_length, size_t *max_length,
const char *words, size_t *offset, int flags,
wordexp_t *pwordexp, const char *ifs, const char *ifs_white)
@@ -2179,7 +2140,6 @@ parse_backtick (char **word, size_t *word_length, size_t *max_length,
}
static int
-internal_function
parse_dquote (char **word, size_t *word_length, size_t *max_length,
const char *words, size_t *offset, int flags,
wordexp_t *pwordexp, const char * ifs, const char * ifs_white)
diff --git a/posix/wordexp.h b/posix/wordexp.h
index 92dfa9f067..8da64fb1a0 100644
--- a/posix/wordexp.h
+++ b/posix/wordexp.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or