00001 /* 00002 00003 Copyright (C) 1996-2012 John W. Eaton 00004 00005 This file is part of Octave. 00006 00007 Octave is free software; you can redistribute it and/or modify it 00008 under the terms of the GNU General Public License as published by the 00009 Free Software Foundation; either version 3 of the License, or (at your 00010 option) any later version. 00011 00012 Octave is distributed in the hope that it will be useful, but WITHOUT 00013 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 00014 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 00015 for more details. 00016 00017 You should have received a copy of the GNU General Public License 00018 along with Octave; see the file COPYING. If not, see 00019 <http://www.gnu.org/licenses/>. 00020 00021 */ 00022 00023 #ifdef HAVE_CONFIG_H 00024 #include <config.h> 00025 #endif 00026 00027 #include <cerrno> 00028 #include <cstring> 00029 00030 #include <sys/types.h> 00031 #include <unistd.h> 00032 00033 #include "filemode.h" 00034 00035 #include "file-ops.h" 00036 #include "file-stat.h" 00037 #include "statdefs.h" 00038 00039 // FIXME -- the is_* and mode_as_string functions are only valid 00040 // for initialized objects. If called for an object that is not 00041 // initialized, they should throw an exception. 00042 00043 bool 00044 base_file_stat::is_blk (void) const 00045 { 00046 return exists () && is_blk (fs_mode); 00047 } 00048 00049 bool 00050 base_file_stat::is_chr (void) const 00051 { 00052 return exists () && is_chr (fs_mode); 00053 } 00054 00055 bool 00056 base_file_stat::is_dir (void) const 00057 { 00058 return exists () && is_dir (fs_mode); 00059 } 00060 00061 bool 00062 base_file_stat::is_fifo (void) const 00063 { 00064 return exists () && is_fifo (fs_mode); 00065 } 00066 00067 bool 00068 base_file_stat::is_lnk (void) const 00069 { 00070 return exists () && is_lnk (fs_mode); 00071 } 00072 00073 bool 00074 base_file_stat::is_reg (void) const 00075 { 00076 return exists () && is_reg (fs_mode); 00077 } 00078 00079 bool 00080 base_file_stat::is_sock (void) const 00081 { 00082 return exists () && is_sock (fs_mode); 00083 } 00084 00085 bool 00086 base_file_stat::is_blk (mode_t mode) 00087 { 00088 #ifdef S_ISBLK 00089 return S_ISBLK (mode); 00090 #else 00091 return false; 00092 #endif 00093 } 00094 00095 bool 00096 base_file_stat::is_chr (mode_t mode) 00097 { 00098 #ifdef S_ISCHR 00099 return S_ISCHR (mode); 00100 #else 00101 return false; 00102 #endif 00103 } 00104 00105 bool 00106 base_file_stat::is_dir (mode_t mode) 00107 { 00108 #ifdef S_ISDIR 00109 return S_ISDIR (mode); 00110 #else 00111 return false; 00112 #endif 00113 } 00114 00115 bool 00116 base_file_stat::is_fifo (mode_t mode) 00117 { 00118 #ifdef S_ISFIFO 00119 return S_ISFIFO (mode); 00120 #else 00121 return false; 00122 #endif 00123 } 00124 00125 bool 00126 base_file_stat::is_lnk (mode_t mode) 00127 { 00128 #ifdef S_ISLNK 00129 return S_ISLNK (mode); 00130 #else 00131 return false; 00132 #endif 00133 } 00134 00135 bool 00136 base_file_stat::is_reg (mode_t mode) 00137 { 00138 #ifdef S_ISREG 00139 return S_ISREG (mode); 00140 #else 00141 return false; 00142 #endif 00143 } 00144 00145 bool 00146 base_file_stat::is_sock (mode_t mode) 00147 { 00148 #ifdef S_ISSOCK 00149 return S_ISSOCK (mode); 00150 #else 00151 return false; 00152 #endif 00153 } 00154 00155 std::string 00156 base_file_stat::mode_as_string (void) const 00157 { 00158 char buf[12]; 00159 00160 strmode (fs_mode, buf); 00161 00162 return std::string (buf); 00163 } 00164 00165 // Has FILE been modified since TIME? Returns 1 for yes, 0 for no, 00166 // and -1 for any error. 00167 00168 int 00169 base_file_stat::is_newer (const std::string& file, const octave_time& time) 00170 { 00171 file_stat fs (file); 00172 00173 return fs ? fs.is_newer (time) : -1; 00174 } 00175 00176 // Private stuff: 00177 00178 void 00179 file_stat::update_internal (bool force) 00180 { 00181 if (! initialized || force) 00182 { 00183 initialized = false; 00184 fail = false; 00185 00186 std::string full_file_name = file_ops::tilde_expand (file_name); 00187 00188 #if defined (__WIN32__) 00189 // Remove trailing slash. 00190 if (file_ops::is_dir_sep (full_file_name[full_file_name.length () - 1]) 00191 && full_file_name.length () != 1 00192 && ! (full_file_name.length() == 3 && full_file_name[1] == ':')) 00193 full_file_name.resize (full_file_name.length () - 1); 00194 #endif 00195 00196 const char *cname = full_file_name.c_str (); 00197 00198 struct stat buf; 00199 00200 int status = follow_links 00201 ? stat (cname, &buf) : gnulib::lstat (cname, &buf); 00202 00203 if (status < 0) 00204 { 00205 fail = true; 00206 errmsg = gnulib::strerror (errno); 00207 } 00208 else 00209 { 00210 fs_mode = buf.st_mode; 00211 fs_ino = buf.st_ino; 00212 fs_dev = buf.st_dev; 00213 fs_nlink = buf.st_nlink; 00214 fs_uid = buf.st_uid; 00215 fs_gid = buf.st_gid; 00216 fs_size = buf.st_size; 00217 fs_atime = buf.st_atime; 00218 fs_mtime = buf.st_mtime; 00219 fs_ctime = buf.st_ctime; 00220 00221 #if defined (HAVE_STRUCT_STAT_ST_RDEV) 00222 fs_rdev = buf.st_rdev; 00223 #endif 00224 00225 #if defined (HAVE_STRUCT_STAT_ST_BLKSIZE) 00226 fs_blksize = buf.st_blksize; 00227 #endif 00228 00229 #if defined (HAVE_STRUCT_STAT_ST_BLOCKS) 00230 fs_blocks = buf.st_blocks; 00231 #endif 00232 } 00233 00234 initialized = true; 00235 } 00236 } 00237 00238 void 00239 file_fstat::update_internal (bool force) 00240 { 00241 if (! initialized || force) 00242 { 00243 initialized = false; 00244 fail = false; 00245 00246 struct stat buf; 00247 00248 int status = gnulib::fstat (fid, &buf); 00249 00250 if (status < 0) 00251 { 00252 fail = true; 00253 errmsg = gnulib::strerror (errno); 00254 } 00255 else 00256 { 00257 fs_mode = buf.st_mode; 00258 fs_ino = buf.st_ino; 00259 fs_dev = buf.st_dev; 00260 fs_nlink = buf.st_nlink; 00261 fs_uid = buf.st_uid; 00262 fs_gid = buf.st_gid; 00263 fs_size = buf.st_size; 00264 fs_atime = buf.st_atime; 00265 fs_mtime = buf.st_mtime; 00266 fs_ctime = buf.st_ctime; 00267 00268 #if defined (HAVE_STRUCT_STAT_ST_RDEV) 00269 fs_rdev = buf.st_rdev; 00270 #endif 00271 00272 #if defined (HAVE_STRUCT_STAT_ST_BLKSIZE) 00273 fs_blksize = buf.st_blksize; 00274 #endif 00275 00276 #if defined (HAVE_STRUCT_STAT_ST_BLOCKS) 00277 fs_blocks = buf.st_blocks; 00278 #endif 00279 } 00280 00281 initialized = true; 00282 } 00283 }