Re: patch@34561 VMS exec handling / cwd realpath fixes

[email protected] ("John E. Malmberg")
Newsgroups perl.perl5.porters,perl.vmsperl
Message-ID <[email protected]>
Ok,

Resubmitting for review.

I removed the setup_cmddsc, and the unneeded readdir stuff, so this 
patch is what is needed for getting the symbolic links to be encoded and 
decoded properly in VMS.C and for CWD in pathtools.

-John
[email protected]
Personal Opinion Only
cwd.patch (text/plain, 2 KB)
--- /rsync_root/perl/lib/cwd.pm	Sun Oct 19 05:26:56 2008
+++ lib/cwd.pm	Wed Oct 22 23:56:34 2008
@@ -647,23 +647,15 @@
     return $ENV{'DEFAULT'} unless @_;
     my $path = shift;
 
-    if (-l $path) {
-        my $link_target = readlink($path);
-        die "Can't resolve link $path: $!" unless defined $link_target;
-	    
-        return _vms_abs_path($link_target);
-    }
-
-    if (defined &VMS::Filespec::vms_realpath) {
-        my $path = $_[0];
+    if (defined &VMS::Filespec::vmsrealpath) {
         if ($path =~ m#(?<=\^)/# ) {
             # Unix format
-            return VMS::Filespec::vms_realpath($path);
+            return VMS::Filespec::unixrealpath($path);
         }
 
 	# VMS format
 
-	my $new_path = VMS::Filespec::vms_realname($path); 
+	my $new_path = VMS::Filespec::vmsrealpath($path);
 
 	# Perl expects directories to be in directory format
 	$new_path = VMS::Filespec::pathify($new_path) if -d $path;
@@ -673,6 +665,13 @@
     # Fallback to older algorithm if correct ones are not
     # available.
 
+    if (-l $path) {
+        my $link_target = readlink($path);
+        die "Can't resolve link $path: $!" unless defined $link_target;
+
+        return _vms_abs_path($link_target);
+    }
+
     # may need to turn foo.dir into [.foo]
     my $pathified = VMS::Filespec::pathify($path);
     $path = $pathified if defined $pathified;
--- /rsync_root/perl/ext/cwd/t/cwd.t	Tue Jan 22 22:17:18 2008
+++ ext/cwd/t/cwd.t	Wed Oct 22 23:32:36 2008
@@ -173,6 +173,15 @@
 			         $ENV{PERL_CORE} ? $Test_Dir : File::Spec->catdir('t', $Test_Dir)
                                                 )
                                   );
+    if ($^O eq 'VMS') {
+       # Not easy to predict the physical volume name
+       $want = $ENV{PERL_CORE} ? $Test_Dir : File::Spec->catdir('t', $Test_Dir);
+
+       # So just use the relative volume name
+       $want =~ s/^\[//;
+
+       $want = quotemeta($want);
+    }
 
     like($abs_path,      qr|$want$|i);
     like($fast_abs_path, qr|$want$|i);
vms_symlink.patch (text/plain, 4.9 KB)
--- /rsync_root/perl/vms/vms.c	Wed Oct 22 19:26:20 2008
+++ vms/vms.c	Wed Oct 29 22:04:08 2008
@@ -12990,14 +12990,41 @@
 /*
  * A thin wrapper around decc$symlink to make sure we follow the 
  * standard and do not create a symlink with a zero-length name.
+ *
+ * Also in ODS-2 mode, existing tests assume that the link target
+ * will be converted to UNIX format.
  */
-/*{{{ int my_symlink(const char *path1, const char *path2)*/
-int my_symlink(const char *path1, const char *path2) {
-  if (!path2 || !*path2) {
+/*{{{ int my_symlink(pTHX_ const char *contents, const char *link_name)*/
+int Perl_my_symlink(pTHX_ const char *contents, const char *link_name) {
+  if (!link_name || !*link_name) {
     SETERRNO(ENOENT, SS$_NOSUCHFILE);
     return -1;
   }
-  return symlink(path1, path2);
+
+  if (decc_efs_charset) {
+      return symlink(contents, link_name);
+  } else {
+      int sts;
+      char * utarget;
+
+      /* Unless we are in ODS-5 mode, convert the symlink target to UNIX */
+      /* because in order to work, the symlink target must be in UNIX format */
+
+      /* As symbolic links can hold things other than files, we will only do */
+      /* the conversion in in ODS-2 mode */
+
+      Newx(utarget, VMS_MAXRSS + 1, char);
+      if (do_tounixspec(contents, utarget, 0, NULL) == NULL) {
+
+          /* This should not fail, as an untranslatable filename */
+          /* should be passed through */
+          utarget = (char *)contents;
+      }
+      sts = symlink(utarget, link_name);
+      Safefree(utarget);
+      return sts;
+  }
+
 }
 /*}}}*/
 
@@ -13203,7 +13230,100 @@
 	                if (haslower) __mystrtolower(rslt);
 	            }
 	        }
-	}
++	} else {
++
++	    /* Now for some hacks to deal with backwards and forward */
++	    /* compatibilty */
++	    if (!decc_efs_charset) {
++
++		/* 1. ODS-2 mode wants to do a syntax only translation */
++		rslt = do_rmsexpand(filespec, outbuf,
++				    0, NULL, 0, NULL, utf8_fl);
++
++	    } else {
++		if (decc_filename_unix_report) {
++		    char * dir_name;
++		    char * vms_dir_name;
++		    char * file_name;
++
++		    /* 2. ODS-5 / UNIX report mode should return a failure */
++		    /*    if the parent directory also does not exist */
++		    /*    Otherwise, get the real path for the parent */
++		    /*    and add the child to it.
++
++		    /* basename / dirname only available for VMS 7.0+ */
++		    /* So we may need to implement them as common routines */
++
++		    Newx(dir_name, VMS_MAXRSS + 1, char);
++		    Newx(vms_dir_name, VMS_MAXRSS + 1, char);
++		    dir_name[0] = '\0';
++		    file_name = NULL;
++
++		    /* First try a VMS parse */
++		    sts = vms_split_path
++			  (filespec,
++			   &v_spec,
++			   &v_len,
++			   &r_spec,
++			   &r_len,
++			   &d_spec,
++			   &d_len,
++			   &n_spec,
++			   &n_len,
++			   &e_spec,
++			   &e_len,
++			   &vs_spec,
++			   &vs_len);
++
++		    if (sts == 0) {
++			/* This is VMS */
++
++			int dir_len = v_len + r_len + d_len + n_len;
++			if (dir_len > 0) {
++			   strncpy(dir_name, filespec, dir_len);
++			   dir_name[dir_len] = '\0';
++			   file_name = (char *)&filespec[dir_len + 1];
++			}
++		    } else {
++			/* This must be UNIX */
++			char * tchar;
++
++			tchar = strrchr(filespec, '/');
++
+			if (tchar != NULL) {
+			    int dir_len = tchar - filespec;
+			    strncpy(dir_name, filespec, dir_len);
+			    dir_name[dir_len] = '\0';
+			    file_name = (char *) &filespec[dir_len + 1];
+			}
+		    }
+
+		    /* Dir name is defaulted */
+		    if (dir_name[0] == 0) {
+			dir_name[0] = '.';
+			dir_name[1] = '\0';
+		    }
+
+		    /* Need realpath for the directory */
+		    sts = vms_fid_to_name(vms_dir_name,
+					  VMS_MAXRSS + 1,
+					  dir_name);
+
+		    if (sts == 0) {
+		        /* Now need to pathify it.
+		        char *tdir = do_pathify_dirspec(vms_dir_name,
+							outbuf, utf8_fl);
+
+			/* And now add the original filespec to it */
+			if (file_name != NULL) {
+			    strcat(outbuf, file_name);
+			}
+			return outbuf;
+		    }
+		    Safefree(vms_dir_name);
+		    Safefree(dir_name);
+		}
+            }
 
         Safefree(vms_spec);
     }
--- /rsync_root/perl/vms/vmsish.h	Fri Jun 13 19:00:12 2008
+++ vms/vmsish.h	Sun Oct 26 23:10:22 2008
@@ -276,7 +276,7 @@
 #define my_endpwent()		Perl_my_endpwent(aTHX)
 #define my_getlogin		Perl_my_getlogin
 #ifdef HAS_SYMLINK
-#  define my_symlink		Perl_my_symlink
+#  define my_symlink(a, b)	Perl_my_symlink(aTHX_ a, b)
 #endif
 #define init_os_extras		Perl_init_os_extras
 #define vms_realpath(a, b, c)	Perl_vms_realpath(aTHX_ a,b,c)
@@ -970,7 +970,7 @@
 int     my_fclose (FILE *);
 int     my_fwrite (const void *, size_t, size_t, FILE *);
 #ifdef HAS_SYMLINK
-int     my_symlink(const char *path1, const char *path2);
+int     Perl_my_symlink(pTHX_ const char *path1, const char *path2);
 #endif
 int	Perl_my_flush (pTHX_ FILE *);
 struct passwd *	Perl_my_getpwnam (pTHX_ const char *name);
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.