- Syntax is now much closer to gnu ar, but still supports whatever was supported before, with the following exceptions (which gnu ar has too): - lib is now mandatory (was optional and defaulted to ar_test.a before). - Path cannot start with '-' (but ./-myfile.o is OK). - Unlike gnu ar, modes are still optional (as before). - Now supports also (like gnu ar): - First argument as options doesn't have to start with '-', later options do. - Now supports mode v (verbose) with same output format as gnu ar. - Any names for lib/objs (were limited to .a/.o - broke cmake on windows). - Now explicitly fail on options which would be destructive for the user. - Now doesn't get confused by options between file arguments. - Still ignores other unknown options - as before. - Now doesn't read out-of-bounds if an option is one char. - As a result, cmake for windows can now use tiny_libmaker as ar, and configure can also detect tiny_libmaker as a valid ar (both couldn't before). Ignoring all options could previously cause to misinterpret the mode in a destructive way, e.g. if the user wanted to do something with an existing archive (such as p - print, or x - extract, etc), then it would instead just delete (re-create) the archive. Modes which can be destructive if ignored now explicitly fail. These include [habdioptxN]. Note that 'h' can be ignored, but this way we also implicitly print the usage for -h/--help. The .a/.o name limitations previously resulted in complete failure on some cases, such as cmake on windows which uses <filename>.obj and <libname>.lib .
Unified · Split
| @@ -71,50 +71,69 @@ ArHdr arhdro = { · 70 unmodified lines | |||
| 71 | ARFMAG | 71 | ARFMAG |
| 72 | }; | 72 | }; |
| 73 | 73 | ||
| 74 | /* Returns 1 if s contains any of the chars of list, else 0 */ | ||
| 75 | int contains_any(const char *s, const char *list) { | ||
| 76 | const char *l; | ||
| 77 | for (; *s; s++) { | ||
| 78 | for (l = list; *l; l++) { | ||
| 79 | if (*s == *l) | ||
| 80 | return 1; | ||
| 81 | } | ||
| 82 | } | ||
| 83 | return 0; | ||
| 84 | } | ||
| 85 | |||
| 86 | int usage(int ret) { | ||
| 87 | fprintf(stderr, "usage: tiny_libmaker [rcsv] lib file...\n"); | ||
| 88 | fprintf(stderr, "Always creates a new lib. [abdioptxN] are explicitly rejected.\n"); | ||
| 89 | return ret; | ||
| 90 | } | ||
| 91 | |||
| 74 | int main(int argc, char **argv) | 92 | int main(int argc, char **argv) |
| 75 | { | 93 | { |
| 76 | FILE *fi, *fh = NULL, *fo = NULL; | 94 | FILE *fi, *fh = NULL, *fo = NULL; |
| 77 | ElfW(Ehdr) *ehdr; | 95 | ElfW(Ehdr) *ehdr; |
| 78 | ElfW(Shdr) *shdr; | 96 | ElfW(Shdr) *shdr; |
| 79 | ElfW(Sym) *sym; | 97 | ElfW(Sym) *sym; |
| 80 | int i, fsize, iarg; | 98 | int i, fsize, i_lib, i_obj; |
| 81 | char *buf, *shstr, *symtab = NULL, *strtab = NULL; | 99 | char *buf, *shstr, *symtab = NULL, *strtab = NULL; |
| 82 | int symtabsize = 0;//, strtabsize = 0; | 100 | int symtabsize = 0;//, strtabsize = 0; |
| 83 | char *anames = NULL; | 101 | char *anames = NULL; |
| 84 | int *afpos = NULL; | 102 | int *afpos = NULL; |
| 85 | int istrlen, strpos = 0, fpos = 0, funccnt = 0, funcmax, hofs; | 103 | int istrlen, strpos = 0, fpos = 0, funccnt = 0, funcmax, hofs; |
| 86 | char afile[260], tfile[260], stmp[20]; | 104 | char tfile[260], stmp[20]; |
| 87 | char *file, *name; | 105 | char *file, *name; |
| 88 | int ret = 2; | 106 | int ret = 2; |
| 107 | char *ops_conflict = "habdioptxN"; // unsupported but destructive if ignored. | ||
| 108 | int verbose = 0; | ||
| 89 | 109 | ||
| 90 | 110 | i_lib = 0; i_obj = 0; // will hold the index of the lib and first obj | |
| 91 | strcpy(afile, "ar_test.a"); | 111 | for (i = 1; i < argc; i++) { |
| 92 | iarg = 1; | 112 | const char *a = argv[i]; |
| 93 | 113 | if (*a == '-' && strstr(a, ".")) | |
| 94 | if (argc < 2) | 114 | return usage(1); // -x.y is always invalid (same as gnu ar) |
| 95 | { | 115 | if ((*a == '-') || (i == 1 && !strstr(a, "."))) { // options argument |
| 96 | printf("usage: tiny_libmaker [lib] file...\n"); | 116 | if (contains_any(a, ops_conflict)) |
| 97 | return 1; | 117 | return usage(1); |
| 98 | } | 118 | if (strstr(a, "v")) |
| 99 | for (i=1; i<argc; i++) { | 119 | verbose = 1; |
| 100 | istrlen = strlen(argv[i]); | 120 | } else { // lib or obj files: don't abort - keep validating all args. |
| 101 | if (argv[i][istrlen-2] == '.') { | 121 | if (!i_lib) // first file is the lib |
| 102 | if(argv[i][istrlen-1] == 'a') | 122 | i_lib = i; |
| 103 | strcpy(afile, argv[i]); | 123 | else if (!i_obj) // second file is the first obj |
| 104 | else if(argv[i][istrlen-1] == 'o') { | 124 | i_obj = i; |
| 105 | iarg = i; | ||
| 106 | break; | ||
| 107 | } | ||
| 108 | } | 125 | } |
| 109 | } | 126 | } |
| 127 | if (!i_obj) // implies also no i_lib | ||
| 128 | return usage(1); | ||
| 110 | 129 | ||
| 111 | if ((fh = fopen(afile, "wb")) == NULL) | 130 | if ((fh = fopen(argv[i_lib], "wb")) == NULL) |
| 112 | { | 131 | { |
| 113 | fprintf(stderr, "Can't open file %s \n", afile); | 132 | fprintf(stderr, "Can't open file %s \n", argv[i_lib]); |
| 114 | goto the_end; | 133 | goto the_end; |
| 115 | } | 134 | } |
| 116 | 135 | ||
| 117 | sprintf(tfile, "%s.tmp", afile); | 136 | sprintf(tfile, "%s.tmp", argv[i_lib]); |
| 118 | if ((fo = fopen(tfile, "wb+")) == NULL) | 137 | if ((fo = fopen(tfile, "wb+")) == NULL) |
| 119 | { | 138 | { |
| 120 | fprintf(stderr, "Can't create temporary file %s\n", tfile); | 139 | fprintf(stderr, "Can't create temporary file %s\n", tfile); |
| @@ -125,16 +144,19 @@ int main(int argc, char **argv) · 4 unmodified lines | |||
| 125 | afpos = realloc(NULL, funcmax * sizeof *afpos); // 250 func | 144 | afpos = realloc(NULL, funcmax * sizeof *afpos); // 250 func |
| 126 | memcpy(&arhdro.ar_mode, "100666", 6); | 145 | memcpy(&arhdro.ar_mode, "100666", 6); |
| 127 | 146 | ||
| 128 | //iarg = 1; | 147 | // i_obj = first input object file |
| 129 | while (iarg < argc) | 148 | while (i_obj < argc) |
| 130 | { | 149 | { |
| 131 | if (!strcmp(argv[iarg], "rcs")) { | 150 | if (*argv[i_obj] == '-') { // by now, all options start with '-' |
| 132 | iarg++; | 151 | i_obj++; |
| 133 | continue; | 152 | continue; |
| 134 | } | 153 | } |
| 135 | if ((fi = fopen(argv[iarg], "rb")) == NULL) | 154 | if (verbose) |
| 155 | printf("a - %s\n", argv[i_obj]); | ||
| 156 | |||
| 157 | if ((fi = fopen(argv[i_obj], "rb")) == NULL) | ||
| 136 | { | 158 | { |
| 137 | fprintf(stderr, "Can't open file %s \n", argv[iarg]); | 159 | fprintf(stderr, "Can't open file %s \n", argv[i_obj]); |
| 138 | goto the_end; | 160 | goto the_end; |
| 139 | } | 161 | } |
| 140 | fseek(fi, 0, SEEK_END); | 162 | fseek(fi, 0, SEEK_END); |
| @@ -144,13 +166,11 @@ int main(int argc, char **argv) · 3 unmodified lines | |||
| 144 | fread(buf, fsize, 1, fi); | 166 | fread(buf, fsize, 1, fi); |
| 145 | fclose(fi); | 167 | fclose(fi); |
| 146 | 168 | ||
| 147 | //printf("%s:\n", argv[iarg]); | ||
| 148 | |||
| 149 | // elf header | 169 | // elf header |
| 150 | ehdr = (ElfW(Ehdr) *)buf; | 170 | ehdr = (ElfW(Ehdr) *)buf; |
| 151 | if (ehdr->e_ident[4] != ELFCLASSW) | 171 | if (ehdr->e_ident[4] != ELFCLASSW) |
| 152 | { | 172 | { |
| 153 | fprintf(stderr, "Unsupported Elf Class: %s\n", argv[iarg]); | 173 | fprintf(stderr, "Unsupported Elf Class: %s\n", argv[i_obj]); |
| 154 | goto the_end; | 174 | goto the_end; |
| 155 | } | 175 | } |
| 156 | 176 | ||
| @@ -202,7 +222,7 @@ int main(int argc, char **argv) · 45 unmodified lines | |||
| 202 | } | 222 | } |
| 203 | } | 223 | } |
| 204 | 224 | ||
| 205 | file = argv[iarg]; | 225 | file = argv[i_obj]; |
| 206 | for (name = strchr(file, 0); | 226 | for (name = strchr(file, 0); |
| 207 | name > file && name[-1] != '/' && name[-1] != '\\'; | 227 | name > file && name[-1] != '/' && name[-1] != '\\'; |
| 208 | --name); | 228 | --name); |
| @@ -217,7 +237,7 @@ int main(int argc, char **argv) · 8 unmodified lines | |||
| 217 | fwrite(&arhdro, sizeof(arhdro), 1, fo); | 237 | fwrite(&arhdro, sizeof(arhdro), 1, fo); |
| 218 | fwrite(buf, fsize, 1, fo); | 238 | fwrite(buf, fsize, 1, fo); |
| 219 | free(buf); | 239 | free(buf); |
| 220 | iarg++; | 240 | i_obj++; |
| 221 | fpos += (fsize + sizeof(arhdro)); | 241 | fpos += (fsize + sizeof(arhdro)); |
| 222 | } | 242 | } |
| 223 | hofs = 8 + sizeof(arhdr) + strpos + (funccnt+1) * sizeof(int); | 243 | hofs = 8 + sizeof(arhdr) + strpos + (funccnt+1) * sizeof(int); |