1 /* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 /*
3  *     Copyright 2016 Couchbase, Inc
4  *
5  *   Licensed under the Apache License, Version 2.0 (the "License");
6  *   you may not use this file except in compliance with the License.
7  *   You may obtain a copy of the License at
8  *
9  *       http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *   Unless required by applicable law or agreed to in writing, software
12  *   distributed under the License is distributed on an "AS IS" BASIS,
13  *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *   See the License for the specific language governing permissions and
15  *   limitations under the License.
16  */
17 #pragma once
18 
19 #include <algorithm>
20 #include <cstdint>
21 #include <cstdio>
22 #include <memory>
23 #include <string>
24 #include <vector>
25 
26 #include <platform/dirutils-visibility.h>
27 
28 namespace cb {
29 namespace io {
30 
31 #ifdef WIN32
32 const char DirectorySeparator{'\\'};
33 #else
34 const char DirectorySeparator{'/'};
35 #endif
36 
37 /**
38  * Return the directory part of an absolute path
39  */
40 DIRUTILS_PUBLIC_API
41 std::string dirname(const std::string& dir);
42 
43 /**
44  * Return the filename part of an absolute path
45  */
46 DIRUTILS_PUBLIC_API
47 std::string basename(const std::string& name);
48 
49 /**
50  * Return a vector containing all of the files starting with a given
51  * name stored in a given directory
52  */
53 DIRUTILS_PUBLIC_API
54 std::vector<std::string> findFilesWithPrefix(const std::string& dir,
55                                              const std::string& name);
56 
57 /**
58  * Return a vector containing all of the files starting with a given
59  * name specified with this absolute path
60  */
61 DIRUTILS_PUBLIC_API
62 std::vector<std::string> findFilesWithPrefix(const std::string& name);
63 
64 /**
65  * Return a vector containing all of the files containing a given
66  * substring located in a given directory
67  */
68 DIRUTILS_PUBLIC_API
69 std::vector<std::string> findFilesContaining(const std::string& dir,
70                                              const std::string& name);
71 
72 /**
73  * Delete a file or directory (including subdirectories)
74  * @param path path of the file or directory that is being removed
75  * @throws system_error in case of any errors during deletion
76  */
77 DIRUTILS_PUBLIC_API
78 void rmrf(const std::string& path);
79 
80 /**
81  * Check if a directory exists or not
82  */
83 DIRUTILS_PUBLIC_API
84 bool isDirectory(const std::string& directory);
85 
86 /**
87  * Check if a path exists and is a file
88  */
89 DIRUTILS_PUBLIC_API
90 bool isFile(const std::string& file);
91 
92 /**
93  * Try to create directory including all of the parent directories
94  *
95  * @param directory the directory to create
96  * @throws std::runtime_error if an error occurs
97  */
98 DIRUTILS_PUBLIC_API
99 void mkdirp(const std::string& directory);
100 
101 /**
102  * Create a unique temporary file with the given prefix.
103  *
104  * This method is implemented by using cb_mktemp, but the caller
105  * does not need to add the XXXXXX in the filename.
106  *
107  * @param prefix The prefix to use in the filename.
108  * @return The unique filename
109  */
110 DIRUTILS_PUBLIC_API
111 std::string mktemp(const std::string& prefix);
112 
113 /**
114  * Create a unique temporary directory with the given prefix.
115  *
116  * It works similar to mktemp
117  *
118  * @param prefix The prefix to use in the directory name.
119  * @return The unique directory name
120  */
121 DIRUTILS_PUBLIC_API
122 std::string mkdtemp(const std::string& prefix);
123 
124 /**
125  * Get the name of the current working directory
126  *
127  * @return the name of the current working directory
128  * @throws std::system_error if we fail to determine the current working
129  *         directory
130  */
131 DIRUTILS_PUBLIC_API
132 std::string getcwd(void);
133 
134 /**
135  * Try to set the maximum number of file descriptors to the requested
136  * limit, and return the number we could get.
137  *
138  * On a Unix system this limit affects files and sockets
139  *
140  * @param limit the requested maximum number of file descriptors
141  * @return the maximum number of file descriptors
142  * @throws std::system_error if we fail to determine the maximum number
143  *         of file descriptor
144  */
145 DIRUTILS_PUBLIC_API
146 uint64_t maximizeFileDescriptors(uint64_t limit);
147 
148 /**
149  * Windows use '\' as the directory separator character (but internally it
150  * allows '/', but I've seen problems where I try to mix '\' and '/' in the
151  * same path. This method replace all occurrences of '/' with '\' on windows.
152  *
153  * @param path the path to sanitize
154  */
sanitizePath(std::string& path)155 inline void sanitizePath(std::string& path) {
156 #ifdef WIN32
157     std::replace(path.begin(), path.end(), '/', '\\');
158 #endif
159 }
160 
161 /**
162  * Load the named file
163  *
164  * @param name the name of the file to load
165  * @return The content of the file
166  * @throws std::system_exception if an error occurs opening / reading the file
167  *         std::bad_alloc for memory allocation errors
168  */
169 DIRUTILS_PUBLIC_API
170 std::string loadFile(const std::string& name);
171 
172 /**
173  * Set the file mode to BINARY
174  *
175  * @param fp the file stream to update
176  * @throws std::system_error if an error occurs
177  */
178 DIRUTILS_PUBLIC_API
179 void setBinaryMode(FILE* fp);
180 
181 /**
182  * A representation for a dynamic loaded library
183  */
184 class LibraryHandle {
185 public:
186     /// Can't be copied
187     LibraryHandle(LibraryHandle&) = delete;
188     virtual ~LibraryHandle();
189 
190     /**
191      * Try to find the named symbol in the library
192      *
193      * @param symbol the symbol to search for
194      * @return pointer to the symbol
195      * @throws std::exception if an error occurrs or the symbol isn't found
196      */
197     template <typename T>
find(const std::string& symbol_name) const198     T find(const std::string& symbol_name) const {
199         return reinterpret_cast<T>(findSymbol(symbol_name));
200     }
201 
202     /// get the name of the loaded library
203     virtual std::string getName() const = 0;
204 
205 protected:
206     virtual void* findSymbol(const std::string& symbol) const = 0;
207     LibraryHandle() = default;
208 };
209 
210 /**
211  * Load a dynamic library
212  *
213  * @param filename The name of the library to load
214  * @return a handle to the loaded library. Closing the library invalidates
215  *         all symbols
216  * @throws std::exception if an error occurs (file not found or missing
217  *                        dependencies / symbols)
218  */
219 DIRUTILS_PUBLIC_API
220 std::unique_ptr<LibraryHandle> loadLibrary(const std::string& filename);
221 } // namespace io
222 } // namespace cb
223