home *** CD-ROM | disk | FTP | other *** search
/ PC Extra Super CD 1998 January / PCPLUS131.iso / DJGPP / V2 / DJLSR201.ZIP / src / libc / posix / unistd / symlink.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-09-19  |  3.3 KB  |  120 lines

  1. #include <libc/stubs.h>
  2. #include <stdio.h>
  3. #include <string.h>
  4. #include <errno.h>
  5. #include <fcntl.h>
  6. #include <unistd.h>
  7. #include <sys/stat.h>
  8. #include <process.h>
  9. #include <dpmi.h>
  10. #include <go32.h>
  11.  
  12. static char EXE_SUFFIX[] = ".exe";
  13. static char STUBIFY[]     = "stubify.exe";
  14. static char STUBEDIT[]     = "stubedit.exe";
  15.  
  16. /* Return a pointer to the tail of the pathname.  */
  17. static const char *
  18. tail (const char *path)
  19. {
  20.   const char *p = path ? path + strlen (path) - 1 : path;
  21.  
  22.   if (p)
  23.     {
  24.       while (p > path && *p != '/' && *p != '\\' && *p != ':')
  25.     p--;
  26.       if (p > path)
  27.     p++;
  28.     }
  29.   return p;
  30. }
  31.  
  32. /* Support the DJGPP ``symlinks'' for .exe files.  */
  33. int
  34. symlink (const char *source, const char *dest)
  35. {
  36.   char src_abs[FILENAME_MAX+5], src_short[FILENAME_MAX+5];
  37.   char dest_abs[FILENAME_MAX+5];
  38.   char *np, ropt[FILENAME_MAX+15]; /* some extra for ``runfile='' */
  39.   const char *src_base, *dest_base;
  40.  
  41.   _fixpath (source, src_abs);
  42.   _fixpath (dest, dest_abs);
  43.   src_base = tail (src_abs);
  44.   dest_base = tail (dest_abs);
  45.  
  46.   /* DJGPP symlinks must be in the same directory.  */
  47.   if (strnicmp (src_abs, dest_abs, src_base - src_abs))
  48.     {
  49.       errno = EXDEV;
  50.       return -1;
  51.     }
  52.  
  53.   /* Any file is already a link to itself.  */
  54.   if (stricmp (src_abs, dest_abs) == 0)
  55.     return 0;
  56.  
  57.   /* Allow to say `ln -s src dest' when we really
  58.      mean `src.exe' and `dest.exe'  */
  59.   np = src_abs + strlen (src_abs) - 4;
  60.   if (stricmp (np, EXE_SUFFIX))
  61.     strcat (src_abs, EXE_SUFFIX);
  62.  
  63.   /* Under LFN, we need the short version of the program name, since that
  64.      is what the stub stores (and what a program gets in its argv[0]).  */
  65.   if (_USE_LFN)
  66.     {
  67.       if (__file_exists (src_abs))
  68.     {
  69.       /* File exists.  Get its 8+3 alias.  */
  70.       __dpmi_regs r;
  71.  
  72.       dosmemput(src_abs, strlen (src_abs)+1, __tb);
  73.       r.x.ax = 0x7160;        /* Truename */
  74.       r.x.cx = 1;            /* Get short name */
  75.       r.x.ds = r.x.es = __tb / 16;
  76.       r.x.si = r.x.di = __tb & 15;
  77.       __dpmi_int(0x21, &r);
  78.       if (r.x.flags & 1 || r.x.ax == 0x7100)
  79.         /* Shouldn't happen: LFN *is* supported and file *does* exist.  */
  80.         {
  81.           errno = EIO;
  82.           return -1;
  83.         }
  84.       dosmemget (__tb, FILENAME_MAX, src_short);
  85.     }
  86.       else
  87.     {
  88.       /* File doesn't exist.  Generate short name that would be used.
  89.          FIXME: this will lose if the generated name collides with
  90.          another file already in that directory; however, the only
  91.          alternative is to disallow symlinks to non-existing files.  */
  92.       char *p = strncpy (src_short, src_abs, src_base - src_abs);
  93.       _lfn_gen_short_fname (src_base, p + (src_base - src_abs));
  94.     }
  95.     }
  96.   else
  97.     strcpy (src_short, src_abs);
  98.  
  99.   /* Need the basename of SRC_SHORT sans the extension.  */
  100.   strcpy (ropt, "runfile=");
  101.   strcat (ropt, tail (src_short));
  102.   for (np = ropt + strlen (ropt) - 1; np > ropt; np--)
  103.     if (*np == '.')
  104.       {
  105.     *np = '\0';
  106.     break;
  107.       }
  108.  
  109.   /* `stubedit' needs its argument with the .EXE suffix explicit.  */
  110.   np = dest_abs + strlen (dest_abs) - 4;
  111.   if (stricmp (np, EXE_SUFFIX))
  112.     strcat (dest_abs, EXE_SUFFIX);
  113.  
  114.  
  115.   if (spawnlp (P_WAIT, STUBIFY, STUBIFY, "-g", dest_abs, (char *)0)
  116.       || spawnlp (P_WAIT, STUBEDIT, STUBEDIT, dest_abs, ropt, (char *)0))
  117.     return -1;
  118.   return 0;
  119. }
  120.