blob: 8fa48be9df3b733fd470be15f85da15732a8201b [file] [log] [blame]
Lei Zhang91af91d2012-08-03 11:02:20 -07001// Copyright (c) 2012 The Chromium OS 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
Eric Caruso721d82e2017-08-21 15:57:30 -07005#include "mtpd/mtpd_server_impl.h"
Lei Zhang91af91d2012-08-03 11:02:20 -07006
Hidehiko Abe018e0fa2019-06-14 19:53:22 +09007#include <base/location.h>
Lei Zhang91af91d2012-08-03 11:02:20 -07008#include <base/logging.h>
Lei Zhang0d66f922012-08-07 15:22:05 -07009#include <base/rand_util.h>
10#include <base/stl_util.h>
Lei Zhang85e6aa02013-03-07 12:29:55 -080011#include <base/strings/string_number_conversions.h>
Lei Zhang12dbc6f2017-04-21 23:00:45 -070012#include <chromeos/dbus/service_constants.h>
Lei Zhang85e6aa02013-03-07 12:29:55 -080013
Lei Zhang91af91d2012-08-03 11:02:20 -070014namespace mtpd {
15
Lei Zhang0d66f922012-08-07 15:22:05 -070016namespace {
17
Lei Zhang032b9e02012-11-13 18:38:38 -080018// Maximum number of bytes to read from the device at one time. This is set low
19// enough such that a reasonable device can read this much data before D-Bus
20// times out.
21const uint32_t kMaxReadCount = 1024 * 1024;
22
Eric Caruso2b923ad2017-08-22 17:18:40 -070023void AddError(brillo::ErrorPtr* error,
Hidehiko Abe018e0fa2019-06-14 19:53:22 +090024 const base::Location& location,
Eric Caruso2b923ad2017-08-22 17:18:40 -070025 const std::string& message) {
Tom Hughes79b550d2020-08-27 16:10:04 -070026 brillo::Error::AddTo(error, location, brillo::errors::dbus::kDomain,
27 kMtpdServiceError, message);
Lei Zhangbd08aa22012-08-22 15:20:36 -070028}
29
Eric Caruso2b923ad2017-08-22 17:18:40 -070030void AddInvalidHandleError(brillo::ErrorPtr* error,
Hidehiko Abe018e0fa2019-06-14 19:53:22 +090031 const base::Location& location,
Eric Caruso2b923ad2017-08-22 17:18:40 -070032 const std::string& handle) {
Tom Hughes79b550d2020-08-27 16:10:04 -070033 brillo::Error::AddToPrintf(error, location, brillo::errors::dbus::kDomain,
34 kMtpdServiceError, "Invalid handle %s",
35 handle.c_str());
Lei Zhangbd08aa22012-08-22 15:20:36 -070036}
37
Lei Zhang0d66f922012-08-07 15:22:05 -070038} // namespace
39
Eric Caruso2b923ad2017-08-22 17:18:40 -070040MtpdServer::MtpdServer(scoped_refptr<dbus::Bus> bus)
41 : org::chromium::MtpdAdaptor(this),
42 dbus_object_(nullptr, bus, dbus::ObjectPath(kMtpdServicePath)),
Lei Zhang1c82c532017-04-17 22:09:12 -070043 device_manager_(this) {}
Lei Zhang91af91d2012-08-03 11:02:20 -070044
Lei Zhang1c82c532017-04-17 22:09:12 -070045MtpdServer::~MtpdServer() {}
Lei Zhang91af91d2012-08-03 11:02:20 -070046
Eric Caruso2b923ad2017-08-22 17:18:40 -070047std::vector<std::string> MtpdServer::EnumerateStorages() {
Lei Zhangc1768cf2012-11-16 13:35:37 -080048 return device_manager_.EnumerateStorages();
Lei Zhang91af91d2012-08-03 11:02:20 -070049}
50
Eric Caruso2b923ad2017-08-22 17:18:40 -070051std::vector<uint8_t> MtpdServer::GetStorageInfo(
52 const std::string& storage_name) {
53 const StorageInfo* info = device_manager_.GetStorageInfo(storage_name);
Lei Zhang6cd0bfc2012-09-06 20:18:26 -070054 return info ? info->ToDBusFormat() : StorageInfo().ToDBusFormat();
Lei Zhang91af91d2012-08-03 11:02:20 -070055}
56
Yuki Awano82560282015-05-19 16:41:20 +090057std::vector<uint8_t> MtpdServer::GetStorageInfoFromDevice(
Eric Caruso2b923ad2017-08-22 17:18:40 -070058 const std::string& storage_name) {
Yuki Awano82560282015-05-19 16:41:20 +090059 const StorageInfo* info =
Eric Caruso2b923ad2017-08-22 17:18:40 -070060 device_manager_.GetStorageInfoFromDevice(storage_name);
Yuki Awano82560282015-05-19 16:41:20 +090061 return info ? info->ToDBusFormat() : StorageInfo().ToDBusFormat();
62}
63
Eric Caruso2b923ad2017-08-22 17:18:40 -070064bool MtpdServer::OpenStorage(brillo::ErrorPtr* error,
65 const std::string& storage_name,
66 const std::string& mode,
67 std::string* id) {
Yuki Awano3a9c4192015-02-24 13:37:40 +090068 if (!(mode == kReadOnlyMode || mode == kReadWriteMode)) {
Tom Hughes79b550d2020-08-27 16:10:04 -070069 brillo::Error::AddToPrintf(error, FROM_HERE, brillo::errors::dbus::kDomain,
70 kMtpdServiceError, "Cannot open %s in mode: %s",
Eric Caruso2b923ad2017-08-22 17:18:40 -070071 storage_name.c_str(), mode.c_str());
72 return false;
Lei Zhang0d66f922012-08-07 15:22:05 -070073 }
74
Eric Caruso2b923ad2017-08-22 17:18:40 -070075 if (!device_manager_.HasStorage(storage_name)) {
Tom Hughes79b550d2020-08-27 16:10:04 -070076 brillo::Error::AddToPrintf(
77 error, FROM_HERE, brillo::errors::dbus::kDomain, kMtpdServiceError,
78 "Cannot open unknown storage %s", storage_name.c_str());
Eric Caruso2b923ad2017-08-22 17:18:40 -070079 return false;
Lei Zhang0d66f922012-08-07 15:22:05 -070080 }
81
Eric Caruso2b923ad2017-08-22 17:18:40 -070082 std::string new_id;
Lei Zhang032b9e02012-11-13 18:38:38 -080083 uint32_t random_data[4];
Lei Zhang0d66f922012-08-07 15:22:05 -070084 do {
85 base::RandBytes(random_data, sizeof(random_data));
Eric Caruso2b923ad2017-08-22 17:18:40 -070086 new_id = base::HexEncode(random_data, sizeof(random_data));
Qijiang Fan52439042020-06-17 15:34:38 +090087 } while (base::Contains(handle_map_, new_id));
Lei Zhang0d66f922012-08-07 15:22:05 -070088
Eric Caruso2b923ad2017-08-22 17:18:40 -070089 handle_map_.insert(
90 std::make_pair(new_id, std::make_pair(storage_name, mode)));
91 *id = new_id;
92 return true;
Lei Zhang91af91d2012-08-03 11:02:20 -070093}
94
Eric Caruso2b923ad2017-08-22 17:18:40 -070095bool MtpdServer::CloseStorage(brillo::ErrorPtr* error,
96 const std::string& handle) {
97 if (handle_map_.erase(handle) == 0) {
98 AddInvalidHandleError(error, FROM_HERE, handle);
99 return false;
100 }
101
102 return true;
Lei Zhang91af91d2012-08-03 11:02:20 -0700103}
104
Eric Caruso2b923ad2017-08-22 17:18:40 -0700105bool MtpdServer::ReadDirectoryEntryIds(
Tom Hughes79b550d2020-08-27 16:10:04 -0700106 brillo::ErrorPtr* error,
107 const std::string& handle,
108 uint32_t file_id,
109 std::vector<uint32_t>* directory_listing) {
Lei Zhang8c3a3f32014-07-22 16:33:25 -0700110 std::string storage_name = LookupHandle(handle);
111 if (storage_name.empty()) {
Eric Caruso2b923ad2017-08-22 17:18:40 -0700112 AddInvalidHandleError(error, FROM_HERE, handle);
113 return false;
Lei Zhang8c3a3f32014-07-22 16:33:25 -0700114 }
115
Eric Caruso2b923ad2017-08-22 17:18:40 -0700116 if (!device_manager_.ReadDirectoryEntryIds(storage_name, file_id,
117 directory_listing)) {
118 AddError(error, FROM_HERE, "ReadDirectoryEntryIds failed");
119 return false;
Lei Zhang8c3a3f32014-07-22 16:33:25 -0700120 }
Eric Caruso2b923ad2017-08-22 17:18:40 -0700121
122 return true;
Lei Zhang8c3a3f32014-07-22 16:33:25 -0700123}
124
Eric Caruso2b923ad2017-08-22 17:18:40 -0700125bool MtpdServer::GetFileInfo(brillo::ErrorPtr* error,
126 const std::string& handle,
127 const std::vector<uint32_t>& file_ids,
128 std::vector<uint8_t>* serialized_file_entries) {
129 if (file_ids.empty()) {
130 AddError(error, FROM_HERE, "GetFileInfo called with no file ids");
131 return false;
Lei Zhang8c3a3f32014-07-22 16:33:25 -0700132 }
133
134 std::string storage_name = LookupHandle(handle);
135 if (storage_name.empty()) {
Eric Caruso2b923ad2017-08-22 17:18:40 -0700136 AddInvalidHandleError(error, FROM_HERE, handle);
137 return false;
Lei Zhang8c3a3f32014-07-22 16:33:25 -0700138 }
139
140 std::vector<FileEntry> file_info;
Eric Caruso2b923ad2017-08-22 17:18:40 -0700141 if (!device_manager_.GetFileInfo(storage_name, file_ids, &file_info)) {
142 AddError(error, FROM_HERE, "GetFileInfo failed");
143 return false;
Lei Zhang8c3a3f32014-07-22 16:33:25 -0700144 }
Eric Caruso2b923ad2017-08-22 17:18:40 -0700145
146 *serialized_file_entries = FileEntry::FileEntriesToDBusFormat(file_info);
147 return true;
Lei Zhang8c3a3f32014-07-22 16:33:25 -0700148}
149
Eric Caruso2b923ad2017-08-22 17:18:40 -0700150bool MtpdServer::ReadFileChunk(brillo::ErrorPtr* error,
151 const std::string& handle,
152 uint32_t file_id,
153 uint32_t offset,
154 uint32_t count,
155 std::vector<uint8_t>* file_contents) {
Lei Zhangc1768cf2012-11-16 13:35:37 -0800156 if (count > kMaxReadCount || count == 0) {
Eric Caruso2b923ad2017-08-22 17:18:40 -0700157 AddError(error, FROM_HERE, "Invalid count for ReadFileChunk");
158 return false;
Lei Zhang032b9e02012-11-13 18:38:38 -0800159 }
160 std::string storage_name = LookupHandle(handle);
Eric Caruso2b923ad2017-08-22 17:18:40 -0700161 if (storage_name.empty()) {
162 AddInvalidHandleError(error, FROM_HERE, handle);
163 return false;
Lei Zhang032b9e02012-11-13 18:38:38 -0800164 }
Eric Caruso2b923ad2017-08-22 17:18:40 -0700165
166 if (!device_manager_.ReadFileChunk(storage_name, file_id, offset, count,
167 file_contents)) {
168 AddError(error, FROM_HERE, "ReadFileChunk failed");
169 return false;
170 }
171
172 return true;
Lei Zhang032b9e02012-11-13 18:38:38 -0800173}
174
Eric Caruso2b923ad2017-08-22 17:18:40 -0700175bool MtpdServer::CopyFileFromLocal(brillo::ErrorPtr* error,
176 const std::string& handle,
Eric Carusoabf933e2018-03-22 16:09:37 -0700177 const base::ScopedFD& file_descriptor,
Eric Caruso2b923ad2017-08-22 17:18:40 -0700178 uint32_t parent_id,
179 const std::string& file_name) {
Yuki Awanod814ec12015-02-13 13:17:18 +0900180 const std::string storage_name = LookupHandle(handle);
Eric Caruso2b923ad2017-08-22 17:18:40 -0700181 if (storage_name.empty() || !IsOpenedWithWrite(handle)) {
182 AddInvalidHandleError(error, FROM_HERE, handle);
183 return false;
Yuki Awanod814ec12015-02-13 13:17:18 +0900184 }
Eric Caruso2b923ad2017-08-22 17:18:40 -0700185
Eric Carusoabf933e2018-03-22 16:09:37 -0700186 if (!device_manager_.CopyFileFromLocal(storage_name, file_descriptor.get(),
Eric Caruso2b923ad2017-08-22 17:18:40 -0700187 parent_id, file_name)) {
188 AddError(error, FROM_HERE, "CopyFileFromLocal failed");
189 return false;
190 }
191
192 return true;
Yuki Awanod814ec12015-02-13 13:17:18 +0900193}
194
Eric Caruso2b923ad2017-08-22 17:18:40 -0700195bool MtpdServer::DeleteObject(brillo::ErrorPtr* error,
196 const std::string& handle,
197 uint32_t object_id) {
Yuki Awano3a9c4192015-02-24 13:37:40 +0900198 const std::string storage_name = LookupHandle(handle);
Eric Caruso2b923ad2017-08-22 17:18:40 -0700199 if (storage_name.empty() || !IsOpenedWithWrite(handle)) {
200 AddInvalidHandleError(error, FROM_HERE, handle);
201 return false;
Yuki Awano3a9c4192015-02-24 13:37:40 +0900202 }
Eric Caruso2b923ad2017-08-22 17:18:40 -0700203
204 if (!device_manager_.DeleteObject(storage_name, object_id)) {
205 AddError(error, FROM_HERE, "DeleteObject failed");
206 return false;
207 }
208
209 return true;
Yuki Awano3a9c4192015-02-24 13:37:40 +0900210}
211
Eric Caruso2b923ad2017-08-22 17:18:40 -0700212bool MtpdServer::RenameObject(brillo::ErrorPtr* error,
213 const std::string& handle,
214 uint32_t object_id,
215 const std::string& new_name) {
Yuki Awano595a8e22015-03-09 15:58:18 +0900216 const std::string storage_name = LookupHandle(handle);
Eric Caruso2b923ad2017-08-22 17:18:40 -0700217 if (storage_name.empty() || !IsOpenedWithWrite(handle)) {
218 AddInvalidHandleError(error, FROM_HERE, handle);
219 return false;
Yuki Awano595a8e22015-03-09 15:58:18 +0900220 }
Eric Caruso2b923ad2017-08-22 17:18:40 -0700221
222 if (!device_manager_.RenameObject(storage_name, object_id, new_name)) {
223 AddError(error, FROM_HERE, "RenameObject failed");
224 return false;
225 }
226
227 return true;
Yuki Awano595a8e22015-03-09 15:58:18 +0900228}
229
Eric Caruso2b923ad2017-08-22 17:18:40 -0700230bool MtpdServer::CreateDirectory(brillo::ErrorPtr* error,
231 const std::string& handle,
232 uint32_t parent_id,
233 const std::string& directory_name) {
Yuki Awanob8062c02015-03-12 20:09:25 +0900234 const std::string storage_name = LookupHandle(handle);
Eric Caruso2b923ad2017-08-22 17:18:40 -0700235 if (storage_name.empty() || !IsOpenedWithWrite(handle)) {
236 AddInvalidHandleError(error, FROM_HERE, handle);
237 return false;
Yuki Awanob8062c02015-03-12 20:09:25 +0900238 }
Eric Caruso2b923ad2017-08-22 17:18:40 -0700239
240 if (!device_manager_.CreateDirectory(storage_name, parent_id,
241 directory_name)) {
242 AddError(error, FROM_HERE, "CreateDirectory failed.");
243 return false;
244 }
245
246 return true;
Yuki Awanob8062c02015-03-12 20:09:25 +0900247}
248
Eric Caruso2b923ad2017-08-22 17:18:40 -0700249bool MtpdServer::IsAlive() {
Lei Zhang91af91d2012-08-03 11:02:20 -0700250 return true;
251}
252
Lei Zhang63e89bd2012-08-06 17:05:33 -0700253void MtpdServer::StorageAttached(const std::string& storage_name) {
254 // Fire DBus signal.
Eric Caruso2b923ad2017-08-22 17:18:40 -0700255 SendMTPStorageAttachedSignal(storage_name);
Lei Zhang63e89bd2012-08-06 17:05:33 -0700256}
257
258void MtpdServer::StorageDetached(const std::string& storage_name) {
259 // Fire DBus signal.
Eric Caruso2b923ad2017-08-22 17:18:40 -0700260 SendMTPStorageDetachedSignal(storage_name);
Lei Zhang63e89bd2012-08-06 17:05:33 -0700261}
262
Lei Zhang91af91d2012-08-03 11:02:20 -0700263int MtpdServer::GetDeviceEventDescriptor() const {
Lei Zhang63e89bd2012-08-06 17:05:33 -0700264 return device_manager_.GetDeviceEventDescriptor();
Lei Zhang91af91d2012-08-03 11:02:20 -0700265}
266
267void MtpdServer::ProcessDeviceEvents() {
Lei Zhang63e89bd2012-08-06 17:05:33 -0700268 device_manager_.ProcessDeviceEvents();
Lei Zhang91af91d2012-08-03 11:02:20 -0700269}
270
Lei Zhanga3264132012-08-16 22:52:49 -0700271std::string MtpdServer::LookupHandle(const std::string& handle) {
272 HandleMap::const_iterator it = handle_map_.find(handle);
Yuki Awano3a9c4192015-02-24 13:37:40 +0900273 return (it == handle_map_.end()) ? std::string() : it->second.first;
274}
275
276bool MtpdServer::IsOpenedWithWrite(const std::string& handle) {
277 HandleMap::const_iterator it = handle_map_.find(handle);
278 return (it == handle_map_.end()) ? false
279 : it->second.second == kReadWriteMode;
Lei Zhanga3264132012-08-16 22:52:49 -0700280}
281
Eric Caruso2b923ad2017-08-22 17:18:40 -0700282void MtpdServer::RegisterAsync(
283 const brillo::dbus_utils::AsyncEventSequencer::CompletionAction& cb) {
284 RegisterWithDBusObject(&dbus_object_);
285 dbus_object_.RegisterAsync(cb);
286}
287
Lei Zhang91af91d2012-08-03 11:02:20 -0700288} // namespace mtpd