]> git.lyx.org Git - lyx.git/blob - src/support/fs_extras.C
update to boost 1.34 cvs
[lyx.git] / src / support / fs_extras.C
1 // -*- C++ -*-
2 /* \file fs_extras.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
12 #include <config.h>
13
14 #include "fs_extras.h"
15
16 #include <boost/filesystem/config.hpp>
17 #include <boost/detail/workaround.hpp>
18 #include <boost/throw_exception.hpp>
19
20 #ifdef HAVE_SYS_TYPES_H
21 # include <sys/types.h>
22 #endif
23 #ifdef HAVE_SYS_STAT_H
24 # include <sys/stat.h>
25 #endif
26 #include <fcntl.h>
27
28 // BOOST_POSIX or BOOST_WINDOWS specify which API to use.
29 # if !defined( BOOST_WINDOWS ) && !defined( BOOST_POSIX )
30 #   if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) || defined(__CYGWIN__)
31 #     define BOOST_WINDOWS
32 #   else
33 #     define BOOST_POSIX
34 #   endif
35 # endif
36
37 #if defined (BOOST_WINDOWS)
38 # define WIN32_LEAN_AND_MEAN
39 # include <windows.h>
40 #endif
41
42 namespace fs = boost::filesystem;
43
44 namespace boost {
45 namespace filesystem {
46
47 bool is_readable(path const & ph)
48 {
49 #ifdef BOOST_POSIX
50         return ::access(ph.string().c_str(), R_OK) == 0;
51 #endif
52 #ifdef BOOST_WINDOWS
53         DWORD const attr = ::GetFileAttributes(ph.string().c_str());
54         return attr != INVALID_FILE_ATTRIBUTES &&
55                 (attr & FILE_ATTRIBUTE_DIRECTORY) != FILE_ATTRIBUTE_DIRECTORY;
56 #endif
57 }
58
59
60 bool is_writable(path const & ph)
61 {
62 #ifdef BOOST_POSIX
63         return ::access(ph.string().c_str(), W_OK) == 0;
64 #endif
65 #ifdef BOOST_WINDOWS
66         DWORD const attr = ::GetFileAttributes(ph.string().c_str());
67         if (attr != INVALID_FILE_ATTRIBUTES &&
68             (attr & FILE_ATTRIBUTE_READONLY) != 0) {
69                 // Read-only - no write access
70                 return false;
71         }
72         return attr != INVALID_FILE_ATTRIBUTES &&
73                 (attr & FILE_ATTRIBUTE_DIRECTORY) != FILE_ATTRIBUTE_DIRECTORY;
74 #endif
75 }
76
77
78 bool is_readonly(path const & ph)
79 {
80 #ifdef BOOST_POSIX
81         return is_readable(ph) && !is_writable(ph);
82 #endif
83 #ifdef BOOST_WINDOWS
84         DWORD const attr = ::GetFileAttributes(ph.string().c_str());
85         return (attr != INVALID_FILE_ATTRIBUTES
86                 && (attr & FILE_ATTRIBUTE_READONLY));
87 #endif
88 }
89
90
91 void copy_file(path const & source, path const & target, bool noclobber)
92 {
93
94 #ifdef BOOST_POSIX
95         int const infile = ::open(source.string().c_str(), O_RDONLY);
96         if (infile == -1) {
97                 boost::throw_exception(
98                         filesystem_path_error(
99                                 "boost::filesystem::copy_file",
100                                 source, target,
101                                 fs::lookup_errno(errno)));
102         }
103
104         struct stat source_stat;
105         int const ret = ::fstat(infile, &source_stat);
106         if (ret == -1) {
107                 int err = errno;
108                 ::close(infile);
109                 boost::throw_exception(
110                         filesystem_path_error(
111                                 "boost::filesystem::copy_file",
112                                 source, target,
113                                 fs::lookup_errno(err)));
114         }
115
116         int const flags = O_WRONLY | O_CREAT | (noclobber ? O_EXCL : O_TRUNC);
117
118         int const outfile = ::open(target.string().c_str(), flags, source_stat.st_mode);
119         if (outfile == -1) {
120                 int err = errno;
121                 ::close(infile);
122                 boost::throw_exception(
123                         filesystem_path_error(
124                                 "boost::filesystem::copy_file",
125                                 source, target,
126                                 fs::lookup_errno(err)));
127         }
128
129         std::size_t const buf_sz = 32768;
130         char buf[buf_sz];
131         ssize_t in = -1;
132         ssize_t out = -1;
133
134         while (true) {
135                 in = ::read(infile, buf, buf_sz);
136                 if (in == -1) {
137                         break;
138                 } else if (in == 0) {
139                         break;
140                 } else {
141                         out = ::write(outfile, buf, in);
142                         if (out == -1) {
143                                 break;
144                         }
145                 }
146         }
147
148         int err = errno;
149
150         ::close(infile);
151         ::close(outfile);
152
153         if (in == -1 || out == -1)
154                 boost::throw_exception(
155                         filesystem_path_error(
156                                 "boost::filesystem::copy_file",
157                                 source, target,
158                                 fs::lookup_errno(err)));
159 #endif
160 #ifdef BOOST_WINDOWS
161         if (::CopyFile(source.string().c_str(), target.string().c_str(), noclobber) == 0) {
162                 // CopyFile is probably not setting errno so this is most
163                 // likely wrong.
164                 boost::throw_exception(
165                         filesystem_path_error(
166                                 "boost::filesystem::copy_file",
167                                 source, target,
168                                 fs::lookup_error_code(errno)));
169         }
170 #endif
171 }
172
173 }
174 }