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 
25 namespace lldb_private {
26 
27 LLVM_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.
36 class File : public IOObject {
37 public:
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);
DescriptorIsValid(int descriptor)71   static bool DescriptorIsValid(int descriptor) { return descriptor >= 0; };
72   static llvm::Expected<const char *>
73   GetStreamOpenModeFromOptions(OpenOptions options);
74 
File()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 
GetOpenMode()320   llvm::Expected<const char *> GetOpenMode() const {
321     auto opts = GetOptions();
322     if (!opts)
323       return opts.takeError();
324     return GetStreamOpenModeFromOptions(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;
isA(const void * classID)363   virtual bool isA(const void *classID) const { return classID == &ID; }
classof(const File * file)364   static bool classof(const File *file) { return file->isA(&ID); }
365 
366 protected:
367   LazyBool m_is_interactive = eLazyBoolCalculate;
368   LazyBool m_is_real_terminal = eLazyBoolCalculate;
369   LazyBool m_supports_colors = eLazyBoolCalculate;
370 
371   void CalculateInteractiveAndTerminal();
372 
373 private:
374   File(const File &) = delete;
375   const File &operator=(const File &) = delete;
376 };
377 
378 class NativeFile : public File {
379 public:
NativeFile()380   NativeFile() : m_descriptor(kInvalidDescriptor), m_stream(kInvalidStream) {}
381 
NativeFile(FILE * fh,bool transfer_ownership)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 
NativeFile(int fd,OpenOptions options,bool transfer_ownership)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 
~NativeFile()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;
isA(const void * classID)412   bool isA(const void *classID) const override {
413     return classID == &ID || File::isA(classID);
414   }
classof(const File * file)415   static bool classof(const File *file) { return file->isA(&ID); }
416 
417 protected:
418   struct ValueGuard {
ValueGuardValueGuard419     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 
DescriptorIsValidUnlocked()425   bool DescriptorIsValidUnlocked() const {
426 
427     return File::DescriptorIsValid(m_descriptor);
428   }
429 
StreamIsValidUnlocked()430   bool StreamIsValidUnlocked() const { return m_stream != kInvalidStream; }
431 
DescriptorIsValid()432   ValueGuard DescriptorIsValid() const {
433     m_descriptor_mutex.lock();
434     return ValueGuard(m_descriptor_mutex, DescriptorIsValidUnlocked());
435   }
436 
StreamIsValid()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 
453 private:
454   NativeFile(const NativeFile &) = delete;
455   const NativeFile &operator=(const NativeFile &) = delete;
456 };
457 
458 class SerialPort : public NativeFile {
459 public:
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 
IsValid()475   bool IsValid() const override {
476     return NativeFile::IsValid() && m_is_interactive == eLazyBoolYes;
477   }
478 
479   Status Close() override;
480 
481   static char ID;
isA(const void * classID)482   bool isA(const void *classID) const override {
483     return classID == &ID || File::isA(classID);
484   }
classof(const File * file)485   static bool classof(const File *file) { return file->isA(&ID); }
486 
487 private:
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