1:
8:
9: package ;
10:
11:
12: import ;
13: import ;
14: import ;
15: import ;
16: import ;
17: import ;
18:
19: public class Main
20: {
21: static private boolean verbose = false;
22:
23: public static void main (String[] s)
24: {
25: boolean fileListFromStdin = false;
26: char filenameSeparator = ' ';
27:
28: insist (s.length >= 1);
29:
30: if (s[0].equals("-") ||
31: s[0].equals("-0"))
32: {
33: if (s[0].equals("-0"))
34: filenameSeparator = (char)0;
35: fileListFromStdin = true;
36: String[] newArgs = new String[s.length - 1];
37: System.arraycopy(s, 1, newArgs, 0, s.length - 1);
38: s = newArgs;
39: }
40:
41: if (s[0].equals("-v") || s[0].equals("--version"))
42: {
43: insist (s.length == 1);
44: System.out.println("gcj-dbtool ("
45: + System.getProperty("java.vm.name")
46: + ") "
47: + System.getProperty("java.vm.version"));
48: System.out.println();
49: System.out.println("Copyright 2016 Free Software Foundation, Inc.");
50: System.out.println("This is free software; see the source for copying conditions. There is NO");
51: System.out.println("warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.");
52: return;
53: }
54: if (s[0].equals("--help"))
55: {
56: usage(System.out);
57: return;
58: }
59:
60: if (s[0].equals("-n"))
61: {
62:
63: insist (s.length >= 2 && s.length <= 3);
64:
65: int capacity = 32749;
66:
67: if (s.length == 3)
68: {
69: capacity = Integer.parseInt(s[2]);
70:
71: if (capacity <= 2)
72: {
73: usage(System.err);
74: System.exit(1);
75: }
76: }
77:
78: try
79: {
80: PersistentByteMap b
81: = PersistentByteMap.emptyPersistentByteMap(new File(s[1]),
82: capacity, capacity*32);
83: }
84: catch (Exception e)
85: {
86: System.err.println ("error: could not create "
87: + s[1] + ": " + e.toString());
88: System.exit(2);
89: }
90: return;
91: }
92:
93: if (s[0].equals("-a") || s[0].equals("-f"))
94: {
95:
96:
97:
98: try
99: {
100: insist (s.length == 4);
101: File database = new File(s[1]);
102: database = database.getAbsoluteFile();
103: File jar = new File(s[2]);
104: PersistentByteMap map;
105: if (database.isFile())
106: map = new PersistentByteMap(database,
107: PersistentByteMap.AccessMode.READ_ONLY);
108: else
109: map = PersistentByteMap.emptyPersistentByteMap(database,
110: 100, 100*32);
111: File soFile = new File(s[3]);
112: if (! s[0].equals("-f") && ! soFile.isFile())
113: throw new IllegalArgumentException(s[3] + " is not a file");
114: map = addJar(jar, map, soFile);
115: }
116: catch (Exception e)
117: {
118: System.err.println ("error: could not update " + s[1]
119: + ": " + e.toString());
120: System.exit(2);
121: }
122: return;
123: }
124:
125: if (s[0].equals("-t"))
126: {
127:
128: try
129: {
130: insist (s.length == 2);
131: PersistentByteMap b
132: = new PersistentByteMap(new File(s[1]),
133: PersistentByteMap.AccessMode.READ_ONLY);
134: Iterator iterator = b.iterator(PersistentByteMap.ENTRIES);
135:
136: while (iterator.hasNext())
137: {
138: PersistentByteMap.MapEntry entry
139: = (PersistentByteMap.MapEntry)iterator.next();
140: byte[] key = (byte[])entry.getKey();
141: byte[] value = (byte[])b.get(key);
142: if (! Arrays.equals (value, (byte[])entry.getValue()))
143: {
144: String err
145: = ("Key " + bytesToString(key) + " at bucket "
146: + entry.getBucket());
147:
148: throw new RuntimeException(err);
149: }
150: }
151: }
152: catch (Exception e)
153: {
154: e.printStackTrace();
155: System.exit(3);
156: }
157: return;
158: }
159:
160: if (s[0].equals("-m"))
161: {
162:
163: insist (s.length >= 3
164: || fileListFromStdin && s.length == 2);
165: try
166: {
167: File database = new File(s[1]);
168: database = database.getAbsoluteFile();
169: File temp = File.createTempFile(database.getName(), "",
170: database.getParentFile());
171:
172: int newSize = 0;
173: int newStringTableSize = 0;
174: Fileset files = getFiles(s, 2, fileListFromStdin,
175: filenameSeparator);
176: PersistentByteMap[] sourceMaps
177: = new PersistentByteMap[files.size()];
178:
179:
180:
181: {
182: Iterator it = files.iterator();
183: int i = 0;
184: while (it.hasNext())
185: {
186: PersistentByteMap b
187: = new PersistentByteMap((File)it.next(),
188: PersistentByteMap.AccessMode.READ_ONLY);
189: newSize += b.size();
190: newStringTableSize += b.stringTableSize();
191: sourceMaps[i++] = b;
192: }
193: }
194:
195: newSize *= 1.5;
196:
197: PersistentByteMap map
198: = PersistentByteMap.emptyPersistentByteMap
199: (temp, newSize, newStringTableSize);
200:
201: for (int i = 0; i < sourceMaps.length; i++)
202: {
203: if (verbose)
204: System.err.println("adding " + sourceMaps[i].size()
205: + " elements from "
206: + sourceMaps[i].getFile());
207: map.putAll(sourceMaps[i]);
208: }
209: map.close();
210: temp.renameTo(database);
211: }
212: catch (Exception e)
213: {
214: e.printStackTrace();
215: System.exit(3);
216: }
217: return;
218: }
219:
220: if (s[0].equals("-l"))
221: {
222:
223: insist (s.length == 2);
224: try
225: {
226: PersistentByteMap b
227: = new PersistentByteMap(new File(s[1]),
228: PersistentByteMap.AccessMode.READ_ONLY);
229:
230: System.out.println ("Capacity: " + b.capacity());
231: System.out.println ("Size: " + b.size());
232: System.out.println ();
233:
234: System.out.println ("Elements: ");
235: Iterator iterator = b.iterator(PersistentByteMap.ENTRIES);
236:
237: while (iterator.hasNext())
238: {
239: PersistentByteMap.MapEntry entry
240: = (PersistentByteMap.MapEntry)iterator.next();
241: byte[] digest = (byte[])entry.getKey();
242: System.out.print ("[" + entry.getBucket() + "] "
243: + bytesToString(digest)
244: + " -> ");
245: System.out.println (new String((byte[])entry.getValue()));
246: }
247: }
248: catch (Exception e)
249: {
250: System.err.println ("error: could not list "
251: + s[1] + ": " + e.toString());
252: System.exit(2);
253: }
254: return;
255: }
256:
257: if (s[0].equals("-d"))
258: {
259:
260: insist (s.length == 2);
261: try
262: {
263: MessageDigest md = MessageDigest.getInstance("MD5");
264: PersistentByteMap b
265: = new PersistentByteMap(new File(s[1]),
266: PersistentByteMap.AccessMode.READ_WRITE);
267: int N = b.capacity();
268: byte[] bytes = new byte[1];
269: byte digest[] = md.digest(bytes);
270: for (int i = 0; i < N; i++)
271: {
272: digest = md.digest(digest);
273: b.put(digest, digest);
274: }
275: }
276: catch (Exception e)
277: {
278: e.printStackTrace();
279: System.exit(3);
280: }
281: return;
282: }
283:
284: if (s[0].equals("-p"))
285: {
286: insist (s.length == 1 || s.length == 2);
287: String result;
288:
289: if (s.length == 1)
290: result = System.getProperty("gnu.gcj.precompiled.db.path", "");
291: else
292: result = (s[1]
293: + (s[1].endsWith(File.separator) ? "" : File.separator)
294: + getDbPathTail ());
295:
296: System.out.println (result);
297: return;
298: }
299:
300: usage(System.err);
301: System.exit(1);
302: }
303:
304: private static native String getDbPathTail ();
305:
306: private static void insist(boolean ok)
307: {
308: if (! ok)
309: {
310: usage(System.err);
311: System.exit(1);
312: }
313: }
314:
315: private static void usage(PrintStream out)
316: {
317: out.println
318: ("gcj-dbtool: Manipulate gcj map database files\n"
319: + "\n"
320: + " Usage: \n"
321: + " gcj-dbtool -n file.gcjdb [size] - Create a new gcj map database\n"
322: + " gcj-dbtool -a file.gcjdb file.jar file.so\n"
323: + " - Add the contents of file.jar to a gcj map database\n"
324: + " gcj-dbtool -f file.gcjdb file.jar file.so\n"
325: + " - Add the contents of file.jar to a gcj map database\n"
326: + " gcj-dbtool -t file.gcjdb - Test a gcj map database\n"
327: + " gcj-dbtool -l file.gcjdb - List a gcj map database\n"
328: + " gcj-dbtool [-][-0] -m dest.gcjdb [source.gcjdb]...\n"
329: + " - Merge gcj map databases into dest\n"
330: + " Replaces dest\n"
331: + " To add to dest, include dest in the list of sources\n"
332: + " If the first arg is -, read the list from stdin\n"
333: + " If the first arg is -0, filenames separated by nul\n"
334: + " gcj-dbtool -p [LIBDIR] - Print default database name"
335: );
336: }
337:
338:
339:
340:
341:
342: private static PersistentByteMap
343: addJar(File f, PersistentByteMap b, File soFile)
344: throws Exception
345: {
346: MessageDigest md = MessageDigest.getInstance("MD5");
347:
348: JarFile jar = new JarFile (f);
349:
350: int count = 0;
351: {
352: Enumeration entries = jar.entries();
353: while (entries.hasMoreElements())
354: {
355: JarEntry classfile = (JarEntry)entries.nextElement();
356: if (classfile.getName().endsWith(".class"))
357: count++;
358: }
359: }
360:
361: if (verbose)
362: System.err.println("adding " + count + " elements from "
363: + f + " to " + b.getFile());
364:
365:
366:
367: b = resizeMap(b, (b.size() + count) * 2, true);
368:
369: Enumeration entries = jar.entries();
370:
371: byte[] soFileName = soFile.getCanonicalPath().getBytes("UTF-8");
372: while (entries.hasMoreElements())
373: {
374: JarEntry classfile = (JarEntry)entries.nextElement();
375: if (classfile.getName().endsWith(".class"))
376: {
377: InputStream str = jar.getInputStream(classfile);
378: int length = (int) classfile.getSize();
379: if (length == -1)
380: throw new EOFException();
381:
382: byte[] data = new byte[length];
383: int pos = 0;
384: while (length - pos > 0)
385: {
386: int len = str.read(data, pos, length - pos);
387: if (len == -1)
388: throw new EOFException("Not enough data reading from: "
389: + classfile.getName());
390: pos += len;
391: }
392: b.put(md.digest(data), soFileName);
393: }
394: }
395: return b;
396: }
397:
398:
399:
400:
401: static PersistentByteMap resizeMap(PersistentByteMap m, int newCapacity, boolean close)
402: throws IOException, IllegalAccessException
403: {
404: newCapacity = Math.max(m.capacity(), newCapacity);
405: File name = m.getFile();
406: File copy = File.createTempFile(name.getName(), "", name.getParentFile());
407: try
408: {
409: PersistentByteMap dest
410: = PersistentByteMap.emptyPersistentByteMap
411: (copy, newCapacity, newCapacity*32);
412: dest.putAll(m);
413: dest.force();
414: if (close)
415: m.close();
416: copy.renameTo(name);
417: return dest;
418: }
419: catch (Exception e)
420: {
421: copy.delete();
422: }
423: return null;
424: }
425:
426:
427: static String bytesToString(byte[] b)
428: {
429: StringBuffer hexBytes = new StringBuffer();
430: int length = b.length;
431: for (int i = 0; i < length; ++i)
432: {
433: int v = b[i] & 0xff;
434: if (v < 16)
435: hexBytes.append('0');
436: hexBytes.append(Integer.toHexString(v));
437: }
438: return hexBytes.toString();
439: }
440:
441:
442:
443:
444: private static final Fileset getFiles(String[] s, int startPos,
445: boolean fileListFromStdin,
446: char separator)
447: {
448: if (fileListFromStdin)
449: return new Fileset(System.in, separator);
450: else
451: return new Fileset(s, startPos, s.length);
452: }
453: }
454:
455:
456:
457: class Tokenizer
458: {
459: final Reader r;
460: final char separator;
461:
462: Tokenizer(Reader r, char separator)
463: {
464: this.r = r;
465: this.separator = separator;
466: }
467:
468: boolean isSeparator(int c)
469: {
470: if (Character.isWhitespace(separator))
471: return Character.isWhitespace((char)c);
472: else
473: return c == separator;
474: }
475:
476:
477:
478: String nextToken ()
479: {
480: StringBuffer buf = new StringBuffer();
481: int c;
482: try
483: {
484: while ((c = r.read()) != -1)
485: {
486: if (! isSeparator(c))
487: {
488: buf.append((char)c);
489: break;
490: }
491: }
492: while ((c = r.read()) != -1)
493: {
494: if (isSeparator(c))
495: break;
496: else
497: buf.append((char)c);
498: }
499: }
500: catch (java.io.IOException e)
501: {
502: }
503: return buf.toString();
504: }
505: }
506:
507:
508:
509:
510: class Fileset
511: {
512: LinkedHashSet files = new LinkedHashSet();
513:
514: Fileset (String[] s, int start, int end)
515: {
516: for (int i = start; i < end; i++)
517: {
518: files.add(new File(s[i]));
519: }
520: }
521:
522: Fileset (InputStream is, char separator)
523: {
524: Reader r = new BufferedReader(new InputStreamReader(is));
525: Tokenizer st = new Tokenizer(r, separator);
526: String name;
527: while (! "".equals(name = st.nextToken()))
528: files.add(new File(name));
529: }
530:
531: Iterator iterator()
532: {
533: return files.iterator();
534: }
535:
536: int size()
537: {
538: return files.size();
539: }
540: }