Skip to content

Instantly share code, notes, and snippets.

@mame
Created May 10, 2012 13:40
Show Gist options
  • Save mame/2653054 to your computer and use it in GitHub Desktop.
Save mame/2653054 to your computer and use it in GitHub Desktop.
sfx support of ruby
From 552877c780545e8b25ededf8fa2f0042597b6bcb Mon Sep 17 00:00:00 2001
From: Yusuke Endoh <[email protected]>
Date: Thu, 10 May 2012 22:38:46 +0900
Subject: [PATCH] * sfx support.
---
cygwin/GNUmakefile.in | 11 ++++++---
io.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++++
ruby.c | 16 +++++++++++++
win32/fix-size.rb | 20 ++++++++++++++++
win32/resource.rb | 2 ++
5 files changed, 110 insertions(+), 3 deletions(-)
create mode 100644 win32/fix-size.rb
diff --git a/cygwin/GNUmakefile.in b/cygwin/GNUmakefile.in
index 19d1727..81cdb82 100644
--- a/cygwin/GNUmakefile.in
+++ b/cygwin/GNUmakefile.in
@@ -48,11 +48,11 @@ scriptbin: $(SCRIPTPROGRAMS)
$(LIBRUBY): $(RUBY_EXP) $(LIBRUBY_SO)
$(RUBY_EXP) $(LIBRUBY_SO): $(DLL_BASE_NAME).res.@OBJEXT@
-%.res.@OBJEXT@: %.rc
+%.res.@OBJEXT@: %.rc %.size
$(ECHO) compiling $@
$(Q) $(WINDRES) --include-dir . --include-dir $(<D) --include-dir $(srcdir)/win32 $< $@
-$(RCFILES): $(RBCONFIG) $(srcdir)/revision.h $(srcdir)/win32/resource.rb
+$(RCFILES) $(RCFILES:.rc=.size): $(RBCONFIG) $(srcdir)/revision.h $(srcdir)/win32/resource.rb
$(ECHO) generating $@
$(Q) $(MINIRUBY) $(srcdir)/win32/resource.rb \
-ruby_name=$(RUBY_INSTALL_NAME) -rubyw_name=$(RUBYW_INSTALL_NAME) \
@@ -60,11 +60,16 @@ $(RCFILES): $(RBCONFIG) $(srcdir)/revision.h $(srcdir)/win32/resource.rb
. $(icondirs) $(srcdir)/win32
$(PROGRAM): $(RUBY_INSTALL_NAME).res.@OBJEXT@
+ @rm -f $@
+ $(ECHO) linking $@
+ $(Q) $(PURIFY) $(CC) $(LDFLAGS) $(XLDFLAGS) $(MAINLIBS) $(MAINOBJ) $(EXTOBJS) $(LIBRUBYARG) $(LIBS) $(OUTFLAG)$@
+ $(Q) $(MINIRUBY) "$(srcdir)/win32/fix-size.rb" $@ $(RUBY_INSTALL_NAME).size
$(WPROGRAM): $(RUBYW_INSTALL_NAME).res.@OBJEXT@
@rm -f $@
$(ECHO) linking $@
$(Q) $(PURIFY) $(CC) -mwindows -e $(SYMBOL_PREFIX)mainCRTStartup $(LDFLAGS) $(XLDFLAGS) \
$(MAINOBJ) $(EXTOBJS) $(LIBRUBYARG) $(LIBS) -o $@
+ $(Q) $(MINIRUBY) "$(srcdir)/win32/fix-size.rb" $@ $(RUBYW_INSTALL_NAME).size
$(STUBPROGRAM): $(RUBY_INSTALL_NAME).res.@OBJEXT@ stub.@OBJEXT@
@rm -f $@
$(ECHO) linking $@
@@ -103,5 +108,5 @@ cygwin-$(RUBY_INSTALL_NAME)$(MAJOR)$(MINOR)$(TEENY).dll: $(LIBRUBY_A) $(RUBYDEF)
endif
clean-local::
- @$(RM) $(RUBY_EXP) $(RCFILES:.rc=.res.@OBJEXT@)
+ @$(RM) $(RUBY_EXP) $(RCFILES:.rc=.res.@OBJEXT@) $(RCFILES:.rc=.size)
@$(RM) $(RCFILES)
diff --git a/io.c b/io.c
index 96087d6..9947a75 100644
--- a/io.c
+++ b/io.c
@@ -7191,6 +7191,70 @@ rb_io_set_autoclose(VALUE io, VALUE autoclose)
return io;
}
+#if defined(_WIN32)
+static long
+get_embedded_payload_offset(void)
+{
+ HINSTANCE hInstance;
+ HRSRC hRes;
+ HGLOBAL hGlobal = NULL;
+ DWORD size;
+ unsigned char *buf;
+ long offset;
+
+ hInstance = (HINSTANCE)GetModuleHandle(0);
+ hRes = FindResource(hInstance, "RUBY_PAYLOAD_OFFSET", RT_RCDATA);
+ if (hRes == NULL) goto err;
+ hGlobal = LoadResource(hInstance, hRes);
+ if (hGlobal == NULL) goto err;
+ size = SizeofResource(hInstance, hRes);
+ if (size != 4) goto err;
+ buf = (unsigned char *) LockResource(hGlobal);
+ if (buf == NULL) goto err;
+ offset = ((long) buf[0]);
+ offset |= ((long) buf[1]) << 8;
+ offset |= ((long) buf[2]) << 16;
+ offset |= ((long) buf[3]) << 24;
+ if (offset < 0) goto err;
+ FreeResource(hGlobal);
+
+ return offset;
+
+err:
+ if (hGlobal) FreeResource(hGlobal);
+ return -1;
+}
+
+VALUE
+rb_io_open_embedded_payload(void)
+{
+ VALUE f;
+ int fd, mode = O_RDONLY;
+ char fname[_MAX_PATH+1];
+ struct stat buf;
+ long offset;
+
+ offset = get_embedded_payload_offset();
+ if (offset < 0) return Qnil;
+
+ GetModuleFileName((HINSTANCE)GetModuleHandle(0), fname, _MAX_PATH);
+ if ((fd = rb_cloexec_open(fname, mode, 0)) < 0) {
+ rb_load_fail(Qnil, strerror(errno));
+ }
+ rb_update_max_fd(fd);
+ if (fstat(fd, &buf) != 0) goto err;
+ if (buf.st_size <= offset) goto err;
+ f = rb_io_fdopen(fd, mode, fname);
+ rb_io_seek(f, LONG2NUM(offset), SEEK_SET);
+
+ return f;
+
+err:
+ close(fd);
+ return Qnil;
+}
+#endif
+
static void
argf_mark(void *ptr)
{
diff --git a/ruby.c b/ruby.c
index 93779a7..677ee82 100644
--- a/ruby.c
+++ b/ruby.c
@@ -121,6 +121,11 @@ static struct {
char **argv;
} origarg;
+#if defined(_WIN32)
+static VALUE rb_embedded_payload = Qnil;
+extern VALUE rb_io_open_embedded_payload(void);
+#endif
+
static void
usage(const char *name)
{
@@ -695,6 +700,14 @@ proc_options(long argc, char **argv, struct cmdline_options *opt, int envopt)
long n, argc0 = argc;
const char *s;
+#if defined(_WIN32)
+ rb_embedded_payload = rb_io_open_embedded_payload();
+ if (rb_embedded_payload != Qnil) {
+ opt->disable = ~0U;
+ return 0;
+ }
+#endif
+
if (argc == 0)
return 0;
@@ -1512,6 +1525,9 @@ load_file_internal(VALUE arg)
if (strcmp(fname, "-") == 0) {
f = rb_stdin;
}
+ else if (rb_embedded_payload != Qnil) {
+ f = rb_embedded_payload;
+ }
else {
int fd, mode = O_RDONLY;
#if defined DOSISH || defined __CYGWIN__
diff --git a/win32/fix-size.rb b/win32/fix-size.rb
new file mode 100644
index 0000000..f8cae8c
--- /dev/null
+++ b/win32/fix-size.rb
@@ -0,0 +1,20 @@
+#!./miniruby -sI.
+
+magic = open(ARGV[1], "rb") {|f| f.read }
+size = [File.size(ARGV[0])].pack("V")
+exit if size == magic
+
+open(ARGV[1], "wb") {|f| f.write size }
+exe_image = open(ARGV[0], "rb") {|f| f.read }
+count = exe_image.scan(magic).size
+
+if count == 1
+ exe_image.sub!(magic) { size }
+ open(ARGV[0], "wb") {|f| f.write exe_image }
+else
+ puts
+ puts "*************************"
+ puts "** Please re-run make! **"
+ puts "*************************"
+ puts
+end
diff --git a/win32/resource.rb b/win32/resource.rb
index 786edb0..75a9004 100755
--- a/win32/resource.rb
+++ b/win32/resource.rb
@@ -62,6 +62,7 @@ end
#endif
#{icon || ''}
+RUBY_PAYLOAD_OFFSET RCDATA DISCARDABLE "#{base}.size"
VS_VERSION_INFO VERSIONINFO
FILEVERSION #{nversion}
PRODUCTVERSION #{nversion}
@@ -93,5 +94,6 @@ BEGIN
END
EOF
}
+ open(base + ".size", "wb") {|f| f.print "SiZE" }
end
--
1.7.9.5
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment