Soletta™ Framework
Framework for making IoT devices

Full online documentation | C API Index
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
/src/samples/crypto/sha256sum.c
/*
* This file is part of the Soletta (TM) Project
*
* Copyright (C) 2015 Intel Corporation. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* This is a regular Soletta application, there are no linux-micro
* specific bits in it, just a timer, an optional gpio writer and some
* monitors for platform and service states. The purpose is to show
* that it can be considered a /init (PID1) binary if Soletta is
* compiled with linux-micro platform and if it runs as PID1, then
* /proc, /sys, /dev are all mounted as well as other bits of the
* system are configured.
*/
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <getopt.h>
#include "soletta.h"
#include "sol-buffer.h"
#include "sol-str-table.h"
#include "sol-util.h"
enum log_level {
};
struct entry {
char *filename;
};
static uint32_t pending;
static const char algorithm[] = "sha256";
static bool checking = false;
static bool checking_strict = false;
static bool checking_warn = false;
static const char stdin_filename[] = "-";
static void
store_digest(void *data, struct sol_message_digest *handle, struct sol_blob *digest)
{
struct entry *entry = data;
sol_str_slice_from_blob(digest), false);
if (r < 0)
fputs("ERROR: could not store digest as hexadecimal\n", stderr);
if (!pending)
}
static struct entry *
entry_new(const char *filename)
{
struct entry *entry;
.algorithm = algorithm,
.on_digest_ready = store_digest,
};
entry = calloc(1, sizeof(struct entry));
if (!entry)
return NULL;
cfg.data = entry;
entry->filename = strdup(filename);
entry->md = sol_message_digest_new(&cfg);
if (!entry->md) {
fprintf(stderr,
"ERROR: could not create message digest for algorithm %s\n",
free(entry);
return NULL;
}
return entry;
}
static void
entry_del(struct entry *entry)
{
free(entry->filename);
free(entry);
}
static struct sol_fd *stdin_watch;
static int
{
printf("TODO check stdin\n");
return 0;
}
static bool
on_stdin_hash(void *data, int fd, uint32_t flags)
{
struct entry *entry = data;
struct sol_blob *b = NULL;
bool is_last = false;
int err;
if (flags & SOL_FD_FLAGS_IN) {
char *mem = malloc(PATH_MAX);
ssize_t r;
if (!mem) {
fputs("ERROR: cannot allocate memory to read stdin.\n", stderr);
return true;
}
b = sol_blob_new(&SOL_BLOB_TYPE_DEFAULT, NULL, mem, PATH_MAX);
if (!b) {
fputs("ERROR: cannot allocate blob for stdin.\n", stderr);
free(mem);
return true;
}
while ((r = read(fd, mem, PATH_MAX)) < 0) {
if (errno == EINTR)
continue;
fprintf(stderr, "ERROR: cannot read from stdin: %s\n",
r = 0;
break;
}
b->size = r;
is_last = !r;
err = sol_message_digest_feed(entry->md, b, is_last);
if (err < 0) {
fprintf(stderr, "ERROR: cannot feed message digest: %s\n",
sol_quit_with_code(EXIT_FAILURE);
}
}
if (flags & (SOL_FD_FLAGS_ERR | SOL_FD_FLAGS_HUP | SOL_FD_FLAGS_NVAL) && !is_last) {
b = sol_blob_new(&SOL_BLOB_TYPE_DEFAULT, NULL, NULL, 0);
if (!b) {
fputs("ERROR: cannot allocate blob for stdin.\n", stderr);
return true;
}
is_last = true;
err = sol_message_digest_feed(entry->md, b, is_last);
if (err < 0) {
fprintf(stderr, "ERROR: cannot feed message digest: %s\n",
sol_quit_with_code(EXIT_FAILURE);
}
}
if (is_last) {
stdin_watch = NULL;
return false;
}
return true;
}
static int
fd_set_flag(int fd, int flag)
{
int flags;
flags = fcntl(fd, F_GETFL);
if (flags < 0)
return -errno;
flags |= flag;
if (fcntl(fd, F_SETFL, flags) < 0)
return -errno;
return 0;
}
static int
{
struct entry *entry;
int r;
if (stdin_watch)
return 0;
if (!entry)
return -ENOMEM;
r = fd_set_flag(STDIN_FILENO, O_NONBLOCK);
if (r < 0)
fputs("WARNING: cannot set stdin to non-blocking.\n", stderr);
stdin_watch = sol_fd_add(STDIN_FILENO,
SOL_FD_FLAGS_IN | SOL_FD_FLAGS_HUP | SOL_FD_FLAGS_ERR,
on_stdin_hash, entry);
if (!stdin_watch) {
entry_del(entry);
return -ENOMEM;
}
r = sol_ptr_vector_append(&entries, entry);
if (r < 0) {
sol_fd_del(stdin_watch);
stdin_watch = NULL;
entry_del(entry);
return -ENOMEM;
}
return 0;
}
static int
check_file(const char *filename)
{
printf("TODO check file\n");
return 0;
}
static int
hash_file(const char *filename)
{
struct entry *entry;
struct sol_file_reader *fr;
struct sol_blob *blob;
int r;
fr = sol_file_reader_open(filename);
if (!fr)
return -errno;
if (!blob)
return -ENOMEM;
entry = entry_new(filename);
if (!entry) {
return -ENOMEM;
}
r = sol_ptr_vector_append(&entries, entry);
if (r < 0) {
entry_del(entry);
return -ENOMEM;
}
r = sol_message_digest_feed(entry->md, blob, true);
return r;
}
static int
{
if (checking)
return check_stdin();
return hash_stdin();
}
static int
process_input(const char *filename)
{
if (!strcmp(filename, stdin_filename))
return process_stdin();
if (checking)
return check_file(filename);
return hash_file(filename);
}
static void
startup(void)
{
char **argv = sol_argv();
int argc = sol_argc();
while (1) {
static const struct option opts[] = {
{ "binary", no_argument, NULL, 'b' },
{ "text", no_argument, NULL, 't' },
{ "tag", no_argument, NULL, 'T' },
{ "check", no_argument, NULL, 'c' },
{ "quiet", no_argument, NULL, 'q' },
{ "status", no_argument, NULL, 's' },
{ "strict", no_argument, NULL, 'S' },
{ "warn", no_argument, NULL, 'w' },
{ "version", no_argument, NULL, 'v' },
{ "help", no_argument, NULL, 'h' },
{ 0, 0, 0, 0 }
};
int opt_idx = 0, c;
c = getopt_long(argc, argv, "btcw", opts, &opt_idx);
if (c == -1)
break;
switch (c) {
case 'b':
fputs("WARNING: ignored unsupported option -b/--binary.\n", stderr);
break;
case 't':
fputs("WARNING: ignored unsupported option -t/--text.\n", stderr);
break;
case 'T':
fputs("ERROR: unsupported option --tag.\n", stderr);
sol_quit_with_code(EXIT_FAILURE);
return;
case 'c':
checking = true;
break;
case 'q':
break;
case 's':
break;
case 'S':
break;
case 'w':
checking_warn = true;
break;
case 'h':
printf(
"Usage:\n"
"\t%s [OPTION]... [FILE]...\n"
"\n"
"With no FILE, or when FILE is -, read standard input.\n"
"\n"
"\t-b, --binary read in binary mode (ignored).\n"
"\t-c, --check read SHA-256 sums from the FILEs and check them\n"
"\t --tag create a BSD-style checksum (not supported).\n"
"\t-t, --text read in text mode (ignored).\n"
"\n"
"The following four options are useful only when verifying checksums:\n"
"\t --quiet don't print OK for each successfully verified file\n"
"\t --status don't output anything, status code shows success\n"
"\t --strict exit non-zero for improperly formatted checksum lines\n"
"\t-w, --warn warn about improperly formatted checksum lines\n"
"\t --version output version information and exit\n"
"\t --help display this help and exit\n"
"\n",
argv[0]);
return;
case 'v':
printf("%s soletta %s\n", argv[0], VERSION);
return;
default:
sol_quit_with_code(EXIT_FAILURE);
return;
}
}
if (optind >= argc)
else {
int i;
for (i = optind; i < argc; i++) {
process_input(argv[i]);
}
}
if (!pending)
sol_quit_with_code(EXIT_FAILURE);
}
static void
shutdown(void)
{
struct entry *entry;
uint16_t i;
SOL_PTR_VECTOR_FOREACH_IDX (&entries, entry, i) {
if (!checking) {
printf("%s %s\n", (char *)entry->digest.data, entry->filename);
} else {
printf("TODO check %s %s\n", (char *)entry->digest.data, entry->filename);
}
entry_del(entry);
}
}