3131#include < boost/filesystem.hpp>
3232
3333#include < string>
34+ #ifdef _WIN32
35+ #include < optional>
36+ #include < boost/algorithm/string/replace.hpp>
37+ #endif
3438
3539#ifdef __linux__
3640#include < errno.h>
@@ -131,11 +135,9 @@ bool IsNetworked(unsigned long ft)
131135} // namespace
132136
133137#undef CASE_RET_STRING
134- #endif // __linux__
135138
136139bool IsNetworkedFilesystem (const boost::filesystem::path& path_)
137140{
138- #ifdef __linux__
139141 // Non-DEV builds put user databases in ~/.config/miopen by default; the binary cache is placed
140142 // in ~/.cache/miopen. If these directories do not exist, this is not a problem, because the
141143 // library creates them as needed.
@@ -172,10 +174,6 @@ bool IsNetworkedFilesystem(const boost::filesystem::path& path_)
172174 MIOPEN_LOG_NQI (" Filesystem type at '" << path.string () << " ' is: 0x" << std::hex << stat.f_type
173175 << " '" << Stringize (stat.f_type ) << ' \' ' );
174176 return IsNetworked (stat.f_type );
175- #else
176- std::ignore = path_;
177- return false ;
178- #endif // __linux__
179177}
180178
181179namespace {
@@ -200,4 +198,71 @@ boost::filesystem::path ExpandUser(const std::string& path)
200198 return {ReplaceString (path, " ~" , home_dir)};
201199}
202200
201+ #else
202+
203+ namespace {
204+ std::optional<std::string> GetEnvironmentVariable (const std::string_view name)
205+ {
206+ std::size_t required_size;
207+ getenv_s (&required_size, nullptr , 0 , name.data ());
208+ if (required_size == 0 )
209+ {
210+ return std::nullopt ;
211+ }
212+ // getenv_s returns the required size of a string including '\0' character.
213+ std::string result (required_size - 1 , ' A' );
214+ getenv_s (&required_size, result.data (), required_size, name.data ());
215+ return {result};
216+ }
217+
218+ std::optional<std::pair<std::string::size_type, std::string>>
219+ ReplaceVariable (const std::string& path, std::string_view name, std::size_t offset = 0 )
220+ {
221+ std::vector<std::string> variables{
222+ " $" + std::string{name}, " $env:" + std::string{name}, " %" + std::string{name} + " %" };
223+ for (auto & variable : variables)
224+ {
225+ auto pos{path.find (variable, offset)};
226+ if (pos != std::string::npos)
227+ {
228+ auto result{path};
229+ auto value{GetEnvironmentVariable (name)};
230+ if (!value)
231+ {
232+ // TODO: log warning message that the name used does not
233+ // correspond to an environment variable.
234+ value = boost::filesystem::temp_directory_path ().string ();
235+ }
236+ result.replace (pos, variable.length (), *value);
237+ return {{pos, result}};
238+ }
239+ }
240+ return std::nullopt ;
241+ }
242+ } // namespace
243+
244+ boost::filesystem::path ExpandUser (const std::string& path)
245+ {
246+ auto result{ReplaceVariable (path, " USERPROFILE" )};
247+ if (!result)
248+ {
249+ result = ReplaceVariable (path, " HOME" );
250+ if (!result)
251+ {
252+ result = ReplaceVariable (path, " HOMEDRIVE" );
253+ if (result)
254+ {
255+ result = ReplaceVariable (std::get<1 >(*result), " HOMEPATH" , std::get<0 >(*result));
256+ // TODO: if (not result): log warning message that
257+ // HOMEDRIVE and HOMEPATH work in conjunction, respectively.
258+ }
259+ }
260+ }
261+ return {!result ? path : std::get<1 >(*result)};
262+ }
263+
264+ bool IsNetworkedFilesystem (const boost::filesystem::path&) { return false ; }
265+
266+ #endif
267+
203268} // namespace miopen
0 commit comments