-
Notifications
You must be signed in to change notification settings - Fork 7.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
newlib: implement posix_memalign, sysconf, realpath
- Loading branch information
Showing
8 changed files
with
272 additions
and
15 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
/* | ||
* SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
#include <unistd.h> | ||
#include <errno.h> | ||
#include <string.h> | ||
#include <stdlib.h> | ||
#include <assert.h> | ||
#include <sys/param.h> | ||
|
||
/* realpath logic: | ||
* 1. prepend CWD (/) | ||
* 2. iterate over components (search until next '/' or end of line) | ||
* - empty, skip the component | ||
* - if it is '.', skip the component | ||
* - if it is '..' | ||
* - and out_level == 0, ??? ('/..') | ||
* - otherwise, reverse-search for '/', set out_pos to that - 1, decrement out_level | ||
* - otherwise, add the component to output, increment out_level | ||
*/ | ||
|
||
char * realpath(const char *file_name, char *resolved_name) | ||
{ | ||
char * out_path = resolved_name; | ||
if (out_path == NULL) { | ||
/* allowed as an extension, allocate memory for the output path */ | ||
out_path = malloc(PATH_MAX); | ||
if (out_path == NULL) { | ||
errno = ENOMEM; | ||
return NULL; | ||
} | ||
} | ||
|
||
/* canonical path starts with / */ | ||
strlcpy(out_path, "/", PATH_MAX); | ||
|
||
/* pointers moving over the input and output path buffers */ | ||
const char* in_ptr = file_name; | ||
char* out_ptr = out_path + 1; | ||
/* number of path components in the output buffer */ | ||
size_t out_depth = 0; | ||
|
||
|
||
while (*in_ptr) { | ||
/* "path component" is the part between two '/' path separators. | ||
* locate the next path component in the input path: | ||
*/ | ||
const char* end_of_path_component = strchrnul(in_ptr, '/'); | ||
size_t path_component_len = end_of_path_component - in_ptr; | ||
|
||
if (path_component_len == 0 || | ||
(path_component_len == 1 && in_ptr[0] == '.')) { | ||
/* empty path component or '.' - nothing to do */ | ||
} else if (path_component_len == 2 && in_ptr[0] == '.' && in_ptr[1] == '.') { | ||
/* '..' - remove one path component from the output */ | ||
if (out_depth == 0) { | ||
/* nothing to remove */ | ||
} else if (out_depth == 1) { | ||
/* there is only one path component in output; | ||
* remove it, but keep the leading separator | ||
*/ | ||
out_ptr = out_path + 1; | ||
*out_ptr = '\0'; | ||
out_depth = 0; | ||
} else { | ||
/* remove last path component and the separator preceding it */ | ||
char * prev_sep = strrchr(out_path, '/'); | ||
assert(prev_sep > out_path); /* this shouldn't be the leading separator */ | ||
out_ptr = prev_sep; | ||
*out_ptr = '\0'; | ||
--out_depth; | ||
} | ||
} else { | ||
/* copy path component to output; +1 is for the separator */ | ||
if (out_ptr - out_path + 1 + path_component_len > PATH_MAX - 1) { | ||
/* output buffer insufficient */ | ||
errno = E2BIG; | ||
goto fail; | ||
} else { | ||
/* add separator if necessary */ | ||
if (out_depth > 0) { | ||
*out_ptr = '/'; | ||
++out_ptr; | ||
} | ||
memcpy(out_ptr, in_ptr, path_component_len); | ||
out_ptr += path_component_len; | ||
*out_ptr = '\0'; | ||
++out_depth; | ||
} | ||
} | ||
/* move input pointer to separator right after this path component */ | ||
in_ptr += path_component_len; | ||
if (*in_ptr != '\0') { | ||
/* move past it unless already at the end of the input string */ | ||
++in_ptr; | ||
} | ||
} | ||
return out_path; | ||
|
||
fail: | ||
if (resolved_name == NULL) { | ||
/* out_path was allocated, free it */ | ||
free(out_path); | ||
} | ||
return NULL; | ||
} | ||
|
||
char * getcwd(char *buf, size_t size) | ||
{ | ||
if (buf == NULL) { | ||
return strdup("/"); | ||
} | ||
strlcpy(buf, "/", size); | ||
return buf; | ||
} | ||
|
||
int chdir(const char *path) | ||
{ | ||
(void) path; | ||
errno = ENOSYS; | ||
return -1; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
/* | ||
* SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
#include <unistd.h> | ||
#include <errno.h> | ||
#include "sdkconfig.h" | ||
#include "freertos/FreeRTOS.h" | ||
|
||
#define CPU_NUM portNUM_PROCESSORS | ||
|
||
long sysconf(int arg) | ||
{ | ||
switch (arg) { | ||
case _SC_NPROCESSORS_CONF: | ||
case _SC_NPROCESSORS_ONLN: | ||
return CPU_NUM; | ||
default: | ||
errno = EINVAL; | ||
return -1; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
idf_component_register(SRCS | ||
"test_newlib_main.c" | ||
"test_stdatomic.c" | ||
"test_misc.c" | ||
REQUIRES test_utils | ||
PRIV_REQUIRES unity) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
/* | ||
* SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
#include <assert.h> | ||
#include <stdint.h> | ||
#include <stddef.h> | ||
#include <stdbool.h> | ||
#include <stdio.h> | ||
#include <unistd.h> | ||
#include <errno.h> | ||
#include <sys/param.h> | ||
#include <stdlib.h> | ||
#include "unity.h" | ||
#include "unity_fixture.h" | ||
|
||
// unity_fixture_malloc_overrides.h defines 'free' as 'unity_free', | ||
// which can only handle pointers allocated with 'unity_malloc'. | ||
// This test allocates memory via 'posix_memalign' so calling 'free' | ||
// for these pointers causes the heap guards check to fail. | ||
#undef free | ||
|
||
TEST_GROUP(misc); | ||
|
||
TEST_SETUP(misc) | ||
{ | ||
} | ||
|
||
TEST_TEAR_DOWN(misc) | ||
{ | ||
} | ||
|
||
TEST(misc, posix_memalign) | ||
{ | ||
void* outptr; | ||
int ret; | ||
|
||
ret = posix_memalign(&outptr, 4, 0); | ||
TEST_ASSERT_EQUAL_PTR(NULL, outptr); | ||
TEST_ASSERT_EQUAL_INT(ret, 0); | ||
|
||
void* magic = (void*) 0xEFEFEFEF; | ||
outptr = magic; | ||
ret = posix_memalign(&outptr, 0x10000000, 64); // too big alignment - should fail on all targets | ||
TEST_ASSERT_EQUAL_INT(ret, ENOMEM); | ||
TEST_ASSERT_EQUAL_PTR(magic, outptr); // was not modified | ||
|
||
outptr = magic; | ||
ret = posix_memalign(&outptr, 16, 0x10000000); // too big size - should fail on all targets | ||
TEST_ASSERT_EQUAL_INT(ret, ENOMEM); | ||
TEST_ASSERT_EQUAL_PTR(magic, outptr); // was not modified | ||
|
||
outptr = magic; | ||
ret = posix_memalign(&outptr, 16, 64); | ||
TEST_ASSERT_TRUE(outptr != magic); | ||
TEST_ASSERT_NOT_NULL(outptr); | ||
TEST_ASSERT_EQUAL_INT(ret, 0); | ||
free(outptr); | ||
} | ||
|
||
TEST(misc, sysconf) | ||
{ | ||
TEST_ASSERT_NOT_EQUAL(-1, sysconf(_SC_NPROCESSORS_ONLN)); | ||
} | ||
|
||
TEST(misc, realpath) | ||
{ | ||
char out[PATH_MAX]; | ||
|
||
TEST_ASSERT_EQUAL_STRING("/", realpath("/", out)); | ||
TEST_ASSERT_EQUAL_STRING("/", realpath("//", out)); | ||
TEST_ASSERT_EQUAL_STRING("/", realpath(".", out)); | ||
TEST_ASSERT_EQUAL_STRING("/", realpath("./", out)); | ||
TEST_ASSERT_EQUAL_STRING("/", realpath("/.", out)); | ||
TEST_ASSERT_EQUAL_STRING("/", realpath("./.", out)); | ||
TEST_ASSERT_EQUAL_STRING("/", realpath("..", out)); | ||
TEST_ASSERT_EQUAL_STRING("/", realpath("../..", out)); | ||
TEST_ASSERT_EQUAL_STRING("/a", realpath("/a/", out)); | ||
TEST_ASSERT_EQUAL_STRING("/", realpath("/a/..", out)); | ||
TEST_ASSERT_EQUAL_STRING("/", realpath("/a/../..", out)); | ||
TEST_ASSERT_EQUAL_STRING("/c", realpath("/a/../b/../c", out)); | ||
TEST_ASSERT_EQUAL_STRING("/abc/def", realpath("/abc/./def/ghi/..", out)); | ||
char* out_new = realpath("/abc/./def/ghi/..", NULL); | ||
TEST_ASSERT_NOT_NULL(out_new); | ||
TEST_ASSERT_EQUAL_STRING("/abc/def", out_new); | ||
free(out_new); | ||
} | ||
|
||
TEST_GROUP_RUNNER(misc) | ||
{ | ||
RUN_TEST_CASE(misc, posix_memalign) | ||
RUN_TEST_CASE(misc, sysconf) | ||
RUN_TEST_CASE(misc, realpath) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters