source: XMLIO_V2/external/src/POCO/Foundation/File_UNIX.hpp @ 80

Last change on this file since 80 was 80, checked in by ymipsl, 14 years ago

ajout lib externe

File size: 9.5 KB
Line 
1//
2// File_UNIX.cpp
3//
4// $Id: //poco/1.3/Foundation/src/File_UNIX.cpp#15 $
5//
6// Library: Foundation
7// Package: Filesystem
8// Module:  File
9//
10// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
11// and Contributors.
12//
13// Permission is hereby granted, free of charge, to any person or organization
14// obtaining a copy of the software and accompanying documentation covered by
15// this license (the "Software") to use, reproduce, display, distribute,
16// execute, and transmit the Software, and to prepare derivative works of the
17// Software, and to permit third-parties to whom the Software is furnished to
18// do so, all subject to the following:
19//
20// The copyright notices in the Software and this entire statement, including
21// the above license grant, this restriction and the following disclaimer,
22// must be included in all copies of the Software, in whole or in part, and
23// all derivative works of the Software, unless such copies or derivative
24// works are solely in the form of machine-executable object code generated by
25// a source language processor.
26//
27// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
28// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
29// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
30// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
31// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
32// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
33// DEALINGS IN THE SOFTWARE.
34//
35
36
37#include <Poco/File_UNIX.h>
38#include <Poco/Buffer.h>
39#include <Poco/Exception.h>
40#include <algorithm>
41#include <sys/stat.h>
42#include <sys/types.h>
43#include <fcntl.h>
44#include <errno.h>
45#include <unistd.h>
46#include <stdio.h>
47#include <utime.h>
48#include <cstring>
49
50
51namespace Poco {
52
53
54FileImpl::FileImpl()
55{
56}
57
58
59FileImpl::FileImpl(const std::string& path): _path(path)
60{
61        std::string::size_type n = _path.size();
62        if (n > 1 && _path[n - 1] == '/')
63                _path.resize(n - 1);
64}
65
66
67FileImpl::~FileImpl()
68{
69}
70
71
72void FileImpl::swapImpl(FileImpl& file)
73{
74        std::swap(_path, file._path);
75}
76
77
78void FileImpl::setPathImpl(const std::string& path)
79{
80        _path = path;
81        std::string::size_type n = _path.size();
82        if (n > 1 && _path[n - 1] == '/')
83                _path.resize(n - 1);
84}
85
86
87bool FileImpl::existsImpl() const
88{
89        poco_assert (!_path.empty());
90
91        struct stat st;
92        return stat(_path.c_str(), &st) == 0;
93}
94
95
96bool FileImpl::canReadImpl() const
97{
98        poco_assert (!_path.empty());
99
100        struct stat st;
101        if (stat(_path.c_str(), &st) == 0)
102        {
103                if (geteuid() == 0)
104                        return true;
105                else if (st.st_uid == geteuid())
106                        return (st.st_mode & S_IRUSR) != 0;
107                else if (st.st_gid == getegid())
108                        return (st.st_mode & S_IRGRP) != 0;
109                else
110                        return (st.st_mode & S_IROTH) != 0;
111        }
112        else handleLastErrorImpl(_path);
113        return false;
114}
115
116
117bool FileImpl::canWriteImpl() const
118{
119        poco_assert (!_path.empty());
120
121        struct stat st;
122        if (stat(_path.c_str(), &st) == 0)
123        {
124                if (geteuid() == 0)
125                        return true;
126                else if (st.st_uid == geteuid())
127                        return (st.st_mode & S_IWUSR) != 0;
128                else if (st.st_gid == getegid())
129                        return (st.st_mode & S_IWGRP) != 0;
130                else
131                        return (st.st_mode & S_IWOTH) != 0;
132        }
133        else handleLastErrorImpl(_path);
134        return false;
135}
136
137
138bool FileImpl::canExecuteImpl() const
139{
140        poco_assert (!_path.empty());
141
142        struct stat st;
143        if (stat(_path.c_str(), &st) == 0)
144        {
145                if (st.st_uid == geteuid() || geteuid() == 0)
146                        return (st.st_mode & S_IXUSR) != 0;
147                else if (st.st_gid == getegid())
148                        return (st.st_mode & S_IXGRP) != 0;
149                else
150                        return (st.st_mode & S_IXOTH) != 0;
151        }
152        else handleLastErrorImpl(_path);
153        return false;
154}
155
156
157bool FileImpl::isFileImpl() const
158{
159        poco_assert (!_path.empty());
160
161        struct stat st;
162        if (stat(_path.c_str(), &st) == 0)
163                return S_ISREG(st.st_mode);
164        else
165                handleLastErrorImpl(_path);
166        return false;
167}
168
169
170bool FileImpl::isDirectoryImpl() const
171{
172        poco_assert (!_path.empty());
173
174        struct stat st;
175        if (stat(_path.c_str(), &st) == 0)
176                return S_ISDIR(st.st_mode);
177        else
178                handleLastErrorImpl(_path);
179        return false;
180}
181
182
183bool FileImpl::isLinkImpl() const
184{
185        poco_assert (!_path.empty());
186
187        struct stat st;
188        if (lstat(_path.c_str(), &st) == 0)
189                return S_ISLNK(st.st_mode);
190        else
191                handleLastErrorImpl(_path);
192        return false;
193}
194
195
196bool FileImpl::isDeviceImpl() const
197{
198        poco_assert (!_path.empty());
199
200        struct stat st;
201        if (stat(_path.c_str(), &st) == 0)
202                return S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode);
203        else
204                handleLastErrorImpl(_path);
205        return false;
206}
207
208
209bool FileImpl::isHiddenImpl() const
210{
211        poco_assert (!_path.empty());
212        Path p(_path);
213        p.makeFile();
214
215        return p.getFileName()[0] == '.';
216}
217
218
219Timestamp FileImpl::createdImpl() const
220{
221        poco_assert (!_path.empty());
222
223#if defined(__APPLE__) && defined(st_birthtime) && !defined(POCO_NO_STAT64) // st_birthtime is available only on 10.5
224        struct stat64 st;
225        if (stat64(_path.c_str(), &st) == 0)
226                return Timestamp::fromEpochTime(st.st_birthtime);
227#elif defined(__FreeBSD__)
228        struct stat st;
229        if (stat(_path.c_str(), &st) == 0)
230                return Timestamp::fromEpochTime(st.st_birthtime);
231#else
232        struct stat st;
233        if (stat(_path.c_str(), &st) == 0)
234                return Timestamp::fromEpochTime(st.st_ctime);
235#endif
236        else
237                handleLastErrorImpl(_path);
238        return 0;
239}
240
241
242Timestamp FileImpl::getLastModifiedImpl() const
243{
244        poco_assert (!_path.empty());
245
246        struct stat st;
247        if (stat(_path.c_str(), &st) == 0)
248                return Timestamp::fromEpochTime(st.st_mtime);
249        else
250                handleLastErrorImpl(_path);
251        return 0;
252}
253
254
255void FileImpl::setLastModifiedImpl(const Timestamp& ts)
256{
257        poco_assert (!_path.empty());
258
259        struct utimbuf tb;
260        tb.actime  = ts.epochTime();
261        tb.modtime = ts.epochTime();
262        if (utime(_path.c_str(), &tb) != 0)
263                handleLastErrorImpl(_path);
264}
265
266
267FileImpl::FileSizeImpl FileImpl::getSizeImpl() const
268{
269        poco_assert (!_path.empty());
270
271        struct stat st;
272        if (stat(_path.c_str(), &st) == 0)
273                return st.st_size;
274        else
275                handleLastErrorImpl(_path);
276        return 0;
277}
278
279
280void FileImpl::setSizeImpl(FileSizeImpl size)
281{
282        poco_assert (!_path.empty());
283
284        if (truncate(_path.c_str(), size) != 0)
285                handleLastErrorImpl(_path);
286}
287
288
289void FileImpl::setWriteableImpl(bool flag)
290{
291        poco_assert (!_path.empty());
292
293        struct stat st;
294        if (stat(_path.c_str(), &st) != 0) 
295                handleLastErrorImpl(_path);
296        mode_t mode;
297        if (flag)
298        {
299                mode = st.st_mode | S_IWUSR;
300        }
301        else
302        {
303                mode_t wmask = S_IWUSR | S_IWGRP | S_IWOTH;
304                mode = st.st_mode & ~wmask;
305        }
306        if (chmod(_path.c_str(), mode) != 0) 
307                handleLastErrorImpl(_path);
308}
309
310
311void FileImpl::setExecutableImpl(bool flag)
312{
313        poco_assert (!_path.empty());
314
315        struct stat st;
316        if (stat(_path.c_str(), &st) != 0) 
317                handleLastErrorImpl(_path);
318        mode_t mode;
319        if (flag)
320        {
321                mode = st.st_mode | S_IXUSR;
322        }
323        else
324        {
325                mode_t wmask = S_IXUSR | S_IXGRP | S_IXOTH;
326                mode = st.st_mode & ~wmask;
327        }
328        if (chmod(_path.c_str(), mode) != 0) 
329                handleLastErrorImpl(_path);
330}
331
332
333void FileImpl::copyToImpl(const std::string& path) const
334{
335        poco_assert (!_path.empty());
336
337        int sd = open(_path.c_str(), O_RDONLY);
338        if (sd == -1) handleLastErrorImpl(_path);
339
340        struct stat st;
341        if (fstat(sd, &st) != 0) 
342        {
343                close(sd);
344                handleLastErrorImpl(_path);
345        }
346        const long blockSize = st.st_blksize;
347
348        int dd = open(path.c_str(), O_CREAT | O_TRUNC | O_WRONLY, st.st_mode & S_IRWXU);
349        if (dd == -1)
350        {
351                close(sd);
352                handleLastErrorImpl(path);
353        }
354        Buffer<char> buffer(blockSize);
355        try
356        {
357                int n;
358                while ((n = read(sd, buffer.begin(), blockSize)) > 0)
359                {
360                        if (write(dd, buffer.begin(), n) != n) 
361                                handleLastErrorImpl(path);
362                }
363                if (n < 0)
364                        handleLastErrorImpl(_path);
365        }
366        catch (...)
367        {
368                close(sd);
369                close(dd);
370                throw;
371        }
372        close(sd);
373        if (fsync(dd) != 0) 
374        {
375                close(dd);
376                handleLastErrorImpl(path);
377        }
378        if (close(dd) != 0)
379                handleLastErrorImpl(path);
380}
381
382
383void FileImpl::renameToImpl(const std::string& path)
384{
385        poco_assert (!_path.empty());
386
387        if (rename(_path.c_str(), path.c_str()) != 0)
388                handleLastErrorImpl(_path);
389}
390
391
392void FileImpl::removeImpl()
393{
394        poco_assert (!_path.empty());
395
396        int rc;
397        if (!isLinkImpl() && isDirectoryImpl())
398                rc = rmdir(_path.c_str());
399        else
400                rc = unlink(_path.c_str());
401        if (rc) handleLastErrorImpl(_path);
402}
403
404
405bool FileImpl::createFileImpl()
406{
407        poco_assert (!_path.empty());
408       
409        int n = open(_path.c_str(), O_WRONLY | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
410        if (n != -1)
411        {
412                close(n);
413                return true;
414        }
415        if (n == -1 && errno == EEXIST)
416                return false;
417        else
418                handleLastErrorImpl(_path);
419        return false;
420}
421
422
423bool FileImpl::createDirectoryImpl()
424{
425        poco_assert (!_path.empty());
426
427        if (existsImpl() && isDirectoryImpl())
428                return false;
429        if (mkdir(_path.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) != 0) 
430                handleLastErrorImpl(_path);
431        return true;
432}
433
434
435void FileImpl::handleLastErrorImpl(const std::string& path)
436{
437        switch (errno)
438        {
439        case EIO:
440                throw IOException(path);
441        case EPERM:
442                throw FileAccessDeniedException("insufficient permissions", path);
443        case EACCES:
444                throw FileAccessDeniedException(path);
445        case ENOENT:
446                throw FileNotFoundException(path);
447        case ENOTDIR:
448                throw OpenFileException("not a directory", path);
449        case EISDIR:
450                throw OpenFileException("not a file", path);
451        case EROFS:
452                throw FileReadOnlyException(path);
453        case EEXIST:
454                throw FileExistsException(path);
455        case ENOSPC:
456                throw FileException("no space left on device", path);
457        case EDQUOT:
458                throw FileException("disk quota exceeded", path);
459#if !defined(_AIX)
460        case ENOTEMPTY:
461                throw FileException("directory not empty", path);
462#endif
463        case ENAMETOOLONG:
464                throw PathSyntaxException(path);
465        case ENFILE:
466        case EMFILE:
467                throw FileException("too many open files", path);
468        default:
469                throw FileException(std::strerror(errno), path);
470        }
471}
472
473
474} // namespace Poco
Note: See TracBrowser for help on using the repository browser.