Mail Archives: djgpp-workers/1996/09/18/13:13:11
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 -