]> git.lyx.org Git - lyx.git/blob - src/support/FileInfo.C
* lyxfunctional.h: delete compare_memfun and helper classes
[lyx.git] / src / support / FileInfo.C
1 /**
2  * \file FileInfo.C
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Lars Gullik Bjønnes
7  *
8  * Full author contact details are available in file CREDITS.
9  */
10
11 #include <config.h>
12
13 #include "FileInfo.h"
14
15 #include <boost/assert.hpp>
16
17 #include <cerrno>
18
19
20 using std::string;
21
22
23 #if !S_IRUSR
24 # if S_IREAD
25 #  define S_IRUSR S_IREAD
26 # else
27 #  define S_IRUSR 00400
28 # endif
29 #endif
30
31 #if !S_IWUSR
32 # if S_IWRITE
33 #  define S_IWUSR S_IWRITE
34 # else
35 #  define S_IWUSR 00200
36 # endif
37 #endif
38
39 #if !S_IXUSR
40 # if S_IEXEC
41 #  define S_IXUSR S_IEXEC
42 # else
43 #  define S_IXUSR 00100
44 # endif
45 #endif
46
47 #ifdef STAT_MACROS_BROKEN
48 #undef S_ISBLK
49 #undef S_ISCHR
50 #undef S_ISDIR
51 #undef S_ISFIFO
52 #undef S_ISLNK
53 #undef S_ISMPB
54 #undef S_ISMPC
55 #undef S_ISNWK
56 #undef S_ISREG
57 #undef S_ISSOCK
58 #endif
59
60 #if !defined(S_ISBLK) && defined(S_IFBLK)
61 #define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
62 #endif
63 #if !defined(S_ISCHR) && defined(S_IFCHR)
64 #define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
65 #endif
66 #if !defined(S_ISDIR) && defined(S_IFDIR)
67 #define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
68 #endif
69 #if !defined(S_ISREG) && defined(S_IFREG)
70 #define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
71 #endif
72 #if !defined(S_ISFIFO) && defined(S_IFIFO)
73 #define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
74 #endif
75 #if !defined(S_ISLNK) && defined(S_IFLNK)
76 #define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
77 #endif
78 #if !defined(S_ISSOCK) && defined(S_IFSOCK)
79 #define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
80 #endif
81 #if !defined(S_ISMPB) && defined(S_IFMPB) /* V7 */
82 #define S_ISMPB(m) (((m) & S_IFMT) == S_IFMPB)
83 #define S_ISMPC(m) (((m) & S_IFMT) == S_IFMPC)
84 #endif
85 #if !defined(S_ISNWK) && defined(S_IFNWK) /* HP/UX */
86 #define S_ISNWK(m) (((m) & S_IFMT) == S_IFNWK)
87 #endif
88
89
90 namespace {
91
92 // builds 'rwx' string describing file access rights
93 void flagRWX(mode_t i, char * str)
94 {
95         str[0] = (i & S_IRUSR) ? 'r' : '-';
96         str[1] = (i & S_IWUSR) ? 'w' : '-';
97         str[2] = (i & S_IXUSR) ? 'x' : '-';
98 }
99
100 // updates mode string to match suid/sgid/sticky bits
101 void setSticky(mode_t i, char * str)
102 {
103 #ifdef S_ISUID
104         if (i & S_ISUID)
105                 str[3] = (str[3] == 'x') ? 's' : 'S';
106 #endif
107 #ifdef S_ISGID
108         if (i & S_ISGID)
109                 str[6] = (str[6] == 'x') ? 's' : 'S';
110 #endif
111 #ifdef S_ISVTX
112         if (i & S_ISVTX)
113                 str[9] = (str[9] == 'x') ? 's' : 'S';
114 #endif
115 }
116
117 // returns a letter describing a file type (ls style)
118 char typeLetter(mode_t i)
119 {
120 #ifdef S_ISBLK
121         if (S_ISBLK(i)) return 'b';
122 #endif
123         if (S_ISCHR(i)) return 'c';
124         if (S_ISDIR(i)) return 'd';
125         if (S_ISREG(i)) return '-';
126 #ifdef S_ISFIFO
127         if (S_ISFIFO(i)) return 'p';
128 #endif
129 #ifdef S_ISLNK
130         if (S_ISLNK(i)) return 'l';
131 #endif
132 #ifdef S_ISSOCK
133         if (S_ISSOCK(i)) return 's';
134 #endif
135 #ifdef S_ISMPC
136         if (S_ISMPC(i)) return 'm';
137 #endif
138 #ifdef S_ISNWK
139         if (S_ISNWK(i)) return 'n';
140 #endif
141         return '?';
142 }
143
144
145 } // namespace anon
146
147
148 namespace lyx {
149 namespace support {
150
151 FileInfo::FileInfo()
152 {
153         init();
154 }
155
156
157 FileInfo::FileInfo(string const & path, bool link)
158         : fname_(path)
159 {
160         init();
161         dostat(link);
162 }
163
164
165 FileInfo::FileInfo(int fildes)
166 {
167         init();
168         status_ = fstat(fildes, &buf_);
169         if (status_)
170                 err_ = errno;
171 }
172
173
174 void FileInfo::init()
175 {
176         status_ = 0;
177         err_ = NoErr;
178 }
179
180
181 void FileInfo::dostat(bool link)
182 {
183         if (link)
184                 status_ = ::lstat(fname_.c_str(), &buf_);
185         else
186                 status_ = ::stat(fname_.c_str(), &buf_);
187         if (status_)
188                 err_ = errno;
189 }
190
191
192 FileInfo & FileInfo::newFile(string const & path, bool link)
193 {
194         fname_  = path;
195         status_ = 0;
196         err_    = NoErr;
197         dostat(link);
198         return *this;
199 }
200
201
202 FileInfo & FileInfo::newFile(int fildes)
203 {
204         status_ = 0;
205         err_    = NoErr;
206         status_ = fstat(fildes, &buf_);
207         if (status_)
208                 err_ = errno;
209         return *this;
210 }
211
212
213 // should not be in FileInfo
214 char FileInfo::typeIndicator() const
215 {
216         BOOST_ASSERT(isOK());
217         if (S_ISDIR(buf_.st_mode))
218                 return '/';
219 #ifdef S_ISLNK
220         if (S_ISLNK(buf_.st_mode))
221                 return '@';
222 #endif
223 #ifdef S_ISFIFO
224         if (S_ISFIFO(buf_.st_mode))
225                 return '|';
226 #endif
227 #ifdef S_ISSOCK
228         if (S_ISSOCK(buf_.st_mode))
229                 return '=';
230 #endif
231         if (S_ISREG(buf_.st_mode) && (buf_.st_mode & (S_IEXEC | S_IXGRP | S_IXOTH)))
232                 return '*';
233         return ' ';
234 }
235
236
237 mode_t FileInfo::getMode() const
238 {
239         BOOST_ASSERT(isOK());
240         return buf_.st_mode;
241 }
242
243
244 // should not be in FileInfo
245 string FileInfo::modeString() const
246 {
247         BOOST_ASSERT(isOK());
248         char str[11];
249         str[0] = typeLetter(buf_.st_mode);
250         flagRWX((buf_.st_mode & 0700) << 0, &str[1]);
251         flagRWX((buf_.st_mode & 0070) << 3, &str[4]);
252         flagRWX((buf_.st_mode & 0007) << 6, &str[7]);
253         setSticky(buf_.st_mode, str);
254         str[10] = 0;
255         return str;
256 }
257
258
259
260 time_t FileInfo::getModificationTime() const
261 {
262         BOOST_ASSERT(isOK());
263         return buf_.st_mtime;
264 }
265
266
267 time_t FileInfo::getAccessTime() const
268 {
269         BOOST_ASSERT(isOK());
270         return buf_.st_atime;
271 }
272
273
274 time_t FileInfo::getStatusChangeTime() const
275 {
276         BOOST_ASSERT(isOK());
277         return buf_.st_ctime;
278 }
279
280
281 nlink_t FileInfo::getNumberOfLinks() const
282 {
283         BOOST_ASSERT(isOK());
284         return buf_.st_nlink;
285 }
286
287
288 uid_t FileInfo::getUid() const
289 {
290         BOOST_ASSERT(isOK());
291         return buf_.st_uid;
292 }
293
294
295 gid_t FileInfo::getGid() const
296 {
297         BOOST_ASSERT(isOK());
298         return buf_.st_gid;
299 }
300
301
302 off_t FileInfo::getSize() const
303 {
304         BOOST_ASSERT(isOK());
305         return buf_.st_size;
306 }
307
308
309 int FileInfo::getError() const
310 {
311         return err_;
312 }
313
314
315 bool FileInfo::isOK() const
316 {
317         return status_ == 0;
318 }
319
320
321 bool FileInfo::isLink() const
322 {
323         BOOST_ASSERT(isOK());
324         return S_ISLNK(buf_.st_mode);
325 }
326
327
328 bool FileInfo::isRegular() const
329 {
330         BOOST_ASSERT(isOK());
331         return S_ISREG(buf_.st_mode);
332 }
333
334
335 bool FileInfo::isDir() const
336 {
337         BOOST_ASSERT(isOK());
338         return S_ISDIR(buf_.st_mode);
339 }
340
341
342 bool FileInfo::isChar() const
343 {
344         BOOST_ASSERT(isOK());
345         return S_ISCHR(buf_.st_mode);
346 }
347
348
349 bool FileInfo::isBlock() const
350 {
351         BOOST_ASSERT(isOK());
352         return S_ISBLK(buf_.st_mode);
353 }
354
355
356 bool FileInfo::isFifo() const
357 {
358         BOOST_ASSERT(isOK());
359         return S_ISFIFO(buf_.st_mode);
360 }
361
362
363 bool FileInfo::isSocket() const
364 {
365         BOOST_ASSERT(isOK());
366 #ifdef S_ISSOCK
367         return S_ISSOCK(buf_.st_mode);
368 #else
369         return false;
370 #endif
371 }
372
373
374 // should not be in FileInfo
375 bool FileInfo::access(int p) const
376 {
377         // if we don't have a filename we fail
378         if (fname_.empty())
379                 return false;
380
381         // If we were really kind, we would also tell why
382         // the file access failed.
383         return ::access(fname_.c_str(), p) == 0;
384 }
385
386 } // namespace support
387 } // namespace lyx