1 /*
2  * Copyright (c) 2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "util/file.h"
17 
18 #include <cstdlib>
19 #include <cstdint>
20 #include <cstring>
21 #include <climits>
22 #include "securec.h"
23 
24 namespace OHOS {
25 namespace Idl {
26 #ifdef __MINGW32__
27 constexpr unsigned int File::READ;
28 constexpr unsigned int File::WRITE;
29 constexpr unsigned int File::APPEND;
30 #endif
31 
File(const String & path,int mode)32 File::File(const String& path, int mode)
33     : mode_(mode)
34 {
35     if (path.IsEmpty()) {
36         return;
37     }
38 
39     String pathTmp = "";
40 #ifndef __MINGW32__
41         char* absolutePath = realpath(path.string(), nullptr);
42         if (absolutePath != nullptr) {
43             pathTmp = absolutePath;
44             free(absolutePath);
45         } else {
46             pathTmp = path;
47         }
48 #else
49         char absolutePath[_MAX_PATH];
50         if (_fullpath(absolutePath, path.string(), _MAX_PATH) == nullptr) {
51             pathTmp = absolutePath;
52         } else {
53             pathTmp = path;
54         }
55 #endif
56 
57     if (mode_ & READ) {
58         if (!pathTmp.IsEmpty()) {
59             fd_ = fopen(pathTmp.string(), "r");
60         }
61     } else if (mode_ & WRITE) {
62         fd_ = fopen(path.string(), "w+");
63     } else if (mode_ & APPEND) {
64         fd_ = fopen(path.string(), "a+");
65     }
66 
67     if (fd_ != nullptr) {
68 #ifndef __MINGW32__
69         char* absolutePath = realpath(path.string(), nullptr);
70         if (absolutePath != nullptr) {
71             path_ = absolutePath;
72             free(absolutePath);
73         } else {
74             path_ = path;
75         }
76 #else
77         char absolutePath[_MAX_PATH];
78         _fullpath(absolutePath, path.string(), _MAX_PATH);
79         path_ = absolutePath;
80 #endif
81     }
82 }
83 
~File()84 File::~File()
85 {
86     Close();
87 }
88 
GetChar()89 char File::GetChar()
90 {
91     char c = PeekChar();
92 
93     if (position_ + 1 <= size_) {
94         position_++;
95 
96         if (c != '\n') {
97             columnNo_++;
98         } else {
99             columnNo_ = 0;
100             lineNo_++;
101         }
102     }
103     return c;
104 }
105 
PeekChar()106 char File::PeekChar()
107 {
108     if (position_ + 1 > size_) {
109         int ret = Read();
110         if (ret == -1) {
111             isEof_ = true;
112         }
113     }
114 
115     return buffer_[position_];
116 }
117 
IsEof() const118 bool File::IsEof() const
119 {
120     return isEof_ || buffer_[position_] == static_cast<char>(-1);
121 }
122 
Read()123 int File::Read()
124 {
125     if (isEof_ || isError_) {
126         return -1;
127     }
128 
129     (void)memset_s(buffer_, BUFFER_SIZE, 0, BUFFER_SIZE);
130     size_t count = fread(buffer_, 1, BUFFER_SIZE - 1, fd_);
131     if (count < BUFFER_SIZE - 1) {
132         isError_ = ferror(fd_) != 0;
133         buffer_[count] = -1;
134     }
135     size_ = count;
136     position_ = 0;
137     if (count <= 0 || count >= BUFFER_SIZE) {
138         return -1;
139     }
140     return count;
141 }
142 
ReadData(void * data,size_t size)143 bool File::ReadData(void* data, size_t size)
144 {
145     if (data == nullptr || size == 0 || size > SIZE_MAX) {
146         return true;
147     }
148 
149     if (fd_ == nullptr) {
150         return false;
151     }
152 
153     size_t count = fread(data, size, 1, fd_);
154     return count == 1;
155 }
156 
WriteData(const void * data,size_t size)157 bool File::WriteData(const void* data, size_t size)
158 {
159     if (data == nullptr || size == 0) {
160         return true;
161     }
162 
163     if (fd_ == nullptr || !(mode_ & (WRITE | APPEND))) {
164         return false;
165     }
166 
167     size_t count = fwrite(data, size, 1, fd_);
168     return count == 1;
169 }
170 
Flush()171 void File::Flush()
172 {
173     if ((mode_ & (WRITE | APPEND)) && fd_ != nullptr) {
174         fflush(fd_);
175     }
176 }
177 
Reset()178 bool File::Reset()
179 {
180     if (fd_ == nullptr) {
181         return false;
182     }
183 
184     return fseek(fd_, 0, SEEK_SET) == 0;
185 }
186 
Skip(long size)187 bool File::Skip(long size)
188 {
189     if (fd_ == nullptr) {
190         return false;
191     }
192 
193     return fseek(fd_, size, SEEK_CUR) == 0;
194 }
195 
Close()196 void File::Close()
197 {
198     if (fd_ != nullptr) {
199         fclose(fd_);
200         fd_ = nullptr;
201     }
202 }
203 }
204 }
205