]> cygwin.com Git - cygwin-apps/setup.git/blame - archive.cc
Added dpiAwareness element to manifest
[cygwin-apps/setup.git] / archive.cc
CommitLineData
b24c88b3
RC
1/*
2 * Copyright (c) 2001, Robert Collins.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * A copy of the GNU General Public License can be found at
10 * http://www.gnu.org/
11 *
12 * Written by Robert Collins <rbtcollins@hotmail.com>
13 *
14 */
15
16/* Archive IO operations
17 */
18
9f4a0c62 19#include "LogSingleton.h"
b24c88b3
RC
20
21#include "io_stream.h"
22#include "archive.h"
23#include "archive_tar.h"
24
4875ac88
MB
25/* This file is the sole user of alloca(), so do this here.
26 * This will go away when this file is useing proper C++ string handling. */
27#if HAVE_ALLOCA_H
28#include <alloca.h>
29#else
30#ifndef alloca
31#define alloca __builtin_alloca
32#endif
33#endif
34
b24c88b3
RC
35/* In case you are wondering why the file magic is not in one place:
36 * It could be. But there is little (any?) benefit.
37 * What is important is that the file magic required for any _task_ is centralised.
38 * One such task is identifying archives
39 *
40 * to federate into each class one might add a magic parameter to the constructor, which
157dc2b8 41 * the class could test itself.
b24c88b3
RC
42 */
43
44/* GNU TAR:
45 * offset 257 string ustar\040\040\0
46 */
47
b24c88b3
RC
48#define longest_magic 265
49
50archive *
51archive::extract (io_stream * original)
52{
53 if (!original)
54 return NULL;
55 char magic[longest_magic];
56 if (original->peek (magic, longest_magic) > 0)
57 {
92ef6cf8
BD
58 if (memcmp (&magic[257], "ustar\040\040\0", 8) == 0
59 || memcmp (&magic[257], "ustar\0", 6) == 0)
b24c88b3
RC
60 {
61 /* tar */
62 archive_tar *rv = new archive_tar (original);
63 if (!rv->error ())
64 return rv;
65 return NULL;
66 }
b24c88b3
RC
67 }
68 return NULL;
69}
70
a5104a04 71archive::extract_results
a3a02820
MB
72archive::extract_file (archive * source, const std::string& prefixURL,
73 const std::string& prefixPath, std::string suffix)
b24c88b3 74{
a5104a04
CF
75 extract_results res = extract_other;
76 if (source)
b24c88b3 77 {
a5104a04
CF
78 const std::string destfilename = prefixURL + prefixPath
79 + source->next_file_name() + suffix;
80 switch (source->next_file_type ())
26922cd2 81 {
a5104a04 82 case ARCHIVE_FILE_REGULAR:
b24c88b3 83 {
a5104a04
CF
84 /* TODO: remove in-the-way directories via mkpath_p */
85 if (io_stream::mkpath_p (PATH_TO_FILE, destfilename, 0755))
25da2f32 86 {
157dc2b8 87 Log (LOG_TIMESTAMP) << "Failed to make the path for " << destfilename
25da2f32
CF
88 << endLog;
89 res = extract_inuse;
90 goto out;
91 }
a5104a04
CF
92 io_stream::remove (destfilename);
93 io_stream *in = source->extract_file ();
94 if (!in)
95 {
157dc2b8
AG
96 Log (LOG_TIMESTAMP) << "Failed to extract the file "
97 << destfilename << " from the archive"
a5104a04
CF
98 << endLog;
99 res = extract_inuse;
100 goto out;
101 }
102 io_stream *tmp = io_stream::open (destfilename, "wb", in->get_mode ());
103 if (!tmp)
25da2f32
CF
104 {
105 delete in;
157dc2b8
AG
106 Log (LOG_TIMESTAMP) << "Failed to open " << destfilename;
107 Log (LOG_TIMESTAMP) << " for writing." << endLog;
25da2f32
CF
108 res = extract_inuse;
109 }
110 else if (io_stream::copy (in, tmp))
a5104a04 111 {
157dc2b8 112 Log (LOG_TIMESTAMP) << "Failed to output " << destfilename
a5104a04
CF
113 << endLog;
114 delete in;
115 delete tmp;
116 io_stream::remove (destfilename);
25da2f32
CF
117 res = extract_other;
118 }
119 else
120 {
121 tmp->set_mtime (in->get_mtime ());
122 delete in;
123 delete tmp;
124 res = extract_ok;
a5104a04 125 }
a5104a04
CF
126 }
127 break;
128 case ARCHIVE_FILE_SYMLINK:
25da2f32 129 if (io_stream::mkpath_p (PATH_TO_FILE, destfilename, 0755))
a5104a04 130 {
157dc2b8 131 Log (LOG_TIMESTAMP) << "Failed to make the path for %s"
a5104a04 132 << destfilename << endLog;
25da2f32
CF
133 res = extract_other;
134 }
135 else
136 {
137 io_stream::remove (destfilename);
138 int x = io_stream::mklink (destfilename,
139 prefixURL+ source->linktarget (),
140 IO_STREAM_SYMLINK);
141 /* FIXME: check what tar's filelength is set to for symlinks */
142 source->skip_file ();
143 res = x == 0 ? extract_ok : extract_inuse;
a5104a04 144 }
a07eee98 145 break;
a5104a04 146 case ARCHIVE_FILE_HARDLINK:
25da2f32 147 if (io_stream::mkpath_p (PATH_TO_FILE, destfilename, 0755))
a5104a04 148 {
157dc2b8 149 Log (LOG_TIMESTAMP) << "Failed to make the path for %s"
a5104a04
CF
150 << destfilename << endLog;
151 res = extract_other;
a5104a04 152 }
25da2f32
CF
153 else
154 {
155 io_stream::remove (destfilename);
156 int x = io_stream::mklink (destfilename,
157 prefixURL + prefixPath + source->linktarget (),
158 IO_STREAM_HARDLINK);
159 /* FIXME: check what tar's filelength is set to for hardlinks */
160 source->skip_file ();
161 res = x == 0 ? extract_ok : extract_inuse;
162 }
a07eee98 163 break;
a5104a04
CF
164 case ARCHIVE_FILE_DIRECTORY:
165 {
a7f2d458 166 char *path = (char *) alloca (destfilename.size() + 1);
a5104a04
CF
167 strcpy (path, destfilename.c_str());
168 while (path[0] && path[strlen (path) - 1] == '/')
169 path[strlen (path) - 1] = 0;
170 io_stream *in = source->extract_file ();
171 int x = io_stream::mkpath_p (PATH_TO_DIR, path, in->get_mode ());
172 delete in;
173 source->skip_file ();
174 res = x == 0 ? extract_ok : extract_other;
175 }
a07eee98 176 break;
a5104a04
CF
177 case ARCHIVE_FILE_INVALID:
178 source->skip_file ();
179 break;
9f4a0c62 180 }
b24c88b3 181 }
a5104a04
CF
182out:
183 return res;
b24c88b3
RC
184}
185
6b68e703 186archive::~archive () {};
This page took 0.144985 seconds and 6 git commands to generate.