supported to read UTF-8 for pax
@@ -1,6 +1,6 @@ | ||
1 | 1 | // tar_ex_header.hpp: extended tar header |
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) |
@@ -18,9 +18,13 @@ | ||
18 | 18 | |
19 | 19 | namespace hamigaki { namespace archivers { namespace detail { |
20 | 20 | |
21 | +template<class Path> | |
21 | 22 | struct tar_ex_header |
22 | 23 | { |
23 | - boost::filesystem::path path; | |
24 | + typedef Path path_type; | |
25 | + typedef typename Path::string_type string_type; | |
26 | + | |
27 | + Path path; | |
24 | 28 | boost::optional<boost::intmax_t> uid; |
25 | 29 | boost::optional<boost::intmax_t> gid; |
26 | 30 | boost::optional<boost::uintmax_t> file_size; |
@@ -27,10 +31,10 @@ | ||
27 | 31 | boost::optional<filesystem::timestamp> modified_time; |
28 | 32 | boost::optional<filesystem::timestamp> access_time; |
29 | 33 | boost::optional<filesystem::timestamp> change_time; |
30 | - boost::filesystem::path link_path; | |
31 | - std::string user_name; | |
32 | - std::string group_name; | |
33 | - std::string comment; | |
34 | + Path link_path; | |
35 | + string_type user_name; | |
36 | + string_type group_name; | |
37 | + string_type comment; | |
34 | 38 | }; |
35 | 39 | |
36 | 40 | } } } // End namespaces detail, archivers, hamigaki. |
@@ -20,6 +20,64 @@ | ||
20 | 20 | |
21 | 21 | namespace hamigaki { namespace archivers { namespace tar_detail { |
22 | 22 | |
23 | +template<class String> | |
24 | +inline String from_tar_string(const std::string& s) | |
25 | +{ | |
26 | + return s; | |
27 | +} | |
28 | + | |
29 | +template<class String> | |
30 | +inline String from_pax_string(const std::string& s) | |
31 | +{ | |
32 | + return charset::to_code_page(charset::from_utf8(s), 0, "_"); | |
33 | +} | |
34 | + | |
35 | +template<class Path> | |
36 | +inline tar::basic_header<Path> to_wide(const tar::header& head) | |
37 | +{ | |
38 | + return head; | |
39 | +} | |
40 | + | |
41 | +#if !defined(BOOST_FILESYSTEM_NARROW_ONLY) | |
42 | +template<> | |
43 | +inline std::wstring from_tar_string<std::wstring>(const std::string& s) | |
44 | +{ | |
45 | + return charset::from_code_page(s, 0); | |
46 | +} | |
47 | + | |
48 | +template<> | |
49 | +inline std::wstring from_pax_string<std::wstring>(const std::string& s) | |
50 | +{ | |
51 | + return charset::from_utf8(s); | |
52 | +} | |
53 | + | |
54 | +template<> | |
55 | +inline tar::wheader to_wide<boost::filesystem::wpath>(const tar::header& head) | |
56 | +{ | |
57 | + tar::wheader tmp; | |
58 | + | |
59 | + tmp.path = tar_detail::from_tar_string<std::wstring>(head.path.string()); | |
60 | + tmp.permissions = head.permissions; | |
61 | + tmp.uid = head.uid; | |
62 | + tmp.gid = head.gid; | |
63 | + tmp.file_size = head.file_size; | |
64 | + tmp.modified_time = head.modified_time; | |
65 | + tmp.access_time = head.access_time; | |
66 | + tmp.change_time = head.change_time; | |
67 | + tmp.type_flag = head.type_flag; | |
68 | + tmp.link_path = | |
69 | + tar_detail::from_tar_string<std::wstring>(head.link_path.string()); | |
70 | + tmp.format = head.format; | |
71 | + tmp.user_name = charset::from_code_page(head.user_name, 0); | |
72 | + tmp.group_name = charset::from_code_page(head.group_name, 0); | |
73 | + tmp.dev_major = head.dev_major; | |
74 | + tmp.dev_minor = head.dev_minor; | |
75 | + tmp.comment = charset::from_code_page(head.comment, 0); | |
76 | + | |
77 | + return tmp; | |
78 | +} | |
79 | +#endif | |
80 | + | |
23 | 81 | inline boost::uint32_t decode_nsec(const char* beg, const char* end) |
24 | 82 | { |
25 | 83 | std::string buf(beg, end); |
@@ -65,13 +123,18 @@ | ||
65 | 123 | |
66 | 124 | namespace hamigaki { namespace archivers { namespace detail { |
67 | 125 | |
68 | -template<class Source, class Path=boost::filesystem::path> | |
126 | +template<class Source, class Path> | |
69 | 127 | class basic_tar_file_source_impl |
70 | 128 | { |
71 | 129 | private: |
72 | 130 | typedef detail::basic_ustar_file_source_impl<Source> ustar_type; |
131 | + typedef detail::tar_ex_header<Path> tar_ex_header; | |
73 | 132 | |
74 | 133 | public: |
134 | + typedef Path path_type; | |
135 | + typedef typename Path::string_type string_type; | |
136 | + typedef tar::basic_header<Path> header_type; | |
137 | + | |
75 | 138 | explicit basic_tar_file_source_impl(const Source& src) |
76 | 139 | : ustar_(src), is_pax_(false) |
77 | 140 | { |
@@ -82,7 +145,7 @@ | ||
82 | 145 | if (!ustar_.next_entry()) |
83 | 146 | return false; |
84 | 147 | |
85 | - header_ = ustar_.header(); | |
148 | + header_ = tar_detail::to_wide<Path>(ustar_.header()); | |
86 | 149 | |
87 | 150 | if (header_.type_flag == tar::type_flag::global) |
88 | 151 | { |
@@ -91,7 +154,7 @@ | ||
91 | 154 | if (!ustar_.next_entry()) |
92 | 155 | throw boost::iostreams::detail::bad_read(); |
93 | 156 | |
94 | - header_ = ustar_.header(); | |
157 | + header_ = tar_detail::to_wide<Path>(ustar_.header()); | |
95 | 158 | is_pax_ = true; |
96 | 159 | } |
97 | 160 |
@@ -105,7 +168,7 @@ | ||
105 | 168 | if (!ustar_.next_entry()) |
106 | 169 | throw boost::iostreams::detail::bad_read(); |
107 | 170 | |
108 | - header_ = ustar_.header(); | |
171 | + header_ = tar_detail::to_wide<Path>(ustar_.header()); | |
109 | 172 | is_pax = true; |
110 | 173 | } |
111 | 174 |
@@ -119,7 +182,7 @@ | ||
119 | 182 | if (!ustar_.next_entry()) |
120 | 183 | throw boost::iostreams::detail::bad_read(); |
121 | 184 | |
122 | - header_ = ustar_.header(); | |
185 | + header_ = tar_detail::to_wide<Path>(ustar_.header()); | |
123 | 186 | } |
124 | 187 | |
125 | 188 | if (is_pax) |
@@ -161,7 +224,7 @@ | ||
161 | 224 | return true; |
162 | 225 | } |
163 | 226 | |
164 | - tar::header header() const | |
227 | + header_type header() const | |
165 | 228 | { |
166 | 229 | return header_; |
167 | 230 | } |
@@ -173,11 +236,11 @@ | ||
173 | 236 | |
174 | 237 | private: |
175 | 238 | ustar_type ustar_; |
176 | - tar::header header_; | |
239 | + header_type header_; | |
177 | 240 | tar_ex_header global_; |
178 | 241 | bool is_pax_; |
179 | 242 | |
180 | - boost::filesystem::path read_long_link() | |
243 | + Path read_long_link() | |
181 | 244 | { |
182 | 245 | std::string buf; |
183 | 246 |
@@ -188,7 +251,7 @@ | ||
188 | 251 | if (!buf.empty() && (*(buf.rbegin()) == '\0')) |
189 | 252 | buf.resize(buf.size()-1); |
190 | 253 | |
191 | - return buf; | |
254 | + return tar_detail::from_tar_string<string_type>(buf); | |
192 | 255 | } |
193 | 256 | |
194 | 257 | void read_extended_header(tar_ex_header& ext) |
@@ -224,7 +287,7 @@ | ||
224 | 287 | const char* end = beg + (size - 1); |
225 | 288 | |
226 | 289 | if (key == "path") |
227 | - ext.path = beg; | |
290 | + ext.path = tar_detail::from_pax_string<string_type>(beg); | |
228 | 291 | else if (key == "uid") |
229 | 292 | ext.uid = hamigaki::from_dec<boost::intmax_t>(beg, end); |
230 | 293 | else if (key == "gid") |
@@ -238,13 +301,13 @@ | ||
238 | 301 | else if (key == "ctime") |
239 | 302 | ext.change_time = tar_detail::to_timestamp(beg, end); |
240 | 303 | else if (key == "linkpath") |
241 | - ext.link_path = beg; | |
304 | + ext.link_path = tar_detail::from_pax_string<string_type>(beg); | |
242 | 305 | else if (key == "uname") |
243 | - ext.user_name = beg; | |
306 | + ext.user_name = tar_detail::from_pax_string<string_type>(beg); | |
244 | 307 | else if (key == "gname") |
245 | - ext.group_name = beg; | |
308 | + ext.group_name = tar_detail::from_pax_string<string_type>(beg); | |
246 | 309 | else if (key == "comment") |
247 | - ext.comment = beg; | |
310 | + ext.comment = tar_detail::from_pax_string<string_type>(beg); | |
248 | 311 | } |
249 | 312 | } |
250 | 313 | }; |
@@ -17,11 +17,11 @@ | ||
17 | 17 | |
18 | 18 | namespace hamigaki { namespace archivers { |
19 | 19 | |
20 | -template<class Source> | |
20 | +template<class Source, class Path=boost::filesystem::path> | |
21 | 21 | class basic_tar_file_source |
22 | 22 | { |
23 | 23 | private: |
24 | - typedef detail::basic_tar_file_source_impl<Source> impl_type; | |
24 | + typedef detail::basic_tar_file_source_impl<Source,Path> impl_type; | |
25 | 25 | |
26 | 26 | public: |
27 | 27 | typedef char char_type; |
@@ -31,7 +31,8 @@ | ||
31 | 31 | , boost::iostreams::device_tag |
32 | 32 | {}; |
33 | 33 | |
34 | - typedef tar::header header_type; | |
34 | + typedef Path path_type; | |
35 | + typedef tar::basic_header<Path> header_type; | |
35 | 36 | |
36 | 37 | explicit basic_tar_file_source(const Source& src) |
37 | 38 | : pimpl_(new impl_type(src)) |
@@ -43,7 +44,7 @@ | ||
43 | 44 | return pimpl_->next_entry(); |
44 | 45 | } |
45 | 46 | |
46 | - tar::header header() const | |
47 | + header_type header() const | |
47 | 48 | { |
48 | 49 | return pimpl_->header(); |
49 | 50 | } |
@@ -67,6 +68,7 @@ | ||
67 | 68 | , boost::iostreams::device_tag |
68 | 69 | {}; |
69 | 70 | |
71 | + typedef boost::filesystem::path path_type; | |
70 | 72 | typedef tar::header header_type; |
71 | 73 | |
72 | 74 | explicit tar_file_source(const std::string& filename) |
@@ -195,6 +197,43 @@ | ||
195 | 197 | }; |
196 | 198 | |
197 | 199 | #if !defined(BOOST_FILESYSTEM_NARROW_ONLY) |
200 | +class wtar_file_source | |
201 | +{ | |
202 | +public: | |
203 | + typedef char char_type; | |
204 | + | |
205 | + struct category | |
206 | + : boost::iostreams::input | |
207 | + , boost::iostreams::device_tag | |
208 | + {}; | |
209 | + | |
210 | + typedef boost::filesystem::wpath path_type; | |
211 | + typedef tar::wheader header_type; | |
212 | + | |
213 | + explicit wtar_file_source(const std::string& filename) | |
214 | + : impl_(iostreams::file_source(filename, BOOST_IOS::binary)) | |
215 | + { | |
216 | + } | |
217 | + | |
218 | + bool next_entry() | |
219 | + { | |
220 | + return impl_.next_entry(); | |
221 | + } | |
222 | + | |
223 | + tar::wheader header() const | |
224 | + { | |
225 | + return impl_.header(); | |
226 | + } | |
227 | + | |
228 | + std::streamsize read(char* s, std::streamsize n) | |
229 | + { | |
230 | + return impl_.read(s, n); | |
231 | + } | |
232 | + | |
233 | +private: | |
234 | + basic_tar_file_source<iostreams::file_source,path_type> impl_; | |
235 | +}; | |
236 | + | |
198 | 237 | class wtar_file_sink |
199 | 238 | { |
200 | 239 | public: |