From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 24586 invoked from network); 27 Mar 2008 10:24:16 -0000 X-Spam-Checker-Version: SpamAssassin 3.2.4 (2008-01-01) on f.primenet.com.au X-Spam-Level: X-Spam-Status: No, score=-2.6 required=5.0 tests=BAYES_00 autolearn=ham version=3.2.4 Received: from news.dotsrc.org (HELO a.mx.sunsite.dk) (130.225.247.88) by ns1.primenet.com.au with SMTP; 27 Mar 2008 10:24:16 -0000 Received-SPF: none (ns1.primenet.com.au: domain at sunsite.dk does not designate permitted sender hosts) Received: (qmail 44222 invoked from network); 27 Mar 2008 10:24:09 -0000 Received: from sunsite.dk (130.225.247.90) by a.mx.sunsite.dk with SMTP; 27 Mar 2008 10:24:09 -0000 Received: (qmail 27995 invoked by alias); 27 Mar 2008 10:24:07 -0000 Mailing-List: contact zsh-workers-help@sunsite.dk; run by ezmlm Precedence: bulk X-No-Archive: yes X-Seq: 24757 Received: (qmail 27982 invoked from network); 27 Mar 2008 10:24:06 -0000 Received: from bifrost.dotsrc.org (130.225.254.106) by sunsite.dk with SMTP; 27 Mar 2008 10:24:06 -0000 Received: from cluster-g.mailcontrol.com (cluster-g.mailcontrol.com [85.115.41.190]) by bifrost.dotsrc.org (Postfix) with ESMTP id 0165382CD267 for ; Thu, 27 Mar 2008 11:23:59 +0100 (CET) Received: from cameurexb01.EUROPE.ROOT.PRI ([62.189.241.200]) by rly07g.srv.mailcontrol.com (MailControl) with ESMTP id m2RAGhLf021281 for ; Thu, 27 Mar 2008 10:23:46 GMT Received: from news01 ([10.103.143.38]) by cameurexb01.EUROPE.ROOT.PRI with Microsoft SMTPSVC(6.0.3790.3959); Thu, 27 Mar 2008 10:23:25 +0000 Date: Thu, 27 Mar 2008 10:23:25 +0000 From: Peter Stephenson To: zsh-workers@sunsite.dk Subject: Re: _canonical_path not working on *BSD Message-ID: <20080327102325.55808716@news01> In-Reply-To: <20080326164615.1d5893ed@news01> References: <20080326114413.80713vrmznwpnyuc@bapt.selfip.org> <080326083638.ZM16858@torch.brasslantern.com> <200803261540.m2QFeJmm017381@news01.csr.com> <200803261604.m2QG41Ke017772@news01.csr.com> <200803261621.m2QGLptV017966@news01.csr.com> <20080326173824.0a55c00d@coredump.raveland.priv> <20080326164615.1d5893ed@news01> Organization: CSR X-Mailer: Claws Mail 3.3.1 (GTK+ 2.12.5; i386-redhat-linux-gnu) Mime-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit X-OriginalArrivalTime: 27 Mar 2008 10:23:25.0586 (UTC) FILETIME=[9774B720:01C88FF4] X-Scanned-By: MailControl A-08-00-05 (www.mailcontrol.com) on 10.71.0.117 X-Virus-Scanned: ClamAV 0.91.2/6421/Thu Mar 27 09:54:20 2008 on bifrost X-Virus-Status: Clean On Wed, 26 Mar 2008 16:46:15 +0000 Peter Stephenson wrote: > +_canonical_paths_get_canonical_path() { > + typeset newfile > + typeset -A seen > + > + REPLY=$1 > + # Guard against loops. > + while [[ -z ${seen[$REPLY]} ]]; do > + seen[$REPLY]=1 > + newfile=$(zstat +link $REPLY 2>/dev/null) > + if [[ -n $newfile ]]; then > + REPLY=$newfile > + else > + break > + fi > + done > +} I should make one more point about this before leaving the subject: this doesn't do everything that "readlink -f" does, in particular it doesn't remove .. path segments, strip multiple /'s or remove symbolic link references in intervening directories. Luckily, we have the technology, I think. We don't need the $(...) for the zstat. It would be quite nice to be able to get the directory canonicalization without a fork, too. Index: Completion/Unix/Type/_canonical_paths =================================================================== RCS file: /cvsroot/zsh/zsh/Completion/Unix/Type/_canonical_paths,v retrieving revision 1.2 diff -u -r1.2 _canonical_paths --- Completion/Unix/Type/_canonical_paths 26 Mar 2008 17:22:25 -0000 1.2 +++ Completion/Unix/Type/_canonical_paths 27 Mar 2008 10:19:10 -0000 @@ -36,20 +36,41 @@ typeset -a matches files _canonical_paths_get_canonical_path() { - typeset newfile + typeset newfile dir typeset -A seen REPLY=$1 - # Guard against loops. + # Resolve any trailing symbolic links, guarding against loops. while [[ -z ${seen[$REPLY]} ]]; do seen[$REPLY]=1 - newfile=$(zstat +link $REPLY 2>/dev/null) - if [[ -n $newfile ]]; then - REPLY=$newfile + newfile=() + zstat -A newfile +link $REPLY 2>/dev/null + if [[ -n $newfile[1] ]]; then + REPLY=$newfile[1] else break fi done + + # Canonicalise the directory path. We may not be able to + # do this if we can't read all components. + if [[ -d $REPLY ]]; then + dir="$(unfunction chpwd + setopt CHASE_LINKS + cd $REPLY 2>/dev/null && pwd)" + if [[ -n $dir ]]; then + REPLY=$dir + fi + elif [[ $REPLY = */*[^/] && $REPLY != /[^/]# ]]; then + # Don't try this if there's a trailing slash or we're in + # the root directory. + dir="$(unfunction chpwd + setopt CHASE_LINKS + cd ${REPLY%/*} 2>/dev/null && pwd)" + if [[ -n $dir ]]; then + REPLY=$dir/${REPLY##*/} + fi + fi }