Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3)

Side by Side Diff: src/platform/update_engine/install_action.cc

Issue 465067: Missed new files in last commit
Patch Set: Created 11 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "update_engine/install_action.h"
6 #include <errno.h>
7 #include <vector>
8 #include <gflags/gflags.h>
9 #include "update_engine/filesystem_iterator.h"
10 #include "update_engine/gzip.h"
11 #include "update_engine/subprocess.h"
12 #include "update_engine/utils.h"
13
14 DEFINE_string(mount_install_path, "",
15 "If set, the path to use when mounting the "
16 "destination device during install");
17
18 using std::vector;
19
20 namespace chromeos_update_engine {
21
22 namespace {
23 const string kBspatchPath = "/usr/bin/bspatch";
24 }
25
26 void InstallAction::PerformAction() {
27 ScopedActionCompleter completer(processor_, this);
28 // For now, do nothing other than pass what we need to to the output pipe
29 CHECK(HasInputObject());
30 const InstallPlan install_plan = GetInputObject();
31 if (HasOutputPipe())
32 SetOutputObject(install_plan.install_path);
33 if (install_plan.is_full_update) {
34 // No need to perform an install
35 completer.set_success(true);
36 return;
37 }
38 // We have a delta update.
39
40 // Open delta file
41 DeltaDiffParser parser(install_plan.download_path);
42 if (!parser.valid()) {
43 LOG(ERROR) << "Unable to open delta file";
44 return;
45 }
46
47 // Mount install fs
48 string mountpoint = FLAGS_mount_install_path;
49 if (mountpoint.empty()) {
50 // Set up dest_path_
51 char *mountpoint_temp = strdup("/tmp/install_mnt.XXXXXX");
52 CHECK(mountpoint_temp);
53 CHECK_EQ(mountpoint_temp, mkdtemp(mountpoint_temp));
54 CHECK_NE('\0', mountpoint_temp[0]);
55 mountpoint = mountpoint_temp;
56 free(mountpoint_temp);
57 }
58
59 TEST_AND_RETURN(utils::MountFilesystem(install_plan.install_path,
60 mountpoint));
61
62 // Automatically unmount the fs when this goes out of scope:
63 ScopedFilesystemUnmounter filesystem_unmounter(mountpoint);
64
65 {
66 // iterate through existing fs, deleting unneeded files
67 FilesystemIterator iter(mountpoint,
68 utils::SetWithValue<string>("/lost+found"));
69 for (; !iter.IsEnd(); iter.Increment()) {
70 if (!parser.ContainsPath(iter.GetPartialPath())) {
71 VLOG(1) << "install removing local path: " << iter.GetFullPath();
72 TEST_AND_RETURN(utils::RecursiveUnlinkDir(iter.GetFullPath()));
73 }
74 }
75 TEST_AND_RETURN(!iter.IsErr());
76 }
77
78 // iterate through delta metadata, writing files
79 DeltaDiffParserIterator iter = parser.Begin();
80 for (; iter != parser.End(); iter.Increment()) {
81 const DeltaArchiveManifest_File& file = iter.GetFile();
82 VLOG(1) << "Installing file: " << iter.path();
83 TEST_AND_RETURN(InstallFile(mountpoint, file, iter.path(), parser));
84 }
85
86 completer.set_success(true);
87 }
88
89 bool InstallAction::InstallFile(const std::string& mountpoint,
90 const DeltaArchiveManifest_File& file,
91 const std::string& path,
92 const DeltaDiffParser& parser) const {
93 // See what's already there
94 struct stat existing_stbuf;
95 int result = lstat((mountpoint + path).c_str(), &existing_stbuf);
96 TEST_AND_RETURN_FALSE_ERRNO((result == 0) || (errno == ENOENT));
97 bool exists = (result == 0);
98 // Create the proper file
99 if (S_ISDIR(file.mode())) {
100 if (!exists) {
101 TEST_AND_RETURN_FALSE_ERRNO(
102 (mkdir((mountpoint + path).c_str(), file.mode())) == 0);
103 }
104 } else if (S_ISLNK(file.mode())) {
105 InstallFileSymlink(mountpoint, file, path, parser, exists);
106 } else if (S_ISCHR(file.mode()) ||
107 S_ISBLK(file.mode()) ||
108 S_ISFIFO(file.mode()) ||
109 S_ISSOCK(file.mode())) {
110 InstallFileSpecialFile(mountpoint, file, path, parser, exists);
111 } else if (S_ISREG(file.mode())) {
112 InstallFileRegularFile(mountpoint, file, path, parser, exists);
113 } else {
114 // unknown mode type
115 TEST_AND_RETURN_FALSE(false);
116 }
117
118 // chmod/chown new file
119 if (!S_ISLNK(file.mode()))
120 TEST_AND_RETURN_FALSE_ERRNO(chmod((mountpoint + path).c_str(), file.mode())
121 == 0);
122 TEST_AND_RETURN_FALSE(file.has_uid() && file.has_gid());
123 TEST_AND_RETURN_FALSE_ERRNO(lchown((mountpoint + path).c_str(),
124 file.uid(), file.gid()) == 0);
125 return true;
126 }
127
128 bool InstallAction::InstallFileRegularFile(
129 const std::string& mountpoint,
130 const DeltaArchiveManifest_File& file,
131 const std::string& path,
132 const DeltaDiffParser& parser,
133 const bool exists) const {
134 if (!file.has_data_format())
135 return true;
136 TEST_AND_RETURN_FALSE(file.has_data_offset() && file.has_data_length());
137 if (file.data_format() == DeltaArchiveManifest_File_DataFormat_BSDIFF) {
138 // Expand with bspatch
139 string patch_path = utils::TempFilename(mountpoint + path + ".XXXXXX");
140 TEST_AND_RETURN_FALSE(file.has_data_length());
141 TEST_AND_RETURN_FALSE(parser.CopyDataToFile(
142 file.data_offset(),
143 static_cast<off_t>(file.data_length()), false,
144 patch_path));
145 string output_path = utils::TempFilename(mountpoint + path + ".XXXXXX");
146 int rc = 1;
147 vector<string> cmd;
148 cmd.push_back(kBspatchPath);
149 cmd.push_back(mountpoint + path);
150 cmd.push_back(output_path);
151 cmd.push_back(patch_path);
152 TEST_AND_RETURN_FALSE(Subprocess::SynchronousExec(cmd, &rc));
153 TEST_AND_RETURN_FALSE(rc == 0);
154 TEST_AND_RETURN_FALSE_ERRNO(rename(output_path.c_str(),
155 (mountpoint + path).c_str()) == 0);
156 TEST_AND_RETURN_FALSE_ERRNO(unlink(patch_path.c_str()) == 0);
157 } else {
158 // Expand full data, decompressing if necessary
159 TEST_AND_RETURN_FALSE((file.data_format() ==
160 DeltaArchiveManifest_File_DataFormat_FULL) ||
161 (file.data_format() ==
162 DeltaArchiveManifest_File_DataFormat_FULL_GZ));
163 if (exists)
164 TEST_AND_RETURN_FALSE_ERRNO(unlink((mountpoint + path).c_str()) == 0);
165 TEST_AND_RETURN_FALSE(file.has_data_length());
166 const bool gzipped = file.data_format() ==
167 DeltaArchiveManifest_File_DataFormat_FULL_GZ;
168 bool success =
169 parser.CopyDataToFile(file.data_offset(), file.data_length(),
170 gzipped,
171 mountpoint + path);
172 TEST_AND_RETURN_FALSE(success);
173 }
174 return true;
175 }
176
177 // char/block devices, fifos, and sockets:
178 bool InstallAction::InstallFileSpecialFile(
179 const std::string& mountpoint,
180 const DeltaArchiveManifest_File& file,
181 const std::string& path,
182 const DeltaDiffParser& parser,
183 const bool exists) const {
184 if (exists)
185 TEST_AND_RETURN_FALSE(unlink((mountpoint + path).c_str()) == 0);
186 dev_t dev = 0;
187 if (S_ISCHR(file.mode()) || S_ISBLK(file.mode())) {
188 vector<char> dev_proto;
189 TEST_AND_RETURN_FALSE(parser.ReadDataVector(file.data_offset(),
190 file.data_length(),
191 &dev_proto));
192 if (file.data_format() == DeltaArchiveManifest_File_DataFormat_FULL_GZ) {
193 TEST_AND_RETURN_FALSE(file.has_data_length());
194 {
195 vector<char> decompressed_dev_proto;
196 TEST_AND_RETURN_FALSE(GzipDecompress(dev_proto,
197 &decompressed_dev_proto));
198 dev_proto = decompressed_dev_proto;
199 }
200 } else {
201 TEST_AND_RETURN_FALSE(file.data_format() ==
202 DeltaArchiveManifest_File_DataFormat_FULL);
203 }
204 LinuxDevice linux_device;
205 utils::HexDumpVector(dev_proto);
206 TEST_AND_RETURN_FALSE(linux_device.ParseFromArray(&dev_proto[0],
207 dev_proto.size()));
208 dev = makedev(linux_device.major(), linux_device.minor());
209 }
210 TEST_AND_RETURN_FALSE_ERRNO(mknod((mountpoint + path).c_str(),
211 file.mode(), dev) == 0);
212 return true;
213 }
214 // symlinks:
215 bool InstallAction::InstallFileSymlink(const std::string& mountpoint,
216 const DeltaArchiveManifest_File& file,
217 const std::string& path,
218 const DeltaDiffParser& parser,
219 const bool exists) const {
220 // If there's no data, we leave the symlink as is
221 if (!file.has_data_format())
222 return true; // No changes needed
223 TEST_AND_RETURN_FALSE((file.data_format() ==
224 DeltaArchiveManifest_File_DataFormat_FULL) ||
225 (file.data_format() ==
226 DeltaArchiveManifest_File_DataFormat_FULL_GZ));
227 TEST_AND_RETURN_FALSE(file.has_data_offset() && file.has_data_length());
228 // We have data, and thus use it to create a symlink.
229 // First delete any existing symlink:
230 if (exists)
231 TEST_AND_RETURN_FALSE_ERRNO(unlink((mountpoint + path).c_str()) == 0);
232 vector<char> symlink_data;
233 TEST_AND_RETURN_FALSE(parser.ReadDataVector(file.data_offset(),
234 file.data_length(),
235 &symlink_data));
236 if (file.data_format() == DeltaArchiveManifest_File_DataFormat_FULL_GZ) {
237 vector<char> decompressed_symlink_data;
238 TEST_AND_RETURN_FALSE(GzipDecompress(symlink_data,
239 &decompressed_symlink_data));
240 symlink_data = decompressed_symlink_data;
241 }
242 symlink_data.push_back('\0');
243 TEST_AND_RETURN_FALSE_ERRNO(symlink(&symlink_data[0],
244 (mountpoint + path).c_str()) == 0);
245 return true;
246 }
247
248
249 } // namespace chromeos_update_engine
OLDNEW
« no previous file with comments | « src/platform/update_engine/install_action.h ('k') | src/platform/update_engine/install_action_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698