delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp-workers/1997/05/20/05:57:18

Date: Tue, 20 May 1997 11:52:51 +0200 (METDST)
From: Robert Hoehne <robert DOT hoehne AT mathematik DOT tu-chemnitz DOT de>
To: DJGPP workers <djgpp-workers AT delorie DOT com>
Subject: Patch for symlink
Message-Id: <Pine.HPP.3.95q.970520114353.14749D-100000@newton.mathematik.tu-chemnitz.de>
Mime-Version: 1.0

During my port of binutils 2.8 I found an annoing thing with
ln.exe.

When running on W95 with long filenames enabled, the following
command will success!!

ln -s foo.c foo_s.c

and produces a file foo_s.c.exe

When running under no LFN this will produce an error and
nonzero exit code of ln.exe (which is OK).

To fix this I wrote a little patch for symlink.c. Please
read the comments inside the patch, because the current
behaviour of ln is in my opinion not correct.

ln -s foo dummy

is OK even when foo or foo.exe not exists. This may be
a feature or not. I think it is a misfeature but I have
not changed this beahaviour (I commented it only and
wrote how to disable this).

I have also updated the doc to reflect my changes.

*** src/libc/posix/unistd/symlink.c~	Thu Sep 19 22:40:46 1996
--- src/libc/posix/unistd/symlink.c	Wed May 14 21:36:52 1997
***************
*** 29,34 ****
--- 29,106 ----
    return p;
  }
  
+ /*
+    This code is borrowed from dosexec.c
+    It returns -1, when the file does not exist
+                0, when it is not a v2 executable
+                1, when it is a v2 executable
+ */
+ 
+ static int is_v2_prog(const char *program)
+ {
+   int is_stubbed = 0, is_coff = 0;
+   unsigned short header[3];
+   int pf;
+   int stub_offset;
+ 
+   int v2_0 = 0;
+ 
+   pf = open(program, O_RDONLY|O_BINARY);
+ 
+   if (pf < 0)
+     return -1;
+ 
+   read(pf, header, sizeof(header));
+   if (header[0] == 0x010b || header[0] == 0x014c)
+   {
+     unsigned char firstbytes[1];
+     unsigned long coffhdr[40];
+ 
+     /* Seems to be an unstubbed COFF.  See what the first opcode
+        is to determine if it's v1.x or v2 COFF (or an impostor).
+ 
+        FIXME: the code here assumes that any COFF that's not a V1
+        can only be V2.  What about other compilers that use COFF?  */
+     is_coff = 1;
+     if (lseek(pf, 2, 1) < 0
+ 	|| read(pf, coffhdr, sizeof(coffhdr)) != sizeof(coffhdr)
+ 	|| lseek(pf, coffhdr[10 + 5], 0) < 0
+ 	|| read(pf, firstbytes, 1) != 1) /* scnptr */
+       is_coff = 0;	/* "Aha! An impostor!" (The Adventure game) */
+     else if (firstbytes[0] != 0xa3) /* opcode of movl %eax, 0x12345678 (V1) */
+       v2_0 = 1;
+   }
+   else if (header[0] == 0x5a4d)	/* "MZ" */
+   {
+     int header_offset = (long)header[2]*512L;
+     char cmdline[9];
+     is_stubbed = 1;
+     if (header[1])
+       header_offset += (long)header[1] - 512L;
+     lseek(pf, 512, 0);
+     read(pf, cmdline, 8);
+     cmdline[8] = 0;
+     if (strcmp(cmdline, "go32stub") == 0)
+     {
+       v2_0 = 1;
+       is_coff = 1;
+     }
+     else
+     {
+       lseek(pf, header_offset - 4, 0);
+       read(pf, &stub_offset, 4);
+       header[0] = 0;
+       read(pf, header, sizeof(header));
+       if (header[0] == 0x010b)
+ 	is_coff = 1;
+       if (header[0] == 0x014c)
+ 	is_coff = 1;
+     }
+   }
+   close(pf);
+   return is_coff && v2_0;
+ }
+ 
  /* Support the DJGPP ``symlinks'' for .exe files.  */
  int
  symlink (const char *source, const char *dest)
***************
*** 38,43 ****
--- 110,117 ----
    char *np, ropt[FILENAME_MAX+15]; /* some extra for ``runfile='' */
    const char *src_base, *dest_base;
  
+   int v2_prog = 0;
+ 
    _fixpath (source, src_abs);
    _fixpath (dest, dest_abs);
    src_base = tail (src_abs);
***************
*** 54,64 ****
--- 128,172 ----
    if (stricmp (src_abs, dest_abs) == 0)
      return 0;
  
+   /* Check at first, if the given name is a v2 executable (may be
+      unstubbed COFF image) */
+   v2_prog = is_v2_prog(src_abs);
+ 
+   /* It is an existing file but no v2 executable */
+   if (v2_prog == 0)
+   {
+     errno = EXDEV;
+     return -1;
+   }
+ 
    /* Allow to say `ln -s src dest' when we really
       mean `src.exe' and `dest.exe'  */
    np = src_abs + strlen (src_abs) - 4;
    if (stricmp (np, EXE_SUFFIX))
+   {
      strcat (src_abs, EXE_SUFFIX);
+     /* Now test again for v2 executable, but only if not already
+        succeed. */
+     v2_prog = v2_prog == 1 ? v2_prog : is_v2_prog(src_abs);
+   }
+ 
+   /* Comment by RH:
+      In my opinion here should be
+        if (v2_prog != 1)
+      which means, to allow a symlink ONLY to real existing
+      v2 executable. But I don't want to change too much at the
+      current behaviour of this function.
+   */
+   /* It is an existing file but no v2 executable */
+   if (v2_prog == 0)
+   {
+     errno = EXDEV;
+     return -1;
+   }
+ 
+   /* When we are here, either the file exists and is a v2 executable
+      or it does not exist and we hope, the the user knows what he
+      does. */
  
    /* Under LFN, we need the short version of the program name, since that
       is what the stub stores (and what a program gets in its argv[0]).  */



*** src/libc/posix/unistd/symlink.tx~	Thu Sep 19 22:41:08 1996
--- src/libc/posix/unistd/symlink.txh	Wed May 14 21:41:54 1997
***************
*** 23,29 ****
  directory (this is a restriction of the DJGPP ``symlinks''); the
  function will fail and set @code{errno} to @code{EXDEV} if they aren't.
  Also note that this function does nothing to ensure that @var{*exists}
! is actually a DJGPP program.
  
  This functions runs the @samp{stubify} and @samp{stubedit} programs, so
  they should be somewhere on your @samp{PATH} for the function to
--- 23,31 ----
  directory (this is a restriction of the DJGPP ``symlinks''); the
  function will fail and set @code{errno} to @code{EXDEV} if they aren't.
  Also note that this function does nothing to ensure that @var{*exists}
! is actually a DJGPP program whith the exception, that if the file
! @var{*exists} does really exist and it is not a usable DJGPP executable,
! this function will also fail with @code{errno} set to @code{EXDEV}.
  
  This functions runs the @samp{stubify} and @samp{stubedit} programs, so
  they should be somewhere on your @samp{PATH} for the function to



- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019