initial import

This commit is contained in:
gmega 2026-01-30 10:30:16 -03:00
commit 51958d8310
No known key found for this signature in database
GPG Key ID: 6290D34EAD824B18
7 changed files with 285 additions and 0 deletions

58
.clang-format Normal file
View File

@ -0,0 +1,58 @@
# Generated from CLion C/C++ Code Style settings
---
Language: Cpp
BasedOnStyle: LLVM
AccessModifierOffset: -4
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
AlignOperands: true
AlignTrailingComments: false
AlwaysBreakTemplateDeclarations: Yes
BraceWrapping:
AfterCaseLabel: false
AfterClass: false
AfterControlStatement: false
AfterEnum: false
AfterFunction: false
AfterNamespace: false
AfterStruct: false
AfterUnion: false
AfterExternBlock: false
BeforeCatch: false
BeforeElse: false
BeforeLambdaBody: false
BeforeWhile: false
SplitEmptyFunction: true
SplitEmptyRecord: true
SplitEmptyNamespace: true
BreakBeforeBraces: Custom
BreakConstructorInitializers: AfterColon
BreakConstructorInitializersBeforeComma: false
ColumnLimit: 120
ConstructorInitializerAllOnOneLineOrOnePerLine: false
ContinuationIndentWidth: 8
IncludeCategories:
- Regex: '^<.*'
Priority: 1
- Regex: '^".*'
Priority: 2
- Regex: '.*'
Priority: 3
IncludeIsMainRegex: '([-_](test|unittest))?$'
IndentCaseLabels: true
IndentWidth: 4
InsertNewlineAtEOF: true
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 2
NamespaceIndentation: All
SpaceAfterCStyleCast: true
SpaceAfterTemplateKeyword: false
SpaceBeforeRangeBasedForLoopColon: false
SpaceInEmptyParentheses: false
SpacesInAngles: false
SpacesInConditionalStatement: false
SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
TabWidth: 4
...

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
cmake-*
.idea

28
CLAUDE.md Normal file
View File

@ -0,0 +1,28 @@
# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Project Overview
storageconsole is a C11 interactive CLI application for managing a distributed storage node. It wraps an external `libstorage` library (Nim-based) through a command dispatch console.
## Build
Requires the `LOGOS_STORAGE_NIM_ROOT` environment variable pointing to the external storage library root (contains `library/libstorage.h` and platform-specific shared library).
```sh
cmake -B build -S .
cmake --build build
```
The build output is an executable named `storageconsole`.
## Architecture
- **main.c** — Entry point and interactive console. Implements a command dispatch loop using a static table of `command` structs mapping names to function pointers. The `console` struct holds an opaque `void *ctx` pointer to the storage node instance.
- **easylibstorage.h** — High-level wrapper API declarations over `libstorage`. Defines `STORAGE_NODE` (opaque pointer), `node_config`, `progress_callback`, and functions for node lifecycle (`e_storage_new/start/stop/destroy`) and data operations (`e_storage_upload/download`). These are declared but not all wired into console commands yet.
- **External dependency**: `libstorage` (platform-specific `.so`/`.dylib`/`.dll`) found via `LOGOS_STORAGE_NIM_ROOT`. Currently only `sync_start()` from `libstorage.h` is called directly.
## Code Style
Formatting is enforced via `.clang-format` (LLVM-based, 4-space indent, 120-char column limit).

30
CMakeLists.txt Normal file
View File

@ -0,0 +1,30 @@
cmake_minimum_required(VERSION 3.14)
project(storageconsole C)
set(CMAKE_C_STANDARD 11)
add_executable(storageconsole main.c
easylibstorage.h
)
if(NOT DEFINED LOGOS_STORAGE_NIM_ROOT)
message(FATAL_ERROR "Need to set LOGOS_STORAGE_NIM_ROOT")
endif()
target_include_directories(storageconsole PRIVATE "${LOGOS_STORAGE_NIM_ROOT}/library")
if(APPLE)
set(LIBSTORAGE_NAMES libstorage.dylib)
elseif(WIN32)
set(LIBSTORAGE_NAMES libstorage.dll)
else()
set(LIBSTORAGE_NAMES libstorage.so)
endif()
find_library(LIBSTORAGE_PATH NAMES ${LIBSTORAGE_NAMES} PATHS ${LOGOS_STORAGE_NIM_ROOT}/build NO_DEFAULT_PATH)
if(LIBSTORAGE_PATH)
target_link_libraries(storageconsole PRIVATE ${LIBSTORAGE_PATH})
else()
message(WARNING "libstorage not found. Build or provide it before linking.")
endif()

32
PROMPT.md Normal file
View File

@ -0,0 +1,32 @@
I want you to implement the API described in easylibstorage.h in a file name easylibstorage.c. This is a simplified
wrapper on top of libstorage. You can find the headers for libstorage here:
- /home/giuliano/Work/Status/logos-storage-nim/library/libstorage.h
You can find examples of how to use libstorage here:
- /home/giuliano/Work/Status/logos-storage-nim/examples/c/examples.c
I want you to implement one function at a time. You MUST follow a Test Driven Development approach where you:
1. write a test for a function; (red)
2. write the function;
3. run it until your test is green; (green)
4. stop, think of ways to refactor and simplify the code, and do it; (refactor)
5. once you're done refactoring and the tests are green, move to the next function. This step is VERY IMPORTANT. You MUST look for ways to simplify,
deduplicate, and coalesce code here, WITHOUT OVERCOMPLICATING. SIMPLICITY
IS KEY AND YOUR GUIDING PRINCIPLE.
Feel free to use an idiomatic C way to write your unit tests, but DO NOT implement the next function before doing
the full 1-5 cycle first. You need to follow the red-greed-refactor tenets of TDD.
Finally, I want you to wire all of the above in the console application under main.c. This console application must
support the following commands:
- help (prints help)
- start [API PORT] [DISCOVERY PORT] [BOOTSTRAP NODE] - creates and starts the node, all parameters are mandatory.
- stop - stops and destroys the node
- upload [LOCAL PATH] - uploads a local file to the node. Shows simple progress, prints the CID on screen when done.
- download [CID] [LOCAL PATH] - downloads a remote CID to a local path. Shows simple progress, prints CID on screen when done.
If needed, the code for libstorage can also be found under /home/giuliano/Work/Status/logos-storage-nim/library.

32
easylibstorage.h Normal file
View File

@ -0,0 +1,32 @@
#ifndef STORAGECONSOLE_EASYLIBSTORAGE_H
#define STORAGECONSOLE_EASYLIBSTORAGE_H
#include <stdio.h>
#define STORAGE_NODE void *
#define CID char *
enum log_level {
WARN,
INFO,
DEBUG,
};
typedef struct {
int api_port;
int disc_port;
char *data_dir;
char *log_level;
char *bootstrap_node;
} node_config;
typedef void (*progress_callback)(int total, int complete, int status);
STORAGE_NODE e_storage_new(node_config config);
int e_storage_start(STORAGE_NODE node);
int e_storage_stop(STORAGE_NODE node);
int e_storage_destroy(STORAGE_NODE node);
CID e_storage_upload(STORAGE_NODE node, FILE *input, progress_callback cb);
STORAGE_NODE e_storage_download(STORAGE_NODE node, CID cid, FILE *output, progress_callback cb);
#endif // STORAGECONSOLE_EASYLIBSTORAGE_H

103
main.c Normal file
View File

@ -0,0 +1,103 @@
#include "easylibstorage.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
void *ctx;
} console;
typedef void (*fn)(void *, console *);
struct command {
const char *name;
const char *desc;
fn command;
};
int n_commands();
static const struct command commands[];
void cmd_help(void *_, console *c) {
printf("Commands:\n");
for (int i = 0; i < n_commands(); i++) {
printf(" [%s]: %s\n", commands[i].name, commands[i].desc);
}
}
void cmd_quit(void *_, console *c) {
}
void progress_print(int total, int complete, int status) {
if (total > 0) {
printf("\r %d / %d bytes", complete, total);
} else {
printf("\r %d bytes", complete);
}
fflush(stdout);
}
void cmd_start(void *args, console *c) {
}
void cmd_stop(void *args, console *c) {
}
void cmd_upload(void *args, console *c) {
}
void cmd_download(void *args, console *c) {
}
static const struct command commands[] = {
{"help", "prints this help message", cmd_help},
{"quit", "quits this program", cmd_quit},
{"start", "[API PORT] [DISC PORT] [BOOTSTRAP NODE] creates and starts a node", cmd_start},
{"stop", "stops and destroys the node", cmd_stop},
{"upload", "[PATH] uploads a file to the node", cmd_upload},
{"download", "[CID] [PATH] downloads content to a file", cmd_download},
};
int n_commands() { return sizeof(commands) / sizeof(commands[0]); }
int main(void) {
char buf[4096];
console c;
int i;
c.ctx = NULL;
while (1) {
printf("> ");
fflush(stdout);
if (!fgets(buf, sizeof(buf), stdin)) {
break;
}
buf[strcspn(buf, "\n")] = 0;
char *cmd = strtok(buf, " ");
if (cmd == NULL) {
// user has input an empty string
continue;
}
for (i = 0; i < n_commands(); i++) {
if (strcmp(cmd, commands[i].name) == 0) {
char *arg = strtok(NULL, " ");
commands[i].command(arg, &c);
break;
}
}
if (i == n_commands()) {
printf("Invalid command %s\n", buf);
}
}
}