delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp-workers/1996/09/18/13:13:11

Date: Wed, 18 Sep 1996 18:54:57 +0200 (IST)
From: Eli Zaretskii <eliz AT is DOT elta DOT co DOT il>
To: djgpp-workers AT delorie DOT com
Subject: `symlink'
Message-Id: <Pine.SUN.3.91.960918185114.1945F-100000@is>
Mime-Version: 1.0

I wrote this for the port of GNU `ln' (so you could say something like 
"ln -s grep fgrep" and get fgrep.exe that runs grep.exe), so I though it 
might as well be in the library.

*** src/libc/posix/unistd/symlink.c~0	Tue Sep 17 19:13:26 1996
--- src/libc/posix/unistd/symlink.c	Wed Sep 18 08:22:54 1996
***************
*** 0 ****
--- 1,119 ----
+ #include <libc/stubs.h>
+ #include <stdio.h>
+ #include <string.h>
+ #include <errno.h>
+ #include <fcntl.h>
+ #include <unistd.h>
+ #include <sys/stat.h>
+ #include <process.h>
+ #include <dpmi.h>
+ #include <go32.h>
+ 
+ static char EXE_SUFFIX[] = ".exe";
+ static char STUBIFY[]	 = "stubify.exe";
+ static char STUBEDIT[]	 = "stubedit.exe";
+ 
+ /* Return a pointer to the tail of the pathname.  */
+ static const char *
+ tail (const char *path)
+ {
+   const char *p = path ? path + strlen (path) - 1 : path;
+ 
+   if (p)
+     {
+       while (p > path && *p != '/' && *p != '\\' && *p != ':')
+ 	p--;
+       if (p > path)
+ 	p++;
+     }
+   return p;
+ }
+ 
+ /* Support the DJGPP ``symlinks'' for .exe files.  */
+ int
+ symlink (const char *source, const char *dest)
+ {
+   char src_abs[FILENAME_MAX+5], src_short[FILENAME_MAX+5];
+   char dest_abs[FILENAME_MAX+5];
+   char *np, ropt[FILENAME_MAX+15]; /* some extra for ``runfile='' */
+   const char *src_base, *dest_base;
+ 
+   _fixpath (source, src_abs);
+   _fixpath (dest, dest_abs);
+   src_base = tail (src_abs);
+   dest_base = tail (dest_abs);
+ 
+   /* DJGPP symlinks must be in the same directory.  */
+   if (strnicmp (src_abs, dest_abs, src_base - src_abs))
+     {
+       errno = EXDEV;
+       return -1;
+     }
+ 
+   /* Any file is already a link to itself.  */
+   if (stricmp (src_abs, dest_abs) == 0)
+     return 0;
+ 
+   /* 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);
+ 
+   /* 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]).  */
+   if (_USE_LFN)
+     {
+       if (__file_exists (src_abs))
+ 	{
+ 	  /* File exists.  Get its 8+3 alias.  */
+ 	  __dpmi_regs r;
+ 
+ 	  dosmemput(src_abs, strlen (src_abs)+1, __tb);
+ 	  r.x.ax = 0x7160;		/* Truename */
+ 	  r.x.cx = 1;			/* Get short name */
+ 	  r.x.ds = r.x.es = __tb / 16;
+ 	  r.x.si = r.x.di = __tb & 15;
+ 	  __dpmi_int(0x21, &r);
+ 	  if (r.x.flags & 1 || r.x.ax == 0x7100)
+ 	    /* Shouldn't happen: LFN *is* supported and file *does* exist.  */
+ 	    {
+ 	      errno = EIO;
+ 	      return -1;
+ 	    }
+ 	  dosmemget (__tb, FILENAME_MAX, src_short);
+ 	}
+       else
+ 	{
+ 	  /* File doesn't exist.  Generate short name that would be used.
+ 	     FIXME: this will lose if the generated name collides with
+ 	     another file already in that directory; however, the only
+ 	     alternative is to disallow symlinks to non-existing files.  */
+ 	  char *p = strncpy (src_short, src_abs, src_base - src_abs);
+ 	  _lfn_gen_short_fname (src_base, p + (src_base - src_abs));
+ 	}
+     }
+   else
+     strcpy (src_short, src_abs);
+ 
+   /* Need the basename of SRC_SHORT sans the extension.  */
+   strcpy (ropt, "runfile=");
+   strcat (ropt, tail (src_short));
+   for (np = ropt + strlen (ropt) - 1; np > ropt; np--)
+     if (*np == '.')
+       {
+ 	*np = '\0';
+ 	break;
+       }
+ 
+   /* `stubedit' needs its argument with the .EXE suffix explicit.  */
+   np = dest_abs + strlen (dest_abs) - 4;
+   if (stricmp (np, EXE_SUFFIX))
+     strcat (dest_abs, EXE_SUFFIX);
+ 
+ 
+   if (spawnlp (P_WAIT, STUBIFY, STUBIFY, "-g", dest_abs, (char *)0)
+       || spawnlp (P_WAIT, STUBEDIT, STUBEDIT, dest_abs, ropt, (char *)0))
+     return -1;
+   return 0;
+ }
*** src/libc/posix/unistd/symlink.t~0	Wed Sep 18 09:12:16 1996
--- src/libc/posix/unistd/symlink.txh	Wed Sep 18 09:16:02 1996
***************
*** 0 ****
--- 1,41 ----
+ @node symlink, io
+ @subheading Syntax
+ 
+ @example
+ #include <unistd.h>
+ 
+ int symlink(const char *exists, const char *new);
+ @end example
+ 
+ @subheading Description
+ MSDOS doesn't support symbolic links.  However, DJGPP supports
+ ``symlinks'' to DJGPP programs.  This function simulates a symlink
+ between two @file{.exe} files in the DJGPP style.  It creates a program
+ whose name is given by @var{*new} which, when run, will actually execute
+ the program @var{*exists} passing it @var{*new} in @code{argv[0]} (some
+ programs change their behavior depending on what's passed in
+ @code{argv[0]}).  The file referred to by @var{exists} doesn't really
+ have to exist when this function is called.  Both @var{*new} and
+ @var{*exists} can point to a name with or without the @file{.exe}
+ extension.
+ 
+ Note that both @var{*exists} and @var{*new} must reside in the same
+ 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{stabify} and @samp{stubedit} programs, so
+ they should be somewhere on your @samp{PATH} for the function to
+ succeed.  (These programs come with the DJGPP development distribution.)
+ 
+ @subheading Return Value
+ 
+ Zero in case of success, -1 in case of failure (and @code{errno} set to
+ the appropriate error code).
+ 
+ @subheading Example
+ 
+ @example
+ symlink ("c:/djgpp/bin/grep", "c:/djgpp/bin/fgrep");
+ @end example
*** src/libc/posix/unistd/makefile.~0~	Sat Jul 15 14:34:24 1995
--- src/libc/posix/unistd/makefile	Wed Sep 18 17:34:08 1996
***************
*** 43,48 ****
--- 43,49 ----
  SRC += setsid.c
  SRC += setuid.c
  SRC += sleep.c
+ SRC += symlink.c
  SRC += sysconf.c
  SRC += ttyname.c
  SRC += unlink.s
*** include/unistd.h~0	Sun Jun 18 05:48:26 1995
--- include/unistd.h	Wed Sep 18 08:55:36 1996
***************
*** 129,134 ****
--- 129,135 ----
  char *		getwd(char *__buffer);
  int		nice(int _increment);
  void *		sbrk(int _delta);
+ int		symlink (const char *, const char *);
  int		sync(void);
  int		truncate(const char*, off_t);
  unsigned int	usleep(unsigned int _useconds);

- Raw text -


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