Skip to content

Commit 01ee2eb

Browse files
committed
add special-folder to rsutils::os
1 parent 5105b4d commit 01ee2eb

File tree

3 files changed

+183
-0
lines changed

3 files changed

+183
-0
lines changed
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// License: Apache 2.0. See LICENSE file in root directory.
2+
// Copyright(c) 2023 Intel Corporation. All Rights Reserved.
3+
#pragma once
4+
5+
#include <string>
6+
7+
8+
namespace rsutils {
9+
namespace os {
10+
11+
12+
enum class special_folder
13+
{
14+
user_desktop,
15+
user_documents,
16+
user_pictures,
17+
user_videos,
18+
temp_folder,
19+
app_data
20+
};
21+
22+
23+
// Get the path to one of the special folders listed above. These differ based on operating system.
24+
// Meant to be used to append a filename to it: may or may not end with a directory separator slash!
25+
// Throws invalid_argument if an invalid folder was passed in.
26+
// Throws runtime_error on failure.
27+
//
28+
std::string get_special_folder( special_folder );
29+
30+
31+
} // namespace os
32+
} // namespace rsutils

third-party/rsutils/py/pyrsutils.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <rsutils/number/running-average.h>
1111
#include <rsutils/number/stabilized-value.h>
1212
#include <rsutils/os/executable-name.h>
13+
#include <rsutils/os/special-folder.h>
1314

1415

1516
#define NAME pyrsutils
@@ -141,4 +142,13 @@ PYBIND11_MODULE(NAME, m) {
141142
.def( "clear", &stabilized_value::clear )
142143
.def( "to_string", to_string )
143144
.def( "__str__", to_string );
145+
146+
py::enum_< rsutils::os::special_folder >( m, "special_folder" )
147+
.value( "app_data", rsutils::os::special_folder::app_data )
148+
.value( "temp_folder", rsutils::os::special_folder::temp_folder )
149+
.value( "user_desktop", rsutils::os::special_folder::user_desktop )
150+
.value( "user_documents", rsutils::os::special_folder::user_documents )
151+
.value( "user_pictures", rsutils::os::special_folder::user_pictures )
152+
.value( "user_videos", rsutils::os::special_folder::user_videos );
153+
m.def( "get_special_folder", rsutils::os::get_special_folder );
144154
}
Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
// License: Apache 2.0. See LICENSE file in root directory.
2+
// Copyright(c) 2023 Intel Corporation. All Rights Reserved.
3+
4+
#include <rsutils/os/special-folder.h>
5+
#include <rsutils/easylogging/easyloggingpp.h>
6+
7+
#ifdef _WIN32
8+
9+
#include <rsutils/os/hresult.h>
10+
#include <KnownFolders.h>
11+
#include <shlobj.h>
12+
13+
#elif defined __linux__ || defined __APPLE__
14+
15+
#include <unistd.h>
16+
#include <sys/types.h>
17+
#include <pwd.h>
18+
19+
#endif
20+
21+
22+
namespace rsutils {
23+
namespace os {
24+
25+
26+
std::string get_folder_path( special_folder f )
27+
{
28+
std::string res;
29+
#ifdef _WIN32
30+
31+
32+
if( f == special_folder::temp_folder )
33+
{
34+
TCHAR buf[MAX_PATH];
35+
if( GetTempPath( MAX_PATH, buf ) != 0 )
36+
{
37+
char str[1024];
38+
wcstombs( str, buf, 1023 );
39+
res = str;
40+
}
41+
}
42+
else
43+
{
44+
GUID folder;
45+
HRESULT hr;
46+
switch( f )
47+
{
48+
case special_folder::user_desktop:
49+
folder = FOLDERID_Desktop;
50+
break;
51+
case special_folder::user_documents:
52+
folder = FOLDERID_Documents;
53+
// The user's Documents folder location may get overridden, as we know OneDrive does in certain
54+
// circumstances. In such cases, the new function, SHGetKnownFolderPath, does not always return the new
55+
// path, while the deprecated function does.
56+
CHAR path[MAX_PATH];
57+
CHECK_HR( SHGetFolderPathA( NULL, CSIDL_PERSONAL, NULL, 0, path ) );
58+
res = path;
59+
res += "\\";
60+
return res;
61+
case special_folder::user_pictures:
62+
folder = FOLDERID_Pictures;
63+
break;
64+
case special_folder::user_videos:
65+
folder = FOLDERID_Videos;
66+
break;
67+
case special_folder::app_data:
68+
folder = FOLDERID_RoamingAppData;
69+
break;
70+
default:
71+
throw std::invalid_argument( std::string( "Value of f (" ) + std::to_string( (int)f )
72+
+ std::string( ") is not supported" ) );
73+
}
74+
75+
PWSTR folder_path = NULL;
76+
hr = SHGetKnownFolderPath( folder, KF_FLAG_DEFAULT_PATH, NULL, &folder_path );
77+
if( SUCCEEDED( hr ) )
78+
{
79+
char str[1024];
80+
wcstombs( str, folder_path, 1023 );
81+
CoTaskMemFree( folder_path );
82+
res = str;
83+
res += "\\";
84+
}
85+
else
86+
{
87+
throw std::runtime_error( "Failed to get requested special folder" );
88+
}
89+
}
90+
91+
92+
#endif //_WIN32
93+
#if defined __linux__ || defined __APPLE__
94+
if( f == special_folder::temp_folder )
95+
{
96+
const char * tmp_dir = getenv( "TMPDIR" );
97+
res = tmp_dir ? tmp_dir : "/tmp/";
98+
}
99+
else
100+
{
101+
const char * home_dir = getenv( "HOME" );
102+
if( ! home_dir )
103+
{
104+
struct passwd * pw = getpwuid( getuid() );
105+
home_dir = ( pw && pw->pw_dir ) ? pw->pw_dir : "";
106+
}
107+
if( home_dir )
108+
{
109+
res = home_dir;
110+
switch( f )
111+
{
112+
case special_folder::user_desktop:
113+
res += "/Desktop/";
114+
break;
115+
case special_folder::user_documents:
116+
res += "/Documents/";
117+
break;
118+
case special_folder::user_pictures:
119+
res += "/Pictures/";
120+
break;
121+
case special_folder::user_videos:
122+
res += "/Videos/";
123+
break;
124+
case special_folder::app_data:
125+
res += "/.";
126+
break;
127+
default:
128+
throw std::invalid_argument( std::string( "Value of f (" ) + std::to_string( (int)f )
129+
+ std::string( ") is not supported" ) );
130+
}
131+
}
132+
}
133+
134+
135+
#endif // defined __linux__ || defined __APPLE__
136+
return res;
137+
}
138+
139+
140+
} // namespace os
141+
} // namespace rsutils

0 commit comments

Comments
 (0)