|
| 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