diff --git a/tcctools.c b/tcctools.c index 2bcc990d..c4af006d 100644 --- a/tcctools.c +++ b/tcctools.c @@ -61,8 +61,8 @@ static int contains_any(const char *s, const char *list) { } static int ar_usage(int ret) { - fprintf(stderr, "usage: tcc -ar [rcsv] lib [file...]\n"); - fprintf(stderr, "create library ([abdioptxN] not supported).\n"); + fprintf(stderr, "usage: tcc -ar [rcstxv] lib [file...]\n"); + fprintf(stderr, "create library ([abdiopN] not supported).\n"); return ret; } @@ -94,7 +94,9 @@ ST_FUNC int tcc_tool_ar(TCCState *s1, int argc, char **argv) char tfile[260], stmp[20]; char *file, *name; int ret = 2; - const char *ops_conflict = "habdioptxN"; // unsupported but destructive if ignored. + const char *ops_conflict = "habdiopN"; // unsupported but destructive if ignored. + int extract = 0; + int table = 0; int verbose = 0; i_lib = 0; i_obj = 0; // will hold the index of the lib and first obj @@ -105,6 +107,10 @@ ST_FUNC int tcc_tool_ar(TCCState *s1, int argc, char **argv) if ((*a == '-') || (i == 1 && !strstr(a, "."))) { // options argument if (contains_any(a, ops_conflict)) ret = 1; + if (strstr(a, "x")) + extract = 1; + if (strstr(a, "t")) + table = 1; if (strstr(a, "v")) verbose = 1; } else { // lib or obj files: don't abort - keep validating all args. @@ -122,9 +128,63 @@ ST_FUNC int tcc_tool_ar(TCCState *s1, int argc, char **argv) if (ret == 1) return ar_usage(ret); + if (extract || table) { + if ((fh = fopen(argv[i_lib], "rb")) == NULL) + { + fprintf(stderr, "tcc: ar: can't open file %s\n", argv[i_lib]); + goto finish; + } + fread(stmp, 1, 8, fh); + if (memcmp(stmp,ARMAG,8)) + { +no_ar: + fprintf(stderr, "tcc: ar: not an ar archive %s\n", argv[i_lib]); + goto finish; + } + while (fread(&arhdr, 1, sizeof(arhdr), fh) == sizeof(arhdr)) { + char *p, *e; + + if (memcmp(arhdr.ar_fmag, ARFMAG, 2)) + goto no_ar; + p = arhdr.ar_name; + for (e = p + sizeof arhdr.ar_name; e > p && e[-1] == ' ';) + e--; + *e = '\0'; + arhdr.ar_size[sizeof arhdr.ar_size-1] = 0; + fsize = atoi(arhdr.ar_size); + buf = tcc_malloc(fsize + 1); + fread(buf, fsize, 1, fh); + if (strcmp(arhdr.ar_name,"/") && strcmp(arhdr.ar_name,"/SYM64/")) { + if (e > p && e[-1] == '/') + e[-1] = '\0'; + /* tv not implemented */ + if (table || verbose) + printf("%s%s\n", extract ? "x - " : "", arhdr.ar_name); + if (extract) { + if ((fo = fopen(arhdr.ar_name, "wb")) == NULL) + { + fprintf(stderr, "tcc: ar: can't create file %s\n", + arhdr.ar_name); + tcc_free(buf); + goto finish; + } + fwrite(buf, fsize, 1, fo); + fclose(fo); + /* ignore date/uid/gid/mode */ + } + } + tcc_free(buf); + } + ret = 0; +finish: + if (fh) + fclose(fh); + return ret; + } + if ((fh = fopen(argv[i_lib], "wb")) == NULL) { - fprintf(stderr, "tcc: ar: can't open file %s \n", argv[i_lib]); + fprintf(stderr, "tcc: ar: can't create file %s\n", argv[i_lib]); goto the_end; }