Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 0 additions & 4 deletions unix/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -394,11 +394,7 @@ int main(int argc, char **argv) {
return usage(argv);
}
} else {
#ifdef __MINGW32__
char *basedir = _fullpath(NULL, argv[a], _MAX_PATH);
#else
char *basedir = realpath(argv[a], NULL);
#endif
if (basedir == NULL) {
fprintf(stderr, "%s: can't open file '%s': [Errno %d] ", argv[0], argv[1], errno);
perror("");
Expand Down
1 change: 1 addition & 0 deletions windows/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ endif
SRC_C = \
unix/main.c \
unix/file.c \
realpath.c \

OBJ = $(PY_O) $(addprefix $(BUILD)/, $(SRC_C:.c=.o))

Expand Down
2 changes: 2 additions & 0 deletions windows/mpconfigport.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,5 @@ typedef const void *machine_const_ptr_t; // must be of pointer size
extern const struct _mp_obj_fun_native_t mp_builtin_open_obj;
#define MICROPY_EXTRA_BUILTINS \
{ MP_OBJ_NEW_QSTR(MP_QSTR_open), (mp_obj_t)&mp_builtin_open_obj },

#include "realpath.h"
42 changes: 42 additions & 0 deletions windows/realpath.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#include <stdlib.h>
#include <errno.h>
#include <io.h>

#ifndef R_OK
#define R_OK 4
#endif

// Make sure a path only has forward slashes.
char *to_unix_path(char *p) {
if (p != NULL) {
char *pp = p;
while (*pp != 0) {
if (*pp == '\\')
*pp = '/';
++pp;
}
}
return p;
}

// Implement realpath() using _fullpath and make it use the same error codes as realpath() on unix.
// Also have it return a path with forward slashes only as some code relies on this,
// but _fullpath() returns backward slashes no matter what.
char *realpath(const char *path, char *resolved_path) {
char *ret = NULL;
if (path == NULL) {
errno = EINVAL;
} else if (access(path, R_OK) == 0) {
ret = resolved_path;
if (ret == NULL)
ret = malloc(_MAX_PATH);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMHO wouldn't

if (resolved_path != NULL) {
    ret = resolved_path;
} else {
    ret = malloc(_MAX_PATH);
}

be slightly cleaner here?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If is always preferred to if/else, unless if gets less efficient than if/else.

The cleanest here IMHO would be avoiding introducing "ret" var and just using resolved_path which is there anyway.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair enough, I just wondered if having to do one less assignment in the resolved_path == NULL case might be more efficient. But optimising low-level C code isn't my area of expertise ;-)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did that first but that ended up with multiple returns statements - I am fine with that, but I had the idea most uPy sources didn't use it. Checked again though, and I was wrong, it's used in multiple places..

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lurch : jumps are the most inefficient on average, and to be avoided. Simple assignments is 1 cycle almost on each CPU.

@stinos: Sure, returns, break, continue are used well and make it much easier to reason about control flow than ladders and ladders of if/else's or same ladders of conditional expressions in if/while.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't realise an if/else jump was more expensive than just an if jump.

if (ret == NULL) {
errno = ENOMEM;
} else {
ret = _fullpath(ret, path, _MAX_PATH);
if (ret == NULL)
errno = EIO;
}
}
return to_unix_path(ret);
}
2 changes: 2 additions & 0 deletions windows/realpath.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@

extern char *realpath(const char *path, char *resolved_path);