E-MailRelay

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

gfile.cpp
Go to the documentation of this file.
1 //
2 // Copyright (C) 2001-2018 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 // gfile.cpp
19 //
20
21 #include "gdef.h"
22 #include "glimits.h"
23 #include "gfile.h"
24 #include "gprocess.h"
25 #include "glog.h"
26 #include <iostream>
27 #include <cstdio>
28
29 bool G::File::remove( const Path & path , const G::File::NoThrow & )
30 {
31 bool rc = 0 == std::remove( path.str().c_str() ) ;
32 G_DEBUG( "G::File::remove: \"" << path << "\": success=" << rc ) ;
33 return rc ;
34 }
35
36 void G::File::remove( const Path & path )
37 {
38 if( 0 != std::remove( path.str().c_str() ) )
39 {
40 throw CannotRemove( path.str() ) ;
41 }
42 G_DEBUG( "G::File::remove: \"" << path << "\"" ) ;
43 }
44
45 bool G::File::rename( const Path & from , const Path & to , const NoThrow & )
46 {
47 bool is_missing = false ;
48 bool ok = rename( from.str().c_str() , to.str().c_str() , is_missing ) ;
49 G_DEBUG( "G::File::rename: \"" << from << "\" -> \"" << to << "\": success=" << ok ) ;
50 return ok ;
51 }
52
53 void G::File::rename( const Path & from , const Path & to , bool ignore_missing )
54 {
55 bool is_missing = false ;
56 bool ok = rename( from.str().c_str() , to.str().c_str() , is_missing ) ;
57 if( !ok && !(is_missing && ignore_missing) )
58 {
59 throw CannotRename( std::string() + "[" + from.str() + "] to [" + to.str() + "]" ) ;
60 }
61 G_DEBUG( "G::File::rename: \"" << from << "\" -> \"" << to << "\": success=" << ok ) ;
62 }
63
64 bool G::File::rename( const char * from , const char * to , bool & enoent )
65 {
66 bool ok = 0 == std::rename( from , to ) ;
67 int error = G::Process::errno_() ;
68 enoent = !ok && error == ENOENT ;
69 return ok ;
70 }
71
72 void G::File::copy( const Path & from , const Path & to )
73 {
74 std::string reason = copy( from , to , 0 ) ;
75 if( !reason.empty() )
76 throw CannotCopy( std::string() + "[" + from.str() + "] to [" + to.str() + "]: " + reason ) ;
77 }
78
79 bool G::File::copy( const Path & from , const Path & to , const NoThrow & )
80 {
81 return copy(from,to,0).empty() ;
82 }
83
84 std::string G::File::copy( const Path & from , const Path & to , int )
85 {
86 std::ifstream in( from.str().c_str() , std::ios::binary | std::ios::in ) ;
87 if( !in.good() )
88 return "cannot open input file" ;
89
90 std::ofstream out( to.str().c_str() , std::ios::binary | std::ios::out | std::ios::trunc ) ;
91 if( !out.good() )
92 return "cannot open output file" ;
93
94 out << in.rdbuf() ;
95
96 if( in.fail() )
97 return "read error" ;
98
99 in.close() ;
100 out.close() ;
101
102 if( out.fail() )
103 return "write error" ;
104
105 return std::string() ;
106 }
107
108 void G::File::copy( std::istream & in , std::ostream & out , std::streamsize limit , std::string::size_type block )
109 {
110 std::ios_base::iostate in_state = in.rdstate() ;
111
112 block = block ? block : static_cast<std::string::size_type>(limits::file_buffer) ;
113 std::vector<char> buffer ;
114 buffer.reserve( block ) ;
115
116 const std::streamsize b = static_cast<std::streamsize>(block) ;
117 std::streamsize size = 0U ;
118 while( ( limit == 0U || size < limit ) && in.good() && out.good() )
119 {
120 std::streamsize request = limit == 0U || (limit-size) > b ? b : (limit-size) ;
121 in.read( &buffer[0] , request ) ;
122 std::streamsize result = in.gcount() ;
123 if( result == 0U )
124 break ;
125 out.write( &buffer[0] , result ) ;
126 size += result ;
127 }
128
129 out.flush() ;
130
131 // restore the input failbit because it might have been set by us reading an incomplete block at eof
132 in.clear( (in.rdstate() & ~std::ios_base::failbit) | (in_state & std::ios_base::failbit) ) ;
133 }
134
135 void G::File::mkdir( const Path & dir )
136 {
137 if( ! mkdir( dir , NoThrow() ) )
138 throw CannotMkdir( dir.str() ) ;
139 }
140
141 bool G::File::exists( const Path & path )
142 {
143 return exists( path , false , true ) ;
144 }
145
146 bool G::File::exists( const Path & path , const NoThrow & )
147 {
148 return exists( path , false , false ) ;
149 }
150
151 bool G::File::exists( const Path & path , bool on_error , bool do_throw )
152 {
153 bool enoent = false ;
154 bool eaccess = false ;
155 bool rc = exists( path.str().c_str() , enoent , eaccess ) ; // o/s-specific implementation
156 if( !rc && enoent )
157 {
158 return false ;
159 }
160 else if( !rc && do_throw )
161 {
162 throw StatError( path.str() , eaccess?"permission denied":"" ) ;
163 }
164 else if( !rc )
165 {
166 return on_error ;
167 }
168 return true ;
169 }
170
171 bool G::File::chmodx( const Path & path , const NoThrow & )
172 {
173 return chmodx( path , false ) ;
174 }
175
176 void G::File::chmodx( const Path & path )
177 {
178 chmodx( path , true ) ;
179 }
180
181 bool G::File::mkdirs( const Path & path , const NoThrow & , int limit )
182 {
183 // (recursive)
184
185 G_DEBUG( "File::mkdirs: " << path ) ;
186 if( limit == 0 )
187 return false ;
188
189 // use a trial mkdir() on the our way towards the root to avoid
190 // problems with the windows "virtual store" mis-feature
191 const bool mkdir_trial = true ;
192 if( mkdir_trial )
193 {
194 if( mkdir(path,NoThrow()) )
195 {
196 G_DEBUG( "File::mkdirs: mkdir(" << path << ") -> ok" ) ;
197 chmodx( path , NoThrow() ) ;
198 return true ;
199 }
200 }
201
202 if( exists(path) )
203 return true ;
204
205 if( path.str().empty() )
206 return true ;
207
208 if( ! mkdirs( path.dirname() , NoThrow() , limit-1 ) ) // (recursion)
209 return false ;
210
211 G_DEBUG( "File::mkdirs: mkdir(" << path << ")" ) ;
212 bool ok = mkdir( path , NoThrow() ) ;
213 if( ok )
214 chmodx( path , NoThrow() ) ;
215
216 G_DEBUG( "File::mkdirs: mkdir(" << path << ") -> " << (ok?"ok":"failed") ) ;
217 return ok ;
218 }
219
220 void G::File::mkdirs( const Path & path , int limit )
221 {
222 if( ! mkdirs(path,NoThrow(),limit) )
223 throw CannotMkdir(path.str()) ;
224 }
225
226 void G::File::create( const Path & path )
227 {
228 std::ofstream f( path.str().c_str() , std::ios_base::out | std::ios_base::app ) ;
229 f.close() ;
230 if( !exists(path) ) // race
231 throw CannotCreate( path.str() ) ;
232 }
233
234 /// \file gfile.cpp
G::Path::str
std::string str() const
Returns the path string.
Definition: gpath.cpp:290
G::File::copy
static bool copy(const Path &from, const Path &to, const NoThrow &)
Copies a file. Returns false on error.
Definition: gfile.cpp:79
glog.h
G::File::create
static void create(const Path &)
Creates an empty file. Throws on error.
Definition: gfile.cpp:226
std
STL namespace.
G::File::rename
static bool rename(const Path &from, const Path &to, const NoThrow &)
Renames the file. Returns false on error.
Definition: gfile.cpp:45
glimits.h
G::File::mkdirs
static bool mkdirs(const Path &dir, const NoThrow &, int=100)
Creates a directory and all necessary parents.
Definition: gfile.cpp:181
gfile.h
gprocess.h
G::File::exists
static bool exists(const Path &file)
Returns true if the file (directory, device etc.) exists.
Definition: gfile.cpp:141
G::Path::dirname
Path dirname() const
Returns the path without the rightmost part, ignoring "." parts.
Definition: gpath.cpp:318
G::File::mkdir
static bool mkdir(const Path &dir, const NoThrow &)
Creates a directory. Returns false on error.
Definition: gfile_unix.cpp:45
G::File::remove
static bool remove(const Path &path, const NoThrow &)
Deletes the file or directory. Returns false on error.
Definition: gfile.cpp:29
G::File::NoThrow
An overload discriminator class for File methods.
Definition: gfile.h:53
G::File::chmodx
static void chmodx(const Path &file)
Makes the file executable.
Definition: gfile.cpp:176
G::Path
A Path object represents a file system path.
Definition: gpath.h:72