Ruby Forum Ruby-core > RFC: #19733 - dln_find_1 prioritizes posix naming conventions over Operating System naming conventio

Posted by Luis Lavena (luislavena)
on 23.04.2008 19:32
(Received via mailing list)
Hello ruby-core developers.

Please apologize for the noise, but dunno if the bugs created at
rubyforge tracker are being 'tracked' by someone.

Basically, this ticket [1] exposes a problem that annoys and add
cross-platform inoperativeness to Ruby. It start with the assumption
that an extensionless file have priority over a true windows
executable (.exe, com, bat, cmd) and try to use it instead when issue
system or any way that calls back into the OS.

To workaround this several projects need to include RUBY_PLATFORM =~
/mswin/ around stuff like 'rake.bat', 'gem.bat', 'spec.bat'
'rails.bat' and the list can go on...

Fixing this not only will get rid of the RUBY_PLATFORM regexp, but
also suppress the need to fix all these utilities to allow MinGW
builds of Ruby work properly.

It was suggested that RubyGems replace the current script+stub
implementation for 1 wrapped file, like built-in MRI scripts does.
This will be good for future, but will not solve the false premise we
are based on.

Since there a huge qty of projects that already fire 'rake' directly,
is silly provides patches for all those instead of fixing the true
root of the problem.

Please, let me know your comments, I could be wrong (like usual) but
I'll gladly provide a patch for 1.9 and 1.8.x series.

Regards and thanks in advance for reading all this.

[1] 
http://rubyforge.org/tracker/?func=detail&aid=19733&group_id=426&atid=1698

--
Luis Lavena
Multimedia systems
-
Human beings, who are almost unique in having the ability to learn from
the experience of others, are also remarkable for their apparent
disinclination to do so.
Douglas Adams
Posted by Nobuyoshi Nakada (nobu)
on 24.04.2008 06:17
(Received via mailing list)
Hi,

At Thu, 24 Apr 2008 02:32:05 +0900,
Luis Lavena wrote in [ruby-core:16517]:
> Basically, this ticket [1] exposes a problem that annoys and add
> cross-platform inoperativeness to Ruby. It start with the assumption
> that an extensionless file have priority over a true windows
> executable (.exe, com, bat, cmd) and try to use it instead when issue
> system or any way that calls back into the OS.

Do you consider files sans extensions shouldn't be returned?


Index: dln.c
===================================================================
--- dln.c  (revision 16174)
+++ dln.c  (working copy)
@@ -1695,24 +1695,7 @@ dln_find_1(const char *fname, const char
   memcpy(bp, fname, i + 1);

-#ifndef __MACOS__
-  if (stat(fbuf, &st) == 0) {
-      if (exe_flag == 0) return fbuf;
-      /* looking for executable */
-      if (!S_ISDIR(st.st_mode) && eaccess(fbuf, X_OK) == 0)
-    return fbuf;
-  }
-#else
-  if (mac_fullpath = _macruby_exist_file_in_libdir_as_posix_name(fbuf)) 
{
-      if (exe_flag == 0) return mac_fullpath;
-      /* looking for executable */
-      if (stat(mac_fullpath, &st) == 0) {
-    if (!S_ISDIR(st.st_mode) && eaccess(mac_fullpath, X_OK) == 0)
-        return mac_fullpath;
-      }
-  }
-#endif
 #if defined(DOSISH)
   if (exe_flag) {
-      static const char *const extension[] = {
+      static const char const extension[][5] = {
 #if defined(MSDOS)
     ".com", ".exe", ".bat",
@@ -1748,7 +1731,26 @@ dln_find_1(const char *fname, const char
 #endif
       }
+      goto next;
   }
 #endif /* MSDOS or _WIN32 or __human68k__ or __EMX__ */

+#ifndef __MACOS__
+  if (stat(fbuf, &st) == 0) {
+      if (exe_flag == 0) return fbuf;
+      /* looking for executable */
+      if (!S_ISDIR(st.st_mode) && eaccess(fbuf, X_OK) == 0)
+    return fbuf;
+  }
+#else
+  if (mac_fullpath = _macruby_exist_file_in_libdir_as_posix_name(fbuf)) 
{
+      if (exe_flag == 0) return mac_fullpath;
+      /* looking for executable */
+      if (stat(mac_fullpath, &st) == 0) {
+    if (!S_ISDIR(st.st_mode) && eaccess(mac_fullpath, X_OK) == 0)
+        return mac_fullpath;
+      }
+  }
+#endif
+
       next:
   /* if not, and no other alternatives, life is bleak */
Posted by Nobuyoshi Nakada (nobu)
on 24.04.2008 06:27
(Received via mailing list)
Hi,

At Thu, 24 Apr 2008 13:17:03 +0900,
Nobuyoshi Nakada wrote in [ruby-core:16548]:
> > Basically, this ticket [1] exposes a problem that annoys and add
> > cross-platform inoperativeness to Ruby. It start with the assumption
> > that an extensionless file have priority over a true windows
> > executable (.exe, com, bat, cmd) and try to use it instead when issue
> > system or any way that calls back into the OS.
> 
> Do you consider files sans extensions shouldn't be returned?

And, rather I want to remove static fbuf in dln.c.


Index: dln.h
===================================================================
--- dln.h  (revision 16174)
+++ dln.h  (working copy)
@@ -31,4 +31,6 @@
 char *dln_find_exe(const char*,const char*);
 char *dln_find_file(const char*,const char*);
+char *dln_find2_exe(const char*,const char*,char*,int);
+char *dln_find2_file(const char*,const char*,char*,int);

 #ifdef USE_DLN_A_OUT
Index: dln.c
===================================================================
--- dln.c  (revision 16174)
+++ dln.c  (working copy)
@@ -1569,8 +1569,8 @@ dln_load(const char *file)
 }

-static char *dln_find_1(const char *fname, const char *path, int 
exe_flag);
+static char *dln_find_1(const char *fname, const char *path, char *buf, 
int size, int exe_flag);

 char *
-dln_find_exe(const char *fname, const char *path)
+dln_find_exe2(const char *fname, const char *path, char *buf, int size)
 {
     if (!path) {
@@ -1585,16 +1585,16 @@ dln_find_exe(const char *fname, const ch
 #endif
     }
-    return dln_find_1(fname, path, 1);
+    return dln_find_1(fname, path, buf, size, 1);
 }

 char *
-dln_find_file(const char *fname, const char *path)
+dln_find_file2(const char *fname, const char *path, char *buf, int 
size)
 {
 #ifndef __MACOS__
     if (!path) path = ".";
-    return dln_find_1(fname, path, 0);
+    return dln_find_1(fname, path, buf, size, 0);
 #else
     if (!path) path = ".";
-    return _macruby_path_conv_posix_to_macos(dln_find_1(fname, path, 
0));
+    return _macruby_path_conv_posix_to_macos(dln_find_1(fname, path, 
buf, size, 0));
 #endif
 }
@@ -1602,6 +1602,19 @@ dln_find_file(const char *fname, const c
 static char fbuf[MAXPATHLEN];

+char *
+dln_find_exe(const char *fname, const char *path)
+{
+    return dln_find_exe2(fname, path, fbuf, sizeof(fbuf));
+}
+
+char *
+dln_find_file(const char *fname, const char *path)
+{
+    return dln_find_file2(fname, path, fbuf, sizeof(fbuf));
+}
+
 static char *
-dln_find_1(const char *fname, const char *path, int exe_flag /* non 0 
if looking for executable. */)
+dln_find_1(const char *fname, const char *path, char *fbuf, int size,
+     int exe_flag /* non 0 if looking for executable. */)
 {
     register const char *dp;
@@ -1643,5 +1656,5 @@ dln_find_1(const char *fname, const char
   l = ep - dp;
   bp = fbuf;
-  fspace = sizeof fbuf - 2;
+  fspace = size - 2;
   if (l > 0) {
       /*
Index: file.c
===================================================================
--- file.c  (revision 16174)
+++ file.c  (working copy)
@@ -4335,9 +4381,10 @@ rb_find_file_ext(VALUE *filep, const cha
   for (i=0;i<RARRAY_LEN(rb_load_path);i++) {
       VALUE str = RARRAY_PTR(rb_load_path)[i];
+      char fbuf[MAXPATHLEN];

       FilePathValue(str);
       if (RSTRING_LEN(str) == 0) continue;
       path = RSTRING_PTR(str);
-      found = dln_find_file(StringValueCStr(fname), path);
+      found = dln_find_file2(StringValueCStr(fname), path, fbuf, 
sizeof(fbuf));
       if (found && file_load_ok(found)) {
     *filep = rb_str_new2(found);
@@ -4355,4 +4402,5 @@ rb_find_file(VALUE path)
     char *f = StringValueCStr(path);
     char *lpath;
+    char fbuf[MAXPATHLEN];

     if (f[0] == '~') {
@@ -4412,5 +4460,5 @@ rb_find_file(VALUE path)
   return 0;    /* no path, no load */
     }
-    if (!(f = dln_find_file(f, lpath))) {
+    if (!(f = dln_find_file2(f, lpath, fbuf, sizeof(fbuf)))) {
   return 0;
     }
Index: process.c
===================================================================
--- process.c  (revision 16174)
+++ process.c  (working copy)
@@ -949,5 +950,5 @@ void rb_thread_reset_timer_thread(void);
   (rb_thread_start_timer_thread(), rb_disable_interrupt())

-extern char *dln_find_exe(const char *fname, const char *path);
+#include "dln.h"

 static void
@@ -964,7 +965,9 @@ static int
 proc_exec_v(char **argv, const char *prog)
 {
+    char fbuf[MAXPATHLEN];
+
     if (!prog)
   prog = argv[0];
-    prog = dln_find_exe(prog, 0);
+    prog = dln_find_exe2(prog, 0, fbuf, sizeof(fbuf));
     if (!prog) {
   errno = ENOENT;
@@ -1001,5 +1004,5 @@ proc_exec_v(char **argv, const char *pro
       new_argv[0] = COMMAND;
       argv = new_argv;
-      prog = dln_find_exe(argv[0], 0);
+      prog = dln_find_exe2(argv[0], 0, fbuf, sizeof(fbuf));
       if (!prog) {
     errno = ENOENT;
@@ -1065,5 +1079,6 @@ rb_proc_exec(const char *str)
     exit(status);
 #elif defined(__human68k__) || defined(__CYGWIN32__) || 
defined(__EMX__)
-      char *shell = dln_find_exe("sh", 0);
+      char fbuf[MAXPATHLEN];
+      char *shell = dln_find_exe2("sh", 0, fbuf, sizeof(fbuf));
       int status = -1;
       before_exec();
@@ -1112,4 +1127,5 @@ static rb_pid_t
 proc_spawn_v(char **argv, char *prog)
 {
+    char fbuf[MAXPATHLEN];
     char *extension;
     rb_pid_t status;
@@ -1118,5 +1134,5 @@ proc_spawn_v(char **argv, char *prog)
   prog = argv[0];
     security(prog);
-    prog = dln_find_exe(prog, 0);
+    prog = dln_find_exe2(prog, 0, fbuf, sizeof(fbuf));
     if (!prog)
   return -1;
@@ -1139,5 +1155,5 @@ proc_spawn_v(char **argv, char *prog)
   new_argv[0] = COMMAND;
   argv = new_argv;
-  prog = dln_find_exe(argv[0], 0);
+  prog = dln_find_exe2(argv[0], 0, fbuf, sizeof(fbuf));
   if (!prog) {
       errno = ENOENT;
@@ -1176,4 +1192,5 @@ static rb_pid_t
 proc_spawn(char *str)
 {
+    char fbuf[MAXPATHLEN];
     char *s, *t;
     char **argv, **a;
@@ -1182,5 +1199,5 @@ proc_spawn(char *str)
     for (s = str; *s; s++) {
   if (*s != ' ' && !ISALPHA(*s) && 
strchr("*?{}[]<>()~&|\\$;'`\"\n",*s)) {
-      char *shell = dln_find_exe("sh", 0);
+      char *shell = dln_find_exe2("sh", 0, fbuf, sizeof(fbuf));
       before_exec();
       status = 
shell?spawnl(P_WAIT,shell,"sh","-c",str,(char*)NULL):system(str);
@@ -949,6 +984,7 @@ process_options(VALUE arg)
     NODE *tree = 0;
     VALUE parser;
     rb_encoding *enc;
     const char *s;
+    char fbuf[MAXPATHLEN];
     int i = proc_options(argc, argv, opt);

@@ -1031,8 +1067,8 @@ process_options(VALUE arg)
     opt->script = 0;
     if (path) {
-        opt->script = dln_find_file(argv[0], path);
+        opt->script = dln_find_file2(argv[0], path, fbuf, 
sizeof(fbuf));
     }
     if (!opt->script) {
-        opt->script = dln_find_file(argv[0], getenv(PATH_ENV));
+        opt->script = dln_find_file(argv[0], getenv(PATH_ENV), fbuf, 
sizeof(fbuf));
     }
     if (!opt->script)
Posted by Luis Lavena (luislavena)
on 24.04.2008 07:30
(Received via mailing list)
On Thu, Apr 24, 2008 at 1:26 AM, Nobuyoshi Nakada <nobu@ruby-lang.org> 
wrote:
>  >
>  > Do you consider files sans extensions shouldn't be returned?
>

Not in Windows. These shouldn't be the first option, since they are
not executables "as-is".

>  And, rather I want to remove static fbuf in dln.c.
>

Tried to apply the patch to trunk but failed to apply file.c and
process.c diffs.

I'll work on porting what you exposed here for 1.8 and get back on the 
ticket.

Thank you again for your time Nobu.

--
Luis Lavena
Multimedia systems
-
Human beings, who are almost unique in having the ability to learn from
the experience of others, are also remarkable for their apparent
disinclination to do so.
Douglas Adams