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) Content-type: text/plain; charset=us-ascii 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> Content-Transfer-Encoding: 8bit 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 Precedence: bulk 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; }