XSLoader revisted
[p5sagit/p5-mst-13.2.git] / ext / Cwd / Cwd.xs
index f163368..3f7b93b 100644 (file)
@@ -2,6 +2,10 @@
 #include "perl.h"
 #include "XSUB.h"
 
+#ifdef I_UNISTD
+#   include <unistd.h>
+#endif
+
 /* The realpath() implementation from OpenBSD 2.9 (realpath.c 1.4)
  * Renamed here to bsd_realpath() to avoid library conflicts.
  * --jhi 2000-06-20 */
@@ -65,16 +69,30 @@ bsd_realpath(path, resolved)
        const char *path;
        char *resolved;
 {
-       struct stat sb;
-       int fd, n, rootd, serrno;
+#ifdef VMS
+       dTHX;
+       return Perl_rmsexpand(aTHX_ (char*)path, resolved, NULL, 0);
+#else
+       int rootd, serrno;
        char *p, *q, wbuf[MAXPATHLEN];
        int symlinks = 0;
 
        /* Save the starting point. */
+#ifdef HAS_FCHDIR
+       int fd;
+
        if ((fd = open(".", O_RDONLY)) < 0) {
                (void)strcpy(resolved, ".");
                return (NULL);
        }
+#else
+       char wd[MAXPATHLEN];
+
+       if (getcwd(wd, MAXPATHLEN - 1) == NULL) {
+               (void)strcpy(resolved, ".");
+               return (NULL);
+       }
+#endif
 
        /*
         * Find the dirname and basename from the path to be resolved.
@@ -104,9 +122,13 @@ loop:
        } else
                p = resolved;
 
+#if defined(HAS_LSTAT) && defined(HAS_READLINK) && defined(HAS_SYMLINK)
+    {
+       struct stat sb;
        /* Deal with the last component. */
        if (lstat(p, &sb) == 0) {
                if (S_ISLNK(sb.st_mode)) {
+                       int n;
                        if (++symlinks > MAXSYMLINKS) {
                                errno = ELOOP;
                                goto err1;
@@ -123,6 +145,8 @@ loop:
                        p = "";
                }
        }
+    }
+#endif
 
        /*
         * Save the last component name and get the full pathname of
@@ -152,20 +176,38 @@ loop:
        }
 
        /* Go back to where we came from. */
+#ifdef HAS_FCHDIR
        if (fchdir(fd) < 0) {
                serrno = errno;
                goto err2;
        }
+#else
+       if (chdir(wd) < 0) {
+               serrno = errno;
+               goto err2;
+       }
+#endif
 
        /* It's okay if the close fails, what's an fd more or less? */
+#ifdef HAS_FCHDIR
        (void)close(fd);
+#endif
        return (resolved);
 
 err1:  serrno = errno;
+#ifdef HAS_FCHDIR
        (void)fchdir(fd);
-err2:  (void)close(fd);
+#else
+       (void)chdir(wd);
+#endif
+
+err2:
+#ifdef HAS_FCHDIR
+       (void)close(fd);
+#endif
        errno = serrno;
        return (NULL);
+#endif
 }
 
 MODULE = Cwd           PACKAGE = Cwd
@@ -174,11 +216,15 @@ PROTOTYPES: ENABLE
 
 void
 fastcwd()
+PROTOTYPE: DISABLE
 PPCODE:
 {
     dXSTARG;
-    sv_getcwd(TARG);
+    getcwd_sv(TARG);
     XSprePUSH; PUSHTARG;
+#ifndef INCOMPLETE_TAINTS
+    SvTAINTED_on(TARG);
+#endif
 }
 
 void
@@ -188,30 +234,20 @@ PPCODE:
 {
     dXSTARG;
     char *path;
-    STRLEN len;
-    char *buf;
-
-    New(0, buf, MAXPATHLEN, char);
-    if (buf) {
-        buf[MAXPATHLEN] = 0;
-        if (pathsv)
-           path = SvPV(pathsv, len);
-       else {
-           path = ".";
-           len  = 1;
-       }
+    char buf[MAXPATHLEN];
 
-       if (bsd_realpath(path, buf)) {
-           sv_setpvn(TARG, buf, strlen(buf));
-           SvPOK_only(TARG);
-       }
-       else
-           sv_setsv(TARG, &PL_sv_undef);
+    path = pathsv ? SvPV_nolen(pathsv) : ".";
 
-       Safefree(buf);
+    if (bsd_realpath(path, buf)) {
+        sv_setpvn(TARG, buf, strlen(buf));
+        SvPOK_only(TARG);
+       SvTAINTED_on(TARG);
     }
     else
         sv_setsv(TARG, &PL_sv_undef);
 
     XSprePUSH; PUSHTARG;
+#ifndef INCOMPLETE_TAINTS
+    SvTAINTED_on(TARG);
+#endif
 }