Skip to content

Commit 36c9310

Browse files
TheSobkiewiczmat-hek
authored andcommitted
Add prim_file:get_cwd/0 (#68)
These changes are made under both the "Apache 2.0" and the "GNU Lesser General Public License 2.1 or later" license terms (dual license). SPDX-License-Identifier: Apache-2.0 OR LGPL-2.1-or-later Added nif implementation for getcwd. Signed-off-by: Mateusz Front <[email protected]>
1 parent df09ed8 commit 36c9310

File tree

7 files changed

+125
-0
lines changed

7 files changed

+125
-0
lines changed

libs/estdlib/src/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ set(ERLANG_MODULES
5555
maps
5656
math
5757
net
58+
prim_file
5859
logger
5960
logger_std_h
6061
proplists

libs/estdlib/src/prim_file.erl

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
%
2+
% This file is part of AtomVM.
3+
%
4+
% Copyright 2024 Tomasz Sobkiewicz <[email protected]>
5+
%
6+
% Licensed under the Apache License, Version 2.0 (the "License");
7+
% you may not use this file except in compliance with the License.
8+
% You may obtain a copy of the License at
9+
%
10+
% http://www.apache.org/licenses/LICENSE-2.0
11+
%
12+
% Unless required by applicable law or agreed to in writing, software
13+
% distributed under the License is distributed on an "AS IS" BASIS,
14+
% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
% See the License for the specific language governing permissions and
16+
% limitations under the License.
17+
%
18+
% SPDX-License-Identifier: Apache-2.0 OR LGPL-2.1-or-later
19+
%
20+
-module(prim_file).
21+
22+
-export([get_cwd/0]).
23+
24+
get_cwd() ->
25+
erlang:nif_error(undefined).

src/libAtomVM/nifs.c

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@
3131
#include <stdio.h>
3232
#include <string.h>
3333
#include <time.h>
34+
#include <unistd.h>
35+
#include <limits.h>
3436

3537
#include "atom_table.h"
3638
#include "avm_version.h"
@@ -99,6 +101,7 @@ static term nif_binary_part_3(Context *ctx, int argc, term argv[]);
99101
static term nif_binary_split(Context *ctx, int argc, term argv[]);
100102
static term nif_binary_replace(Context *ctx, int argc, term argv[]);
101103
static term nif_binary_match(Context *ctx, int argc, term argv[]);
104+
static term nif_prim_file_get_cwd_0(Context *ctx, int argc, term argv[]);
102105
static term nif_calendar_system_time_to_universal_time_2(Context *ctx, int argc, term argv[]);
103106
static term nif_erlang_delete_element_2(Context *ctx, int argc, term argv[]);
104107
static term nif_erlang_atom_to_binary(Context *ctx, int argc, term argv[]);
@@ -277,6 +280,12 @@ static const struct Nif binary_match_nif =
277280
.nif_ptr = nif_binary_match
278281
};
279282

283+
static const struct Nif prim_file_get_cwd_nif =
284+
{
285+
.base.type = NIFFunctionType,
286+
.nif_ptr = nif_prim_file_get_cwd_0
287+
};
288+
280289
static const struct Nif make_ref_nif =
281290
{
282291
.base.type = NIFFunctionType,
@@ -5842,6 +5851,53 @@ static term nif_erlang_lists_subtract(Context *ctx, int argc, term argv[])
58425851
return result;
58435852
}
58445853

5854+
5855+
static term nif_prim_file_get_cwd_0(Context *ctx, int argc, term argv[])
5856+
{
5857+
UNUSED(argc)
5858+
UNUSED(argv)
5859+
char cwd[PATH_MAX];
5860+
if (UNLIKELY(IS_NULL_PTR(cwd))) {
5861+
RAISE_ERROR(OUT_OF_MEMORY_ATOM);
5862+
}
5863+
5864+
if (UNLIKELY(memory_ensure_free(ctx, TUPLE_SIZE(2)) != MEMORY_GC_OK)) {
5865+
RAISE_ERROR(OUT_OF_MEMORY_ATOM);
5866+
}
5867+
term result_tuple = term_alloc_tuple(2, &ctx->heap);
5868+
5869+
if (UNLIKELY(IS_NULL_PTR(getcwd(cwd, PATH_MAX)))) {
5870+
term reason = UNDEFINED_ATOM;
5871+
switch (errno) {
5872+
case EACCES:
5873+
reason = globalcontext_make_atom(ctx->global, ATOM_STR("\x11", "permission_denied"));
5874+
break;
5875+
case EINVAL:
5876+
reason = globalcontext_make_atom(ctx->global, ATOM_STR("\xD", "negative_size"));
5877+
break;
5878+
case ERANGE:
5879+
reason = globalcontext_make_atom(ctx->global, ATOM_STR("\x10", "buffer_too_small"));
5880+
break;
5881+
default:
5882+
reason = globalcontext_make_atom(ctx->global, ATOM_STR("\xD", "unknown_error"));
5883+
break;
5884+
}
5885+
term_put_tuple_element(result_tuple, 0, ERROR_ATOM);
5886+
term_put_tuple_element(result_tuple, 1, reason);
5887+
return result_tuple;
5888+
}
5889+
5890+
size_t cwd_length = strlen(cwd);
5891+
if (UNLIKELY(memory_ensure_free_with_roots(ctx, term_binary_heap_size(cwd_length), 1, &result_tuple, MEMORY_CAN_SHRINK) != MEMORY_GC_OK)) {
5892+
RAISE_ERROR(OUT_OF_MEMORY_ATOM);
5893+
}
5894+
term result = term_from_literal_binary(cwd, cwd_length, &ctx->heap, ctx->global);
5895+
5896+
term_put_tuple_element(result_tuple, 0, OK_ATOM);
5897+
term_put_tuple_element(result_tuple, 1, result);
5898+
return result_tuple;
5899+
}
5900+
58455901
#ifdef WITH_ZLIB
58465902
static term nif_zlib_compress_1(Context *ctx, int argc, term argv[])
58475903
{

src/libAtomVM/nifs.gperf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,7 @@ ets:insert/2, &ets_insert_nif
145145
ets:lookup/2, &ets_lookup_nif
146146
ets:lookup_element/3, &ets_lookup_element_nif
147147
ets:delete/1, &ets_delete_nif
148+
prim_file:get_cwd/0, &prim_file_get_cwd_nif
148149
ets:delete/2, &ets_delete_nif
149150
ets:update_counter/3, &ets_update_counter_nif
150151
ets:update_counter/4, &ets_update_counter_nif

tests/erlang_tests/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,8 @@ compile_erlang(test_binary_match)
298298

299299
compile_erlang(test_zlib_compress)
300300

301+
compile_erlang(test_prim_file_getcwd)
302+
301303
compile_erlang(plusone)
302304
compile_erlang(plusone2)
303305
compile_erlang(minusone)
@@ -816,6 +818,8 @@ add_custom_target(erlang_test_modules DEPENDS
816818

817819
test_zlib_compress.beam
818820

821+
test_prim_file_getcwd.beam
822+
819823
plusone.beam
820824
plusone2.beam
821825
minusone.beam
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
%
2+
% This file is part of AtomVM.
3+
%
4+
% Copyright 2024 Tomasz Sobkiewicz <[email protected]>
5+
%
6+
% Licensed under the Apache License, Version 2.0 (the "License");
7+
% you may not use this file except in compliance with the License.
8+
% You may obtain a copy of the License at
9+
%
10+
% http://www.apache.org/licenses/LICENSE-2.0
11+
%
12+
% Unless required by applicable law or agreed to in writing, software
13+
% distributed under the License is distributed on an "AS IS" BASIS,
14+
% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
% See the License for the specific language governing permissions and
16+
% limitations under the License.
17+
%
18+
% SPDX-License-Identifier: Apache-2.0 OR LGPL-2.1-or-later
19+
%
20+
21+
-module(test_prim_file_getcwd).
22+
23+
-export([start/0]).
24+
25+
start() ->
26+
ok = test_getcwd(),
27+
0.
28+
29+
test_getcwd() ->
30+
{ok, Path} = prim_file:get_cwd(),
31+
true = is_valid_path(Path),
32+
ok.
33+
34+
is_valid_path(<<"/", _/binary>>) ->
35+
true;
36+
is_valid_path(_) ->
37+
false.

tests/test.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,7 @@ struct Test tests[] = {
329329
TEST_CASE(test_binary_match),
330330

331331
TEST_CASE(test_zlib_compress),
332+
TEST_CASE(test_prim_file_getcwd),
332333

333334
TEST_CASE_COND(plusone, 134217728, LONG_MAX != 9223372036854775807),
334335

0 commit comments

Comments
 (0)