added wuntar.cpp
@@ -0,0 +1,106 @@ | ||
1 | +// untar.cpp: a simple tar extracting program (Unicode version) | |
2 | + | |
3 | +// Copyright Takeshi Mouri 2008. | |
4 | +// Distributed under the Boost Software License, Version 1.0. | |
5 | +// (See accompanying file LICENSE_1_0.txt or copy at | |
6 | +// http://www.boost.org/LICENSE_1_0.txt) | |
7 | + | |
8 | +// See http://hamigaki.sourceforge.jp/libs/archivers for library home page. | |
9 | + | |
10 | + | |
11 | +// Security warning: | |
12 | +// This program never check the validity of paths in the archive. | |
13 | +// See http://www.forest.impress.co.jp/article/2004/07/30/arcsecurity.html . | |
14 | +// (The above link is Japanese site) | |
15 | + | |
16 | + | |
17 | +#include <hamigaki/archivers/tar_file.hpp> | |
18 | +#include <hamigaki/filesystem/operations.hpp> | |
19 | +#include <boost/filesystem/convenience.hpp> | |
20 | +#include <boost/filesystem/fstream.hpp> | |
21 | +#include <boost/iostreams/copy.hpp> | |
22 | +#include <clocale> | |
23 | +#include <exception> | |
24 | +#include <iostream> | |
25 | + | |
26 | +namespace ar = hamigaki::archivers; | |
27 | +namespace fs_ex = hamigaki::filesystem; | |
28 | +namespace io_ex = hamigaki::iostreams; | |
29 | +namespace fs = boost::filesystem; | |
30 | +namespace io = boost::iostreams; | |
31 | + | |
32 | +int main(int argc, char* argv[]) | |
33 | +{ | |
34 | + try | |
35 | + { | |
36 | + if (argc != 2) | |
37 | + { | |
38 | + std::cerr << "Usage: untar (archive)" << std::endl; | |
39 | + return 1; | |
40 | + } | |
41 | + | |
42 | + std::setlocale(LC_ALL, ""); | |
43 | + | |
44 | + ar::wtar_file_source tar(argv[1]); | |
45 | + | |
46 | + while (tar.next_entry()) | |
47 | + { | |
48 | + const ar::tar::wheader& head = tar.header(); | |
49 | + | |
50 | + std::wcout << head.path << std::endl; | |
51 | + | |
52 | + if (head.type_flag == ar::tar::type_flag::link) | |
53 | + { | |
54 | + if (head.path.has_branch_path()) | |
55 | + fs::create_directories(head.path.branch_path()); | |
56 | + | |
57 | + fs_ex::create_hard_link(head.link_path, head.path); | |
58 | + } | |
59 | + else if (head.type_flag == ar::tar::type_flag::symlink) | |
60 | + { | |
61 | + if (head.path.has_branch_path()) | |
62 | + fs::create_directories(head.path.branch_path()); | |
63 | + | |
64 | + fs_ex::create_symlink(head.link_path, head.path); | |
65 | + } | |
66 | + else if (head.type_flag == ar::tar::type_flag::directory) | |
67 | + fs::create_directories(head.path); | |
68 | + else if (head.type_flag == ar::tar::type_flag::char_device) | |
69 | + std::cerr << "Warning: skip character device\n"; | |
70 | + else if (head.type_flag == ar::tar::type_flag::block_device) | |
71 | + std::cerr << "Warning: skip block device\n"; | |
72 | + else if (head.type_flag == ar::tar::type_flag::fifo) | |
73 | + std::cerr << "Warning: skip FIFO file\n"; | |
74 | + // Note: All unknown types are treated as a regular file. | |
75 | + else | |
76 | + { | |
77 | + if (head.path.has_branch_path()) | |
78 | + fs::create_directories(head.path.branch_path()); | |
79 | + | |
80 | + fs::ofstream os(head.path, std::ios_base::binary); | |
81 | + io::copy(tar, os); | |
82 | + } | |
83 | + | |
84 | + // Note: | |
85 | + // The POSIX chown() clears S_ISUID/S_ISGID bits. | |
86 | + // So, we must call change_symlink_owner() | |
87 | + // before calling change_permissions(). | |
88 | + fs_ex::error_code ec; | |
89 | + fs_ex::change_symlink_owner(head.path, head.uid, head.gid, ec); | |
90 | + | |
91 | + fs_ex::change_permissions(head.path, head.permissions, ec); | |
92 | + | |
93 | + if (head.modified_time) | |
94 | + fs_ex::last_write_time(head.path, *head.modified_time); | |
95 | + if (head.access_time) | |
96 | + fs_ex::last_access_time(head.path, *head.access_time); | |
97 | + } | |
98 | + | |
99 | + return 0; | |
100 | + } | |
101 | + catch (const std::exception& e) | |
102 | + { | |
103 | + std::cerr << "Error: " << e.what() << std::endl; | |
104 | + } | |
105 | + return 1; | |
106 | +} |