History

tiny_libmaker: more robust arguments interpretation

- 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 .

Avi Halachmi (:avih) committed 10 years ago

Commit 100f94b1 parent 1ca685f1 file · +54 −34Browse files

Unified · Split

win32/tools/tiny_libmaker.c+54−34
@@ -71,50 +71,69 @@ ArHdr arhdro = { · 70 unmodified lines
71 ARFMAG71 ARFMAG
72 };72 };
73 73
74/* Returns 1 if s contains any of the chars of list, else 0 */
75int 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
86int 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
74int main(int argc, char **argv)92int 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 func144 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 header169 // 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);

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t