supported to write UTF-8 for pax
@@ -1,6 +1,6 @@ | ||
1 | 1 | // headers.hpp: tar headers |
2 | 2 | |
3 | -// Copyright Takeshi Mouri 2006, 2007. | |
3 | +// Copyright Takeshi Mouri 2006-2008. | |
4 | 4 | // Distributed under the Boost Software License, Version 1.0. |
5 | 5 | // (See accompanying file LICENSE_1_0.txt or copy at |
6 | 6 | // http://www.boost.org/LICENSE_1_0.txt) |
@@ -22,9 +22,13 @@ | ||
22 | 22 | |
23 | 23 | namespace hamigaki { namespace archivers { namespace tar { |
24 | 24 | |
25 | -struct header | |
25 | +template<class Path> | |
26 | +struct basic_header | |
26 | 27 | { |
27 | - boost::filesystem::path path; | |
28 | + typedef Path path_type; | |
29 | + typedef typename Path::string_type string_type; | |
30 | + | |
31 | + Path path; | |
28 | 32 | boost::uint16_t permissions; |
29 | 33 | boost::intmax_t uid; |
30 | 34 | boost::intmax_t gid; |
@@ -33,15 +37,15 @@ | ||
33 | 37 | boost::optional<filesystem::timestamp> access_time; |
34 | 38 | boost::optional<filesystem::timestamp> change_time; |
35 | 39 | char type_flag; |
36 | - boost::filesystem::path link_path; | |
40 | + Path link_path; | |
37 | 41 | file_format format; |
38 | - std::string user_name; | |
39 | - std::string group_name; | |
42 | + string_type user_name; | |
43 | + string_type group_name; | |
40 | 44 | boost::uint16_t dev_major; |
41 | 45 | boost::uint16_t dev_minor; |
42 | - std::string comment; | |
46 | + string_type comment; | |
43 | 47 | |
44 | - header() | |
48 | + basic_header() | |
45 | 49 | : permissions(0644), uid(0), gid(0), file_size(0) |
46 | 50 | , type_flag(tar::type_flag::regular), format(gnu) |
47 | 51 | , dev_major(0), dev_minor(0) |
@@ -98,6 +102,11 @@ | ||
98 | 102 | } |
99 | 103 | }; |
100 | 104 | |
105 | +typedef basic_header<boost::filesystem::path> header; | |
106 | +#if !defined(BOOST_FILESYSTEM_NARROW_ONLY) | |
107 | +typedef basic_header<boost::filesystem::wpath> wheader; | |
108 | +#endif | |
109 | + | |
101 | 110 | } } } // End namespaces tar, archivers, hamigaki. |
102 | 111 | |
103 | 112 | #endif // HAMIGAKI_ARCHIVERS_TAR_HEADERS_HPP |
@@ -22,7 +22,7 @@ | ||
22 | 22 | #include <algorithm> |
23 | 23 | #include <cstring> |
24 | 24 | |
25 | -namespace hamigaki { namespace archivers { namespace detail { | |
25 | +namespace hamigaki { namespace archivers { namespace tar_detail { | |
26 | 26 | |
27 | 27 | template<std::size_t Size> |
28 | 28 | inline bool is_valid(const char (&s)[Size]) |
@@ -97,11 +97,11 @@ | ||
97 | 97 | if (std::memcmp(raw.magic, "ustar", 5) != 0) |
98 | 98 | throw BOOST_IOSTREAMS_FAILURE("unknown tar header format"); |
99 | 99 | |
100 | - if (!detail::is_valid(raw.uname) || !detail::is_valid(raw.gname)) | |
100 | + if (!tar_detail::is_valid(raw.uname) || !tar_detail::is_valid(raw.gname)) | |
101 | 101 | throw BOOST_IOSTREAMS_FAILURE("invalid tar header"); |
102 | 102 | |
103 | - const boost::filesystem::path name(detail::read_string(raw.name)); | |
104 | - const boost::filesystem::path prefix(detail::read_string(raw.prefix)); | |
103 | + const boost::filesystem::path name(tar_detail::read_string(raw.name)); | |
104 | + const boost::filesystem::path prefix(tar_detail::read_string(raw.prefix)); | |
105 | 105 | |
106 | 106 | tar::header head; |
107 | 107 |
@@ -116,27 +116,28 @@ | ||
116 | 116 | head.path = prefix / name; |
117 | 117 | } |
118 | 118 | |
119 | - head.permissions = detail::read_oct<boost::uint16_t>(raw.mode); | |
120 | - head.uid = detail::read_oct<boost::int32_t>(raw.uid); | |
121 | - head.gid = detail::read_oct<boost::int32_t>(raw.gid); | |
122 | - head.file_size = detail::read_oct<boost::uint64_t>(raw.size); | |
119 | + head.permissions = tar_detail::read_oct<boost::uint16_t>(raw.mode); | |
120 | + head.uid = tar_detail::read_oct<boost::int32_t>(raw.uid); | |
121 | + head.gid = tar_detail::read_oct<boost::int32_t>(raw.gid); | |
122 | + head.file_size = tar_detail::read_oct<boost::uint64_t>(raw.size); | |
123 | 123 | head.modified_time = |
124 | 124 | filesystem::timestamp::from_time_t( |
125 | - detail::read_oct<std::time_t>(raw.mtime)); | |
125 | + tar_detail::read_oct<std::time_t>(raw.mtime)); | |
126 | 126 | |
127 | - detail::uint17_t chksum = detail::read_oct<detail::uint17_t>(raw.chksum); | |
127 | + detail::uint17_t chksum = | |
128 | + tar_detail::read_oct<detail::uint17_t>(raw.chksum); | |
128 | 129 | if (detail::tar_checksum(block) != chksum) |
129 | 130 | throw BOOST_IOSTREAMS_FAILURE("invalid tar checksum"); |
130 | 131 | |
131 | 132 | head.type_flag = raw.typeflag ? raw.typeflag : '0'; |
132 | - head.link_path = detail::read_string(raw.linkname); | |
133 | + head.link_path = tar_detail::read_string(raw.linkname); | |
133 | 134 | |
134 | - head.user_name = detail::read_c_string(raw.uname); | |
135 | - head.group_name = detail::read_c_string(raw.gname); | |
135 | + head.user_name = tar_detail::read_c_string(raw.uname); | |
136 | + head.group_name = tar_detail::read_c_string(raw.gname); | |
136 | 137 | if ((head.format != tar::gnu) || (head.is_device())) |
137 | 138 | { |
138 | - head.dev_major = detail::read_oct<boost::uint16_t>(raw.devmajor); | |
139 | - head.dev_minor = detail::read_oct<boost::uint16_t>(raw.devminor); | |
139 | + head.dev_major = tar_detail::read_oct<boost::uint16_t>(raw.devmajor); | |
140 | + head.dev_minor = tar_detail::read_oct<boost::uint16_t>(raw.devminor); | |
140 | 141 | } |
141 | 142 | else |
142 | 143 | { |
@@ -147,6 +148,10 @@ | ||
147 | 148 | return head; |
148 | 149 | } |
149 | 150 | |
151 | +} } } // End namespaces tar_detail, archivers, hamigaki. | |
152 | + | |
153 | +namespace hamigaki { namespace archivers { namespace detail { | |
154 | + | |
150 | 155 | template<class Source> |
151 | 156 | class basic_ustar_file_source_impl : private boost::noncopyable |
152 | 157 | { |
@@ -184,7 +189,7 @@ | ||
184 | 189 | iostreams::blocking_read(src_, block_, sizeof(block_)); |
185 | 190 | return false; |
186 | 191 | } |
187 | - header_ = detail::read_tar_header(block_); | |
192 | + header_ = tar_detail::read_tar_header(block_); | |
188 | 193 | |
189 | 194 | return true; |
190 | 195 | } |
@@ -11,9 +11,62 @@ | ||
11 | 11 | #define HAMIGAKI_ARCHIVERS_DETAIL_TAR_FILE_SINK_IMPL_HPP |
12 | 12 | |
13 | 13 | #include <hamigaki/archivers/detail/ustar_file_sink_impl.hpp> |
14 | +#include <hamigaki/charset/code_page.hpp> | |
15 | +#include <hamigaki/charset/utf8.hpp> | |
14 | 16 | |
15 | -namespace hamigaki { namespace archivers { namespace detail { | |
17 | +namespace hamigaki { namespace archivers { namespace tar_detail { | |
16 | 18 | |
19 | +inline std::string to_tar_string(const std::string& s) | |
20 | +{ | |
21 | + return s; | |
22 | +} | |
23 | + | |
24 | +inline std::string to_pax_string(const std::string& s) | |
25 | +{ | |
26 | + return charset::to_utf8(charset::from_code_page(s, 0)); | |
27 | +} | |
28 | + | |
29 | +inline tar::header to_narrow(const tar::header& head) | |
30 | +{ | |
31 | + return head; | |
32 | +} | |
33 | + | |
34 | +#if !defined(BOOST_FILESYSTEM_NARROW_ONLY) | |
35 | +inline std::string to_tar_string(const std::wstring& ws) | |
36 | +{ | |
37 | + return charset::to_code_page(ws, 0, "_"); | |
38 | +} | |
39 | + | |
40 | +inline std::string to_pax_string(const std::wstring& ws) | |
41 | +{ | |
42 | + return charset::to_utf8(ws); | |
43 | +} | |
44 | + | |
45 | +inline tar::header to_narrow(const tar::wheader& head) | |
46 | +{ | |
47 | + tar::header tmp; | |
48 | + | |
49 | + tmp.path = tar_detail::to_tar_string(head.path.string()); | |
50 | + tmp.permissions = head.permissions; | |
51 | + tmp.uid = head.uid; | |
52 | + tmp.gid = head.gid; | |
53 | + tmp.file_size = head.file_size; | |
54 | + tmp.modified_time = head.modified_time; | |
55 | + tmp.access_time = head.access_time; | |
56 | + tmp.change_time = head.change_time; | |
57 | + tmp.type_flag = head.type_flag; | |
58 | + tmp.link_path = tar_detail::to_tar_string(head.link_path.string()); | |
59 | + tmp.format = head.format; | |
60 | + tmp.user_name = charset::to_code_page(head.user_name, 0); | |
61 | + tmp.group_name = charset::to_code_page(head.group_name, 0); | |
62 | + tmp.dev_major = head.dev_major; | |
63 | + tmp.dev_minor = head.dev_minor; | |
64 | + tmp.comment = charset::to_code_page(head.comment, 0); | |
65 | + | |
66 | + return tmp; | |
67 | +} | |
68 | +#endif | |
69 | + | |
17 | 70 | inline std::string |
18 | 71 | make_ex_header_recoed(const std::string& key, const std::string value) |
19 | 72 | { |
@@ -38,9 +91,15 @@ | ||
38 | 91 | { |
39 | 92 | return (static_cast<unsigned char>(c) & 0x80) != 0; |
40 | 93 | } |
94 | + | |
95 | + bool operator()(wchar_t wc) const | |
96 | + { | |
97 | + return static_cast<boost::uint32_t>(wc) > 0x7F; | |
98 | + } | |
41 | 99 | }; |
42 | 100 | |
43 | -inline bool is_non_ascii(const std::string& s) | |
101 | +template<class String> | |
102 | +inline bool is_non_ascii(const String& s) | |
44 | 103 | { |
45 | 104 | return std::find_if(s.begin(), s.end(), is_non_ascii_func()) != s.end(); |
46 | 105 | } |
@@ -81,7 +140,11 @@ | ||
81 | 140 | return to_dec<char>(x.seconds); |
82 | 141 | } |
83 | 142 | |
84 | -template<class Sink> | |
143 | +} } } // End namespaces tar_detail, archivers, hamigaki. | |
144 | + | |
145 | +namespace hamigaki { namespace archivers { namespace detail { | |
146 | + | |
147 | +template<class Sink, class Path> | |
85 | 148 | class basic_tar_file_sink_impl |
86 | 149 | { |
87 | 150 | private: |
@@ -88,33 +151,42 @@ | ||
88 | 151 | typedef detail::basic_ustar_file_sink_impl<Sink> ustar_type; |
89 | 152 | |
90 | 153 | public: |
154 | + typedef Path path_type; | |
155 | + typedef tar::basic_header<Path> header_type; | |
156 | + | |
91 | 157 | explicit basic_tar_file_sink_impl(const Sink& sink) : ustar_(sink) |
92 | 158 | { |
93 | 159 | } |
94 | 160 | |
95 | - void create_entry(const tar::header& head) | |
161 | + void create_entry(const header_type& head) | |
96 | 162 | { |
97 | - tar::header local = head; | |
163 | + tar::header local = tar_detail::to_narrow(head); | |
98 | 164 | |
99 | - std::string name = head.path.string(); | |
165 | + std::string name = tar_detail::to_tar_string(head.path.string()); | |
100 | 166 | std::string prefix; |
101 | 167 | if ((head.format != tar::gnu) && |
102 | 168 | (name.size() > tar::raw_header::name_size) ) |
103 | 169 | { |
104 | - name = head.path.leaf(); | |
105 | - prefix = head.path.branch_path().string(); | |
170 | + name = tar_detail::to_tar_string(head.path.leaf()); | |
171 | + prefix = | |
172 | + tar_detail::to_tar_string(head.path.branch_path().string()); | |
106 | 173 | } |
107 | 174 | |
108 | - std::string long_link = head.link_path.string(); | |
175 | + std::string long_link = | |
176 | + tar_detail::to_tar_string(head.link_path.string()); | |
109 | 177 | if (head.format == tar::pax) |
110 | 178 | { |
111 | 179 | std::string ex; |
112 | 180 | if ((name.size() > tar::raw_header::name_size) || |
113 | - (prefix.size() > tar::raw_header::prefix_size)) | |
181 | + (prefix.size() > tar::raw_header::prefix_size) || | |
182 | + tar_detail::is_non_ascii(head.path.string()) ) | |
114 | 183 | { |
115 | - std::string long_name = head.path.string(); | |
116 | - ex += detail::make_ex_header_recoed("path", long_name); | |
184 | + std::string path = | |
185 | + tar_detail::to_pax_string(head.path.string()); | |
186 | + ex += tar_detail::make_ex_header_recoed("path", path); | |
117 | 187 | |
188 | + std::string long_name = | |
189 | + tar_detail::to_tar_string(head.path.string()); | |
118 | 190 | long_name.resize(tar::raw_header::name_size); |
119 | 191 | local.path = long_name; |
120 | 192 | } |
@@ -121,7 +193,7 @@ | ||
121 | 193 | |
122 | 194 | if ((head.uid < 0) || (head.uid > tar::raw_header::max_uid)) |
123 | 195 | { |
124 | - ex += detail:: | |
196 | + ex += tar_detail:: | |
125 | 197 | make_ex_header_recoed("uid", to_dec<char>(head.uid)); |
126 | 198 | |
127 | 199 | local.uid = 0; |
@@ -129,7 +201,7 @@ | ||
129 | 201 | |
130 | 202 | if ((head.gid < 0) || (head.gid > tar::raw_header::max_gid)) |
131 | 203 | { |
132 | - ex += detail:: | |
204 | + ex += tar_detail:: | |
133 | 205 | make_ex_header_recoed("gid", to_dec<char>(head.gid)); |
134 | 206 | |
135 | 207 | local.gid = 0; |
@@ -137,7 +209,7 @@ | ||
137 | 209 | |
138 | 210 | if (head.file_size > tar::raw_header::max_size) |
139 | 211 | { |
140 | - ex += detail:: | |
212 | + ex += tar_detail:: | |
141 | 213 | make_ex_header_recoed("size", to_dec<char>(head.file_size)); |
142 | 214 | |
143 | 215 | local.file_size = 0; |
@@ -145,59 +217,72 @@ | ||
145 | 217 | |
146 | 218 | if (head.modified_time && (head.modified_time->nanoseconds != 0)) |
147 | 219 | { |
148 | - ex += detail::make_ex_header_recoed( | |
220 | + ex += tar_detail::make_ex_header_recoed( | |
149 | 221 | "mtime", |
150 | - detail::from_timestamp(head.modified_time.get())); | |
222 | + tar_detail::from_timestamp(head.modified_time.get())); | |
151 | 223 | } |
152 | 224 | |
153 | 225 | if (head.access_time) |
154 | 226 | { |
155 | - ex += detail::make_ex_header_recoed( | |
227 | + ex += tar_detail::make_ex_header_recoed( | |
156 | 228 | "atime", |
157 | - detail::from_timestamp(head.access_time.get())); | |
229 | + tar_detail::from_timestamp(head.access_time.get())); | |
158 | 230 | } |
159 | 231 | |
160 | 232 | if (head.change_time) |
161 | 233 | { |
162 | - ex += detail::make_ex_header_recoed( | |
234 | + ex += tar_detail::make_ex_header_recoed( | |
163 | 235 | "ctime", |
164 | - detail::from_timestamp(head.change_time.get())); | |
236 | + tar_detail::from_timestamp(head.change_time.get())); | |
165 | 237 | } |
166 | 238 | |
167 | - if (long_link.size() > tar::raw_header::name_size) | |
239 | + if ((long_link.size() > tar::raw_header::name_size) || | |
240 | + tar_detail::is_non_ascii(head.link_path.string()) ) | |
168 | 241 | { |
169 | - ex += detail::make_ex_header_recoed("linkpath", long_link); | |
242 | + std::string linkpath = | |
243 | + tar_detail::to_tar_string(head.link_path.string()); | |
244 | + ex += tar_detail::make_ex_header_recoed("linkpath", linkpath); | |
170 | 245 | |
171 | 246 | long_link.resize(tar::raw_header::name_size); |
172 | 247 | local.link_path = long_link; |
173 | 248 | } |
174 | 249 | |
175 | - if (detail::is_non_ascii(head.user_name)) | |
250 | + if (tar_detail::is_non_ascii(head.user_name)) | |
176 | 251 | { |
177 | - ex += detail:: | |
178 | - make_ex_header_recoed("uname", head.user_name); | |
252 | + ex += | |
253 | + tar_detail::make_ex_header_recoed( | |
254 | + "uname", | |
255 | + tar_detail::to_pax_string(head.user_name) | |
256 | + ); | |
179 | 257 | } |
180 | 258 | |
181 | - if (detail::is_non_ascii(head.group_name)) | |
259 | + if (tar_detail::is_non_ascii(head.group_name)) | |
182 | 260 | { |
183 | - ex += detail:: | |
184 | - make_ex_header_recoed("gname", head.group_name); | |
261 | + ex += | |
262 | + tar_detail::make_ex_header_recoed( | |
263 | + "gname", | |
264 | + tar_detail::to_pax_string(head.group_name) | |
265 | + ); | |
185 | 266 | } |
186 | 267 | |
187 | 268 | if (!head.comment.empty()) |
188 | 269 | { |
189 | - ex += detail:: | |
190 | - make_ex_header_recoed("comment", head.comment); | |
270 | + ex += | |
271 | + tar_detail::make_ex_header_recoed( | |
272 | + "comment", | |
273 | + tar_detail::to_pax_string(head.comment) | |
274 | + ); | |
191 | 275 | } |
192 | 276 | |
193 | 277 | if (!ex.empty()) |
194 | - write_extended_header(head.path, ex); | |
278 | + write_extended_header(local.path, ex); | |
195 | 279 | } |
196 | 280 | else if (head.format == tar::gnu) |
197 | 281 | { |
198 | 282 | if (name.size() > tar::raw_header::name_size) |
199 | 283 | { |
200 | - std::string long_name = head.path.string(); | |
284 | + std::string long_name = | |
285 | + tar_detail::to_tar_string(head.path.string()); | |
201 | 286 | if (head.type_flag == tar::type_flag::directory) |
202 | 287 | long_name += '/'; |
203 | 288 |
@@ -32,7 +32,7 @@ | ||
32 | 32 | #include <unistd.h> |
33 | 33 | #endif |
34 | 34 | |
35 | -namespace hamigaki { namespace archivers { namespace detail { | |
35 | +namespace hamigaki { namespace archivers { namespace tar_detail { | |
36 | 36 | |
37 | 37 | #if defined(BOOST_WINDOWS) |
38 | 38 | inline unsigned long get_pid() |
@@ -164,29 +164,32 @@ | ||
164 | 164 | |
165 | 165 | std::string prefix; |
166 | 166 | if (head.is_long()) |
167 | - detail::write_string(raw.name, "././@LongLink"); | |
167 | + tar_detail::write_string(raw.name, "././@LongLink"); | |
168 | 168 | else if (head.type_flag == tar::type_flag::extended) |
169 | - detail::write_string(raw.name, detail::make_ex_header_name(head.path)); | |
169 | + { | |
170 | + tar_detail::write_string( | |
171 | + raw.name, tar_detail::make_ex_header_name(head.path)); | |
172 | + } | |
170 | 173 | else |
171 | 174 | { |
172 | 175 | std::string name; |
173 | 176 | split_path(head.path, prefix, name); |
174 | - detail::write_string(raw.name, name); | |
177 | + tar_detail::write_string(raw.name, name); | |
175 | 178 | } |
176 | 179 | |
177 | - detail::write_oct(raw.mode, head.permissions); | |
178 | - detail::write_oct(raw.uid, head.uid); | |
179 | - detail::write_oct(raw.gid, head.gid); | |
180 | - detail::write_oct(raw.size, head.file_size); | |
180 | + tar_detail::write_oct(raw.mode, head.permissions); | |
181 | + tar_detail::write_oct(raw.uid, head.uid); | |
182 | + tar_detail::write_oct(raw.gid, head.gid); | |
183 | + tar_detail::write_oct(raw.size, head.file_size); | |
181 | 184 | if (head.modified_time) |
182 | - detail::write_oct(raw.mtime, head.modified_time->seconds); | |
185 | + tar_detail::write_oct(raw.mtime, head.modified_time->seconds); | |
183 | 186 | else |
184 | - detail::write_oct(raw.mtime, static_cast<std::time_t>(0)); | |
187 | + tar_detail::write_oct(raw.mtime, static_cast<std::time_t>(0)); | |
185 | 188 | std::memset(raw.chksum, ' ', sizeof(raw.chksum)); |
186 | 189 | raw.typeflag = head.type_flag; |
187 | 190 | |
188 | 191 | if (head.type_flag != tar::type_flag::extended) |
189 | - detail::write_string(raw.linkname, linkname); | |
192 | + tar_detail::write_string(raw.linkname, linkname); | |
190 | 193 | |
191 | 194 | std::strcpy(raw.magic, "ustar"); |
192 | 195 | if (head.format == tar::gnu) |
@@ -198,15 +201,15 @@ | ||
198 | 201 | else |
199 | 202 | std::memcpy(raw.version, "00", 2); |
200 | 203 | |
201 | - detail::write_c_string(raw.uname, head.user_name); | |
202 | - detail::write_c_string(raw.gname, head.group_name); | |
204 | + tar_detail::write_c_string(raw.uname, head.user_name); | |
205 | + tar_detail::write_c_string(raw.gname, head.group_name); | |
203 | 206 | |
204 | 207 | if ((head.format != tar::gnu) || (head.dev_major != 0)) |
205 | - detail::write_oct(raw.devmajor, head.dev_major); | |
208 | + tar_detail::write_oct(raw.devmajor, head.dev_major); | |
206 | 209 | if ((head.format != tar::gnu) || (head.dev_minor != 0)) |
207 | - detail::write_oct(raw.devminor, head.dev_minor); | |
210 | + tar_detail::write_oct(raw.devminor, head.dev_minor); | |
208 | 211 | |
209 | - detail::write_string(raw.prefix, prefix); | |
212 | + tar_detail::write_string(raw.prefix, prefix); | |
210 | 213 | |
211 | 214 | std::memset(block, 0, tar::raw_header::block_size); |
212 | 215 | hamigaki::binary_write(block, raw); |
@@ -219,6 +222,10 @@ | ||
219 | 222 | hamigaki::binary_write(block, raw); |
220 | 223 | } |
221 | 224 | |
225 | +} } } // End namespaces tar_detail, archivers, hamigaki. | |
226 | + | |
227 | +namespace hamigaki { namespace archivers { namespace detail { | |
228 | + | |
222 | 229 | template<class Sink> |
223 | 230 | class basic_ustar_file_sink_impl : private boost::noncopyable |
224 | 231 | { |
@@ -241,7 +248,7 @@ | ||
241 | 248 | if (pos_ != size_) |
242 | 249 | throw BOOST_IOSTREAMS_FAILURE("tar entry size mismatch"); |
243 | 250 | |
244 | - detail::write_tar_header(block_, head); | |
251 | + tar_detail::write_tar_header(block_, head); | |
245 | 252 | iostreams::blocking_write(sink_, block_, sizeof(block_)); |
246 | 253 | |
247 | 254 | pos_ = 0; |
@@ -18,7 +18,7 @@ | ||
18 | 18 | #include <boost/ref.hpp> |
19 | 19 | #include <boost/scoped_array.hpp> |
20 | 20 | |
21 | -namespace hamigaki { namespace archivers { namespace detail { | |
21 | +namespace hamigaki { namespace archivers { namespace tar_detail { | |
22 | 22 | |
23 | 23 | inline boost::uint32_t decode_nsec(const char* beg, const char* end) |
24 | 24 | { |
@@ -58,10 +58,14 @@ | ||
58 | 58 | |
59 | 59 | inline filesystem::timestamp to_timestamp(const char* beg, const char* end) |
60 | 60 | { |
61 | - return detail::to_timestamp(std::string(beg, end)); | |
61 | + return tar_detail::to_timestamp(std::string(beg, end)); | |
62 | 62 | } |
63 | 63 | |
64 | -template<class Source> | |
64 | +} } } // End namespaces tar_detail, archivers, hamigaki. | |
65 | + | |
66 | +namespace hamigaki { namespace archivers { namespace detail { | |
67 | + | |
68 | +template<class Source, class Path=boost::filesystem::path> | |
65 | 69 | class basic_tar_file_source_impl |
66 | 70 | { |
67 | 71 | private: |
@@ -228,11 +232,11 @@ | ||
228 | 232 | else if (key == "size") |
229 | 233 | ext.file_size = hamigaki::from_dec<boost::uintmax_t>(beg, end); |
230 | 234 | else if (key == "mtime") |
231 | - ext.modified_time = detail::to_timestamp(beg, end); | |
235 | + ext.modified_time = tar_detail::to_timestamp(beg, end); | |
232 | 236 | else if (key == "atime") |
233 | - ext.access_time = detail::to_timestamp(beg, end); | |
237 | + ext.access_time = tar_detail::to_timestamp(beg, end); | |
234 | 238 | else if (key == "ctime") |
235 | - ext.change_time = detail::to_timestamp(beg, end); | |
239 | + ext.change_time = tar_detail::to_timestamp(beg, end); | |
236 | 240 | else if (key == "linkpath") |
237 | 241 | ext.link_path = beg; |
238 | 242 | else if (key == "uname") |
@@ -1,6 +1,6 @@ | ||
1 | 1 | // tar_file.hpp: POSIX tar file device |
2 | 2 | |
3 | -// Copyright Takeshi Mouri 2006, 2007. | |
3 | +// Copyright Takeshi Mouri 2006-2008. | |
4 | 4 | // Distributed under the Boost Software License, Version 1.0. |
5 | 5 | // (See accompanying file LICENSE_1_0.txt or copy at |
6 | 6 | // http://www.boost.org/LICENSE_1_0.txt) |
@@ -94,11 +94,11 @@ | ||
94 | 94 | }; |
95 | 95 | |
96 | 96 | |
97 | -template<class Sink> | |
97 | +template<class Sink, class Path=boost::filesystem::path> | |
98 | 98 | class basic_tar_file_sink |
99 | 99 | { |
100 | 100 | private: |
101 | - typedef detail::basic_tar_file_sink_impl<Sink> impl_type; | |
101 | + typedef detail::basic_tar_file_sink_impl<Sink,Path> impl_type; | |
102 | 102 | |
103 | 103 | public: |
104 | 104 | typedef char char_type; |
@@ -109,7 +109,8 @@ | ||
109 | 109 | , boost::iostreams::closable_tag |
110 | 110 | {}; |
111 | 111 | |
112 | - typedef tar::header header_type; | |
112 | + typedef Path path_type; | |
113 | + typedef tar::basic_header<Path> header_type; | |
113 | 114 | |
114 | 115 | explicit basic_tar_file_sink(const Sink& sink) |
115 | 116 | : pimpl_(new impl_type(sink)) |
@@ -116,7 +117,7 @@ | ||
116 | 117 | { |
117 | 118 | } |
118 | 119 | |
119 | - void create_entry(const tar::header& head) | |
120 | + void create_entry(const header_type& head) | |
120 | 121 | { |
121 | 122 | pimpl_->create_entry(head); |
122 | 123 | } |
@@ -156,6 +157,7 @@ | ||
156 | 157 | , boost::iostreams::closable_tag |
157 | 158 | {}; |
158 | 159 | |
160 | + typedef boost::filesystem::path path_type; | |
159 | 161 | typedef tar::header header_type; |
160 | 162 | |
161 | 163 | explicit tar_file_sink(const std::string& filename) |
@@ -192,6 +194,56 @@ | ||
192 | 194 | basic_tar_file_sink<iostreams::file_sink> impl_; |
193 | 195 | }; |
194 | 196 | |
197 | +#if !defined(BOOST_FILESYSTEM_NARROW_ONLY) | |
198 | +class wtar_file_sink | |
199 | +{ | |
200 | +public: | |
201 | + typedef char char_type; | |
202 | + | |
203 | + struct category | |
204 | + : boost::iostreams::output | |
205 | + , boost::iostreams::device_tag | |
206 | + , boost::iostreams::closable_tag | |
207 | + {}; | |
208 | + | |
209 | + typedef boost::filesystem::wpath path_type; | |
210 | + typedef tar::wheader header_type; | |
211 | + | |
212 | + explicit wtar_file_sink(const std::string& filename) | |
213 | + : impl_(iostreams::file_sink(filename, BOOST_IOS::binary)) | |
214 | + { | |
215 | + } | |
216 | + | |
217 | + void create_entry(const tar::wheader& head) | |
218 | + { | |
219 | + impl_.create_entry(head); | |
220 | + } | |
221 | + | |
222 | + void rewind_entry() | |
223 | + { | |
224 | + throw std::runtime_error("unsupported operation"); | |
225 | + } | |
226 | + | |
227 | + std::streamsize write(const char* s, std::streamsize n) | |
228 | + { | |
229 | + return impl_.write(s, n); | |
230 | + } | |
231 | + | |
232 | + void close() | |
233 | + { | |
234 | + impl_.close(); | |
235 | + } | |
236 | + | |
237 | + void close_archive() | |
238 | + { | |
239 | + impl_.close_archive(); | |
240 | + } | |
241 | + | |
242 | +private: | |
243 | + basic_tar_file_sink<iostreams::file_sink,path_type> impl_; | |
244 | +}; | |
245 | +#endif // !defined(BOOST_FILESYSTEM_NARROW_ONLY) | |
246 | + | |
195 | 247 | } } // End namespaces archivers, hamigaki. |
196 | 248 | |
197 | 249 | #endif // HAMIGAKI_ARCHIVERS_TAR_FILE_HPP |