xref: /aosp_15_r20/external/tensorflow/tensorflow/core/platform/env.cc (revision b6fb3261f9314811a0f4371741dbb8839866f948)
1 /* Copyright 2015 The TensorFlow Authors. All Rights Reserved.
2 
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 "tensorflow/core/platform/env.h"
17 
18 #include <sys/stat.h>
19 
20 #include <deque>
21 #include <utility>
22 #include <vector>
23 
24 #include "tensorflow/core/platform/env_time.h"
25 #include "tensorflow/core/platform/errors.h"
26 #include "tensorflow/core/platform/host_info.h"
27 #include "tensorflow/core/platform/path.h"
28 #include "tensorflow/core/platform/platform.h"
29 #include "tensorflow/core/platform/protobuf.h"
30 #include "tensorflow/core/platform/stringprintf.h"
31 
32 #if defined(__APPLE__)
33 #include <mach-o/dyld.h>
34 #endif
35 #if defined(__FreeBSD__)
36 #include <sys/sysctl.h>
37 #endif
38 #if defined(PLATFORM_WINDOWS)
39 #include <windows.h>
40 #undef DeleteFile
41 #undef CopyFile
42 #include "tensorflow/tsl/platform/windows/wide_char.h"
43 #define PATH_MAX MAX_PATH
44 #else
45 #include <fcntl.h>
46 #include <string.h>
47 #include <sys/types.h>
48 #include <unistd.h>
49 #endif
50 
51 namespace tensorflow {
52 
53 // 128KB copy buffer
54 constexpr size_t kCopyFileBufferSize = 128 * 1024;
55 
56 class FileSystemRegistryImpl : public FileSystemRegistry {
57  public:
58   Status Register(const std::string& scheme, Factory factory) override;
59   Status Register(const std::string& scheme,
60                   std::unique_ptr<FileSystem> filesystem) override;
61   FileSystem* Lookup(const std::string& scheme) override;
62   Status GetRegisteredFileSystemSchemes(
63       std::vector<std::string>* schemes) override;
64 
65  private:
66   mutable mutex mu_;
67   mutable std::unordered_map<std::string, std::unique_ptr<FileSystem>> registry_
68       TF_GUARDED_BY(mu_);
69 };
70 
Register(const std::string & scheme,FileSystemRegistry::Factory factory)71 Status FileSystemRegistryImpl::Register(const std::string& scheme,
72                                         FileSystemRegistry::Factory factory) {
73   mutex_lock lock(mu_);
74   if (!registry_.emplace(scheme, std::unique_ptr<FileSystem>(factory()))
75            .second) {
76     return errors::AlreadyExists("File factory for ", scheme,
77                                  " already registered");
78   }
79   return OkStatus();
80 }
81 
Register(const std::string & scheme,std::unique_ptr<FileSystem> filesystem)82 Status FileSystemRegistryImpl::Register(
83     const std::string& scheme, std::unique_ptr<FileSystem> filesystem) {
84   mutex_lock lock(mu_);
85   if (!registry_.emplace(scheme, std::move(filesystem)).second) {
86     return errors::AlreadyExists("File system for ", scheme,
87                                  " already registered");
88   }
89   return OkStatus();
90 }
91 
Lookup(const std::string & scheme)92 FileSystem* FileSystemRegistryImpl::Lookup(const std::string& scheme) {
93   mutex_lock lock(mu_);
94   const auto found = registry_.find(scheme);
95   if (found == registry_.end()) {
96     return nullptr;
97   }
98   return found->second.get();
99 }
100 
GetRegisteredFileSystemSchemes(std::vector<std::string> * schemes)101 Status FileSystemRegistryImpl::GetRegisteredFileSystemSchemes(
102     std::vector<std::string>* schemes) {
103   mutex_lock lock(mu_);
104   for (const auto& e : registry_) {
105     schemes->push_back(e.first);
106   }
107   return OkStatus();
108 }
109 
Env()110 Env::Env() : file_system_registry_(new FileSystemRegistryImpl) {}
111 
GetFileSystemForFile(const std::string & fname,FileSystem ** result)112 Status Env::GetFileSystemForFile(const std::string& fname,
113                                  FileSystem** result) {
114   StringPiece scheme, host, path;
115   io::ParseURI(fname, &scheme, &host, &path);
116   FileSystem* file_system = file_system_registry_->Lookup(std::string(scheme));
117   if (!file_system) {
118     if (scheme.empty()) {
119       scheme = "[local]";
120     }
121 
122     return errors::Unimplemented("File system scheme '", scheme,
123                                  "' not implemented (file: '", fname, "')");
124   }
125   *result = file_system;
126   return OkStatus();
127 }
128 
GetRegisteredFileSystemSchemes(std::vector<std::string> * schemes)129 Status Env::GetRegisteredFileSystemSchemes(std::vector<std::string>* schemes) {
130   return file_system_registry_->GetRegisteredFileSystemSchemes(schemes);
131 }
132 
RegisterFileSystem(const std::string & scheme,FileSystemRegistry::Factory factory)133 Status Env::RegisterFileSystem(const std::string& scheme,
134                                FileSystemRegistry::Factory factory) {
135   return file_system_registry_->Register(scheme, std::move(factory));
136 }
137 
RegisterFileSystem(const std::string & scheme,std::unique_ptr<FileSystem> filesystem)138 Status Env::RegisterFileSystem(const std::string& scheme,
139                                std::unique_ptr<FileSystem> filesystem) {
140   return file_system_registry_->Register(scheme, std::move(filesystem));
141 }
142 
SetOption(const std::string & scheme,const std::string & key,const std::string & value)143 Status Env::SetOption(const std::string& scheme, const std::string& key,
144                       const std::string& value) {
145   FileSystem* file_system = file_system_registry_->Lookup(scheme);
146   if (!file_system) {
147     return errors::Unimplemented("File system scheme '", scheme,
148                                  "' not found to set configuration");
149   }
150   return file_system->SetOption(key, value);
151 }
152 
SetOption(const std::string & scheme,const std::string & key,const std::vector<string> & values)153 Status Env::SetOption(const std::string& scheme, const std::string& key,
154                       const std::vector<string>& values) {
155   FileSystem* file_system = file_system_registry_->Lookup(scheme);
156   if (!file_system) {
157     return errors::Unimplemented("File system scheme '", scheme,
158                                  "' not found to set configuration");
159   }
160   return file_system->SetOption(key, values);
161 }
162 
SetOption(const std::string & scheme,const std::string & key,const std::vector<int64_t> & values)163 Status Env::SetOption(const std::string& scheme, const std::string& key,
164                       const std::vector<int64_t>& values) {
165   FileSystem* file_system = file_system_registry_->Lookup(scheme);
166   if (!file_system) {
167     return errors::Unimplemented("File system scheme '", scheme,
168                                  "' not found to set configuration");
169   }
170   return file_system->SetOption(key, values);
171 }
172 
SetOption(const std::string & scheme,const std::string & key,const std::vector<double> & values)173 Status Env::SetOption(const std::string& scheme, const std::string& key,
174                       const std::vector<double>& values) {
175   FileSystem* file_system = file_system_registry_->Lookup(scheme);
176   if (!file_system) {
177     return errors::Unimplemented("File system scheme '", scheme,
178                                  "' not found to set configuration");
179   }
180   return file_system->SetOption(key, values);
181 }
182 
FlushFileSystemCaches()183 Status Env::FlushFileSystemCaches() {
184   std::vector<string> schemes;
185   TF_RETURN_IF_ERROR(GetRegisteredFileSystemSchemes(&schemes));
186   for (const string& scheme : schemes) {
187     FileSystem* fs = nullptr;
188     TF_RETURN_IF_ERROR(
189         GetFileSystemForFile(io::CreateURI(scheme, "", ""), &fs));
190     fs->FlushCaches();
191   }
192   return OkStatus();
193 }
194 
NewRandomAccessFile(const string & fname,std::unique_ptr<RandomAccessFile> * result)195 Status Env::NewRandomAccessFile(const string& fname,
196                                 std::unique_ptr<RandomAccessFile>* result) {
197   FileSystem* fs;
198   TF_RETURN_IF_ERROR(GetFileSystemForFile(fname, &fs));
199   return fs->NewRandomAccessFile(fname, result);
200 }
201 
NewReadOnlyMemoryRegionFromFile(const string & fname,std::unique_ptr<ReadOnlyMemoryRegion> * result)202 Status Env::NewReadOnlyMemoryRegionFromFile(
203     const string& fname, std::unique_ptr<ReadOnlyMemoryRegion>* result) {
204   FileSystem* fs;
205   TF_RETURN_IF_ERROR(GetFileSystemForFile(fname, &fs));
206   return fs->NewReadOnlyMemoryRegionFromFile(fname, result);
207 }
208 
NewWritableFile(const string & fname,std::unique_ptr<WritableFile> * result)209 Status Env::NewWritableFile(const string& fname,
210                             std::unique_ptr<WritableFile>* result) {
211   FileSystem* fs;
212   TF_RETURN_IF_ERROR(GetFileSystemForFile(fname, &fs));
213   return fs->NewWritableFile(fname, result);
214 }
215 
NewAppendableFile(const string & fname,std::unique_ptr<WritableFile> * result)216 Status Env::NewAppendableFile(const string& fname,
217                               std::unique_ptr<WritableFile>* result) {
218   FileSystem* fs;
219   TF_RETURN_IF_ERROR(GetFileSystemForFile(fname, &fs));
220   return fs->NewAppendableFile(fname, result);
221 }
222 
FileExists(const string & fname)223 Status Env::FileExists(const string& fname) {
224   FileSystem* fs;
225   TF_RETURN_IF_ERROR(GetFileSystemForFile(fname, &fs));
226   return fs->FileExists(fname);
227 }
228 
FilesExist(const std::vector<string> & files,std::vector<Status> * status)229 bool Env::FilesExist(const std::vector<string>& files,
230                      std::vector<Status>* status) {
231   std::unordered_map<string, std::vector<string>> files_per_fs;
232   for (const auto& file : files) {
233     StringPiece scheme, host, path;
234     io::ParseURI(file, &scheme, &host, &path);
235     files_per_fs[string(scheme)].push_back(file);
236   }
237 
238   std::unordered_map<string, Status> per_file_status;
239   bool result = true;
240   for (auto itr : files_per_fs) {
241     FileSystem* file_system = file_system_registry_->Lookup(itr.first);
242     bool fs_result;
243     std::vector<Status> local_status;
244     std::vector<Status>* fs_status = status ? &local_status : nullptr;
245     if (!file_system) {
246       fs_result = false;
247       if (fs_status) {
248         Status s = errors::Unimplemented("File system scheme '", itr.first,
249                                          "' not implemented");
250         local_status.resize(itr.second.size(), s);
251       }
252     } else {
253       fs_result = file_system->FilesExist(itr.second, fs_status);
254     }
255     if (fs_status) {
256       result &= fs_result;
257       for (size_t i = 0; i < itr.second.size(); ++i) {
258         per_file_status[itr.second[i]] = fs_status->at(i);
259       }
260     } else if (!fs_result) {
261       // Return early
262       return false;
263     }
264   }
265 
266   if (status) {
267     for (const auto& file : files) {
268       status->push_back(per_file_status[file]);
269     }
270   }
271 
272   return result;
273 }
274 
GetChildren(const string & dir,std::vector<string> * result)275 Status Env::GetChildren(const string& dir, std::vector<string>* result) {
276   FileSystem* fs;
277   TF_RETURN_IF_ERROR(GetFileSystemForFile(dir, &fs));
278   return fs->GetChildren(dir, result);
279 }
280 
GetMatchingPaths(const string & pattern,std::vector<string> * results)281 Status Env::GetMatchingPaths(const string& pattern,
282                              std::vector<string>* results) {
283   FileSystem* fs;
284   TF_RETURN_IF_ERROR(GetFileSystemForFile(pattern, &fs));
285   return fs->GetMatchingPaths(pattern, results);
286 }
287 
DeleteFile(const string & fname)288 Status Env::DeleteFile(const string& fname) {
289   FileSystem* fs;
290   TF_RETURN_IF_ERROR(GetFileSystemForFile(fname, &fs));
291   return fs->DeleteFile(fname);
292 }
293 
RecursivelyCreateDir(const string & dirname)294 Status Env::RecursivelyCreateDir(const string& dirname) {
295   FileSystem* fs;
296   TF_RETURN_IF_ERROR(GetFileSystemForFile(dirname, &fs));
297   return fs->RecursivelyCreateDir(dirname);
298 }
299 
CreateDir(const string & dirname)300 Status Env::CreateDir(const string& dirname) {
301   FileSystem* fs;
302   TF_RETURN_IF_ERROR(GetFileSystemForFile(dirname, &fs));
303   return fs->CreateDir(dirname);
304 }
305 
DeleteDir(const string & dirname)306 Status Env::DeleteDir(const string& dirname) {
307   FileSystem* fs;
308   TF_RETURN_IF_ERROR(GetFileSystemForFile(dirname, &fs));
309   return fs->DeleteDir(dirname);
310 }
311 
Stat(const string & fname,FileStatistics * stat)312 Status Env::Stat(const string& fname, FileStatistics* stat) {
313   FileSystem* fs;
314   TF_RETURN_IF_ERROR(GetFileSystemForFile(fname, &fs));
315   return fs->Stat(fname, stat);
316 }
317 
IsDirectory(const string & fname)318 Status Env::IsDirectory(const string& fname) {
319   FileSystem* fs;
320   TF_RETURN_IF_ERROR(GetFileSystemForFile(fname, &fs));
321   return fs->IsDirectory(fname);
322 }
323 
HasAtomicMove(const string & path,bool * has_atomic_move)324 Status Env::HasAtomicMove(const string& path, bool* has_atomic_move) {
325   FileSystem* fs;
326   TF_RETURN_IF_ERROR(GetFileSystemForFile(path, &fs));
327   return fs->HasAtomicMove(path, has_atomic_move);
328 }
329 
CanCreateTempFile(const string & fname,bool * can_create_temp_file)330 Status Env::CanCreateTempFile(const string& fname, bool* can_create_temp_file) {
331   FileSystem* fs;
332   TF_RETURN_IF_ERROR(GetFileSystemForFile(fname, &fs));
333   return fs->CanCreateTempFile(fname, can_create_temp_file);
334 }
335 
DeleteRecursively(const string & dirname,int64_t * undeleted_files,int64_t * undeleted_dirs)336 Status Env::DeleteRecursively(const string& dirname, int64_t* undeleted_files,
337                               int64_t* undeleted_dirs) {
338   FileSystem* fs;
339   TF_RETURN_IF_ERROR(GetFileSystemForFile(dirname, &fs));
340   return fs->DeleteRecursively(dirname, undeleted_files, undeleted_dirs);
341 }
342 
GetFileSize(const string & fname,uint64 * file_size)343 Status Env::GetFileSize(const string& fname, uint64* file_size) {
344   FileSystem* fs;
345   TF_RETURN_IF_ERROR(GetFileSystemForFile(fname, &fs));
346   return fs->GetFileSize(fname, file_size);
347 }
348 
RenameFile(const string & src,const string & target)349 Status Env::RenameFile(const string& src, const string& target) {
350   FileSystem* src_fs;
351   FileSystem* target_fs;
352   TF_RETURN_IF_ERROR(GetFileSystemForFile(src, &src_fs));
353   TF_RETURN_IF_ERROR(GetFileSystemForFile(target, &target_fs));
354   if (src_fs != target_fs) {
355     return errors::Unimplemented("Renaming ", src, " to ", target,
356                                  " not implemented");
357   }
358   return src_fs->RenameFile(src, target);
359 }
360 
CopyFile(const string & src,const string & target)361 Status Env::CopyFile(const string& src, const string& target) {
362   FileSystem* src_fs;
363   FileSystem* target_fs;
364   TF_RETURN_IF_ERROR(GetFileSystemForFile(src, &src_fs));
365   TF_RETURN_IF_ERROR(GetFileSystemForFile(target, &target_fs));
366   if (src_fs == target_fs) {
367     return src_fs->CopyFile(src, target);
368   }
369   return FileSystemCopyFile(src_fs, src, target_fs, target);
370 }
371 
GetExecutablePath()372 string Env::GetExecutablePath() {
373   char exe_path[PATH_MAX] = {0};
374 #ifdef __APPLE__
375   uint32_t buffer_size(0U);
376   _NSGetExecutablePath(nullptr, &buffer_size);
377   std::vector<char> unresolved_path(buffer_size);
378   _NSGetExecutablePath(unresolved_path.data(), &buffer_size);
379   CHECK(realpath(unresolved_path.data(), exe_path));
380 #elif defined(__FreeBSD__)
381   int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1};
382   size_t exe_path_size = PATH_MAX;
383 
384   if (sysctl(mib, 4, exe_path, &exe_path_size, NULL, 0) != 0) {
385     // Resolution of path failed
386     return "";
387   }
388 #elif defined(PLATFORM_WINDOWS)
389   HMODULE hModule = GetModuleHandleW(NULL);
390   WCHAR wc_file_path[MAX_PATH] = {0};
391   GetModuleFileNameW(hModule, wc_file_path, MAX_PATH);
392   string file_path = WideCharToUtf8(wc_file_path);
393   std::copy(file_path.begin(), file_path.end(), exe_path);
394 #else
395   char buf[PATH_MAX] = {0};
396   int path_length = readlink("/proc/self/exe", buf, sizeof(buf) - 1);
397   CHECK_NE(-1, path_length);
398 
399   if (strstr(buf, "python") != nullptr) {
400     // Discard the path of the python binary, and any flags.
401     int fd = open("/proc/self/cmdline", O_RDONLY);
402     int cmd_length = read(fd, buf, PATH_MAX - 1);
403     CHECK_NE(-1, cmd_length);
404     int token_pos = 0;
405     for (bool token_is_first_or_flag = true; token_is_first_or_flag;) {
406       // Get token length, including null
407       int token_len = strlen(&buf[token_pos]) + 1;
408       token_is_first_or_flag = false;
409       // Check if we can skip without overshooting
410       if (token_pos + token_len < cmd_length) {
411         token_pos += token_len;
412         token_is_first_or_flag = (buf[token_pos] == '-');  // token is a flag
413       }
414     }
415     snprintf(exe_path, sizeof(exe_path), "%s", &buf[token_pos]);
416   } else {
417     snprintf(exe_path, sizeof(exe_path), "%s", buf);
418   }
419 
420 #endif
421   // Make sure it's null-terminated:
422   exe_path[sizeof(exe_path) - 1] = 0;
423 
424   return exe_path;
425 }
426 
LocalTempFilename(string * filename)427 bool Env::LocalTempFilename(string* filename) {
428   std::vector<string> dirs;
429   GetLocalTempDirectories(&dirs);
430 
431   // Try each directory, as they might be full, have inappropriate
432   // permissions or have different problems at times.
433   for (const string& dir : dirs) {
434     *filename = io::JoinPath(dir, "tempfile-");
435     if (CreateUniqueFileName(filename, "")) {
436       return true;
437     }
438   }
439   return false;
440 }
441 
CreateUniqueFileName(string * prefix,const string & suffix)442 bool Env::CreateUniqueFileName(string* prefix, const string& suffix) {
443   int32_t tid = GetCurrentThreadId();
444   int32_t pid = GetProcessId();
445   long long now_microsec = NowMicros();  // NOLINT
446 
447   *prefix += strings::Printf("%s-%x-%d-%llx", port::Hostname().c_str(), tid,
448                              pid, now_microsec);
449 
450   if (!suffix.empty()) {
451     *prefix += suffix;
452   }
453   if (FileExists(*prefix).ok()) {
454     prefix->clear();
455     return false;
456   } else {
457     return true;
458   }
459 }
460 
GetProcessId()461 int32 Env::GetProcessId() {
462 #ifdef PLATFORM_WINDOWS
463   return static_cast<int32>(GetCurrentProcessId());
464 #else
465   return static_cast<int32>(getpid());
466 #endif
467 }
468 
~Thread()469 Thread::~Thread() {}
470 
~EnvWrapper()471 EnvWrapper::~EnvWrapper() {}
472 
ReadFileToString(Env * env,const string & fname,string * data)473 Status ReadFileToString(Env* env, const string& fname, string* data) {
474   uint64 file_size;
475   Status s = env->GetFileSize(fname, &file_size);
476   if (!s.ok()) {
477     return s;
478   }
479   std::unique_ptr<RandomAccessFile> file;
480   s = env->NewRandomAccessFile(fname, &file);
481   if (!s.ok()) {
482     return s;
483   }
484   data->resize(file_size);
485   char* p = &*data->begin();
486   StringPiece result;
487   s = file->Read(0, file_size, &result, p);
488   if (!s.ok()) {
489     data->clear();
490   } else if (result.size() != file_size) {
491     s = errors::Aborted("File ", fname, " changed while reading: ", file_size,
492                         " vs. ", result.size());
493     data->clear();
494   } else if (result.data() == p) {
495     // Data is already in the correct location
496   } else {
497     memmove(p, result.data(), result.size());
498   }
499   return s;
500 }
501 
WriteStringToFile(Env * env,const string & fname,const StringPiece & data)502 Status WriteStringToFile(Env* env, const string& fname,
503                          const StringPiece& data) {
504   std::unique_ptr<WritableFile> file;
505   Status s = env->NewWritableFile(fname, &file);
506   if (!s.ok()) {
507     return s;
508   }
509   s = file->Append(data);
510   if (s.ok()) {
511     s = file->Close();
512   }
513   return s;
514 }
515 
FileSystemCopyFile(FileSystem * src_fs,const string & src,FileSystem * target_fs,const string & target)516 Status FileSystemCopyFile(FileSystem* src_fs, const string& src,
517                           FileSystem* target_fs, const string& target) {
518   std::unique_ptr<RandomAccessFile> src_file;
519   TF_RETURN_IF_ERROR(src_fs->NewRandomAccessFile(src, &src_file));
520 
521   // When `target` points to a directory, we need to create a file within.
522   string target_name;
523   if (target_fs->IsDirectory(target).ok()) {
524     target_name = io::JoinPath(target, io::Basename(src));
525   } else {
526     target_name = target;
527   }
528 
529   std::unique_ptr<WritableFile> target_file;
530   TF_RETURN_IF_ERROR(target_fs->NewWritableFile(target_name, &target_file));
531 
532   uint64 offset = 0;
533   std::unique_ptr<char[]> scratch(new char[kCopyFileBufferSize]);
534   Status s = OkStatus();
535   while (s.ok()) {
536     StringPiece result;
537     s = src_file->Read(offset, kCopyFileBufferSize, &result, scratch.get());
538     if (!(s.ok() || s.code() == error::OUT_OF_RANGE)) {
539       return s;
540     }
541     TF_RETURN_IF_ERROR(target_file->Append(result));
542     offset += result.size();
543   }
544   return target_file->Close();
545 }
546 
547 // A ZeroCopyInputStream on a RandomAccessFile.
548 namespace {
549 class FileStream : public protobuf::io::ZeroCopyInputStream {
550  public:
FileStream(RandomAccessFile * file)551   explicit FileStream(RandomAccessFile* file) : file_(file), pos_(0) {}
552 
BackUp(int count)553   void BackUp(int count) override { pos_ -= count; }
Skip(int count)554   bool Skip(int count) override {
555     pos_ += count;
556     return true;
557   }
ByteCount() const558   int64_t ByteCount() const override { return pos_; }
status() const559   Status status() const { return status_; }
560 
Next(const void ** data,int * size)561   bool Next(const void** data, int* size) override {
562     StringPiece result;
563     Status s = file_->Read(pos_, kBufSize, &result, scratch_);
564     if (result.empty()) {
565       status_ = s;
566       return false;
567     }
568     pos_ += result.size();
569     *data = result.data();
570     *size = result.size();
571     return true;
572   }
573 
574  private:
575   static constexpr int kBufSize = 512 << 10;
576 
577   RandomAccessFile* file_;
578   int64_t pos_;
579   Status status_;
580   char scratch_[kBufSize];
581 };
582 
583 }  // namespace
584 
WriteBinaryProto(Env * env,const string & fname,const protobuf::MessageLite & proto)585 Status WriteBinaryProto(Env* env, const string& fname,
586                         const protobuf::MessageLite& proto) {
587   string serialized;
588   proto.AppendToString(&serialized);
589   return WriteStringToFile(env, fname, serialized);
590 }
591 
ReadBinaryProto(Env * env,const string & fname,protobuf::MessageLite * proto)592 Status ReadBinaryProto(Env* env, const string& fname,
593                        protobuf::MessageLite* proto) {
594   std::unique_ptr<RandomAccessFile> file;
595   TF_RETURN_IF_ERROR(env->NewRandomAccessFile(fname, &file));
596   std::unique_ptr<FileStream> stream(new FileStream(file.get()));
597   protobuf::io::CodedInputStream coded_stream(stream.get());
598 
599   if (!proto->ParseFromCodedStream(&coded_stream) ||
600       !coded_stream.ConsumedEntireMessage()) {
601     TF_RETURN_IF_ERROR(stream->status());
602     return errors::DataLoss("Can't parse ", fname, " as binary proto");
603   }
604   return OkStatus();
605 }
606 
WriteTextProto(Env * env,const string & fname,const protobuf::Message & proto)607 Status WriteTextProto(Env* env, const string& fname,
608                       const protobuf::Message& proto) {
609   string serialized;
610   if (!protobuf::TextFormat::PrintToString(proto, &serialized)) {
611     return errors::FailedPrecondition("Unable to convert proto to text.");
612   }
613   return WriteStringToFile(env, fname, serialized);
614 }
615 
ReadTextProto(Env * env,const string & fname,protobuf::Message * proto)616 Status ReadTextProto(Env* env, const string& fname, protobuf::Message* proto) {
617   std::unique_ptr<RandomAccessFile> file;
618   TF_RETURN_IF_ERROR(env->NewRandomAccessFile(fname, &file));
619   std::unique_ptr<FileStream> stream(new FileStream(file.get()));
620 
621   if (!protobuf::TextFormat::Parse(stream.get(), proto)) {
622     TF_RETURN_IF_ERROR(stream->status());
623     return errors::DataLoss("Can't parse ", fname, " as text proto");
624   }
625   return OkStatus();
626 }
627 
ReadTextOrBinaryProto(Env * env,const string & fname,protobuf::Message * proto)628 Status ReadTextOrBinaryProto(Env* env, const string& fname,
629                              protobuf::Message* proto) {
630   if (ReadTextProto(env, fname, proto).ok()) {
631     return OkStatus();
632   }
633   return ReadBinaryProto(env, fname, proto);
634 }
635 
ReadTextOrBinaryProto(Env * env,const string & fname,protobuf::MessageLite * proto)636 Status ReadTextOrBinaryProto(Env* env, const string& fname,
637                              protobuf::MessageLite* proto) {
638   return ReadBinaryProto(env, fname, proto);
639 }
640 
641 }  // namespace tensorflow
642