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