Implement bytes
This commit is contained in:
parent
257bf51bb4
commit
00c94d88d6
3 changed files with 90 additions and 38 deletions
|
@ -211,7 +211,13 @@ defmodule GenMagic.Server do
|
|||
@doc false
|
||||
def available({:call, from}, {:perform, path}, data) do
|
||||
data = %{data | cycles: data.cycles + 1, request: {path, from, :erlang.now()}}
|
||||
send(data.port, {:file, path})
|
||||
arg =
|
||||
case path do
|
||||
path when is_binary(path) -> {:file, path}
|
||||
{:bytes, bytes} -> {:bytes, bytes}
|
||||
end
|
||||
|
||||
send(data.port, arg)
|
||||
{:next_state, :processing, data}
|
||||
end
|
||||
|
||||
|
|
104
src/apprentice.c
104
src/apprentice.c
|
@ -68,7 +68,9 @@ void setup_system();
|
|||
int process_command(byte *buf);
|
||||
void process_line(char *line);
|
||||
void process_file(char *path, ei_x_buff *result);
|
||||
void process_bytes(char *bytes, int size, ei_x_buff *result);
|
||||
void error(ei_x_buff *result, const char *error);
|
||||
void handle_magic_error(magic_t handle, int errn, ei_x_buff *result);
|
||||
|
||||
struct magic_file {
|
||||
struct magic_file *prev;
|
||||
|
@ -105,7 +107,7 @@ int main(int argc, char **argv) {
|
|||
int process_command(byte *buf) {
|
||||
ei_x_buff result;
|
||||
char atom[128];
|
||||
int index, version, arity;
|
||||
int index, version, arity, termtype, termsize;
|
||||
index = 0;
|
||||
|
||||
if (ei_decode_version(buf, &index, &version) != 0)
|
||||
|
@ -130,25 +132,35 @@ int process_command(byte *buf) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
if (strncmp(atom, "file", 3) == 0) {
|
||||
int pathtype;
|
||||
int pathsize;
|
||||
if (strncmp(atom, "file", 4) == 0) {
|
||||
char path[4097];
|
||||
ei_get_type(buf, &index, &pathtype, &pathsize);
|
||||
ei_get_type(buf, &index, &termtype, &termsize);
|
||||
|
||||
if (pathtype == ERL_BINARY_EXT && pathsize < 4096) {
|
||||
if (termtype == ERL_BINARY_EXT && termsize < 4096) {
|
||||
long bin_length;
|
||||
ei_decode_binary(buf, &index, path, &bin_length);
|
||||
path[pathsize] = '\0';
|
||||
path[termsize] = '\0';
|
||||
process_file(path, &result);
|
||||
} else {
|
||||
error(&result, "badarg");
|
||||
return 1;
|
||||
}
|
||||
} else if (strncmp(atom, "bytes", 3) == 0) {
|
||||
ei_x_encode_atom(&result, "ok");
|
||||
ei_x_encode_atom(&result, "bytes_not_implemented");
|
||||
} else if (strncmp(atom, "stop", 3) == 0) {
|
||||
} else if (strncmp(atom, "bytes", 5) == 0) {
|
||||
int termtype;
|
||||
int termsize;
|
||||
char bytes[51];
|
||||
ei_get_type(buf, &index, &termtype, &termsize);
|
||||
|
||||
if (termtype == ERL_BINARY_EXT && termsize < 50) {
|
||||
long bin_length;
|
||||
ei_decode_binary(buf, &index, bytes, &bin_length);
|
||||
bytes[termsize] = '\0';
|
||||
process_bytes(bytes, termsize, &result);
|
||||
} else {
|
||||
error(&result, "badarg");
|
||||
return 1;
|
||||
}
|
||||
} else if (strncmp(atom, "stop", 4) == 0) {
|
||||
exit(ERROR_OK);
|
||||
} else {
|
||||
error(&result, "badarg");
|
||||
|
@ -249,44 +261,72 @@ magic_t magic_setup(int flags) {
|
|||
return magic;
|
||||
}
|
||||
|
||||
void process_file(char *path, ei_x_buff *result) {
|
||||
const char *mime_type_result = magic_file(magic_mime_type, path);
|
||||
const char *mime_type_error = magic_error(magic_mime_type);
|
||||
int mime_type_errno = magic_errno(magic_mime_type);
|
||||
void process_bytes(char *path, int size, ei_x_buff *result) {
|
||||
const char *mime_type_result = magic_buffer(magic_mime_type, path, size);
|
||||
const int mime_type_errno = magic_errno(magic_mime_type);
|
||||
|
||||
if (mime_type_errno > 0) {
|
||||
handle_magic_error(magic_mime_type, mime_type_errno, result);
|
||||
return;
|
||||
}
|
||||
|
||||
const char *mime_encoding_result = magic_buffer(magic_mime_encoding, path, size);
|
||||
int mime_encoding_errno = magic_errno(magic_mime_encoding);
|
||||
|
||||
if (mime_encoding_errno > 0) {
|
||||
handle_magic_error(magic_mime_encoding, mime_encoding_errno, result);
|
||||
return;
|
||||
}
|
||||
|
||||
const char *type_name_result = magic_buffer(magic_type_name, path, size);
|
||||
int type_name_errno = magic_errno(magic_type_name);
|
||||
|
||||
if (type_name_errno > 0) {
|
||||
handle_magic_error(magic_type_name, type_name_errno, result);
|
||||
return;
|
||||
}
|
||||
|
||||
ei_x_encode_atom(result, "ok");
|
||||
ei_x_encode_tuple_header(result, 3);
|
||||
ei_x_encode_binary(result, mime_type_result, strlen(mime_type_result));
|
||||
ei_x_encode_binary(result, mime_encoding_result,
|
||||
strlen(mime_encoding_result));
|
||||
ei_x_encode_binary(result, type_name_result, strlen(type_name_result));
|
||||
return;
|
||||
}
|
||||
|
||||
void handle_magic_error(magic_t handle, int errn, ei_x_buff *result) {
|
||||
const char *error = magic_error(handle);
|
||||
ei_x_encode_atom(result, "error");
|
||||
ei_x_encode_tuple_header(result, 2);
|
||||
long errlon = (long)mime_type_errno;
|
||||
long errlon = (long)errn;
|
||||
ei_x_encode_long(result, errlon);
|
||||
ei_x_encode_binary(result, mime_type_error, strlen(mime_type_error));
|
||||
ei_x_encode_binary(result, error, strlen(error));
|
||||
return;
|
||||
}
|
||||
|
||||
void process_file(char *path, ei_x_buff *result) {
|
||||
const char *mime_type_result = magic_file(magic_mime_type, path);
|
||||
const int mime_type_errno = magic_errno(magic_mime_type);
|
||||
|
||||
if (mime_type_errno > 0) {
|
||||
handle_magic_error(magic_mime_type, mime_type_errno, result);
|
||||
return;
|
||||
}
|
||||
|
||||
const char *mime_encoding_result = magic_file(magic_mime_encoding, path);
|
||||
const char *mime_encoding_error = magic_error(magic_mime_encoding);
|
||||
int mime_encoding_errno = magic_errno(magic_mime_encoding);
|
||||
|
||||
if (mime_encoding_error) {
|
||||
ei_x_encode_atom(result, "error");
|
||||
ei_x_encode_tuple_header(result, 2);
|
||||
long errlon = (long)mime_encoding_errno;
|
||||
ei_x_encode_long(result, errlon);
|
||||
ei_x_encode_binary(result, mime_encoding_error,
|
||||
strlen(mime_encoding_error));
|
||||
if (mime_encoding_errno > 0) {
|
||||
handle_magic_error(magic_mime_encoding, mime_encoding_errno, result);
|
||||
return;
|
||||
}
|
||||
|
||||
const char *type_name_result = magic_file(magic_type_name, path);
|
||||
const char *type_name_error = magic_error(magic_type_name);
|
||||
int type_name_errno = magic_errno(magic_type_name);
|
||||
|
||||
if (type_name_error) {
|
||||
ei_x_encode_atom(result, "error");
|
||||
ei_x_encode_tuple_header(result, 2);
|
||||
long errlon = (long)type_name_errno;
|
||||
ei_x_encode_long(result, errlon);
|
||||
ei_x_encode_binary(result, type_name_error, strlen(type_name_error));
|
||||
if (type_name_errno > 0) {
|
||||
handle_magic_error(magic_type_name, type_name_errno, result);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -66,19 +66,25 @@ defmodule GenMagic.ApprenticeTest do
|
|||
refute_receive _
|
||||
end
|
||||
|
||||
test "works", %{port: port} do
|
||||
test "file works", %{port: port} do
|
||||
send(port, {self(), {:command, :erlang.term_to_binary({:file, Path.expand("Makefile")})}})
|
||||
assert_receive {^port, {:data, data}}
|
||||
assert {:ok, _} = :erlang.binary_to_term(data)
|
||||
end
|
||||
|
||||
test "bytes works", %{port: port} do
|
||||
send(port, {self(), {:command, :erlang.term_to_binary({:bytes, "some bytes!"})}})
|
||||
assert_receive {^port, {:data, data}}
|
||||
assert {:ok, _} = :erlang.binary_to_term(data)
|
||||
end
|
||||
|
||||
test "fails with non existent file", %{port: port} do
|
||||
send(port, {self(), {:command, :erlang.term_to_binary({:file, "/path/to/nowhere"})}})
|
||||
assert_receive {^port, {:data, data}}
|
||||
assert {:error, _} = :erlang.binary_to_term(data)
|
||||
end
|
||||
|
||||
test "works with big path", %{port: port} do
|
||||
test "works with big file path", %{port: port} do
|
||||
file = too_big() <> "/a"
|
||||
File.mkdir_p!(too_big())
|
||||
File.touch!(file)
|
||||
|
|
Loading…
Reference in a new issue