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