Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update nob_file_exists to distinguish between errors on windows. #72

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
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
78 changes: 61 additions & 17 deletions src/nob.h
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ int nob_file_exists(const char *file_path);

// TODO: add MinGW support for Go Rebuild Urself™ Technology
#ifndef NOB_REBUILD_URSELF
# if _WIN32
# ifdef _WIN32
# if defined(__GNUC__)
# define NOB_REBUILD_URSELF(binary_path, source_path) "gcc", "-o", binary_path, source_path
# elif defined(__clang__)
Expand All @@ -235,6 +235,24 @@ int nob_file_exists(const char *file_path);
# endif
#endif

#ifdef _WIN32
// utility function
// returns a pointer to a human readable string with the name of the last windows error (GetLastError())
// YOU need to LocalFree( result ) after you're done with it! (just see how it's used below)
char* nob_get_last_windows_error_name()
{
LPTSTR result = NULL;
FormatMessage(
FORMAT_MESSAGE_FROM_SYSTEM
|FORMAT_MESSAGE_ALLOCATE_BUFFER
|FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&result, 0, NULL);
return result;
}
#endif //_WIN32

// Go Rebuild Urself™ Technology
//
// How to use it:
Expand Down Expand Up @@ -402,7 +420,9 @@ bool nob_copy_file(const char *src_path, const char *dst_path)
nob_log(NOB_INFO, "copying %s -> %s", src_path, dst_path);
#ifdef _WIN32
if (!CopyFile(src_path, dst_path, FALSE)) {
nob_log(NOB_ERROR, "Could not copy file: %lu", GetLastError());
LPTSTR errorText = nob_get_last_windows_error_name();
nob_log(NOB_ERROR, "Could not copy file: %s", errorText);
LocalFree(errorText);
return false;
}
return true;
Expand Down Expand Up @@ -514,7 +534,9 @@ Nob_Proc nob_cmd_run_async(Nob_Cmd cmd)
nob_sb_free(sb);

if (!bSuccess) {
nob_log(NOB_ERROR, "Could not create child process: %lu", GetLastError());
LPTSTR errorText = nob_get_last_windows_error_name();
nob_log(NOB_ERROR, "Could not create child process: %s", errorText);
LocalFree(errorText);
return NOB_INVALID_PROC;
}

Expand Down Expand Up @@ -566,18 +588,22 @@ bool nob_proc_wait(Nob_Proc proc)
);

if (result == WAIT_FAILED) {
nob_log(NOB_ERROR, "could not wait on child process: %lu", GetLastError());
LPTSTR errorText = nob_get_last_windows_error_name();
nob_log(NOB_ERROR, "Could not wait on child process: %s", errorText);
LocalFree(errorText);
return false;
}

DWORD exit_status;
if (!GetExitCodeProcess(proc, &exit_status)) {
nob_log(NOB_ERROR, "could not get process exit code: %lu", GetLastError());
LPTSTR errorText = nob_get_last_windows_error_name();
nob_log(NOB_ERROR, "Could not get process exit code: %s", errorText);
LocalFree(errorText);
return false;
}

if (exit_status != 0) {
nob_log(NOB_ERROR, "command exited with exit code %lu", exit_status);
nob_log(NOB_ERROR, "Command exited with exit code: %d", exit_status);
return false;
}

Expand Down Expand Up @@ -716,7 +742,9 @@ Nob_File_Type nob_get_file_type(const char *path)
#ifdef _WIN32
DWORD attr = GetFileAttributesA(path);
if (attr == INVALID_FILE_ATTRIBUTES) {
nob_log(NOB_ERROR, "Could not get file attributes of %s: %lu", path, GetLastError());
LPTSTR errorText = nob_get_last_windows_error_name();
nob_log(NOB_ERROR, "Could not get file attributes of %s: %s", path, errorText);
LocalFree(errorText);
return -1;
}

Expand Down Expand Up @@ -872,14 +900,18 @@ int nob_needs_rebuild(const char *output_path, const char **input_paths, size_t
if (output_path_fd == INVALID_HANDLE_VALUE) {
// NOTE: if output does not exist it 100% must be rebuilt
if (GetLastError() == ERROR_FILE_NOT_FOUND) return 1;
nob_log(NOB_ERROR, "Could not open file %s: %lu", output_path, GetLastError());
LPTSTR errorText = nob_get_last_windows_error_name();
nob_log(NOB_ERROR, "Could not open file %s: %s", output_path, errorText);
LocalFree(errorText);
return -1;
}
FILETIME output_path_time;
bSuccess = GetFileTime(output_path_fd, NULL, NULL, &output_path_time);
CloseHandle(output_path_fd);
if (!bSuccess) {
nob_log(NOB_ERROR, "Could not get time of %s: %lu", output_path, GetLastError());
LPTSTR errorText = nob_get_last_windows_error_name();
nob_log(NOB_ERROR, "Could not open file %s: %s", output_path, errorText);
LocalFree(errorText);
return -1;
}

Expand All @@ -888,14 +920,18 @@ int nob_needs_rebuild(const char *output_path, const char **input_paths, size_t
HANDLE input_path_fd = CreateFile(input_path, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL);
if (input_path_fd == INVALID_HANDLE_VALUE) {
// NOTE: non-existing input is an error cause it is needed for building in the first place
nob_log(NOB_ERROR, "Could not open file %s: %lu", input_path, GetLastError());
LPTSTR errorText = nob_get_last_windows_error_name();
nob_log(NOB_ERROR, "Could not open file %s: %s", input_path, errorText);
LocalFree(errorText);
return -1;
}
FILETIME input_path_time;
bSuccess = GetFileTime(input_path_fd, NULL, NULL, &input_path_time);
CloseHandle(input_path_fd);
if (!bSuccess) {
nob_log(NOB_ERROR, "Could not get time of %s: %lu", input_path, GetLastError());
LPTSTR errorText = nob_get_last_windows_error_name();
nob_log(NOB_ERROR, "Could not get time of %s: %s", input_path, errorText);
LocalFree(errorText);
return -1;
}

Expand Down Expand Up @@ -938,15 +974,17 @@ int nob_needs_rebuild1(const char *output_path, const char *input_path)

bool nob_rename(const char *old_path, const char *new_path)
{
nob_log(NOB_INFO, "renaming %s -> %s", old_path, new_path);
nob_log(NOB_INFO, "Renaming %s -> %s", old_path, new_path);
#ifdef _WIN32
if (!MoveFileEx(old_path, new_path, MOVEFILE_REPLACE_EXISTING)) {
nob_log(NOB_ERROR, "could not rename %s to %s: %lu", old_path, new_path, GetLastError());
LPTSTR errorText = nob_get_last_windows_error_name();
nob_log(NOB_ERROR, "Could not rename %s to %s: %s", old_path, new_path, errorText);
LocalFree(errorText);
return false;
}
#else
if (rename(old_path, new_path) < 0) {
nob_log(NOB_ERROR, "could not rename %s to %s: %s", old_path, new_path, strerror(errno));
nob_log(NOB_ERROR, "Could not rename %s to %s: %s", old_path, new_path, strerror(errno));
return false;
}
#endif // _WIN32
Expand Down Expand Up @@ -1054,10 +1092,16 @@ bool nob_sv_eq(Nob_String_View a, Nob_String_View b)
// -1 - error while checking if file exists. The error is logged
int nob_file_exists(const char *file_path)
{
#if _WIN32
// TODO: distinguish between "does not exists" and other errors
#ifdef _WIN32
DWORD dwAttrib = GetFileAttributesA(file_path);
return dwAttrib != INVALID_FILE_ATTRIBUTES;
if (dwAttrib == INVALID_FILE_ATTRIBUTES) {
if (GetLastError() == ERROR_FILE_NOT_FOUND) return 0;
LPTSTR errorText = nob_get_last_windows_error_name();
nob_log(NOB_ERROR, "Could not check if file %s exists: %s", file_path, errorText);
LocalFree(errorText);
return -1;
}
return 1;
#else
struct stat statbuf;
if (stat(file_path, &statbuf) < 0) {
Expand Down