@mikrojs/native 0.21.0-pr-431.20260920213100 → 0.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -21,3 +21,14 @@ MIKAppCommitResult mik__app_commit(const char* base, bool erased);
|
|
|
21
21
|
/* Recover from an interrupted commit: restore the rollback copy if the live
|
|
22
22
|
* app is missing, otherwise drop leftover staging/rollback dirs. */
|
|
23
23
|
void mik__app_recover(const char* base);
|
|
24
|
+
|
|
25
|
+
/* Remove a directory tree. Returns true when nothing is left at `path` (also
|
|
26
|
+
* when nothing was there). On failure errno is that of the first entry that
|
|
27
|
+
* could not be removed. Descends at most 32 levels and feeds the watchdog. */
|
|
28
|
+
bool mik__rmdir_recursive(const char* path);
|
|
29
|
+
|
|
30
|
+
/* Create `path` and any missing parents. Returns true when `path` is a
|
|
31
|
+
* directory afterwards. On failure errno is that of the first mkdir that
|
|
32
|
+
* left no directory behind, so a full filesystem reads as ENOSPC here instead
|
|
33
|
+
* of as ENOENT from a later open. */
|
|
34
|
+
bool mik__mkdirs(const char* path);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mikrojs/native",
|
|
3
|
-
"version": "0.21.0
|
|
3
|
+
"version": "0.21.0",
|
|
4
4
|
"description": "Mikro.js C++ runtime library and Node.js native addon",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"esp32",
|
|
@@ -85,14 +85,14 @@
|
|
|
85
85
|
"./runtime/wifi/types": "./runtime/wifi/types.ts"
|
|
86
86
|
},
|
|
87
87
|
"dependencies": {
|
|
88
|
-
"@mikrojs/quickjs": "0.21.0
|
|
88
|
+
"@mikrojs/quickjs": "0.21.0",
|
|
89
89
|
"cmake-js": "^8.0.0",
|
|
90
90
|
"node-addon-api": "^8.9.2",
|
|
91
91
|
"node-gyp-build": "^4.8.4"
|
|
92
92
|
},
|
|
93
93
|
"devDependencies": {
|
|
94
|
-
"@mikrojs/registry": "0.21.0
|
|
95
|
-
"@mikrojs/schema": "0.21.0
|
|
94
|
+
"@mikrojs/registry": "0.21.0",
|
|
95
|
+
"@mikrojs/schema": "0.21.0",
|
|
96
96
|
"@swc/core": "^1.16.2",
|
|
97
97
|
"@types/node": "^24.12.2",
|
|
98
98
|
"esbuild": "^0.28.2",
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/src/mik_app_store.cpp
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
#include "mikrojs/app_store.h"
|
|
2
2
|
|
|
3
3
|
#include <dirent.h>
|
|
4
|
+
#include <errno.h>
|
|
4
5
|
#include <stdio.h>
|
|
5
6
|
#include <string.h>
|
|
6
7
|
#include <sys/stat.h>
|
|
7
8
|
#include <unistd.h>
|
|
8
9
|
|
|
10
|
+
#include "mikrojs/platform.h"
|
|
11
|
+
|
|
9
12
|
namespace {
|
|
10
13
|
|
|
11
14
|
bool path_exists(const char* path) {
|
|
@@ -33,43 +36,86 @@ constexpr int kMaxDepth = 32;
|
|
|
33
36
|
|
|
34
37
|
/* `path` is a mutable buffer of `cap` bytes holding the directory to remove;
|
|
35
38
|
* each level appends into it and truncates on the way out, so a frame costs a
|
|
36
|
-
* few dozen bytes rather than a 512-byte path of its own.
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
39
|
+
* few dozen bytes rather than a 512-byte path of its own. Returns true when
|
|
40
|
+
* the directory is gone; `first_errno` keeps the first failure. */
|
|
41
|
+
bool rmdir_recursive_at(char* path, size_t cap, int depth, int* first_errno) {
|
|
42
|
+
const MIKPlatform* platform = MIK_GetPlatform();
|
|
41
43
|
const size_t base = strlen(path);
|
|
42
|
-
struct dirent* entry;
|
|
43
|
-
while ((entry = readdir(dir)) != NULL) {
|
|
44
|
-
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) continue;
|
|
45
|
-
|
|
46
|
-
const int n = snprintf(path + base, cap - base, "/%s", entry->d_name);
|
|
47
|
-
if (n < 0 || (size_t)n >= cap - base) {
|
|
48
|
-
path[base] = 0; /* would truncate to a different path; skip it */
|
|
49
|
-
continue;
|
|
50
|
-
}
|
|
51
44
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
45
|
+
DIR* dir = opendir(path);
|
|
46
|
+
if (dir) {
|
|
47
|
+
struct dirent* entry;
|
|
48
|
+
while ((entry = readdir(dir)) != NULL) {
|
|
49
|
+
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) continue;
|
|
50
|
+
if (platform->feed_watchdog) platform->feed_watchdog();
|
|
51
|
+
|
|
52
|
+
const int n = snprintf(path + base, cap - base, "/%s", entry->d_name);
|
|
53
|
+
if (n < 0 || (size_t)n >= cap - base) {
|
|
54
|
+
path[base] = 0; /* would truncate to a different path; skip it */
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
struct stat st;
|
|
59
|
+
if (stat(path, &st) == 0 && S_ISDIR(st.st_mode)) {
|
|
60
|
+
if (depth < kMaxDepth) rmdir_recursive_at(path, cap, depth + 1, first_errno);
|
|
61
|
+
} else if (unlink(path) != 0 && *first_errno == 0) {
|
|
62
|
+
*first_errno = errno;
|
|
63
|
+
}
|
|
64
|
+
path[base] = 0;
|
|
57
65
|
}
|
|
58
|
-
|
|
66
|
+
closedir(dir);
|
|
59
67
|
}
|
|
60
|
-
|
|
61
|
-
rmdir(path);
|
|
68
|
+
|
|
69
|
+
if (rmdir(path) == 0) return true;
|
|
70
|
+
if (*first_errno == 0) *first_errno = errno;
|
|
71
|
+
return false;
|
|
62
72
|
}
|
|
63
73
|
|
|
64
|
-
|
|
74
|
+
} // namespace
|
|
75
|
+
|
|
76
|
+
bool mik__rmdir_recursive(const char* path) {
|
|
65
77
|
char buf[512];
|
|
66
78
|
const size_t n = strlen(path);
|
|
67
|
-
if (n >= sizeof(buf))
|
|
79
|
+
if (n >= sizeof(buf)) {
|
|
80
|
+
errno = ENAMETOOLONG;
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
if (!path_exists(path)) return true;
|
|
68
84
|
memcpy(buf, path, n + 1);
|
|
69
|
-
|
|
85
|
+
int first_errno = 0;
|
|
86
|
+
if (rmdir_recursive_at(buf, sizeof(buf), 0, &first_errno)) return true;
|
|
87
|
+
errno = first_errno;
|
|
88
|
+
return false;
|
|
70
89
|
}
|
|
71
90
|
|
|
72
|
-
|
|
91
|
+
bool mik__mkdirs(const char* path) {
|
|
92
|
+
char tmp[512];
|
|
93
|
+
const size_t n = strlen(path);
|
|
94
|
+
if (n == 0 || n >= sizeof(tmp)) {
|
|
95
|
+
errno = n == 0 ? EINVAL : ENAMETOOLONG;
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
98
|
+
memcpy(tmp, path, n + 1);
|
|
99
|
+
|
|
100
|
+
int first_errno = 0;
|
|
101
|
+
for (char* p = tmp + 1;; p++) {
|
|
102
|
+
if (*p != '/' && *p != '\0') continue;
|
|
103
|
+
const char saved = *p;
|
|
104
|
+
*p = '\0';
|
|
105
|
+
if (mkdir(tmp, 0755) != 0 && errno != EEXIST) {
|
|
106
|
+
/* A prefix that is there anyway (a mount point may not answer
|
|
107
|
+
* EEXIST) must not hide the errno of the one that is missing. */
|
|
108
|
+
const int e = errno;
|
|
109
|
+
if (first_errno == 0 && !dir_exists(tmp)) first_errno = e;
|
|
110
|
+
}
|
|
111
|
+
*p = saved;
|
|
112
|
+
if (saved == '\0') break;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
if (dir_exists(path)) return true;
|
|
116
|
+
errno = first_errno ? first_errno : ENOTDIR;
|
|
117
|
+
return false;
|
|
118
|
+
}
|
|
73
119
|
|
|
74
120
|
MIKAppCommitResult mik__app_commit(const char* base, bool erased) {
|
|
75
121
|
char app[512];
|
|
@@ -85,14 +131,14 @@ MIKAppCommitResult mik__app_commit(const char* base, bool erased) {
|
|
|
85
131
|
* leave the live app untouched and just clean up. The original logic
|
|
86
132
|
* would have deleted the live app in this degenerate case. */
|
|
87
133
|
if (!dir_exists(staged_app)) {
|
|
88
|
-
|
|
89
|
-
|
|
134
|
+
mik__rmdir_recursive(old);
|
|
135
|
+
mik__rmdir_recursive(tmp);
|
|
90
136
|
return MIK_APP_COMMIT_OK;
|
|
91
137
|
}
|
|
92
138
|
|
|
93
139
|
/* Atomic swap: staging dir → app dir */
|
|
94
140
|
if (path_exists(app) && !erased) {
|
|
95
|
-
|
|
141
|
+
mik__rmdir_recursive(old);
|
|
96
142
|
if (rename(app, old) != 0) {
|
|
97
143
|
return MIK_APP_COMMIT_STASH_FAILED;
|
|
98
144
|
}
|
|
@@ -105,8 +151,8 @@ MIKAppCommitResult mik__app_commit(const char* base, bool erased) {
|
|
|
105
151
|
return MIK_APP_COMMIT_SWAP_FAILED;
|
|
106
152
|
}
|
|
107
153
|
|
|
108
|
-
|
|
109
|
-
|
|
154
|
+
mik__rmdir_recursive(old);
|
|
155
|
+
mik__rmdir_recursive(tmp);
|
|
110
156
|
return MIK_APP_COMMIT_OK;
|
|
111
157
|
}
|
|
112
158
|
|
|
@@ -125,10 +171,10 @@ void mik__app_recover(const char* base) {
|
|
|
125
171
|
if (!has_app && has_old) {
|
|
126
172
|
rename(old, app);
|
|
127
173
|
} else if (has_old) {
|
|
128
|
-
|
|
174
|
+
mik__rmdir_recursive(old);
|
|
129
175
|
}
|
|
130
176
|
|
|
131
177
|
if (has_tmp) {
|
|
132
|
-
|
|
178
|
+
mik__rmdir_recursive(tmp);
|
|
133
179
|
}
|
|
134
180
|
}
|