Skip to content

Commit

Permalink
Use a single macro in the ARGS line of primitives to indicate a Windo…
Browse files Browse the repository at this point in the history
…ws path (#1400)

Instead of using argv[0] to get the executable.
  • Loading branch information
Erik Corry authored Feb 6, 2023
1 parent c6a9e94 commit 5038479
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 28 deletions.
18 changes: 18 additions & 0 deletions src/primitive.h
Original file line number Diff line number Diff line change
Expand Up @@ -893,6 +893,24 @@ namespace toit {
Blob name; \
if (!_raw_##name->byte_content(process->program(), &name, STRINGS_ONLY)) WRONG_TYPE;

// Filesystem primitives should generally use this, since the chdir primitive
// merely changes a string representing the current directory.
#define BLOB_TO_ABSOLUTE_PATH(result, blob) \
if (blob.length() == 0) INVALID_ARGUMENT; \
WideCharAllocationManager allocation_##result(process); \
wchar_t* wchar_##result = allocation_##result.to_wcs(&blob); \
wchar_t result[MAX_PATH]; \
auto error_##result = get_absolute_path(process, wchar_##result, result); \
if (error_##result) return error_##result

HeapObject* get_absolute_path(Process* process, const wchar_t* pathname, wchar_t* output, const wchar_t* used_for_relative = null);

#define _A_T_WindowsPath(N, name) \
Object* _raw_##name = __args[-(N)]; \
Blob name##_blob; \
if (!_raw_##name->byte_content(process->program(), &name##_blob, STRINGS_ONLY)) WRONG_TYPE; \
BLOB_TO_ABSOLUTE_PATH(name, name##_blob);

#define _A_T_Blob(N, name) \
Object* _raw_##name = __args[-(N)]; \
Blob name; \
Expand Down
37 changes: 9 additions & 28 deletions src/primitive_file_win.cc
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ const wchar_t* current_dir(Process* process) {
return current_directory;
}

HeapObject* get_absolute_path(Process* process, const wchar_t* pathname, wchar_t* output, const wchar_t* used_for_relative = null) {
HeapObject* get_absolute_path(Process* process, const wchar_t* pathname, wchar_t* output, const wchar_t* used_for_relative) {
size_t pathname_length = wcslen(pathname);

// Poor man's version. For better platform handling, use PathCchAppendEx.
Expand Down Expand Up @@ -144,18 +144,8 @@ HeapObject* get_absolute_path(Process* process, const wchar_t* pathname, wchar_t
return null;
}

// Filesystem primitives should generally use this, since the chdir primitive
// merely changes a string representing the current directory.
#define BLOB_TO_ABSOLUTE_PATH(result, blob) \
WideCharAllocationManager allocation_##result(process); \
wchar_t* wchar_##result = allocation_##result.to_wcs(&blob); \
wchar_t result[MAX_PATH]; \
auto error_##result = get_absolute_path(process, wchar_##result, result); \
if (error_##result) return error_##result

PRIMITIVE(open) {
ARGS(StringOrSlice, pathname, int, flags, int, mode);
BLOB_TO_ABSOLUTE_PATH(path, pathname);
ARGS(WindowsPath, path, int, flags, int, mode);

int os_flags = _O_BINARY;
if ((flags & FILE_RDWR) == FILE_RDONLY) os_flags |= _O_RDONLY;
Expand Down Expand Up @@ -212,8 +202,7 @@ PRIMITIVE(opendir) {
}

PRIMITIVE(opendir2) {
ARGS(SimpleResourceGroup, group, StringOrSlice, pathname);
BLOB_TO_ABSOLUTE_PATH(path, pathname);
ARGS(SimpleResourceGroup, group, WindowsPath, path);

ByteArray* proxy = process->object_heap()->allocate_proxy();
if (proxy == null) ALLOCATION_FAILED;
Expand Down Expand Up @@ -351,8 +340,7 @@ Object* time_stamp(Process* process, time_t time) {
// Returns null for entries that do not exist.
// Otherwise returns an array with indices from the FILE_ST_xxx constants.
PRIMITIVE(stat) {
ARGS(StringOrSlice, pathname, bool, follow_links);
BLOB_TO_ABSOLUTE_PATH(path, pathname);
ARGS(WindowsPath, path, bool, follow_links);

USE(follow_links);

Expand Down Expand Up @@ -405,35 +393,29 @@ PRIMITIVE(stat) {
}

PRIMITIVE(unlink) {
ARGS(StringOrSlice, pathname);
BLOB_TO_ABSOLUTE_PATH(path, pathname);
ARGS(WindowsPath, path);

int result = _wunlink(path);
if (result < 0) return return_open_error(process, errno);
return process->program()->null_object();
}

PRIMITIVE(rmdir) {
ARGS(StringOrSlice, pathname);
BLOB_TO_ABSOLUTE_PATH(path, pathname);
ARGS(WindowsPath, path);

if (RemoveDirectoryW(path) == 0) WINDOWS_ERROR;
return process->program()->null_object();
}

PRIMITIVE(rename) {
ARGS(StringOrSlice, old_name_blob, StringOrSlice, new_name_blob);
BLOB_TO_ABSOLUTE_PATH(old_name, old_name_blob);
BLOB_TO_ABSOLUTE_PATH(new_name, new_name_blob);
ARGS(WindowsPath, old_name, WindowsPath, new_name);
int result = _wrename(old_name, new_name);
if (result < 0) return return_open_error(process, errno);
return process->program()->null_object();
}

PRIMITIVE(chdir) {
ARGS(StringOrSlice, pathname);
if (pathname.length() == 0) INVALID_ARGUMENT;
BLOB_TO_ABSOLUTE_PATH(path, pathname);
ARGS(WindowsPath, path);

struct stat64 statbuf{};
int result = _wstat64(path, &statbuf);
Expand All @@ -448,8 +430,7 @@ PRIMITIVE(chdir) {
}

PRIMITIVE(mkdir) {
ARGS(StringOrSlice, pathname, int, mode);
BLOB_TO_ABSOLUTE_PATH(path, pathname);
ARGS(WindowsPath, path, int, mode);

int result = CreateDirectoryW(path, NULL);
if (result == 0) WINDOWS_ERROR;
Expand Down
2 changes: 2 additions & 0 deletions src/resources/pipe_win.cc
Original file line number Diff line number Diff line change
Expand Up @@ -454,6 +454,8 @@ static Object* fork_helper(
if (!arguments->at(i)->byte_content(process->program(), &argument, STRINGS_ONLY)) {
WRONG_TYPE;
}
// TODO: Escape quotes and backslashes in arguments. See
// https://stackoverflow.com/questions/31838469/how-do-i-convert-argv-to-lpcommandline-parameter-of-createprocess
if (memchr(argument.address(), ' ', argument.length()) != NULL) {
format = (i != arguments->length() - 1) ? L"\"%ls\" " : L"\"%ls\"";
} else {
Expand Down

0 comments on commit 5038479

Please sign in to comment.