1 // Copyright 2016 The Chromium Embedded Framework Authors. Portions copyright
2 // 2012 The Chromium Authors. All rights reserved. Use of this source code is
3 // governed by a BSD-style license that can be found in the LICENSE file.
4
5 #include "tests/shared/browser/file_util.h"
6
7 #include <algorithm>
8 #include <cstdio>
9 #include <memory>
10
11 #include "include/base/cef_build.h"
12 #include "include/cef_task.h"
13
14 namespace client {
15 namespace file_util {
16
17 namespace {
18
AllowFileIO()19 bool AllowFileIO() {
20 if (CefCurrentlyOn(TID_UI) || CefCurrentlyOn(TID_IO)) {
21 NOTREACHED() << "file IO is not allowed on the current thread";
22 return false;
23 }
24 return true;
25 }
26
27 } // namespace
28
29 #if defined(OS_WIN)
30 const char kPathSep = '\\';
31 #else
32 const char kPathSep = '/';
33 #endif
34
ReadFileToString(const std::string & path,std::string * contents,size_t max_size)35 bool ReadFileToString(const std::string& path,
36 std::string* contents,
37 size_t max_size) {
38 if (!AllowFileIO())
39 return false;
40
41 if (contents)
42 contents->clear();
43 FILE* file = fopen(path.c_str(), "rb");
44 if (!file)
45 return false;
46
47 const size_t kBufferSize = 1 << 16;
48 std::unique_ptr<char[]> buf(new char[kBufferSize]);
49 size_t len;
50 size_t size = 0;
51 bool read_status = true;
52
53 // Many files supplied in |path| have incorrect size (proc files etc).
54 // Hence, the file is read sequentially as opposed to a one-shot read.
55 while ((len = fread(buf.get(), 1, kBufferSize, file)) > 0) {
56 if (contents)
57 contents->append(buf.get(), std::min(len, max_size - size));
58
59 if ((max_size - size) < len) {
60 read_status = false;
61 break;
62 }
63
64 size += len;
65 }
66 read_status = read_status && !ferror(file);
67 fclose(file);
68
69 return read_status;
70 }
71
WriteFile(const std::string & path,const char * data,int size)72 int WriteFile(const std::string& path, const char* data, int size) {
73 if (!AllowFileIO())
74 return -1;
75
76 FILE* file = fopen(path.c_str(), "wb");
77 if (!file)
78 return -1;
79
80 int written = 0;
81
82 do {
83 size_t write = fwrite(data + written, 1, size - written, file);
84 if (write == 0)
85 break;
86 written += static_cast<int>(write);
87 } while (written < size);
88
89 fclose(file);
90
91 return written;
92 }
93
JoinPath(const std::string & path1,const std::string & path2)94 std::string JoinPath(const std::string& path1, const std::string& path2) {
95 if (path1.empty() && path2.empty())
96 return std::string();
97 if (path1.empty())
98 return path2;
99 if (path2.empty())
100 return path1;
101
102 std::string result = path1;
103 if (result[result.size() - 1] != kPathSep)
104 result += kPathSep;
105 if (path2[0] == kPathSep)
106 result += path2.substr(1);
107 else
108 result += path2;
109 return result;
110 }
111
GetFileExtension(const std::string & path)112 std::string GetFileExtension(const std::string& path) {
113 size_t sep = path.find_last_of(".");
114 if (sep != std::string::npos)
115 return path.substr(sep + 1);
116 return std::string();
117 }
118
119 } // namespace file_util
120 } // namespace client
121