1 // ----------------------------------------------------------------------------
2 // -                        Open3D: www.open3d.org                            -
3 // ----------------------------------------------------------------------------
4 // The MIT License (MIT)
5 //
6 // Copyright (c) 2018 www.open3d.org
7 //
8 // Permission is hereby granted, free of charge, to any person obtaining a copy
9 // of this software and associated documentation files (the "Software"), to deal
10 // in the Software without restriction, including without limitation the rights
11 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 // copies of the Software, and to permit persons to whom the Software is
13 // furnished to do so, subject to the following conditions:
14 //
15 // The above copyright notice and this permission notice shall be included in
16 // all copies or substantial portions of the Software.
17 //
18 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
24 // IN THE SOFTWARE.
25 // ----------------------------------------------------------------------------
26 
27 #include "FileSystem.h"
28 
29 #include <algorithm>
30 #include <cstdio>
31 #include <cstdlib>
32 #ifdef WINDOWS
33 #include <dirent/dirent.h>
34 #include <direct.h>
35 #ifndef PATH_MAX
36 #define PATH_MAX MAX_PATH
37 #endif
38 #else
39 #include <sys/stat.h>
40 #include <dirent.h>
41 #include <unistd.h>
42 #include <limits.h>
43 #endif
44 
45 namespace three{
46 
47 namespace filesystem {
48 
GetFileExtensionInLowerCase(const std::string & filename)49 std::string GetFileExtensionInLowerCase(const std::string &filename)
50 {
51     size_t dot_pos = filename.find_last_of(".");
52     if (dot_pos == std::string::npos || dot_pos == filename.length() - 1) {
53         return "";
54     }
55     std::string filename_ext = filename.substr(dot_pos + 1);
56     if (filename_ext.find_first_of("/\\") != std::string::npos) {
57         return "";
58     }
59     std::transform(filename_ext.begin(), filename_ext.end(),
60             filename_ext.begin(), ::tolower);
61     return filename_ext;
62 }
63 
GetFileNameWithoutExtension(const std::string & filename)64 std::string GetFileNameWithoutExtension(const std::string &filename)
65 {
66     std::string ext = GetFileExtensionInLowerCase(filename);
67     if (ext.length() >= filename.length() - 1) {
68         return "";
69     } else {
70         return filename.substr(0, filename.length() - ext.length() - 1);
71     }
72 }
73 
GetFileNameWithoutDirectory(const std::string & filename)74 std::string GetFileNameWithoutDirectory(const std::string &filename)
75 {
76     size_t slash_pos = filename.find_last_of("/\\");
77     if (slash_pos == std::string::npos) {
78         return filename;
79     } else {
80         return filename.substr(slash_pos + 1);
81     }
82 }
83 
GetFileParentDirectory(const std::string & filename)84 std::string GetFileParentDirectory(const std::string &filename)
85 {
86     size_t slash_pos = filename.find_last_of("/\\");
87     if (slash_pos == std::string::npos) {
88         return "";
89     } else {
90         return filename.substr(0, slash_pos + 1);
91     }
92 }
93 
GetRegularizedDirectoryName(const std::string & directory)94 std::string GetRegularizedDirectoryName(const std::string &directory)
95 {
96     if (directory.back() != '/' && directory.back() != '\\') {
97         return directory + "/";
98     } else {
99         return directory;
100     }
101 }
102 
GetWorkingDirectory()103 std::string GetWorkingDirectory()
104 {
105     char buff[PATH_MAX + 1];
106     getcwd(buff, PATH_MAX + 1);
107     return std::string(buff);
108 }
109 
ChangeWorkingDirectory(const std::string & directory)110 bool ChangeWorkingDirectory(const std::string &directory)
111 {
112     return (chdir(directory.c_str()) == 0);
113 }
114 
DirectoryExists(const std::string & directory)115 bool DirectoryExists(const std::string &directory)
116 {
117     struct stat info;
118     if (stat(directory.c_str(), &info) == -1)
119         return false;
120     return S_ISDIR(info.st_mode);
121 }
122 
MakeDirectory(const std::string & directory)123 bool MakeDirectory(const std::string &directory)
124 {
125 #ifdef WINDOWS
126     return (_mkdir(directory.c_str()) == 0);
127 #else
128     return (mkdir(directory.c_str(), S_IRWXU) == 0);
129 #endif
130 }
131 
MakeDirectoryHierarchy(const std::string & directory)132 bool MakeDirectoryHierarchy(const std::string &directory)
133 {
134     std::string full_path = GetRegularizedDirectoryName(directory);
135     size_t curr_pos = full_path.find_first_of("/\\", 1);
136     while (curr_pos != std::string::npos) {
137         std::string subdir = full_path.substr(0, curr_pos + 1);
138         if (DirectoryExists(subdir) == false) {
139             if (MakeDirectory(subdir) == false) {
140                 return false;
141             }
142         }
143         curr_pos = full_path.find_first_of("/\\", curr_pos + 1);
144     }
145     return true;
146 }
147 
DeleteDirectory(const std::string & directory)148 bool DeleteDirectory(const std::string &directory)
149 {
150 #ifdef WINDOWS
151     return (_rmdir(directory.c_str()) == 0);
152 #else
153     return (rmdir(directory.c_str()) == 0);
154 #endif
155 }
156 
FileExists(const std::string & filename)157 bool FileExists(const std::string &filename)
158 {
159 #ifdef WINDOWS
160     struct _stat64 info;
161     if (_stat64(filename.c_str(), &info) == -1)
162         return false;
163     return S_ISREG(info.st_mode);
164 #else
165     struct stat info;
166     if (stat(filename.c_str(), &info) == -1)
167         return false;
168     return S_ISREG(info.st_mode);
169 #endif
170 }
171 
RemoveFile(const std::string & filename)172 bool RemoveFile(const std::string &filename)
173 {
174     return (std::remove(filename.c_str()) == 0);
175 }
176 
ListFilesInDirectory(const std::string & directory,std::vector<std::string> & filenames)177 bool ListFilesInDirectory(const std::string &directory,
178     std::vector<std::string> &filenames)
179 {
180     if (directory.empty()) {
181         return false;
182     }
183     DIR *dir;
184     struct dirent *ent;
185     struct stat st;
186     dir = opendir(directory.c_str());
187     if (!dir) {
188         return false;
189     }
190     filenames.clear();
191     while ((ent = readdir(dir)) != NULL) {
192         const std::string file_name = ent->d_name;
193         if (file_name[0] == '.')
194             continue;
195         std::string full_file_name = GetRegularizedDirectoryName(directory) +
196                 file_name;
197         if (stat(full_file_name.c_str(), &st) == -1)
198             continue;
199         if (S_ISREG(st.st_mode))
200             filenames.push_back(full_file_name);
201     }
202     closedir(dir);
203     return true;
204 }
205 
ListFilesInDirectoryWithExtension(const std::string & directory,const std::string & extname,std::vector<std::string> & filenames)206 bool ListFilesInDirectoryWithExtension(const std::string &directory,
207         const std::string &extname, std::vector<std::string> &filenames)
208 {
209     std::vector<std::string> all_files;
210     if (ListFilesInDirectory(directory, all_files) == false) {
211         return false;
212     }
213     std::string ext_in_lower = extname;
214     std::transform(ext_in_lower.begin(), ext_in_lower.end(),
215             ext_in_lower.begin(), ::tolower);
216     filenames.clear();
217     for (const auto &fn : all_files) {
218         if (GetFileExtensionInLowerCase(fn) == ext_in_lower) {
219             filenames.push_back(fn);
220         }
221     }
222     return true;
223 }
224 
225 }    // namespace three::filesystem
226 
227 }    // namespace three
228