Coverage Report

Created: 2023-09-30 09:22

/Users/buildslave/jenkins/workspace/coverage/llvm-project/lldb/include/lldb/Host/File.h
Line
Count
Source (jump to first uncovered line)
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);
71
4.02M
  static bool DescriptorIsValid(int descriptor) { return descriptor >= 0; };
72
  static llvm::Expected<const char *>
73
  GetStreamOpenModeFromOptions(OpenOptions options);
74
75
46.1k
  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
18
  llvm::Expected<const char *> GetOpenMode() const {
321
18
    auto opts = GetOptions();
322
18
    if (!opts)
323
0
      return opts.takeError();
324
18
    return GetStreamOpenModeFromOptions(opts.get());
325
18
  }
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
0
  operator bool() const { return IsValid(); };
359
360
36.8k
  bool operator!() const { return !IsValid(); };
361
362
  static char ID;
363
38.3k
  virtual bool isA(const void *classID) const { return classID == &ID; }
364
0
  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:
380
0
  NativeFile() : m_descriptor(kInvalidDescriptor), m_stream(kInvalidStream) {}
381
382
  NativeFile(FILE *fh, bool transfer_ownership)
383
20.0k
      : m_descriptor(kInvalidDescriptor), m_own_descriptor(false), m_stream(fh),
384
20.0k
        m_options(), m_own_stream(transfer_ownership) {}
385
386
  NativeFile(int fd, OpenOptions options, bool transfer_ownership)
387
26.0k
      : m_descriptor(fd), m_own_descriptor(transfer_ownership),
388
26.0k
        m_stream(kInvalidStream), m_options(options), m_own_stream(false) {}
389
390
45.9k
  ~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
38.3k
  bool isA(const void *classID) const override {
413
38.3k
    return classID == &ID || File::isA(classID);
414
38.3k
  }
415
0
  static bool classof(const File *file) { return file->isA(&ID); }
416
417
protected:
418
  struct ValueGuard {
419
2.02M
    ValueGuard(std::mutex &m, bool b) : guard(m, std::adopt_lock), value(b) {}
420
    std::lock_guard<std::mutex> guard;
421
    bool value;
422
2.02M
    operator bool() { return value; }
423
  };
424
425
4.00M
  bool DescriptorIsValidUnlocked() const {
426
427
4.00M
    return File::DescriptorIsValid(m_descriptor);
428
4.00M
  }
429
430
656k
  bool StreamIsValidUnlocked() const { return m_stream != kInvalidStream; }
431
432
1.93M
  ValueGuard DescriptorIsValid() const {
433
1.93M
    m_descriptor_mutex.lock();
434
1.93M
    return ValueGuard(m_descriptor_mutex, DescriptorIsValidUnlocked());
435
1.93M
  }
436
437
98.7k
  ValueGuard StreamIsValid() const {
438
98.7k
    m_stream_mutex.lock();
439
98.7k
    return ValueGuard(m_stream_mutex, StreamIsValidUnlocked());
440
98.7k
  }
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
475
331
  bool IsValid() const override {
476
331
    return NativeFile::IsValid() && 
m_is_interactive == eLazyBoolYes286
;
477
331
  }
478
479
  Status Close() override;
480
481
  static char ID;
482
0
  bool isA(const void *classID) const override {
483
0
    return classID == &ID || File::isA(classID);
484
0
  }
485
0
  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