gfile.cpp
Go to the documentation of this file.
1 //
2 // Copyright (C) 2001-2013 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  //int error = G::Process::errno_() ;
41  throw CannotRemove( path.str() ) ;
42  }
43  G_DEBUG( "G::File::remove: \"" << path << "\"" ) ;
44 }
45 
46 bool G::File::rename( const Path & from , const Path & to , const NoThrow & )
47 {
48  bool rc = 0 == std::rename( from.str().c_str() , to.str().c_str() ) ;
49  G_DEBUG( "G::File::rename: \"" << from << "\" -> \"" << to << "\": success=" << rc ) ;
50  return rc ;
51 }
52 
53 void G::File::rename( const Path & from , const Path & to )
54 {
55  if( 0 != std::rename( from.str().c_str() , to.str().c_str() ) )
56  {
57  //int error = G::Process::errno_() ;
58  throw CannotRename( std::string() + "[" + from.str() + "] to [" + to.str() + "]" ) ;
59  }
60  G_DEBUG( "G::File::rename: \"" << from << "\" -> \"" << to << "\"" ) ;
61 }
62 
63 void G::File::copy( const Path & from , const Path & to )
64 {
65  std::string reason = copy( from , to , 0 ) ;
66  if( !reason.empty() )
67  throw CannotCopy( std::string() + "[" + from.str() + "] to [" + to.str() + "]: " + reason ) ;
68 }
69 
70 bool G::File::copy( const Path & from , const Path & to , const NoThrow & )
71 {
72  return copy(from,to,0).empty() ;
73 }
74 
75 std::string G::File::copy( const Path & from , const Path & to , int )
76 {
77  std::ifstream in( from.str().c_str() , std::ios::binary | std::ios::in ) ;
78  if( !in.good() )
79  return "cannot open input file" ;
80 
81  std::ofstream out( to.str().c_str() , std::ios::binary | std::ios::out | std::ios::trunc ) ;
82  if( !out.good() )
83  return "cannot open output file" ;
84 
85  out << in.rdbuf() ;
86 
87  if( in.fail() || in.bad() )
88  return "read error" ;
89 
90  if( !out.good() )
91  return "write error" ;
92 
93  in.close() ;
94  out.close() ;
95  if( sizeString(from) != sizeString(to) )
96  return "file size mismatch" ;
97 
98  return std::string() ;
99 }
100 
101 void G::File::copy( std::istream & in , std::ostream & out , std::streamsize limit , std::string::size_type block )
102 {
103  block = block ? block : static_cast<std::string::size_type>(limits::file_buffer) ;
104  std::vector<char> buffer ;
105  buffer.reserve( block ) ;
106 
107  const std::streamsize b = static_cast<std::streamsize>(block) ;
108  std::streamsize size = 0U ;
109  while( ( limit == 0U || size < limit ) && in.good() && out.good() )
110  {
111  std::streamsize request = limit == 0U || (limit-size) > b ? b : (limit-size) ;
112  in.read( &buffer[0] , request ) ;
113  std::streamsize result = in.gcount() ;
114  if( result == 0U )
115  break ;
116  out.write( &buffer[0] , result ) ;
117  size += result ;
118  }
119 
120  out.flush() ;
121  in.clear( in.rdstate() & ~std::ios_base::failbit ) ; // failbit set at eof so not useful
122 }
123 
124 void G::File::mkdir( const Path & dir )
125 {
126  if( ! mkdir( dir , NoThrow() ) )
127  throw CannotMkdir( dir.str() ) ;
128 }
129 
130 bool G::File::exists( const Path & path )
131 {
132  return exists( path , false , true ) ;
133 }
134 
135 bool G::File::exists( const Path & path , const NoThrow & )
136 {
137  return exists( path , false , false ) ;
138 }
139 
140 bool G::File::exists( const Path & path , bool on_error , bool do_throw )
141 {
142  bool enoent = false ;
143  bool rc = exists( path.str().c_str() , enoent ) ; // o/s-specific
144  if( !rc && enoent )
145  {
146  return false ;
147  }
148  else if( !rc && do_throw )
149  {
150  throw StatError( path.str() ) ;
151  }
152  else if( !rc )
153  {
154  return on_error ;
155  }
156  return true ;
157 }
158 
159 bool G::File::chmodx( const Path & path , const NoThrow & )
160 {
161  return chmodx(path,false) ;
162 }
163 
164 void G::File::chmodx( const Path & path )
165 {
166  chmodx(path,true) ;
167 }
168 
169 bool G::File::mkdirs( const Path & path , const NoThrow & , int limit )
170 {
171  // (recursive)
172  G_DEBUG( "File::mkdirs: " << path ) ;
173  if( limit == 0 ) return false ;
174  if( exists(path) ) return true ;
175  if( path.str().empty() ) return true ;
176  if( ! mkdirs( path.dirname() , NoThrow() , limit-1 ) ) return false ;
177  bool ok = mkdir( path , NoThrow() ) ;
178  if( ok ) chmodx( path , NoThrow() ) ;
179  return ok ;
180 }
181 
182 void G::File::mkdirs( const Path & path , int limit )
183 {
184  if( ! mkdirs(path,NoThrow(),limit) )
185  throw CannotMkdir(path.str()) ;
186 }
187 
188 void G::File::create( const Path & path )
189 {
190  std::ofstream f( path.str().c_str() ) ;
191  f.close() ;
192  if( !exists(path) ) // race
193  throw CannotCreate( path.str() ) ;
194 }
195 
std::string str() const
Returns the path string.
Definition: gpath.cpp:135
static bool copy(const Path &from, const Path &to, const NoThrow &)
Copies a file. Returns false on error.
Definition: gfile.cpp:70
static void create(const Path &)
Creates an empty file. Throws on error.
Definition: gfile.cpp:188
std::string::size_type size_type
A std::size_t type.
Definition: md5.h:43
static bool rename(const Path &from, const Path &to, const NoThrow &)
Renames the file. Returns false on error.
Definition: gfile.cpp:46
static bool mkdirs(const Path &dir, const NoThrow &, int=100)
Creates a directory and all necessary parents.
Definition: gfile.cpp:169
static bool exists(const Path &file)
Returns true if the file (directory, link, device etc.) exists.
Definition: gfile.cpp:130
Path dirname() const
Returns the drive/directory parts of the path.
Definition: gpath.cpp:182
#define G_DEBUG(expr)
Definition: glog.h:95
static bool mkdir(const Path &dir, const NoThrow &)
Creates a directory. Returns false on error.
Definition: gfile_unix.cpp:30
static bool remove(const Path &path, const NoThrow &)
Deletes the file or directory. Returns false on error.
Definition: gfile.cpp:29
An overload discriminator class for File methods.
Definition: gfile.h:56
static void chmodx(const Path &file)
Makes the file executable.
Definition: gfile.cpp:164
A Path object represents a file system path.
Definition: gpath.h:44