Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 31 Mar 2005 16:18:14 +0200 (CEST)
From:      Jean-Yves Lefort <jylefort@brutele.be>
To:        FreeBSD-gnats-submit@FreeBSD.org
Subject:   ports/79398: New port: archivers/unmakeself, and make bsd.port.mk use it
Message-ID:  <20050331141814.5DC41869C@jsite.lefort.net>
Resent-Message-ID: <200503311420.j2VEK4pA001103@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help

>Number:         79398
>Category:       ports
>Synopsis:       New port: archivers/unmakeself, and make bsd.port.mk use it
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    freebsd-ports-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Thu Mar 31 14:20:04 GMT 2005
>Closed-Date:
>Last-Modified:
>Originator:     Jean-Yves Lefort
>Release:        FreeBSD 5.3-RELEASE-p6 i386
>Organization:
>Environment:
System: FreeBSD jsite.lefort.net 5.3-RELEASE-p6 FreeBSD 5.3-RELEASE-p6 #0: Tue Mar 29 00:14:29 CEST 2005 jylefort@jsite.lefort.net:/usr/obj/usr/src/sys/JSITE i386
>Description:
Here's a port for extracting Makeself archives. They are the .run or
.sh self-extracting shell scripts most commercial games ship as.

Several ports (mostly games) use Makeself archives as distfiles. With
the provided bsd.port.mk patch, they can now define USE_MAKESELF=yes
instead of manually specifying EXTRACT_SUFX and do-extract.
>How-To-Repeat:
>Fix:
# This is a shell archive.  Save it in a file, remove anything before
# this line, and then unpack it by entering "sh file".  Note, it may
# create directories; files and directories will be owned by you and
# have default permissions.
#
# This archive contains:
#
#	unmakeself
#	unmakeself/files
#	unmakeself/files/unmakeself.c
#	unmakeself/pkg-descr
#	unmakeself/Makefile
#
echo c - unmakeself
mkdir -p unmakeself > /dev/null 2>&1
echo c - unmakeself/files
mkdir -p unmakeself/files > /dev/null 2>&1
echo x - unmakeself/files/unmakeself.c
sed 's/^X//' >unmakeself/files/unmakeself.c << 'END-of-unmakeself/files/unmakeself.c'
X/*
X * unmakeself - extracts Makeself archives
X *
X * Copyright (C) 2005 Jean-Yves Lefort
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms, with or without
X * modification, are permitted provided that the following conditions
X * are met:
X * 1. Redistributions of source code must retain the above copyright
X *    notice, this list of conditions and the following disclaimer.
X * 2. Redistributions in binary form must reproduce the above copyright
X *    notice, this list of conditions and the following disclaimer in the
X *    documentation and/or other materials provided with the distribution.
X * 3. Neither the name of Jean-Yves Lefort nor the names of its contributors
X *    may be used to endorse or promote products derived from this software
X *    without specific prior written permission.
X *
X * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
X * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
X * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
X * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
X * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
X * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
X * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
X * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
X * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
X * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
X * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
X * POSSIBILITY OF SUCH DAMAGE.
X */
X
X#include <stdio.h>
X#include <stdlib.h>
X#include <locale.h>
X#include <string.h>
X#include <errno.h>
X#include <fcntl.h>
X#include <sys/types.h>
X#include <sys/uio.h>
X#include <unistd.h>
X#include <getopt.h>
X#include <archive.h>
X
Xstatic char *self = NULL;				/* program name */
Xstatic int extract_flags = ARCHIVE_EXTRACT_TIME;	/* bsdtar default */
X
Xstatic void unmakeself_print_help (void);
Xstatic void unmakeself_print_version (void);
Xstatic void unmakeself_extract (const char *filename);
X
Xint
Xmain (int argc, char **argv)
X{
X  const struct option options[] = {
X    { "help",			no_argument,	NULL, '?'	},
X    { "version",		no_argument,	NULL, 'v'	},
X    { "keep-old-files",		no_argument,	NULL, 'k'	},
X    { "modification-time",	no_argument,	NULL, 'm'	},
X    { "no-same-owner",		no_argument,	NULL, 'o'	},
X    { "preserve-permissions",	no_argument,	NULL, 'p'	},
X    { "unlink",			no_argument,	NULL, 'U'	},
X    { "unlink-first",		no_argument,	NULL, 'U'	},
X    { NULL,			0,		NULL, 0		}
X  };
X  int c;
X
X  self = argc > 0 ? strdup(argv[0]) : "unmakeself";
X  setlocale(LC_ALL, "");
X
X  if (geteuid() == 0)		/* bsdtar does this */
X    extract_flags |= ARCHIVE_EXTRACT_OWNER;
X
X  while ((c = getopt_long(argc, argv, "?vkmpUx", options, NULL)) != -1)
X    switch (c)
X      {
X      case '?':
X	unmakeself_print_help();
X	exit(0);
X	break;
X
X      case 'v':
X	unmakeself_print_version();
X	exit(0);
X	break;
X
X      case 'k':			/* GNU tar, bsdtar */
X	extract_flags |= ARCHIVE_EXTRACT_NO_OVERWRITE;
X	break;
X
X      case 'm':			/* SUSv2, bsdtar */
X	extract_flags &= ~ARCHIVE_EXTRACT_TIME;
X	break;
X
X      case 'o':			/* bsdtar */
X	extract_flags &= ~ARCHIVE_EXTRACT_OWNER;
X	break;
X
X      case 'p':			/* GNU tar, star, bsdtar */
X	extract_flags |= ARCHIVE_EXTRACT_PERM;
X	extract_flags |= ARCHIVE_EXTRACT_ACL;
X	extract_flags |= ARCHIVE_EXTRACT_FFLAGS;
X	break;
X
X      case 'U':			/* GNU tar, bsdtar */
X	extract_flags |= ARCHIVE_EXTRACT_UNLINK;
X	break;
X
X      default:
X	abort();
X      }
X
X  argc -= optind;
X  argv += optind;
X
X  if (argc != 1)
X    {
X      fprintf(stderr, "%s: a file to extract must be specified\n", self);
X      exit(1);
X    }
X
X  unmakeself_extract(argv[0]);
X
X  /* on some systems, the return value of main() is ignored */
X  exit(0);
X
X  return 0;
X}
X
Xstatic void
Xunmakeself_print_help (void)
X{
X  printf("Synopsis:\n");
X  printf("  %s {-? | -v}\n", self);
X  printf("  %s [-kmopU] FILE\n", self);
X}
X
Xstatic void
Xunmakeself_print_version (void)
X{
X  printf("unmakeself version 0.99\n");
X  printf("Copyright (C) 2005 Jean-Yves Lefort\n");
X}
X
Xstatic void
Xunmakeself_extract (const char *filename)
X{
X  int fd;
X  char buf[4096];
X  int pos = 0;
X  int last_newline = -1;
X  int offset = -1;
X  int done = 0;
X  ssize_t len;
X
X  fd = open(filename, O_RDONLY);
X  if (fd < 0)
X    {
X      fprintf(stderr, "%s: unable to open %s: %s\n", self, filename, strerror(errno));
X      exit(1);
X    }
X
X  /*
X   * We find the start offset of the archive inside the shell script
X   * by locating the first non-printable character following a
X   * newline. The archive starts immediately after that newline.
X   */
X  while (! done && (len = read(fd, buf, sizeof(buf))) > 0)
X    {
X      int i;
X
X      for (i = 0; i < len; i++, pos++)
X	if (buf[i] == '\n')
X	  last_newline = pos;
X	else if (buf[i] != '\t' && (buf[i] < 32 || buf[i] > 126))
X	  {
X	    if (last_newline != -1)
X	      offset = last_newline + 1;
X	    
X	    done = 1;
X	    break;
X	  }
X    }
X
X  if (offset != -1)		/* offset found, extract using libarchive */
X    {
X      struct archive *archive;
X      struct archive_entry *entry;
X      int status;
X
X      if (lseek(fd, offset, SEEK_SET) < 0)
X	{
X	  fprintf(stderr, "%s: unable to seek into %s: %s\n", self, filename, strerror(errno));
X	  exit(1);
X	}
X      
X      archive = archive_read_new();
X
X      if (archive_read_support_compression_all(archive) != ARCHIVE_OK)
X	fprintf(stderr, "%s: warning: unable to support all compression formats: %s\n", self, archive_error_string(archive));
X      if (archive_read_support_format_all(archive) != ARCHIVE_OK)
X	fprintf(stderr, "%s: warning: unable to support all archive formats: %s\n", self, archive_error_string(archive));
X
X      /* same block size as DEFAULT_BYTES_PER_BLOCK in bsdtar.h */
X      if (archive_read_open_fd(archive, fd, 20 * 512) != ARCHIVE_OK)
X	{
X	  fprintf(stderr, "%s: unable to open %s with libarchive: %s\n", self, filename, archive_error_string(archive));
X	  exit(1);
X	}
X      
X      while ((status = archive_read_next_header(archive, &entry)) == ARCHIVE_OK)
X	if (archive_read_extract(archive, entry, extract_flags) != ARCHIVE_OK)
X	  {
X	    fprintf(stderr, "%s: unable to extract %s: %s\n", self, filename, archive_error_string(archive));
X	    exit(1);
X	  }
X
X      if (status != ARCHIVE_EOF)
X	{
X	  fprintf(stderr, "%s: unable to read next header of %s: %s\n", self, filename, archive_error_string(archive));
X	  exit(1);
X	}
X      
X      if (archive_read_close(archive) != ARCHIVE_OK)
X	{
X	  fprintf(stderr, "%s: unable to close %s with libarchive: %s\n", self, filename, archive_error_string(archive));
X	  exit(1);
X	}
X      
X      archive_read_finish(archive);
X    }
X  else
X    {
X      if (len >= 0)		/* EOF, or couldn't find start offset */
X	{
X	  fprintf(stderr, "%s: %s is not a valid Makeself archive\n", self, filename);
X	  exit(1);
X	}
X      else			/* read error */
X	{
X	  fprintf(stderr, "%s: unable to read %s: %s\n", self, filename, strerror(errno));
X	  exit(1);
X	}
X    }
X
X  if (close(fd) < 0)
X    {
X      fprintf(stderr, "%s: unable to close %s: %s\n", self, filename, strerror(errno));
X      exit(1);
X    }
X}
END-of-unmakeself/files/unmakeself.c
echo x - unmakeself/pkg-descr
sed 's/^X//' >unmakeself/pkg-descr << 'END-of-unmakeself/pkg-descr'
Xunmakeself is a program for extracting Makeself archives without
Xhaving to run the self-extracting shell script.
X
X- Jean-Yves Lefort
Xjylefort@brutele.be
END-of-unmakeself/pkg-descr
echo x - unmakeself/Makefile
sed 's/^X//' >unmakeself/Makefile << 'END-of-unmakeself/Makefile'
X# New ports collection makefile for:	unmakeself
X# Date created:			31 Mar 2005
X# Whom:				Jean-Yves Lefort <jylefort@brutele.be>
X#
X# $FreeBSD$
X#
X
XPORTNAME=		unmakeself
XPORTVERSION=		0.99
XCATEGORIES=		archivers
XDISTFILES=
X
XMAINTAINER=		jylefort@brutele.be
XCOMMENT=		Extract Makeself archives
X
XLDFLAGS=		-larchive -lbz2 -lz
XUSE_GETOPT_LONG=	yes
XNO_WRKSUBDIR=		yes
X
XPLIST_FILES=		bin/unmakeself
X
X.include <bsd.port.pre.mk>
X
X.if ${OSVERSION} < 502103
XBUILD_DEPENDS+=		${LOCALBASE}/lib/libarchive.a:${PORTSDIR}/archivers/libarchive
XCPPFLAGS+=		-I${LOCALBASE}/include
XLDFLAGS+=		-L${LOCALBASE}/lib
X.endif
X
Xdo-build:
X	${CC} ${CFLAGS} ${CPPFLAGS} -o ${WRKSRC}/unmakeself \
X		${FILESDIR}/unmakeself.c ${LDFLAGS}
X
Xdo-install:
X	${MKDIR} ${PREFIX}/bin
X	${INSTALL_PROGRAM} ${WRKSRC}/unmakeself ${PREFIX}/bin
X
X.include <bsd.port.post.mk>
END-of-unmakeself/Makefile
exit

--- bsd.port.mk.orig	Fri Mar 18 09:45:37 2005
+++ bsd.port.mk	Thu Mar 31 14:01:21 2005
@@ -92,7 +92,7 @@
 # EXTRACT_SUFX	- Suffix for archive names
 #				  You never have to set both DISTFILES and EXTRACT_SUFX.
 #				  Default: .tar.bz2 if USE_BZIP2 is set, .zip if USE_ZIP is
-#				  set, .tar.gz otherwise).
+#				  set, .run if USE_MAKESELF is set, .tar.gz otherwise).
 # MASTER_SITES	- Primary location(s) for distribution files if not found
 #				  locally.  See bsd.sites.mk for common choices for
 #				  MASTER_SITES.
@@ -216,6 +216,8 @@
 #				  compression.
 # USE_ZIP		- If set, this port distfile uses zip, not tar w/[bg]zip
 #				  for compression.
+# USE_MAKESELF	- If set, this port distfile uses makeself, not tar w/[bg]zip
+#				  for compression.
 # USE_GCC		- If set, this port requires this version of gcc, either in
 #				  the system or installed from a port.
 # USE_GMAKE		- If set, this port uses gmake.
@@ -701,7 +703,8 @@
 # For extract:
 #
 # EXTRACT_CMD	- Command for extracting archive: "bzip2" if USE_BZIP2
-#				  is set, "unzip" if USE_ZIP is set, "gzip" otherwise.
+#				  is set, "unzip" if USE_ZIP is set, "unmakeself" if
+#				  USE_MAKESELF if set, "gzip" otherwise.
 # EXTRACT_BEFORE_ARGS
 #				- Arguments to ${EXTRACT_CMD} before filename.
 #				  Default: "-dc"
@@ -989,6 +992,7 @@
 UNZIP_CMD?=	${LOCALBASE}/bin/unzip
 ZIPDEPENDS=	yes
 .endif
+UNMAKESELF_CMD?= ${LOCALBASE}/bin/unmakeself
 WHICH?=		/usr/bin/which
 XARGS?=		/usr/bin/xargs
 YACC?=		/usr/bin/yacc
@@ -1176,6 +1180,8 @@
 EXTRACT_SUFX?=			.tar.bz2
 .elif defined(USE_ZIP)
 EXTRACT_SUFX?=			.zip
+.elif defined(USE_MAKESELF)
+EXTRACT_SUFX?=			.run
 .else
 EXTRACT_SUFX?=			.tar.gz
 .endif
@@ -1433,6 +1439,9 @@
 .if defined(USE_ZIP) && defined(ZIPDEPENDS)
 EXTRACT_DEPENDS+=	unzip:${PORTSDIR}/archivers/unzip
 .endif
+.if defined(USE_MAKESELF)
+EXTRACT_DEPENDS+=	unmakeself:${PORTSDIR}/archivers/unmakeself
+.endif
 .if defined(USE_GMAKE)
 BUILD_DEPENDS+=		gmake:${PORTSDIR}/devel/gmake
 CONFIGURE_ENV+=	MAKE=${GMAKE}
@@ -1943,6 +1952,10 @@
 EXTRACT_CMD?=		${UNZIP_CMD}
 EXTRACT_BEFORE_ARGS?=	-qo
 EXTRACT_AFTER_ARGS?=	-d ${WRKDIR}
+.elif defined(USE_MAKESELF)
+EXTRACT_CMD?=		${UNMAKESELF_CMD}
+EXTRACT_BEFORE_ARGS?=
+EXTRACT_AFTER_ARGS?=
 .else
 EXTRACT_BEFORE_ARGS?=	-dc
 EXTRACT_AFTER_ARGS?=	| ${TAR} -xf -
>Release-Note:
>Audit-Trail:
>Unformatted:



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20050331141814.5DC41869C>