Skip to content

Commit a2d97a1

Browse files
committed
wip
1 parent d3ab5a7 commit a2d97a1

File tree

12 files changed

+802
-212
lines changed

12 files changed

+802
-212
lines changed

packages/std/packages/std/manifest.rs

Lines changed: 66 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
use std::{
22
collections::BTreeMap,
3-
io::{Read, Seek},
4-
path::Path,
3+
io::{Read, Seek, Write},
4+
path::{Path, PathBuf},
55
str::FromStr as _,
66
sync::LazyLock,
77
};
88
use tangram_client as tg;
99

10+
use crate::CLOSEST_ARTIFACT_PATH;
11+
1012
/// The magic number used to indicate an executable has a manifest.
1113
pub const MAGIC_NUMBER: &[u8] = b"tangram\0";
1214

@@ -300,49 +302,70 @@ impl Manifest {
300302
.as_ref()
301303
.ok_or_else(|| tg::error!("expected a wrap binary"))?;
302304

305+
tg::cache::cache(tg, tg::cache::Arg {
306+
artifacts: vec![file.id().into(), stub.id().into(), wrap.id().into()]
307+
})
308+
.await
309+
.map_err(|source| tg::error!(!source, "failed to cache artifacts"))?;
310+
311+
// Get their paths on disk.
312+
let path: PathBuf = CLOSEST_ARTIFACT_PATH.clone().into();
313+
let file = path.join(file.id().to_string());
314+
let stub = path.join(stub.id().to_string());
315+
let wrap = path.join(wrap.id().to_string());
316+
317+
// Create a temp file for the manifest.
318+
let mut manifest = tempfile::NamedTempFile::new().map_err(|source| tg::error!(!source, "failed to get temp file"))?;
319+
let output = "/tmp/__wrap_output__";
320+
303321
// Create the manifest file. TODO: asyncify.
304-
let contents = tangram_serialize::to_vec(self)
322+
let contents = serde_json::to_vec(self)
305323
.map_err(|source| tg::error!(!source, "failed to serialize manifest"))?;
306-
let contents = std::io::Cursor::new(contents);
307-
let blob = tg::Blob::with_reader(tg, contents)
308-
.await
309-
.map_err(|source| tg::error!(!source, "failed to create blob"))?;
310-
let manifest = tg::File::with_contents(blob);
311-
manifest
312-
.store(tg)
313-
.await
314-
.map_err(|source| tg::error!(!source, "failed to store manifest file"))?;
315-
316-
let host = std::env::var("TANGRAM_HOST").map_err(|_| tg::error!("expected TANGRAM_HOST to be set"))?;
317-
318-
// Run the build.
319-
let output = tg::build::build(
320-
tg,
321-
tg::build::Arg {
322-
executable: Some(tg::command::Executable::Artifact(
323-
tg::command::ArtifactExecutable {
324-
artifact: wrap.clone().into(),
325-
path: None,
326-
},
327-
)),
328-
args: vec![
329-
tg::Template::with_components(vec![file.clone().into()]).into(),
330-
tg::Template::with_components(vec![manifest.into()]).into(),
331-
tg::Template::with_components(vec![stub.clone().into()]).into(),
332-
],
333-
host: Some(host),
334-
..tg::build::Arg::default()
335-
},
336-
)
337-
.await
338-
.map_err(|source| tg::error!(!source, "failed to embed wrapper"))
339-
.inspect_err(|error| eprintln!("{error:#?}"))?
340-
.try_unwrap_object()
341-
.map_err(|_| tg::error!("expected an object"))?
342-
.try_unwrap_file()
343-
.map_err(|_| tg::error!("expected a file"))?;
344-
345-
Ok(output)
324+
manifest.as_file_mut().write_all(&contents).map_err(|source| tg::error!(!source, "failed to write manifest"))?;
325+
326+
// Run the command.
327+
let success = std::process::Command::new(wrap)
328+
.arg(file)
329+
.arg(manifest.path())
330+
.arg(stub)
331+
.arg(output)
332+
.stdout(std::process::Stdio::inherit())
333+
.stderr(std::process::Stdio::inherit())
334+
.output()
335+
.map_err(|source| tg::error!(!source, "failed to wrap the binary"))?
336+
.status
337+
.success();
338+
if !success {
339+
return Err(tg::error!("failed to run the command"));
340+
}
341+
342+
let bytes = std::fs::read(output).map_err(|source| tg::error!(!source, "failed to read the output"))?;
343+
let cursor = std::io::Cursor::new(bytes);
344+
let blob = tg::Blob::with_reader(tg, cursor).await.map_err(|source| tg::error!(!source, "failed to create blob"))?;
345+
346+
// Obtain the dependencies from the manifest to add to the file.
347+
// NOTE: We know the wrapper file has no dependencies, so there is no need to merge.
348+
let dependencies = self.dependencies();
349+
let dependencies = if dependencies.is_empty() {
350+
None
351+
} else {
352+
Some(dependencies)
353+
};
354+
355+
// Create a file with the new blob and references.
356+
let mut output_file = tg::File::builder(blob).executable(true);
357+
if let Some(dependencies) = dependencies {
358+
output_file = output_file.dependencies(dependencies);
359+
}
360+
let output_file = output_file.build();
361+
362+
#[cfg(feature = "tracing")]
363+
{
364+
let file_id = output_file.id();
365+
tracing::trace!(?file_id, "created wrapper file");
366+
}
367+
368+
Ok(output_file)
346369
}
347370

348371
/// Create a new wrapper from a manifest. Will locate the wrapper file from the `TANGRAM_WRAPPER_ID` environment variable.

packages/std/packages/stub/include/json.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -513,8 +513,6 @@ static int print_json_string (String* string) {
513513
static JsonValue* json_get (JsonObject* object, const char* k) {
514514
while (object) {
515515
if (object->value && cstreq(object->key, k)) {
516-
print_json_string(&object->key);
517-
trace(" == %s?\n", k);
518516
return object->value;
519517
}
520518
object = object->next;
@@ -532,4 +530,4 @@ static uint64_t json_array_len (JsonArray* array) {
532530
len++;
533531
}
534532
return len;
535-
}
533+
}

packages/std/packages/stub/include/manifest.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ typedef struct {
1717
String* preloads;
1818
size_t argc;
1919
String* argv;
20+
size_t interp_argc;
21+
String* interp_argv;
2022
Table env;
2123
} Manifest;
2224

packages/std/packages/stub/include/syscall.h

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,14 @@
1212
#define MAP_FIXED 0x10
1313
#define MAP_FIXED_NOREPLACE 0x100000
1414
#define MAP_FAILED (void*)-1
15-
1615
#define RLIMIT_STACK 3
16+
#define GRND_NONBLOCK 0x01
17+
18+
#define O_RDONLY 00
19+
#define O_WRONLY 01
20+
#define O_RDWR 02
21+
#define O_CREAT 0100
1722

18-
#define O_RDONLY 0
1923
#define SEEK_SET 0
2024
#define SEEK_CUR 1
2125
#define SEEK_END 2
@@ -40,8 +44,8 @@ static inline long write (int fd, const void *buf, size_t count) {
4044
return syscall3(__NR_write, (long)fd, (long)buf, (long)count);
4145
}
4246

43-
static inline int open (const char* path, int mode) {
44-
return (int)syscall2(__NR_open, (long)path, (long)mode);
47+
static inline int open (const char* path, int flags, int mode) {
48+
return (int)syscall3(__NR_open, (long)path, (long)flags, (long)mode);
4549
}
4650

4751
static inline int close (int fd) {
@@ -97,6 +101,10 @@ static inline int stat (const char* pathname, stat_t* statbuf) {
97101
return (int)syscall2(__NR_stat, (long)pathname, (long)statbuf);
98102
}
99103

100-
// static inline int execve (const char* pathname, const char** const argv, const char** envp) {
101-
// return (int)syscall3(__NR_execve, (long)pathname, (long)argv, (long)envp);
102-
// }
104+
static inline long getrandom (void *buf, size_t buflen, unsigned int flags) {
105+
return (long)syscall3(__NR_getrandom, (long)buf, (long)buflen, (long)flags);
106+
}
107+
108+
static inline int execve (char* pathname, char** const argv, char** envp) {
109+
return (int)syscall3(__NR_execve, (long)pathname, (long)argv, (long)envp);
110+
}

packages/std/packages/stub/include/table.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,14 @@ static String lookup (
139139
return empty;
140140
}
141141

142+
static String clookup (
143+
Table* table,
144+
const char* key
145+
) {
146+
String key_ = STRING_LITERAL(key);
147+
return lookup(table, key_);
148+
}
149+
142150
static void clear (
143151
Table* table
144152
) {

packages/std/packages/stub/include/util.h

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,4 +83,79 @@ static bool starts_with (String a, String prefix) {
8383
}
8484
}
8585
return true;
86+
}
87+
88+
static bool cstarts_with (String a, const char* prefix) {
89+
for (size_t n = 0; n < a.len; n++) {
90+
if (!prefix[n]) {
91+
return false;
92+
}
93+
if (a.ptr[n] != prefix[n]) {
94+
return false;
95+
}
96+
}
97+
return true;
98+
}
99+
100+
static String join (Arena* arena, String separator, String* strings, size_t nstrings) {
101+
size_t len = 0;
102+
for (size_t n = 0; n < nstrings; n++) {
103+
len += strings[n].len;
104+
if (n != (nstrings - 1)) {
105+
len += separator.len;
106+
}
107+
}
108+
109+
String out = {0};
110+
out.ptr = ALLOC_N(arena, len + 1, uint8_t);
111+
112+
for (size_t n = 0; n < nstrings; n++) {
113+
if (strings[n].ptr) {
114+
memcpy(out.ptr + out.len, strings[n].ptr, strings[n].len);
115+
out.len += strings[n].len;
116+
if (separator.ptr && n != (nstrings - 1)) {
117+
memcpy(out.ptr + out.len, separator.ptr, separator.len);
118+
out.len += separator.len;
119+
}
120+
}
121+
}
122+
123+
return out;
124+
}
125+
126+
static void reverse (String* s) {
127+
int i = 0;
128+
int j = s->len - 1;
129+
while (i < j) {
130+
char buf = s->ptr[i];
131+
s->ptr[i] = s->ptr[j];
132+
s->ptr[j] = buf;
133+
i++;
134+
j--;
135+
}
136+
}
137+
138+
static void double_to_string (Arena* arena, double d, String* s) {
139+
s->ptr = ALLOC_N(arena, 64, uint8_t);
140+
char sign = d >= 0 ? 0 : '-';
141+
142+
double mag = d >= 0 ? d : -d;
143+
uint64_t whole = (uint64_t)mag;
144+
double frac = d - (double)whole;
145+
ABORT_IF(frac != 0, "only integer numbers are supported");
146+
147+
do {
148+
"012345689"[whole % 10];
149+
whole /= 10;
150+
} while (whole != 0);
151+
152+
if (sign) {
153+
s->ptr[s->len++] = sign;
154+
}
155+
156+
reverse(s);
157+
}
158+
159+
static String clone_str (Arena* arena, String s) {
160+
ABORT("todo");
86161
}

0 commit comments

Comments
 (0)