diff options
author | Patrick J Volkerding <volkerdi@slackware.com> | 2013-11-04 17:08:47 +0000 |
---|---|---|
committer | Eric Hameleers <alien@slackware.com> | 2018-05-31 22:57:36 +0200 |
commit | 76fc4757ac91ac7947a01fb7b53dddf9a78a01d1 (patch) | |
tree | 9b98e6e193c7870cb27ac861394c1c4592850922 /source/ap/ksh93/patches | |
parent | 9664bee729d487bcc0a0bc35859f8e13d5421c75 (diff) | |
download | current-76fc4757ac91ac7947a01fb7b53dddf9a78a01d1.tar.gz |
Slackware 14.1slackware-14.1
Mon Nov 4 17:08:47 UTC 2013
Slackware 14.1 x86_64 stable is released!
It's been another interesting release cycle here at Slackware bringing
new features like support for UEFI machines, updated compilers and
development tools, the switch from MySQL to MariaDB, and many more
improvements throughout the system. Thanks to the team, the upstream
developers, the dedicated Slackware community, and everyone else who
pitched in to help make this release a reality.
The ISOs are off to be replicated, a 6 CD-ROM 32-bit set and a
dual-sided
32-bit/64-bit x86/x86_64 DVD. Please consider supporting the Slackware
project by picking up a copy from store.slackware.com. We're taking
pre-orders now, and offer a discount if you sign up for a subscription.
Have fun! :-)
Diffstat (limited to 'source/ap/ksh93/patches')
-rw-r--r-- | source/ap/ksh93/patches/ksh-20070328-builtins.patch | 32 | ||||
-rw-r--r-- | source/ap/ksh93/patches/ksh-20100826-fixregr.patch | 68 | ||||
-rw-r--r-- | source/ap/ksh93/patches/ksh-20120801-cdfix.patch | 14 | ||||
-rw-r--r-- | source/ap/ksh93/patches/ksh-20120801-cdfix2.patch | 25 | ||||
-rw-r--r-- | source/ap/ksh93/patches/ksh-20120801-tabfix.patch | 18 | ||||
-rw-r--r-- | source/ap/ksh93/patches/ksh-20130214-fixkill.patch | 21 | ||||
-rw-r--r-- | source/ap/ksh93/patches/rmdirfix.patch | 505 |
7 files changed, 683 insertions, 0 deletions
diff --git a/source/ap/ksh93/patches/ksh-20070328-builtins.patch b/source/ap/ksh93/patches/ksh-20070328-builtins.patch new file mode 100644 index 00000000..5c6b21c2 --- /dev/null +++ b/source/ap/ksh93/patches/ksh-20070328-builtins.patch @@ -0,0 +1,32 @@ +diff -up ksh-20120620/src/cmd/ksh93/data/builtins.c.builtins ksh-20120620/src/cmd/ksh93/data/builtins.c +--- ksh-20120620/src/cmd/ksh93/data/builtins.c.builtins 2012-06-19 10:02:12.000000000 +0200 ++++ ksh-20120620/src/cmd/ksh93/data/builtins.c 2012-06-22 12:35:05.587717588 +0200 +@@ -131,20 +131,28 @@ const struct shtable3 shtab_builtins[] = + #undef mktemp /* undo possible map-libc mktemp => _ast_mktemp */ + #include SHOPT_CMDLIB_HDR + #else ++#if 1 + CMDLIST(basename) + CMDLIST(chmod) + CMDLIST(dirname) + CMDLIST(getconf) + CMDLIST(head) ++#if 0 ++does not work when ACLs are used + CMDLIST(mkdir) ++#endif + CMDLIST(logname) ++#if 1 ++//does not work in chrooted environments, because /dev/fd/? is missing + CMDLIST(cat) ++#endif + CMDLIST(cmp) + CMDLIST(cut) + CMDLIST(uname) + CMDLIST(wc) + CMDLIST(sync) + #endif ++#endif + #if SHOPT_REGRESS + "__regress__", NV_BLTIN|BLT_ENV, bltin(__regress__), + #endif diff --git a/source/ap/ksh93/patches/ksh-20100826-fixregr.patch b/source/ap/ksh93/patches/ksh-20100826-fixregr.patch new file mode 100644 index 00000000..87cb13c6 --- /dev/null +++ b/source/ap/ksh93/patches/ksh-20100826-fixregr.patch @@ -0,0 +1,68 @@ +diff -up ksh-20120801/src/cmd/ksh93/tests/builtins.sh.fixregr ksh-20120801/src/cmd/ksh93/tests/builtins.sh +--- ksh-20120801/src/cmd/ksh93/tests/builtins.sh.fixregr 2012-07-16 17:23:56.000000000 +0200 ++++ ksh-20120801/src/cmd/ksh93/tests/builtins.sh 2012-08-08 12:29:00.733243019 +0200 +@@ -303,9 +303,9 @@ then err_exit "printf '%..*s' not workin + fi + [[ $(printf '%q\n') == '' ]] || err_exit 'printf "%q" with missing arguments' + # we won't get hit by the one second boundary twice, right? +-[[ $(printf '%T\n' now) == "$(date)" ]] || +-[[ $(printf '%T\n' now) == "$(date)" ]] || +-err_exit 'printf "%T" now' ++[[ $(printf '%T\n' now | sed 's/GMT/UTC/') == "$(date)" ]] || ++[[ $(printf '%T\n' now | sed 's/GMT/UTC/') == "$(date)" ]] || ++err_exit 'printf "%T" now = '"$(printf '%T\n' now) != $(date)" + behead() + { + read line +diff -up ksh-20120801/src/cmd/ksh93/tests/locale.sh.fixregr ksh-20120801/src/cmd/ksh93/tests/locale.sh +--- ksh-20120801/src/cmd/ksh93/tests/locale.sh.fixregr 2012-06-26 21:57:46.000000000 +0200 ++++ ksh-20120801/src/cmd/ksh93/tests/locale.sh 2012-08-08 12:29:20.039405240 +0200 +@@ -104,6 +104,7 @@ if (( $($SHELL -c $'export LC_ALL='$loca + then LC_ALL=$locale $SHELL -c b1=$'"\342\202\254\342\202\254\342\202\254\342\202\254w\342\202\254\342\202\254\342\202\254\342\202\254"; [[ ${b1:4:1} == w ]]' || err_exit 'multibyte ${var:offset:len} not working correctly' + fi + ++locale=en_US.UTF-8 + #$SHELL -c 'export LANG='$locale'; printf "\u[20ac]\u[20ac]" > $tmp/two_euro_chars.txt' + printf $'\342\202\254\342\202\254' > $tmp/two_euro_chars.txt + exp="6 2 6" +@@ -111,11 +112,11 @@ set -- $($SHELL -c " + unset LC_CTYPE + export LANG=$locale + export LC_ALL=C +- command wc -C < $tmp/two_euro_chars.txt ++ command wc -m < $tmp/two_euro_chars.txt + unset LC_ALL +- command wc -C < $tmp/two_euro_chars.txt ++ command wc -m < $tmp/two_euro_chars.txt + export LC_ALL=C +- command wc -C < $tmp/two_euro_chars.txt ++ command wc -m < $tmp/two_euro_chars.txt + ") + got=$* + [[ $got == $exp ]] || err_exit "command wc LC_ALL default failed -- expected '$exp', got '$got'" +@@ -134,6 +135,8 @@ set -- $($SHELL -c " + got=$* + [[ $got == $exp ]] || err_exit "builtin wc LC_ALL default failed -- expected '$exp', got '$got'" + ++locale=C_EU.UTF-8 ++ + # multibyte char straddling buffer boundary + + { +@@ -190,6 +193,7 @@ do exp=$1 + done + + # setocale(LC_ALL,"") after setlocale() initialization ++locale=en_US.UTF-8 + + printf 'f1\357\274\240f2\n' > input1 + printf 't2\357\274\240f1\n' > input2 +@@ -336,7 +340,7 @@ then LC_ALL=en_US.UTF-8 + [[ $(print -r -- "$x") == $'hello\u[20ac]\xee world' ]] || err_exit '%q with unicode and non-unicode not working' + if [[ $(whence od) ]] + then got='68 65 6c 6c 6f e2 82 ac ee 20 77 6f 72 6c 64 0a' +- [[ $(print -r -- "$x" | od -An -tx1) == "$got" ]] || err_exit "incorrect string from printf %q" ++ [[ $(print -r -- "$x" | od -An -tx1) =~ $got ]] || err_exit "incorrect string from printf %q" + fi + + fi diff --git a/source/ap/ksh93/patches/ksh-20120801-cdfix.patch b/source/ap/ksh93/patches/ksh-20120801-cdfix.patch new file mode 100644 index 00000000..59265dda --- /dev/null +++ b/source/ap/ksh93/patches/ksh-20120801-cdfix.patch @@ -0,0 +1,14 @@ +diff -up ksh-20120801/src/cmd/ksh93/bltins/cd_pwd.c.cdfix ksh-20120801/src/cmd/ksh93/bltins/cd_pwd.c +--- ksh-20120801/src/cmd/ksh93/bltins/cd_pwd.c.cdfix 2013-02-01 16:04:55.507150242 +0100 ++++ ksh-20120801/src/cmd/ksh93/bltins/cd_pwd.c 2013-02-01 16:06:39.361007641 +0100 +@@ -214,7 +214,10 @@ int b_cd(int argc, char *argv[],Shbltin_ + if(*++dp=='.' && (*++dp=='/' || *dp==0)) + n++; + else if(*dp && *dp!='/') ++ { ++ dp--; + break; ++ } + if(*dp==0) + break; + } diff --git a/source/ap/ksh93/patches/ksh-20120801-cdfix2.patch b/source/ap/ksh93/patches/ksh-20120801-cdfix2.patch new file mode 100644 index 00000000..84bb4912 --- /dev/null +++ b/source/ap/ksh93/patches/ksh-20120801-cdfix2.patch @@ -0,0 +1,25 @@ +diff -up ksh-20120801/src/cmd/ksh93/bltins/cd_pwd.c.cdfix2 ksh-20120801/src/cmd/ksh93/bltins/cd_pwd.c +--- ksh-20120801/src/cmd/ksh93/bltins/cd_pwd.c.cdfix2 2013-02-01 16:46:50.441771371 +0100 ++++ ksh-20120801/src/cmd/ksh93/bltins/cd_pwd.c 2013-02-01 16:57:43.241784024 +0100 +@@ -61,6 +61,7 @@ int sh_diropenat(Shell_t *shp, int dir, + { + int fd,shfd; + int savederrno=errno; ++ struct stat fs; + #ifndef AT_FDCWD + NOT_USED(dir); + #endif +@@ -133,6 +134,13 @@ int sh_diropenat(Shell_t *shp, int dir, + + if(fd < 0) + return fd; ++ ++ if (!fstat(fd, &fs) && !S_ISDIR(fs.st_mode)) ++ { ++ close(fd); ++ errno = ENOTDIR; ++ return -1; ++ } + + /* Move fd to a number > 10 and *register* the fd number with the shell */ + shfd = sh_fcntl(fd, F_dupfd_cloexec, 10); diff --git a/source/ap/ksh93/patches/ksh-20120801-tabfix.patch b/source/ap/ksh93/patches/ksh-20120801-tabfix.patch new file mode 100644 index 00000000..962763ed --- /dev/null +++ b/source/ap/ksh93/patches/ksh-20120801-tabfix.patch @@ -0,0 +1,18 @@ +diff -up ksh-20120801/src/cmd/ksh93/edit/emacs.c.tabfix ksh-20120801/src/cmd/ksh93/edit/emacs.c +--- ksh-20120801/src/cmd/ksh93/edit/emacs.c.tabfix 2012-07-17 22:44:44.000000000 +0200 ++++ ksh-20120801/src/cmd/ksh93/edit/emacs.c 2013-03-07 15:58:59.902161711 +0100 +@@ -1011,10 +1011,13 @@ static int escape(register Emacs_t* ep,r + ep->ed->e_tabcount=0; + else + { ++ int oldi = i; + i=ed_getchar(ep->ed,0); + ed_ungetchar(ep->ed,i); +- if(isdigit(i)) ++ if(isdigit(i) && oldi=='=') + ed_ungetchar(ep->ed,ESC); ++ else if (isdigit(i) || i=='\t') ++ ep->ed->e_tabcount=0; + } + } + else diff --git a/source/ap/ksh93/patches/ksh-20130214-fixkill.patch b/source/ap/ksh93/patches/ksh-20130214-fixkill.patch new file mode 100644 index 00000000..0862880d --- /dev/null +++ b/source/ap/ksh93/patches/ksh-20130214-fixkill.patch @@ -0,0 +1,21 @@ +diff -up ksh-20130214/src/cmd/ksh93/sh/jobs.c.fixkill ksh-20130214/src/cmd/ksh93/sh/jobs.c +--- ksh-20130214/src/cmd/ksh93/sh/jobs.c.fixkill 2012-09-26 17:43:04.000000000 +0200 ++++ ksh-20130214/src/cmd/ksh93/sh/jobs.c 2013-02-22 16:38:05.080161740 +0100 +@@ -1104,6 +1104,8 @@ static struct process *job_bystring(regi + + int job_kill(register struct process *pw,register int sig) + { ++ if(pw==0) ++ goto error; + Shell_t *shp = pw->p_shp; + register pid_t pid; + register int r; +@@ -1127,8 +1129,6 @@ int job_kill(register struct process *pw + #endif /* SIGTSTP */ + job_lock(); + errno = ECHILD; +- if(pw==0) +- goto error; + pid = pw->p_pid; + #if SHOPT_COSHELL + if(pw->p_cojob) diff --git a/source/ap/ksh93/patches/rmdirfix.patch b/source/ap/ksh93/patches/rmdirfix.patch new file mode 100644 index 00000000..132de7db --- /dev/null +++ b/source/ap/ksh93/patches/rmdirfix.patch @@ -0,0 +1,505 @@ +diff -up ksh20120801/src/cmd/ksh93/sh/subshell.c.orig ksh20120801/src/cmd/ksh93/sh/subshell.c +--- ksh20120801/src/cmd/ksh93/sh/subshell.c.orig 2012-07-17 23:54:21.000000000 +0200 ++++ ksh20120801/src/cmd/ksh93/sh/subshell.c 2012-10-24 15:03:44.436870792 +0200 +@@ -40,14 +40,6 @@ + # define PIPE_BUF 512 + #endif + +-#ifndef O_SEARCH +-# ifdef O_PATH +-# define O_SEARCH O_PATH +-# else +-# define O_SEARCH 0 +-# endif +-#endif +- + /* + * Note that the following structure must be the same + * size as the Dtlink_t structure +@@ -84,7 +76,7 @@ static struct subshell + char *pwd; /* present working directory */ + const char *shpwd; /* saved pointer to sh.pwd */ + void *jobs; /* save job info */ +- int pwdfd; /* file descritor for pwd */ ++ int shpwdfd;/* fd for present working directory */ + mode_t mask; /* saved umask */ + short tmpfd; /* saved tmp file descriptor */ + short pipefd; /* read fd if pipe is created */ +@@ -101,7 +93,6 @@ static struct subshell + int subdup; + char subshare; + char comsub; +- char pwdclose; + #if SHOPT_COSHELL + void *coshell; + #endif /* SHOPT_COSHELL */ +@@ -518,7 +509,6 @@ Sfio_t *sh_subshell(Shell_t *shp,Shnode_ + shp->pathinit = 0; + } + sp->pathlist = path_dup((Pathcomp_t*)shp->pathlist); +- sp->pwdfd = -1; + if(!shp->pwd) + path_pwd(shp,0); + sp->bckpid = shp->bckpid; +@@ -531,39 +521,14 @@ Sfio_t *sh_subshell(Shell_t *shp,Shnode_ + shp->subshare = comsub==2 || (comsub==1 && sh_isoption(SH_SUBSHARE)); + if(comsub) + shp->comsub = comsub; ++ sp->shpwdfd=-1; + if(!comsub || !shp->subshare) + { +- struct subshell *xp; + sp->shpwd = shp->pwd; +-#ifdef _lib_fchdir +- for(xp=sp->prev; xp; xp=xp->prev) +- { +- if(xp->pwdfd>0 && strcmp(xp->pwd,shp->pwd)==0) +- { +- sp->pwdfd = xp->pwdfd; +- break; +- } +- } +- if(sp->pwdfd<0) +- { +- int n = open(".",O_RDONLY); +- if(O_SEARCH && errno==EACCES) +- n = open(".",O_RDONLY); +- if(n>=0) +- { +- sp->pwdfd = n; +- if(n<10) +- { +- sp->pwdfd = fcntl(n,F_DUPFD,10); +- close(n); +- } +- if(sp->pwdfd>0) +- { +- fcntl(sp->pwdfd,F_SETFD,FD_CLOEXEC); +- sp->pwdclose = 1; +- } +- } +- } ++ sp->shpwdfd=((shp->pwdfd >= 0))?sh_fcntl(shp->pwdfd, F_dupfd_cloexec, 10):-1; ++#ifdef O_SEARCH ++ if(sp->shpwdfd<0) ++ errormsg(SH_DICT,ERROR_system(1), "Can't obtain directory fd."); + #endif + sp->pwd = (shp->pwd?strdup(shp->pwd):0); + sp->mask = shp->mask; +@@ -741,14 +706,11 @@ Sfio_t *sh_subshell(Shell_t *shp,Shnode_ + Namval_t *pwdnod = sh_scoped(shp,PWDNOD); + if(shp->pwd) + { +- if(sp->pwdfd >=0) +- { +- if(fchdir(sp->pwdfd)<0) +- chdir(sp->pwd); +- } +- else +- chdir(sp->pwd); + shp->pwd=sp->pwd; ++#ifndef O_SEARCH ++ if (sp->shpwdfd < 0) ++ chdir(shp->pwd); ++#endif + path_newdir(shp,shp->pathlist); + } + if(nv_isattr(pwdnod,NV_NOFREE)) +@@ -762,8 +724,6 @@ Sfio_t *sh_subshell(Shell_t *shp,Shnode_ + } + else + free((void*)sp->pwd); +- if(sp->pwdclose) +- close(sp->pwdfd); + if(sp->mask!=shp->mask) + umask(shp->mask=sp->mask); + if(shp->coutpipe!=sp->coutpipe) +@@ -775,6 +735,13 @@ Sfio_t *sh_subshell(Shell_t *shp,Shnode_ + shp->cpipe[1] = sp->cpipe; + shp->coutpipe = sp->coutpipe; + } ++ if(sp->shpwdfd >=0) ++ { ++ if(shp->pwdfd >=0) ++ sh_close(shp->pwdfd); ++ shp->pwdfd=sp->shpwdfd; ++ fchdir(shp->pwdfd); ++ } + shp->subshare = sp->subshare; + shp->comsub = sp->comsub; + shp->subdup = sp->subdup; +diff -up ksh-20120801/src/cmd/ksh93/bltins/cd_pwd.c.orig ksh-20120801/src/cmd/ksh93/bltins/cd_pwd.c +--- ksh-20120801/src/cmd/ksh93/bltins/cd_pwd.c.orig 2012-08-02 16:50:40.000000000 +0200 ++++ ksh-20120801/src/cmd/ksh93/bltins/cd_pwd.c 2012-10-24 15:37:46.814469045 +0200 +@@ -38,6 +38,10 @@ + #include "builtins.h" + #include <ls.h> + ++#ifndef EINTR_REPEAT ++# define EINTR_REPEAT(expr) while((expr) && (errno == EINTR)) errno=0; ++#endif ++ + /* + * Invalidate path name bindings to relative paths + */ +@@ -49,6 +53,95 @@ static void rehash(register Namval_t *np + _nv_unset(np,0); + } + ++/* ++ * Obtain a file handle to the directory "path" relative to directory ++ * "dir", or open a NFSv4 xattr directory handle for file dir/path. ++ */ ++int sh_diropenat(Shell_t *shp, int dir, const char *path, bool xattr) ++{ ++ int fd,shfd; ++ int savederrno=errno; ++#ifndef AT_FDCWD ++ NOT_USED(dir); ++#endif ++#ifndef O_XATTR ++ NOT_USED(xattr); ++#endif ++ ++#ifdef O_XATTR ++ if(xattr) ++ { ++ int apfd; /* attribute parent fd */ ++ /* open parent node... */ ++ EINTR_REPEAT((apfd = openat(dir, path, O_RDONLY|O_NONBLOCK|O_cloexec)) < 0); ++ if(apfd < 0) ++ return -1; ++ ++ /* ... and then open a fd to the attribute directory */ ++ EINTR_REPEAT((fd = openat(apfd, e_dot, O_XATTR|O_cloexec)) < 0); ++ ++ savederrno = errno; ++ EINTR_REPEAT(close(apfd) < 0); ++ errno = savederrno; ++ } ++ else ++#endif ++ { ++#ifdef AT_FDCWD ++ /* ++ * Open directory. First we try without |O_SEARCH| and ++ * if this fails with EACCESS we try with |O_SEARCH| ++ * again. ++ * This is required ... ++ * - ... because some platforms may require that it can ++ * only be used for directories while some filesystems ++ * (e.g. Reiser4 or HSM systems) allow a |fchdir()| into ++ * files, too) ++ * - ... to preserve the semantics of "cd", e.g. ++ * otherwise "cd" would return [No access] instead of ++ * [Not a directory] for files on filesystems which do ++ * not allow a "cd" into files. ++ * - ... to allow that a ++ * $ redirect {n}</etc ; cd /dev/fd/$n # works on most ++ * platforms. ++ */ ++ EINTR_REPEAT((fd = openat(dir, path, O_RDONLY|O_NONBLOCK|O_cloexec)) < 0); ++# ifdef O_SEARCH ++ if((fd < 0) && (errno == EACCES)) ++ { ++ EINTR_REPEAT((fd = openat(dir, path, O_SEARCH|O_cloexec)) < 0) ++ } ++# endif ++#else ++ /* ++ * Version of openat() call above for systems without ++ * openat API. This only works because we basically ++ * gurantee that |dir| is always the same place as ++ * |cwd| on such machines (but this won't be the case ++ * in the future). ++ */ ++ /* ++ * This |fchdir()| call is not needed (yet) since ++ * all consumers do not use |dir| when |AT_FDCWD| ++ * is not available. ++ * ++ * fchdir(dir); ++ */ ++ EINTR_REPEAT((fd = open(path, O_cloexec)) < 0); ++#endif ++ } ++ ++ if(fd < 0) ++ return fd; ++ ++ /* Move fd to a number > 10 and *register* the fd number with the shell */ ++ shfd = sh_fcntl(fd, F_dupfd_cloexec, 10); ++ savederrno=errno; ++ sh_close(fd); ++ errno=savederrno; ++ return(shfd); ++} ++ + int b_cd(int argc, char *argv[],Shbltin_t *context) + { + register char *dir; +@@ -56,18 +149,20 @@ int b_cd(int argc, char *argv[],Shbltin_ + register const char *dp; + register Shell_t *shp = context->shp; + int saverrno=0; +- int rval,flag=0; ++ int rval; ++ bool flag=false,xattr=false; + char *oldpwd; ++ int newdirfd; + Namval_t *opwdnod, *pwdnod; + if(sh_isoption(SH_RESTRICTED)) + errormsg(SH_DICT,ERROR_exit(1),e_restricted+4); + while((rval = optget(argv,sh_optcd))) switch(rval) + { + case 'L': +- flag = 0; ++ flag = false; + break; + case 'P': +- flag = 1; ++ flag = true; + break; + case ':': + errormsg(SH_DICT,2, "%s", opt_info.arg); +@@ -179,14 +274,72 @@ int b_cd(int argc, char *argv[],Shbltin_ + continue; + #endif /* SHOPT_FS_3D */ + } ++ rval = newdirfd = sh_diropenat(shp, shp->pwdfd, ++ path_relative(shp,stakptr(PATH_OFFSET)), xattr); ++ if(newdirfd >=0) ++ { ++ /* chdir for directories on HSM/tapeworms may take minutes */ ++ if(fchdir(newdirfd) >= 0) ++ { ++ if(shp->pwdfd >= 0) ++ sh_close(shp->pwdfd); ++ shp->pwdfd=newdirfd; ++ goto success; ++ } ++ } ++#ifndef O_SEARCH ++ else ++ { + if((rval=chdir(path_relative(shp,stakptr(PATH_OFFSET)))) >= 0) +- goto success; +- if(errno!=ENOENT && saverrno==0) ++ { ++ if(shp->pwdfd >= 0) ++ { ++ sh_close(shp->pwdfd); ++#ifdef AT_FDCWD ++ shp->pwdfd = AT_FDCWD; ++#else ++ shp->pwdfd = -1; ++#endif ++ } ++ } ++ } ++#endif ++ if(saverrno==0) + saverrno=errno; ++ if(newdirfd >=0) ++ sh_close(newdirfd); + } + while(cdpath); + if(rval<0 && *dir=='/' && *(path_relative(shp,stakptr(PATH_OFFSET)))!='/') +- rval = chdir(dir); ++ { ++ rval = newdirfd = sh_diropenat(shp, ++ shp->pwdfd, ++ dir, xattr); ++ if(newdirfd >=0) ++ { ++ /* chdir for directories on HSM/tapeworms may take minutes */ ++ if(fchdir(newdirfd) >= 0) ++ { ++ if(shp->pwdfd >= 0) ++ sh_close(shp->pwdfd); ++ shp->pwdfd=newdirfd; ++ goto success; ++ } ++ } ++#ifndef O_SEARCH ++ else ++ { ++ if(chdir(dir) >=0) ++ { ++ if(shp->pwdfd >= 0) ++ { ++ sh_close(shp->pwdfd); ++ shp->pwdfd=-1; ++ } ++ } ++ } ++#endif ++ } + /* use absolute chdir() if relative chdir() fails */ + if(rval<0) + { +@@ -213,7 +366,7 @@ success: + if(*dir != '/') + return(0); + nv_putval(opwdnod,oldpwd,NV_RDONLY); +- flag = strlen(dir); ++ flag = (strlen(dir)>0)?true:false; + /* delete trailing '/' */ + while(--flag>0 && dir[flag]=='/') + dir[flag] = 0; +diff -up ksh-20120801/src/cmd/ksh93/include/shell.h.orig ksh-20120801/src/cmd/ksh93/include/shell.h +--- ksh-20120801/src/cmd/ksh93/include/shell.h.orig 2012-07-17 22:07:40.000000000 +0200 ++++ ksh-20120801/src/cmd/ksh93/include/shell.h 2012-10-24 15:42:10.756987230 +0200 +@@ -145,6 +145,7 @@ struct Shell_s + unsigned char trapnote; /* set when trap/signal is pending */ + char shcomp; /* set when runing shcomp */ + short subshell; /* set for virtual subshell */ ++ int pwdfd; /* file descriptor for pwd */ + #ifdef _SH_PRIVATE + _SH_PRIVATE + #endif /* _SH_PRIVATE */ +diff -up ksh-20120801/src/cmd/ksh93/sh/init.c.orig ksh-20120801/src/cmd/ksh93/sh/init.c +--- ksh-20120801/src/cmd/ksh93/sh/init.c.orig 2012-05-11 19:19:10.000000000 +0200 ++++ ksh-20120801/src/cmd/ksh93/sh/init.c 2012-10-24 15:31:59.659485151 +0200 +@@ -1365,6 +1365,18 @@ Shell_t *sh_init(register int argc,regis + } + } + sh_ioinit(shp); ++#ifdef AT_FDCWD ++ shp->pwdfd = sh_diropenat(shp, AT_FDCWD, e_dot, false); ++#else ++ /* Systems without AT_FDCWD/openat() do not use the |dir| argument */ ++ shp->pwdfd = sh_diropenat(shp, -1, e_dot, false); ++#endif ++#ifdef O_SEARCH ++ /* This should _never_ happen, guranteed by design and goat sacrifice */ ++ if(shp->pwdfd < 0) ++ errormsg(SH_DICT,ERROR_system(1), "Can't obtain directory fd."); ++#endif ++ + /* initialize signal handling */ + sh_siginit(shp); + stakinstall(NIL(Stak_t*),nospace); +diff -up ksh-20120801/src/cmd/ksh93/sh/xec.c.orig ksh-20120801/src/cmd/ksh93/sh/xec.c +--- ksh-20120801/src/cmd/ksh93/sh/xec.c.orig 2012-07-23 16:49:32.000000000 +0200 ++++ ksh-20120801/src/cmd/ksh93/sh/xec.c 2012-10-24 15:35:02.209539671 +0200 +@@ -1348,8 +1348,12 @@ int sh_exec(register const Shnode_t *t, + { + if(!shp->pwd) + path_pwd(shp,0); +- if(shp->pwd) +- stat(".",&statb); ++#ifndef O_SEARCH ++ else if (shp->pwdfd>=0) ++ fstat(shp->pwdfd,&statb); ++ else if (shp->pwd) ++ stat(e_dot,&statb); ++#endif + sfsync(NULL); + share = sfset(sfstdin,SF_SHARE,0); + sh_onstate(SH_STOPOK); +@@ -1428,14 +1432,32 @@ int sh_exec(register const Shnode_t *t, + sh_offstate(SH_NOFORK); + if(!(nv_isattr(np,BLT_ENV))) + { +- if(shp->pwd) ++#ifdef O_SEARCH ++ while((fchdir(shp->pwdfd) < 0) && errno==EINTR) ++ errno = 0; ++#else ++ if(shp->pwd || (shp->pwdfd >= 0)) + { + struct stat stata; + stat(".",&stata); + /* restore directory changed */ + if(statb.st_ino!=stata.st_ino || statb.st_dev!=stata.st_dev) +- chdir(shp->pwd); ++ { ++ /* chdir for directories on HSM/tapeworms may take minutes */ ++ int err=errno; ++ if(shp->pwdfd >= 0) ++ { ++ while((fchdir(shp->pwdfd) < 0) && errno==EINTR) ++ errno = err; ++ } ++ else ++ { ++ while((chdir(shp->pwd) < 0) && errno==EINTR) ++ errno = err; ++ } ++ } + } ++#endif /* O_SEARCH */ + sh_offstate(SH_STOPOK); + if(share&SF_SHARE) + sfset(sfstdin,SF_PUBLIC|SF_SHARE,1); +diff -up ksh-20120801/src/lib/libast/features/common.orig ksh-20120801/src/lib/libast/features/common +--- ksh-20120801/src/lib/libast/features/common.orig 2011-12-12 20:55:33.000000000 +0100 ++++ ksh-20120801/src/lib/libast/features/common 2012-10-24 15:54:35.433885131 +0200 +@@ -463,6 +463,66 @@ typ uintptr_t stdint.h inttypes.h no{ + typedef unsigned _ast_int4_t uintptr_t; + #endif + }end ++typ _Bool = uint8_t ++cat{ ++ #if defined(_STDC_C99) || __STDC_VERSION__ >= 199901L ++ #include <stdbool.h> ++ #else ++ #define bool _Bool ++ #define false 0 ++ #define true 1 ++ #endif ++}end ++tst key __thread -lpthread note{ __thread keyword exists and works with -lpthread }end execute{ ++ #include <pthread.h> ++ ++ #define INITIAL 1 ++ #define LOOP 100 ++ ++ static __thread int specific = INITIAL; ++ static int global = 0; ++ ++ static void* worker(void* arg) ++ { ++ int k; ++ int v; ++ v = (int)(arg - 0); ++ for (k = 0; k < LOOP; ++k) ++ { ++ specific += v; ++ usleep(1); ++ } ++ if (specific != (INITIAL + LOOP * v)) ++ global = 1; ++ return 0; ++ } ++ int main() ++ { ++ pthread_t th[2]; ++ ++ if (pthread_create(&th[0], 0, worker, (void*)0 + 5) || ++ pthread_create(&th[1], 0, worker, (void*)0 + 7)) ++ { ++ NOTE("pthread_create failed"); ++ return 1; ++ } ++ pthread_join(th[0], 0); ++ pthread_join(th[1], 0); ++ if (global) ++ { ++ NOTE("__thread variable not thread specific"); ++ return 1; ++ } ++ if (specific != INITIAL) ++ { ++ NOTE("main __thread variable changed by another thread"); ++ return 1; ++ } ++ return 0; ++ } ++}end no{ ++ #define __thread /* __thread keyword does not exist or does not work with -lpthread */ ++}end + + tst - -DTRY=1 - -DTRY=1 -Dvoid=char - -DTRY=2 - -DTRY=3 - -DTRY=4 output{ + #if _STD_ && _hdr_stdarg |