blob: dacca193b92fa4100e99e50a89320fc5e97a206a [file] [log] [blame]
Patrick Venture22e38752018-11-21 08:52:49 -08001/*
2 * Copyright 2018 Google Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Patrick Venture64919ec2018-11-15 11:52:07 -080017#include "file_handler.hpp"
18
19#include <cstdint>
Patrick Venture2bd70212019-03-08 13:14:08 -080020#include <filesystem>
Jason Ling56a22732020-10-23 19:53:17 -070021#include <ios>
Patrick Venture64919ec2018-11-15 11:52:07 -080022#include <memory>
23#include <string>
24#include <vector>
25
Patrick Venture1d5a31c2019-05-20 11:38:22 -070026namespace ipmi_flash
Patrick Venture64919ec2018-11-15 11:52:07 -080027{
Patrick Venture2bd70212019-03-08 13:14:08 -080028namespace fs = std::filesystem;
Patrick Venture64919ec2018-11-15 11:52:07 -080029
Jason Ling56a22732020-10-23 19:53:17 -070030bool FileHandler::open(const std::string& path, std::ios_base::openmode mode)
Patrick Venture64919ec2018-11-15 11:52:07 -080031{
Jason Ling56a22732020-10-23 19:53:17 -070032 /* force binary mode */
33 mode |= std::ios::binary;
Patrick Venture64919ec2018-11-15 11:52:07 -080034 this->path = path;
35
36 if (file.is_open())
37 {
38 /* This wasn't properly closed somehow.
39 * TODO: Throw an error or just reset the state?
40 */
41 return false;
42 }
43
Jason Ling56a22732020-10-23 19:53:17 -070044 file.open(filename, mode);
45 if (!file.good()) /* on success goodbit is set */
Patrick Venture64919ec2018-11-15 11:52:07 -080046 {
47 /* TODO: Oh no! Care about this. */
48 return false;
49 }
50
51 /* We were able to open the file for staging.
52 * TODO: We'll need to do other stuff to eventually.
53 */
54 return true;
55}
56
57void FileHandler::close()
58{
59 if (file.is_open())
60 {
61 file.close();
62 }
63 return;
64}
65
66bool FileHandler::write(std::uint32_t offset,
67 const std::vector<std::uint8_t>& data)
68{
69 if (!file.is_open())
70 {
71 return false;
72 }
73
74 /* We could track this, but if they write in a scattered method, this is
75 * easier.
76 */
77 file.seekp(offset, std::ios_base::beg);
78 if (!file.good())
79 {
80 /* the documentation wasn't super clear on fail vs bad in these cases,
81 * so let's only be happy with goodness.
82 */
83 return false;
84 }
85
86 file.write(reinterpret_cast<const char*>(data.data()), data.size());
87 if (!file.good())
88 {
89 return false;
90 }
91
92 return true;
93}
94
Jason Ling56a22732020-10-23 19:53:17 -070095std::optional<std::vector<uint8_t>> FileHandler::read(std::uint32_t offset,
96 std::uint32_t size)
97{
98 if (!file.is_open())
99 {
100 return std::nullopt;
101 }
102
103 /* determine size of file */
104 file.seekg(0, std::ios_base::end);
105 uint32_t filesize = file.tellg();
106 uint32_t bytesToRead = size;
107
108 /* make sure to not read past the end of file */
109 if (offset + size > filesize)
110 {
111 bytesToRead = filesize - offset;
112 }
113
114 /* if no bytes can be read, fail */
115 if (0 == bytesToRead)
116 {
117 return std::nullopt;
118 }
119
120 /* seek to offset then read */
121 file.seekg(offset);
122 std::vector<uint8_t> fileData(bytesToRead);
123 file.read(reinterpret_cast<char*>(fileData.data()), bytesToRead);
124
125 /* if any sort of failure happened during all the seeks
126 * and reads then fail the entire operation
127 */
128 if (!file.good())
129 {
130 return std::nullopt;
131 }
132 return fileData;
133}
134
Patrick Venturecc7d1602018-11-15 13:58:33 -0800135int FileHandler::getSize()
136{
Patrick Venture86b49e22018-11-15 14:29:00 -0800137 try
138 {
139 return static_cast<int>(fs::file_size(filename));
140 }
141 catch (const fs::filesystem_error& e)
Patrick Venture9b37b092020-05-28 20:58:57 -0700142 {}
Patrick Venture86b49e22018-11-15 14:29:00 -0800143
Patrick Venturecc7d1602018-11-15 13:58:33 -0800144 return 0;
145}
146
Patrick Venture1d5a31c2019-05-20 11:38:22 -0700147} // namespace ipmi_flash