Skip to content
This repository was archived by the owner on Aug 31, 2021. It is now read-only.

Commit 0acae79

Browse files
committed
libsystem: Add MCSFileGetType().
Basic ability to distinguish between files and directories, given a path.
1 parent 0617a39 commit 0acae79

4 files changed

Lines changed: 96 additions & 0 deletions

File tree

libfoundation/include/system-file.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,13 @@ bool __MCSFileCreateStream (MCStringRef p_native_path, intenum_t p_mode, MCStrea
112112
* Filesystem operations
113113
* ================================================================ */
114114

115+
enum MCSFileType
116+
{
117+
kMCSFileTypeRegular = (1 << 0),
118+
kMCSFileTypeDirectory = (1 << 1),
119+
kMCSFileTypeSymbolicLink = (1 << 5),
120+
};
121+
115122
/* Delete the file at path. */
116123
MC_DLLEXPORT bool MCSFileDelete (MCStringRef p_path);
117124

@@ -126,12 +133,17 @@ MC_DLLEXPORT bool MCSFileDeleteDirectory (MCStringRef p_path);
126133
* returned list never includes "." and "..". */
127134
MC_DLLEXPORT bool MCSFileGetDirectoryEntries (MCStringRef p_path, MCProperListRef & r_entries);
128135

136+
/* Get the type of the file located at p_path. If p_follow_links is
137+
* true, dereferences symbolic links in p_path. */
138+
MC_DLLEXPORT bool MCSFileGetType (MCStringRef p_path, bool p_follow_links, MCSFileType & r_type);
139+
129140
#ifdef __MCS_INTERNAL_API__
130141

131142
bool __MCSFileDelete (MCStringRef p_native_path);
132143
bool __MCSFileCreateDirectory (MCStringRef p_native_path);
133144
bool __MCSFileDeleteDirectory (MCStringRef p_native_path);
134145
bool __MCSFileGetDirectoryEntries (MCStringRef p_native_path, MCProperListRef & r_entries);
146+
bool __MCSFileGetType (MCStringRef p_native_path, bool p_follow_links, MCSFileType & r_type);
135147

136148
#endif
137149

libfoundation/src/system-file-posix.cpp

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -700,3 +700,43 @@ __MCSFileGetDirectoryEntries (MCStringRef p_native_path,
700700
free (t_raw_entries);
701701
return false;
702702
}
703+
704+
bool
705+
__MCSFileGetType (MCStringRef p_native_path,
706+
bool p_follow_links,
707+
MCSFileType & r_type)
708+
{
709+
/* Get a system path */
710+
MCAutoStringRefAsSysString t_path_sys;
711+
if (!t_path_sys.Lock (p_native_path))
712+
return false;
713+
714+
struct stat t_stat_buf;
715+
int t_stat_result;
716+
717+
if (p_follow_links)
718+
{
719+
t_stat_result = stat (*t_path_sys, &t_stat_buf);
720+
}
721+
else
722+
{
723+
t_stat_result = lstat (*t_path_sys, &t_stat_buf);
724+
}
725+
726+
if (0 != t_stat_result)
727+
{
728+
return __MCSFileThrowIOErrorWithErrno (p_native_path, MCSTR("Failed to stat %{path}: %{description}"), errno);
729+
}
730+
731+
switch (t_stat_buf.st_mode & S_IFMT)
732+
{
733+
case S_IFREG: r_type = kMCSFileTypeRegular; break;
734+
case S_IFDIR: r_type = kMCSFileTypeDirectory; break;
735+
case S_IFLNK: r_type = kMCSFileTypeSymbolicLink; break;
736+
737+
default:
738+
return __MCSFileThrowIOErrorWithErrno (p_native_path, MCSTR("Unsupported file type for %{path}"), EIO);
739+
}
740+
741+
return true;
742+
}

libfoundation/src/system-file-w32.cpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -757,3 +757,38 @@ __MCSFileGetDirectoryEntries (MCStringRef p_native_path,
757757
FindClose (t_find_handle);
758758
return false;
759759
}
760+
761+
bool
762+
__MCSFileGetType (MCStringRef p_native_path,
763+
bool p_follow_links,
764+
MCSFileType & r_type)
765+
{
766+
/* Get a system path */
767+
MCAutoStringRefAsWString t_path_w32;
768+
if (!t_path_w32.Lock (p_native_path))
769+
return false;
770+
771+
DWORD t_attributes = GetFileAttributesW(*t_path_w32);
772+
773+
if (INVALID_FILE_ATTRIBUTES == t_attributes)
774+
{
775+
return __MCSFileThrowIOErrorWithErrorCode (p_native_path, MCSTR("Failed to get attributes from file '%{path}': %{description}"), p_error_code);
776+
}
777+
778+
/* Symbolic links are indicated by the reparse point flag. But the other
779+
* relevant attributes are still present. */
780+
if ((t_attributes & FILE_ATTRIBUTE_REPARSE_POINT) && !p_follow_links)
781+
{
782+
r_type = kMCSFileTypeSymbolicLink;
783+
}
784+
else if (t_attributes & FILE_ATTRIBUTE_DIRECTORY)
785+
{
786+
r_type = kMCSFileTypeDirectory;
787+
}
788+
else
789+
{
790+
r_type = kMCSFileTypeRegular;
791+
}
792+
793+
return true;
794+
}

libfoundation/src/system-file.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,15 @@ MCSFileGetDirectoryEntries (MCStringRef p_path,
197197
NULL);
198198
}
199199

200+
MC_DLLEXPORT_DEF bool
201+
MCSFileGetType (MCStringRef p_path,
202+
bool p_follow_links,
203+
MCSFileType & r_type)
204+
{
205+
MCS_FILE_CONVERT_PATH(p_path, t_native_path);
206+
return __MCSFileGetType(t_native_path, p_follow_links, r_type);
207+
}
208+
200209
/* ================================================================
201210
* Initialization
202211
* ================================================================ */

0 commit comments

Comments
 (0)