www.delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp-workers/2005/01/12/23:54:17

X-Authentication-Warning: delorie.com: mail set sender to djgpp-workers-bounces using -f
Date: Wed, 12 Jan 2005 21:53:47 -0700
From: Brian Inglis <Brian DOT Inglis AT SystematicSw DOT ab DOT ca>
Subject: Re: ANNOUNCE: DJGPP port of GNU gzip-1.3.5 uploaded
In-reply-to: <01c4e928$Blat.v2.2.2$fb5f31a0@zahav.net.il>
To: djgpp-workers AT delorie DOT com
Message-id: <1ivbu0pv2hh31kfsvblhbn4lshpfi3drp2@4ax.com>
Organization: Systematic Software
MIME-version: 1.0
X-Mailer: Forte Agent 1.93/32.576 English (American)
References: <200412191748 DOT iBJHmmaM005825 AT envy DOT delorie DOT com>
<01c4e604$Blat.v2.2.2$63db7180 AT zahav DOT net DOT il>
<38obs0ddbi3hjj9rj1753em0fi7qcm20or AT 4ax DOT com>
<01c4e718$Blat.v2.2.2$633278e0 AT zahav DOT net DOT il>
<200412211534 DOT iBLFYXii019390 AT envy DOT delorie DOT com>
<01c4e797$Blat.v2.2.2$6714a260 AT zahav DOT net DOT il>
<bbvhs05qaa8gghciljptu89vojtvkk2i47 AT 4ax DOT com>
<01c4e854$Blat.v2.2.2$09be9b80 AT zahav DOT net DOT il>
<kgmks05q8sjh250gp7es1mfmru16c3c6kf AT 4ax DOT com>
<01c4e928$Blat.v2.2.2$fb5f31a0 AT zahav DOT net DOT il>
X-MIME-Autoconverted: from quoted-printable to 8bit by delorie.com id j0D4rtZk002955
Reply-To: djgpp-workers AT delorie DOT com
Errors-To: nobody AT delorie DOT com
X-Mailing-List: djgpp-workers AT delorie DOT com
X-Unsubscribes-To: listserv AT delorie DOT com

On Thu, 23 Dec 2004 21:51:47 +0200, Eli Zaretskii <eliz AT gnu DOT org> wrote:

>> Date: Wed, 22 Dec 2004 22:42:41 -0700
>> From: Brian Inglis <Brian DOT Inglis AT SystematicSw DOT ab DOT ca>
>> 
>> >  if (spawnlp (P_WAIT, STUBIFY, STUBIFY, "-g", dest_abs, (char *)0)
>> >      || spawnlp (P_WAIT, STUBEDIT, STUBEDIT, dest_abs, ropt, (char *)0))
>> >    return -1;
>> >
>> >Should we create a v2.04 style symlink if stubify and/or stubedit
>> >failed in this fragment?  I don't know.
>> 
>> I guess some research into the failure modes and return codes of
>> stubify and stubedit are in order. 
>
>Indeed.
>
>> The intermingling of 2.03 and 2.04 symlinks is looking more
>> interesting (as in the Chinese curse!) 
>
>Happy hacking!

I've read everything useful I could find on the workers archives
about the old and new symlinks. 
I'd like some review feedback on the design and implementation
of a version of symlink that creates new symlinks unless
a v2 prog exists or an exe file is specified and does not exist. 
It started out as a version of old symlink that called the new
symlink instead of returning an error code, and the design and
implementation has evolved from there. 
Any/all comments, suggestions, questions about the approach
taken or the appended code are welcome.
It's compilable and could be tested, but I'm not yet ready to
take that step, until I find out if the design decisions can
be considered valid.

Thanks. Take care, Brian Inglis


/* Copyright (C) 2005 DJ Delorie, see COPYING.DJ for details */
/* Copyright (C) 2004 DJ Delorie, see COPYING.DJ for details */
/* Copyright (C) 2003 DJ Delorie, see COPYING.DJ for details */
/* Copyright (C) 2002 DJ Delorie, see COPYING.DJ for details */
/* Copyright (C) 2000 DJ Delorie, see COPYING.DJ for details */
/* Copyright (C) 1999 DJ Delorie, see COPYING.DJ for details */
/* Copyright (C) 1997 DJ Delorie, see COPYING.DJ for details */

#include <libc/stubs.h>
#include <libc/fsexthlp.h>
#include <libc/symlink.h>

#include <sys/fsext.h>
#include <sys/stat.h>
#include <sys/system.h>

#include <errno.h>
#include <limits.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <dpmi.h>
#include <fcntl.h>
#include <go32.h>
#include <io.h>
#include <process.h>
#include <unistd.h>

#include "xsymlink.h"

/* Emulate symlinks for all files */
static int
softlink(const char *src, const char *dst)
{
   int         symlink_file;
   static char fill_buf[_SYMLINK_FILE_LEN - _SYMLINK_PREFIX_LEN + 1] =
                             "\nThis is just a text to force symlink file to "
                             "be 510 bytes long. Do not delete it nor spaces "
                             "following it.";

   memset(fill_buf + strlen(fill_buf), ' ',
                _SYMLINK_FILE_LEN - _SYMLINK_PREFIX_LEN - strlen(fill_buf));

   if ((symlink_file = _creat(dst, 0)) < 0)
      return -1; /* Return errno from creat() call */

   write(symlink_file, _SYMLINK_PREFIX, _SYMLINK_PREFIX_LEN);
   write(symlink_file, src, strlen(src));
   write(symlink_file, fill_buf,
                        _SYMLINK_FILE_LEN - _SYMLINK_PREFIX_LEN - strlen(src));
   _close(symlink_file);

   return 0;
}

/*
  is_v2_prog returns:
    non-zero, when program is     a v2 executable
        zero, when program is NOT a v2 executable
*/
static int
is_v2_prog(const char *program)
{
  const _v2_prog_type *type = _check_v2_prog(program, -1);

  return (type && type->valid && type->version.v.major >= 2
                && type->object_format == _V2_OBJECT_FORMAT_COFF);
}

/* get file's 8+3 alias */
static char *
get_shorty( char *short_name, const char *long_name, int short_len)
{
      __dpmi_regs r;

      dosmemput(long_name, strlen(long_name)+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.  */
        return NULL;

      dosmemget(__tb, short_len, short_name);
      return short_name;
}

static const char EXE_SUFFIX[] = ".exe";
static const char STUBIFY[]    = "stubify.exe";
static const char STUBEDIT[]   = "stubedit.exe";

/* Support the DJGPP ``symlinks'' for .exe files.  */
int
symlink(const char *src, const char *dst)
{
  char        ropt[PATH_MAX+10] = "runfile=";
  char        src_real[PATH_MAX];
  char        src_abs[PATH_MAX];
  char        src_short[PATH_MAX];
  char        dst_real[PATH_MAX];
  char        dst_abs[PATH_MAX];
  char *      src_base;
  char *      dst_base;
  char *      np;
  int         ret;

  /* Common error conditions */
  if (!src || !dst || !*src || !*dst)
  {
     errno = EINVAL;
     return -1;
  }

  /* Provide ability to hook symlink support */
  if (__FSEXT_call_open_handlers_wrapper(__FSEXT_symlink, &ret, src, dst))
     return ret;

  /* src may have symlinks in the path */
  if (!__solve_symlinks(src, src_real))
     return -1; /* Errno (ELOOP) from __solve_symlinks() call.  */

  /* dst may have symlinks somewhere in the path */
  if (!__solve_symlinks(dst, dst_real))
     return -1; /* Errno (ELOOP) from __solve_symlinks() call.  */

  _fixpath(src_real, src_abs);
  _fixpath(dst_real, dst_abs);

  /* Any file is already a link to itself.  */
  if (stricmp(src_abs, dst_abs) == 0)
    return 0;

  /* Check if there already is file with symlink's name */
  if (__file_exists(dst_abs))
  {
    errno = EEXIST;
    return -1;
  }

  src_base = basename(src_abs);
  dst_base = basename(dst_abs);

  /* DJGPP symlinks must be in the same directory.  */
  if (src_base - src_abs != dst_base - dst_abs
      || strnicmp (src_abs, dst_abs, src_base - src_abs))
  {
    /* not in same directory */
    return softlink( src, dst_real);
  }

  /* check if src exists */
  if (__file_exists(src_abs))
  {
    /* Check at first, if the given name is a v2 executable (may be
       unstubbed COFF image) */
    if (!is_v2_prog(src_abs))
    {
      /* not v2 executable */
      return softlink( src, dst_real);
    }
  }
  else /* src does not exist */
  {
    /* if src base name has no suffix */
    if (!(np = strrchr( src_base, '.')))
    {
      /* add exe suffix */
      strcat(src_base, EXE_SUFFIX);

      /* check if exe exists */
      if (__file_exists(src_abs))
      {
        /* Now test again for v2 executable */
        if (!is_v2_prog(src_abs))
        {
          /* not v2 executable */
          return softlink( src, dst_real);
        }
      }
    }
    else /* src already has suffix */
    {
      /* if suffix wrong length or not exe */
      if (np != src_base + strlen( src_base ) - strlen( EXE_SUFFIX )
                                        || stricmp( np, EXE_SUFFIX))
        return softlink( src, dst_real);
    } /* src already has suffix */
  } /* src does not exist */

  /* 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]).  */
  if (_USE_LFN)
  {
    if (__file_exists(src_abs))
    {
      /* File exists.  Get its 8+3 alias.  */
      if (!get_shorty( src_short, src_abs, PATH_MAX))
      {
        return softlink( src, dst_real);
      }
    }
    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.  */
  strcat(ropt, basename(src_short));
  if ((np = strrchr( ropt, '.')))
    *np = '\0';

  /* `stubedit' needs its argument with the .EXE suffix explicit.  */
  np = dst_abs + strlen(dst_abs);
  if (np - strlen( EXE_SUFFIX ) > dst_abs
      && stricmp(np - strlen( EXE_SUFFIX ), EXE_SUFFIX))
    strcpy(np, EXE_SUFFIX);

  if (spawnlp(P_WAIT, STUBIFY, STUBIFY, "-g", dst_abs, NULL)
      || spawnlp(P_WAIT, STUBEDIT, STUBEDIT, dst_abs, ropt, NULL))
    return -1;
  return 0;
}

- Raw text -


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