2013/6/28 Glenn Fowler <[email protected]>:
>
> the AT&T Software Technology ast alpha 2013-06-28 source release
> has been posted to the download site
> http://www.research.att.com/sw/download/alpha/
> the package names and md5 checksums are
> INIT eddbf89d061348519d86f2618b708a94
> ast-base a745a7d4ce6f53c2e4134af4cc835ff7
> ast-open fdb74839ff041e34c800c333188a050e
> ast-ksh 8f22428cf30af7146bd210664c2fd166
> the md5 sums should match the ones listed on the download page
>
> NOTE NOTE NOTE NOTE NOTE NOTE
>
> (*) *at() emulations for systems that need it
> (*) O_CLOEXEC F_DUPFD_CLOEXEC SOCK_CLOEXEC
> (*) accept4 pipe2
> (*) syscall restart on EINTR controlled by astserial(AST_SERIAL_RESTART,op)
> (*) REALLY IMPORTANT: works on modern linux, some problems on solaris
> REASON: one of the ast team will not be logging on for 16 days and
> didn't have time left to figure out the solaris problems
> most likely in one of these
> src/lib/libast/comp/at.c
> src/lib/libast/port/intercept.c
> figuring that out left as a summer homework assignment
Homework more or less done for Solaris (including |O_XATTR|/|O_SEARCH|
support) and fixing Linux's |O_PATH| support... the prototype patch is
attached as "astksh20130628_solaris_fixes001.diff.txt".
**Notes:
* Please please leave the comments about |O_PATH| and |#define
__USE_GNU 1| in src/lib/libast/features/fcntl.c intact. They are there
for a very good reason (mostly to bypass bugs in the Linux #includes).
I really don't want to hunt for ghost bugs over and over again.
The core part is this one:
-- snip --
- printf("#define O_SEARCH O_PATH\n");
+ /*
+ * O_PATH is a Linux's variation of O_SEARCH. Since this is treated
+ * as extension it may not be available without _GNU_SOURCE.
+ * Even even with _GNU_SOURCE some Linux platforms have bugs in their
+ * headers which prevents the definition of O_PATH in some hideous
+ * cases. To prevent all this mess we just grab the octal value and
+ * define it as O_SEARCH.
+ * Do not change this. You'll end-up in hell, together with the Linux
+ * headers. Quickly.
+ */
+ printf("#define O_SEARCH 0%o\n", (int)O_PATH);
-- snip --
Please please don't change that... otherwise |O_PATH| is *NOT*
available in libast&&co. This is the 4th time I'm fixing this. Again.
;-((
* Solaris didn't work because...
1. ... newer versions have many more |O_*|-flags for |open()|,
including |O_EXEC| and |O_SEARCH|. The same issue applied to the |F_*|
flags (I only added the |F_*| flags with the highest numbers in
Solaris 9/10/11/11.1 like |F_BADFD| ... maybe other platforms require
more "love" in this area...) ...
2. ... -lgen was missing when |eaccess()| is used... but...
3. ... why do we have to use |eaccess()| when |faccess()| is available ?
Remember that modern platforms (like Solaris >= 11) revamped their
syscalls and now map the "old" filesystem calls all to their |*at()|
version, e.g. ...
-- snip --
/* |open()| argument |flags| is part of |__VA_ARGS__| since
|__VA_ARGS__| must never be empty */
#define open(path, ...) openat(AST_AT_GET_FDCWD, (path),
__VA_ARGS__)
#define creat(path, ...) openat(AST_AT_GET_FDCWD, (path),
O_WRONLY|O_CREAT|O_TRUNC, __VA_ARGS__)
#define unlink(path) unlinkat(AST_AT_GET_FDCWD, (path), 0)
#define rmdir(path) unlinkat(AST_AT_GET_FDCWD, (path),
AT_REMOVEDIR)
#define chown(path, uid, gid) fchownat(AST_AT_GET_FDCWD, (path),
(uid), (gid), 0)
#define lchown(path, uid, gid) fchownat(AST_AT_GET_FDCWD, (path),
(uid), (gid), AT_SYMLINK_NOFOLLOW)
#define fchown(fd, uid, gid) fchownat((fd), NULL, (uid), (gid), 0)
#define stat(path, sb) fstatat(AST_AT_GET_FDCWD, (path), (sb),
0)
#define lstat(path, sb) fstatat(AST_AT_GET_FDCWD, (path), (sb),
AT_SYMLINK_NOFOLLOW)
#define fstat(fd, sb) fstatat((fd), NULL, (sb), 0)
#define rename(oldname, newname) renameat(AST_AT_GET_FDCWD, (oldname),
AST_AT_GET_FDCWD, (newname))
#define access(path, amode) faccessat(AST_AT_GET_FDCWD, (path),
(amode), 0)
#define eaccess(path, amode) faccessat(AST_AT_GET_FDCWD, (path),
(amode), AT_EACCESS)
#define mkdir(path, amode) mkdirat(AST_AT_GET_FDCWD, (path),
(amode))
#define mkfifo(path, amode) mkfifoat(AST_AT_GET_FDCWD, (path),
(amode))
#define mknod(path, amode, adev) mknodat(AST_AT_GET_FDCWD, (path),
(amode), (adev))
#define readlink(path, buf, bufsize) readlinkat(AST_AT_GET_FDCWD,
(path), (buf), (bufsize))
#define symlink(oldpath, newpath) symlinkat((oldpath),
AST_AT_GET_FDCWD, (newpath))
-- snip --
* I still have to warm-up with the new syscall restart API. Some
things with trouble me:
- The restart option (as all other signal-related stuff) must be
per-thread. But headaches will occur if a single Shell_t object is
created by one thread and then passed over to another one (possible
fix: Add APIs like |sh_thread_attach()| and |sh_thread_detach()|
- Why does it require an atomic counter (which is _very_ expensive
from the CPU pipeline point of view... basically it can count
(depending on CPU/architecture) as an equivalent of adding a full
pipeline flush+sync... which itself can take 500 or more ticks to
complete) ?
- IMO it would be nice to add |ioctl()| calls per ioctl type with
proper prototypes, e.g. replace something like
|ioctl(JOBTTY,TIOCSETD,&linedisc)| with
|ioctl_TIOCSETD(JOBTTY,&linedisc)|. The point is to get stronger C
type checks and properly pass the types to the real |ioctl()|. Right
now the code assumes a specific layout and padding of the varargs data
which is *NOT* true and *NOT* portable (maybe we should just wait
until something like IA64 breaks and comes back with more teeth&&slime
to bite you... :-) ).
Another nice side-effect would be that we can do per-|ioctl()|-type
breakpoints... :-)
----
Bye,
Roland
--
__ . . __
(o.\ \/ /.o) [email protected]
\__\/\/__/ MPEG specialist, C&&JAVA&&Sun&&Unix programmer
/O /==\ O\ TEL +49 641 3992797
(;O/ \/ \O;)
diff -r -u original/src/cmd/ksh93/bltins/cd_pwd.c
build_i386_64bit_debug/src/cmd/ksh93/bltins/cd_pwd.c
--- src/cmd/ksh93/bltins/cd_pwd.c Wed Jun 26 22:12:28 2013
+++ src/cmd/ksh93/bltins/cd_pwd.c Sun Jun 30 00:55:15 2013
@@ -55,9 +55,17 @@
*/
int sh_diropenat(Shell_t *shp, int dir, const char *path, bool xattr)
{
+#ifdef O_DIRECTORY
+#define O_directory (O_DIRECTORY)
+#else
+#define O_directory (0)
+#endif
+
int fd,shfd;
int savederrno=errno;
+#ifndef O_DIRECTORY
struct stat fs;
+#endif
#ifndef O_XATTR
NOT_USED(xattr);
#endif
@@ -70,15 +78,47 @@
if((apfd = openat(dir, path, O_RDONLY|O_NONBLOCK|O_cloexec))>=0)
{
fd = openat(apfd, e_dot, O_XATTR|O_cloexec);
+ savederrno=errno;
close(apfd);
}
+ else
+ {
+ return -1;
+ }
}
else
#endif
- fd = openat(dir, path, O_SEARCH|O_NONBLOCK|O_cloexec);
+ {
+ /*
+ * 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.
+ */
+ fd = openat(dir, path, O_directory|O_NONBLOCK|O_cloexec);
+ if ((fd < 0) && (errno == EACCES))
+ {
+ fd = openat(dir, path,
O_SEARCH|O_directory|O_NONBLOCK|O_cloexec);
+ }
+ savederrno=errno;
+ }
+
if(fd < 0)
return fd;
+
+#ifndef O_DIRECTORY
if (!fstat(fd, &fs) && !S_ISDIR(fs.st_mode))
{
close(fd);
@@ -85,10 +125,10 @@
errno = ENOTDIR;
return -1;
}
+#endif
/* Move fd to a number > 10 and register the fd number with the shell */
shfd = fcntl(fd, F_dupfd_cloexec, 10);
- savederrno=errno;
close(fd);
errno=savederrno;
return(shfd);
diff -r -u original/src/lib/libast/features/eaccess
build_i386_64bit_debug/src/lib/libast/features/eaccess
--- src/lib/libast/features/eaccess Fri Jul 23 08:02:25 2004
+++ src/lib/libast/features/eaccess Sun Jun 30 00:55:15 2013
@@ -1,4 +1,4 @@
-lib eaccess,euidaccess
+lib eaccess,euidaccess -lgen
macro{
#include <sys/types.h>
#include <unistd.h>
diff -r -u original/src/lib/libast/features/fcntl.c
build_i386_64bit_debug/src/lib/libast/features/fcntl.c
--- src/lib/libast/features/fcntl.c Thu Jun 27 08:39:11 2013
+++ src/lib/libast/features/fcntl.c Sun Jun 30 07:41:16 2013
@@ -27,10 +27,30 @@
* generate POSIX fcntl.h
*/
+/*
+ * We use this to force Linux and some *BSD versions to tell us all
+ * their flags
+ */
+#define _GNU_SOURCE 1
+#define __USE_GNU 1 /* why is this neccesary on Linux ? */
+
#include <sys/types.h>
#include "FEATURE/lib"
+/*
+ * Make sure _GNU_SOURCE is active on Linux. Some versions
+ * give us serious trouble in this case so we have this
+ * assert to *abort* early instead of let us hunt for "ghost
+ * bugs"
+ */
+#ifdef __linux__
+#ifndef __USE_GNU
+#error "ASSERT: __USE_GNU should be defined by now"
+#endif
+#endif
+
+
#define getdtablesize ______getdtablesize
#define getpagesize ______getpagesize
#define ioctl ______ioctl
@@ -186,6 +206,15 @@
#ifdef F_SHLCK
if (F_SHLCK > f_local) f_local = F_SHLCK;
#endif
+#ifdef F_SHARE
+ if (F_SHARE > f_local) f_local = F_SHARE;
+#endif
+#ifdef F_UNSHARE
+ if (F_UNSHARE > f_local) f_local = F_UNSHARE;
+#endif
+#ifdef F_BADFD /* Create Poison FD */
+ if (F_BADFD > f_local) f_local = F_BADFD;
+#endif
#if NEED_F
#if _lib_fcntl
@@ -240,12 +269,12 @@
#define NEED_O 1
#endif
-#ifdef O_DSYNC
- if (O_DSYNC > o_local) o_local = O_DSYNC;
-#endif
#ifdef O_LARGEFILE
if (O_LARGEFILE > o_local) o_local = O_LARGEFILE;
#endif
+#ifdef O_LARGEFILE128
+ if (O_LARGEFILE128 > o_local) o_local = O_LARGEFILE128;
+#endif
#ifdef O_NOFOLLOW
if (O_NOFOLLOW > o_local) o_local = O_NOFOLLOW;
#endif
@@ -258,6 +287,9 @@
#ifdef O_RSYNC
if (O_RSYNC > o_local) o_local = O_RSYNC;
#endif
+#ifdef O_DSYNC
+ if (O_DSYNC > o_local) o_local = O_DSYNC;
+#endif
#ifdef O_SYNC
if (O_SYNC > o_local) o_local = O_SYNC;
#endif
@@ -264,6 +296,24 @@
#ifdef O_XATTR
if (O_XATTR > o_local) o_local = O_XATTR;
#endif
+#ifdef O_DIRECTORY
+ if (O_DIRECTORY > o_local) o_local = O_DIRECTORY;
+#endif
+#ifdef O_SEARCH
+ if (O_SEARCH > o_local) o_local = O_SEARCH;
+#endif
+#ifdef O_PATH
+ if (O_PATH > o_local) o_local = O_PATH;
+#endif
+#ifdef O_EXEC
+ if (O_EXEC > o_local) o_local = O_EXEC;
+#endif
+#ifdef O_CLOEXEC
+ if (O_CLOEXEC > o_local) o_local = O_CLOEXEC;
+#endif
+#ifdef O_TTY_INIT
+ if (O_TTY_INIT > o_local) o_local = O_TTY_INIT;
+#endif
printf("#define _ast_O_LOCAL 0%o\n", o_local<<1);
#if NEED_O
@@ -316,7 +366,17 @@
#endif
#ifndef O_SEARCH
#ifdef O_PATH
- printf("#define O_SEARCH O_PATH\n");
+ /*
+ * O_PATH is a Linux's variation of O_SEARCH. Since this is treated
+ * as extension it may not be available without _GNU_SOURCE.
+ * Even even with _GNU_SOURCE some Linux platforms have bugs in their
+ * headers which prevents the definition of O_PATH in some hideous
+ * cases. To prevent all this mess we just grab the octal value and
+ * define it as O_SEARCH.
+ * Do not change this. You'll end-up in hell, together with the Linux
+ * headers. Quickly.
+ */
+ printf("#define O_SEARCH 0%o\n", (int)O_PATH);
#else
printf("#define O_SEARCH 0%o\n", o_local <<= 1);
#endif
_______________________________________________
ast-developers mailing list
[email protected]
http://lists.research.att.com/mailman/listinfo/ast-developers