aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar bigfoot547 <[email protected]>2023-12-27 06:51:29 -0600
committerLibravatar bigfoot547 <[email protected]>2023-12-27 06:51:29 -0600
commit5e141e336c3a2cb8921edcd7af6f14a29ff63942 (patch)
tree80df676cd02693746b505aecbec5c9ee529b5e7b
parentrefactor instances (diff)
add cheap SHA1 implementation
-rw-r--r--meson.build8
-rw-r--r--src/cmd-instance.c2
-rw-r--r--src/cmd-version.c20
-rw-r--r--src/command.c42
-rw-r--r--src/config.h.in3
-rw-r--r--src/digest/digest.h32
-rw-r--r--src/digest/sha1.c253
-rw-r--r--src/endian.c28
-rw-r--r--src/endian.h43
-rw-r--r--src/instance.c4
-rw-r--r--src/meson.build2
-rw-r--r--src/uuid/uuid.c6
-rw-r--r--src/uuid/uuid.h1
-rw-r--r--src/version.h11
14 files changed, 450 insertions, 5 deletions
diff --git a/meson.build b/meson.build
index cdb51a0..e65eb11 100644
--- a/meson.build
+++ b/meson.build
@@ -9,5 +9,13 @@ config_data = configuration_data()
config_data.set_quoted('PROJECT_NAME', 'l2su')
config_data.set_quoted('PROJECT_NAME_UPPER', 'L2SU')
+if host_machine.endian() == 'little'
+ config_data.set('L2SU_ENDIAN_LITTLE', true)
+elif host_machine.endian() == 'big'
+ config_data.set('L2SU_ENDIAN_BIG', true)
+else
+ error('Middle endian is unsupported')
+endif
+
subdir('src')
executable('l2su', launcher_srcs, dependencies : [curl_dep, jansson_dep], include_directories : [config_include_dir], override_options : {'c_std': 'c99'})
diff --git a/src/cmd-instance.c b/src/cmd-instance.c
index c81eb7c..7a569e8 100644
--- a/src/cmd-instance.c
+++ b/src/cmd-instance.c
@@ -139,7 +139,7 @@ unsigned cmd_instance_add(struct l2_context_node *ctx, char **args)
struct l2_instance inst;
- inst.uuid = uuid;
+ l2_uuid_copy(&inst.uuid, &uuid);
inst.name = name;
inst.path = path;
diff --git a/src/cmd-version.c b/src/cmd-version.c
new file mode 100644
index 0000000..873108a
--- /dev/null
+++ b/src/cmd-version.c
@@ -0,0 +1,20 @@
+#include "command.h"
+#include "commands.h"
+#include "digest/digest.h"
+
+#include <stdio.h>
+
+unsigned cmd_version_list_remote(struct l2_context_node *ctx, char **args)
+{
+ return CMD_RESULT_SUCCESS;
+}
+
+unsigned cmd_version_list_local(struct l2_context_node *ctx, char **args)
+{
+ return CMD_RESULT_SUCCESS;
+}
+
+unsigned cmd_version_install(struct l2_context_node *ctx, char **args)
+{
+ return CMD_RESULT_SUCCESS;
+}
diff --git a/src/command.c b/src/command.c
index 2f91db0..55e7970 100644
--- a/src/command.c
+++ b/src/command.c
@@ -99,6 +99,48 @@ struct l2_command_node l2_cmd_root = {
{ 0 }
}
},
+ {
+ .type = CMD_NODE_TYPE_LITERAL,
+ .name = "version",
+
+ .children = (struct l2_command_node []) {
+ {
+ .type = CMD_NODE_TYPE_LITERAL,
+ .name = "list",
+
+ .children = (struct l2_command_node []) {
+ {
+ .type = CMD_NODE_TYPE_LITERAL,
+ .name = "local",
+
+ .cmd_proc = &cmd_version_list_local
+ },
+ {
+ .type = CMD_NODE_TYPE_LITERAL,
+ .name = "remote",
+
+ .cmd_proc = &cmd_version_list_remote
+ },
+ { 0 }
+ }
+ },
+ {
+ .type = CMD_NODE_TYPE_LITERAL,
+ .name = "install",
+
+ .children = (struct l2_command_node []) {
+ {
+ .type = CMD_NODE_TYPE_ARGUMENT,
+ .name = "remotever",
+
+ .cmd_proc = &cmd_version_install
+ },
+ { 0 }
+ }
+ },
+ { 0 }
+ }
+ },
{ 0 }
}
};
diff --git a/src/config.h.in b/src/config.h.in
index 05e3045..df91d35 100644
--- a/src/config.h.in
+++ b/src/config.h.in
@@ -4,4 +4,7 @@
#mesondefine PROJECT_NAME
#mesondefine PROJECT_NAME_UPPER
+#mesondefine L2SU_ENDIAN_LITTLE
+#mesondefine L2SU_ENDIAN_BIG
+
#endif /* include guard */
diff --git a/src/digest/digest.h b/src/digest/digest.h
new file mode 100644
index 0000000..d047b8e
--- /dev/null
+++ b/src/digest/digest.h
@@ -0,0 +1,32 @@
+#ifndef L2SU_DIGEST_H_INCLUDED
+#define L2SU_DIGEST_H_INCLUDED
+
+#include <stdint.h>
+#include <stddef.h>
+
+#define L2_SHA1_BLOCKLEN (64) /* 512 / 8 = 64 */
+#define L2_SHA1_DIGESTLEN (5) /* 160 / 32 = 5 */
+#define L2_SHA1_HEX_STRLEN (40)
+
+typedef struct tag_l2_sha1_state {
+ /* struct members are internal do not use directly */
+ uint32_t state[L2_SHA1_DIGESTLEN];
+ uint8_t chunk[L2_SHA1_BLOCKLEN];
+ size_t nchunk;
+ uint64_t totallen;
+} l2_sha1_state_t;
+
+typedef struct tag_l2_sha1_digest {
+ uint32_t state[L2_SHA1_DIGESTLEN];
+} l2_sha1_digest_t;
+
+void l2_sha1_init(l2_sha1_state_t *st);
+void l2_sha1_update(l2_sha1_state_t *st, const void *data, size_t sz);
+void l2_sha1_finalize(l2_sha1_state_t *st, l2_sha1_digest_t *digest);
+
+int l2_sha1_digest_compare(const l2_sha1_digest_t *d1, const l2_sha1_digest_t *d2);
+void l2_sha1_digest_copy(l2_sha1_digest_t *restrict dest, const l2_sha1_digest_t *restrict src);
+void l2_sha1_digest_to_hex(const l2_sha1_digest_t *dg, char *out);
+int l2_sha1_digest_from_hex(l2_sha1_digest_t *dg, const char *in);
+
+#endif /* include guard */
diff --git a/src/digest/sha1.c b/src/digest/sha1.c
new file mode 100644
index 0000000..6601961
--- /dev/null
+++ b/src/digest/sha1.c
@@ -0,0 +1,253 @@
+#include "digest.h"
+#include "endian.h"
+
+#include <string.h>
+#include <stdio.h>
+#include <inttypes.h>
+
+#define L2_SHA1_H0 UINT32_C(0x67452301)
+#define L2_SHA1_H1 UINT32_C(0xEFCDAB89)
+#define L2_SHA1_H2 UINT32_C(0x98BADCFE)
+#define L2_SHA1_H3 UINT32_C(0x10325476)
+#define L2_SHA1_H4 UINT32_C(0xC3D2E1F0)
+
+#define L2_SHA1_K0 UINT32_C(0x5A827999)
+#define L2_SHA1_K1 UINT32_C(0x6ED9EBA1)
+#define L2_SHA1_K2 UINT32_C(0x8F1BBCDC)
+#define L2_SHA1_K3 UINT32_C(0xCA62C1D6)
+
+void l2_sha1_init(l2_sha1_state_t *st)
+{
+ st->state[0] = L2_SHA1_H0;
+ st->state[1] = L2_SHA1_H1;
+ st->state[2] = L2_SHA1_H2;
+ st->state[3] = L2_SHA1_H3;
+ st->state[4] = L2_SHA1_H4;
+
+ memset(st->chunk, 0, L2_SHA1_BLOCKLEN);
+ st->nchunk = 0;
+ st->totallen = 0;
+}
+
+uint32_t l2_sha1__rol(uint32_t in, uint32_t v)
+{
+ return (in << v) | (in >> (32 - v));
+}
+
+void l2_sha1__update_int(l2_sha1_state_t *st)
+{
+ uint32_t w[80];
+
+ for (int i = 0; i < 16; ++i) {
+ memcpy(w + i, st->chunk + (i * 4), 4);
+ w[i] = l2_betoh32(w[i]);
+ }
+
+ for (unsigned i = 16; i < 80; ++i) {
+ w[i] = l2_sha1__rol((w[i-3] ^ w[i-8] ^ w[i-14] ^ w[i-16]), 1);
+ }
+
+ uint32_t a, b, c, d, e, f, k, temp;
+ a = st->state[0];
+ b = st->state[1];
+ c = st->state[2];
+ d = st->state[3];
+ e = st->state[4];
+
+ for (unsigned i = 0; i < 80; ++i) {
+ if (i < 20) {
+ f = (b & c) ^ ((~b) & d);
+ k = L2_SHA1_K0;
+ } else if (i < 40) {
+ f = b ^ c ^ d;
+ k = L2_SHA1_K1;
+ } else if (i < 60) {
+ f = (b & c) ^ (b & d) ^ (c & d);
+ k = L2_SHA1_K2;
+ } else {
+ f = b ^ c ^ d;
+ k = L2_SHA1_K3;
+ }
+
+ temp = l2_sha1__rol(a, 5) + f + e + k + w[i];
+ e = d;
+ d = c;
+ c = l2_sha1__rol(b, 30);
+ b = a;
+ a = temp;
+ }
+
+ st->state[0] += a;
+ st->state[1] += b;
+ st->state[2] += c;
+ st->state[3] += d;
+ st->state[4] += e;
+}
+
+void l2_sha1_update(l2_sha1_state_t *st, const void *data, size_t sz)
+{
+ const uint8_t *dbytes = data;
+ size_t rem;
+ st->totallen += sz;
+
+ if (sz < L2_SHA1_BLOCKLEN - st->nchunk) {
+ memcpy(st->chunk + st->nchunk, dbytes, sz);
+ st->nchunk += sz;
+ return;
+ }
+
+ while (sz >= (rem = (L2_SHA1_BLOCKLEN - st->nchunk))) {
+ memcpy(st->chunk, dbytes, rem);
+ l2_sha1__update_int(st);
+
+ st->nchunk = 0;
+ dbytes += rem;
+ sz -= rem;
+ }
+
+ if (sz > 0) {
+ memcpy(st->chunk, dbytes, sz);
+ st->nchunk = sz;
+ }
+}
+
+void l2_sha1_finalize(l2_sha1_state_t *st, l2_sha1_digest_t *digest)
+{
+ st->chunk[st->nchunk] = UINT8_C(0x80);
+ ++st->nchunk;
+ if (st->nchunk > (L2_SHA1_BLOCKLEN - 8)) {
+ /* must pad the rest of the way */
+ memset(st->chunk + st->nchunk, 0, L2_SHA1_BLOCKLEN - st->nchunk);
+ l2_sha1__update_int(st);
+ st->nchunk = 0;
+ }
+
+ size_t rem = (L2_SHA1_BLOCKLEN - st->nchunk) - 8;
+ uint64_t len = l2_htobe64(st->totallen * 8);
+ memset(st->chunk + st->nchunk, 0, rem);
+ st->nchunk += rem;
+
+ memcpy(st->chunk + st->nchunk, (uint8_t *)&len, 8);
+ l2_sha1__update_int(st);
+
+ digest->state[0] = st->state[0];
+ digest->state[1] = st->state[1];
+ digest->state[2] = st->state[2];
+ digest->state[3] = st->state[3];
+ digest->state[4] = st->state[4];
+}
+
+int l2_sha1_digest_compare(const l2_sha1_digest_t *d1, const l2_sha1_digest_t *d2)
+{
+ return memcmp(d1, d2, sizeof(l2_sha1_digest_t));
+}
+
+void l2_sha1_digest_copy(l2_sha1_digest_t *restrict dest, const l2_sha1_digest_t *restrict src)
+{
+ memcpy(dest, src, sizeof(l2_sha1_digest_t));
+}
+
+void l2_sha1_digest_to_hex(const l2_sha1_digest_t *dg, char *out)
+{
+ snprintf(out, L2_SHA1_HEX_STRLEN + 1,
+ "%08" PRIx32 "%08" PRIx32 "%08" PRIx32 "%08" PRIx32 "%08" PRIx32,
+ dg->state[0], dg->state[1], dg->state[2], dg->state[3], dg->state[4]);
+}
+
+int l2_sha1__hex_to_uint32(const char *in, uint32_t *out);
+
+int l2_sha1_digest_from_hex(l2_sha1_digest_t *dg, const char *in)
+{
+ size_t len = strlen(in);
+ l2_sha1_digest_t dg1;
+
+ if (len != L2_SHA1_HEX_STRLEN) return -1;
+
+ for (unsigned i = 0; i < 5; ++i) {
+ if (l2_sha1__hex_to_uint32(in + (i * 8), dg1.state + i) < 0) return -1;
+ }
+
+ l2_sha1_digest_copy(dg, &dg1);
+ return 0;
+}
+
+int l2_sha1__hex_to_uint32(const char *in, uint32_t *out)
+{
+ uint32_t ret = 0;
+
+ for (unsigned i = 0; i < 8; ++i) {
+ switch (in[i]) {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ ret |= (in[i] - '0') << ((7 - i) << 2);
+ break;
+ case 'a':
+ case 'b':
+ case 'c':
+ case 'd':
+ case 'e':
+ case 'f':
+ ret |= (in[i] - 'a' + 0xa) << ((7 - i) << 2);
+ break;
+ case 'A':
+ case 'B':
+ case 'C':
+ case 'D':
+ case 'E':
+ case 'F':
+ ret |= (in[i] - 'A' + 0xA) << ((7 - i) << 2);
+ break;
+ default:
+ return -1;
+ }
+ }
+
+ *out = ret;
+
+ return 0;
+}
+
+#if 0
+int main(int argc, char **argv)
+{
+ if (argc < 2) return 1;
+
+ FILE *fp = fopen(argv[1], "rb");
+ if (!fp) {
+ fputs("oh no\n", stderr);
+ return 1;
+ }
+
+ char b[1024];
+ size_t nread = 0;
+ l2_sha1_state_t st;
+ l2_sha1_digest_t dg;
+
+ l2_sha1_init(&st);
+
+ while ((nread = fread(b, 1, 1024, fp))) {
+ printf("%zu\n", nread);
+ l2_sha1_update(&st, b, nread);
+ }
+
+ l2_sha1_finalize(&st, &dg);
+
+ char hex[L2_SHA1_HEX_STRLEN + 1];
+ l2_sha1_digest_to_hex(&dg, hex);
+ printf("%s\n", hex);
+
+ printf("%d\n", l2_sha1_digest_from_hex(&dg, "2fd4e1c67a2d28fced849ee1bb76e7391b93eb12"));
+ l2_sha1_digest_to_hex(&dg, hex);
+ printf("%s\n", hex);
+
+ return 0;
+}
+#endif
diff --git a/src/endian.c b/src/endian.c
new file mode 100644
index 0000000..0229c57
--- /dev/null
+++ b/src/endian.c
@@ -0,0 +1,28 @@
+#include "endian.h"
+
+#include <inttypes.h>
+
+uint64_t l2__bswap_64_int(uint64_t in)
+{
+ return (in << 56)
+ | ((in & UINT64_C(0x000000000000FF00)) << 40)
+ | ((in & UINT64_C(0x0000000000FF0000)) << 24)
+ | ((in & UINT64_C(0x00000000FF000000)) << 8)
+ | ((in & UINT64_C(0x000000FF00000000)) >> 8)
+ | ((in & UINT64_C(0x0000FF0000000000)) >> 24)
+ | ((in & UINT64_C(0x00FF000000000000)) >> 40)
+ | (in >> 56);
+}
+
+uint32_t l2__bswap_32_int(uint32_t in)
+{
+ return (in << 24)
+ | ((in & UINT32_C(0x0000FF00)) << 8)
+ | ((in & UINT32_C(0x00FF0000)) >> 8)
+ | (in >> 24);
+}
+
+uint16_t l2__bswap_16_int(uint16_t in)
+{
+ return (in >> 8) | (in << 8);
+}
diff --git a/src/endian.h b/src/endian.h
new file mode 100644
index 0000000..a486223
--- /dev/null
+++ b/src/endian.h
@@ -0,0 +1,43 @@
+#ifndef L2SU_ENDIAN_H_INCLUDED
+#define L2SU_ENDIAN_H_INCLUDED
+
+#include <stdint.h>
+#include "config.h"
+
+uint64_t l2__bswap_64_int(uint64_t in);
+uint32_t l2__bswap_32_int(uint32_t in);
+uint16_t l2__bswap_16_int(uint16_t in);
+
+#ifdef __GNUC__
+#define l2__bswap_64 __builtin_bswap64
+#define l2__bswap_32 __builtin_bswap32
+#define l2__bswap_16 __builtin_bswap16
+#else
+#define l2__bswap_64 l2__bswap_64_int
+#define l2__bswap_32 l2__bswap_32_int
+#define l2__bswap_16 l2__bswap_16_int
+#endif
+
+#if defined(L2SU_ENDIAN_LITTLE)
+
+#define l2_htobe64 l2__bswap_64
+#define l2_betoh64 l2__bswap_64
+#define l2_htobe32 l2__bswap_32
+#define l2_betoh32 l2__bswap_32
+#define l2_htobe16 l2__bswap_16
+#define l2_betoh16 l2__bswap_16
+
+#elif defined(L2SU_ENDIAN_BIG)
+
+#define l2_htobe64
+#define l2_betoh64
+#define l2_htobe32
+#define l2_betoh32
+#define l2_htobe16
+#define l2_betoh16
+
+#else
+#error "middle endian unsupported"
+#endif
+
+#endif /* include guard */
diff --git a/src/instance.c b/src/instance.c
index 8d62e1e..b8c70fd 100644
--- a/src/instance.c
+++ b/src/instance.c
@@ -95,7 +95,7 @@ int l2_instance_add_instance(const struct l2_instance *inst)
return INSTANCE_ERRNO;
}
- newinst->uuid = inst->uuid;
+ l2_uuid_copy(&newinst->uuid, &inst->uuid);
newinst->path = path;
newinst->name = name;
@@ -144,7 +144,7 @@ int l2_instance_rename_instance(struct l2_instance *inst, const char *newname)
struct l2_instance *l2_instance_find_by_uuid(const uuid_t *id)
{
for (struct l2_instance *inst = l2_state.instance_head; inst; inst = inst->next) {
- if (!memcmp(id, &inst->uuid, sizeof(uuid_t))) {
+ if (!l2_uuid_compare(id, &inst->uuid)) {
return inst;
}
}
diff --git a/src/meson.build b/src/meson.build
index 000bf6b..261148a 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -1,4 +1,4 @@
-launcher_srcs = files('l2su.c', 'command.c', 'cmd-instance.c', 'uuid/uuid.c', 'launcherutil.c', 'instance.c')
+launcher_srcs = files('l2su.c', 'command.c', 'cmd-instance.c', 'uuid/uuid.c', 'launcherutil.c', 'instance.c', 'cmd-version.c', 'digest/sha1.c')
configure_file(input : 'config.h.in', output : 'config.h', configuration : config_data)
config_include_dir = include_directories('.')
diff --git a/src/uuid/uuid.c b/src/uuid/uuid.c
index 0dfcfbd..e1498fc 100644
--- a/src/uuid/uuid.c
+++ b/src/uuid/uuid.c
@@ -74,7 +74,7 @@ bool l2_uuid_from_string_short(uuid_t *id, const char *str)
if (!l2__str_to_uint64(outid.halves + 1, str)) return false;
if (!l2__str_to_uint64(outid.halves, str + 16)) return false;
- memcpy(id, &outid, sizeof(uuid_t));
+ l2_uuid_copy(id, &outid);
return true;
}
@@ -83,6 +83,10 @@ int l2_uuid_compare(const uuid_t *c1, const uuid_t *c2)
return memcmp(c1, c2, sizeof(uuid_t));
}
+void l2_uuid_copy(uuid_t *restrict dest, const uuid_t *restrict in) {
+ memcpy(dest, in, sizeof(uuid_t));
+}
+
/* This function exists because there's not a portable way to do this.
* Don't suggest strtoull, because uint64_t may not be a ulonglong. */
bool l2__str_to_uint64(uint64_t *out, const char *str)
diff --git a/src/uuid/uuid.h b/src/uuid/uuid.h
index 7ddeeb4..eb1d41e 100644
--- a/src/uuid/uuid.h
+++ b/src/uuid/uuid.h
@@ -28,5 +28,6 @@ bool l2_uuid_from_string(uuid_t *id, const char *str);
bool l2_uuid_from_string_short(uuid_t *id, const char *str);
int l2_uuid_compare(const uuid_t *c1, const uuid_t *c2);
+void l2_uuid_copy(uuid_t *restrict dest, const uuid_t *restrict src);
#endif /* include guard */
diff --git a/src/version.h b/src/version.h
new file mode 100644
index 0000000..b3f640f
--- /dev/null
+++ b/src/version.h
@@ -0,0 +1,11 @@
+#ifndef L2SU_VERSION_H_INCLUDED
+#define L2SU_VERSION_H_INCLUDED
+
+struct l2_version_remote {
+
+};
+
+unsigned l2_version_load_remote(void);
+unsigned l2_version_load_local(void);
+
+#endif /* include guard */