Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:12:41

0001 // Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
0002 // Distributed under the MIT License (http://opensource.org/licenses/MIT)
0003 
0004 #pragma once
0005 
0006 #ifndef SPDLOG_HEADER_ONLY
0007 #    include <spdlog/details/file_helper.h>
0008 #endif
0009 
0010 #include <spdlog/details/os.h>
0011 #include <spdlog/common.h>
0012 
0013 #include <cerrno>
0014 #include <chrono>
0015 #include <cstdio>
0016 #include <string>
0017 #include <thread>
0018 #include <tuple>
0019 
0020 namespace spdlog {
0021 namespace details {
0022 
0023 SPDLOG_INLINE file_helper::file_helper(const file_event_handlers &event_handlers)
0024     : event_handlers_(event_handlers)
0025 {}
0026 
0027 SPDLOG_INLINE file_helper::~file_helper()
0028 {
0029     close();
0030 }
0031 
0032 SPDLOG_INLINE void file_helper::open(const filename_t &fname, bool truncate)
0033 {
0034     close();
0035     filename_ = fname;
0036 
0037     auto *mode = SPDLOG_FILENAME_T("ab");
0038     auto *trunc_mode = SPDLOG_FILENAME_T("wb");
0039 
0040     if (event_handlers_.before_open)
0041     {
0042         event_handlers_.before_open(filename_);
0043     }
0044     for (int tries = 0; tries < open_tries_; ++tries)
0045     {
0046         // create containing folder if not exists already.
0047         os::create_dir(os::dir_name(fname));
0048         if (truncate)
0049         {
0050             // Truncate by opening-and-closing a tmp file in "wb" mode, always
0051             // opening the actual log-we-write-to in "ab" mode, since that
0052             // interacts more politely with eternal processes that might
0053             // rotate/truncate the file underneath us.
0054             std::FILE *tmp;
0055             if (os::fopen_s(&tmp, fname, trunc_mode))
0056             {
0057                 continue;
0058             }
0059             std::fclose(tmp);
0060         }
0061         if (!os::fopen_s(&fd_, fname, mode))
0062         {
0063             if (event_handlers_.after_open)
0064             {
0065                 event_handlers_.after_open(filename_, fd_);
0066             }
0067             return;
0068         }
0069 
0070         details::os::sleep_for_millis(open_interval_);
0071     }
0072 
0073     throw_spdlog_ex("Failed opening file " + os::filename_to_str(filename_) + " for writing", errno);
0074 }
0075 
0076 SPDLOG_INLINE void file_helper::reopen(bool truncate)
0077 {
0078     if (filename_.empty())
0079     {
0080         throw_spdlog_ex("Failed re opening file - was not opened before");
0081     }
0082     this->open(filename_, truncate);
0083 }
0084 
0085 SPDLOG_INLINE void file_helper::flush()
0086 {
0087     if (std::fflush(fd_) != 0)
0088     {
0089         throw_spdlog_ex("Failed flush to file " + os::filename_to_str(filename_), errno);
0090     }
0091 }
0092 
0093 SPDLOG_INLINE void file_helper::close()
0094 {
0095     if (fd_ != nullptr)
0096     {
0097         if (event_handlers_.before_close)
0098         {
0099             event_handlers_.before_close(filename_, fd_);
0100         }
0101 
0102         std::fclose(fd_);
0103         fd_ = nullptr;
0104 
0105         if (event_handlers_.after_close)
0106         {
0107             event_handlers_.after_close(filename_);
0108         }
0109     }
0110 }
0111 
0112 SPDLOG_INLINE void file_helper::write(const memory_buf_t &buf)
0113 {
0114     size_t msg_size = buf.size();
0115     auto data = buf.data();
0116     if (std::fwrite(data, 1, msg_size, fd_) != msg_size)
0117     {
0118         throw_spdlog_ex("Failed writing to file " + os::filename_to_str(filename_), errno);
0119     }
0120 }
0121 
0122 SPDLOG_INLINE size_t file_helper::size() const
0123 {
0124     if (fd_ == nullptr)
0125     {
0126         throw_spdlog_ex("Cannot use size() on closed file " + os::filename_to_str(filename_));
0127     }
0128     return os::filesize(fd_);
0129 }
0130 
0131 SPDLOG_INLINE const filename_t &file_helper::filename() const
0132 {
0133     return filename_;
0134 }
0135 
0136 //
0137 // return file path and its extension:
0138 //
0139 // "mylog.txt" => ("mylog", ".txt")
0140 // "mylog" => ("mylog", "")
0141 // "mylog." => ("mylog.", "")
0142 // "/dir1/dir2/mylog.txt" => ("/dir1/dir2/mylog", ".txt")
0143 //
0144 // the starting dot in filenames is ignored (hidden files):
0145 //
0146 // ".mylog" => (".mylog". "")
0147 // "my_folder/.mylog" => ("my_folder/.mylog", "")
0148 // "my_folder/.mylog.txt" => ("my_folder/.mylog", ".txt")
0149 SPDLOG_INLINE std::tuple<filename_t, filename_t> file_helper::split_by_extension(const filename_t &fname)
0150 {
0151     auto ext_index = fname.rfind('.');
0152 
0153     // no valid extension found - return whole path and empty string as
0154     // extension
0155     if (ext_index == filename_t::npos || ext_index == 0 || ext_index == fname.size() - 1)
0156     {
0157         return std::make_tuple(fname, filename_t());
0158     }
0159 
0160     // treat cases like "/etc/rc.d/somelogfile or "/abc/.hiddenfile"
0161     auto folder_index = fname.find_last_of(details::os::folder_seps_filename);
0162     if (folder_index != filename_t::npos && folder_index >= ext_index - 1)
0163     {
0164         return std::make_tuple(fname, filename_t());
0165     }
0166 
0167     // finally - return a valid base and extension tuple
0168     return std::make_tuple(fname.substr(0, ext_index), fname.substr(ext_index));
0169 }
0170 
0171 } // namespace details
0172 } // namespace spdlog