]> git.lyx.org Git - lyx.git/blob - src/support/fs_extras.C
Asgers Win32 changes to fs_extras
[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 namespace fs = boost::filesystem;
26
27 namespace boost {
28 namespace filesystem {
29
30 bool is_readable(path const & ph)
31 {
32 #ifdef BOOST_POSIX
33         return ::access(ph.string().c_str(), R_OK) == 0;
34 #endif
35 #ifdef BOOST_WINDOWS
36         DWORD const attr = ::GetFileAttributes(ph.string().c_str());
37         return attr != INVALID_FILE_ATTRIBUTES &&
38                 (attr & FILE_ATTRIBUTE_DIRECTORY) != FILE_ATTRIBUTE_DIRECTORY;
39 #endif
40 }
41
42
43 bool is_writable(path const & ph)
44 {
45 #ifdef BOOST_POSIX
46         return ::access(ph.string().c_str(), W_OK) == 0;
47 #endif
48 #ifdef BOOST_WINDOWS
49         DWORD const attr = ::GetFileAttributes(ph.string().c_str());
50         if (attr != INVALID_FILE_ATTRIBUTES &&
51             (attr & FILE_ATTRIBUTE_READONLY) != 0) {
52                 // Read-only - no write access
53                 return false;
54         }
55         return attr != INVALID_FILE_ATTRIBUTES &&
56                 (attr & FILE_ATTRIBUTE_DIRECTORY) != FILE_ATTRIBUTE_DIRECTORY;
57 #endif
58 }
59
60
61 bool is_readonly(path const & ph)
62 {
63 #ifdef BOOST_POSIX
64         return is_readable(ph) && !is_writable(ph);
65 #endif
66 #ifdef BOOST_WINDOWS
67         DWORD const attr = ::GetFileAttributes(ph.string().c_str());
68         return (attr != INVALID_FILE_ATTRIBUTES
69                 && (attr & FILE_ATTRIBUTE_READONLY));
70 #endif
71 }
72
73
74 void copy_file(path const & source, path const & target, bool noclobber)
75 {
76
77 #ifdef BOOST_POSIX
78         int const infile = ::open(source.string().c_str(), O_RDONLY);
79         if (infile == -1) {
80                 boost::throw_exception(
81                         filesystem_error(
82                                 "boost::filesystem::copy_file",
83                                 source, target,
84                                 fs::detail::system_error_code()));
85         }
86
87         struct stat source_stat;
88         int const ret = ::fstat(infile, &source_stat);
89         if (ret == -1) {
90                 ::close(infile);
91                 boost::throw_exception(
92                         filesystem_error(
93                                 "boost::filesystem::copy_file",
94                                 source, target,
95                                 fs::detail::system_error_code()));
96         }
97
98         int const flags = O_WRONLY | O_CREAT | (noclobber ? O_EXCL : O_TRUNC);
99
100         int const outfile = ::open(target.string().c_str(), flags, source_stat.st_mode);
101         if (outfile == -1) {
102                 ::close(infile);
103                 boost::throw_exception(
104                         filesystem_error(
105                                 "boost::filesystem::copy_file",
106                                 source, target,
107                                 fs::detail::system_error_code()));
108         }
109
110         std::size_t const buf_sz = 32768;
111         char buf[buf_sz];
112         ssize_t in = -1;
113         ssize_t out = -1;
114
115         while (true) {
116                 in = ::read(infile, buf, buf_sz);
117                 if (in == -1) {
118                         break;
119                 } else if (in == 0) {
120                         break;
121                 } else {
122                         out = ::write(outfile, buf, in);
123                         if (out == -1) {
124                                 break;
125                         }
126                 }
127         }
128
129         ::close(infile);
130         ::close(outfile);
131
132         if (in == -1 || out == -1)
133                 boost::throw_exception(
134                         filesystem_error(
135                                 "boost::filesystem::copy_file",
136                                 source, target,
137                                 fs::detail::system_error_code()));
138 #endif
139 #ifdef BOOST_WINDOWS
140         if (::CopyFile(source.string().c_str(), target.string().c_str(), !noclobber) == 0) {
141                 boost::throw_exception(
142                         filesystem_error(
143                                 "boost::filesystem::copy_file",
144                                 source, target,
145                                 fs::detail::system_error_code()));
146         }
147 #endif
148 }
149
150 }
151 }