aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator/beam
diff options
context:
space:
mode:
Diffstat (limited to 'erts/emulator/beam')
-rw-r--r--erts/emulator/beam/beam_load.c8
-rw-r--r--erts/emulator/beam/beam_ranges.c6
-rw-r--r--erts/emulator/beam/bif.c29
-rw-r--r--erts/emulator/beam/bif.tab8
-rw-r--r--erts/emulator/beam/binary.c63
-rw-r--r--erts/emulator/beam/break.c16
-rw-r--r--erts/emulator/beam/dist.c2
-rw-r--r--erts/emulator/beam/erl_alloc.types6
-rw-r--r--erts/emulator/beam/erl_bif_binary.c23
-rw-r--r--erts/emulator/beam/erl_bif_info.c15
-rw-r--r--erts/emulator/beam/erl_bif_os.c199
-rw-r--r--erts/emulator/beam/erl_bif_port.c193
-rw-r--r--erts/emulator/beam/erl_init.c20
-rw-r--r--erts/emulator/beam/erl_io_queue.c19
-rw-r--r--erts/emulator/beam/erl_nif.c16
-rw-r--r--erts/emulator/beam/erl_unicode.c182
-rw-r--r--erts/emulator/beam/erl_unicode.h5
-rw-r--r--erts/emulator/beam/external.c62
-rw-r--r--erts/emulator/beam/global.h4
-rw-r--r--erts/emulator/beam/io.c62
-rw-r--r--erts/emulator/beam/sys.h37
-rw-r--r--erts/emulator/beam/utils.c19
22 files changed, 397 insertions, 597 deletions
diff --git a/erts/emulator/beam/beam_load.c b/erts/emulator/beam/beam_load.c
index e43f7fda2c..beaef0951e 100644
--- a/erts/emulator/beam/beam_load.c
+++ b/erts/emulator/beam/beam_load.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1996-2017. All Rights Reserved.
+ * Copyright Ericsson AB 1996-2018. 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.
@@ -40,6 +40,7 @@
#include "erl_zlib.h"
#include "erl_map.h"
#include "erl_process_dict.h"
+#include "erl_unicode.h"
#ifdef HIPE
#include "hipe_bif0.h"
@@ -1806,7 +1807,7 @@ read_line_table(LoaderState* stp)
GetInt(stp, 2, n);
GetString(stp, fname, n);
- stp->fname[i] = erts_atom_put(fname, n, ERTS_ATOM_ENC_LATIN1, 1);
+ stp->fname[i] = erts_atom_put(fname, n, ERTS_ATOM_ENC_UTF8, 1);
}
}
@@ -6254,8 +6255,7 @@ erts_build_mfa_item(FunctionInfo* fi, Eterm* hp, Eterm args, Eterm* mfa_p)
file_term = buf_to_intlist(&hp, ".erl", 4, NIL);
file_term = buf_to_intlist(&hp, (char*)ap->name, ap->len, file_term);
} else {
- Atom* ap = atom_tab(atom_val((fi->fname_ptr)[file-1]));
- file_term = buf_to_intlist(&hp, (char*)ap->name, ap->len, NIL);
+ file_term = erts_atom_to_string(&hp, (fi->fname_ptr)[file-1]);
}
tuple = TUPLE2(hp, am_line, make_small(line));
diff --git a/erts/emulator/beam/beam_ranges.c b/erts/emulator/beam/beam_ranges.c
index 01bda7f3c1..f0c9496341 100644
--- a/erts/emulator/beam/beam_ranges.c
+++ b/erts/emulator/beam/beam_ranges.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2012-2016. All Rights Reserved.
+ * Copyright Ericsson AB 2012-2018. 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.
@@ -26,6 +26,7 @@
#include "erl_vm.h"
#include "global.h"
#include "beam_load.h"
+#include "erl_unicode.h"
typedef struct {
BeamInstr* start; /* Pointer to start of module. */
@@ -341,8 +342,7 @@ lookup_loc(FunctionInfo* fi, const BeamInstr* pc,
Atom* mod_atom = atom_tab(atom_val(fi->mfa->module));
fi->needed += 2*(mod_atom->len+4);
} else {
- Atom* ap = atom_tab(atom_val((fi->fname_ptr)[file-1]));
- fi->needed += 2*ap->len;
+ fi->needed += 2*erts_atom_to_string_length((fi->fname_ptr)[file-1]);
}
return;
} else {
diff --git a/erts/emulator/beam/bif.c b/erts/emulator/beam/bif.c
index 0e5f7bb22b..f086c434ea 100644
--- a/erts/emulator/beam/bif.c
+++ b/erts/emulator/beam/bif.c
@@ -2244,20 +2244,15 @@ do_send(Process *p, Eterm to, Eterm msg, Eterm *refp, ErtsSendContext *ctx)
send_message: {
ErtsProcLocks rp_locks = 0;
- Sint res;
if (p == rp)
rp_locks |= ERTS_PROC_LOCK_MAIN;
/* send to local process */
- res = erts_send_message(p, rp, &rp_locks, msg, 0);
- if (erts_use_sender_punish)
- res *= 4;
- else
- res = 0;
+ erts_send_message(p, rp, &rp_locks, msg, 0);
erts_proc_unlock(rp,
p == rp
? (rp_locks & ~ERTS_PROC_LOCK_MAIN)
: rp_locks);
- return res;
+ return 0;
}
}
@@ -2312,8 +2307,8 @@ BIF_RETTYPE send_3(BIF_ALIST_3)
result = do_send(p, to, msg, &ref, ctx);
ERTS_MSACC_POP_STATE_M_X();
- if (result > 0) {
- ERTS_VBUMP_REDS(p, result);
+ if (result >= 0) {
+ ERTS_VBUMP_REDS(p, 4);
if (ERTS_IS_PROC_OUT_OF_REDS(p))
goto yield_return;
ERTS_BIF_PREP_RET(retval, am_ok);
@@ -2321,12 +2316,6 @@ BIF_RETTYPE send_3(BIF_ALIST_3)
}
switch (result) {
- case 0:
- /* May need to yield even though we do not bump reds here... */
- if (ERTS_IS_PROC_OUT_OF_REDS(p))
- goto yield_return;
- ERTS_BIF_PREP_RET(retval, am_ok);
- break;
case SEND_NOCONNECT:
if (ctx->connect) {
ERTS_BIF_PREP_RET(retval, am_ok);
@@ -2443,8 +2432,8 @@ Eterm erl_send(Process *p, Eterm to, Eterm msg)
ERTS_MSACC_POP_STATE_M_X();
- if (result > 0) {
- ERTS_VBUMP_REDS(p, result);
+ if (result >= 0) {
+ ERTS_VBUMP_REDS(p, 4);
if (ERTS_IS_PROC_OUT_OF_REDS(p))
goto yield_return;
ERTS_BIF_PREP_RET(retval, msg);
@@ -2452,12 +2441,6 @@ Eterm erl_send(Process *p, Eterm to, Eterm msg)
}
switch (result) {
- case 0:
- /* May need to yield even though we do not bump reds here... */
- if (ERTS_IS_PROC_OUT_OF_REDS(p))
- goto yield_return;
- ERTS_BIF_PREP_RET(retval, msg);
- break;
case SEND_NOCONNECT:
ERTS_BIF_PREP_RET(retval, msg);
break;
diff --git a/erts/emulator/beam/bif.tab b/erts/emulator/beam/bif.tab
index 33f6eef652..c0d5e8ce74 100644
--- a/erts/emulator/beam/bif.tab
+++ b/erts/emulator/beam/bif.tab
@@ -376,9 +376,10 @@ bif ets:match_spec_run_r/3
# Bifs in os module.
#
-bif os:putenv/2
-bif os:getenv/0
-bif os:getenv/1
+bif os:get_env_var/1
+bif os:set_env_var/2
+bif os:unset_env_var/1
+bif os:list_env_vars/0
bif os:getpid/0
bif os:timestamp/0
bif os:system_time/0
@@ -619,7 +620,6 @@ bif erlang:float_to_binary/2
bif erlang:binary_to_float/1
bif io:printable_range/0
-bif os:unsetenv/1
#
# New in 17.0
diff --git a/erts/emulator/beam/binary.c b/erts/emulator/beam/binary.c
index ca3e48e205..d4db1a4188 100644
--- a/erts/emulator/beam/binary.c
+++ b/erts/emulator/beam/binary.c
@@ -60,14 +60,36 @@ erts_init_binary(void)
}
+static ERTS_INLINE
+Eterm build_proc_bin(ErlOffHeap* ohp, Eterm* hp, Binary* bptr)
+{
+ ProcBin* pb = (ProcBin *) hp;
+ pb->thing_word = HEADER_PROC_BIN;
+ pb->size = bptr->orig_size;
+ pb->next = ohp->first;
+ ohp->first = (struct erl_off_heap_header*)pb;
+ pb->val = bptr;
+ pb->bytes = (byte*) bptr->orig_bytes;
+ pb->flags = 0;
+ OH_OVERHEAD(ohp, pb->size / sizeof(Eterm));
+
+ return make_binary(pb);
+}
+
+/** @brief Initiate a ProcBin for a full Binary.
+ * @param hp must point to PROC_BIN_SIZE available heap words.
+ */
+Eterm erts_build_proc_bin(ErlOffHeap* ohp, Eterm* hp, Binary* bptr)
+{
+ return build_proc_bin(ohp, hp, bptr);
+}
+
/*
* Create a brand new binary from scratch.
*/
-
Eterm
new_binary(Process *p, byte *buf, Uint len)
{
- ProcBin* pb;
Binary* bptr;
if (len <= ERL_ONHEAP_BIN_LIMIT) {
@@ -88,23 +110,7 @@ new_binary(Process *p, byte *buf, Uint len)
sys_memcpy(bptr->orig_bytes, buf, len);
}
- /*
- * Now allocate the ProcBin on the heap.
- */
- pb = (ProcBin *) HAlloc(p, PROC_BIN_SIZE);
- pb->thing_word = HEADER_PROC_BIN;
- pb->size = len;
- pb->next = MSO(p).first;
- MSO(p).first = (struct erl_off_heap_header*)pb;
- pb->val = bptr;
- pb->bytes = (byte*) bptr->orig_bytes;
- pb->flags = 0;
-
- /*
- * Miscellaneous updates. Return the tagged binary.
- */
- OH_OVERHEAD(&(MSO(p)), pb->size / sizeof(Eterm));
- return make_binary(pb);
+ return build_proc_bin(&MSO(p), HAlloc(p, PROC_BIN_SIZE), bptr);
}
/*
@@ -113,7 +119,6 @@ new_binary(Process *p, byte *buf, Uint len)
Eterm erts_new_mso_binary(Process *p, byte *buf, Uint len)
{
- ProcBin* pb;
Binary* bptr;
/*
@@ -124,23 +129,7 @@ Eterm erts_new_mso_binary(Process *p, byte *buf, Uint len)
sys_memcpy(bptr->orig_bytes, buf, len);
}
- /*
- * Now allocate the ProcBin on the heap.
- */
- pb = (ProcBin *) HAlloc(p, PROC_BIN_SIZE);
- pb->thing_word = HEADER_PROC_BIN;
- pb->size = len;
- pb->next = MSO(p).first;
- MSO(p).first = (struct erl_off_heap_header*)pb;
- pb->val = bptr;
- pb->bytes = (byte*) bptr->orig_bytes;
- pb->flags = 0;
-
- /*
- * Miscellaneous updates. Return the tagged binary.
- */
- OH_OVERHEAD(&(MSO(p)), pb->size / sizeof(Eterm));
- return make_binary(pb);
+ return build_proc_bin(&MSO(p), HAlloc(p, PROC_BIN_SIZE), bptr);
}
/*
diff --git a/erts/emulator/beam/break.c b/erts/emulator/beam/break.c
index 2cff05c7f3..e7acea0c5f 100644
--- a/erts/emulator/beam/break.c
+++ b/erts/emulator/beam/break.c
@@ -775,16 +775,16 @@ erl_crash_dump_v(char *file, int line, char* fmt, va_list args)
* - write dump until alarm or file is written completely
*/
- if (erts_sys_getenv__("ERL_CRASH_DUMP_SECONDS", env, &envsz) != 0) {
- env_erl_crash_dump_seconds_set = 0;
- secs = -1;
+ if (erts_sys_explicit_8bit_getenv("ERL_CRASH_DUMP_SECONDS", env, &envsz) == 1) {
+ env_erl_crash_dump_seconds_set = 1;
+ secs = atoi(env);
} else {
- env_erl_crash_dump_seconds_set = 1;
- secs = atoi(env);
+ env_erl_crash_dump_seconds_set = 0;
+ secs = -1;
}
if (secs == 0) {
- return;
+ return;
}
/* erts_sys_prepare_crash_dump returns 1 if heart port is found, otherwise 0
@@ -800,7 +800,7 @@ erl_crash_dump_v(char *file, int line, char* fmt, va_list args)
crash_dump_limit = ERTS_SINT64_MAX;
envsz = sizeof(env);
- if (erts_sys_getenv__("ERL_CRASH_DUMP_BYTES", env, &envsz) == 0) {
+ if (erts_sys_explicit_8bit_getenv("ERL_CRASH_DUMP_BYTES", env, &envsz) == 1) {
Sint64 limit;
char* endptr;
errno = 0;
@@ -813,7 +813,7 @@ erl_crash_dump_v(char *file, int line, char* fmt, va_list args)
}
}
- if (erts_sys_getenv__("ERL_CRASH_DUMP",&dumpnamebuf[0],&dumpnamebufsize) != 0)
+ if (erts_sys_explicit_8bit_getenv("ERL_CRASH_DUMP",&dumpnamebuf[0],&dumpnamebufsize) != 1)
dumpname = "erl_crash.dump";
else
dumpname = &dumpnamebuf[0];
diff --git a/erts/emulator/beam/dist.c b/erts/emulator/beam/dist.c
index 7ff7462bf6..30390cdb5e 100644
--- a/erts/emulator/beam/dist.c
+++ b/erts/emulator/beam/dist.c
@@ -1212,7 +1212,7 @@ erts_dsig_send_group_leader(ErtsDSigData *dsdp, Eterm leader, Eterm remote)
# define PURIFY_MSG(msg) \
do { \
char buf__[1]; size_t bufsz__ = sizeof(buf__); \
- if (erts_sys_getenv_raw("VALGRIND_LOG_XML", buf__, &bufsz__) >= 0) { \
+ if (erts_sys_explicit_8bit_getenv("VALGRIND_LOG_XML", buf__, &bufsz__) >= 0) { \
VALGRIND_PRINTF_XML("<erlang_error_log>" \
"%s, line %d: %s</erlang_error_log>\n", \
__FILE__, __LINE__, msg); \
diff --git a/erts/emulator/beam/erl_alloc.types b/erts/emulator/beam/erl_alloc.types
index c6cc5c78b3..8107f133aa 100644
--- a/erts/emulator/beam/erl_alloc.types
+++ b/erts/emulator/beam/erl_alloc.types
@@ -283,6 +283,8 @@ type THR_PRGR_DATA LONG_LIVED SYSTEM thr_prgr_data
type T_THR_PRGR_DATA SHORT_LIVED SYSTEM temp_thr_prgr_data
type RELEASE_LAREA SHORT_LIVED SYSTEM release_literal_area
+type ENVIRONMENT SYSTEM SYSTEM environment
+
#
# Types used for special emulators
#
@@ -370,8 +372,6 @@ type SYS_READ_BUF TEMPORARY SYSTEM sys_read_buf
type FD_TAB LONG_LIVED SYSTEM fd_tab
type FD_ENTRY_BUF STANDARD SYSTEM fd_entry_buf
type CS_PROG_PATH LONG_LIVED SYSTEM cs_prog_path
-type ENVIRONMENT TEMPORARY SYSTEM environment
-type PUTENV_STR SYSTEM SYSTEM putenv_string
type PRT_REP_EXIT STANDARD SYSTEM port_report_exit
type SYS_BLOCKING STANDARD SYSTEM sys_blocking
@@ -383,9 +383,7 @@ type SYS_WRITE_BUF TEMPORARY SYSTEM sys_write_buf
type DRV_DATA_BUF SYSTEM SYSTEM drv_data_buf
type PRELOADED LONG_LIVED SYSTEM preloaded
-type PUTENV_STR SYSTEM SYSTEM putenv_string
type WAITER_OBJ LONG_LIVED SYSTEM waiter_object
-type ENVIRONMENT SYSTEM SYSTEM environment
type CON_VPRINTF_BUF TEMPORARY SYSTEM con_vprintf_buf
+endif
diff --git a/erts/emulator/beam/erl_bif_binary.c b/erts/emulator/beam/erl_bif_binary.c
index 4cafa499a9..41c2ae08d3 100644
--- a/erts/emulator/beam/erl_bif_binary.c
+++ b/erts/emulator/beam/erl_bif_binary.c
@@ -2825,28 +2825,21 @@ BIF_RETTYPE binary_copy_trap(BIF_ALIST_2)
BIF_TRAP2(&binary_copy_trap_export, BIF_P, BIF_ARG_1, BIF_ARG_2);
} else {
Binary *save;
- ProcBin* pb;
+ Eterm resbin;
Uint target_size = cbs->result->orig_size;
while (pos < target_size) {
memcpy(t+pos,cbs->source, size);
pos += size;
}
- save = cbs->result;
+ save = cbs->result;
cbs->result = NULL;
cleanup_copy_bin_state(mb); /* now cbs is dead */
- pb = (ProcBin *) HAlloc(BIF_P, PROC_BIN_SIZE);
- pb->thing_word = HEADER_PROC_BIN;
- pb->size = target_size;
- pb->next = MSO(BIF_P).first;
- MSO(BIF_P).first = (struct erl_off_heap_header*) pb;
- pb->val = save;
- pb->bytes = t;
- pb->flags = 0;
-
- OH_OVERHEAD(&(MSO(BIF_P)), target_size / sizeof(Eterm));
- BUMP_REDS(BIF_P,(pos - opos) / BINARY_COPY_LOOP_FACTOR);
-
- BIF_RET(make_binary(pb));
+
+ resbin = erts_build_proc_bin(&MSO(BIF_P),
+ HAlloc(BIF_P, PROC_BIN_SIZE),
+ save);
+ BUMP_REDS(BIF_P,(pos - opos) / BINARY_COPY_LOOP_FACTOR);
+ BIF_RET(resbin);
}
}
diff --git a/erts/emulator/beam/erl_bif_info.c b/erts/emulator/beam/erl_bif_info.c
index 2f6f2c6e0a..903f54e2fb 100644
--- a/erts/emulator/beam/erl_bif_info.c
+++ b/erts/emulator/beam/erl_bif_info.c
@@ -1754,7 +1754,7 @@ static int check_if_xml(void)
{
char buf[1];
size_t bufsz = sizeof(buf);
- return erts_sys_getenv_raw("VALGRIND_LOG_XML", buf, &bufsz) >= 0;
+ return erts_sys_explicit_8bit_getenv("VALGRIND_LOG_XML", buf, &bufsz) >= 0;
}
#else
#define check_if_xml() 0
@@ -4334,6 +4334,19 @@ BIF_RETTYPE erts_debug_set_internal_state_2(BIF_ALIST_2)
BIF_RET(res);
}
}
+ else if (ERTS_IS_ATOM_STR("binary", BIF_ARG_1)) {
+ Sint64 size;
+ if (term_to_Sint64(BIF_ARG_2, &size)) {
+ Binary* refbin = erts_bin_drv_alloc_fnf(size);
+ if (!refbin)
+ BIF_RET(am_false);
+ sys_memset(refbin->orig_bytes, 0, size);
+ BIF_RET(erts_build_proc_bin(&MSO(BIF_P),
+ HAlloc(BIF_P, PROC_BIN_SIZE),
+ refbin));
+ }
+ }
+
}
BIF_ERROR(BIF_P, BADARG);
diff --git a/erts/emulator/beam/erl_bif_os.c b/erts/emulator/beam/erl_bif_os.c
index 910325a2f4..ce2b27409b 100644
--- a/erts/emulator/beam/erl_bif_os.c
+++ b/erts/emulator/beam/erl_bif_os.c
@@ -36,8 +36,7 @@
#include "big.h"
#include "dist.h"
#include "erl_version.h"
-
-static int check_env_name(char *name);
+#include "erl_osenv.h"
/*
* Return the pid for the Erlang process in the host OS.
@@ -67,148 +66,78 @@ BIF_RETTYPE os_getpid_0(BIF_ALIST_0)
BIF_RET(buf_to_intlist(&hp, pid_string, n, NIL));
}
-BIF_RETTYPE os_getenv_0(BIF_ALIST_0)
+static void os_getenv_foreach(Process *process, Eterm *result, Eterm key, Eterm value)
{
- GETENV_STATE state;
- char *cp;
- Eterm* hp;
- Eterm ret;
- Eterm str;
+ Eterm kvp_term, *hp;
- init_getenv_state(&state);
+ hp = HAlloc(process, 5);
+ kvp_term = TUPLE2(hp, key, value);
+ hp += 3;
- ret = NIL;
- while ((cp = getenv_string(&state)) != NULL) {
- str = erts_convert_native_to_filename(BIF_P,(byte *)cp);
- hp = HAlloc(BIF_P, 2);
- ret = CONS(hp, str, ret);
- }
+ (*result) = CONS(hp, kvp_term, (*result));
+}
- fini_getenv_state(&state);
+BIF_RETTYPE os_list_env_vars_0(BIF_ALIST_0)
+{
+ const erts_osenv_t *global_env;
+ Eterm result = NIL;
+
+ global_env = erts_sys_rlock_global_osenv();
+ erts_osenv_foreach_term(global_env, BIF_P, &result, (void*)&os_getenv_foreach);
+ erts_sys_runlock_global_osenv();
- return ret;
+ return result;
}
-#define STATIC_BUF_SIZE 1024
-BIF_RETTYPE os_getenv_1(BIF_ALIST_1)
+BIF_RETTYPE os_get_env_var_1(BIF_ALIST_1)
{
- Process* p = BIF_P;
- Eterm str;
- Sint len;
- int res;
- char *key_str, *val;
- char buf[STATIC_BUF_SIZE];
- size_t val_size = sizeof(buf);
-
- key_str = erts_convert_filename_to_native(BIF_ARG_1,buf,STATIC_BUF_SIZE,
- ERTS_ALC_T_TMP,1,0,&len);
-
- if (!check_env_name(key_str)) {
- if (key_str && key_str != &buf[0])
- erts_free(ERTS_ALC_T_TMP, key_str);
- BIF_ERROR(p, BADARG);
- }
+ const erts_osenv_t *global_env;
+ Eterm out_term;
+ int error;
- if (key_str != &buf[0])
- val = &buf[0];
- else {
- /* len includes zero byte */
- val_size -= len;
- val = &buf[len];
- }
- res = erts_sys_getenv(key_str, val, &val_size);
-
- if (res < 0) {
- no_var:
- str = am_false;
- } else {
- if (res > 0) {
- val = erts_alloc(ERTS_ALC_T_TMP, val_size);
- while (1) {
- res = erts_sys_getenv(key_str, val, &val_size);
- if (res == 0)
- break;
- else if (res < 0)
- goto no_var;
- else
- val = erts_realloc(ERTS_ALC_T_TMP, val, val_size);
- }
- }
- str = erts_convert_native_to_filename(p,(byte *)val);
- }
- if (key_str != &buf[0])
- erts_free(ERTS_ALC_T_TMP, key_str);
- if (val < &buf[0] || &buf[sizeof(buf)-1] < val)
- erts_free(ERTS_ALC_T_TMP, val);
- BIF_RET(str);
+ global_env = erts_sys_rlock_global_osenv();
+ error = erts_osenv_get_term(global_env, BIF_P, BIF_ARG_1, &out_term);
+ erts_sys_runlock_global_osenv();
+
+ if (error == 0) {
+ return am_false;
+ } else if (error < 0) {
+ BIF_ERROR(BIF_P, BADARG);
+ }
+
+ return out_term;
}
-BIF_RETTYPE os_putenv_2(BIF_ALIST_2)
+BIF_RETTYPE os_set_env_var_2(BIF_ALIST_2)
{
- char def_buf_key[STATIC_BUF_SIZE];
- char def_buf_value[STATIC_BUF_SIZE];
- char *key_buf = NULL, *value_buf = NULL;
-
- key_buf = erts_convert_filename_to_native(BIF_ARG_1,def_buf_key,
- STATIC_BUF_SIZE,
- ERTS_ALC_T_TMP,0,0,NULL);
- if (!check_env_name(key_buf))
- goto badarg;
-
- value_buf = erts_convert_filename_to_native(BIF_ARG_2,def_buf_value,
- STATIC_BUF_SIZE,
- ERTS_ALC_T_TMP,1,0,
- NULL);
- if (!value_buf)
- goto badarg;
-
- if (erts_sys_putenv(key_buf, value_buf)) {
- if (key_buf != def_buf_key) {
- erts_free(ERTS_ALC_T_TMP, key_buf);
- }
- if (value_buf != def_buf_value) {
- erts_free(ERTS_ALC_T_TMP, value_buf);
- }
- BIF_ERROR(BIF_P, BADARG);
- }
- if (key_buf != def_buf_key) {
- erts_free(ERTS_ALC_T_TMP, key_buf);
- }
- if (value_buf != def_buf_value) {
- erts_free(ERTS_ALC_T_TMP, value_buf);
+ erts_osenv_t *global_env;
+ int error;
+
+ global_env = erts_sys_rwlock_global_osenv();
+ error = erts_osenv_put_term(global_env, BIF_ARG_1, BIF_ARG_2);
+ erts_sys_rwunlock_global_osenv();
+
+ if (error < 0) {
+ BIF_ERROR(BIF_P, BADARG);
}
- BIF_RET(am_true);
-badarg:
- if (key_buf && key_buf != def_buf_key)
- erts_free(ERTS_ALC_T_TMP, key_buf);
- if (value_buf && value_buf != def_buf_value)
- erts_free(ERTS_ALC_T_TMP, value_buf);
- BIF_ERROR(BIF_P, BADARG);
+ BIF_RET(am_true);
}
-BIF_RETTYPE os_unsetenv_1(BIF_ALIST_1)
+BIF_RETTYPE os_unset_env_var_1(BIF_ALIST_1)
{
- char *key_buf;
- char buf[STATIC_BUF_SIZE];
+ erts_osenv_t *global_env;
+ int error;
- key_buf = erts_convert_filename_to_native(BIF_ARG_1,buf,STATIC_BUF_SIZE,
- ERTS_ALC_T_TMP,0,0,NULL);
- if (!check_env_name(key_buf))
- goto badarg;
+ global_env = erts_sys_rwlock_global_osenv();
+ error = erts_osenv_unset_term(global_env, BIF_ARG_1);
+ erts_sys_rwunlock_global_osenv();
- if (erts_sys_unsetenv(key_buf))
- goto badarg;
-
- if (key_buf != buf) {
- erts_free(ERTS_ALC_T_TMP, key_buf);
+ if (error < 0) {
+ BIF_ERROR(BIF_P, BADARG);
}
- BIF_RET(am_true);
-badarg:
- if (key_buf && key_buf != buf)
- erts_free(ERTS_ALC_T_TMP, key_buf);
- BIF_ERROR(BIF_P, BADARG);
+ BIF_RET(am_true);
}
BIF_RETTYPE os_set_signal_2(BIF_ALIST_2) {
@@ -224,27 +153,3 @@ BIF_RETTYPE os_set_signal_2(BIF_ALIST_2) {
error:
BIF_ERROR(BIF_P, BADARG);
}
-
-static int
-check_env_name(char *raw_name)
-{
- byte *c = (byte *) raw_name;
- int encoding;
-
- if (!c)
- return 0;
-
- encoding = erts_get_native_filename_encoding();
-
- if (erts_raw_env_char_is_7bit_ascii_char('\0', c, encoding))
- return 0; /* Do not allow empty name... */
-
- /* Verify no '=' characters in variable name... */
- do {
- if (erts_raw_env_char_is_7bit_ascii_char('=', c, encoding))
- return 0;
- c = erts_raw_env_next_char(c, encoding);
- } while (!erts_raw_env_char_is_7bit_ascii_char('\0', c, encoding));
-
- return 1; /* Seems ok... */
-}
diff --git a/erts/emulator/beam/erl_bif_port.c b/erts/emulator/beam/erl_bif_port.c
index c4a4dd5863..9f0c90ff7b 100644
--- a/erts/emulator/beam/erl_bif_port.c
+++ b/erts/emulator/beam/erl_bif_port.c
@@ -45,7 +45,7 @@
#include "dtrace-wrapper.h"
static Port *open_port(Process* p, Eterm name, Eterm settings, int *err_typep, int *err_nump);
-static char* convert_environment(Eterm env);
+static int merge_global_environment(erts_osenv_t *env, Eterm key_value_pairs);
static char **convert_args(Eterm);
static void free_args(char **);
@@ -651,6 +651,7 @@ BIF_RETTYPE port_get_data_1(BIF_ALIST_1)
static Port *
open_port(Process* p, Eterm name, Eterm settings, int *err_typep, int *err_nump)
{
+ int merged_environment = 0;
Sint i;
Eterm option;
Uint arity;
@@ -672,12 +673,13 @@ open_port(Process* p, Eterm name, Eterm settings, int *err_typep, int *err_nump)
opts.read_write = 0;
opts.hide_window = 0;
opts.wd = NULL;
- opts.envir = NULL;
opts.exit_status = 0;
opts.overlapped_io = 0;
opts.spawn_type = ERTS_SPAWN_ANY;
opts.argv = NULL;
opts.parallelism = erts_port_parallelism;
+ erts_osenv_init(&opts.envir);
+
linebuf = 0;
*err_nump = 0;
@@ -718,11 +720,16 @@ open_port(Process* p, Eterm name, Eterm settings, int *err_typep, int *err_nump)
goto badarg;
}
} else if (option == am_env) {
- if (opts.envir) /* ignore previous env option... */
- erts_free(ERTS_ALC_T_OPEN_PORT_ENV, opts.envir);
- opts.envir = convert_environment(*tp);
- if (!opts.envir)
- goto badarg;
+ if (merged_environment) {
+ /* Ignore previous env option */
+ erts_osenv_clear(&opts.envir);
+ }
+
+ merged_environment = 1;
+
+ if (merge_global_environment(&opts.envir, *tp)) {
+ goto badarg;
+ }
} else if (option == am_args) {
char **av;
char **oav = opts.argv;
@@ -807,6 +814,12 @@ open_port(Process* p, Eterm name, Eterm settings, int *err_typep, int *err_nump)
if((linebuf && opts.packet_bytes) ||
(opts.redir_stderr && !opts.use_stdio)) {
goto badarg;
+}
+
+ /* If we lacked an env option, fill in the global environment without
+ * changes. */
+ if (!merged_environment) {
+ merge_global_environment(&opts.envir, NIL);
}
/*
@@ -956,8 +969,7 @@ open_port(Process* p, Eterm name, Eterm settings, int *err_typep, int *err_nump)
erts_atomic32_read_bor_relb(&port->state, sflgs);
do_return:
- if (opts.envir)
- erts_free(ERTS_ALC_T_OPEN_PORT_ENV, opts.envir);
+ erts_osenv_clear(&opts.envir);
if (name_buf)
erts_free(ERTS_ALC_T_TMP, (void *) name_buf);
if (opts.argv) {
@@ -977,6 +989,45 @@ open_port(Process* p, Eterm name, Eterm settings, int *err_typep, int *err_nump)
goto do_return;
}
+/* Merges the the global environment and the given {Key, Value} list into env,
+ * unsetting all keys whose value is either 'false' or NIL. The behavior on
+ * NIL is undocumented and perhaps surprising, but the previous implementation
+ * worked in this manner. */
+static int merge_global_environment(erts_osenv_t *env, Eterm key_value_pairs) {
+ const erts_osenv_t *global_env = erts_sys_rlock_global_osenv();
+ erts_osenv_merge(env, global_env, 0);
+ erts_sys_runlock_global_osenv();
+
+ while (is_list(key_value_pairs)) {
+ Eterm *cell, *tuple;
+
+ cell = list_val(key_value_pairs);
+
+ if(!is_tuple_arity(CAR(cell), 2)) {
+ return -1;
+ }
+
+ tuple = tuple_val(CAR(cell));
+ key_value_pairs = CDR(cell);
+
+ if(is_nil(tuple[2]) || tuple[2] == am_false) {
+ if(erts_osenv_unset_term(env, tuple[1]) < 0) {
+ return -1;
+ }
+ } else {
+ if(erts_osenv_put_term(env, tuple[1], tuple[2]) < 0) {
+ return -1;
+ }
+ }
+ }
+
+ if(!is_nil(key_value_pairs)) {
+ return -1;
+ }
+
+ return 0;
+}
+
/* Arguments can be given i unicode and as raw binaries, convert filename is used to convert */
static char **convert_args(Eterm l)
{
@@ -1024,130 +1075,6 @@ static void free_args(char **av)
erts_free(ERTS_ALC_T_TMP, av);
}
-#ifdef DEBUG
-#define ERTS_CONV_ENV_BUF_EXTRA 2
-#else
-#define ERTS_CONV_ENV_BUF_EXTRA 1024
-#endif
-
-static char* convert_environment(Eterm env)
-{
- /*
- * Returns environment buffer in memory allocated
- * as ERTS_ALC_T_OPEN_PORT_ENV. Caller *needs*
- * to deallocate...
- */
-
- Sint size, alloc_size;
- byte* bytes;
- int encoding = erts_get_native_filename_encoding();
-
- alloc_size = ERTS_CONV_ENV_BUF_EXTRA;
- bytes = erts_alloc(ERTS_ALC_T_OPEN_PORT_ENV,
- alloc_size);
- size = 0;
-
- /* ERTS_CONV_ENV_BUF_EXTRA >= for end delimiter... */
- ERTS_CT_ASSERT(ERTS_CONV_ENV_BUF_EXTRA >= 2);
-
- while (is_list(env)) {
- Sint var_sz, val_sz, need;
- byte *str, *limit;
- Eterm tmp, *tp, *consp;
-
- consp = list_val(env);
- tmp = CAR(consp);
- if (is_not_tuple_arity(tmp, 2))
- goto error;
-
- tp = tuple_val(tmp);
-
- /* Check encoding of env variable... */
- if (is_not_list(tp[1]))
- goto error;
- var_sz = erts_native_filename_need(tp[1], encoding);
- if (var_sz <= 0)
- goto error;
- /* Check encoding of value... */
- if (tp[2] == am_false || is_nil(tp[2]))
- val_sz = 0;
- else if (is_not_list(tp[2]))
- goto error;
- else {
- val_sz = erts_native_filename_need(tp[2], encoding);
- if (val_sz < 0)
- goto error;
- }
-
- /* Ensure enough memory... */
- need = size;
- need += var_sz + val_sz;
- /* '=' and '\0' */
- need += 2 * erts_raw_env_7bit_ascii_char_need(encoding);
- if (need > alloc_size) {
- alloc_size = (need - alloc_size) + alloc_size;
- alloc_size += ERTS_CONV_ENV_BUF_EXTRA;
- bytes = erts_realloc(ERTS_ALC_T_OPEN_PORT_ENV,
- bytes, alloc_size);
- }
-
- /* Write environment variable name... */
- str = bytes + size;
- erts_native_filename_put(tp[1], encoding, str);
- /* empty variable name is not allowed... */
- if (erts_raw_env_char_is_7bit_ascii_char('\0', str, encoding))
- goto error;
-
- /*
- * Drop null characters at the end and verify that we do
- * not have any '=' characters in the name...
- */
- limit = str + var_sz;
- while (str < limit) {
- if (erts_raw_env_char_is_7bit_ascii_char('\0', str, encoding))
- break;
- if (erts_raw_env_char_is_7bit_ascii_char('=', str, encoding))
- goto error;
- str = erts_raw_env_next_char(str, encoding);
- }
-
- /* Write the equals sign... */
- str = erts_raw_env_7bit_ascii_char_put('=', str, encoding);
-
- /* Write the value... */
- if (val_sz > 0) {
- limit = str + val_sz;
- erts_native_filename_put(tp[2], encoding, str);
- while (str < limit) {
- if (erts_raw_env_char_is_7bit_ascii_char('\0', str, encoding))
- break;
- str = erts_raw_env_next_char(str, encoding);
- }
- }
-
- /* Delimit... */
- str = erts_raw_env_7bit_ascii_char_put('\0', str, encoding);
-
- size = str - bytes;
- ASSERT(size <= alloc_size);
-
- env = CDR(consp);
- }
-
- /* End delimit... */
- (void) erts_raw_env_7bit_ascii_char_put('\0', &bytes[size], encoding);
-
- if (is_nil(env))
- return (char *) bytes;
-
-error:
-
- if (bytes)
- erts_free(ERTS_ALC_T_OPEN_PORT_ENV, bytes);
-
- return (char *) NULL; /* error... */
-}
-
/* ------------ decode_packet() and friends: */
struct packet_callback_args
diff --git a/erts/emulator/beam/erl_init.c b/erts/emulator/beam/erl_init.c
index 6cef9bd0e3..4846ccd2d3 100644
--- a/erts/emulator/beam/erl_init.c
+++ b/erts/emulator/beam/erl_init.c
@@ -50,7 +50,7 @@
#define ERTS_WANT_TIMER_WHEEL_API
#include "erl_time.h"
#include "erl_check_io.h"
-
+#include "erl_osenv.h"
#ifdef HIPE
#include "hipe_mode_switch.h" /* for hipe_mode_switch_init() */
#include "hipe_signal.h" /* for hipe_signal_init() */
@@ -155,9 +155,6 @@ erts_atomic32_t erts_writing_erl_crash_dump;
erts_tsd_key_t erts_is_crash_dumping_key;
int erts_initialized = 0;
-
-int erts_use_sender_punish;
-
/*
* Configurable parameters.
*/
@@ -758,8 +755,6 @@ early_init(int *argc, char **argv) /*
erts_initialized = 0;
- erts_use_sender_punish = 1;
-
erts_pre_early_init_cpu_topology(&max_reader_groups,
&ncpu,
&ncpuonln,
@@ -803,8 +798,9 @@ early_init(int *argc, char **argv) /*
envbufsz = sizeof(envbuf);
- /* erts_sys_getenv(_raw)() not initialized yet; need erts_sys_getenv__() */
- if (erts_sys_getenv__("ERL_THREAD_POOL_SIZE", envbuf, &envbufsz) == 0)
+ /* erts_osenv hasn't been initialized yet, so we need to fall back to
+ * erts_sys_explicit_host_getenv() */
+ if (erts_sys_explicit_host_getenv("ERL_THREAD_POOL_SIZE", envbuf, &envbufsz) == 1)
erts_async_max_threads = atoi(envbuf);
else
erts_async_max_threads = ERTS_DEFAULT_NO_ASYNC_THREADS;
@@ -1210,20 +1206,20 @@ erl_start(int argc, char **argv)
&time_warp_mode);
envbufsz = sizeof(envbuf);
- if (erts_sys_getenv_raw(ERL_MAX_ETS_TABLES_ENV, envbuf, &envbufsz) == 0)
+ if (erts_sys_explicit_8bit_getenv(ERL_MAX_ETS_TABLES_ENV, envbuf, &envbufsz) == 1)
user_requested_db_max_tabs = atoi(envbuf);
else
user_requested_db_max_tabs = 0;
envbufsz = sizeof(envbuf);
- if (erts_sys_getenv_raw("ERL_FULLSWEEP_AFTER", envbuf, &envbufsz) == 0) {
+ if (erts_sys_explicit_8bit_getenv("ERL_FULLSWEEP_AFTER", envbuf, &envbufsz) == 1) {
Uint16 max_gen_gcs = atoi(envbuf);
erts_atomic32_set_nob(&erts_max_gen_gcs,
(erts_aint32_t) max_gen_gcs);
}
envbufsz = sizeof(envbuf);
- if (erts_sys_getenv_raw("ERL_MAX_PORTS", envbuf, &envbufsz) == 0) {
+ if (erts_sys_explicit_8bit_getenv("ERL_MAX_PORTS", envbuf, &envbufsz) == 1) {
port_tab_sz = atoi(envbuf);
port_tab_sz_ignore_files = 1;
}
@@ -1764,8 +1760,6 @@ erl_start(int argc, char **argv)
erts_usage();
}
}
- else if (sys_strcmp("nsp", sub_param) == 0)
- erts_use_sender_punish = 0;
else if (has_prefix("tbt", sub_param)) {
arg = get_arg(sub_param+3, argv[i+1], &i);
res = erts_init_scheduler_bind_type_string(arg);
diff --git a/erts/emulator/beam/erl_io_queue.c b/erts/emulator/beam/erl_io_queue.c
index 40d69ea6b0..c93b5248d9 100644
--- a/erts/emulator/beam/erl_io_queue.c
+++ b/erts/emulator/beam/erl_io_queue.c
@@ -817,24 +817,15 @@ static Eterm iol2v_make_sub_bin(iol2v_state_t *state, Eterm bin_term,
}
static Eterm iol2v_promote_acc(iol2v_state_t *state) {
- ProcBin *pb;
-
- state->acc = erts_bin_realloc(state->acc, state->acc_size);
-
- pb = (ProcBin*)HAlloc(state->process, PROC_BIN_SIZE);
- pb->thing_word = HEADER_PROC_BIN;
- pb->size = state->acc_size;
- pb->val = state->acc;
- pb->bytes = (byte*)(state->acc)->orig_bytes;
- pb->flags = 0;
- pb->next = MSO(state->process).first;
- OH_OVERHEAD(&(MSO(state->process)), pb->size / sizeof(Eterm));
- MSO(state->process).first = (struct erl_off_heap_header*)pb;
+ Eterm bin;
+ bin = erts_build_proc_bin(&MSO(state->process),
+ HAlloc(state->process, PROC_BIN_SIZE),
+ erts_bin_realloc(state->acc, state->acc_size));
state->acc_size = 0;
state->acc = NULL;
- return make_binary(pb);
+ return bin;
}
/* Destructively enqueues a term to the result list, saving us the hassle of
diff --git a/erts/emulator/beam/erl_nif.c b/erts/emulator/beam/erl_nif.c
index 0a5fe026db..94ebf88b56 100644
--- a/erts/emulator/beam/erl_nif.c
+++ b/erts/emulator/beam/erl_nif.c
@@ -1317,21 +1317,11 @@ Eterm enif_make_binary(ErlNifEnv* env, ErlNifBinary* bin)
}
else if (bin->ref_bin != NULL) {
Binary* bptr = bin->ref_bin;
- ProcBin* pb;
Eterm bin_term;
- /* !! Copy-paste from new_binary() !! */
- pb = (ProcBin *) alloc_heap(env, PROC_BIN_SIZE);
- pb->thing_word = HEADER_PROC_BIN;
- pb->size = bptr->orig_size;
- pb->next = MSO(env->proc).first;
- MSO(env->proc).first = (struct erl_off_heap_header*) pb;
- pb->val = bptr;
- pb->bytes = (byte*) bptr->orig_bytes;
- pb->flags = 0;
-
- OH_OVERHEAD(&(MSO(env->proc)), pb->size / sizeof(Eterm));
- bin_term = make_binary(pb);
+ bin_term = erts_build_proc_bin(&MSO(env->proc),
+ alloc_heap(env, PROC_BIN_SIZE),
+ bptr);
if (erts_refc_read(&bptr->intern.refc, 1) == 1) {
/* Total ownership transfer */
bin->ref_bin = NULL;
diff --git a/erts/emulator/beam/erl_unicode.c b/erts/emulator/beam/erl_unicode.c
index b7a5c45fea..604f0be127 100644
--- a/erts/emulator/beam/erl_unicode.c
+++ b/erts/emulator/beam/erl_unicode.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2008-2017. All Rights Reserved.
+ * Copyright Ericsson AB 2008-2018. 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.
@@ -1158,14 +1158,15 @@ static ERTS_INLINE int
analyze_utf8(byte *source, Uint size, byte **err_pos, Uint *num_chars, int *left,
Sint *num_latin1_chars, Uint max_chars)
{
+ int res = ERTS_UTF8_OK;
Uint latin1_count;
int is_latin1;
+ Uint nchars = 0;
*err_pos = source;
if (num_latin1_chars) {
is_latin1 = 1;
latin1_count = 0;
}
- *num_chars = 0;
while (size) {
if (((*source) & ((byte) 0x80)) == 0) {
source++;
@@ -1174,11 +1175,13 @@ analyze_utf8(byte *source, Uint size, byte **err_pos, Uint *num_chars, int *left
latin1_count++;
} else if (((*source) & ((byte) 0xE0)) == 0xC0) {
if (size < 2) {
- return ERTS_UTF8_INCOMPLETE;
+ res = ERTS_UTF8_INCOMPLETE;
+ break;
}
if (((source[1] & ((byte) 0xC0)) != 0x80) ||
((*source) < 0xC2) /* overlong */) {
- return ERTS_UTF8_ERROR;
+ res = ERTS_UTF8_ERROR;
+ break;
}
if (num_latin1_chars) {
latin1_count++;
@@ -1189,16 +1192,19 @@ analyze_utf8(byte *source, Uint size, byte **err_pos, Uint *num_chars, int *left
size -= 2;
} else if (((*source) & ((byte) 0xF0)) == 0xE0) {
if (size < 3) {
- return ERTS_UTF8_INCOMPLETE;
+ res = ERTS_UTF8_INCOMPLETE;
+ break;
}
if (((source[1] & ((byte) 0xC0)) != 0x80) ||
((source[2] & ((byte) 0xC0)) != 0x80) ||
(((*source) == 0xE0) && (source[1] < 0xA0)) /* overlong */ ) {
- return ERTS_UTF8_ERROR;
+ res = ERTS_UTF8_ERROR;
+ break;
}
if ((((*source) & ((byte) 0xF)) == 0xD) &&
((source[1] & 0x20) != 0)) {
- return ERTS_UTF8_ERROR;
+ res = ERTS_UTF8_ERROR;
+ break;
}
source += 3;
size -= 3;
@@ -1206,37 +1212,47 @@ analyze_utf8(byte *source, Uint size, byte **err_pos, Uint *num_chars, int *left
is_latin1 = 0;
} else if (((*source) & ((byte) 0xF8)) == 0xF0) {
if (size < 4) {
- return ERTS_UTF8_INCOMPLETE;
+ res = ERTS_UTF8_INCOMPLETE;
+ break;
}
if (((source[1] & ((byte) 0xC0)) != 0x80) ||
((source[2] & ((byte) 0xC0)) != 0x80) ||
((source[3] & ((byte) 0xC0)) != 0x80) ||
(((*source) == 0xF0) && (source[1] < 0x90)) /* overlong */) {
- return ERTS_UTF8_ERROR;
+ res = ERTS_UTF8_ERROR;
+ break;
}
if ((((*source) & ((byte)0x7)) > 0x4U) ||
((((*source) & ((byte)0x7)) == 0x4U) &&
((source[1] & ((byte)0x3F)) > 0xFU))) {
- return ERTS_UTF8_ERROR;
+ res = ERTS_UTF8_ERROR;
+ break;
}
source += 4;
size -= 4;
if (num_latin1_chars)
is_latin1 = 0;
} else {
- return ERTS_UTF8_ERROR;
+ res = ERTS_UTF8_ERROR;
+ break;
}
- ++(*num_chars);
+ ++nchars;
*err_pos = source;
- if (max_chars && size > 0 && *num_chars == max_chars)
- return ERTS_UTF8_OK_MAX_CHARS;
+ if (max_chars && size > 0 && nchars == max_chars) {
+ res = ERTS_UTF8_OK_MAX_CHARS;
+ break;
+ }
if (left && --(*left) <= 0 && size) {
- return ERTS_UTF8_ANALYZE_MORE;
+ res = ERTS_UTF8_ANALYZE_MORE;
+ break;
}
}
+
+ *num_chars = nchars;
if (num_latin1_chars)
*num_latin1_chars = is_latin1 ? latin1_count : -1;
- return ERTS_UTF8_OK;
+
+ return res;
}
int erts_analyze_utf8(byte *source, Uint size,
@@ -1252,29 +1268,18 @@ int erts_analyze_utf8_x(byte *source, Uint size,
return analyze_utf8(source, size, err_pos, num_chars, left, num_latin1_chars, max_chars);
}
-/*
- * No errors should be able to occur - no overlongs, no malformed, no nothing
- */
-static Eterm do_utf8_to_list(Process *p, Uint num, byte *bytes, Uint sz,
- Uint left,
- Uint *num_built, Uint *num_eaten, Eterm tail)
+static ERTS_INLINE Eterm
+make_list_from_utf8_buf(Eterm **hpp, Uint num,
+ byte *bytes, Uint sz,
+ Uint *num_built, Uint *num_eaten,
+ Eterm tail)
{
Eterm *hp;
Eterm ret;
+ Uint left = num;
byte *source, *ssource;
Uint unipoint;
-
- ASSERT(num > 0);
- if (left < num) {
- if (left > 0)
- num = left;
- else
- num = 1;
- }
-
- *num_built = num; /* Always */
-
- hp = HAlloc(p,num * 2);
+ hp = *hpp;
ret = tail;
source = bytes + sz;
ssource = source;
@@ -1302,20 +1307,97 @@ static Eterm do_utf8_to_list(Process *p, Uint num, byte *bytes, Uint sz,
}
ret = CONS(hp,make_small(unipoint),ret);
hp += 2;
- if (--num <= 0) {
+ if (--left <= 0) {
break;
}
}
+ *hpp = hp;
+ *num_built = num; /* Always */
*num_eaten = (ssource - source);
return ret;
}
+/*
+ * No errors should be able to occur - no overlongs, no malformed, no nothing
+ */
+static Eterm do_utf8_to_list(Process *p, Uint num, byte *bytes, Uint sz,
+ Uint left,
+ Uint *num_built, Uint *num_eaten, Eterm tail)
+{
+ Eterm *hp;
+
+ ASSERT(num > 0);
+ if (left < num) {
+ if (left > 0)
+ num = left;
+ else
+ num = 1;
+ }
+
+ hp = HAlloc(p,num * 2);
+
+ return make_list_from_utf8_buf(&hp, num, bytes, sz,
+ num_built, num_eaten,
+ tail);
+}
Eterm erts_utf8_to_list(Process *p, Uint num, byte *bytes, Uint sz, Uint left,
Uint *num_built, Uint *num_eaten, Eterm tail)
{
return do_utf8_to_list(p, num, bytes, sz, left, num_built, num_eaten, tail);
}
+Uint erts_atom_to_string_length(Eterm atom)
+{
+ Atom *ap;
+
+ ASSERT(is_atom(atom));
+ ap = atom_tab(atom_val(atom));
+
+ if (ap->latin1_chars >= 0)
+ return (Uint) ap->len;
+ else {
+ byte* err_pos;
+ Uint num_chars;
+#ifdef DEBUG
+ int ares =
+#endif
+ erts_analyze_utf8(ap->name, ap->len, &err_pos, &num_chars, NULL);
+ ASSERT(ares == ERTS_UTF8_OK);
+
+ return num_chars;
+ }
+}
+
+Eterm erts_atom_to_string(Eterm **hpp, Eterm atom)
+{
+ Atom *ap;
+
+ ASSERT(is_atom(atom));
+ ap = atom_tab(atom_val(atom));
+ if (ap->latin1_chars >= 0)
+ return buf_to_intlist(hpp, (char*)ap->name, ap->len, NIL);
+ else {
+ Eterm res;
+ byte* err_pos;
+ Uint num_chars, num_built, num_eaten;
+#ifdef DEBUG
+ Eterm *hp_start = *hpp;
+ int ares =
+#endif
+ erts_analyze_utf8(ap->name, ap->len, &err_pos, &num_chars, NULL);
+ ASSERT(ares == ERTS_UTF8_OK);
+
+ res = make_list_from_utf8_buf(hpp, num_chars, ap->name, ap->len,
+ &num_built, &num_eaten, NIL);
+
+ ASSERT(num_built == num_chars);
+ ASSERT(num_eaten == ap->len);
+ ASSERT(*hpp - hp_start == 2*num_chars);
+
+ return res;
+ }
+}
+
static int is_candidate(Uint cp)
{
int index,pos;
@@ -2083,18 +2165,9 @@ char* erts_convert_filename_to_wchar(byte* bytes, Uint size,
return name_buf;
}
-
-static int filename_len_16bit(byte *str)
-{
- byte *p = str;
- while(*p != '\0' || p[1] != '\0') {
- p += 2;
- }
- return (p - str);
-}
-Eterm erts_convert_native_to_filename(Process *p, byte *bytes)
+Eterm erts_convert_native_to_filename(Process *p, size_t size, byte *bytes)
{
- Uint size,num_chars;
+ Uint num_chars;
Eterm *hp;
byte *err_pos;
Uint num_built; /* characters */
@@ -2108,7 +2181,6 @@ Eterm erts_convert_native_to_filename(Process *p, byte *bytes)
case ERL_FILENAME_UTF8_MAC:
mac = 1;
case ERL_FILENAME_UTF8:
- size = strlen((char *) bytes);
if (size == 0)
return NIL;
if (erts_analyze_utf8(bytes,size,&err_pos,&num_chars,NULL) != ERTS_UTF8_OK) {
@@ -2123,7 +2195,6 @@ Eterm erts_convert_native_to_filename(Process *p, byte *bytes)
}
return ret;
case ERL_FILENAME_WIN_WCHAR:
- size=filename_len_16bit(bytes);
if ((size % 2) != 0) { /* Panic fixup to avoid crashing the emulator */
size--;
hp = HAlloc(p, size+2);
@@ -2146,7 +2217,6 @@ Eterm erts_convert_native_to_filename(Process *p, byte *bytes)
goto noconvert;
}
noconvert:
- size = strlen((char *) bytes);
hp = HAlloc(p, 2 * size);
return erts_bin_bytes_to_list(NIL, hp, bytes, size, 0);
}
@@ -2158,7 +2228,6 @@ Sint erts_native_filename_need(Eterm ioterm, int encoding)
Eterm obj;
DECLARE_ESTACK(stack);
Sint need = 0;
- int seen_null = 0;
if (is_atom(ioterm)) {
Atom* ap;
@@ -2203,9 +2272,7 @@ Sint erts_native_filename_need(Eterm ioterm, int encoding)
byte *name = ap->name;
int len = ap->len;
for (i = 0; i < len; i++) {
- if (name[i] == 0)
- seen_null = 1;
- else if (seen_null) {
+ if (name[i] == 0) {
need = -1;
break;
}
@@ -2245,9 +2312,7 @@ L_Again: /* Restart with sublist, old listend was pushed on stack */
* Do not allow null in
* the middle of filenames
*/
- if (x == 0)
- seen_null = 1;
- else if (seen_null) {
+ if (x == 0) {
DESTROY_ESTACK(stack);
return ((Sint) -1);
}
@@ -2580,7 +2645,6 @@ BIF_RETTYPE prim_file_internal_name2native_1(BIF_ALIST_1)
BIF_ERROR(BIF_P,BADARG);
}
if (is_binary(BIF_ARG_1)) {
- int seen_null = 0;
byte *temp_alloc = NULL;
byte *bytes;
byte *err_pos;
@@ -2597,8 +2661,6 @@ BIF_RETTYPE prim_file_internal_name2native_1(BIF_ALIST_1)
for (i = 0; i < size; i++) {
/* Don't allow null in the middle of filenames... */
if (bytes[i] == 0)
- seen_null = 1;
- else if (seen_null)
goto bin_name_error;
bin_p[i] = bytes[i];
}
@@ -2617,8 +2679,6 @@ BIF_RETTYPE prim_file_internal_name2native_1(BIF_ALIST_1)
while (size--) {
/* Don't allow null in the middle of filenames... */
if (*bytes == 0)
- seen_null = 1;
- else if (seen_null)
goto bin_name_error;
*bin_p++ = *bytes++;
*bin_p++ = 0;
diff --git a/erts/emulator/beam/erl_unicode.h b/erts/emulator/beam/erl_unicode.h
index e01eaa787e..31369fc8f9 100644
--- a/erts/emulator/beam/erl_unicode.h
+++ b/erts/emulator/beam/erl_unicode.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2008-2016. All Rights Reserved.
+ * Copyright Ericsson AB 2008-2018. 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.
@@ -21,4 +21,7 @@
#ifndef _ERL_UNICODE_H
#define _ERL_UNICODE_H
+Uint erts_atom_to_string_length(Eterm atom);
+Eterm erts_atom_to_string(Eterm **hpp, Eterm atom);
+
#endif /* _ERL_UNICODE_H */
diff --git a/erts/emulator/beam/external.c b/erts/emulator/beam/external.c
index 9cc5e71afa..b12a021e41 100644
--- a/erts/emulator/beam/external.c
+++ b/erts/emulator/beam/external.c
@@ -2032,23 +2032,14 @@ static Eterm erts_term_to_binary_int(Process* p, Eterm Term, int level, Uint fla
level = context->s.ec.level;
BUMP_REDS(p, (initial_reds - reds) / TERM_TO_BINARY_LOOP_FACTOR);
if (level == 0 || real_size < 6) { /* We are done */
- ProcBin* pb;
return_normal:
context->s.ec.result_bin = NULL;
context->alive = 0;
- pb = (ProcBin *) HAlloc(p, PROC_BIN_SIZE);
- pb->thing_word = HEADER_PROC_BIN;
- pb->size = real_size;
- pb->next = MSO(p).first;
- MSO(p).first = (struct erl_off_heap_header*)pb;
- pb->val = result_bin;
- pb->bytes = (byte*) result_bin->orig_bytes;
- pb->flags = 0;
- OH_OVERHEAD(&(MSO(p)), pb->size / sizeof(Eterm));
if (context_b && erts_refc_read(&context_b->intern.refc,0) == 0) {
erts_bin_free(context_b);
}
- return make_binary(pb);
+ return erts_build_proc_bin(&MSO(p), HAlloc(p, PROC_BIN_SIZE),
+ result_bin);
}
/* Continue with compression... */
/* To make absolutely sure that zlib does not barf on a reallocated context,
@@ -2105,16 +2096,7 @@ static Eterm erts_term_to_binary_int(Process* p, Eterm Term, int level, Uint fla
result_bin = erts_bin_realloc(context->s.cc.destination_bin,
context->s.cc.dest_len+6);
context->s.cc.destination_bin = NULL;
- pb = (ProcBin *) HAlloc(p, PROC_BIN_SIZE);
- pb->thing_word = HEADER_PROC_BIN;
- pb->size = context->s.cc.dest_len+6;
- pb->next = MSO(p).first;
- MSO(p).first = (struct erl_off_heap_header*)pb;
- pb->val = result_bin;
ASSERT(erts_refc_read(&result_bin->intern.refc, 1));
- pb->bytes = (byte*) result_bin->orig_bytes;
- pb->flags = 0;
- OH_OVERHEAD(&(MSO(p)), pb->size / sizeof(Eterm));
erts_bin_free(context->s.cc.result_bin);
context->s.cc.result_bin = NULL;
context->alive = 0;
@@ -2122,7 +2104,9 @@ static Eterm erts_term_to_binary_int(Process* p, Eterm Term, int level, Uint fla
if (context_b && erts_refc_read(&context_b->intern.refc,0) == 0) {
erts_bin_free(context_b);
}
- return make_binary(pb);
+ return erts_build_proc_bin(&MSO(p),
+ HAlloc(p, PROC_BIN_SIZE),
+ result_bin);
}
default: /* Compression error, revert to uncompressed binary (still in
context) */
@@ -3584,18 +3568,9 @@ dec_term_atom_common:
*objp = make_binary(hb);
} else {
Binary* dbin = erts_bin_nrml_alloc(n);
- ProcBin* pb;
- pb = (ProcBin *) hp;
+
+ *objp = erts_build_proc_bin(factory->off_heap, hp, dbin);
hp += PROC_BIN_SIZE;
- pb->thing_word = HEADER_PROC_BIN;
- pb->size = n;
- pb->next = factory->off_heap->first;
- factory->off_heap->first = (struct erl_off_heap_header*)pb;
- OH_OVERHEAD(factory->off_heap, pb->size / sizeof(Eterm));
- pb->val = dbin;
- pb->bytes = (byte*) dbin->orig_bytes;
- pb->flags = 0;
- *objp = make_binary(pb);
if (ctx) {
int n_limit = reds * B2T_MEMCPY_FACTOR;
if (n > n_limit) {
@@ -3635,18 +3610,9 @@ dec_term_atom_common:
ep += n;
} else {
Binary* dbin = erts_bin_nrml_alloc(n);
- ProcBin* pb;
+ Uint n_copy = n;
- pb = (ProcBin *) hp;
- pb->thing_word = HEADER_PROC_BIN;
- pb->size = n;
- pb->next = factory->off_heap->first;
- factory->off_heap->first = (struct erl_off_heap_header*)pb;
- OH_OVERHEAD(factory->off_heap, pb->size / sizeof(Eterm));
- pb->val = dbin;
- pb->bytes = (byte*) dbin->orig_bytes;
- pb->flags = 0;
- bin = make_binary(pb);
+ bin = erts_build_proc_bin(factory->off_heap, hp, dbin);
hp += PROC_BIN_SIZE;
if (ctx) {
int n_limit = reds * B2T_MEMCPY_FACTOR;
@@ -3654,15 +3620,15 @@ dec_term_atom_common:
ctx->state = B2TDecodeBinary;
ctx->u.dc.remaining_n = n - n_limit;
ctx->u.dc.remaining_bytes = dbin->orig_bytes + n_limit;
- n = n_limit;
+ n_copy = n_limit;
reds = 0;
}
- else
+ else {
reds -= n / B2T_MEMCPY_FACTOR;
+ }
}
- sys_memcpy(dbin->orig_bytes, ep, n);
- ep += n;
- n = pb->size;
+ sys_memcpy(dbin->orig_bytes, ep, n_copy);
+ ep += n_copy;
}
if (bitsize == 8 || n == 0) {
diff --git a/erts/emulator/beam/global.h b/erts/emulator/beam/global.h
index 09207364eb..86e2c351af 100644
--- a/erts/emulator/beam/global.h
+++ b/erts/emulator/beam/global.h
@@ -861,6 +861,7 @@ Eterm erts_new_heap_binary(Process *p, byte *buf, int len, byte** datap);
Eterm erts_new_mso_binary(Process*, byte*, Uint);
Eterm new_binary(Process*, byte*, Uint);
Eterm erts_realloc_binary(Eterm bin, size_t size);
+Eterm erts_build_proc_bin(ErlOffHeap*, Eterm*, Binary*);
/* erl_bif_info.c */
@@ -1122,7 +1123,6 @@ extern int erts_no_line_info;
extern Eterm erts_error_logger_warnings;
extern int erts_initialized;
extern int erts_compat_rel;
-extern int erts_use_sender_punish;
void erl_start(int, char**);
void erts_usage(void);
Eterm erts_preloaded(Process* p);
@@ -1264,7 +1264,7 @@ char* erts_convert_filename_to_wchar(byte* bytes, Uint size,
char *statbuf, size_t statbuf_size,
ErtsAlcType_t alloc_type, Sint* used,
Uint extra_wchars);
-Eterm erts_convert_native_to_filename(Process *p, byte *bytes);
+Eterm erts_convert_native_to_filename(Process *p, size_t size, byte *bytes);
Eterm erts_utf8_to_list(Process *p, Uint num, byte *bytes, Uint sz, Uint left,
Uint *num_built, Uint *num_eaten, Eterm tail);
int erts_utf8_to_latin1(byte* dest, const byte* source, int slen);
diff --git a/erts/emulator/beam/io.c b/erts/emulator/beam/io.c
index 9933c8dda4..2c1b7871c4 100644
--- a/erts/emulator/beam/io.c
+++ b/erts/emulator/beam/io.c
@@ -3384,24 +3384,11 @@ static void deliver_read_message(Port* prt, erts_aint32_t state, Eterm to,
if ((state & ERTS_PORT_SFLG_BINARY_IO) == 0) {
listp = buf_to_intlist(&hp, buf, len, listp);
} else if (buf != NULL) {
- ProcBin* pb;
- Binary* bptr;
-
- bptr = erts_bin_nrml_alloc(len);
+ Binary* bptr = erts_bin_nrml_alloc(len);
sys_memcpy(bptr->orig_bytes, buf, len);
- pb = (ProcBin *) hp;
- pb->thing_word = HEADER_PROC_BIN;
- pb->size = len;
- pb->next = ohp->first;
- ohp->first = (struct erl_off_heap_header*)pb;
- pb->val = bptr;
- pb->bytes = (byte*) bptr->orig_bytes;
- pb->flags = 0;
+ listp = erts_build_proc_bin(ohp, hp, bptr);
hp += PROC_BIN_SIZE;
-
- OH_OVERHEAD(ohp, pb->size / sizeof(Eterm));
- listp = make_binary(pb);
}
/* Prepend the header */
@@ -4204,17 +4191,9 @@ write_port_control_result(int control_flags,
else {
dbin = (ErlDrvBinary *) resp_bufp;
if (dbin->orig_size > ERL_ONHEAP_BIN_LIMIT) {
- ProcBin* pb = (ProcBin *) *hpp;
+ res = erts_build_proc_bin(ohp, *hpp, ErlDrvBinary2Binary(dbin));
*hpp += PROC_BIN_SIZE;
- pb->thing_word = HEADER_PROC_BIN;
- pb->size = dbin->orig_size;
- pb->next = ohp->first;
- ohp->first = (struct erl_off_heap_header *) pb;
- pb->val = ErlDrvBinary2Binary(dbin);
- pb->bytes = (byte*) dbin->orig_bytes;
- pb->flags = 0;
- OH_OVERHEAD(ohp, dbin->orig_size / sizeof(Eterm));
- return make_binary(pb);
+ return res;
}
resp_bufp = dbin->orig_bytes;
resp_size = dbin->orig_size;
@@ -5978,21 +5957,12 @@ driver_deliver_term(Port *prt, Eterm to, ErlDrvTermData* data, int len)
mess = make_binary(hbp);
}
else {
- ProcBin* pbp;
+ Eterm* hp;
Binary* bp = erts_bin_nrml_alloc(size);
ASSERT(bufp);
sys_memcpy((void *) bp->orig_bytes, (void *) bufp, size);
- pbp = (ProcBin *) erts_produce_heap(&factory,
- PROC_BIN_SIZE, HEAP_EXTRA);
- pbp->thing_word = HEADER_PROC_BIN;
- pbp->size = size;
- pbp->next = factory.off_heap->first;
- factory.off_heap->first = (struct erl_off_heap_header*)pbp;
- pbp->val = bp;
- pbp->bytes = (byte*) bp->orig_bytes;
- pbp->flags = 0;
- OH_OVERHEAD(factory.off_heap, pbp->size / sizeof(Eterm));
- mess = make_binary(pbp);
+ hp = erts_produce_heap(&factory, PROC_BIN_SIZE, HEAP_EXTRA);
+ mess = erts_build_proc_bin(factory.off_heap, hp, bp);
}
ptr += 2;
break;
@@ -7715,13 +7685,27 @@ int null_func(void)
int
erl_drv_putenv(const char *key, char *value)
{
- return erts_sys_putenv_raw((char*)key, value);
+ switch (erts_sys_explicit_8bit_putenv((char*)key, value)) {
+ case -1: /* Insufficient buffer space */
+ return 1;
+ case 1: /* Success */
+ return 0;
+ default: /* Not found */
+ return -1;
+ }
}
int
erl_drv_getenv(const char *key, char *value, size_t *value_size)
{
- return erts_sys_getenv_raw((char*)key, value, value_size);
+ switch (erts_sys_explicit_8bit_getenv((char*)key, value, value_size)) {
+ case -1: /* Insufficient buffer space */
+ return 1;
+ case 1: /* Success */
+ return 0;
+ default: /* Not found */
+ return -1;
+ }
}
/* get heart_port
diff --git a/erts/emulator/beam/sys.h b/erts/emulator/beam/sys.h
index bf7d310568..290e0b209a 100644
--- a/erts/emulator/beam/sys.h
+++ b/erts/emulator/beam/sys.h
@@ -636,6 +636,8 @@ typedef struct preload {
*/
typedef Eterm ErtsTracer;
+#include "erl_osenv.h"
+
/*
* This structure contains options to all built in drivers.
* None of the drivers use all of the fields.
@@ -651,8 +653,7 @@ typedef struct _SysDriverOpts {
int hide_window; /* Hide this windows (Windows). */
int exit_status; /* Report exit status of subprocess. */
int overlapped_io; /* Only has effect on windows NT et al */
- char *envir; /* Environment of the port process, */
- /* in Windows format. */
+ erts_osenv_t envir; /* Environment of the port process */
char **argv; /* Argument vector in Unix'ish format. */
char *wd; /* Working directory. */
unsigned spawn_type; /* Bitfield of ERTS_SPAWN_DRIVER |
@@ -782,9 +783,6 @@ void set_break_quit(void (*)(void), void (*)(void));
void os_flavor(char*, unsigned);
void os_version(int*, int*, int*);
-void init_getenv_state(GETENV_STATE *);
-char * getenv_string(GETENV_STATE *);
-void fini_getenv_state(GETENV_STATE *);
#define HAVE_ERTS_CHECK_IO_DEBUG
typedef struct {
@@ -805,20 +803,21 @@ int sys_double_to_chars_ext(double, char*, size_t, size_t);
int sys_double_to_chars_fast(double, char*, int, int, int);
void sys_get_pid(char *, size_t);
-/* erts_sys_putenv() returns, 0 on success and a value != 0 on failure. */
-int erts_sys_putenv(char *key, char *value);
-/* Simple variant used from drivers, raw eightbit interface */
-int erts_sys_putenv_raw(char *key, char *value);
-/* erts_sys_getenv() returns 0 on success (length of value string in
- *size), a value > 0 if value buffer is too small (*size is set to needed
- size), and a value < 0 on failure. */
-int erts_sys_getenv(char *key, char *value, size_t *size);
-/* Simple variant used from drivers, raw eightbit interface */
-int erts_sys_getenv_raw(char *key, char *value, size_t *size);
-/* erts_sys_getenv__() is only allowed to be used in early init phase */
-int erts_sys_getenv__(char *key, char *value, size_t *size);
-/* erst_sys_unsetenv() returns 0 on success and a value != 0 on failure. */
-int erts_sys_unsetenv(char *key);
+/* erl_drv_get/putenv have been implicitly 8-bit for so long that we can't
+ * change them without breaking things on Windows. Their return values are
+ * identical to erts_osenv_get/putenv */
+int erts_sys_explicit_8bit_getenv(char *key, char *value, size_t *size);
+int erts_sys_explicit_8bit_putenv(char *key, char *value);
+
+/* This is identical to erts_sys_explicit_8bit_getenv but falls down to the
+ * host OS implementation instead of erts_osenv. */
+int erts_sys_explicit_host_getenv(char *key, char *value, size_t *size);
+
+const erts_osenv_t *erts_sys_rlock_global_osenv(void);
+void erts_sys_runlock_global_osenv(void);
+
+erts_osenv_t *erts_sys_rwlock_global_osenv(void);
+void erts_sys_rwunlock_global_osenv(void);
/* Easier to use, but not as efficient, environment functions */
char *erts_read_env(char *key);
diff --git a/erts/emulator/beam/utils.c b/erts/emulator/beam/utils.c
index 993585be10..fe9f1c7606 100644
--- a/erts/emulator/beam/utils.c
+++ b/erts/emulator/beam/utils.c
@@ -4360,15 +4360,20 @@ erts_read_env(char *key)
char *value = erts_alloc(ERTS_ALC_T_TMP, value_len);
int res;
while (1) {
- res = erts_sys_getenv_raw(key, value, &value_len);
- if (res <= 0)
- break;
- value = erts_realloc(ERTS_ALC_T_TMP, value, value_len);
+ res = erts_sys_explicit_8bit_getenv(key, value, &value_len);
+
+ if (res >= 0) {
+ break;
+ }
+
+ value = erts_realloc(ERTS_ALC_T_TMP, value, value_len);
}
- if (res != 0) {
- erts_free(ERTS_ALC_T_TMP, value);
- return NULL;
+
+ if (res != 1) {
+ erts_free(ERTS_ALC_T_TMP, value);
+ return NULL;
}
+
return value;
}