Current section

Files

Jump to
grisp_updater src grisp_updater_dummy.erl
Raw

src/grisp_updater_dummy.erl

-module(grisp_updater_dummy).
-behaviour(grisp_updater_system).
%--- Includes ------------------------------------------------------------------
-include_lib("kernel/include/logger.hrl").
-include("grisp_updater.hrl").
%--- Exports -------------------------------------------------------------------
% Behaviour grisp_updater_system callbacks
-export([system_init/1]).
-export([system_get_global_target/1]).
-export([system_get_systems/1]).
-export([system_prepare_update/2]).
-export([system_prepare_target/4]).
-export([system_set_updated/2]).
-export([system_cancel_update/1]).
-export([system_validate/1]).
-export([system_terminate/2]).
%--- Records -------------------------------------------------------------------
-record(state, {
boot :: grisp_updater_system:system_id() | removable,
valid :: grisp_updater_system:system_id(),
next :: grisp_updater_system:system_id(),
device :: binary(),
size :: non_neg_integer()
}).
%--- Macros --------------------------------------------------------------------
-define(DEFAULT_BOOT, removable).
-define(DEFAULT_VALID, 0).
-define(DEFAULT_NEXT, 0).
-define(DEFAULT_DEVICE, <<"dummy.img">>).
-define(DEFAULT_DEVICE_SIZE, ((4 + 256 + 256) * (1024 * 1024))).
%--- Behaviour grisp_updater_system Callback -----------------------------------
system_init(Opts) ->
?LOG_INFO("Initializing GRiSP updater's dummy system interface", []),
Boot = case maps:find(boot_system, Opts) of
{ok, Sys1} when Sys1 =:= removable; Sys1 >= 0, Sys1 =< 1 -> Sys1;
error -> ?DEFAULT_BOOT
end,
Valid = case maps:find(valid_system, Opts) of
{ok, Sys2} when Sys2 >= 0, Sys2 =< 1 -> Sys2;
error -> ?DEFAULT_VALID
end,
Next = case maps:find(next_system, Opts) of
{ok, Sys3} when Sys3 >= 0, Sys3 =< 1 -> Sys3;
error -> ?DEFAULT_NEXT
end,
DeviceFile = case maps:find(device_file, Opts) of
{ok, F} when is_list(F); is_binary(F) -> F;
error ->
{ok, CurrDir} = file:get_cwd(),
filename:join(CurrDir, ?DEFAULT_DEVICE)
end,
DeviceSize = case maps:find(device_size, Opts) of
{ok, S} when is_integer(S), S > 0 -> S;
error -> ?DEFAULT_DEVICE_SIZE
end,
State = #state{boot = Boot, valid = Valid, next = Next,
device = DeviceFile, size = DeviceSize},
ok = filelib:ensure_dir(DeviceFile),
case file:open(DeviceFile, [raw, write, read]) of
{error, _Reason} = Error -> Error;
{ok, File} ->
case file:pread(File, DeviceSize - 1, 1) of
{ok, [_]} ->
ok = file:close(File),
{ok, State};
eof ->
ok = file:pwrite(File, DeviceSize - 1, <<0>>),
ok = file:close(File),
{ok, State};
{error, _Reason} = Error -> Error
end
end.
system_get_global_target(#state{device = Device, size = Size}) ->
#target{device = Device, offset = 0, size = Size, total = Size}.
system_get_systems(#state{boot = Boot, valid = Valid, next = Next}) ->
{Boot, Valid, Next}.
system_prepare_update(State, 1) ->
?LOG_DEBUG("Preparing system 1 for update", []),
{ok, State}.
system_prepare_target(_State, SysId, _SysTarget,
#file_target_spec{context = Context, path = Path}) ->
Path2 = iolist_to_binary(lists:join("#", string:split(Path, "/", all))),
Path3 = iolist_to_binary(io_lib:format("dummy.~s", [Path2])),
Path4 = case Context of
system -> iolist_to_binary(io_lib:format("~s.~b", [Path3, SysId]));
_ -> Path3
end,
{ok, #target{device = Path4, offset = 0, size = undefined}};
system_prepare_target(_State, _SysId, #target{offset = SysOffset} = SysTarget,
#raw_target_spec{context = system, offset = ObjOffset}) ->
{ok, SysTarget#target{offset = SysOffset + ObjOffset}};
system_prepare_target(#state{device = Device}, _SysId, _SysTarget,
#raw_target_spec{context = global, offset = Offset}) ->
{ok, #target{device = Device, offset = Offset, size = undefined}}.
system_set_updated(State, SystemId) ->
?LOG_DEBUG("System ~b marked as update", [SystemId]),
{ok, State}.
system_cancel_update(State) ->
?LOG_DEBUG("Update canceled", []),
{ok, State}.
system_validate(State) ->
?LOG_DEBUG("Current system marked as validated", []),
{ok, State}.
system_terminate(_State, _Reason) ->
?LOG_INFO("Terminating GRiSP updater's dummy system interface", []),
ok.