3
3
// SPDX-FileCopyrightText: Copyright (c) 2016-2017 Scott Shawcroft for Adafruit Industries
4
4
//
5
5
// SPDX-License-Identifier: MIT
6
+ #include <stddef.h>
6
7
#include <string.h>
7
8
8
9
#include "py/obj.h"
25
26
#include "shared-bindings/time/__init__.h"
26
27
#include "shared-bindings/supervisor/Runtime.h"
27
28
#include "shared-bindings/supervisor/StatusBar.h"
29
+ #include "shared-bindings/util.h"
28
30
29
31
//| """Supervisor settings"""
30
32
//|
@@ -57,6 +59,7 @@ MP_DEFINE_CONST_FUN_OBJ_0(supervisor_reload_obj, supervisor_reload);
57
59
//| def set_next_code_file(
58
60
//| filename: Optional[str],
59
61
//| *,
62
+ //| working_directory: Optional[str] = None,
60
63
//| reload_on_success: bool = False,
61
64
//| reload_on_error: bool = False,
62
65
//| sticky_on_success: bool = False,
@@ -99,6 +102,7 @@ MP_DEFINE_CONST_FUN_OBJ_0(supervisor_reload_obj, supervisor_reload);
99
102
static mp_obj_t supervisor_set_next_code_file (size_t n_args , const mp_obj_t * pos_args , mp_map_t * kw_args ) {
100
103
static const mp_arg_t allowed_args [] = {
101
104
{ MP_QSTR_filename , MP_ARG_REQUIRED | MP_ARG_OBJ , {.u_rom_obj = mp_const_none } },
105
+ { MP_QSTR_working_directory , MP_ARG_KW_ONLY | MP_ARG_OBJ , {.u_rom_obj = mp_const_none } },
102
106
{ MP_QSTR_reload_on_success , MP_ARG_KW_ONLY | MP_ARG_BOOL , {.u_bool = false} },
103
107
{ MP_QSTR_reload_on_error , MP_ARG_KW_ONLY | MP_ARG_BOOL , {.u_bool = false} },
104
108
{ MP_QSTR_sticky_on_success , MP_ARG_KW_ONLY | MP_ARG_BOOL , {.u_bool = false} },
@@ -107,6 +111,7 @@ static mp_obj_t supervisor_set_next_code_file(size_t n_args, const mp_obj_t *pos
107
111
};
108
112
struct {
109
113
mp_arg_val_t filename ;
114
+ mp_arg_val_t working_directory ;
110
115
mp_arg_val_t reload_on_success ;
111
116
mp_arg_val_t reload_on_error ;
112
117
mp_arg_val_t sticky_on_success ;
@@ -118,6 +123,11 @@ static mp_obj_t supervisor_set_next_code_file(size_t n_args, const mp_obj_t *pos
118
123
if (!mp_obj_is_str_or_bytes (filename_obj ) && filename_obj != mp_const_none ) {
119
124
mp_raise_TypeError_varg (MP_ERROR_TEXT ("%q must be of type %q or %q, not %q" ), MP_QSTR_filename , MP_QSTR_str , MP_QSTR_None , mp_obj_get_type (filename_obj )-> name );
120
125
}
126
+
127
+ mp_obj_t working_directory_obj = args .working_directory .u_obj ;
128
+ if (!mp_obj_is_str_or_bytes (working_directory_obj ) && working_directory_obj != mp_const_none ) {
129
+ mp_raise_TypeError_varg (MP_ERROR_TEXT ("%q must be of type %q or %q, not %q" ), MP_QSTR_working_directory , MP_QSTR_str , MP_QSTR_None , mp_obj_get_type (working_directory_obj )-> name );
130
+ }
121
131
if (filename_obj == mp_const_none ) {
122
132
filename_obj = mp_const_empty_bytes ;
123
133
}
@@ -139,18 +149,50 @@ static mp_obj_t supervisor_set_next_code_file(size_t n_args, const mp_obj_t *pos
139
149
}
140
150
size_t len ;
141
151
const char * filename = mp_obj_str_get_data (filename_obj , & len );
152
+ if (!path_exists (filename )) {
153
+ mp_raise_ValueError (MP_ERROR_TEXT ("File not found" ));
154
+ }
155
+
156
+ size_t working_directory_len = 0 ;
157
+ const char * working_directory = NULL ;
158
+ if (working_directory_obj != mp_const_none ) {
159
+ working_directory = mp_obj_str_get_data (working_directory_obj , & working_directory_len );
160
+ if (!path_exists (working_directory )) {
161
+ mp_raise_ValueError_varg (MP_ERROR_TEXT ("Invalid %q" ), MP_QSTR_working_directory );
162
+ }
163
+ }
142
164
if (next_code_configuration != NULL ) {
143
165
port_free (next_code_configuration );
144
166
next_code_configuration = NULL ;
145
167
}
146
168
if (options != 0 || len != 0 ) {
147
- next_code_configuration = port_malloc (sizeof (supervisor_next_code_info_t ) + len + 1 , false);
169
+
170
+ size_t next_code_size = sizeof (supervisor_next_code_info_t ) + len + 1 ;
171
+ if (working_directory_len > 0 ) {
172
+ next_code_size += working_directory_len + 1 ;
173
+ }
174
+ next_code_configuration = port_malloc (next_code_size , false);
148
175
if (next_code_configuration == NULL ) {
149
- m_malloc_fail (sizeof (supervisor_next_code_info_t ) + len + 1 );
176
+ m_malloc_fail (next_code_size );
177
+ }
178
+ char * filename_ptr = (char * )next_code_configuration + sizeof (supervisor_next_code_info_t );
179
+
180
+ // Copy filename
181
+ memcpy (filename_ptr , filename , len );
182
+ filename_ptr [len ] = '\0' ;
183
+
184
+ char * working_directory_ptr = NULL ;
185
+ // Copy working directory after filename if present
186
+ if (working_directory_len > 0 ) {
187
+ working_directory_ptr = filename_ptr + len + 1 ;
188
+ memcpy (working_directory_ptr , working_directory , working_directory_len );
189
+ working_directory_ptr [working_directory_len ] = '\0' ;
150
190
}
191
+ // Set everything up last. We may have raised an exception early and we
192
+ // don't want to free the memory if we failed.
193
+ next_code_configuration -> filename = filename_ptr ;
194
+ next_code_configuration -> working_directory = working_directory_ptr ;
151
195
next_code_configuration -> options = options | SUPERVISOR_NEXT_CODE_OPT_NEWLY_SET ;
152
- memcpy (& next_code_configuration -> filename , filename , len );
153
- next_code_configuration -> filename [len ] = '\0' ;
154
196
}
155
197
return mp_const_none ;
156
198
}
0 commit comments