package org.jerlang.stdlib.beam_lib;
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.EOFException;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.file.Files;
import org.jerlang.erts.erlang.Error;
import org.jerlang.stdlib.Lists;
import org.jerlang.type.Atom;
import org.jerlang.type.Integer;
import org.jerlang.type.List;
import org.jerlang.type.Str;
import org.jerlang.type.Term;
import org.jerlang.type.Tuple;
import org.jerlang.util.ByteUtil;
public class BeamLibInfo {
private BeamLibInfo() {
}
public static final Atom beam_lib = Atom.of("beam_lib");
public static final Atom enoent = Atom.of("enoent");
public static final Atom eperm = Atom.of("eperm");
public static final Atom error = Atom.of("error");
public static final Atom file = Atom.of("file");
public static final Atom file_error = Atom.of("file_error");
public static final Atom invalid_beam_file = Atom.of("invalid_beam_file");
public static final Atom not_a_beam_file = Atom.of("not_a_beam_file");
public static Term dispatch(List params) {
switch (params.length()) {
case 1:
return info_1(params.head().toStr());
default:
throw Error.badarg;
}
}
public static Term info_1(Str filename_term) {
File file = new File(filename_term.string());
Term result = new List();
if (!file.exists()) {
return Tuple.of(error, beam_lib, Tuple.of(file_error, filename_term, enoent));
}
if (!file.canRead()) {
return Tuple.of(error, beam_lib, Tuple.of(file_error, filename_term, eperm));
}
try {
byte[] bytes = ByteUtil.maybe_decompress(Files.readAllBytes(file.toPath()));
result = do_info(filename_term, bytes);
if (result instanceof List) {
result = new List(Tuple.of(Atom.of("file"), filename_term), (List) result);
}
} catch (FileNotFoundException fileNotFoundException) {
return Tuple.of(error, beam_lib, Tuple.of(file_error, filename_term, enoent));
} catch (EOFException eofException) {
return Tuple.of(error, beam_lib, Tuple.of(invalid_beam_file, filename_term, Integer.ZERO));
} catch (IOException ioException) {
System.err.println("IOException: " + ioException);
}
return result;
}
private static Term do_info(Term filename, byte[] bytes) throws IOException {
List chunks = List.nil;
DataInputStream dis = new DataInputStream(new ByteArrayInputStream(bytes));
if (dis.readInt() != 0x464f5231) { // "FOR1"
return Tuple.of(not_a_beam_file, filename);
}
int length = dis.readInt();
if (dis.readInt() != 0x4245414d) { // "BEAM"
return Tuple.of(not_a_beam_file, filename);
}
int offset = 20;
while (offset < length) {
Chunk chunk = new Chunk(ChunkId.of(dis.readInt()), offset, dis.readInt());
// Unknown chunk tags are ignored
if (chunk.id() != null && !chunk.id().skip()) {
chunks = new List(chunk.asTuple(), chunks);
}
offset += 8 + ((chunk.length() + 3) & ~3);
dis.skipBytes((chunk.length() + 3) & ~3);
}
return new List(Tuple.of(Atom.of("chunks"), Lists.reverse(chunks)));
}
}