#include <bee2/core/der.h>
#include <bee2/core/file.h>
#include <bee2/core/mem.h>
#include <bee2/core/str.h>
#include <bee2/core/util.h>
#include <bee2/crypto/bash.h>
#include "bee2/cmd.h"
static err_t cmdFileStamp(
octet* stamp,
const char* name,
bool_t suffix
)
{
const size_t buf_size = 4096;
err_t code;
octet* stack;
octet* buf;
octet* stamp1;
octet* stamp2;
octet* state;
file_t file;
size_t count;
bool_t stamped;
ASSERT((suffix == TRUE && stamp == 0) || memIsValid(stamp, 10));
ASSERT(strIsValid(name));
code = cmdBlobCreate(stack, buf_size + 20 + bashHash_keep());
ERR_CALL_CHECK(code);
buf = stack;
stamp1 = buf + buf_size;
stamp2 = stamp1 + 10;
state = stamp2 + 10;
code = cmdFileOpen(file, name, "rb");
ERR_CALL_HANDLE(code, cmdBlobClose(stack));
if ((count = fileSize(file)) == SIZE_MAX)
code = ERR_FILE_READ;
ERR_CALL_HANDLE(code, (cmdFileClose(file), cmdBlobClose(stack)));
stamped = FALSE;
if (suffix && count >= 10)
{
if (!fileSeek(file, count - 10, SEEK_SET) ||
fileRead2(stamp2, 10, file) != 10 ||
!fileSeek(file, 0, SEEK_SET))
code = ERR_FILE_READ;
ERR_CALL_HANDLE(code, (cmdFileClose(file), cmdBlobClose(stack)));
memRev(stamp2, 10);
stamped = (derOCTDec2(0, stamp2, 10, 8) == 10);
memRev(stamp2, 10);
}
if (stamp == 0 && !stamped)
code = ERR_MAX;
ERR_CALL_HANDLE(code, (cmdFileClose(file), cmdBlobClose(stack)));
count = stamped ? count - 10 : count;
bashHashStart(state, 32);
while (count)
{
size_t c = MIN2(count, buf_size);
if (fileRead2(buf, c, file) != c)
code = ERR_FILE_READ;
ERR_CALL_HANDLE(code, (cmdFileClose(file), cmdBlobClose(stack)));
bashHashStepH(buf, c, state);
count -= c;
}
code = cmdFileClose2(file);
ERR_CALL_HANDLE(code, cmdBlobClose(stack));
bashHashStepG(stamp1, 8, state);
VERIFY(derOCTEnc(stamp1, stamp1, 8) == 10);
memRev(stamp1, 10);
if (suffix)
{
if (stamped)
code = memEq(stamp1, stamp2, 10) ? ERR_OK : ERR_FILE_STAMP;
else
code = ERR_MAX;
}
if (stamp)
memCopy(stamp, stamp1, 10);
cmdBlobClose(stack);
return code;
}
err_t cmdStampGen(const char* stamp_name, const char* name)
{
err_t code;
octet* stamp;
if (!strIsValid(name) || !strIsValid(stamp_name))
return ERR_BAD_INPUT;
code = cmdBlobCreate(stamp, 10);
ERR_CALL_CHECK(code);
cmdFileStamp(stamp, name, FALSE);
if (cmdFileAreSame(name, stamp_name))
code = cmdFileAppend(name, stamp, 10);
else
code = cmdFileWrite(stamp_name, stamp, 10);
cmdBlobClose(stamp);
return code;
}
err_t cmdStampVal(const char* name, const char* stamp_name)
{
err_t code;
if (!strIsValid(name) || !strIsValid(stamp_name))
return ERR_BAD_INPUT;
if (cmdFileAreSame(name, stamp_name))
{
code = cmdFileStamp(0, name, TRUE);
if (code == ERR_MAX)
code = ERR_FILE_STAMP;
}
else
{
void* stack;
octet* stamp;
octet* stamp1;
size_t count;
code = cmdBlobCreate(stack, 20);
ERR_CALL_CHECK(code);
stamp = (octet*)stack;
stamp1 = stamp + 10;
code = cmdFileStamp(stamp, name, FALSE);
ERR_CALL_HANDLE(code, cmdBlobClose(stack));
count = 10;
code = cmdFileReadAll(stamp1, &count, stamp_name);
ERR_CALL_HANDLE(code, cmdBlobClose(stack));
if (!memEq(stamp, stamp1, 10))
code = ERR_FILE_STAMP;
cmdBlobClose(stack);
}
return code;
}
err_t cmdStampSelfVal()
{
const char* ext = ".stamp";
err_t code;
size_t count;
void* stack;
octet* stamp;
octet* stamp1;
char* name;
code = cmdSysModulePath(0, &count);
ERR_CALL_CHECK(code);
code = cmdBlobCreate(stack, 10 + 10 + count + strLen(ext));
ERR_CALL_CHECK(code);
stamp = (octet*)stack;
stamp1 = stamp + 10;
name = (char*)(stamp1 + 10);
code = cmdSysModulePath(name, &count);
ERR_CALL_HANDLE(code, cmdBlobClose(stack));
code = cmdFileStamp(stamp, name, TRUE);
if (code == ERR_MAX)
{
count = 10;
strCopy(name + strLen(name), ext);
code = cmdFileReadAll(stamp1, &count, name);
ERR_CALL_HANDLE(code, cmdBlobClose(stack));
if (!memEq(stamp, stamp1, 10))
code = ERR_FILE_STAMP;
}
cmdBlobClose(stack);
return code;
}