• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 Huawei Device Co., Ltd.
3  *
4  * HDF is dual licensed: you can use it either under the terms of
5  * the GPL, or the BSD license, at your option.
6  * See the LICENSE file in the root of this repository for complete details.
7  */
8 
9 #include "util/file.h"
10 #include <cstdlib>
11 #include <cstring>
12 #include <functional>
13 #include <string>
14 #include <sys/stat.h>
15 #include <unistd.h>
16 #include "securec.h"
17 #include "util/string_builder.h"
18 
19 namespace OHOS {
20 namespace HDI {
21 #ifdef __MINGW32__
22 constexpr unsigned int File::READ;
23 constexpr unsigned int File::WRITE;
24 constexpr unsigned int File::APPEND;
25 #endif
26 
File(const String & path,unsigned int mode)27 File::File(const String& path, unsigned int mode)
28     : mode_(mode)
29 {
30     if (path.IsEmpty()) {
31         return;
32     }
33 
34     if (mode_ & READ) {
35         if (!CheckValid(path)) {
36             return;
37         }
38         fd_ = fopen(path.string(), "r");
39     } else if (mode_ & WRITE) {
40         fd_ = fopen(path.string(), "w+");
41     } else if (mode_ & APPEND) {
42         fd_ = fopen(path.string(), "a+");
43     }
44 
45     if (fd_ != nullptr) {
46 #ifndef __MINGW32__
47         char* absolutePath = realpath(path.string(), nullptr);
48         if (absolutePath != nullptr) {
49             path_ = absolutePath;
50             free(absolutePath);
51         } else {
52             path_ = path;
53         }
54 #else
55         char absolutePath[_MAX_PATH];
56         _fullpath(absolutePath, path.string(), _MAX_PATH);
57         path_ = absolutePath;
58 #endif
59     }
60 }
61 
~File()62 File::~File()
63 {
64     Close();
65 }
66 
GetChar()67 char File::GetChar()
68 {
69     char c = PeekChar();
70 
71     if (position_ + 1 <= size_) {
72         position_++;
73 
74         if (c != '\n') {
75             columnNo_++;
76         } else {
77             columnNo_ = 0;
78             lineNo_++;
79         }
80     }
81     return c;
82 }
83 
PeekChar()84 char File::PeekChar()
85 {
86     if (position_ + 1 > size_) {
87         int ret = Read();
88         if (ret == -1) {
89             isEof_ = true;
90         }
91     }
92 
93     return buffer_[position_];
94 }
95 
IsEof() const96 bool File::IsEof() const
97 {
98     return isEof_ || buffer_[position_] == -1;
99 }
100 
Read()101 int File::Read()
102 {
103     if (isEof_ || isError_) {
104         return -1;
105     }
106 
107     (void)memset_s(buffer_, BUFFER_SIZE, 0, BUFFER_SIZE);
108     size_t count = fread(buffer_, 1, BUFFER_SIZE - 1, fd_);
109     if (count < BUFFER_SIZE - 1) {
110         isError_ = ferror(fd_) != 0;
111         buffer_[count] = -1;
112     }
113     size_ = count;
114     position_ = 0;
115     return (count != 0) ? count : -1;
116 }
117 
ReadData(void * data,size_t size) const118 bool File::ReadData(void* data, size_t size) const
119 {
120     if (data == nullptr || size == 0) {
121         return true;
122     }
123 
124     if (fd_ == nullptr) {
125         return false;
126     }
127 
128     size_t count = fread(data, size, 1, fd_);
129     return count == 1;
130 }
131 
WriteData(const void * data,size_t size) const132 bool File::WriteData(const void* data, size_t size) const
133 {
134     if (data == nullptr || size == 0) {
135         return true;
136     }
137 
138     if (fd_ == nullptr || !(mode_ & (WRITE | APPEND))) {
139         return false;
140     }
141 
142     size_t count = fwrite(data, size, 1, fd_);
143     return count == 1;
144 }
145 
Flush()146 void File::Flush()
147 {
148     if ((mode_ & (WRITE | APPEND)) && fd_ != nullptr) {
149         fflush(fd_);
150     }
151 }
152 
Reset()153 bool File::Reset()
154 {
155     if (fd_ == nullptr) {
156         return false;
157     }
158 
159     return fseek(fd_, 0, SEEK_SET) == 0;
160 }
161 
Skip(long size)162 bool File::Skip(long size)
163 {
164     if (fd_ == nullptr) {
165         return false;
166     }
167 
168     return fseek(fd_, size, SEEK_CUR) == 0;
169 }
170 
Close()171 void File::Close()
172 {
173     if (fd_ != nullptr) {
174         fclose(fd_);
175         fd_ = nullptr;
176     }
177 }
178 
CreateParentDir(const String & path)179 bool File::CreateParentDir(const String& path)
180 {
181     if (!access(path.string(), F_OK | R_OK | W_OK)) {
182         return true;
183     }
184 
185     int pos = 1;
186 
187 #ifndef __MINGW32__
188     char Separator = '/';
189 #else
190     char Separator = '\\';
191 #endif
192 
193     while ((pos = path.IndexOf(Separator, pos)) != -1) {
194         String partPath = path.Substring(0, pos);
195         struct stat st;
196         if (stat(partPath.string(), &st) < 0) {
197             if (errno != ENOENT) {
198                 return false;
199             }
200 
201 #ifndef __MINGW32__
202             if (mkdir(partPath.string(), S_IRWXU | S_IRWXG | S_IRWXO) < 0) {
203 #else
204             if (mkdir(partPath.string()) < 0) {
205 #endif
206                 return false;
207             }
208         } else if (!S_ISDIR(st.st_mode)) {
209             return false;
210         }
211         pos += 1;
212     }
213     return true;
214 }
215 
216 String File::AdapterPath(const String& path)
217 {
218 #ifndef __MINGW32__
219     return path;
220 #else
221     return path.Replace('/', '\\');
222 #endif
223 }
224 
225 size_t File::GetHashKey()
226 {
227     StringBuilder fileStr;
228     while (!IsEof()) {
229         fileStr.Append(GetChar());
230     }
231 
232     return std::hash<std::string>()(fileStr.ToString().string());
233 }
234 
235 bool File::CheckValid(const String& path)
236 {
237     if (access(path.string(), F_OK | R_OK | W_OK)) {
238         return false;
239     }
240 
241     struct stat st;
242     if (stat(path.string(), &st) < 0) {
243         return false;
244     }
245 
246     if (S_ISDIR(st.st_mode)) {
247         return false;
248     }
249 
250     return true;
251 }
252 } // namespace HDI
253 } // namespace OHOS