Zsh Mailing List Archive
Messages sorted by:
Reverse Date,
Date,
Thread,
Author
Re: PATCH: Modifiers that implement realpath-like feature
- X-seq: zsh-workers 26731
- From: Michael Hwang <nomex45@xxxxxxxxx>
- To: zsh-workers@xxxxxxxxxx
- Subject: Re: PATCH: Modifiers that implement realpath-like feature
- Date: Sat, 14 Mar 2009 14:27:09 -0700 (PDT)
- Dkim-signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yahoo.com; s=s1024; t=1237066029; bh=k8HjwdH++xCTjdBeC5ZPNTwcObyWepfRKXVhsO7JQnQ=; h=Message-ID:X-YMail-OSG:Received:X-Mailer:References:Date:From:Subject:To:MIME-Version:Content-Type; b=jVfRiOFVAXBe+ggptCFJZ+9pWZNsreQGa1hs4FIFKOFfpDb5hwtgwzWk7BSMzjdwDnaeXFVXdn/qdmpg1PlkStHYr7iOaKXxcUIUSzjaXZFn91iB77WClYDYt336dMKW71amIBu+LNaG1njNjXpYxFuPuE4nebr1SuWiZ8KOwmE=
- Domainkey-signature: a=rsa-sha1; q=dns; c=nofws; s=s1024; d=yahoo.com; h=Message-ID:X-YMail-OSG:Received:X-Mailer:References:Date:From:Subject:To:MIME-Version:Content-Type; b=yg9Ts/7ei92vfqc+hqU4JOH09fe2F7Sf4ugHEzTHTCNWblTp0WMOsUX5kkf4WWbleJpt+2SlJOZ5AodHY+c/9puvSKojJygWFjdxe+5dcX+iWk8+bhdUSFbRFwWAG/xUWczp5UqoFOX+bk1SwwDtAGmN7QCyPEke0tIUutJEGKw=;
- Mailing-list: contact zsh-workers-help@xxxxxxxxxx; run by ezmlm
- References: <18038.70384.qm@xxxxxxxxxxxxxxxxxxxxxxxxxxx> <20090314181458.007906bc@pws-pc>
Sorry, here.
----- Original Message ----
From: Peter Stephenson <p.w.stephenson@xxxxxxxxxxxx>
To: Michael Hwang <nomex45@xxxxxxxxx>
Cc: zsh-workers@xxxxxxxxxx
Sent: Saturday, March 14, 2009 2:14:58 PM
Subject: Re: PATCH: Modifiers that implement realpath-like feature
On Thu, 12 Mar 2009 15:42:25 -0700 (PDT)
Michael Hwang <nomex45@xxxxxxxxx> wrote:
> I'm particularly proud of this patch, as it's my first time
> contributing to an open source project. (I'm sure the novelty will wear
> off in a while.) It implements two history-style realpath-like modifiers
> for getting the absolute path of a file. I chose the letter 'a' for
> 'absolute' (r was already taken). Both 'a' and 'A' have different
> meanings. The uppercase A will resolve symbolic links.
This looks useful but your mailer's screwed it up. Could you send it as
an attachment?
Thanks
--
Peter Stephenson <p.w.stephenson@xxxxxxxxxxxx>
Web page now at http://homepage.ntlworld.com/p.w.stephenson/
diff --git a/Src/hist.c b/Src/hist.c
index 38ceac3..0dd8c21 100644
--- a/Src/hist.c
+++ b/Src/hist.c
@@ -623,6 +623,21 @@ histsubchar(int c)
case 'p':
histdone = HISTFLAG_DONE | HISTFLAG_NOEXEC;
break;
+ case 'a':
+ if (!chabspath(&sline)) {
+ herrflush();
+ zerr("modifier failed: a");
+ return -1;
+ }
+ break;
+
+ case 'A':
+ if (!chrealpath(&sline)) {
+ herrflush();
+ zerr("modifier failed: A");
+ return -1;
+ }
+ break;
case 'h':
if (!remtpath(&sline)) {
herrflush();
@@ -1484,6 +1499,119 @@ hcomsearch(char *str)
/**/
int
+chabspath(char **junkptr)
+{
+ if (!**junkptr)
+ return 1;
+
+ if (**junkptr != '/') {
+ *junkptr = zhtricat(zgetcwd(), "/", *junkptr);
+ }
+
+ char *current = *junkptr;
+ char *dest = *junkptr;
+
+#ifdef HAVE_SUPERROOT
+ while (*current == '/' && current[1] == '.' && current[2] == '.' && (!current[3] || current[3] == '/')) {
+ *dest++ = '/';
+ *dest++ = '.';
+ *dest++ = '.';
+ current += 3;
+ }
+#endif
+
+ for (;;) {
+ if (*current == '/') {
+#ifdef __CYGWIN__
+ if (current == *junkptr && current[1] == '/')
+ *dest++ = *current++;
+#endif
+ *dest++ = *current++;
+ while (*current == '/')
+ current++;
+ } else if (!*current) {
+ while (dest > *junkptr + 1 && dest[-1] == '/')
+ dest--;
+ *dest = '\0';
+ break;
+ } else if (current[0] == '.' && current[1] == '.' && (!current[2] || current[2] == '/')) {
+ if (current == *junkptr || dest == *junkptr) {
+ *dest++ = '.';
+ *dest++ = '.';
+ current += 2;
+ } else if (dest > *junkptr + 2 && !strncmp(dest - 3, "../", 3)) {
+ *dest++ = '.';
+ *dest++ = '.';
+ current += 2;
+ } else if (dest > *junkptr + 1) {
+ *dest = '\0';
+ for (dest--; dest > *junkptr + 1 && dest[-1] != '/'; dest--);
+ if (dest[-1] != '/')
+ dest--;
+ current += 2;
+ } else if (dest == *junkptr + 1) { /* This might break with Cygwin's leading double slashes? */
+ current += 2;
+ } else {
+ return 0;
+ }
+ } else if (current[0] == '.' && (current[1] == '/' || !current[1])) {
+ while (*++current == '/');
+ } else {
+ while (*current != '/' && *current != '\0')
+ if ((*dest++ = *current++) == Meta)
+ dest[-1] = *current++ ^ 32;
+ }
+ }
+ return 1;
+}
+
+/**/
+int
+chrealpath(char **junkptr)
+{
+ if (!**junkptr)
+ return 1;
+
+ /* Notice that this means ..'s are applied before symlinks are resolved! */
+ if (!chabspath(junkptr))
+ return 0;
+
+ /* Notice that this means you cannot pass relative paths into this function! */
+ if (**junkptr != '/')
+ return 0;
+
+ char *lastpos = strend(*junkptr);
+ char *nonreal = lastpos + 1;
+ char real[PATH_MAX];
+
+ while (!realpath(*junkptr, real)) {
+ if (errno == EINVAL || errno == ELOOP || errno == ENAMETOOLONG || errno == ENOMEM)
+ return 0;
+
+ if (nonreal == *junkptr) {
+ *real = '\0';
+ break;
+ }
+
+ while (*nonreal != '/' && nonreal >= *junkptr)
+ nonreal--;
+ *nonreal = '\0';
+ }
+
+ char *str = nonreal;
+ while (str <= lastpos) {
+ if (*str == '\0')
+ *str = '/';
+ str++;
+ }
+
+ *junkptr = bicat(real, nonreal);
+
+ return 1;
+}
+
+/**/
+int
remtpath(char **junkptr)
{
char *str = strend(*junkptr);
diff --git a/Src/subst.c b/Src/subst.c
index 9e3f06f..5033dd4 100644
--- a/Src/subst.c
+++ b/Src/subst.c
@@ -3199,6 +3199,8 @@ modify(char **str, char **ptr)
for (; !c && **ptr;) {
switch (**ptr) {
+ case 'a':
+ case 'A':
case 'h':
case 'r':
case 'e':
@@ -3337,6 +3339,12 @@ modify(char **str, char **ptr)
copy = dupstring(tt);
*e = tc;
switch (c) {
+ case 'a':
+ chabspath(©);
+ break;
+ case 'A':
+ chrealpath(©);
+ break;
case 'h':
remtpath(©);
break;
@@ -3396,6 +3404,12 @@ modify(char **str, char **ptr)
} else {
switch (c) {
+ case 'a':
+ chabspath(str);
+ break;
+ case 'A':
+ chrealpath(str);
+ break;
case 'h':
remtpath(str);
break;
Messages sorted by:
Reverse Date,
Date,
Thread,
Author