3 * This file is part of LyX, the document processor.
4 * Licence details can be found in the file COPYING.
6 * \author Lars Gullik Bjønnes
8 * Full author contact details are available in file CREDITS.
13 #include "support/FileInfo.h"
14 #include "support/lstrings.h"
16 #include <boost/assert.hpp>
19 #include <sys/types.h>
28 # define S_IRUSR S_IREAD
30 # define S_IRUSR 00400
36 # define S_IWUSR S_IWRITE
38 # define S_IWUSR 00200
44 # define S_IXUSR S_IEXEC
46 # define S_IXUSR 00100
50 #ifdef STAT_MACROS_BROKEN
63 #if !defined(S_ISBLK) && defined(S_IFBLK)
64 #define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
66 #if !defined(S_ISCHR) && defined(S_IFCHR)
67 #define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
69 #if !defined(S_ISDIR) && defined(S_IFDIR)
70 #define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
72 #if !defined(S_ISREG) && defined(S_IFREG)
73 #define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
75 #if !defined(S_ISFIFO) && defined(S_IFIFO)
76 #define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
78 #if !defined(S_ISLNK) && defined(S_IFLNK)
79 #define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
81 #if !defined(S_ISSOCK) && defined(S_IFSOCK)
82 #define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
84 #if !defined(S_ISMPB) && defined(S_IFMPB) /* V7 */
85 #define S_ISMPB(m) (((m) & S_IFMT) == S_IFMPB)
86 #define S_ISMPC(m) (((m) & S_IFMT) == S_IFMPC)
88 #if !defined(S_ISNWK) && defined(S_IFNWK) /* HP/UX */
89 #define S_ISNWK(m) (((m) & S_IFMT) == S_IFNWK)
95 // builds 'rwx' string describing file access rights
96 void flagRWX(mode_t i, char * str)
98 str[0] = (i & S_IRUSR) ? 'r' : '-';
99 str[1] = (i & S_IWUSR) ? 'w' : '-';
100 str[2] = (i & S_IXUSR) ? 'x' : '-';
103 // updates mode string to match suid/sgid/sticky bits
104 void setSticky(mode_t i, char * str)
108 str[3] = (str[3] == 'x') ? 's' : 'S';
112 str[6] = (str[6] == 'x') ? 's' : 'S';
116 str[9] = (str[9] == 'x') ? 's' : 'S';
120 // returns a letter describing a file type (ls style)
121 char typeLetter(mode_t i)
124 if (S_ISBLK(i)) return 'b';
126 if (S_ISCHR(i)) return 'c';
127 if (S_ISDIR(i)) return 'd';
128 if (S_ISREG(i)) return '-';
130 if (S_ISFIFO(i)) return 'p';
133 if (S_ISLNK(i)) return 'l';
136 if (S_ISSOCK(i)) return 's';
139 if (S_ISMPC(i)) return 'm';
142 if (S_ISNWK(i)) return 'n';
159 FileInfo::FileInfo(string const & path, bool link)
160 // Win32 stat() doesn't dig trailing slashes.
161 // Posix stat() doesn't care, but we'll remove it anyway.
162 : fname_(rtrim(path, "/"))
169 FileInfo::FileInfo(int fildes)
172 status_ = fstat(fildes, &buf_);
178 void FileInfo::init()
185 void FileInfo::dostat(bool link)
189 status_ = ::lstat(fname_.c_str(), &buf_);
191 status_ = ::stat(fname_.c_str(), &buf_);
193 status_ = ::stat(fname_.c_str(), &buf_);
201 FileInfo & FileInfo::newFile(string const & path, bool link)
203 // Win32 stat() doesn't dig trailing slashes.
204 // Posix stat() doesn't care, but we'll remove it anyway.
205 fname_ = rtrim(path, "/");
213 FileInfo & FileInfo::newFile(int fildes)
217 status_ = fstat(fildes, &buf_);
224 // should not be in FileInfo
225 char FileInfo::typeIndicator() const
227 BOOST_ASSERT(isOK());
228 if (S_ISDIR(buf_.st_mode))
231 if (S_ISLNK(buf_.st_mode))
235 if (S_ISFIFO(buf_.st_mode))
239 if (S_ISSOCK(buf_.st_mode))
242 if (S_ISREG(buf_.st_mode) && (buf_.st_mode & (S_IEXEC | S_IXGRP | S_IXOTH)))
248 mode_t FileInfo::getMode() const
250 BOOST_ASSERT(isOK());
255 // should not be in FileInfo
256 string FileInfo::modeString() const
258 BOOST_ASSERT(isOK());
260 str[0] = typeLetter(buf_.st_mode);
261 flagRWX((buf_.st_mode & 0700) << 0, &str[1]);
262 flagRWX((buf_.st_mode & 0070) << 3, &str[4]);
263 flagRWX((buf_.st_mode & 0007) << 6, &str[7]);
264 setSticky(buf_.st_mode, str);
271 time_t FileInfo::getModificationTime() const
273 BOOST_ASSERT(isOK());
274 return buf_.st_mtime;
278 time_t FileInfo::getAccessTime() const
280 BOOST_ASSERT(isOK());
281 return buf_.st_atime;
285 time_t FileInfo::getStatusChangeTime() const
287 BOOST_ASSERT(isOK());
288 return buf_.st_ctime;
292 uid_t FileInfo::getUid() const
294 BOOST_ASSERT(isOK());
299 gid_t FileInfo::getGid() const
301 BOOST_ASSERT(isOK());
306 off_t FileInfo::getSize() const
308 BOOST_ASSERT(isOK());
313 int FileInfo::getError() const
319 bool FileInfo::isOK() const
325 bool FileInfo::isLink() const
327 BOOST_ASSERT(isOK());
329 return S_ISLNK(buf_.st_mode);
336 bool FileInfo::isRegular() const
338 BOOST_ASSERT(isOK());
339 return S_ISREG(buf_.st_mode);
343 bool FileInfo::isDir() const
345 BOOST_ASSERT(isOK());
346 return S_ISDIR(buf_.st_mode);
350 bool FileInfo::isChar() const
352 BOOST_ASSERT(isOK());
353 return S_ISCHR(buf_.st_mode);
357 bool FileInfo::isBlock() const
359 BOOST_ASSERT(isOK());
360 return S_ISBLK(buf_.st_mode);
364 bool FileInfo::isFifo() const
366 BOOST_ASSERT(isOK());
367 return S_ISFIFO(buf_.st_mode);
371 bool FileInfo::isSocket() const
373 BOOST_ASSERT(isOK());
375 return S_ISSOCK(buf_.st_mode);
382 // should not be in FileInfo
383 bool FileInfo::access(int p) const
385 // if we don't have a filename we fail
389 // If we were really kind, we would also tell why
390 // the file access failed.
391 return ::access(fname_.c_str(), p) == 0;
394 } // namespace support