No point in going into memory-saving contortions
Jarkko Hietaniemi [Wed, 20 Jun 2001 13:07:18 +0000 (13:07 +0000)]
with getcwd() since there's a danger of buffer overflow.
Also make the POSIX extension to use sv_getcwd().
Finally, a missed proto.h fragment.

p4raw-id: //depot/perl@10748

ext/POSIX/POSIX.xs
proto.h
util.c

index 49ea57e..e5e5f16 100644 (file)
@@ -1744,40 +1744,12 @@ char *
 ttyname(fd)
        int             fd
 
-#XXX: use sv_getcwd()
 void
 getcwd()
-       PPCODE:
-#ifdef HAS_GETCWD
-       char *          buf;
-       int             buflen = 128;
-
-       New(0, buf, buflen, char);
-       /* Many getcwd()s know how to automatically allocate memory
-        * for the directory if the buffer argument is NULL but...
-        * (1) we cannot assume all getcwd()s do that
-        * (2) this may interfere with Perl's malloc
-         * So let's not.  --jhi */
-       while ((getcwd(buf, buflen) == NULL) && errno == ERANGE) {
-           buflen += 128;
-           if (buflen > MAXPATHLEN) {
-               Safefree(buf);
-               buf = NULL;
-               break;
-           }
-           Renew(buf, buflen, char);
-       }
-       if (buf) {
-           PUSHs(sv_2mortal(newSVpv(buf, 0)));
-           Safefree(buf);
-       }
-       else
-           PUSHs(&PL_sv_undef);
-#else
-       require_pv("Cwd.pm");
-        /* Module require may have grown the stack */
-       SPAGAIN;
-       PUSHMARK(sp);
-       PUTBACK;
-       XSRETURN(call_pv("Cwd::cwd", GIMME_V));
-#endif
+    PPCODE:
+      {
+       dXSTARG;
+       sv_getcwd(TARG);
+       XSprePUSH; PUSHTARG;
+      }
+
diff --git a/proto.h b/proto.h
index 927f3b5..eaa6ed7 100644 (file)
--- a/proto.h
+++ b/proto.h
@@ -780,7 +780,7 @@ PERL_CALLCONV void  Perl_sv_pos_b2u(pTHX_ SV* sv, I32* offsetp);
 PERL_CALLCONV char*    Perl_sv_pvn_force(pTHX_ SV* sv, STRLEN* lp);
 PERL_CALLCONV char*    Perl_sv_pvutf8n_force(pTHX_ SV* sv, STRLEN* lp);
 PERL_CALLCONV char*    Perl_sv_pvbyten_force(pTHX_ SV* sv, STRLEN* lp);
-PERL_CALLCONV int      Perl_sv_realpath(pTHX_ SV* sv, char *path, STRLEN len);
+PERL_CALLCONV int      Perl_sv_realpath(pTHX_ SV* sv, char *path, STRLEN maxlen);
 PERL_CALLCONV char*    Perl_sv_reftype(pTHX_ SV* sv, int ob);
 PERL_CALLCONV void     Perl_sv_replace(pTHX_ SV* sv, SV* nsv);
 PERL_CALLCONV void     Perl_sv_report_used(pTHX);
diff --git a/util.c b/util.c
index 1d69fe5..838c362 100644 (file)
--- a/util.c
+++ b/util.c
@@ -3604,36 +3604,48 @@ Fill the sv with current working directory
  *     because you might chdir out of a directory that you can't chdir
  *     back into. */
 
-/* XXX: this needs more porting #ifndef HAS_GETCWD */
 int
 Perl_sv_getcwd(pTHX_ register SV *sv)
 {
 #ifndef PERL_MICRO
 
-#ifndef HAS_GETCWD
+#ifdef HAS_GETCWD
+    {
+       char* buf;
+
+       SvPOK_off(sv);
+       New(0, buf, MAXPATHLEN, char);
+       if (buf) {
+           buf[MAXPATHLEN] = 0;
+           /* Yes, some getcwd()s automatically allocate a buffer
+            * if given a NULL one.  Portability is the problem.
+            * XXX Configure probe needed. */
+           if (getcwd(buf, MAXPATHLEN - 1)) {
+               STRLEN len = strlen(buf);
+               sv_setpvn(sv, buf, len);
+               SvPOK_only(sv);
+               SvCUR_set(sv, len);
+           }
+           else
+               sv_setsv(sv, &PL_sv_undef);
+           Safefree(buf);
+       }
+       else
+           sv_setsv(sv, &PL_sv_undef);
+
+       return SvPOK(sv) ? TRUE : FALSE;
+    }
+
+#else
+
     struct stat statbuf;
     int orig_cdev, orig_cino, cdev, cino, odev, oino, tdev, tino;
     int namelen, pathlen=0;
     DIR *dir;
     Direntry_t *dp;
-#endif
 
     (void)SvUPGRADE(sv, SVt_PV);
 
-#ifdef HAS_GETCWD
-
-    SvGROW(sv, 128);
-    while ((getcwd(SvPVX(sv), SvLEN(sv)-1) == NULL) && errno == ERANGE) {
-        if (SvLEN(sv) + 128 >= MAXPATHLEN) {
-            SV_CWD_RETURN_UNDEF;
-       }
-        SvGROW(sv, SvLEN(sv) + 128);
-    }
-    SvCUR_set(sv, strlen(SvPVX(sv)));
-    SvPOK_only(sv);
-
-#else
-
     if (PerlLIO_lstat(".", &statbuf) < 0) {
         SV_CWD_RETURN_UNDEF;
     }