• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2018 The Chromium Authors
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 "base/fuchsia/mem_buffer_util.h"
6 
7 #include <lib/fdio/io.h>
8 
9 #include <lib/zx/vmo.h>
10 #include <string>
11 #include <utility>
12 
13 #include "base/files/file.h"
14 #include "base/fuchsia/fuchsia_logging.h"
15 #include "base/numerics/safe_conversions.h"
16 #include "base/strings/string_piece.h"
17 #include "base/strings/utf_string_conversions.h"
18 
19 namespace base {
20 
ReadUTF8FromVMOAsUTF16(const fuchsia::mem::Buffer & buffer)21 absl::optional<std::u16string> ReadUTF8FromVMOAsUTF16(
22     const fuchsia::mem::Buffer& buffer) {
23   absl::optional<std::string> output_utf8 = StringFromMemBuffer(buffer);
24   if (!output_utf8)
25     return absl::nullopt;
26   std::u16string output;
27   return UTF8ToUTF16(&output_utf8->front(), output_utf8->size(), &output)
28              ? absl::optional<std::u16string>(std::move(output))
29              : absl::nullopt;
30 }
31 
VmoFromString(StringPiece data,StringPiece name)32 zx::vmo VmoFromString(StringPiece data, StringPiece name) {
33   zx::vmo vmo;
34 
35   // The `ZX_PROP_VMO_CONTENT_SIZE` property is automatically set on VMO
36   // creation.
37   zx_status_t status = zx::vmo::create(data.size(), 0, &vmo);
38   ZX_CHECK(status == ZX_OK, status) << "zx_vmo_create";
39   status = vmo.set_property(ZX_PROP_NAME, name.data(), name.size());
40   ZX_DCHECK(status == ZX_OK, status);
41   if (data.size() > 0) {
42     status = vmo.write(data.data(), 0, data.size());
43     ZX_CHECK(status == ZX_OK, status) << "zx_vmo_write";
44   }
45   return vmo;
46 }
47 
MemBufferFromString(StringPiece data,StringPiece name)48 fuchsia::mem::Buffer MemBufferFromString(StringPiece data, StringPiece name) {
49   fuchsia::mem::Buffer buffer;
50   buffer.vmo = VmoFromString(data, name);
51   buffer.size = data.size();
52   return buffer;
53 }
54 
MemBufferFromString16(StringPiece16 data,StringPiece name)55 fuchsia::mem::Buffer MemBufferFromString16(StringPiece16 data,
56                                            StringPiece name) {
57   return MemBufferFromString(
58       StringPiece(reinterpret_cast<const char*>(data.data()),
59                   data.size() * sizeof(char16_t)),
60       name);
61 }
62 
StringFromVmo(const zx::vmo & vmo)63 absl::optional<std::string> StringFromVmo(const zx::vmo& vmo) {
64   std::string result;
65 
66   size_t size;
67   zx_status_t status = vmo.get_prop_content_size(&size);
68   if (status != ZX_OK) {
69     ZX_LOG(ERROR, status) << "zx::vmo::get_prop_content_size";
70     return absl::nullopt;
71   }
72 
73   if (size == 0)
74     return result;
75 
76   result.resize(size);
77   status = vmo.read(&result[0], 0, size);
78   if (status == ZX_OK)
79     return result;
80 
81   ZX_LOG(ERROR, status) << "zx_vmo_read";
82   return absl::nullopt;
83 }
84 
StringFromMemBuffer(const fuchsia::mem::Buffer & buffer)85 absl::optional<std::string> StringFromMemBuffer(
86     const fuchsia::mem::Buffer& buffer) {
87   std::string result;
88 
89   if (buffer.size == 0)
90     return result;
91 
92   result.resize(buffer.size);
93   zx_status_t status = buffer.vmo.read(&result[0], 0, buffer.size);
94   if (status == ZX_OK)
95     return result;
96 
97   ZX_LOG(ERROR, status) << "zx_vmo_read";
98   return absl::nullopt;
99 }
100 
StringFromMemData(const fuchsia::mem::Data & data)101 absl::optional<std::string> StringFromMemData(const fuchsia::mem::Data& data) {
102   switch (data.Which()) {
103     case fuchsia::mem::Data::kBytes: {
104       const std::vector<uint8_t>& bytes = data.bytes();
105       return std::string(bytes.begin(), bytes.end());
106     }
107     case fuchsia::mem::Data::kBuffer:
108       return StringFromMemBuffer(data.buffer());
109     case fuchsia::mem::Data::kUnknown:
110     case fuchsia::mem::Data::Invalid:
111       // TODO(fxbug.dev/66155): Determine whether to use a default case instead.
112       break;
113   }
114 
115   return absl::nullopt;
116 }
117 
MemBufferFromFile(File file)118 fuchsia::mem::Buffer MemBufferFromFile(File file) {
119   if (!file.IsValid())
120     return {};
121 
122   zx::vmo vmo;
123   zx_status_t status =
124       fdio_get_vmo_copy(file.GetPlatformFile(), vmo.reset_and_get_address());
125   if (status != ZX_OK) {
126     ZX_LOG(ERROR, status) << "fdio_get_vmo_copy";
127     return {};
128   }
129 
130   fuchsia::mem::Buffer output;
131   output.vmo = std::move(vmo);
132   output.size = checked_cast<uint64_t>(file.GetLength());
133   return output;
134 }
135 
CloneBuffer(const fuchsia::mem::Buffer & buffer,StringPiece name)136 fuchsia::mem::Buffer CloneBuffer(const fuchsia::mem::Buffer& buffer,
137                                  StringPiece name) {
138   fuchsia::mem::Buffer output;
139   output.size = buffer.size;
140   zx_status_t status = buffer.vmo.create_child(
141       ZX_VMO_CHILD_SNAPSHOT_AT_LEAST_ON_WRITE, 0, buffer.size, &output.vmo);
142   ZX_CHECK(status == ZX_OK, status) << "zx_vmo_create_child";
143 
144   status = output.vmo.set_property(ZX_PROP_NAME, name.data(), name.size());
145   ZX_DCHECK(status == ZX_OK, status);
146 
147   return output;
148 }
149 
150 }  // namespace base
151