1 ////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (C) 1996-2021 The Octave Project Developers
4 //
5 // See the file COPYRIGHT.md in the top-level directory of this
6 // distribution or <https://octave.org/copyright/>.
7 //
8 // This file is part of Octave.
9 //
10 // Octave is free software: you can redistribute it and/or modify it
11 // under the terms of the GNU General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // Octave is distributed in the hope that it will be useful, but
16 // WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 // GNU General Public License for more details.
19 //
20 // You should have received a copy of the GNU General Public License
21 // along with Octave; see the file COPYING.  If not, see
22 // <https://www.gnu.org/licenses/>.
23 //
24 ////////////////////////////////////////////////////////////////////////
25 
26 #if ! defined (octave_file_stat_h)
27 #define octave_file_stat_h 1
28 
29 #include "octave-config.h"
30 
31 #include <string>
32 
33 #include "oct-time.h"
34 
35 #include <sys/types.h>
36 
37 namespace octave
38 {
39   namespace sys
40   {
41     class
42     OCTAVE_API
43     base_file_stat
44     {
45     public:
46 
base_file_stat(void)47       base_file_stat (void)
48         : initialized (false), fail (false), errmsg (), m_mode (),
49           m_ino (), m_dev (), m_nlink (), m_uid (), m_gid (),
50           m_size (), m_atime (), m_mtime (), m_ctime (), m_rdev (),
51           m_blksize (), m_blocks () { }
52 
base_file_stat(const base_file_stat & fs)53       base_file_stat (const base_file_stat& fs)
54         : initialized (fs.initialized), fail (fs.fail), errmsg (fs.errmsg),
55           m_mode (fs.m_mode), m_ino (fs.m_ino), m_dev (fs.m_dev),
56           m_nlink (fs.m_nlink), m_uid (fs.m_uid), m_gid (fs.m_gid),
57           m_size (fs.m_size), m_atime (fs.m_atime), m_mtime (fs.m_mtime),
58           m_ctime (fs.m_ctime), m_rdev (fs.m_rdev),
59           m_blksize (fs.m_blksize), m_blocks (fs.m_blocks) { }
60 
61       base_file_stat& operator = (const base_file_stat& fs)
62       {
63         if (this != &fs)
64           {
65             initialized = fs.initialized;
66             fail = fs.fail;
67             errmsg = fs.errmsg;
68             m_mode = fs.m_mode;
69             m_ino = fs.m_ino;
70             m_dev = fs.m_dev;
71             m_nlink = fs.m_nlink;
72             m_uid = fs.m_uid;
73             m_gid = fs.m_gid;
74             m_size = fs.m_size;
75             m_atime = fs.m_atime;
76             m_mtime = fs.m_mtime;
77             m_ctime = fs.m_ctime;
78             m_rdev = fs.m_rdev;
79             m_blksize = fs.m_blksize;
80             m_blocks = fs.m_blocks;
81           }
82 
83         return *this;
84       }
85 
86       // The minimum difference in file time stamp values.
87       // FIXME: This value should come from the filesystem itself.
88       //        How can we get that info?
time_resolution(void)89       sys::time time_resolution (void) const
90       {
91         static sys::time resolution (1.0);
92         return resolution;
93       }
94 
95       // File status and info.  The is_XXX functions will return false for
96       // file_stat objects that are not properly initialized.  The others
97       // should all return 0 (or the equivalent, for the given object)
98       // which is likely not meaningful.
99 
100       bool is_blk (void) const;
101       bool is_chr (void) const;
102       bool is_dir (void) const;
103       bool is_fifo (void) const;
104       bool is_lnk (void) const;
105       bool is_reg (void) const;
106       bool is_sock (void) const;
107 
108       static bool is_blk (mode_t mode);
109       static bool is_chr (mode_t mode);
110       static bool is_dir (mode_t mode);
111       static bool is_fifo (mode_t mode);
112       static bool is_lnk (mode_t mode);
113       static bool is_reg (mode_t mode);
114       static bool is_sock (mode_t mode);
115 
116       static bool have_struct_stat_st_rdev (void);
117       static bool have_struct_stat_st_blksize (void);
118       static bool have_struct_stat_st_blocks (void);
119 
ino(void)120       ino_t ino (void) const { return m_ino; }
dev(void)121       dev_t dev (void) const { return m_dev; }
122 
nlink(void)123       nlink_t nlink (void) const { return m_nlink; }
124 
uid(void)125       uid_t uid (void) const { return m_uid; }
gid(void)126       gid_t gid (void) const { return m_gid; }
127 
size(void)128       off_t size (void) const { return m_size; }
129 
atime(void)130       sys::time atime (void) const { return m_atime; }
mtime(void)131       sys::time mtime (void) const { return m_mtime; }
ctime(void)132       sys::time ctime (void) const { return m_ctime; }
133 
rdev(void)134       dev_t rdev (void) const { return m_rdev; }
135 
blksize(void)136       long blksize (void) const { return m_blksize; }
blocks(void)137       long blocks (void) const { return m_blocks; }
138 
mode(void)139       mode_t mode (void) const { return m_mode; }
140 
141       std::string mode_as_string (void) const;
142 
ok(void)143       bool ok (void) const { return initialized && ! fail; }
144 
145       operator bool () const { return ok (); }
146 
exists(void)147       bool exists (void) const { return ok (); }
148 
error(void)149       std::string error (void) const { return ok () ? "" : errmsg; }
150 
151       // Has the file referenced by this object been modified since TIME?
is_newer(const sys::time & time)152       bool is_newer (const sys::time& time) const { return m_mtime > time; }
153 
154       // It's nice to be able to hide the file_stat object if we don't
155       // really care about it.
156       static int is_newer (const std::string&, const sys::time&);
157 
158     protected:
159 
160       virtual ~base_file_stat (void) = default;
161 
162       // TRUE means we have already called stat.
163       bool initialized;
164 
165       // TRUE means the stat for this file failed.
166       bool fail;
167 
168       // If a failure occurs, this contains the system error text.
169       std::string errmsg;
170 
171       // file type and permissions
172       mode_t m_mode;
173 
174       // serial number
175       ino_t m_ino;
176 
177       // device number
178       dev_t m_dev;
179 
180       // number of links
181       nlink_t m_nlink;
182 
183       // user ID of owner
184       uid_t m_uid;
185 
186       // group ID of owner
187       gid_t m_gid;
188 
189       // size in bytes, for regular files
190       off_t m_size;
191 
192       // time of last access
193       sys::time m_atime;
194 
195       // time of last modification
196       sys::time m_mtime;
197 
198       // time of last file status change
199       sys::time m_ctime;
200 
201       // device number for special files
202       dev_t m_rdev;
203 
204       // best I/O block size
205       long m_blksize;
206 
207       // number of 512-byte blocks allocated
208       long m_blocks;
209     };
210 
211     class
212     OCTAVE_API
213     file_stat : public base_file_stat
214     {
215     public:
216 
217       // This constructor must remain defined in the cpp file rather than in
218       // the header file (bug #50234).
219       file_stat (const std::string& n = "", bool fl = true);
220 
file_stat(const file_stat & fs)221       file_stat (const file_stat& fs)
222         : base_file_stat (fs), file_name (fs.file_name),
223           follow_links (fs.follow_links) { }
224 
225       file_stat& operator = (const file_stat& fs)
226       {
227         if (this != &fs)
228           {
229             base_file_stat::operator = (fs);
230 
231             file_name = fs.file_name;
232             follow_links = fs.follow_links;
233           }
234 
235         return *this;
236       }
237 
238       // This destructor must remain as an empty destructor defined in the
239       // cpp file rather than in the header file (bug #50234).
240       ~file_stat (void);
241 
242       void get_stats (bool force = false)
243       {
244         if (! initialized || force)
245           update_internal (force);
246       }
247 
248       void get_stats (const std::string& n, bool force = false)
249       {
250         if (n != file_name || ! initialized || force)
251           {
252             initialized = false;
253 
254             file_name = n;
255 
256             update_internal (force);
257           }
258       }
259 
260     private:
261 
262       // Name of the file.
263       std::string file_name;
264 
265       // TRUE means follow symbolic links to the ultimate file (stat).
266       // FALSE means get information about the link itself (lstat).
267       bool follow_links;
268 
269       void update_internal (bool force = false);
270     };
271 
272     class
273     OCTAVE_API
274     file_fstat : public base_file_stat
275     {
276     public:
277 
file_fstat(int n)278       file_fstat (int n) : base_file_stat (), fid (n)
279       {
280         update_internal ();
281       }
282 
file_fstat(const file_fstat & fs)283       file_fstat (const file_fstat& fs)
284         : base_file_stat (fs), fid (fs.fid) { }
285 
286       file_fstat& operator = (const file_fstat& fs)
287       {
288         if (this != &fs)
289           {
290             base_file_stat::operator = (fs);
291 
292             fid = fs.fid;
293           }
294 
295         return *this;
296       }
297 
298       ~file_fstat (void) = default;
299 
300       void get_stats (bool force = false)
301       {
302         if (! initialized || force)
303           update_internal (force);
304       }
305 
306       void get_stats (int n, bool force = false)
307       {
308         if (n != fid || ! initialized || force)
309           {
310             initialized = false;
311 
312             fid = n;
313 
314             update_internal (force);
315           }
316       }
317 
318     private:
319 
320       // Open file descriptor.
321       int fid;
322 
323       void update_internal (bool force = false);
324     };
325   }
326 }
327 
328 #endif
329