commit 887b0bef5f76997de2bdbd2a91168dde357821d1
parent 5cdbd266c31962ec9ebcef0415d2f104b209cddb
Author: Roberto E. Vargas Caballero <k0ga@shike2.net>
Date: Fri, 8 May 2026 19:27:24 +0200
ranlib: Use 2 phases writing the index
When the different offsets are calculated they are based in the
size of the existing index if there was any index, but if the new
index has a different size then the offset are misplaced. In order
to fix this issue we have to record the size of the existing index
file, generate the new index file, and apply fixups to every offset
to adjust it to the actual offset in the final archive.
Diffstat:
1 file changed, 19 insertions(+), 4 deletions(-)
diff --git a/src/cmd/scc-ranlib.c b/src/cmd/scc-ranlib.c
@@ -28,7 +28,7 @@ static long nsymbols;
static int status, artype, nolib;
static char *filename, *membname;
static Symdef *htab[NR_SYMDEF], *head;
-static long offset;
+static long offset, oldsize;
char *argv0;
static void
@@ -180,6 +180,7 @@ readsyms(FILE *fp)
nolib = 0;
artype = -1;
nsymbols = 0;
+ oldsize = 0;
if (!archive(fp)) {
error("file format not recognized");
@@ -190,8 +191,10 @@ readsyms(FILE *fp)
if ((off = armember(fp, memb, NULL)) < 0)
goto corrupted;
- if (strcmp(memb, "/") == 0 || strcmp(memb, "__.SYMDEF") == 0)
+ if (strcmp(memb, "/") == 0 || strcmp(memb, "__.SYMDEF") == 0) {
+ oldsize = off;
cur += off;
+ }
fseek(fp, cur, SEEK_SET);
for (;;) {
@@ -265,7 +268,7 @@ static void
ranlib(char *fname)
{
size_t r;
- long *offs, i;
+ long *offs, size, i;
char **names;
FILE *fp, *idx, *out;
Symdef *dp;
@@ -298,6 +301,7 @@ ranlib(char *fname)
names[i] = dp->name;
}
+ /* First pass: write index to determine its size */
if (setindex(artype, nsymbols, names, offs, idx) < 0) {
error(strerror(errno));
goto err3;
@@ -307,8 +311,19 @@ ranlib(char *fname)
error(strerror(errno));
goto err3;
}
- prop.size = ftell(idx);
prop.time = time(NULL);
+ prop.size = ftell(idx);
+
+ size = sizeof(struct ar_hdr) + prop.size + (prop.size & 1);
+ for (i = 0; i < nsymbols; i++)
+ offs[i] += size - oldsize;
+
+ /* Second pass: rewrite index with corrected offsets */
+ rewind(idx);
+ if (setindex(artype, nsymbols, names, offs, idx) < 0) {
+ error(strerror(errno));
+ goto err3;
+ }
r = snprintf(tmpname, sizeof(tmpname), "%s.tmp", fname);
if (r >= sizeof(tmpname)) {