Skip to content

Commit

Permalink
[common] Split common_dep into several dependencies
Browse files Browse the repository at this point in the history
Currently, all `common/` source files are supplied via a single
`common_dep`. However in some cases, we may only want to reuse the part
of the utility functions in `common/` without importing the other part
of Gramine-supplied mini-libc (which might lead to colliding issues).

This commit separates `common/` into several dependencies for more
flexible usage.

Signed-off-by: Kailun Qin <[email protected]>
  • Loading branch information
kailun-qin authored and Dmitrii Kuvaiskii committed Oct 31, 2022
1 parent bd97741 commit cda5d4d
Show file tree
Hide file tree
Showing 14 changed files with 240 additions and 179 deletions.
38 changes: 1 addition & 37 deletions common/include/api.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "cpu.h"
#include "list.h"
#include "log.h"
#include "string_utils.h"

/* TODO: remove this once Gramine does not use host headers. */
#ifndef ssize_t
Expand Down Expand Up @@ -219,23 +220,6 @@ int strcmp(const char* lhs, const char* rhs);
long strtol(const char* s, char** endptr, int base);
long long strtoll(const char* s, char** endptr, int base);

/*!
* \brief Convert a string to number.
*
* \param str Input string.
* \param base Digit base, between 2 and 36.
* \param[out] out_value On success, set to the parsed number.
* \param[out] out_end On success, set to the rest of string.
*
* \returns 0 on success, negative on failure.
*
* Parses a number from the beginning of a string. The number should be non-empty, consist of digits
* only (no `+`/`-` signs), and not overflow the `unsigned long` type. For base 16, the "0x" prefix
* is allowed but not required.
*/
int str_to_ulong(const char* str, unsigned int base, unsigned long* out_value,
const char** out_end);

int atoi(const char* nptr);
long int atol(const char* nptr);

Expand Down Expand Up @@ -283,8 +267,6 @@ void* _real_memmove(void* dest, const void* src, size_t count);
void* _real_memset(void* dest, int ch, size_t count);
int _real_memcmp(const void* lhs, const void* rhs, size_t count);

bool strstartswith(const char* str, const char* prefix);
bool strendswith(const char* str, const char* suffix);
char* strdup(const char* str);
char* alloc_substr(const char* start, size_t len);
char* alloc_concat(const char* a, size_t a_len, const char* b, size_t b_len);
Expand Down Expand Up @@ -392,24 +374,6 @@ uint16_t __ntohs(uint16_t x);

extern const char* const* sys_errlist_internal;

/* Gramine functions */

int get_norm_path(const char* path, char* buf, size_t* inout_size);
int get_base_name(const char* path, char* buf, size_t* inout_size);

bool is_dot_or_dotdot(const char* name);

/*!
* \brief Parse a size (number with optional "G"/"M"/"K" suffix) into an uint64_t.
*
* \param str A string containing a non-negative, decimal number. The string may end with
* "G"/"g" suffix denoting value in GBs, "M"/"m" for MBs, or "K"/"k" for KBs.
* \param[out] out_val Parsed size (in bytes).
*
* \returns 0 on success, negative if string cannot be parsed into a size (e.g., suffix is wrong).
*/
int parse_size_str(const char* str, uint64_t* out_val);

#define URI_PREFIX_SEPARATOR ":"

#define URI_TYPE_DIR "dir"
Expand Down
13 changes: 13 additions & 0 deletions common/include/path_utils.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/* SPDX-License-Identifier: LGPL-3.0-or-later */
/* Copyright (C) 2014 Stony Brook University */

#pragma once

#include <stdbool.h>
#include <stddef.h>

bool get_norm_path(const char* path, char* buf, size_t* inout_size);

bool get_base_name(const char* path, char* buf, size_t* inout_size);

bool is_dot_or_dotdot(const char* name);
41 changes: 41 additions & 0 deletions common/include/string_utils.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/* SPDX-License-Identifier: LGPL-3.0-or-later */
/* Copyright (C) 2014 Stony Brook University */

#pragma once

#include <stdbool.h>
#include <stdint.h>

/*!
* \brief Parse a size (number with optional "G"/"M"/"K" suffix) into an uint64_t.
*
* \param str A string containing a non-negative, decimal number. The string may end with
* "G"/"g" suffix denoting value in GBs, "M"/"m" for MBs, or "K"/"k" for KBs.
* \param[out] out_val Parsed size (in bytes).
*
* \returns 0 on success, negative if string cannot be parsed into a size (e.g., suffix is wrong).
*/
int parse_size_str(const char* str, uint64_t* out_val);

/*!
* \brief Convert a string to number.
*
* \param str Input string.
* \param base Digit base, between 2 and 36.
* \param[out] out_value On success, set to the parsed number.
* \param[out] out_end On success, set to the rest of string.
*
* \returns 0 on success, negative on failure.
*
* Parses a number from the beginning of a string. The number should be non-empty, consist of digits
* only (no `+`/`-` signs), and not overflow the `unsigned long` type. For base 16, the "0x" prefix
* is allowed but not required.
*/
int str_to_ulong(const char* str, unsigned int base, unsigned long* out_value,
const char** out_end);

bool strstartswith(const char* str, const char* prefix);

bool strendswith(const char* str, const char* suffix);

int parse_digit(char c, int base);
26 changes: 19 additions & 7 deletions common/src/meson.build
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
common_src = files(
common_src_utils = files(
'path_utils.c',
'string_utils.c',
)

common_src_internal = files(
'avl_tree.c',
'init.c',
'location.c',
'network/hton.c',
'network/inet_pton.c',
'path.c',
'printf.c',
'socket_utils.c',
'stack_protector.c',
Expand All @@ -19,27 +23,35 @@ common_src = files(
'string/strspn.c',
'string/strstr.c',
'string/toml_utils.c',
'string/utils.c',
'string/util.c',
)

# Arch-specific meson.build must define the following Meson variables:
# - `common_src_arch` - a list of arch-specific sources.
subdir('arch')
common_src += common_src_arch
# Current common arch-specific sources are for `common_src_internal` only.
common_src_internal += common_src_arch

if asan
common_src += files('asan.c')
common_src_internal += files('asan.c')
endif
if ubsan
common_src += files('ubsan.c')
common_src_internal += files('ubsan.c')
endif

common_utils_dep = declare_dependency(
sources: common_src_utils,

include_directories: common_inc,
)

common_dep = declare_dependency(
sources: common_src,
sources: common_src_internal,

include_directories: common_inc,

dependencies: [
common_utils_dep,
uthash_dep,
tomlc99_dep,
],
Expand Down
36 changes: 23 additions & 13 deletions common/src/path.c → common/src/path_utils.c
Original file line number Diff line number Diff line change
@@ -1,13 +1,23 @@
/* SPDX-License-Identifier: LGPL-3.0-or-later */
/* Copyright (C) 2014 Stony Brook University */
/* Copyright (C) 2019 Invisible Things Lab
* Borys Popławski <[email protected]>
*/

/*
* This file contains functions to read app config (manifest) file and create a tree to
* lookup / access config values.
*/

#include <stddef.h>

#ifdef USE_STDLIB
#include <assert.h>
#include <string.h>
#else
#include "api.h"
#include "pal_error.h"
#endif

#include "path_utils.h"

/*
* Finds next '/' in `path`.
Expand Down Expand Up @@ -53,14 +63,14 @@ static inline bool find_prev_slash_offset(const char* path, size_t* offset) {
* After returning it holds number of bytes actually written to it (including the ending '\0'). This
* number is never greater than the size of the input path.
*/
int get_norm_path(const char* path, char* buf, size_t* inout_size) {
bool get_norm_path(const char* path, char* buf, size_t* inout_size) {
assert(path && buf && inout_size);
size_t path_size = strlen(path) + 1;
__UNUSED(path_size); // used only for an assert at the end
(void)(path_size); // used only for an assert at the end

size_t size = *inout_size;
if (!size) {
return -PAL_ERROR_INVAL;
return false;
}
/* reserve 1 byte for ending '\0' */
size--;
Expand All @@ -73,7 +83,7 @@ int get_norm_path(const char* path, char* buf, size_t* inout_size) {
/* handle an absolute path */
if (is_absolute_path) {
if (size < 1) {
return -PAL_ERROR_TOOLONG;
return false;
}
*buf++ = '/';
size--;
Expand All @@ -93,7 +103,7 @@ int get_norm_path(const char* path, char* buf, size_t* inout_size) {
/* append undiscardable ".." since there is no previous token
* but only if the path is not absolute */
if (need_slash + 2u > size) {
return -PAL_ERROR_TOOLONG;
return false;
}
if (need_slash) {
*buf++ = '/';
Expand All @@ -113,7 +123,7 @@ int get_norm_path(const char* path, char* buf, size_t* inout_size) {
} else {
size_t len = (size_t)(end - path);
if (need_slash + len > size - offset) {
return -PAL_ERROR_TOOLONG;
return false;
}
if (need_slash) {
buf[offset++] = '/';
Expand All @@ -133,17 +143,17 @@ int get_norm_path(const char* path, char* buf, size_t* inout_size) {
*inout_size = ret_size + offset + 1;
assert(*inout_size <= path_size);

return 0;
return true;
}

/*
* Returns the part after the last '/' (so `path` should probably be normalized).
* Before calling this function *size should hold the size of buf.
* After returning it holds number of bytes actually written to it (including the trailing '\0').
*/
int get_base_name(const char* path, char* buf, size_t* inout_size) {
bool get_base_name(const char* path, char* buf, size_t* inout_size) {
if (!path || !buf || !inout_size) {
return -PAL_ERROR_INVAL;
return false;
}

const char* end;
Expand All @@ -153,15 +163,15 @@ int get_base_name(const char* path, char* buf, size_t* inout_size) {

size_t result = (size_t)(end - path);
if (result + 1 > *inout_size) {
return -PAL_ERROR_TOOLONG;
return false;
}

memcpy(buf, path, result);
buf[result] = '\0';

*inout_size = result + 1;

return 0;
return true;
}

bool is_dot_or_dotdot(const char* name) {
Expand Down
78 changes: 0 additions & 78 deletions common/src/string/atoi.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,23 +43,6 @@ static void begin_number(const char* str, int base, const char** out_s, int* out
*out_sign = sign;
}

static int parse_digit(char c, int base) {
int digit;

if (c >= '0' && c <= '9') {
digit = c - '0';
} else if (c >= 'a' && c <= 'z') {
digit = c - 'a' + 10;
} else if (c >= 'A' && c <= 'Z') {
digit = c - 'A' + 10;
} else {
return -1;
}
if (digit >= base)
return -1;
return digit;
}

long strtol(const char* str, char** out_end, int base) {
bool nothing_parsed = true;
const char* s;
Expand Down Expand Up @@ -91,35 +74,6 @@ long strtol(const char* str, char** out_end, int base) {
return value;
}

int str_to_ulong(const char* str, unsigned int base, unsigned long* out_value,
const char** out_end) {
if (base == 16 && str[0] == '0' && str[1] == 'x')
str += 2;

unsigned long value = 0;
const char* s = str;
while (*s != '\0') {
int digit = parse_digit(*s, base);
if (digit == -1)
break;

if (__builtin_mul_overflow(value, base, &value))
return -1;

if (__builtin_add_overflow(value, digit, &value))
return -1;

s++;
}

if (s == str)
return -1;

*out_value = value;
*out_end = s;
return 0;
}

#ifdef __LP64__
/* long int == long long int on targets with data model LP64 */
long long strtoll(const char* s, char** endptr, int base) {
Expand Down Expand Up @@ -155,35 +109,3 @@ long int atol(const char* str) {
}
return value;
}

int parse_size_str(const char* str, uint64_t* out_val) {
const char* endptr = NULL;
unsigned long size;
int ret = str_to_ulong(str, 10, &size, &endptr);
if (ret < 0)
return -1;

unsigned long unit = 1;
if (*endptr == 'G' || *endptr == 'g') {
unit = 1024 * 1024 * 1024;
endptr++;
} else if (*endptr == 'M' || *endptr == 'm') {
unit = 1024 * 1024;
endptr++;
} else if (*endptr == 'K' || *endptr == 'k') {
unit = 1024;
endptr++;
}

if (__builtin_mul_overflow(size, unit, &size))
return -1;

if (*endptr != '\0')
return -1; /* garbage found after the size string */

if (OVERFLOWS(__typeof__(*out_val), size))
return -1;

*out_val = size;
return 0;
}
Loading

0 comments on commit cda5d4d

Please sign in to comment.