gfile_unix.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_unix.cpp
19 //
20 
21 #include "gdef.h"
22 #include "glimits.h"
23 #include "gfile.h"
24 #include "gprocess.h"
25 #include "gdebug.h"
26 #include <errno.h>
27 #include <sys/stat.h>
28 #include <sstream>
29 
30 bool G::File::mkdir( const Path & dir , const NoThrow & )
31 {
32  return 0 == ::mkdir( dir.str().c_str() , S_IRUSR | S_IWUSR | S_IXUSR ) ;
33 }
34 
35 bool G::File::exists( const char * path , bool & enoent )
36 {
37  struct stat statbuf ;
38  if( 0 == ::stat( path , &statbuf ) )
39  {
40  return true ;
41  }
42  else
43  {
44  int error = G::Process::errno_() ;
45  enoent = error == ENOENT || error == ENOTDIR ;
46  return false ;
47  }
48 }
49 
50 bool G::File::executable( const Path & path )
51 {
52  struct stat statbuf ;
53  if( 0 == ::stat( path.str().c_str() , &statbuf ) )
54  {
55  bool x = !!( statbuf.st_mode & S_IXUSR ) ;
56  bool r =
57  ( statbuf.st_mode & S_IFMT ) == S_IFREG ||
58  ( statbuf.st_mode & S_IFMT ) == S_IFLNK ;
59  return x && r ; // indicitive only
60  }
61  else
62  {
63  return false ;
64  }
65 }
66 
67 std::string G::File::sizeString( const Path & path )
68 {
69  struct stat statbuf ;
70  if( 0 != ::stat( path.str().c_str() , &statbuf ) )
71  return std::string() ;
72 
73  std::ostringstream ss ;
74  ss << statbuf.st_size ;
75  return ss.str() ;
76 }
77 
79 {
80  struct stat statbuf ;
81  if( 0 != ::stat( path.str().c_str() , &statbuf ) )
82  throw TimeError( path.str() ) ;
83  return statbuf.st_mtime ;
84 }
85 
86 G::File::time_type G::File::time( const Path & path , const NoThrow & )
87 {
88  struct stat statbuf ;
89  return ::stat( path.str().c_str() , &statbuf ) == 0 ? statbuf.st_mtime : 0 ;
90 }
91 
92 bool G::File::chmodx( const Path & path , bool do_throw )
93 {
94  mode_t mode = S_IRUSR | S_IWUSR | S_IXUSR ;
95  struct stat statbuf ;
96  if( 0 == ::stat( path.str().c_str() , &statbuf ) )
97  {
98  G_DEBUG( "G::File::chmodx: old: " << statbuf.st_mode ) ;
99  mode = statbuf.st_mode | S_IXUSR ;
100  if( mode & S_IRGRP ) mode |= S_IXGRP ;
101  if( mode & S_IROTH ) mode |= S_IXOTH ;
102  G_DEBUG( "G::File::chmodx: new: " << mode ) ;
103  }
104 
105  bool ok = 0 == ::chmod( path.str().c_str() , mode ) ;
106  if( !ok && do_throw )
107  throw CannotChmod( path.str() ) ;
108  return ok ;
109 }
110 
111 void G::File::link( const Path & target , const Path & new_link )
112 {
113  if( !link(target,new_link,NoThrow()) )
114  {
115  int error = G::Process::errno_() ; // keep first
116  std::ostringstream ss ;
117  ss << "[" << new_link << "] -> [" << target << "] " "(" << error << ")" ;
118  throw CannotLink( ss.str() ) ;
119  }
120 }
121 
122 bool G::File::link( const Path & target , const Path & new_link , const NoThrow & )
123 {
124  // optimisation
125  char buffer[limits::path] ;
126  ssize_t rc = ::readlink( new_link.str().c_str() , buffer , sizeof(buffer) ) ;
127  size_t n = rc < 0 ? size_t(0U) : static_cast<size_t>(rc) ;
128  if( rc > 0 && n != sizeof(buffer) )
129  {
130  std::string old_target( buffer , n ) ;
131  if( target.str() == old_target )
132  return true ;
133  }
134 
135  if( exists(new_link) )
136  remove( new_link , NoThrow() ) ;
137 
138  rc = ::symlink( target.str().c_str() , new_link.str().c_str() ) ;
139  // dont put anything here (preserve errno)
140  return rc == 0 ;
141 }
142 
std::string str() const
Returns the path string.
Definition: gpath.cpp:135
DateTime::EpochTime time_type
Definition: gfile.h:44
static int errno_()
Returns the process's current 'errno' value.
static bool executable(const Path &)
Returns true if the path is probably executable.
Definition: gfile_unix.cpp:50
static bool exists(const Path &file)
Returns true if the file (directory, link, device etc.) exists.
Definition: gfile.cpp:130
#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
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
static void link(const Path &target, const Path &new_link)
Creates a symlink.
Definition: gfile_unix.cpp:111
static std::string sizeString(const Path &file)
Returns the file's size in string format.
Definition: gfile_unix.cpp:67
A Path object represents a file system path.
Definition: gpath.h:44
static time_type time(const Path &file)
Returns the file's timestamp.
Definition: gfile_unix.cpp:78