Line data Source code
1 : /*
2 : *
3 : * Copyright (c) 2024 Project CHIP Authors
4 : * All rights reserved.
5 : *
6 : * Licensed under the Apache License, Version 2.0 (the "License");
7 : * you may not use this file except in compliance with the License.
8 : * You may obtain a copy of the License at
9 : *
10 : * http://www.apache.org/licenses/LICENSE-2.0
11 : *
12 : * Unless required by applicable law or agreed to in writing, software
13 : * distributed under the License is distributed on an "AS IS" BASIS,
14 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 : * See the License for the specific language governing permissions and
16 : * limitations under the License.
17 : */
18 :
19 : #pragma once
20 :
21 : #include <cstdlib>
22 : #include <ostream>
23 : #include <streambuf>
24 : #include <string>
25 : #include <unistd.h>
26 :
27 : #include <lib/support/FileDescriptor.h>
28 :
29 : namespace chip {
30 : namespace DeviceLayer {
31 : namespace Internal {
32 :
33 : class FileDescriptorStreamBuf : public std::streambuf
34 : {
35 : public:
36 146 : FileDescriptorStreamBuf() = default;
37 146 : explicit FileDescriptorStreamBuf(int fd) : mFd(fd) {}
38 :
39 : FileDescriptorStreamBuf(FileDescriptorStreamBuf &) = delete;
40 : FileDescriptorStreamBuf & operator=(FileDescriptorStreamBuf &) = delete;
41 :
42 : FileDescriptorStreamBuf(FileDescriptorStreamBuf && other) = default;
43 146 : FileDescriptorStreamBuf & operator=(FileDescriptorStreamBuf && other) = default;
44 :
45 : protected:
46 1388 : int overflow(int c) override
47 : {
48 1388 : if (c != EOF)
49 : {
50 1388 : char z = c;
51 1388 : if (write(mFd, &z, 1) != 1)
52 : {
53 0 : return EOF;
54 : }
55 : }
56 1388 : return c;
57 : }
58 :
59 980 : std::streamsize xsputn(const char * s, std::streamsize n) override { return write(mFd, s, static_cast<size_t>(n)); }
60 :
61 : private:
62 : int mFd = -1;
63 : };
64 :
65 : /// File stream for a temporary file compatible with std::ostream.
66 : class TemporaryFileStream : public std::ostream
67 : {
68 : public:
69 : TemporaryFileStream() : std::ostream(&mBuf) {}
70 146 : explicit TemporaryFileStream(std::string nameTemplate) : std::ostream(&mBuf) { Open(std::move(nameTemplate)); };
71 :
72 : /// Disallow copy and assignment.
73 : TemporaryFileStream(const TemporaryFileStream &) = delete;
74 : TemporaryFileStream & operator=(const TemporaryFileStream &) = delete;
75 :
76 : /// Open a temporary file with a given name template.
77 : ///
78 : /// In order to check if the file was opened successfully, use IsOpen().
79 146 : void Open(std::string nameTemplate)
80 : {
81 146 : mFileName = std::move(nameTemplate);
82 146 : mFd = FileDescriptor(mkstemp(mFileName.data()));
83 146 : mBuf = FileDescriptorStreamBuf(mFd.Get());
84 146 : }
85 :
86 : /// Check if the file was opened successfully.
87 : ///
88 : /// In case of failure, the error can be retrieved using errno.
89 146 : bool IsOpen() const { return mFd.Get() != -1; };
90 :
91 : /// Synchronize the file's contents with the underlying storage device.
92 : ///
93 : /// In case of failure, the error can be retrieved using errno.
94 146 : bool DataSync() { return fdatasync(mFd.Get()) == 0; }
95 :
96 : /// Get the name of created temporary file.
97 146 : const std::string & GetFileName() const { return mFileName; }
98 :
99 : private:
100 : FileDescriptor mFd;
101 : FileDescriptorStreamBuf mBuf;
102 : std::string mFileName;
103 : };
104 :
105 : } // namespace Internal
106 : } // namespace DeviceLayer
107 : } // namespace chip
|