DEADSOFTWARE

Patched for Linux
[mp3cc.git] / MPC.3.5.LINUX / preverifier / file.c
1 /*
2 * @(#)file.c 1.40 02/09/27
3 *
4 * Copyright 1995-1998 by Sun Microsystems, Inc.,
5 * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
6 * All rights reserved.
7 *
8 * This software is the confidential and proprietary information
9 * of Sun Microsystems, Inc. ("Confidential Information"). You
10 * shall not disclose such Confidential Information and shall use
11 * it only in accordance with the terms of the license agreement
12 * you entered into with Sun.
13 * Use is subject to license terms.
14 */
16 /*=========================================================================
17 * SYSTEM: Verifier
18 * SUBSYSTEM: Operations on class files.
19 * FILE: file.c
20 * OVERVIEW: Routines for outputing the internal class file.
21 *
22 * AUTHOR(s): Original implementation,
23 * Sheng Liang, Sun Microsystems, Inc.
24 *
25 * Modifications for JAR support, debug support, CLDC compliance,
26 * Tasneem Sayeed, Sun Microsystems
27 *
28 * Added support for inner classes, fixes for stack maps, etc.
29 * Frank Yellin, Sun Microsystems
30 *=======================================================================*/
32 /*=========================================================================
33 * Include files
34 *=======================================================================*/
36 #include <sys/types.h>
37 #include <fcntl.h>
38 #include <sys/stat.h>
39 #include <stdio.h>
40 #include <string.h>
41 #include <stdlib.h>
42 #include <stddef.h>
44 #ifdef UNIX
45 #include <unistd.h>
46 #endif
48 #include "oobj.h"
49 #include "jar.h"
50 #include "tree.h"
51 #include "sys_api.h"
52 #include "convert_md.h"
54 #ifdef WIN32
55 #include <direct.h>
56 #endif
58 /* initialize opnames[256]; */
59 #include "opcodes.init"
62 /*=========================================================================
63 * Globals and extern declarations
64 *=======================================================================*/
66 extern char *progname;
67 extern bool_t JARfile;
68 extern bool_t tmpDirExists;
70 char *current_class_name = NULL;
72 bool_t stack_map_on = TRUE;
74 static char *PrintableClassname(char *classname);
76 extern char tmp_dir[32];
78 char *output_dir = "output";
79 unsigned char *class_buf;
80 int class_buf_size = 0;
81 int class_index;
82 int last_not_utf8_index;
84 #define INIT_CLASS_BUF_SIZE 256
86 void ensure_capacity(int sz)
87 {
88 if (class_index + sz >= class_buf_size) {
89 while (class_index + sz >= class_buf_size) {
90 class_buf_size *= 2;
91 }
92 }
93 class_buf = (unsigned char *)realloc(class_buf, class_buf_size);
94 }
96 void write_u1(unsigned long u1)
97 {
98 ensure_capacity(1);
99 class_buf[class_index++] = (unsigned char)u1;
102 void write_u2(unsigned long u2)
104 ensure_capacity(2);
105 class_buf[class_index++] = (unsigned char)(u2 >> 8);
106 class_buf[class_index++] = (unsigned char)u2;
109 void write_u4(unsigned long u4)
111 ensure_capacity(4);
112 class_buf[class_index++] = (unsigned char)(u4 >> 24);
113 class_buf[class_index++] = (unsigned char)(u4 >> 16);
114 class_buf[class_index++] = (unsigned char)(u4 >> 8);
115 class_buf[class_index++] = (unsigned char)u4;
118 int new_utf8_index(ClassClass *cb, int index)
120 if (index > last_not_utf8_index) {
121 return index + unhand(cb)->n_new_class_entries;
122 } else {
123 return index;
127 unsigned long lookup_utf8(ClassClass *cb, char *utf8)
129 int i;
130 cp_item_type *constant_pool = cbConstantPool(cb);
131 int cpEntries, newEntries;
132 unsigned char *type_table =
133 constant_pool[CONSTANT_POOL_TYPE_TABLE_INDEX].type;
134 cpEntries = cbConstantPoolCount(cb);
135 newEntries = unhand(cb)->n_new_utf8_entries;
136 for (i = 0; i < cpEntries; i++) {
137 if (type_table[i] == (CONSTANT_Utf8 | CONSTANT_POOL_ENTRY_RESOLVED) &&
138 strcmp(utf8, constant_pool[i].cp) == 0) {
139 return new_utf8_index(cb, i);
142 for (i = 0; i < newEntries; i++) {
143 if (strcmp(unhand(cb)->new_utf8_entries[i], utf8) == 0) {
144 return i + cpEntries + unhand(cb)->n_new_class_entries;
147 unhand(cb)->new_utf8_entries[newEntries] = utf8;
148 unhand(cb)->n_new_utf8_entries = newEntries + 1;
149 return newEntries + cpEntries + unhand(cb)->n_new_class_entries;
153 unsigned long lookup_class(ClassClass *cb, char *name)
155 int i;
156 cp_item_type *constant_pool = cbConstantPool(cb);
157 unsigned char *type_table =
158 constant_pool[CONSTANT_POOL_TYPE_TABLE_INDEX].type;
159 for (i = 0; i < cbConstantPoolCount(cb); i++) {
160 if (type_table[i] == (CONSTANT_Class | CONSTANT_POOL_ENTRY_RESOLVED) &&
161 strcmp(name, cbName(constant_pool[i].clazz)) == 0) {
162 return i;
164 if (type_table[i] == CONSTANT_Class &&
165 strcmp(name, constant_pool[constant_pool[i].i].cp) == 0) {
166 return i;
169 // panic("class expected to be in constant pool: %s", name);
170 return 0;
173 int get_last_not_utf8_index(ClassClass *cb)
175 int i;
176 int result;
177 cp_item_type *constant_pool = cbConstantPool(cb);
178 unsigned char *type_table =
179 constant_pool[CONSTANT_POOL_TYPE_TABLE_INDEX].type;
180 for (i = 0, result = -1; i < cbConstantPoolCount(cb); i++) {
181 if (type_table[i] != (CONSTANT_Utf8 | CONSTANT_POOL_ENTRY_RESOLVED)) {
182 result = i;
185 return result;
188 void write_constant_pool_preverifier(ClassClass *cb)
190 int i, j;
191 cp_item_type *constant_pool = cbConstantPool(cb);
192 unsigned char *type_table =
193 constant_pool[CONSTANT_POOL_TYPE_TABLE_INDEX].type;
194 unsigned int sealedValue;
196 last_not_utf8_index = get_last_not_utf8_index(cb);
197 if (stack_map_on && unhand(cb)->has_stack_maps) {
198 /* The maximum number of new utf8 entries we'll need is one
199 * for "StackMap", plus one for each of the new class entries.
200 * However, we bump the number to 2 in case we need to add another
201 * entry for the SourceFile attribute.
202 */
203 unhand(cb)->n_new_utf8_entries = 0;
204 unhand(cb)->new_utf8_entries =
205 (char **)malloc((unhand(cb)->n_new_class_entries + 2) *
206 sizeof(char *));
207 /* Put sure we have all the Utf8 entries that we need, so that
208 * we'll know the final size of the constant pool.
209 */
210 lookup_utf8(cb, "StackMap");
211 for (i = 0; i < unhand(cb)->n_new_class_entries; i++) {
212 lookup_utf8(cb, unhand(cb)->new_class_entries[i]);
214 } else {
215 unhand(cb)->n_new_utf8_entries = 0;
216 unhand(cb)->new_utf8_entries = NULL;
217 unhand(cb)->n_new_class_entries = 0;
218 if (unhand(cb)->new_class_entries != NULL) {
219 free(unhand(cb)->new_class_entries);
220 unhand(cb)->new_class_entries = NULL;
223 /* At this, we should not add have to create any more utf8 entries.
224 * We find the value of unhand(cb)->n_new_utf8_entries, and complain
225 * later if this value has changed.
226 */
227 sealedValue = unhand(cb)->n_new_utf8_entries;
229 write_u2(cbConstantPoolCount(cb) +
230 unhand(cb)->n_new_class_entries +
231 unhand(cb)->n_new_utf8_entries);
233 for (i = 1; i < cbConstantPoolCount(cb); i++) {
234 write_u1(type_table[i] & CONSTANT_POOL_ENTRY_TYPEMASK);
235 switch(type_table[i]) {
236 case CONSTANT_Utf8 | CONSTANT_POOL_ENTRY_RESOLVED:
237 write_u2(strlen(constant_pool[i].cp));
238 for (j = 0; j < (int)strlen(constant_pool[i].cp); j++) {
239 write_u1(constant_pool[i].cp[j]);
241 break;
243 case CONSTANT_Class:
244 case CONSTANT_String:
245 write_u2(new_utf8_index(cb, constant_pool[i].i));
246 break;
248 case CONSTANT_Class | CONSTANT_POOL_ENTRY_RESOLVED:
249 write_u2(lookup_utf8(cb, cbName(constant_pool[i].clazz)));
250 break;
252 case CONSTANT_Fieldref:
253 case CONSTANT_Methodref:
254 case CONSTANT_InterfaceMethodref:
255 write_u2(constant_pool[i].i >> 16);
256 write_u2(constant_pool[i].i & 0xFFFF);
257 break;
259 case CONSTANT_NameAndType:
260 write_u2(new_utf8_index(cb, constant_pool[i].i >> 16));
261 write_u2(new_utf8_index(cb, constant_pool[i].i & 0xFFFF));
262 break;
264 case CONSTANT_Integer | CONSTANT_POOL_ENTRY_RESOLVED:
265 case CONSTANT_Float | CONSTANT_POOL_ENTRY_RESOLVED:
266 write_u4(constant_pool[i].i);
267 break;
269 case CONSTANT_Long | CONSTANT_POOL_ENTRY_RESOLVED:
270 case CONSTANT_Double | CONSTANT_POOL_ENTRY_RESOLVED:
271 write_u4(constant_pool[i].i);
272 write_u4(constant_pool[i + 1].i);
273 i++;
274 break;
276 // default:
277 // panic("bad constant pool entry type: %d", type_table[i]);
279 if (i == last_not_utf8_index) {
280 /* Write extra CONSTANT_Class entries created by the stackmaps */
281 for (j = 0; j < unhand(cb)->n_new_class_entries; j++) {
282 char *classname = unhand(cb)->new_class_entries[j];
283 write_u1(CONSTANT_Class);
284 write_u2(lookup_utf8(cb, classname));
288 /* Write extra CONSTANT_Utf8 entries created by the stackmaps */
289 for (i = 0; i < unhand(cb)->n_new_utf8_entries; i++) {
290 char *string = unhand(cb)->new_utf8_entries[i];
291 int length = strlen(string);
292 write_u1(CONSTANT_Utf8);
293 write_u2(length);
294 for (j = 0; j < length; j++) {
295 write_u1(string[j]);
298 if (sealedValue != (unsigned int) unhand(cb)->n_new_utf8_entries) {
299 // panic("New utf8 entries have been added???");
304 void write_interfaces(ClassClass *cb)
306 int i;
307 write_u2(cbImplementsCount(cb));
308 for (i = 0; i < cbImplementsCount(cb); i++) {
309 write_u2(cbImplements(cb)[i]);
313 void write_fields(ClassClass *cb)
315 int i;
316 write_u2(cbFieldsCount(cb));
317 for (i = 0; i < cbFieldsCount(cb); i++) {
318 struct fieldblock *fb = &cbFields(cb)[i];
319 write_u2(fb->access & ACC_WRITTEN_FLAGS);
320 write_u2(lookup_utf8(cb, fb->name));
321 write_u2(lookup_utf8(cb, fb->signature));
322 /* Number of attributes we're about to output.
323 * Each item in the following sum is a boolean that returns 1 or 0.
324 */
325 write_u2( ((fb->access & ACC_VALKNOWN) != 0)
326 + (fb->synthetic != 0)
327 + (fb->deprecated != 0));
328 if (fb->access & ACC_VALKNOWN) {
329 write_u2(lookup_utf8(cb, "ConstantValue")); /* Attribute name */
330 write_u4(2); /* Length */
331 write_u2(fb->u.offset);
333 if (fb->deprecated) {
334 write_u2(lookup_utf8(cb, "Deprecated")); /* Attribute name */
335 write_u4(0); /* Length */
337 if (fb->synthetic) {
338 write_u2(lookup_utf8(cb, "Synthetic")); /* Attribute name */
339 write_u4(0); /* Length */
344 void write_stack_map(int nentries, struct map_entry *entries)
346 int i;
347 for (i = 0; i < nentries; i++) {
348 struct map_entry *entry = entries + i;
349 write_u1(entry->type);
350 if (entry->type == CF_ITEM_NewObject) {
351 write_u2(entry->info);
353 if (entry->type == CF_ITEM_Object) {
354 /* This is ugly
355 * Non-negative entries refer to classes
356 * in the original constant pool.
357 * Negative entries, ~(entry->info) is the entry's index
358 * in the list of additional constant pool entries.
359 */
360 if (entry->info >= 0) {
361 write_u2(entry->info);
362 } else {
363 write_u2(last_not_utf8_index + 1 + ~entry->info);
369 int stack_map_size(int nentries, struct map_entry *entries)
371 int i;
372 int result = 0;
373 for (i = 0; i < nentries; i++) {
374 struct map_entry *entry = entries + i;
375 result += 1;
376 if (entry->type == CF_ITEM_Object || entry->type == CF_ITEM_NewObject) {
377 result += 2;
380 return result;
383 void write_methods(ClassClass *cb)
385 int i;
386 write_u2(cbMethodsCount(cb));
387 for (i = 0; i < cbMethodsCount(cb); i++) {
388 struct methodblock *mb = &cbMethods(cb)[i];
389 write_u2(mb->fb.access & ACC_WRITTEN_FLAGS);
390 write_u2(lookup_utf8(cb, mb->fb.name));
391 write_u2(lookup_utf8(cb, mb->fb.signature));
393 /* Attribute count
394 * Each item in the following sum is a boolean that returns 1 or 0.
395 */
396 write_u2( (mb->code_length > 0)
397 + (mb->nexceptions > 0)
398 + (mb->fb.synthetic != 0)
399 + (mb->fb.deprecated != 0));
401 if (mb->code_length > 0) {
402 int j;
403 int stack_map_attr_length = 0; /* Stack Map attribute length */
404 int line_no_attr_length = 0; /* line_number_table attr Length */
405 int localvar_attr_length = 0; /* localVar_table attr Length */
406 int code_attrs = 0; /* Attributes count for Code attribute */
408 if (stack_map_on && mb->n_stack_maps > 0) {
409 stack_map_attr_length = 8;
410 code_attrs++; /* increment code attributes */
411 for (j = 0; j < mb->n_stack_maps; j++) {
412 stack_map_attr_length += 6 +
413 stack_map_size(mb->stack_maps[j].nlocals,
414 mb->stack_maps[j].locals) +
415 stack_map_size(mb->stack_maps[j].nstacks,
416 mb->stack_maps[j].stacks);
420 /* attribute_name_index for "Code" attribute */
421 write_u2(lookup_utf8(cb, "Code"));
422 if (mb->line_number_table_length > 0) {
423 /* calculate the size of the line_number_table attribute */
424 /* Attribute length for line_number_table
425 * sizeof line_number_table(4) * no. of table entries + 8
426 * 8 bytes = 2 bytes for attr_name_index +
427 * 4 bytes for attr_length +
428 * 2 bytes for line_number_table_length
429 */
430 code_attrs++; /* increment code attributes */
431 line_no_attr_length = 4 * mb->line_number_table_length + 8;
433 if (mb->localvar_table_length > 0) {
434 /* calculate the size of the localvar_table attribute */
435 /* Attribute length for localvar_table
436 * sizeof localvar_table (10) * no. of table entries + 8
437 * 8 bytes = 2 bytes for attr_name_index +
438 * 4 bytes for attr_length +
439 * 2 bytes for line_number_table_length
440 */
441 code_attrs++; /* increment code attributes */
442 localvar_attr_length = 10 * mb->localvar_table_length + 8;
445 /* Attribute Length */
446 write_u4(12 + mb->code_length
447 + mb->exception_table_length * 8
448 + stack_map_attr_length
449 + line_no_attr_length
450 + localvar_attr_length);
451 write_u2(mb->maxstack);
452 write_u2(mb->nlocals);
453 write_u4(mb->code_length);
454 for (j = 0; j < (int)mb->code_length; j++) {
455 write_u1(mb->code[j]);
457 write_u2(mb->exception_table_length);
458 for (j = 0; j < (int)mb->exception_table_length; j++) {
459 write_u2(mb->exception_table[j].start_pc);
460 write_u2(mb->exception_table[j].end_pc);
461 write_u2(mb->exception_table[j].handler_pc);
462 write_u2(mb->exception_table[j].catchType);
465 /* Attributes count for Code attribute */
466 write_u2(code_attrs);
468 /* check if we have a valid line_number_table entries and
469 * if so, write out the pc and line_number entries.
470 */
472 if (mb->line_number_table_length > 0) {
473 /* line_number_table attribute exists */
474 /* attribute_name_index for "LineNumberTable" */
475 write_u2(lookup_utf8(cb, "LineNumberTable"));
476 /* Attribute length for line_number_table
477 * (exclude initial 6 bytes = 2 bytes for attr_name_index +
478 * 4 bytes for attr_length)
479 */
480 write_u4(line_no_attr_length - 6);
481 /* Length of line_number_table */
482 write_u2(mb->line_number_table_length);
483 /* write out the line_number_table entries */
484 for (j=0; j< (int) mb->line_number_table_length; j++) {
485 if (mb->line_number_table != NULL) {
486 write_u2(mb->line_number_table[j].pc);
487 write_u2(mb->line_number_table[j].line_number);
492 /* check if we have a valid localvar_table entries and
493 * if so, write out its entries
494 */
496 if (mb->localvar_table_length > 0) {
497 /* localvar_table attribute exists */
498 /* attribute_name_index for "LocalVariableTable" */
499 write_u2(lookup_utf8(cb, "LocalVariableTable"));
501 /* Attribute length for localvar_table
502 * (exclude initial 6 bytes = 2 bytes for attr_name_index +
503 * 4 bytes for attr_length)
504 */
505 write_u4(localvar_attr_length - 6);
507 /* Length of localvar_table */
508 write_u2(mb->localvar_table_length);
510 /* write out the localvar_table entries */
511 for (j=0; j< (int) mb->localvar_table_length; j++) {
512 if (mb->localvar_table != NULL) {
513 write_u2(mb->localvar_table[j].pc0);
514 write_u2(mb->localvar_table[j].length);
515 write_u2(lookup_utf8(cb,mb->localvar_table[j].name));
516 write_u2(lookup_utf8(cb,mb->localvar_table[j].signature));
517 write_u2(mb->localvar_table[j].slot);
522 if (stack_map_on && mb->n_stack_maps > 0) {
523 write_u2(lookup_utf8(cb, "StackMap"));
524 write_u4(stack_map_attr_length - 6);
525 write_u2(mb->n_stack_maps);
526 for (j = 0; j < mb->n_stack_maps; j++) {
527 write_u2(mb->stack_maps[j].offset);
528 write_u2(mb->stack_maps[j].nlocals);
529 write_stack_map(mb->stack_maps[j].nlocals,
530 mb->stack_maps[j].locals);
531 write_u2(mb->stack_maps[j].nstacks);
532 write_stack_map(mb->stack_maps[j].nstacks,
533 mb->stack_maps[j].stacks);
537 if (mb->nexceptions > 0) {
538 int j;
539 write_u2(lookup_utf8(cb, "Exceptions"));
540 write_u4(2 + mb->nexceptions * 2);
541 write_u2(mb->nexceptions);
542 for (j = 0; j < mb->nexceptions; j++) {
543 write_u2(mb->exceptions[j]);
546 if (mb->fb.deprecated) {
547 write_u2(lookup_utf8(cb, "Deprecated"));
548 write_u4(0); /* Length */
550 if (mb->fb.synthetic) {
551 write_u2(lookup_utf8(cb, "Synthetic"));
552 write_u4(0); /* Length */
557 void ensure_dir_exists(char *dir)
559 struct stat stat_buf;
560 char *parent;
561 char *q;
562 if (dir[0] == 0) {
563 return;
565 parent = strdup(dir);
566 q = strrchr(parent, '/');
567 if (q) {
568 *q = 0;
569 ensure_dir_exists(parent);
571 if (stat(dir, &stat_buf) < 0) {
572 if (JAR_DEBUG && verbose) {
573 // jio_fprintf(stderr, "Creating output directory [%s]\n", dir);
575 #ifdef WIN32
576 mkdir(dir);
577 #endif
578 #ifdef UNIX
579 mkdir(dir, 0755);
580 #endif
582 free(parent);
585 void ensure_dir_writable(char *dir)
587 struct stat stat_buf;
589 stat(dir, &stat_buf);
590 if ((stat_buf.st_mode & S_IFMT) == S_IFDIR) { /* is dir ? */
591 #ifdef WIN32
592 if (access(dir, 06) < 0) {
593 #endif
594 #ifdef UNIX
595 if (access(dir, R_OK | W_OK) < 0) {
596 #endif
597 // panic("%s is write protected\n", dir);
599 } else {
600 // panic("%s is not a directory\n", dir);
604 extern char *output_path;
606 void
607 WriteClass(ClassClass *cb)
609 int fd;
610 char fname[1024];
611 char buff[BUFSIZ];
612 char *nativeName = &buff[0];
614 class_buf = (unsigned char*)malloc(INIT_CLASS_BUF_SIZE);
615 if (class_buf == NULL) {
616 // panic("out of memory");
618 class_buf_size = INIT_CLASS_BUF_SIZE;
620 class_index = 0;
622 write_u4(0xcafebabe);
624 write_u2(cbMinorVersion(cb));
625 write_u2(cbMajorVersion(cb));
627 write_constant_pool_preverifier(cb);
629 write_u2(cbAccess(cb) & ACC_WRITTEN_FLAGS);
631 write_u2(lookup_class(cb, cbName(cb)));
632 write_u2(unhand(cb)->superclass_idx);
633 write_interfaces(cb);
634 write_fields(cb);
635 write_methods(cb);
638 /* Output number of attributes
639 * Each item in the following sum is a boolean that returns 1 or 0.
640 */
641 write_u2( (cbSourceName(cb) != NULL)
642 + (cbAbsoluteSourceName(cb) != NULL)
643 + (unhand(cb)->hasTimeStamp)
644 + (unhand(cb)->deprecated)
645 + (unhand(cb)->synthetic)
646 + (cbInnerClasses(cb) != NULL)
647 );
648 if (cbSourceName(cb) != NULL) {
649 /* write the source file attribute used for debugging purposes */
650 write_u2(lookup_utf8(cb, "SourceFile")); /* SourceFile attribute */
651 write_u4(2); /* Length */
652 /* CP entry containing the source name */
653 write_u2(lookup_utf8(cb, cbSourceName(cb)));
655 if (cbAbsoluteSourceName(cb) != NULL) {
656 /* write the source file attribute used for debugging purposes */
657 write_u2(lookup_utf8(cb, "AbsoluteSourcePath"));
658 write_u4(2);
659 write_u2(lookup_utf8(cb, cbAbsoluteSourceName(cb)));
661 if (unhand(cb)->hasTimeStamp) {
662 write_u2(lookup_utf8(cb, "TimeStamp"));
663 write_u4(8);
664 write_u4(cbTimestamp(cb).high);
665 write_u4(cbTimestamp(cb).low);
667 if (unhand(cb)->deprecated) {
668 write_u2(lookup_utf8(cb, "Deprecated")); /* attribute name */
669 write_u4(0); /* Length */
671 if (unhand(cb)->synthetic) {
672 write_u2(lookup_utf8(cb, "Synthetic")); /* attribute name */
673 write_u4(0); /* Length */
676 if (cbInnerClasses(cb) != NULL) {
677 int count = cbInnerClassesCount(cb);
678 struct innerClasses *thisInnerClass= cbInnerClasses(cb);
679 struct innerClasses *lastInnerClass = thisInnerClass + count;
680 write_u2(lookup_utf8(cb, "InnerClasses")); /* Attribute name */
681 write_u4(8 * count + 2); /* Length */
682 write_u2(count);
683 for ( ; thisInnerClass < lastInnerClass; thisInnerClass++) {
684 char *innerName = thisInnerClass->inner_name;
685 write_u2(thisInnerClass->inner_class);
686 write_u2(thisInnerClass->outer_class);
687 write_u2( (innerName != 0) ? lookup_utf8(cb, innerName) : 0);
688 write_u2(thisInnerClass->access);
692 /* Conversion for Japanese filenames */
693 utf2native(cbName(cb), nativeName, BUFSIZ);
695 // if (JARfile) {
696 /* classes need to be put in a JAR file */
697 // sprintf(fname, "%s/%s.class", tmp_dir, nativeName);
698 // } else {
699 sprintf(fname, "%s/%s.class", output_path, nativeName);
700 // }
703 char *dir = strdup(fname);
704 char *q;
706 q = strrchr(dir, '/');
707 if (q) {
708 *q = 0;
709 ensure_dir_exists(dir);
710 ensure_dir_writable(dir);
712 free(dir);
715 #ifdef UNIX
716 fd = open(fname, O_WRONLY | O_CREAT | O_TRUNC , 0644);
717 #endif
718 #ifdef WIN32
719 fd = open(fname, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644);
720 #endif
722 if (fd < 0) {
723 // panic("failed to open %s", fname);
726 tmpDirExists = TRUE; /* tmpDir exists with verified classes */
727 write(fd, class_buf, class_index);
728 close(fd);
729 free(class_buf);
730 class_buf_size = 0;
733 void
734 VerifyFile(char *fn)
736 /* If this is the first class, we'll run into problems if loading the
737 * class forces Object to be loaded, when then forces this class to
738 * be loaded. To prohibit such problems, we force Object to be loaded
739 */
740 FindClass(0, "java/lang/Object", TRUE);
743 ClassClass *cb = FindClass(0, fn, TRUE);
744 char *class_name = PrintableClassname(fn);
746 if (cb == NULL) {
747 errorCode = 1; /* set error status to indicate error */
748 // jio_fprintf(stderr, "Error loading class %s\n", class_name);
749 } else {
750 if (no_native_methods) {
751 /* Check for native methods in classes */
752 struct methodblock *mb;
753 int size;
754 mb = cbMethods(cb);
755 for (size=0; size < (int) cbMethodsCount(cb); size++, mb++) {
756 if (mb->fb.access & ACC_NATIVE) {
757 current_class_name = fn;
758 // panic("native methods should not appear");
763 VerifyClass(cb);
765 WriteClass(cb);
770 char *PrintableClassname(char *class_name)
772 char *p;
773 static char class_copy[257];
774 strncpy(class_copy, class_name, 256);
776 /* Convert all slashes in the classname to periods */
777 for (p = class_copy; ((p = strchr(p, '/')) != 0); *p++ = '.');
778 return class_copy;
781 void printCurrentClassName(void)
783 if (current_class_name) {
784 // fprintf(stderr, "Error preverifying class %s\n ",
785 // PrintableClassname(current_class_name));