E-MailRelay
gfile.h
Go to the documentation of this file.
1//
2// Copyright (C) 2001-2024 Graeme Walker <graeme_walker@users.sourceforge.net>
3//
4// This program is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// This program is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with this program. If not, see <http://www.gnu.org/licenses/>.
16// ===
17///
18/// \file gfile.h
19///
20
21#ifndef G_FILE_H
22#define G_FILE_H
23
24#include "gdef.h"
25#include "gpath.h"
26#include "gexception.h"
27#include "gcleanup.h"
28#include "gdatetime.h"
29#include <cstdio> // std::remove(), std::FILE
30#include <new> // std::nothrow
31#include <fstream>
32
33namespace G
34{
35 class File ;
36 class DirectoryIteratorImp ;
37}
38
39//| \class G::File
40/// A simple static class for dealing with files.
41/// \see G::Path, G::FileSystem, G::Directory
42///
44{
45public:
46 G_EXCEPTION( StatError , tx("cannot access file") )
47 G_EXCEPTION( CannotRemove , tx("cannot delete file") )
48 G_EXCEPTION( CannotRename , tx("cannot rename file") )
49 G_EXCEPTION( CannotCopy , tx("cannot copy file") )
50 G_EXCEPTION( CannotMkdir , tx("cannot create directory") )
51 G_EXCEPTION( CannotChmod , tx("cannot chmod file") )
52 G_EXCEPTION( CannotChgrp , tx("cannot chgrp file") )
53 G_EXCEPTION( CannotLink , tx("cannot create symlink") )
54 G_EXCEPTION( CannotCreate , tx("cannot create file") )
55 G_EXCEPTION( CannotReadLink , tx("cannot read symlink") )
56 G_EXCEPTION( SizeOverflow , tx("file size overflow") )
57 G_EXCEPTION( TimeError , tx("cannot get file modification time") )
58 enum class InOut { In , Out } ;
59 enum class InOutAppend { In , Out , Append , OutNoCreate } ;
60 enum class Seek { Start , Current , End } ;
61 class Append /// An overload discriminator for G::File::open().
62 {} ;
63 class Text /// An overload discriminator for G::File::open().
64 {} ;
65 struct CreateExclusive /// An overload discriminator for G::File::open().
66 {} ;
67 struct Stat /// A portable 'struct stat'.
68 {
69 int error {0} ;
70 bool enoent {false} ;
71 bool eaccess {false} ;
72 bool is_dir {false} ;
73 bool is_link {false} ;
74 bool is_executable {false} ;
75 bool is_empty {false} ;
76 std::time_t mtime_s {0} ;
77 unsigned int mtime_us {0} ;
78 unsigned long mode {0} ;
79 unsigned long long size {0} ;
80 unsigned long long blocks {0} ;
81 uid_t uid {0} ; // unix
82 gid_t gid {0} ; // unix
83 bool inherit {false} ; // unix, directory group ownership passed on to new files
84 } ;
85
86 static bool remove( const Path & path , std::nothrow_t ) noexcept ;
87 ///< Deletes the file or directory. Returns false on error.
88
89 static void remove( const Path & path ) ;
90 ///< Deletes the file or directory. Throws an exception on error.
91
92 static bool cleanup( const Cleanup::Arg & path_arg ) noexcept ;
93 ///< Deletes the file. Returns false on error. Used in
94 ///< G::Cleanup handlers:
95
96 static bool rename( const Path & from , const Path & to , std::nothrow_t ) noexcept ;
97 ///< Renames the file. Whether it fails if 'to' already
98 ///< exists depends on the o/s (see also renameOnto()).
99 ///< Returns false on error.
100
101 static void rename( const Path & from , const Path & to , bool ignore_missing = false ) ;
102 ///< Renames the file. Throws on error, but optionally
103 ///< ignores errors caused by a missing 'from' file or
104 ///< missing 'to' directory component.
105
106 static bool renameOnto( const Path & from , const Path & to , std::nothrow_t ) noexcept ;
107 ///< Renames the file, deleting 'to' first if necessary.
108 ///< Returns false on error.
109
110 static bool copy( const Path & from , const Path & to , std::nothrow_t ) ;
111 ///< Copies a file. Returns false on error.
112
113 static void copy( const Path & from , const Path & to ) ;
114 ///< Copies a file.
115
116 static void copy( std::istream & from , std::ostream & to ,
117 std::streamsize limit = 0U , std::size_t block = 0U ) ;
118 ///< Copies a stream with an optional size limit.
119
120 static Path backup( const Path & from , std::nothrow_t ) ;
121 ///< Creates a backup copy of the given file in the same directory and
122 ///< with a lightly-mangled filename. Sets a tight umask. Returns
123 ///< the path of the backup file or the empty path on error.
124
125 static bool copyInto( const Path & from , const Path & to_dir , std::nothrow_t ) ;
126 ///< Copies a file into a directory and does a chmodx()
127 ///< if necessary. Returns false on error.
128
129 static bool mkdirs( const Path & dir , std::nothrow_t , int = 100 ) ;
130 ///< Creates a directory and all necessary parents.
131 ///< Returns false on error, but EEXIST is not
132 ///< an error and chmod errors are also ignored.
133 ///<
134 ///< Note that the EEXIST result is ignored even if
135 ///< the target path already exists as a non-directory.
136 ///< This is a feature not a bug because it can avoid
137 ///< races.
138
139 static void mkdirs( const Path & dir , int = 100 ) ;
140 ///< Creates a directory and all necessary parents.
141 ///< Throws on error, but EEXIST is not an error.
142
143 static bool mkdir( const Path & dir , std::nothrow_t ) ;
144 ///< Creates a directory. Returns false on error
145 ///< (including EEXIST).
146
147 static void mkdir( const Path & dir ) ;
148 ///< Creates a directory. Throws on error (including
149 ///< EEXIST).
150
151 static bool isEmpty( const Path & file , std::nothrow_t ) ;
152 ///< Returns true if the file size is zero.
153 ///< Returns false on error.
154
155 static std::string sizeString( const Path & file ) ;
156 ///< Returns the file's size in string format.
157 ///< Returns the empty string on error.
158
159 static bool exists( const Path & file ) ;
160 ///< Returns true if the file (directory, device etc.)
161 ///< exists. Symlinks are followed. Throws an exception
162 ///< if permission denied or too many symlinks etc.
163
164 static bool exists( const Path & file , std::nothrow_t ) ;
165 ///< Returns true if the file (directory, device etc.)
166 ///< exists. Symlinks are followed. Returns false on error.
167
168 static bool isExecutable( const Path & , std::nothrow_t ) ;
169 ///< Returns true if the path is probably executable by the
170 ///< calling process. Because of portability and implementation
171 ///< difficulties this does not return a definitive result so
172 ///< it should only used for generating warnings on a
173 ///< false return. Returns false on error.
174
175 static bool isLink( const Path & path , std::nothrow_t ) ;
176 ///< Returns true if the path is an existing symlink.
177 ///< Returns false on error.
178
179 static bool isDirectory( const Path & path , std::nothrow_t ) ;
180 ///< Returns true if the path exists() and is a directory.
181 ///< Symlinks are followed. Returns false on error.
182
183 static Stat stat( const Path & path , bool symlink_nofollow = false ) ;
184 ///< Returns a file status structure. Returns with the
185 ///< 'error' field set on error. The 'symlink_nofollow'
186 ///< parameter value is ignored on Windows.
187
188 static SystemTime time( const Path & file ) ;
189 ///< Returns the file's timestamp. Throws on error.
190
191 static SystemTime time( const Path & file , std::nothrow_t ) ;
192 ///< Returns the file's timestamp. Returns SystemTime(0)
193 ///< on error.
194
195 static void chmodx( const Path & file ) ;
196 ///< Makes the file executable. Throws on error.
197
198 static bool chmodx( const Path & file , std::nothrow_t ) ;
199 ///< Makes the file executable.
200
201 static void chmod( const Path & file , const std::string & spec ) ;
202 ///< Sets the file permissions. Throws on error. The
203 ///< spec is a simplified sub-set of the /bin/chmod
204 ///< command syntax. The umask is ignored.
205
206 static void chgrp( const Path & file , const std::string & group ) ;
207 ///< Sets the file group ownership. Throws on error.
208
209 static bool chgrp( const Path & file , const std::string & group , std::nothrow_t ) ;
210 ///< Sets the file group ownership. Returns false on error.
211
212 static bool chgrp( const Path & file , gid_t group_id , std::nothrow_t ) ;
213 ///< Sets the file group ownership. Returns false on error.
214
215 static G::Path readlink( const Path & link ) ;
216 ///< Reads a symlink. Throws on error.
217
218 static G::Path readlink( const Path & link , std::nothrow_t ) ;
219 ///< Reads a symlink. Returns the empty path on error.
220
221 static void link( const Path & target , const Path & new_link ) ;
222 ///< Creates a symlink. If the link already exists but is
223 ///< not not pointing at the correct target then the link
224 ///< is deleted and recreated. Throws on error.
225
226 static bool link( const Path & target , const Path & new_link , std::nothrow_t ) ;
227 ///< Creates a symlink. Returns false on error.
228
229 static bool hardlink( const Path & src , const Path & dst , std::nothrow_t ) ;
230 ///< Creates a hard link. Returns false on error or if
231 ///< not implemented.
232
233 static void create( const Path & ) ;
234 ///< Creates the file if it does not exist. Leaves it
235 ///< alone if it does. Throws on error.
236
237 static int compare( const Path & , const Path & , bool ignore_whitespace = false ) ;
238 ///< Compares the contents of the two files. Returns 0, 1 or -1.
239
240 static void open( std::ofstream & , const Path & ) ;
241 ///< Calls open() on the given output file stream.
242 ///< Uses SH_DENYNO and O_BINARY on windows.
243
244 static void open( std::ofstream & , const Path & , Append ) ;
245 ///< Calls open() on the given output file stream.
246 ///< This overload is for append-on-every-write mode.
247 ///< Uses SH_DENYNO and O_BINARY on windows.
248
249 static void open( std::ofstream & , const Path & , Text ) ;
250 ///< Calls open() on the given output file stream.
251 ///< This overload is for native end-of-line conversion.
252 ///< Uses SH_DENYNO and O_BINARY on windows.
253
254 static void open( std::ifstream & , const Path & ) ;
255 ///< Calls open() on the given input file stream.
256 ///< Uses SH_DENYNO and O_BINARY on windows.
257
258 static void open( std::ifstream & , const Path & , Text ) ;
259 ///< Calls open() on the given input file stream.
260 ///< This overload is for native end-of-line conversion.
261 ///< Uses SH_DENYNO and O_BINARY on windows.
262
263 static std::filebuf * open( std::filebuf & , const Path & , InOut ) ;
264 ///< Calls open() on the given filebuf. Returns the address
265 ///< of the given filebuf, or nullptr on failure.
266 ///< Uses SH_DENYNO and O_BINARY on windows.
267
268 static int open( const Path & , InOutAppend , bool windows_inherit = false ) noexcept ;
269 ///< Opens a file descriptor. Returns -1 on error.
270 ///< Uses SH_DENYNO, O_BINARY and optionally O_NOINHERIT
271 ///< on windows. The inherit flag is ignored on unix.
272
273 static int open( const Path & , CreateExclusive ) noexcept ;
274 ///< Creates a file and returns a writable file descriptor.
275 ///< Fails if the file already exists. Returns -1 on error.
276 ///< Uses SH_DENYNO and O_BINARY on windows.
277
278 static std::FILE * fopen( const Path & , const char * mode ) noexcept ;
279 ///< Calls std::fopen().
280
281 static bool probe( const Path & ) noexcept ;
282 ///< Creates and deletes a temporary probe file. Fails if
283 ///< the file already exists. Returns false on error.
284
285 static ssize_t read( int fd , char * , std::size_t ) noexcept ;
286 ///< Calls ::read() or equivalent.
287
288 static ssize_t write( int fd , const char * , std::size_t ) noexcept ;
289 ///< Calls ::write() or equivalent.
290
291 static void close( int fd ) noexcept ;
292 ///< Calls ::close() or equivalent.
293
294 static std::streamoff seek( int fd , std::streamoff offset , Seek ) noexcept ;
295 ///< Does ::lseek() or equivalent.
296
297 static void setNonBlocking( int fd ) noexcept ;
298 ///< Sets the file descriptor to non-blocking mode.
299
300public:
301 File() = delete ;
302 // deletions to avoid implicit Path construction for noexcept methods
303 static bool remove( const char * , std::nothrow_t ) = delete ;
304 static bool remove( const std::string & , std::nothrow_t ) = delete ;
305 static bool rename( const char * , const Path & , std::nothrow_t ) = delete ;
306 static bool rename( const std::string & , const Path & , std::nothrow_t ) = delete ;
307 static bool rename( const char * , const char * , std::nothrow_t ) = delete ;
308 static bool rename( const std::string & , const std::string & , std::nothrow_t ) = delete ;
309 static bool renameOnto( const char * , const char * , std::nothrow_t ) = delete ;
310 static bool renameOnto( const std::string & , const std::string & , std::nothrow_t ) = delete ;
311 static int open( const char * , InOutAppend ) = delete ;
312 static int open( const std::string & , InOutAppend ) = delete ;
313 static int open( const char * , CreateExclusive ) = delete ;
314 static int open( const std::string & , CreateExclusive ) = delete ;
315 static std::FILE * fopen( const char * , const char * mode ) = delete ;
316 static std::FILE * fopen( const std::string & , const char * mode ) = delete ;
317 static bool probe( const char * ) = delete ;
318 static bool probe( const std::string & ) = delete ;
319
320private:
321 static const int rdonly = 1<<0 ;
322 static const int wronly = 1<<1 ;
323 static const int rdwr = 1<<2 ;
324 static const int trunc = 1<<3 ;
325 static const int creat = 1<<4 ;
326 static const int append = 1<<5 ;
327 friend class G::DirectoryIteratorImp ;
328 static std::string copy( const Path & , const Path & , int ) ;
329 static bool exists( const Path & , bool , bool ) ;
330 static bool existsImp( const char * , bool & , bool & ) noexcept ;
331 static Stat statImp( const char * , bool = false ) noexcept ;
332 static bool renameImp( const char * , const char * , int * ) noexcept ;
333 static bool chmodx( const Path & file , bool ) ;
334 static int linkImp( const char * , const char * ) ;
335 static bool linked( const Path & , const Path & ) ;
336 static int mkdirImp( const Path & dir ) noexcept ;
337 static bool mkdirsImp( const Path & dir , int & , int ) ;
338 static bool chmod( const Path & , const std::string & , std::nothrow_t ) ;
339} ;
340
341#endif
An overload discriminator for G::File::open().
Definition: gfile.h:62
An overload discriminator for G::File::open().
Definition: gfile.h:64
A simple static class for dealing with files.
Definition: gfile.h:44
static void open(std::ofstream &, const Path &)
Calls open() on the given output file stream.
Definition: gfile_unix.cpp:56
static bool isExecutable(const Path &, std::nothrow_t)
Returns true if the path is probably executable by the calling process.
Definition: gfile.cpp:185
static void close(int fd) noexcept
Calls ::close() or equivalent.
Definition: gfile_unix.cpp:159
static SystemTime time(const Path &file)
Returns the file's timestamp. Throws on error.
Definition: gfile.cpp:205
static bool isEmpty(const Path &file, std::nothrow_t)
Returns true if the file size is zero.
Definition: gfile.cpp:192
static void link(const Path &target, const Path &new_link)
Creates a symlink.
Definition: gfile_unix.cpp:396
static bool isDirectory(const Path &path, std::nothrow_t)
Returns true if the path exists() and is a directory.
Definition: gfile.cpp:179
static std::string sizeString(const Path &file)
Returns the file's size in string format.
Definition: gfile.cpp:199
static std::streamoff seek(int fd, std::streamoff offset, Seek) noexcept
Does ::lseek() or equivalent.
Definition: gfile_unix.cpp:472
static void setNonBlocking(int fd) noexcept
Sets the file descriptor to non-blocking mode.
Definition: gfile_unix.cpp:480
static bool rename(const Path &from, const Path &to, std::nothrow_t) noexcept
Renames the file.
Definition: gfile.cpp:40
static ssize_t write(int fd, const char *, std::size_t) noexcept
Calls ::write() or equivalent.
Definition: gfile_unix.cpp:154
static void chmod(const Path &file, const std::string &spec)
Sets the file permissions.
Definition: gfile_unix.cpp:272
static bool remove(const Path &path, std::nothrow_t) noexcept
Deletes the file or directory. Returns false on error.
Definition: gfile_unix.cpp:177
static Stat stat(const Path &path, bool symlink_nofollow=false)
Returns a file status structure.
Definition: gfile.cpp:174
static bool exists(const Path &file)
Returns true if the file (directory, device etc.) exists.
Definition: gfile.cpp:136
static void chmodx(const Path &file)
Makes the file executable. Throws on error.
Definition: gfile.cpp:229
static bool isLink(const Path &path, std::nothrow_t)
Returns true if the path is an existing symlink.
Definition: gfile.cpp:167
static Path backup(const Path &from, std::nothrow_t)
Creates a backup copy of the given file in the same directory and with a lightly-mangled filename.
Definition: gfile.cpp:322
static ssize_t read(int fd, char *, std::size_t) noexcept
Calls read() or equivalent.
Definition: gfile_unix.cpp:149
static bool mkdirs(const Path &dir, std::nothrow_t, int=100)
Creates a directory and all necessary parents.
Definition: gfile.cpp:276
static bool renameOnto(const Path &from, const Path &to, std::nothrow_t) noexcept
Renames the file, deleting 'to' first if necessary.
Definition: gfile_unix.cpp:144
static bool copy(const Path &from, const Path &to, std::nothrow_t)
Copies a file. Returns false on error.
Definition: gfile.cpp:67
static bool copyInto(const Path &from, const Path &to_dir, std::nothrow_t)
Copies a file into a directory and does a chmodx() if necessary.
Definition: gfile.cpp:73
static bool mkdir(const Path &dir, std::nothrow_t)
Creates a directory.
Definition: gfile.cpp:235
static void create(const Path &)
Creates the file if it does not exist.
Definition: gfile_unix.cpp:135
static G::Path readlink(const Path &link)
Reads a symlink. Throws on error.
Definition: gfile_unix.cpp:436
static std::FILE * fopen(const Path &, const char *mode) noexcept
Calls std::fopen().
Definition: gfile_unix.cpp:114
static bool hardlink(const Path &src, const Path &dst, std::nothrow_t)
Creates a hard link.
Definition: gfile_unix.cpp:390
static bool probe(const Path &) noexcept
Creates and deletes a temporary probe file.
Definition: gfile_unix.cpp:120
static int compare(const Path &, const Path &, bool ignore_whitespace=false)
Compares the contents of the two files. Returns 0, 1 or -1.
Definition: gfile.cpp:293
static bool cleanup(const Cleanup::Arg &path_arg) noexcept
Deletes the file.
Definition: gfile_unix.cpp:172
static void chgrp(const Path &file, const std::string &group)
Sets the file group ownership. Throws on error.
Definition: gfile_unix.cpp:370
A Path object represents a file system path.
Definition: gpath.h:82
Represents a unix-epoch time with microsecond resolution.
Definition: gdatetime.h:140
Low-level classes.
Definition: garg.h:36
constexpr const char * tx(const char *p) noexcept
A briefer alternative to G::gettext_noop().
Definition: ggettext.h:84
STL namespace.
Opaque leaky string pointer wrapper created by G::Cleanup::arg().
Definition: gcleanup.h:55
An overload discriminator for G::File::open().
Definition: gfile.h:66
A portable 'struct stat'.
Definition: gfile.h:68