Discussion:
[ast-developers] [patch] readlink(1) builtin for libcmd...
Roland Mainz
2013-07-27 23:53:16 UTC
Permalink
Hi!

----

Attached (as "astksh20130727_readlink001.diff.txt") is the prototype
patch for the readlink(1) builtin.

** Notes:
* the builtin is currently at the level of functionality which
FreeBSD's and busybox's readlink(1) utilities provide... plus -D
* AST readlink(1) has an option to pass a directory fd to |readlinkat()|
* GNU readlink provides these three extra options...
-- snip --
-f, --canonicalize canonicalize by following every symlink in
every component of the given name recursively;
all but the last component must exist
-e, --canonicalize-existing canonicalize by following every symlink in
every component of the given name recursively,
all components must exist
-m, --canonicalize-missing canonicalize by following every symlink in
every component of the given name recursively,
without requirements on components existence
-- snip --
... are these options needed by anyone... and if "yes" ... what would
be the best way to implement them ?

Comments/rants/etc. welcome... :-)

----

Bye,
Roland

P.S.: Originally I thought about adding --dirfd support to "ln" to
complement readlink(1) ... but it turns out that AST ln(1) is married
to AST cp(1)/mv(1) and I need to think about some API design first
before trying to shoot myself in my feet... ;-)
--
__ . . __
(o.\ \/ /.o) roland.mainz at nrubsig.org
\__\/\/__/ MPEG specialist, C&&JAVA&&Sun&&Unix programmer
/O /==\ O\ TEL +49 641 3992797
(;O/ \/ \O;)
-------------- next part --------------
diff -N -r -u build_i386_64bit_debug/src/lib/libcmd/Makefile build_readlink/src/lib/libcmd/Makefile
--- src/lib/libcmd/Makefile 2013-04-22 07:12:50.000000000 +0200
+++ src/lib/libcmd/Makefile 2013-07-27 21:57:39.311526852 +0200
@@ -24,7 +24,7 @@
getconf.c head.c id.c join.c ln.c logname.c md5sum.c mkdir.c \
mkfifo.c mktemp.c mv.c paste.c pathchk.c pids.c rev.c rm.c \
rmdir.c stty.c sum.c sync.c tail.c tee.c tty.c uname.c uniq.c \
- vmstate.c wc.c revlib.c wclib.c sumlib.o context.c \
+ vmstate.c wc.c readlink.c revlib.c wclib.c sumlib.o context.c \
fts_fix.c lib.c \
grep.c xargs.c iconv.c \
od.c tr.c \
diff -N -r -u build_i386_64bit_debug/src/lib/libcmd/Mamfile build_readlink/src/lib/libcmd/Mamfile
--- src/lib/libcmd/Mamfile 2013-07-27 17:46:53.000000000 +0200
+++ src/lib/libcmd/Mamfile 2013-07-27 21:57:39.315526885 +0200
@@ -451,6 +451,11 @@
done wc.h
prev cmd.h implicit
done wc.c
+make readlink.c
+prev ${PACKAGE_ast_INCLUDE}/ls.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+prev cmd.h implicit
+done readlink.c
make revlib.c
prev rev.h implicit
prev cmd.h implicit
@@ -542,7 +547,7 @@
exec - -e 's/^b_//' \
exec - -e 's/(.*//' \
exec - -e 's/.*/extern int b_&(int, char**, Shbltin_t*);/' \
-exec - cmdinit.c basename.c cat.c chgrp.c chmod.c chown.c cksum.c cmp.c comm.c cp.c cut.c dirname.c date.c expr.c fds.c fmt.c fold.c getconf.c head.c id.c join.c ln.c logname.c md5sum.c mkdir.c mkfifo.c mktemp.c mv.c paste.c pathchk.c pids.c rev.c rm.c rmdir.c stty.c sum.c sync.c tail.c tee.c tty.c uname.c uniq.c vmstate.c wc.c revlib.c wclib.c context.c fts_fix.c lib.c grep.c xargs.c iconv.c od.c tr.c |
+exec - cmdinit.c basename.c cat.c chgrp.c chmod.c chown.c cksum.c cmp.c comm.c cp.c cut.c dirname.c date.c expr.c fds.c fmt.c fold.c getconf.c head.c id.c join.c ln.c logname.c md5sum.c mkdir.c mkfifo.c mktemp.c mv.c paste.c pathchk.c pids.c rev.c rm.c rmdir.c stty.c sum.c sync.c tail.c tee.c tty.c uname.c uniq.c vmstate.c wc.c readlink.c revlib.c wclib.c context.c fts_fix.c lib.c grep.c xargs.c iconv.c od.c tr.c |
exec - sort -u
exec - } > 1.${COTEMP}.h
exec - if cmp 2>/dev/null -s 1.${COTEMP}.h cmdext.h
@@ -822,6 +827,12 @@
prev wc.c
exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -I${PACKAGE_ast_INCLUDE} -DERROR_CATALOG=\""libcmd"\" -D_PACKAGE_ast -D_BLD_cmd -DUSAGE_LICENSE=\""[-author?Glenn Fowler <gsf at research.att.com>][-author?David Korn <dgk at research.att.com>][-copyright?Copyright (c) 1992-2013 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?libcmd]"\" -c wc.c
done wc.o generated
+make readlink.o
+prev readlink.c
+meta readlink.o %.c>%.o readlink.c readlink
+prev readlink.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -I${PACKAGE_ast_INCLUDE} -DERROR_CATALOG=\""libcmd"\" -D_PACKAGE_ast -D_BLD_cmd -DUSAGE_LICENSE=\""[-author?Glenn Fowler <gsf at research.att.com>][-author?David Korn <dgk at research.att.com>][-copyright?Copyright (c) 1992-2013 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?libcmd]"\" -c readlink.c
+done readlink.o generated
make revlib.o
prev revlib.c
meta revlib.o %.c>%.o revlib.c revlib
@@ -890,7 +901,7 @@
exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -I${PACKAGE_ast_INCLUDE} -DERROR_CATALOG=\""libcmd"\" -D_PACKAGE_ast -D_BLD_cmd -DUSAGE_LICENSE=\""[-author?Glenn Fowler <gsf at research.att.com>][-author?David Korn <dgk at research.att.com>][-copyright?Copyright (c) 1992-2013 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?libcmd]"\" -c tr.c
done tr.o generated
exec - ${AR} rc libcmd.a cmdinit.o basename.o cat.o chgrp.o chmod.o chown.o cksum.o cmp.o comm.o cp.o cut.o dirname.o date.o expr.o fds.o fmt.o fold.o getconf.o head.o id.o join.o ln.o logname.o md5sum.o mkdir.o mkfifo.o mktemp.o mv.o paste.o pathchk.o
-exec - ${AR} rc libcmd.a pids.o rev.o rm.o rmdir.o stty.o sum.o sync.o tail.o tee.o tty.o uname.o uniq.o vmstate.o wc.o revlib.o wclib.o sumlib.o context.o fts_fix.o lib.o grep.o xargs.o iconv.o od.o tr.o
+exec - ${AR} rc libcmd.a pids.o rev.o rm.o rmdir.o stty.o sum.o sync.o tail.o tee.o tty.o uname.o uniq.o vmstate.o wc.o readlink.o revlib.o wclib.o sumlib.o context.o fts_fix.o lib.o grep.o xargs.o iconv.o od.o tr.o
exec - (ranlib libcmd.a) >/dev/null 2>&1 || true
done libcmd.a generated
done cmd virtual
@@ -984,6 +995,7 @@
prev uniq.c
prev vmstate.c
prev wc.c
+prev readlink.c
prev revlib.c
prev wclib.c
prev context.c
@@ -1009,7 +1021,7 @@
exec - -e '/^b_[a-z_][a-z_0-9]*(/!d' \
exec - -e 's/^b_//' \
exec - -e 's/(.*//' \
-exec - cmdinit.c basename.c cat.c chgrp.c chmod.c chown.c cksum.c cmp.c comm.c cp.c cut.c dirname.c date.c expr.c fds.c fmt.c fold.c getconf.c head.c id.c join.c ln.c logname.c md5sum.c mkdir.c mkfifo.c mktemp.c mv.c paste.c pathchk.c pids.c rev.c rm.c rmdir.c stty.c sum.c sync.c tail.c tee.c tty.c uname.c uniq.c vmstate.c wc.c revlib.c wclib.c context.c fts_fix.c lib.c grep.c xargs.c iconv.c od.c tr.c |
+exec - cmdinit.c basename.c cat.c chgrp.c chmod.c chown.c cksum.c cmp.c comm.c cp.c cut.c dirname.c date.c expr.c fds.c fmt.c fold.c getconf.c head.c id.c join.c ln.c logname.c md5sum.c mkdir.c mkfifo.c mktemp.c mv.c paste.c pathchk.c pids.c rev.c rm.c rmdir.c stty.c sum.c sync.c tail.c tee.c tty.c uname.c uniq.c vmstate.c wc.c readlink.c revlib.c wclib.c context.c fts_fix.c lib.c grep.c xargs.c iconv.c od.c tr.c |
exec - sort -u
exec - `
exec - for cmd
diff -N -r -u build_i386_64bit_debug/src/lib/libcmd/readlink.c build_readlink/src/lib/libcmd/readlink.c
--- src/lib/libcmd/readlink.c 1970-01-01 01:00:00.000000000 +0100
+++ src/lib/libcmd/readlink.c 2013-07-28 01:33:04.004309047 +0200
@@ -0,0 +1,132 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 2013 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Roland Mainz <roland.mainz at nrubsig.org> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Roland Mainz
+ * AT&T Research
+ */
+
+#include <cmd.h>
+
+static const char optreadlink[] =
+"[-?\n@(#)$Id: readlink (AT&T Research) 2013-07-26 $\n]"
+"[-author?Roland Mainz <roland.mainz at nrubsig.org>]"
+"[+NAME?readlink - print value of a symbolic link]"
+"[+DESCRIPTION?The \breadlink\b(1) Print value of a symbolic link.]"
+"[+?If pathname given in pathname is relative, then it is "
+"interpreted relative to the directory referred to by the file "
+"descriptor dirfd or - if no dirfd is provided - relative to the "
+"current working directory of the calling process, as is done by "
+"readlink(2) for a relative pathname).]"
+"[+?If pathname is absolute, then dirfd is ignored.]"
+"[D:dirfd]:[fd?Path is interpreted as relative to the by the given "
+ "file descriptor.]"
+#ifdef NOT_YET_IMPLEMENTED
+"[e:canonicalize-existing?Canonicalize by following every symlink "
+ "in every component of the given name recursively, all "
+ "components must exist.]"
+"[f:canonicalize?Canonicalize by following every symlink in every "
+ "component of the given name recursively; all but the last "
+ "component must exist.]"
+"[m:canonicalize-missing?Canonicalize by following every symlink "
+ "in every component of the given name recursively, "
+ "without requirements on components existence.]"
+#endif
+"[n!:newline?Output a trailing newline after the resolved link.]"
+"[q:quiet?Suppress error messages.]"
+"\n"
+"\npath\n"
+"\n"
+"[+SEE ALSO?\breadlinkat\b(2), \breadlink\b(2), \bsymlinkat\b(2)]"
+;
+
+#define sh_contexttoshell(context) ((context)?((context)->shp):(NULL))
+#define sh_contexttopwdfd(context) ((context)?((context)->pwdfd):(AT_FDCWD))
+
+int
+b_readlink(int argc, char** argv, Shbltin_t* context)
+{
+ Shell_t *shp = sh_contexttoshell(context);
+ int dirfd = sh_contexttopwdfd(context);
+ int n;
+ bool fquiet = false;
+ bool fnewline = true;
+ const char *pathname;
+ char *endp;
+ char buff[PATH_MAX+2]; /* room for path, '\0' and newline */
+ ssize_t res;
+
+ while (n = optget(argv, optreadlink)) switch (n)
+ {
+ case 'D':
+ errno = 0;
+ dirfd = strtol(opt_info.arg, (char **)NULL, 0);
+ if ((errno != 0) || (dirfd < 0))
+ error(ERROR_system(1), "%s: invalid file descriptor", opt_info.arg);
+ break;
+ case 'n':
+ fnewline = opt_info.num?true:false;
+ break;
+ case 'q':
+ fquiet = opt_info.num?true:false;
+ break;
+ case ':':
+ error(2, "%s", opt_info.arg);
+ break;
+ case '?':
+ error(ERROR_usage(2), "%s", opt_info.arg);
+ break;
+ }
+ argc -= opt_info.index;
+ argv += opt_info.index;
+ if (argc != 1)
+ error(ERROR_usage(2), "%s", optusage(NiL));
+#if _lib_readlink
+ pathname = argv[0];
+
+ /*
+ * |readlinkat()| will be emulated on systems which do
+ * not provide it
+ */
+ res = readlinkat(dirfd, pathname, buff, sizeof(buff)-1);
+
+ if (res < 0)
+ {
+ if (fquiet)
+ return (1);
+ else
+ error(ERROR_system(1), "readlink() failed");
+ }
+
+ endp = &buff[res];
+
+ if (fnewline)
+ {
+ *endp++ = '\n';
+ *endp = '\0';
+ }
+
+ res = endp-buff;
+ res = (sfwrite(sfstdout, buff, res) == res)?0:1;
+ return (res);
+#else
+ error(ERROR_ERROR, "readlink() not implemented");
+#endif
+}
Glenn Fowler
2013-07-28 04:51:09 UTC
Permalink
Post by Roland Mainz
Attached (as "astksh20130727_readlink001.diff.txt") is the prototype
patch for the readlink(1) builtin.
* the builtin is currently at the level of functionality which
FreeBSD's and busybox's readlink(1) utilities provide... plus -D
* AST readlink(1) has an option to pass a directory fd to |readlinkat()|
* GNU readlink provides these three extra options...
-- snip --
-f, --canonicalize canonicalize by following every symlink in
every component of the given name recursively;
all but the last component must exist
-e, --canonicalize-existing canonicalize by following every symlink in
every component of the given name recursively,
all components must exist
-m, --canonicalize-missing canonicalize by following every symlink in
every component of the given name recursively,
without requirements on components existence
-- snip --
... are these options needed by anyone... and if "yes" ... what would
be the best way to implement them ?
see src/lib/libast/path/pathcanon.c
the PATH_* flags handle all but the "all but the last component must exist" part
by default pathcanon() does logical canonicalization (not existence checks, no symlinks)
Roland Mainz
2013-07-29 11:50:13 UTC
Permalink
Post by Glenn Fowler
Post by Roland Mainz
Attached (as "astksh20130727_readlink001.diff.txt") is the prototype
patch for the readlink(1) builtin.
* the builtin is currently at the level of functionality which
FreeBSD's and busybox's readlink(1) utilities provide... plus -D
* AST readlink(1) has an option to pass a directory fd to |readlinkat()|
* GNU readlink provides these three extra options...
-- snip --
-f, --canonicalize canonicalize by following every symlink in
every component of the given name recursively;
all but the last component must exist
-e, --canonicalize-existing canonicalize by following every symlink in
every component of the given name recursively,
all components must exist
-m, --canonicalize-missing canonicalize by following every symlink in
every component of the given name recursively,
without requirements on components existence
-- snip --
... are these options needed by anyone... and if "yes" ... what would
be the best way to implement them ?
see src/lib/libast/path/pathcanon.c
the PATH_* flags handle all but the "all but the last component must exist" part
by default pathcanon() does logical canonicalization (not existence checks, no symlinks)
OK... but I defer that work to a late ast-ksh alpha release because I
first like to get some feedback on which options are really required
(for example busybox and FreeBSD seems to be OK without { -e, -f, -m }
...) ... and the work for the { -e, -f, -m }-options has a dependency
on |fgetcwd()|.

Attached (as "astksh20130727_readlink002.diff.txt") is an updated
patch for ast-ksh.2013-07-27 ... AFAIK the work is isolated enough
that it can make it into the next alpha... right ?

----

Bye,
Roland
--
__ . . __
(o.\ \/ /.o) roland.mainz at nrubsig.org
\__\/\/__/ MPEG specialist, C&&JAVA&&Sun&&Unix programmer
/O /==\ O\ TEL +49 641 3992797
(;O/ \/ \O;)
-------------- next part --------------
diff -N -r -u build_i386_64bit_debug/src/lib/libcmd/Makefile build_readlink/src/lib/libcmd/Makefile
--- src/lib/libcmd/Makefile 2013-04-22 07:12:50.000000000 +0200
+++ src/lib/libcmd/Makefile 2013-07-27 21:57:39.311526852 +0200
@@ -24,7 +24,7 @@
getconf.c head.c id.c join.c ln.c logname.c md5sum.c mkdir.c \
mkfifo.c mktemp.c mv.c paste.c pathchk.c pids.c rev.c rm.c \
rmdir.c stty.c sum.c sync.c tail.c tee.c tty.c uname.c uniq.c \
- vmstate.c wc.c revlib.c wclib.c sumlib.o context.c \
+ vmstate.c wc.c readlink.c revlib.c wclib.c sumlib.o context.c \
fts_fix.c lib.c \
grep.c xargs.c iconv.c \
od.c tr.c \
diff -N -r -u build_i386_64bit_debug/src/lib/libcmd/Mamfile build_readlink/src/lib/libcmd/Mamfile
--- src/lib/libcmd/Mamfile 2013-07-27 17:46:53.000000000 +0200
+++ src/lib/libcmd/Mamfile 2013-07-27 21:57:39.315526885 +0200
@@ -451,6 +451,11 @@
done wc.h
prev cmd.h implicit
done wc.c
+make readlink.c
+prev ${PACKAGE_ast_INCLUDE}/ls.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+prev cmd.h implicit
+done readlink.c
make revlib.c
prev rev.h implicit
prev cmd.h implicit
@@ -542,7 +547,7 @@
exec - -e 's/^b_//' \
exec - -e 's/(.*//' \
exec - -e 's/.*/extern int b_&(int, char**, Shbltin_t*);/' \
-exec - cmdinit.c basename.c cat.c chgrp.c chmod.c chown.c cksum.c cmp.c comm.c cp.c cut.c dirname.c date.c expr.c fds.c fmt.c fold.c getconf.c head.c id.c join.c ln.c logname.c md5sum.c mkdir.c mkfifo.c mktemp.c mv.c paste.c pathchk.c pids.c rev.c rm.c rmdir.c stty.c sum.c sync.c tail.c tee.c tty.c uname.c uniq.c vmstate.c wc.c revlib.c wclib.c context.c fts_fix.c lib.c grep.c xargs.c iconv.c od.c tr.c |
+exec - cmdinit.c basename.c cat.c chgrp.c chmod.c chown.c cksum.c cmp.c comm.c cp.c cut.c dirname.c date.c expr.c fds.c fmt.c fold.c getconf.c head.c id.c join.c ln.c logname.c md5sum.c mkdir.c mkfifo.c mktemp.c mv.c paste.c pathchk.c pids.c rev.c rm.c rmdir.c stty.c sum.c sync.c tail.c tee.c tty.c uname.c uniq.c vmstate.c wc.c readlink.c revlib.c wclib.c context.c fts_fix.c lib.c grep.c xargs.c iconv.c od.c tr.c |
exec - sort -u
exec - } > 1.${COTEMP}.h
exec - if cmp 2>/dev/null -s 1.${COTEMP}.h cmdext.h
@@ -822,6 +827,12 @@
prev wc.c
exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -I${PACKAGE_ast_INCLUDE} -DERROR_CATALOG=\""libcmd"\" -D_PACKAGE_ast -D_BLD_cmd -DUSAGE_LICENSE=\""[-author?Glenn Fowler <gsf at research.att.com>][-author?David Korn <dgk at research.att.com>][-copyright?Copyright (c) 1992-2013 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?libcmd]"\" -c wc.c
done wc.o generated
+make readlink.o
+prev readlink.c
+meta readlink.o %.c>%.o readlink.c readlink
+prev readlink.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -I${PACKAGE_ast_INCLUDE} -DERROR_CATALOG=\""libcmd"\" -D_PACKAGE_ast -D_BLD_cmd -DUSAGE_LICENSE=\""[-author?Glenn Fowler <gsf at research.att.com>][-author?David Korn <dgk at research.att.com>][-copyright?Copyright (c) 1992-2013 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?libcmd]"\" -c readlink.c
+done readlink.o generated
make revlib.o
prev revlib.c
meta revlib.o %.c>%.o revlib.c revlib
@@ -890,7 +901,7 @@
exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -I${PACKAGE_ast_INCLUDE} -DERROR_CATALOG=\""libcmd"\" -D_PACKAGE_ast -D_BLD_cmd -DUSAGE_LICENSE=\""[-author?Glenn Fowler <gsf at research.att.com>][-author?David Korn <dgk at research.att.com>][-copyright?Copyright (c) 1992-2013 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?libcmd]"\" -c tr.c
done tr.o generated
exec - ${AR} rc libcmd.a cmdinit.o basename.o cat.o chgrp.o chmod.o chown.o cksum.o cmp.o comm.o cp.o cut.o dirname.o date.o expr.o fds.o fmt.o fold.o getconf.o head.o id.o join.o ln.o logname.o md5sum.o mkdir.o mkfifo.o mktemp.o mv.o paste.o pathchk.o
-exec - ${AR} rc libcmd.a pids.o rev.o rm.o rmdir.o stty.o sum.o sync.o tail.o tee.o tty.o uname.o uniq.o vmstate.o wc.o revlib.o wclib.o sumlib.o context.o fts_fix.o lib.o grep.o xargs.o iconv.o od.o tr.o
+exec - ${AR} rc libcmd.a pids.o rev.o rm.o rmdir.o stty.o sum.o sync.o tail.o tee.o tty.o uname.o uniq.o vmstate.o wc.o readlink.o revlib.o wclib.o sumlib.o context.o fts_fix.o lib.o grep.o xargs.o iconv.o od.o tr.o
exec - (ranlib libcmd.a) >/dev/null 2>&1 || true
done libcmd.a generated
done cmd virtual
@@ -984,6 +995,7 @@
prev uniq.c
prev vmstate.c
prev wc.c
+prev readlink.c
prev revlib.c
prev wclib.c
prev context.c
@@ -1009,7 +1021,7 @@
exec - -e '/^b_[a-z_][a-z_0-9]*(/!d' \
exec - -e 's/^b_//' \
exec - -e 's/(.*//' \
-exec - cmdinit.c basename.c cat.c chgrp.c chmod.c chown.c cksum.c cmp.c comm.c cp.c cut.c dirname.c date.c expr.c fds.c fmt.c fold.c getconf.c head.c id.c join.c ln.c logname.c md5sum.c mkdir.c mkfifo.c mktemp.c mv.c paste.c pathchk.c pids.c rev.c rm.c rmdir.c stty.c sum.c sync.c tail.c tee.c tty.c uname.c uniq.c vmstate.c wc.c revlib.c wclib.c context.c fts_fix.c lib.c grep.c xargs.c iconv.c od.c tr.c |
+exec - cmdinit.c basename.c cat.c chgrp.c chmod.c chown.c cksum.c cmp.c comm.c cp.c cut.c dirname.c date.c expr.c fds.c fmt.c fold.c getconf.c head.c id.c join.c ln.c logname.c md5sum.c mkdir.c mkfifo.c mktemp.c mv.c paste.c pathchk.c pids.c rev.c rm.c rmdir.c stty.c sum.c sync.c tail.c tee.c tty.c uname.c uniq.c vmstate.c wc.c readlink.c revlib.c wclib.c context.c fts_fix.c lib.c grep.c xargs.c iconv.c od.c tr.c |
exec - sort -u
exec - `
exec - for cmd
diff -N -r -u build_i386_64bit_debug/src/lib/libcmd/readlink.c build_readlink/src/lib/libcmd/readlink.c
--- src/lib/libcmd/readlink.c 1970-01-01 01:00:00.000000000 +0100
+++ src/lib/libcmd/readlink.c 2013-07-29 13:35:57.968064591 +0200
@@ -0,0 +1,129 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 2013 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Roland Mainz <roland.mainz at nrubsig.org> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Roland Mainz
+ * AT&T Research
+ */
+
+#include <cmd.h>
+
+static const char optreadlink[] =
+"[-?\n@(#)$Id: readlink (AT&T Research) 2013-07-28 $\n]"
+"[-author?Roland Mainz <roland.mainz at nrubsig.org>]"
+"[+NAME?readlink - print value of a symbolic link]"
+"[+DESCRIPTION?The \breadlink\b(1) Print value of a symbolic link.]"
+"[+?If pathname given in pathname is relative, then it is "
+"interpreted relative to the directory referred to by the file "
+"descriptor dirfd or - if no dirfd is provided - relative to the "
+"current working directory of the calling process, as is done by "
+"readlink(2) for a relative pathname).]"
+"[+?If pathname is absolute, then dirfd is ignored.]"
+"[D]#[dirfd:[fd?Path is interpreted as relative to the by the given "
+ "file descriptor.]"
+#ifdef NOT_YET_IMPLEMENTED
+"[e:canonicalize-existing?Canonicalize by following every symlink "
+ "in every component of the given name recursively, all "
+ "components must exist.]"
+"[f:canonicalize?Canonicalize by following every symlink in every "
+ "component of the given name recursively; all but the last "
+ "component must exist.]"
+"[m:canonicalize-missing?Canonicalize by following every symlink "
+ "in every component of the given name recursively, "
+ "without requirements on components existence.]"
+#endif
+"[n!:newline?Output a trailing newline after the resolved link.]"
+"[q:quiet?Suppress error messages.]"
+"\n"
+"\npath\n"
+"\n"
+"[+SEE ALSO?\breadlinkat\b(2), \breadlink\b(2), \bsymlinkat\b(2)]"
+;
+
+#define sh_contexttoshell(context) ((context)?((context)->shp):(NULL))
+#define sh_contexttopwdfd(context) ((context)?((context)->pwdfd):(AT_FDCWD))
+
+int
+b_readlink(int argc, char** argv, Shbltin_t* context)
+{
+ Shell_t *shp = sh_contexttoshell(context);
+ int dirfd = sh_contexttopwdfd(context);
+ int n;
+ bool fquiet = false;
+ bool fnewline = true;
+ const char *pathname;
+ char *endp;
+ char buff[PATH_MAX+2]; /* room for path, '\0' and newline */
+ ssize_t res;
+
+ while (n = optget(argv, optreadlink)) switch (n)
+ {
+ case 'D':
+ dirfd = opt_info.num;
+ break;
+ case 'n':
+ fnewline = opt_info.num?true:false;
+ break;
+ case 'q':
+ fquiet = opt_info.num?true:false;
+ break;
+ case ':':
+ error(2, "%s", opt_info.arg);
+ break;
+ case '?':
+ error(ERROR_usage(2), "%s", opt_info.arg);
+ break;
+ }
+ argc -= opt_info.index;
+ argv += opt_info.index;
+ if (argc != 1)
+ error(ERROR_usage(2), "%s", optusage(NiL));
+#if _lib_readlink
+ pathname = argv[0];
+
+ /*
+ * |readlinkat()| will be emulated on systems which do
+ * not provide it
+ */
+ res = readlinkat(dirfd, pathname, buff, sizeof(buff)-1);
+
+ if (res < 0)
+ {
+ if (fquiet)
+ return (1);
+ else
+ error(ERROR_system(1), "readlink() failed");
+ }
+
+ endp = &buff[res];
+
+ if (fnewline)
+ {
+ *endp++ = '\n';
+ *endp = '\0';
+ }
+
+ res = endp-buff;
+ res = (sfwrite(sfstdout, buff, res) == res)?0:1;
+ return (res);
+#else
+ error(ERROR_ERROR, "readlink() not implemented");
+#endif
+}
Dan Douglas
2013-07-31 02:12:22 UTC
Permalink
`readlink -f' is the most common invocation I see in scripts. I'd recommend making compatibility with at least coreutils' readlink a goal. See path_resolution(7) from the Linux man-pages for details on that part.
--
Dan Douglas
Cedric Blancher
2013-07-31 11:36:21 UTC
Permalink
Post by Dan Douglas
`readlink -f' is the most common invocation I see in scripts. I'd recommend making compatibility with at least coreutils' readlink a goal. See path_resolution(7) from the Linux man-pages for details on that part.
Agreed. But as Roland Mainz wrote "the work for the { -e, -f, -m
}-options has a dependency on |fgetcwd()|.". So we have to wait with
-f until fgetcwd() appears in libast, and until then take readlink(1)
as is. Good enough for me, and good enough for users coming from
FreeBSD or busybox.

Ced
--
Cedric Blancher <cedric.blancher at gmail.com>
Institute Pasteur
Cedric Blancher
2013-08-30 03:35:43 UTC
Permalink
Post by Cedric Blancher
Post by Dan Douglas
`readlink -f' is the most common invocation I see in scripts. I'd recommend making compatibility with at least coreutils' readlink a goal. See path_resolution(7) from the Linux man-pages for details on that part.
Agreed. But as Roland Mainz wrote "the work for the { -e, -f, -m
}-options has a dependency on |fgetcwd()|.". So we have to wait with
-f until fgetcwd() appears in libast, and until then take readlink(1)
as is. Good enough for me, and good enough for users coming from
FreeBSD or busybox.
Glenn, is there *now* hope to get readlink(1) integrated into libcmd?
I know ls -l could work too but there are existing consumers (mostly
FreeBSD and busybox) relying on readlink(1) and realpath(1) who could
benefit from this work.

Ced
--
Cedric Blancher <cedric.blancher at gmail.com>
Institute Pasteur
Glenn Fowler
2013-08-30 05:28:26 UTC
Permalink
Post by Cedric Blancher
Post by Cedric Blancher
Post by Dan Douglas
`readlink -f' is the most common invocation I see in scripts. I'd recommend making compatibility with at least coreutils' readlink a goal. See path_resolution(7) from the Linux man-pages for details on that part.
Agreed. But as Roland Mainz wrote "the work for the { -e, -f, -m
}-options has a dependency on |fgetcwd()|.". So we have to wait with
-f until fgetcwd() appears in libast, and until then take readlink(1)
as is. Good enough for me, and good enough for users coming from
FreeBSD or busybox.
Glenn, is there *now* hope to get readlink(1) integrated into libcmd?
I know ls -l could work too but there are existing consumers (mostly
FreeBSD and busybox) relying on readlink(1) and realpath(1) who could
benefit from this work.
yes
I extended the src/lib/libast/path/pathcanon.c flags to handle resolvepath(2)
and readlink(1) options -- do you have a url for the realpath(1) man page?
I'm guessing readlink(1) would be sufficient
the ast readlink(1) will probably add a few more options to cover the underlying
ast pathcanon() and pathdev() PATH_* flags -- then it could be used as a
regression test harness

just looked at the posix realpath(2) api -- can't believe it doesn't have
a buffer size arg, and the linux vs bsd vs solaris behavior is all over the place
soem preserve relative path, some always return absolute path

Loading...