1//===-- File.h --------------------------------------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#ifndef LLDB_HOST_FILE_H
10#define LLDB_HOST_FILE_H
11
12#include "lldb/Host/PosixApi.h"
13#include "lldb/Host/Terminal.h"
14#include "lldb/Utility/IOObject.h"
15#include "lldb/Utility/Status.h"
16#include "lldb/lldb-private.h"
17#include "llvm/ADT/BitmaskEnum.h"
18
19#include <cstdarg>
20#include <cstdio>
21#include <mutex>
22#include <optional>
23#include <sys/types.h>
24
25namespace lldb_private {
26
27LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();
28
29/// \class File File.h "lldb/Host/File.h"
30/// An abstract base class for files.
31///
32/// Files will often be NativeFiles, which provides a wrapper
33/// around host OS file functionality. But it
34/// is also possible to subclass file to provide objects that have file
35/// or stream functionality but are not backed by any host OS file.
36class File : public IOObject {
37public:
38 static int kInvalidDescriptor;
39 static FILE *kInvalidStream;
40
41 // NB this enum is used in the lldb platform gdb-remote packet
42 // vFile:open: and existing values cannot be modified.
43 //
44 // The first set of values is defined by gdb headers and can be found
45 // in the documentation at:
46 // * https://sourceware.org/gdb/onlinedocs/gdb/Open-Flags.html#Open-Flags
47 //
48 // The second half are LLDB extensions and use the highest uint32_t bits
49 // to avoid risk of collisions with future gdb remote protocol changes.
50 enum OpenOptions : uint32_t {
51 eOpenOptionReadOnly = 0x0, // Open file for reading (only)
52 eOpenOptionWriteOnly = 0x1, // Open file for writing (only)
53 eOpenOptionReadWrite = 0x2, // Open file for both reading and writing
54 eOpenOptionAppend =
55 0x8, // Don't truncate file when opening, append to end of file
56 eOpenOptionCanCreate = 0x200, // Create file if doesn't already exist
57 eOpenOptionTruncate = 0x400, // Truncate file when opening
58 eOpenOptionCanCreateNewOnly =
59 0x800, // Can create file only if it doesn't already exist
60
61 eOpenOptionNonBlocking = (1u << 28), // File reads
62 eOpenOptionDontFollowSymlinks = (1u << 29),
63 eOpenOptionCloseOnExec =
64 (1u << 30), // Close the file when executing a new process
65 eOpenOptionInvalid = (1u << 31), // Used as invalid value
66 LLVM_MARK_AS_BITMASK_ENUM(/* largest_value= */ eOpenOptionInvalid)
67 };
68
69 static mode_t ConvertOpenOptionsForPOSIXOpen(OpenOptions open_options);
70 static llvm::Expected<OpenOptions> GetOptionsFromMode(llvm::StringRef mode);
71 static bool DescriptorIsValid(int descriptor) { return descriptor >= 0; };
72 static llvm::Expected<const char *>
73 GetStreamOpenModeFromOptions(OpenOptions options);
74
75 File() : IOObject(eFDTypeFile){};
76
77 /// Read bytes from a file from the current file position into buf.
78 ///
79 /// NOTE: This function is NOT thread safe. Use the read function
80 /// that takes an "off_t &offset" to ensure correct operation in multi-
81 /// threaded environments.
82 ///
83 /// \param[in,out] num_bytes
84 /// Pass in the size of buf. Read will pass out the number
85 /// of bytes read. Zero bytes read with no error indicates
86 /// EOF.
87 ///
88 /// \return
89 /// success, ENOTSUP, or another error.
90 Status Read(void *buf, size_t &num_bytes) override;
91
92 /// Write bytes from buf to a file at the current file position.
93 ///
94 /// NOTE: This function is NOT thread safe. Use the write function
95 /// that takes an "off_t &offset" to ensure correct operation in multi-
96 /// threaded environments.
97 ///
98 /// \param[in,out] num_bytes
99 /// Pass in the size of buf. Write will pass out the number
100 /// of bytes written. Write will attempt write the full number
101 /// of bytes and will not return early except on error.
102 ///
103 /// \return
104 /// success, ENOTSUP, or another error.
105 Status Write(const void *buf, size_t &num_bytes) override;
106
107 /// IsValid
108 ///
109 /// \return
110 /// true iff the file is valid.
111 bool IsValid() const override;
112
113 /// Flush any buffers and release any resources owned by the file.
114 /// After Close() the file will be invalid.
115 ///
116 /// \return
117 /// success or an error.
118 Status Close() override;
119
120 /// Get a handle that can be used for OS polling interfaces, such
121 /// as WaitForMultipleObjects, select, or epoll. This may return
122 /// IOObject::kInvalidHandleValue if none is available. This will
123 /// generally be the same as the file descriptor, this function
124 /// is not interchangeable with GetDescriptor(). A WaitableHandle
125 /// must only be used for polling, not actual I/O.
126 ///
127 /// \return
128 /// a valid handle or IOObject::kInvalidHandleValue
129 WaitableHandle GetWaitableHandle() override;
130
131 /// Get the file specification for this file, if possible.
132 ///
133 /// \param[out] file_spec
134 /// the file specification.
135 /// \return
136 /// ENOTSUP, success, or another error.
137 virtual Status GetFileSpec(FileSpec &file_spec) const;
138
139 /// Get underlying OS file descriptor for this file, or kInvalidDescriptor.
140 /// If the descriptor is valid, then it may be used directly for I/O
141 /// However, the File may also perform it's own buffering, so avoid using
142 /// this if it is not necessary, or use Flush() appropriately.
143 ///
144 /// \return
145 /// a valid file descriptor for this file or kInvalidDescriptor
146 virtual int GetDescriptor() const;
147
148 /// Get the underlying libc stream for this file, or NULL.
149 ///
150 /// Not all valid files will have a FILE* stream. This should only be
151 /// used if absolutely necessary, such as to interact with 3rd party
152 /// libraries that need FILE* streams.
153 ///
154 /// \return
155 /// a valid stream or NULL;
156 virtual FILE *GetStream();
157
158 /// Seek to an offset relative to the beginning of the file.
159 ///
160 /// NOTE: This function is NOT thread safe, other threads that
161 /// access this object might also change the current file position. For
162 /// thread safe reads and writes see the following functions: @see
163 /// File::Read (void *, size_t, off_t &) \see File::Write (const void *,
164 /// size_t, off_t &)
165 ///
166 /// \param[in] offset
167 /// The offset to seek to within the file relative to the
168 /// beginning of the file.
169 ///
170 /// \param[in] error_ptr
171 /// A pointer to a lldb_private::Status object that will be
172 /// filled in if non-nullptr.
173 ///
174 /// \return
175 /// The resulting seek offset, or -1 on error.
176 virtual off_t SeekFromStart(off_t offset, Status *error_ptr = nullptr);
177
178 /// Seek to an offset relative to the current file position.
179 ///
180 /// NOTE: This function is NOT thread safe, other threads that
181 /// access this object might also change the current file position. For
182 /// thread safe reads and writes see the following functions: @see
183 /// File::Read (void *, size_t, off_t &) \see File::Write (const void *,
184 /// size_t, off_t &)
185 ///
186 /// \param[in] offset
187 /// The offset to seek to within the file relative to the
188 /// current file position.
189 ///
190 /// \param[in] error_ptr
191 /// A pointer to a lldb_private::Status object that will be
192 /// filled in if non-nullptr.
193 ///
194 /// \return
195 /// The resulting seek offset, or -1 on error.
196 virtual off_t SeekFromCurrent(off_t offset, Status *error_ptr = nullptr);
197
198 /// Seek to an offset relative to the end of the file.
199 ///
200 /// NOTE: This function is NOT thread safe, other threads that
201 /// access this object might also change the current file position. For
202 /// thread safe reads and writes see the following functions: @see
203 /// File::Read (void *, size_t, off_t &) \see File::Write (const void *,
204 /// size_t, off_t &)
205 ///
206 /// \param[in,out] offset
207 /// The offset to seek to within the file relative to the
208 /// end of the file which gets filled in with the resulting
209 /// absolute file offset.
210 ///
211 /// \param[in] error_ptr
212 /// A pointer to a lldb_private::Status object that will be
213 /// filled in if non-nullptr.
214 ///
215 /// \return
216 /// The resulting seek offset, or -1 on error.
217 virtual off_t SeekFromEnd(off_t offset, Status *error_ptr = nullptr);
218
219 /// Read bytes from a file from the specified file offset.
220 ///
221 /// NOTE: This function is thread safe in that clients manager their
222 /// own file position markers and reads on other threads won't mess up the
223 /// current read.
224 ///
225 /// \param[in] dst
226 /// A buffer where to put the bytes that are read.
227 ///
228 /// \param[in,out] num_bytes
229 /// The number of bytes to read from the current file position
230 /// which gets modified with the number of bytes that were read.
231 ///
232 /// \param[in,out] offset
233 /// The offset within the file from which to read \a num_bytes
234 /// bytes. This offset gets incremented by the number of bytes
235 /// that were read.
236 ///
237 /// \return
238 /// An error object that indicates success or the reason for
239 /// failure.
240 virtual Status Read(void *dst, size_t &num_bytes, off_t &offset);
241
242 /// Write bytes to a file at the specified file offset.
243 ///
244 /// NOTE: This function is thread safe in that clients manager their
245 /// own file position markers, though clients will need to implement their
246 /// own locking externally to avoid multiple people writing to the file at
247 /// the same time.
248 ///
249 /// \param[in] src
250 /// A buffer containing the bytes to write.
251 ///
252 /// \param[in,out] num_bytes
253 /// The number of bytes to write to the file at offset \a offset.
254 /// \a num_bytes gets modified with the number of bytes that
255 /// were read.
256 ///
257 /// \param[in,out] offset
258 /// The offset within the file at which to write \a num_bytes
259 /// bytes. This offset gets incremented by the number of bytes
260 /// that were written.
261 ///
262 /// \return
263 /// An error object that indicates success or the reason for
264 /// failure.
265 virtual Status Write(const void *src, size_t &num_bytes, off_t &offset);
266
267 /// Flush the current stream
268 ///
269 /// \return
270 /// An error object that indicates success or the reason for
271 /// failure.
272 virtual Status Flush();
273
274 /// Sync to disk.
275 ///
276 /// \return
277 /// An error object that indicates success or the reason for
278 /// failure.
279 virtual Status Sync();
280
281 /// Output printf formatted output to the stream.
282 ///
283 /// NOTE: this is not virtual, because it just calls the va_list
284 /// version of the function.
285 ///
286 /// Print some formatted output to the stream.
287 ///
288 /// \param[in] format
289 /// A printf style format string.
290 ///
291 /// \param[in] ...
292 /// Variable arguments that are needed for the printf style
293 /// format string \a format.
294 size_t Printf(const char *format, ...) __attribute__((format(printf, 2, 3)));
295
296 /// Output printf formatted output to the stream.
297 ///
298 /// Print some formatted output to the stream.
299 ///
300 /// \param[in] format
301 /// A printf style format string.
302 ///
303 /// \param[in] args
304 /// Variable arguments that are needed for the printf style
305 /// format string \a format.
306 virtual size_t PrintfVarArg(const char *format, va_list args);
307
308 /// Return the OpenOptions for this file.
309 ///
310 /// Some options like eOpenOptionDontFollowSymlinks only make
311 /// sense when a file is being opened (or not at all)
312 /// and may not be preserved for this method. But any valid
313 /// File should return either eOpenOptionReadOnly, eOpenOptionWriteOnly
314 /// or eOpenOptionReadWrite here.
315 ///
316 /// \return
317 /// OpenOptions flags for this file, or an error.
318 virtual llvm::Expected<OpenOptions> GetOptions() const;
319
320 llvm::Expected<const char *> GetOpenMode() const {
321 auto opts = GetOptions();
322 if (!opts)
323 return opts.takeError();
324 return GetStreamOpenModeFromOptions(options: opts.get());
325 }
326
327 /// Get the permissions for a this file.
328 ///
329 /// \return
330 /// Bits logical OR'ed together from the permission bits defined
331 /// in lldb_private::File::Permissions.
332 uint32_t GetPermissions(Status &error) const;
333
334 /// Return true if this file is interactive.
335 ///
336 /// \return
337 /// True if this file is a terminal (tty or pty), false
338 /// otherwise.
339 bool GetIsInteractive();
340
341 /// Return true if this file from a real terminal.
342 ///
343 /// Just knowing a file is a interactive isn't enough, we also need to know
344 /// if the terminal has a width and height so we can do cursor movement and
345 /// other terminal manipulations by sending escape sequences.
346 ///
347 /// \return
348 /// True if this file is a terminal (tty, not a pty) that has
349 /// a non-zero width and height, false otherwise.
350 bool GetIsRealTerminal();
351
352 /// Return true if this file is a terminal which supports colors.
353 ///
354 /// \return
355 /// True iff this is a terminal and it supports colors.
356 bool GetIsTerminalWithColors();
357
358 operator bool() const { return IsValid(); };
359
360 bool operator!() const { return !IsValid(); };
361
362 static char ID;
363 virtual bool isA(const void *classID) const { return classID == &ID; }
364 static bool classof(const File *file) { return file->isA(classID: &ID); }
365
366protected:
367 LazyBool m_is_interactive = eLazyBoolCalculate;
368 LazyBool m_is_real_terminal = eLazyBoolCalculate;
369 LazyBool m_supports_colors = eLazyBoolCalculate;
370
371 void CalculateInteractiveAndTerminal();
372
373private:
374 File(const File &) = delete;
375 const File &operator=(const File &) = delete;
376};
377
378class NativeFile : public File {
379public:
380 NativeFile() : m_descriptor(kInvalidDescriptor), m_stream(kInvalidStream) {}
381
382 NativeFile(FILE *fh, bool transfer_ownership)
383 : m_descriptor(kInvalidDescriptor), m_own_descriptor(false), m_stream(fh),
384 m_options(), m_own_stream(transfer_ownership) {}
385
386 NativeFile(int fd, OpenOptions options, bool transfer_ownership)
387 : m_descriptor(fd), m_own_descriptor(transfer_ownership),
388 m_stream(kInvalidStream), m_options(options), m_own_stream(false) {}
389
390 ~NativeFile() override { Close(); }
391
392 bool IsValid() const override;
393
394 Status Read(void *buf, size_t &num_bytes) override;
395 Status Write(const void *buf, size_t &num_bytes) override;
396 Status Close() override;
397 WaitableHandle GetWaitableHandle() override;
398 Status GetFileSpec(FileSpec &file_spec) const override;
399 int GetDescriptor() const override;
400 FILE *GetStream() override;
401 off_t SeekFromStart(off_t offset, Status *error_ptr = nullptr) override;
402 off_t SeekFromCurrent(off_t offset, Status *error_ptr = nullptr) override;
403 off_t SeekFromEnd(off_t offset, Status *error_ptr = nullptr) override;
404 Status Read(void *dst, size_t &num_bytes, off_t &offset) override;
405 Status Write(const void *src, size_t &num_bytes, off_t &offset) override;
406 Status Flush() override;
407 Status Sync() override;
408 size_t PrintfVarArg(const char *format, va_list args) override;
409 llvm::Expected<OpenOptions> GetOptions() const override;
410
411 static char ID;
412 bool isA(const void *classID) const override {
413 return classID == &ID || File::isA(classID);
414 }
415 static bool classof(const File *file) { return file->isA(classID: &ID); }
416
417protected:
418 struct ValueGuard {
419 ValueGuard(std::mutex &m, bool b) : guard(m, std::adopt_lock), value(b) {}
420 std::lock_guard<std::mutex> guard;
421 bool value;
422 operator bool() { return value; }
423 };
424
425 bool DescriptorIsValidUnlocked() const {
426
427 return File::DescriptorIsValid(descriptor: m_descriptor);
428 }
429
430 bool StreamIsValidUnlocked() const { return m_stream != kInvalidStream; }
431
432 ValueGuard DescriptorIsValid() const {
433 m_descriptor_mutex.lock();
434 return ValueGuard(m_descriptor_mutex, DescriptorIsValidUnlocked());
435 }
436
437 ValueGuard StreamIsValid() const {
438 m_stream_mutex.lock();
439 return ValueGuard(m_stream_mutex, StreamIsValidUnlocked());
440 }
441
442 int m_descriptor;
443 bool m_own_descriptor = false;
444 mutable std::mutex m_descriptor_mutex;
445
446 FILE *m_stream;
447 mutable std::mutex m_stream_mutex;
448
449 OpenOptions m_options{};
450 bool m_own_stream = false;
451 std::mutex offset_access_mutex;
452
453private:
454 NativeFile(const NativeFile &) = delete;
455 const NativeFile &operator=(const NativeFile &) = delete;
456};
457
458class SerialPort : public NativeFile {
459public:
460 struct Options {
461 std::optional<unsigned int> BaudRate;
462 std::optional<Terminal::Parity> Parity;
463 std::optional<Terminal::ParityCheck> ParityCheck;
464 std::optional<unsigned int> StopBits;
465 };
466
467 // Obtain Options corresponding to the passed URL query string
468 // (i.e. the part after '?').
469 static llvm::Expected<Options> OptionsFromURL(llvm::StringRef urlqs);
470
471 static llvm::Expected<std::unique_ptr<SerialPort>>
472 Create(int fd, OpenOptions options, Options serial_options,
473 bool transfer_ownership);
474
475 bool IsValid() const override {
476 return NativeFile::IsValid() && m_is_interactive == eLazyBoolYes;
477 }
478
479 Status Close() override;
480
481 static char ID;
482 bool isA(const void *classID) const override {
483 return classID == &ID || File::isA(classID);
484 }
485 static bool classof(const File *file) { return file->isA(classID: &ID); }
486
487private:
488 SerialPort(int fd, OpenOptions options, Options serial_options,
489 bool transfer_ownership);
490
491 SerialPort(const SerialPort &) = delete;
492 const SerialPort &operator=(const SerialPort &) = delete;
493
494 TerminalState m_state;
495};
496
497} // namespace lldb_private
498
499#endif // LLDB_HOST_FILE_H
500

source code of lldb/include/lldb/Host/File.h