-
Notifications
You must be signed in to change notification settings - Fork 193
feat: exists
to return the type of a path
#1026
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
base: master
Are you sure you want to change the base?
Changes from 9 commits
42c839c
8510867
866fddb
aebb335
cd61274
4ec8097
661ec55
dd10b5a
5be9e94
1aa265d
306bc86
a5a340e
2c738a8
2b3f141
9f5655a
1613fb5
e6c6a21
713ed1c
39ab1b7
029860f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
! Illustrate the usage of `exists` | ||
program example_exists | ||
use stdlib_system, only: exists, type_unknown, type_regular_file, & | ||
type_directory, type_symlink | ||
use stdlib_error, only: state_type | ||
implicit none | ||
|
||
type(state_type) :: err | ||
|
||
character(*), parameter :: path = "path" | ||
integer :: t | ||
|
||
t = exists(path, err) | ||
|
||
if (err%error()) then | ||
print *, err%print() | ||
end if | ||
|
||
select case (t) | ||
case (type_unknown); print *, "Unknown type!" | ||
case (type_regular_file); print *, "Regular File!" | ||
case (type_directory); print *, "Directory!" | ||
case (type_symlink); print *, "Symbolic Link!" | ||
end select | ||
end program example_exists | ||
|
||
wassup05 marked this conversation as resolved.
Show resolved
Hide resolved
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,16 +1,44 @@ | ||
#include <stdbool.h> | ||
#include <stddef.h> | ||
#include <sys/stat.h> | ||
#include <sys/types.h> | ||
#include <string.h> | ||
#include <errno.h> | ||
#ifdef _WIN32 | ||
#include <direct.h> | ||
#include <windows.h> | ||
#else | ||
#include <unistd.h> | ||
#endif /* ifdef _WIN32 */ | ||
|
||
// Returns the string describing the meaning of `errno` code (by calling `strerror`). | ||
char* stdlib_strerror(size_t* len){ | ||
// Wrapper to get the string describing a system syscall error. | ||
// Uses `strerr` on unix. | ||
// if `winapi` is `false`, uses the usual `strerr` on windows. | ||
// If `winapi` is `false`, uses `FormatMessage`(from windows.h) on windows. | ||
char* stdlib_strerror(size_t* len, bool winapi){ | ||
|
||
if (winapi) { | ||
#ifdef _WIN32 | ||
LPSTR err = NULL; | ||
DWORD dw = GetLastError(); | ||
|
||
FormatMessage( | ||
FORMAT_MESSAGE_ALLOCATE_BUFFER | | ||
FORMAT_MESSAGE_FROM_SYSTEM | | ||
FORMAT_MESSAGE_IGNORE_INSERTS, | ||
NULL, | ||
dw, | ||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), | ||
(LPSTR) &err, | ||
0, | ||
NULL); | ||
|
||
*len = strlen(err); | ||
return (char*) err; | ||
|
||
#endif /* ifdef _WIN32 */ | ||
} | ||
|
||
char* err = strerror(errno); | ||
*len = strlen(err); | ||
return err; | ||
|
@@ -44,3 +72,50 @@ int stdlib_remove_directory(const char* path){ | |
|
||
return (!code) ? 0 : errno; | ||
} | ||
|
||
// Wrapper to the platform's `stat`(status of path) call. | ||
// Uses `lstat` on unix, `GetFileAttributesA` on windows. | ||
// Returns the `type` of the path, and sets the `stat`(if any errors). | ||
int stdlib_exists(const char* path, int* stat){ | ||
// All the valid types | ||
const int type_unknown = 0; | ||
const int type_regular_file = 1; | ||
const int type_directory = 2; | ||
const int type_symlink = 3; | ||
wassup05 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
int type = type_unknown; | ||
*stat = 0; | ||
|
||
#ifdef _WIN32 | ||
DWORD attrs = GetFileAttributesA(path); | ||
|
||
if (attrs == INVALID_FILE_ATTRIBUTES) { | ||
*stat = (int) GetLastError(); | ||
return type_unknown; | ||
} | ||
|
||
// It is not a directory or a symlink | ||
type = type_regular_file; | ||
|
||
if (attrs & FILE_ATTRIBUTE_REPARSE_POINT) type = type_symlink; | ||
if (attrs & FILE_ATTRIBUTE_DIRECTORY) type = type_directory; | ||
#else | ||
struct stat buf = {0}; | ||
int status; | ||
status = lstat(path, &buf); | ||
|
||
if (status == -1) { | ||
// `lstat` failed | ||
*stat = errno; | ||
return type_unknown; | ||
} | ||
|
||
switch (buf.st_mode & S_IFMT) { | ||
case S_IFREG: type = type_regular_file; break; | ||
case S_IFDIR: type = type_directory; break; | ||
case S_IFLNK: type = type_symlink; break; | ||
default: type = type_unknown; break; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we differentiate between a missing and an invalid object? What do other libraries do in this respect? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think it is possible to do that, because the respective syscalls may error out, then we don't truly know the status of the path, whether it is missing or invalid, also windows only returns There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok so for now, I agree to just leave it |
||
} | ||
#endif /* ifdef _WIN32 */ | ||
return type; | ||
} |
Uh oh!
There was an error while loading. Please reload this page.