Skip to content

Commit eed1cd5

Browse files
committed
Faster binary rewriter
1 parent 7c06228 commit eed1cd5

File tree

2 files changed

+199
-3
lines changed

2 files changed

+199
-3
lines changed

bin/ruby-package

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,27 @@
11
#!/usr/bin/env bash
22
set -e
33

4+
resolve_link() {
5+
$(type -p greadlink readlink | head -1) $1
6+
}
7+
8+
abs_dirname() {
9+
local cwd="$(pwd)"
10+
local path="$1"
11+
12+
while [ -n "$path" ]; do
13+
cd "${path%/*}"
14+
local name="${path##*/}"
15+
path="$(resolve_link "$name" || true)"
16+
done
17+
18+
pwd
19+
cd "$cwd"
20+
}
21+
22+
bin_root="$(abs_dirname "$0")"
23+
24+
425
definition="$1"
526
if [ -z "$definition" ]; then
627
echo "usage: ruby-package DEFINITION"
@@ -10,13 +31,14 @@ package="${definition##*/}"
1031
prefix="/tmp/ruby-build/-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------/$package"
1132

1233

13-
# ruby-build "$definition" "$prefix"
34+
"${bin_root}/ruby-build" -v "$definition" "$prefix"
1435
cwd="$(pwd)"
1536
cd "${prefix}/.."
1637

17-
# FIXME don't assume share is in cwd
1838
mkdir -p "${package}.rubypackage/bin"
19-
cp "${cwd}/share/ruby-package/"* "${package}.rubypackage/bin"
39+
cp "${bin_root}/../share/ruby-package/ruby-package-install" "${package}.rubypackage/bin"
40+
cp "${bin_root}/../share/ruby-package/ruby-package-rewrite-text" "${package}.rubypackage/bin"
41+
cc -Wall "${bin_root}/../share/ruby-package/ruby-package-rewrite-binary.c" -o "${package}.rubypackage/bin/ruby-package-rewrite-binary"
2042

2143
mkdir -p "${package}.rubypackage/metadata"
2244
echo -n "$prefix" > "${package}.rubypackage/metadata/prefix"
Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
#include <stdio.h>
2+
#include <stdlib.h>
3+
#include <string.h>
4+
5+
#define BUF_SIZE 4096
6+
7+
typedef struct {
8+
unsigned int initial_size;
9+
unsigned int size;
10+
unsigned int pos;
11+
char *data;
12+
} buf_t;
13+
14+
void *buf_malloc(size_t size) {
15+
void *result = malloc(size);
16+
17+
if (result == NULL) {
18+
fprintf(stderr, "error allocating memory, aborting\n");
19+
exit(1);
20+
}
21+
22+
return result;
23+
}
24+
25+
void buf_init(buf_t *this, unsigned int size) {
26+
this->initial_size = size;
27+
this->size = size;
28+
this->pos = 0;
29+
this->data = buf_malloc(size);
30+
}
31+
32+
void buf_grow(buf_t *this) {
33+
unsigned int size = this->size + this->initial_size;
34+
char *data = buf_malloc(size);
35+
36+
memcpy(data, this->data, this->size);
37+
free(this->data);
38+
this->data = data;
39+
this->size = size;
40+
}
41+
42+
int buf_putc(buf_t *this, int chr) {
43+
if (this->pos == this->size) {
44+
buf_grow(this);
45+
}
46+
47+
this->data[this->pos] = chr;
48+
this->pos++;
49+
return chr;
50+
}
51+
52+
void buf_append(buf_t *this, char *src, unsigned int length) {
53+
unsigned int i;
54+
for (i = 0; i < length; i++) {
55+
buf_putc(this, src[i]);
56+
}
57+
}
58+
59+
void buf_concat(buf_t *this, buf_t *src) {
60+
buf_append(this, src->data, src->pos);
61+
}
62+
63+
void buf_print(buf_t *this, FILE *out) {
64+
unsigned int i;
65+
for (i = 0; i < this->pos; i++) {
66+
fputc(this->data[i], out);
67+
}
68+
}
69+
70+
void buf_reset(buf_t *this) {
71+
this->pos = 0;
72+
}
73+
74+
void buf_destroy(buf_t *this) {
75+
buf_reset(this);
76+
free(this->data);
77+
this->data = NULL;
78+
}
79+
80+
void rewrite_chunk(buf_t *in, FILE *out, char *src_prefix, char *dst_prefix) {
81+
unsigned int src_prefix_len, dst_prefix_len, chr, i;
82+
buf_t result;
83+
84+
buf_init(&result, BUF_SIZE);
85+
src_prefix_len = strlen(src_prefix);
86+
dst_prefix_len = strlen(dst_prefix);
87+
i = 0;
88+
89+
while (i < in->pos) {
90+
buf_append(&result, dst_prefix, dst_prefix_len);
91+
i += src_prefix_len;
92+
93+
while (i < in->pos && (chr = in->data[i++])) {
94+
buf_putc(&result, chr);
95+
}
96+
97+
buf_putc(&result, 0);
98+
}
99+
100+
for (i = result.pos; i < in->pos; i++) {
101+
buf_putc(&result, 0);
102+
}
103+
104+
buf_print(&result, out);
105+
buf_destroy(&result);
106+
}
107+
108+
void rewrite(FILE *in, FILE *out, char *src_prefix, char *dst_prefix) {
109+
unsigned int src_prefix_len, chr;
110+
buf_t chunk, buf;
111+
112+
buf_init(&chunk, BUF_SIZE);
113+
buf_init(&buf, BUF_SIZE);
114+
src_prefix_len = strlen(src_prefix);
115+
116+
while ((chr = fgetc(in)) != EOF) {
117+
if (buf.pos < src_prefix_len && chr == src_prefix[buf.pos]) {
118+
buf_putc(&buf, chr);
119+
continue;
120+
121+
} else if (buf.pos >= src_prefix_len && chr != 0) {
122+
buf_putc(&buf, chr);
123+
continue;
124+
125+
} else if (buf.pos > 0 && chr == 0) {
126+
buf_concat(&chunk, &buf);
127+
buf_putc(&chunk, 0);
128+
buf_reset(&buf);
129+
continue;
130+
}
131+
132+
if (chunk.pos > 0) {
133+
if (chunk.pos > src_prefix_len) {
134+
rewrite_chunk(&chunk, out, src_prefix, dst_prefix);
135+
} else {
136+
buf_print(&chunk, out);
137+
}
138+
buf_reset(&chunk);
139+
}
140+
141+
if (buf.pos > 0) {
142+
buf_print(&buf, out);
143+
buf_reset(&buf);
144+
}
145+
146+
fputc(chr, out);
147+
}
148+
149+
buf_destroy(&buf);
150+
buf_destroy(&chunk);
151+
}
152+
153+
int main(int argc, char **argv) {
154+
char *src_prefix, *dst_prefix;
155+
int src_prefix_length;
156+
157+
if (argc != 3) {
158+
fprintf(stderr, "usage: %s SRC_PREFIX DST_PREFIX\n", argv[0]);
159+
return 1;
160+
}
161+
162+
src_prefix = argv[1];
163+
src_prefix_length = strlen(src_prefix);
164+
dst_prefix = argv[2];
165+
166+
if (strlen(dst_prefix) > strlen(src_prefix)) {
167+
fprintf(stderr, "error: destination prefix must be %d bytes or less\n", src_prefix_length);
168+
return 2;
169+
}
170+
171+
rewrite(stdin, stdout, src_prefix, dst_prefix);
172+
173+
return 0;
174+
}

0 commit comments

Comments
 (0)