1 //===-- File.h --------------------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #ifndef liblldb_File_h_
11 #define liblldb_File_h_
12 
13 #include "lldb/Host/PosixApi.h"
14 #include "lldb/Utility/IOObject.h"
15 #include "lldb/Utility/Status.h"
16 #include "lldb/lldb-private.h"
17 
18 #include <stdarg.h>
19 #include <stdio.h>
20 #include <sys/types.h>
21 
22 namespace lldb_private {
23 
24 //----------------------------------------------------------------------
25 /// @class File File.h "lldb/Host/File.h"
26 /// A file class.
27 ///
28 /// A file class that divides abstracts the LLDB core from host file
29 /// functionality.
30 //----------------------------------------------------------------------
31 class File : public IOObject {
32 public:
33   static int kInvalidDescriptor;
34   static FILE *kInvalidStream;
35 
36   // NB this enum is used in the lldb platform gdb-remote packet
37   // vFile:open: and existing values cannot be modified.
38   enum OpenOptions {
39     eOpenOptionRead = (1u << 0),  // Open file for reading
40     eOpenOptionWrite = (1u << 1), // Open file for writing
41     eOpenOptionAppend =
42         (1u << 2), // Don't truncate file when opening, append to end of file
43     eOpenOptionTruncate = (1u << 3),    // Truncate file when opening
44     eOpenOptionNonBlocking = (1u << 4), // File reads
45     eOpenOptionCanCreate = (1u << 5),   // Create file if doesn't already exist
46     eOpenOptionCanCreateNewOnly =
47         (1u << 6), // Can create file only if it doesn't already exist
48     eOpenOptionDontFollowSymlinks = (1u << 7),
49     eOpenOptionCloseOnExec =
50         (1u << 8) // Close the file when executing a new process
51   };
52 
53   static mode_t ConvertOpenOptionsForPOSIXOpen(uint32_t open_options);
54 
File()55   File()
56       : IOObject(eFDTypeFile, false), m_descriptor(kInvalidDescriptor),
57         m_stream(kInvalidStream), m_options(0), m_own_stream(false),
58         m_is_interactive(eLazyBoolCalculate),
59         m_is_real_terminal(eLazyBoolCalculate),
60         m_supports_colors(eLazyBoolCalculate) {}
61 
File(FILE * fh,bool transfer_ownership)62   File(FILE *fh, bool transfer_ownership)
63       : IOObject(eFDTypeFile, false), m_descriptor(kInvalidDescriptor),
64         m_stream(fh), m_options(0), m_own_stream(transfer_ownership),
65         m_is_interactive(eLazyBoolCalculate),
66         m_is_real_terminal(eLazyBoolCalculate),
67         m_supports_colors(eLazyBoolCalculate) {}
68 
File(int fd,bool transfer_ownership)69   File(int fd, bool transfer_ownership)
70       : IOObject(eFDTypeFile, transfer_ownership), m_descriptor(fd),
71         m_stream(kInvalidStream), m_options(0), m_own_stream(false),
72         m_is_interactive(eLazyBoolCalculate),
73         m_is_real_terminal(eLazyBoolCalculate) {}
74 
75   //------------------------------------------------------------------
76   /// Destructor.
77   ///
78   /// The destructor is virtual in case this class is subclassed.
79   //------------------------------------------------------------------
80   ~File() override;
81 
IsValid()82   bool IsValid() const override {
83     return DescriptorIsValid() || StreamIsValid();
84   }
85 
86   //------------------------------------------------------------------
87   /// Convert to pointer operator.
88   ///
89   /// This allows code to check a File object to see if it contains anything
90   /// valid using code such as:
91   ///
92   /// @code
93   /// File file(...);
94   /// if (file)
95   /// { ...
96   /// @endcode
97   ///
98   /// @return
99   ///     A pointer to this object if either the directory or filename
100   ///     is valid, nullptr otherwise.
101   //------------------------------------------------------------------
102   operator bool() const { return DescriptorIsValid() || StreamIsValid(); }
103 
104   //------------------------------------------------------------------
105   /// Logical NOT operator.
106   ///
107   /// This allows code to check a File object to see if it is invalid using
108   /// code such as:
109   ///
110   /// @code
111   /// File file(...);
112   /// if (!file)
113   /// { ...
114   /// @endcode
115   ///
116   /// @return
117   ///     Returns \b true if the object has an empty directory and
118   ///     filename, \b false otherwise.
119   //------------------------------------------------------------------
120   bool operator!() const { return !DescriptorIsValid() && !StreamIsValid(); }
121 
122   //------------------------------------------------------------------
123   /// Get the file spec for this file.
124   ///
125   /// @return
126   ///     A reference to the file specification object.
127   //------------------------------------------------------------------
128   Status GetFileSpec(FileSpec &file_spec) const;
129 
130   Status Close() override;
131 
132   void Clear();
133 
134   int GetDescriptor() const;
135 
136   WaitableHandle GetWaitableHandle() override;
137 
138   void SetDescriptor(int fd, bool transfer_ownership);
139 
140   FILE *GetStream();
141 
142   void SetStream(FILE *fh, bool transfer_ownership);
143 
144   //------------------------------------------------------------------
145   /// Read bytes from a file from the current file position.
146   ///
147   /// NOTE: This function is NOT thread safe. Use the read function
148   /// that takes an "off_t &offset" to ensure correct operation in multi-
149   /// threaded environments.
150   ///
151   /// @param[in] buf
152   ///     A buffer where to put the bytes that are read.
153   ///
154   /// @param[in,out] num_bytes
155   ///     The number of bytes to read form the current file position
156   ///     which gets modified with the number of bytes that were read.
157   ///
158   /// @return
159   ///     An error object that indicates success or the reason for
160   ///     failure.
161   //------------------------------------------------------------------
162   Status Read(void *buf, size_t &num_bytes) override;
163 
164   //------------------------------------------------------------------
165   /// Write bytes to a file at the current file position.
166   ///
167   /// NOTE: This function is NOT thread safe. Use the write function
168   /// that takes an "off_t &offset" to ensure correct operation in multi-
169   /// threaded environments.
170   ///
171   /// @param[in] buf
172   ///     A buffer where to put the bytes that are read.
173   ///
174   /// @param[in,out] num_bytes
175   ///     The number of bytes to write to the current file position
176   ///     which gets modified with the number of bytes that were
177   ///     written.
178   ///
179   /// @return
180   ///     An error object that indicates success or the reason for
181   ///     failure.
182   //------------------------------------------------------------------
183   Status Write(const void *buf, size_t &num_bytes) override;
184 
185   //------------------------------------------------------------------
186   /// Seek to an offset relative to the beginning of the file.
187   ///
188   /// NOTE: This function is NOT thread safe, other threads that
189   /// access this object might also change the current file position. For
190   /// thread safe reads and writes see the following functions: @see
191   /// File::Read (void *, size_t, off_t &) @see File::Write (const void *,
192   /// size_t, off_t &)
193   ///
194   /// @param[in] offset
195   ///     The offset to seek to within the file relative to the
196   ///     beginning of the file.
197   ///
198   /// @param[in] error_ptr
199   ///     A pointer to a lldb_private::Status object that will be
200   ///     filled in if non-nullptr.
201   ///
202   /// @return
203   ///     The resulting seek offset, or -1 on error.
204   //------------------------------------------------------------------
205   off_t SeekFromStart(off_t offset, Status *error_ptr = nullptr);
206 
207   //------------------------------------------------------------------
208   /// Seek to an offset relative to the current file position.
209   ///
210   /// NOTE: This function is NOT thread safe, other threads that
211   /// access this object might also change the current file position. For
212   /// thread safe reads and writes see the following functions: @see
213   /// File::Read (void *, size_t, off_t &) @see File::Write (const void *,
214   /// size_t, off_t &)
215   ///
216   /// @param[in] offset
217   ///     The offset to seek to within the file relative to the
218   ///     current file position.
219   ///
220   /// @param[in] error_ptr
221   ///     A pointer to a lldb_private::Status object that will be
222   ///     filled in if non-nullptr.
223   ///
224   /// @return
225   ///     The resulting seek offset, or -1 on error.
226   //------------------------------------------------------------------
227   off_t SeekFromCurrent(off_t offset, Status *error_ptr = nullptr);
228 
229   //------------------------------------------------------------------
230   /// Seek to an offset relative to the end of the file.
231   ///
232   /// NOTE: This function is NOT thread safe, other threads that
233   /// access this object might also change the current file position. For
234   /// thread safe reads and writes see the following functions: @see
235   /// File::Read (void *, size_t, off_t &) @see File::Write (const void *,
236   /// size_t, off_t &)
237   ///
238   /// @param[in,out] offset
239   ///     The offset to seek to within the file relative to the
240   ///     end of the file which gets filled in with the resulting
241   ///     absolute file offset.
242   ///
243   /// @param[in] error_ptr
244   ///     A pointer to a lldb_private::Status object that will be
245   ///     filled in if non-nullptr.
246   ///
247   /// @return
248   ///     The resulting seek offset, or -1 on error.
249   //------------------------------------------------------------------
250   off_t SeekFromEnd(off_t offset, Status *error_ptr = nullptr);
251 
252   //------------------------------------------------------------------
253   /// Read bytes from a file from the specified file offset.
254   ///
255   /// NOTE: This function is thread safe in that clients manager their
256   /// own file position markers and reads on other threads won't mess up the
257   /// current read.
258   ///
259   /// @param[in] dst
260   ///     A buffer where to put the bytes that are read.
261   ///
262   /// @param[in,out] num_bytes
263   ///     The number of bytes to read form the current file position
264   ///     which gets modified with the number of bytes that were read.
265   ///
266   /// @param[in,out] offset
267   ///     The offset within the file from which to read \a num_bytes
268   ///     bytes. This offset gets incremented by the number of bytes
269   ///     that were read.
270   ///
271   /// @return
272   ///     An error object that indicates success or the reason for
273   ///     failure.
274   //------------------------------------------------------------------
275   Status Read(void *dst, size_t &num_bytes, off_t &offset);
276 
277   //------------------------------------------------------------------
278   /// Read bytes from a file from the specified file offset.
279   ///
280   /// NOTE: This function is thread safe in that clients manager their
281   /// own file position markers and reads on other threads won't mess up the
282   /// current read.
283   ///
284   /// @param[in,out] num_bytes
285   ///     The number of bytes to read form the current file position
286   ///     which gets modified with the number of bytes that were read.
287   ///
288   /// @param[in,out] offset
289   ///     The offset within the file from which to read \a num_bytes
290   ///     bytes. This offset gets incremented by the number of bytes
291   ///     that were read.
292   ///
293   /// @param[in] null_terminate
294   ///     Ensure that the data that is read is terminated with a NULL
295   ///     character so that the data can be used as a C string.
296   ///
297   /// @param[out] data_buffer_sp
298   ///     A data buffer to create and fill in that will contain any
299   ///     data that is read from the file. This buffer will be reset
300   ///     if an error occurs.
301   ///
302   /// @return
303   ///     An error object that indicates success or the reason for
304   ///     failure.
305   //------------------------------------------------------------------
306   Status Read(size_t &num_bytes, off_t &offset, bool null_terminate,
307               lldb::DataBufferSP &data_buffer_sp);
308 
309   //------------------------------------------------------------------
310   /// Write bytes to a file at the specified file offset.
311   ///
312   /// NOTE: This function is thread safe in that clients manager their
313   /// own file position markers, though clients will need to implement their
314   /// own locking externally to avoid multiple people writing to the file at
315   /// the same time.
316   ///
317   /// @param[in] src
318   ///     A buffer containing the bytes to write.
319   ///
320   /// @param[in,out] num_bytes
321   ///     The number of bytes to write to the file at offset \a offset.
322   ///     \a num_bytes gets modified with the number of bytes that
323   ///     were read.
324   ///
325   /// @param[in,out] offset
326   ///     The offset within the file at which to write \a num_bytes
327   ///     bytes. This offset gets incremented by the number of bytes
328   ///     that were written.
329   ///
330   /// @return
331   ///     An error object that indicates success or the reason for
332   ///     failure.
333   //------------------------------------------------------------------
334   Status Write(const void *src, size_t &num_bytes, off_t &offset);
335 
336   //------------------------------------------------------------------
337   /// Flush the current stream
338   ///
339   /// @return
340   ///     An error object that indicates success or the reason for
341   ///     failure.
342   //------------------------------------------------------------------
343   Status Flush();
344 
345   //------------------------------------------------------------------
346   /// Sync to disk.
347   ///
348   /// @return
349   ///     An error object that indicates success or the reason for
350   ///     failure.
351   //------------------------------------------------------------------
352   Status Sync();
353 
354   //------------------------------------------------------------------
355   /// Get the permissions for a this file.
356   ///
357   /// @return
358   ///     Bits logical OR'ed together from the permission bits defined
359   ///     in lldb_private::File::Permissions.
360   //------------------------------------------------------------------
361   uint32_t GetPermissions(Status &error) const;
362 
363   //------------------------------------------------------------------
364   /// Return true if this file is interactive.
365   ///
366   /// @return
367   ///     True if this file is a terminal (tty or pty), false
368   ///     otherwise.
369   //------------------------------------------------------------------
370   bool GetIsInteractive();
371 
372   //------------------------------------------------------------------
373   /// Return true if this file from a real terminal.
374   ///
375   /// Just knowing a file is a interactive isn't enough, we also need to know
376   /// if the terminal has a width and height so we can do cursor movement and
377   /// other terminal manipulations by sending escape sequences.
378   ///
379   /// @return
380   ///     True if this file is a terminal (tty, not a pty) that has
381   ///     a non-zero width and height, false otherwise.
382   //------------------------------------------------------------------
383   bool GetIsRealTerminal();
384 
385   bool GetIsTerminalWithColors();
386 
387   //------------------------------------------------------------------
388   /// Output printf formatted output to the stream.
389   ///
390   /// Print some formatted output to the stream.
391   ///
392   /// @param[in] format
393   ///     A printf style format string.
394   ///
395   /// @param[in] ...
396   ///     Variable arguments that are needed for the printf style
397   ///     format string \a format.
398   //------------------------------------------------------------------
399   size_t Printf(const char *format, ...) __attribute__((format(printf, 2, 3)));
400 
401   size_t PrintfVarArg(const char *format, va_list args);
402 
SetOptions(uint32_t options)403   void SetOptions(uint32_t options) { m_options = options; }
404 
DescriptorIsValid(int descriptor)405   static bool DescriptorIsValid(int descriptor) { return descriptor >= 0; };
406 
407 protected:
DescriptorIsValid()408   bool DescriptorIsValid() const { return DescriptorIsValid(m_descriptor); }
409 
StreamIsValid()410   bool StreamIsValid() const { return m_stream != kInvalidStream; }
411 
412   void CalculateInteractiveAndTerminal();
413 
414   //------------------------------------------------------------------
415   // Member variables
416   //------------------------------------------------------------------
417   int m_descriptor;
418   FILE *m_stream;
419   uint32_t m_options;
420   bool m_own_stream;
421   LazyBool m_is_interactive;
422   LazyBool m_is_real_terminal;
423   LazyBool m_supports_colors;
424 
425 private:
426   DISALLOW_COPY_AND_ASSIGN(File);
427 };
428 
429 } // namespace lldb_private
430 
431 #endif // liblldb_File_h_
432