1// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
2// (C) Copyright 2003-2007 Jonathan Turkanis
3// Distributed under the Boost Software License, Version 1.0. (See accompanying
4// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt.)
5
6// See http://www.boost.org/libs/iostreams for documentation.
7
8// Define BOOST_IOSTREAMS_SOURCE so that <boost/iostreams/detail/config.hpp>
9// knows that we are building the library (possibly exporting code), rather
10// than using it (possibly importing code).
11#define BOOST_IOSTREAMS_SOURCE
12
13#include <cassert>
14#include <cerrno>
15#include <cstdio> // SEEK_SET, etc.
16#include <boost/config.hpp> // BOOST_JOIN
17#include <boost/iostreams/detail/error.hpp>
18#include <boost/iostreams/detail/config/dyn_link.hpp>
19#include <boost/iostreams/detail/config/rtl.hpp> // BOOST_IOSTREAMS_FD_XXX
20#include <boost/iostreams/detail/config/windows_posix.hpp>
21#include <boost/iostreams/detail/system_failure.hpp>
22#include <boost/iostreams/detail/ios.hpp> // openmodes, failure.
23#include <boost/iostreams/device/file_descriptor.hpp>
24#include <boost/integer_traits.hpp>
25#include <boost/throw_exception.hpp>
26
27// Must come last.
28#include <boost/iostreams/detail/config/disable_warnings.hpp>
29
30 // OS-specific headers for low-level i/o.
31
32#include <fcntl.h> // file opening flags.
33#include <sys/stat.h> // file access permissions.
34#ifdef BOOST_IOSTREAMS_WINDOWS
35# include <io.h> // low-level file i/o.
36# define WINDOWS_LEAN_AND_MEAN
37# include <windows.h>
38# ifndef INVALID_SET_FILE_POINTER
39# define INVALID_SET_FILE_POINTER ((DWORD)-1)
40# endif
41#else
42# include <sys/types.h> // mode_t.
43# include <unistd.h> // low-level file i/o.
44#endif
45
46namespace boost { namespace iostreams {
47
48//------------------Definition of file_descriptor_impl------------------------//
49
50namespace detail {
51
52// Contains the platform dependant implementation
53struct file_descriptor_impl {
54 // Note: These need to match file_desciptor_flags
55 enum flags {
56 never_close = 0,
57 close_on_exit = 1,
58 close_on_close = 2,
59 close_always = 3
60 };
61
62 file_descriptor_impl();
63 ~file_descriptor_impl();
64 void open(file_handle fd, flags);
65#ifdef BOOST_IOSTREAMS_WINDOWS
66 void open(int fd, flags);
67#endif
68 void open(const detail::path&, BOOST_IOS::openmode);
69 bool is_open() const;
70 void close();
71 void close_impl(bool close_flag, bool throw_);
72 std::streamsize read(char* s, std::streamsize n);
73 std::streamsize write(const char* s, std::streamsize n);
74 std::streampos seek(stream_offset off, BOOST_IOS::seekdir way);
75 static file_handle invalid_handle();
76 file_handle handle_;
77 int flags_;
78};
79
80//------------------Implementation of file_descriptor_impl--------------------//
81
82file_descriptor_impl::file_descriptor_impl()
83 : handle_(invalid_handle()), flags_(0)
84 { }
85
86file_descriptor_impl::~file_descriptor_impl()
87{
88 close_impl(close_flag: flags_ & close_on_exit, throw_: false);
89}
90
91void file_descriptor_impl::open(file_handle fd, flags f)
92{
93 // Using 'close' to close the existing handle so that it will throw an
94 // exception if it fails.
95 //
96 // Only closing after assigning the new handle, so that the class will
97 // take ownership of the handle regardless of whether close throws.
98
99 file_descriptor_impl tmp;
100 tmp.handle_ = handle_;
101 tmp.flags_ = flags_ & close_on_exit ? close_on_close : never_close;
102
103 handle_ = fd;
104 flags_ = f;
105
106 tmp.close();
107}
108
109#ifdef BOOST_IOSTREAMS_WINDOWS //---------------------------------------------//
110
111void file_descriptor_impl::open(int fd, flags f)
112{ open(reinterpret_cast<file_handle>(_get_osfhandle(fd)), f); }
113
114#endif // #ifdef BOOST_IOSTREAMS_WINDOWS //-----------------------------------//
115
116void file_descriptor_impl::open(const detail::path& p, BOOST_IOS::openmode mode)
117{
118 close_impl(close_flag: flags_ & close_on_exit, throw_: true);
119
120#ifdef BOOST_IOSTREAMS_WINDOWS //---------------------------------------------//
121 DWORD dwDesiredAccess;
122 DWORD dwCreationDisposition;
123
124 if ( !(mode & (BOOST_IOS::in | BOOST_IOS::out | BOOST_IOS::app)) ||
125 ((mode & BOOST_IOS::trunc) &&
126 ((mode & BOOST_IOS::app) || !(mode & BOOST_IOS::out))) ) {
127 boost::throw_exception(BOOST_IOSTREAMS_FAILURE("bad open mode"));
128 }
129 else if ( mode & BOOST_IOS::in ) {
130 if ( mode & BOOST_IOS::app )
131 {
132 dwCreationDisposition = OPEN_ALWAYS;
133 dwDesiredAccess =
134 GENERIC_READ |
135 FILE_APPEND_DATA |
136 FILE_WRITE_ATTRIBUTES |
137 FILE_WRITE_EA |
138 STANDARD_RIGHTS_WRITE |
139 SYNCHRONIZE;
140 }
141 else if ( mode & BOOST_IOS::trunc )
142 {
143 dwCreationDisposition = CREATE_ALWAYS;
144 dwDesiredAccess = GENERIC_READ | GENERIC_WRITE;
145 }
146 else if ( mode & BOOST_IOS::out )
147 {
148 dwCreationDisposition = OPEN_EXISTING;
149 dwDesiredAccess = GENERIC_READ | GENERIC_WRITE;
150 }
151 else
152 {
153 dwCreationDisposition = OPEN_EXISTING;
154 dwDesiredAccess = GENERIC_READ;
155 }
156 }
157 else {
158 if ( mode & BOOST_IOS::app )
159 {
160 dwCreationDisposition = OPEN_ALWAYS;
161 dwDesiredAccess =
162 FILE_APPEND_DATA |
163 FILE_WRITE_ATTRIBUTES |
164 FILE_WRITE_EA |
165 STANDARD_RIGHTS_WRITE |
166 SYNCHRONIZE;
167 }
168 else
169 {
170 dwCreationDisposition = CREATE_ALWAYS;
171 dwDesiredAccess = GENERIC_WRITE;
172 }
173 }
174
175
176 HANDLE handle = p.is_wide() ?
177 ::CreateFileW( p.c_wstr(),
178 dwDesiredAccess,
179 FILE_SHARE_READ | FILE_SHARE_WRITE,
180 NULL, // lpSecurityAttributes
181 dwCreationDisposition,
182 FILE_ATTRIBUTE_NORMAL,
183 NULL ) : // hTemplateFile
184 ::CreateFileA( p.c_str(),
185 dwDesiredAccess,
186 FILE_SHARE_READ | FILE_SHARE_WRITE,
187 NULL, // lpSecurityAttributes
188 dwCreationDisposition,
189 FILE_ATTRIBUTE_NORMAL,
190 NULL ); // hTemplateFile
191 if (handle != INVALID_HANDLE_VALUE) {
192 handle_ = handle;
193 flags_ = close_always;
194 } else {
195 flags_ = 0;
196 throw_system_failure("failed opening file");
197 }
198#else // #ifdef BOOST_IOSTREAMS_WINDOWS //------------------------------------//
199
200 // Calculate oflag argument to open.
201
202 int oflag = 0;
203 if ( !(mode & (BOOST_IOS::in | BOOST_IOS::out | BOOST_IOS::app)) ||
204 ((mode & BOOST_IOS::trunc) &&
205 ((mode & BOOST_IOS::app) || !(mode & BOOST_IOS::out))) ) {
206 boost::throw_exception(BOOST_IOSTREAMS_FAILURE("bad open mode"));
207 }
208 else if ( mode & BOOST_IOS::in ) {
209 if ( mode & BOOST_IOS::app )
210 oflag |= O_CREAT | O_APPEND | O_RDWR;
211 else if ( mode & BOOST_IOS::trunc )
212 oflag |= O_CREAT | O_TRUNC | O_RDWR;
213 else if ( mode & BOOST_IOS::out )
214 oflag |= O_RDWR;
215 else
216 oflag |= O_RDONLY;
217 }
218 else {
219 if ( mode & BOOST_IOS::app )
220 oflag |= O_CREAT | O_APPEND | O_WRONLY;
221 else
222 oflag |= O_CREAT | O_TRUNC | O_WRONLY;
223 }
224 #ifdef _LARGEFILE64_SOURCE
225 oflag |= O_LARGEFILE;
226 #endif
227
228 // Calculate pmode argument to open.
229
230 mode_t pmode = S_IRUSR | S_IWUSR |
231 S_IRGRP | S_IWGRP |
232 S_IROTH | S_IWOTH;
233
234 // Open file.
235
236 int fd = BOOST_IOSTREAMS_FD_OPEN(file: p.c_str(), oflag: oflag, pmode);
237 if (fd == -1) {
238 boost::throw_exception(e: system_failure(msg: "failed opening file"));
239 } else {
240 if ( mode & BOOST_IOS::ate ) {
241 if (BOOST_IOSTREAMS_FD_SEEK(fd: fd, offset: 0, SEEK_END) == -1) {
242 BOOST_IOSTREAMS_FD_CLOSE(fd: fd);
243 boost::throw_exception(e: system_failure(msg: "failed opening file"));
244 }
245 }
246 handle_ = fd;
247 flags_ = close_always;
248 }
249#endif // #ifndef BOOST_IOSTREAMS_WINDOWS //----------------------------------//
250}
251
252bool file_descriptor_impl::is_open() const
253{ return handle_ != invalid_handle(); }
254
255void file_descriptor_impl::close()
256{
257 close_impl(close_flag: (flags_ & close_on_close) != 0, throw_: true);
258}
259
260void file_descriptor_impl::close_impl(bool close_flag, bool throw_) {
261 if (handle_ != invalid_handle()) {
262 bool success = true;
263
264 if (close_flag) {
265#ifdef BOOST_IOSTREAMS_WINDOWS
266 success = ::CloseHandle(handle_) == 1;
267#else
268 success = BOOST_IOSTREAMS_FD_CLOSE(fd: handle_) != -1;
269#endif
270 }
271 // Even if the close fails, we want nothing more to do with the handle
272 handle_ = invalid_handle();
273 flags_ = 0;
274 if (!success && throw_)
275 throw_system_failure(msg: "failed closing file");
276 }
277}
278
279std::streamsize file_descriptor_impl::read(char* s, std::streamsize n)
280{
281#ifdef BOOST_IOSTREAMS_WINDOWS
282 DWORD result;
283 if (!::ReadFile(handle_, s, static_cast<DWORD>(n), &result, NULL))
284 {
285 // report EOF if the write-side of a pipe has been closed
286 if (GetLastError() == ERROR_BROKEN_PIPE)
287 {
288 result = 0;
289 }
290 else
291 throw_system_failure("failed reading");
292 }
293 return result == 0 ? -1 : static_cast<std::streamsize>(result);
294#else // #ifdef BOOST_IOSTREAMS_WINDOWS
295 errno = 0;
296 std::streamsize result = BOOST_IOSTREAMS_FD_READ(fd: handle_, buf: s, nbytes: n);
297 if (errno != 0)
298 throw_system_failure(msg: "failed reading");
299 return result == 0 ? -1 : result;
300#endif // #ifdef BOOST_IOSTREAMS_WINDOWS
301}
302
303std::streamsize file_descriptor_impl::write(const char* s, std::streamsize n)
304{
305#ifdef BOOST_IOSTREAMS_WINDOWS
306 DWORD ignore;
307 if (!::WriteFile(handle_, s, static_cast<DWORD>(n), &ignore, NULL))
308 throw_system_failure("failed writing");
309 return n;
310#else // #ifdef BOOST_IOSTREAMS_WINDOWS
311 int amt = BOOST_IOSTREAMS_FD_WRITE(fd: handle_, buf: s, n: n);
312 if (amt < n) // Handles blocking fd's only.
313 throw_system_failure(msg: "failed writing");
314 return n;
315#endif // #ifdef BOOST_IOSTREAMS_WINDOWS
316}
317
318std::streampos file_descriptor_impl::seek
319 (stream_offset off, BOOST_IOS::seekdir way)
320{
321#ifdef BOOST_IOSTREAMS_WINDOWS
322 LONG lDistanceToMove = static_cast<LONG>(off & 0xffffffff);
323 LONG lDistanceToMoveHigh = static_cast<LONG>(off >> 32);
324 DWORD dwResultLow =
325 ::SetFilePointer( handle_,
326 lDistanceToMove,
327 &lDistanceToMoveHigh,
328 way == BOOST_IOS::beg ?
329 FILE_BEGIN :
330 way == BOOST_IOS::cur ?
331 FILE_CURRENT :
332 FILE_END );
333 if ( dwResultLow == INVALID_SET_FILE_POINTER &&
334 ::GetLastError() != NO_ERROR )
335 {
336 boost::throw_exception(system_failure("failed seeking"));
337 } else {
338 return offset_to_position(
339 (stream_offset(lDistanceToMoveHigh) << 32) + dwResultLow
340 );
341 }
342#else // #ifdef BOOST_IOSTREAMS_WINDOWS
343 if ( off > integer_traits<BOOST_IOSTREAMS_FD_OFFSET>::const_max ||
344 off < integer_traits<BOOST_IOSTREAMS_FD_OFFSET>::const_min )
345 {
346 boost::throw_exception(BOOST_IOSTREAMS_FAILURE("bad offset"));
347 }
348 stream_offset result =
349 BOOST_IOSTREAMS_FD_SEEK(
350 fd: handle_,
351 offset: static_cast<BOOST_IOSTREAMS_FD_OFFSET>(off),
352 whence: ( way == BOOST_IOS::beg ?
353 SEEK_SET :
354 way == BOOST_IOS::cur ?
355 SEEK_CUR :
356 SEEK_END )
357 );
358 if (result == -1)
359 boost::throw_exception(e: system_failure(msg: "failed seeking"));
360 return offset_to_position(off: result);
361#endif // #ifdef BOOST_IOSTREAMS_WINDOWS
362}
363
364// Returns the value stored in a file_handle variable when no file is open
365file_handle file_descriptor_impl::invalid_handle()
366{
367#ifdef BOOST_IOSTREAMS_WINDOWS
368 return INVALID_HANDLE_VALUE;
369#else
370 return -1;
371#endif
372}
373
374} // End namespace detail.
375
376//------------------Implementation of file_descriptor-------------------------//
377
378file_descriptor::file_descriptor() : pimpl_(new impl_type) { }
379
380file_descriptor::file_descriptor(handle_type fd, file_descriptor_flags f)
381 : pimpl_(new impl_type)
382{ open(fd, f); }
383
384#if defined(BOOST_IOSTREAMS_USE_DEPRECATED)
385file_descriptor::file_descriptor(handle_type fd, bool close_on_exit)
386 : pimpl_(new impl_type)
387{ open(fd, close_on_exit); }
388#endif
389
390#ifdef BOOST_IOSTREAMS_WINDOWS //---------------------------------------------//
391
392file_descriptor::file_descriptor(int fd, file_descriptor_flags f)
393 : pimpl_(new impl_type)
394{ open(fd, f); }
395
396#if defined(BOOST_IOSTREAMS_USE_DEPRECATED)
397file_descriptor::file_descriptor(int fd, bool close_on_exit)
398 : pimpl_(new impl_type)
399{ open(fd, close_on_exit); }
400#endif
401
402#endif // #ifdef BOOST_IOSTREAMS_WINDOWS //-----------------------------------//
403
404file_descriptor::file_descriptor( const std::string& path,
405 BOOST_IOS::openmode mode )
406 : pimpl_(new impl_type)
407{ open(path, mode); }
408
409file_descriptor::file_descriptor( const char* path,
410 BOOST_IOS::openmode mode )
411 : pimpl_(new impl_type)
412{ open(path, mode); }
413
414file_descriptor::file_descriptor(const file_descriptor& other)
415 : pimpl_(other.pimpl_)
416 { }
417
418void file_descriptor::open(handle_type fd, file_descriptor_flags f)
419{ pimpl_->open(fd, f: static_cast<detail::file_descriptor_impl::flags>(f)); }
420
421#if defined(BOOST_IOSTREAMS_USE_DEPRECATED)
422void file_descriptor::open(handle_type fd, bool close_on_exit)
423{ pimpl_->open(fd, close_on_exit ?
424 detail::file_descriptor_impl::close_always :
425 detail::file_descriptor_impl::close_on_close); }
426#endif
427
428#ifdef BOOST_IOSTREAMS_WINDOWS //---------------------------------------------//
429
430void file_descriptor::open(int fd, file_descriptor_flags f)
431{ pimpl_->open(fd, static_cast<detail::file_descriptor_impl::flags>(f)); }
432
433#if defined(BOOST_IOSTREAMS_USE_DEPRECATED)
434void file_descriptor::open(int fd, bool close_on_exit)
435{ pimpl_->open(fd, close_on_exit ?
436 detail::file_descriptor_impl::close_always :
437 detail::file_descriptor_impl::close_on_close); }
438#endif
439
440#endif // #ifdef BOOST_IOSTREAMS_WINDOWS //-----------------------------------//
441
442void file_descriptor::open(const std::string& path, BOOST_IOS::openmode mode)
443{ open(path: detail::path(path), mode); }
444
445void file_descriptor::open(const char* path, BOOST_IOS::openmode mode)
446{ open(path: detail::path(path), mode); }
447
448bool file_descriptor::is_open() const { return pimpl_->is_open(); }
449
450void file_descriptor::close() { pimpl_->close(); }
451
452std::streamsize file_descriptor::read(char_type* s, std::streamsize n)
453{ return pimpl_->read(s, n); }
454
455std::streamsize file_descriptor::write(const char_type* s, std::streamsize n)
456{ return pimpl_->write(s, n); }
457
458std::streampos file_descriptor::seek(stream_offset off, BOOST_IOS::seekdir way)
459{ return pimpl_->seek(off, way); }
460
461detail::file_handle file_descriptor::handle() const { return pimpl_->handle_; }
462
463void file_descriptor::init() { pimpl_.reset(p: new impl_type); }
464
465void file_descriptor::open(
466 const detail::path& path,
467 BOOST_IOS::openmode mode,
468 BOOST_IOS::openmode base )
469{
470 mode |= base;
471 pimpl_->open(p: path, mode);
472}
473
474//------------------Implementation of file_descriptor_source------------------//
475
476file_descriptor_source::file_descriptor_source(
477 handle_type fd, file_descriptor_flags f)
478{ open(fd, f); }
479
480#if defined(BOOST_IOSTREAMS_USE_DEPRECATED)
481file_descriptor_source::file_descriptor_source(
482 handle_type fd, bool close_on_exit)
483{ open(fd, close_on_exit); }
484#endif
485
486#ifdef BOOST_IOSTREAMS_WINDOWS //---------------------------------------------//
487
488file_descriptor_source::file_descriptor_source(int fd, file_descriptor_flags f)
489{ open(fd, f); }
490
491#if defined(BOOST_IOSTREAMS_USE_DEPRECATED)
492file_descriptor_source::file_descriptor_source(int fd, bool close_on_exit)
493{ open(fd, close_on_exit); }
494#endif
495
496#endif // #ifdef BOOST_IOSTREAMS_WINDOWS //-----------------------------------//
497
498file_descriptor_source::file_descriptor_source(
499 const std::string& path, BOOST_IOS::openmode mode)
500{ open(path, mode); }
501
502file_descriptor_source::file_descriptor_source(
503 const char* path, BOOST_IOS::openmode mode)
504{ open(path, mode); }
505
506file_descriptor_source::file_descriptor_source(
507 const file_descriptor_source& other)
508 : file_descriptor(static_cast<const file_descriptor&>(other))
509 { }
510
511void file_descriptor_source::open(handle_type fd, file_descriptor_flags f)
512{ file_descriptor::open(fd, f); }
513
514#if defined(BOOST_IOSTREAMS_USE_DEPRECATED)
515void file_descriptor_source::open(handle_type fd, bool close_on_exit)
516{ file_descriptor::open(fd, close_on_exit); }
517#endif
518
519#ifdef BOOST_IOSTREAMS_WINDOWS //---------------------------------------------//
520
521void file_descriptor_source::open(int fd, file_descriptor_flags f)
522{ file_descriptor::open(fd, f); }
523
524#if defined(BOOST_IOSTREAMS_USE_DEPRECATED)
525void file_descriptor_source::open(int fd, bool close_on_exit)
526{ file_descriptor::open(fd, close_on_exit); }
527#endif
528
529#endif // #ifdef BOOST_IOSTREAMS_WINDOWS //-----------------------------------//
530
531void file_descriptor_source::open(
532 const std::string& path, BOOST_IOS::openmode mode)
533{ open(path: detail::path(path), mode); }
534
535void file_descriptor_source::open(
536 const char* path, BOOST_IOS::openmode mode)
537{ open(path: detail::path(path), mode); }
538
539void file_descriptor_source::open(
540 const detail::path& path, BOOST_IOS::openmode mode)
541{
542 if (mode & (BOOST_IOS::out | BOOST_IOS::trunc))
543 boost::throw_exception(BOOST_IOSTREAMS_FAILURE("invalid mode"));
544 file_descriptor::open(path, mode, BOOST_IOS::in);
545}
546
547//------------------Implementation of file_descriptor_sink--------------------//
548
549file_descriptor_sink::file_descriptor_sink(
550 handle_type fd, file_descriptor_flags f)
551{ open(fd, f); }
552
553#if defined(BOOST_IOSTREAMS_USE_DEPRECATED)
554file_descriptor_sink::file_descriptor_sink(
555 handle_type fd, bool close_on_exit)
556{ open(fd, close_on_exit); }
557#endif
558
559#ifdef BOOST_IOSTREAMS_WINDOWS //---------------------------------------------//
560
561file_descriptor_sink::file_descriptor_sink(int fd, file_descriptor_flags f)
562{ open(fd, f); }
563
564#if defined(BOOST_IOSTREAMS_USE_DEPRECATED)
565file_descriptor_sink::file_descriptor_sink(int fd, bool close_on_exit)
566{ open(fd, close_on_exit); }
567#endif
568
569#endif // #ifdef BOOST_IOSTREAMS_WINDOWS //-----------------------------------//
570
571file_descriptor_sink::file_descriptor_sink(
572 const std::string& path, BOOST_IOS::openmode mode)
573{ open(path, mode); }
574
575file_descriptor_sink::file_descriptor_sink(
576 const char* path, BOOST_IOS::openmode mode)
577{ open(path, mode); }
578
579file_descriptor_sink::file_descriptor_sink(const file_descriptor_sink& other)
580 : file_descriptor(static_cast<const file_descriptor&>(other))
581 { }
582
583void file_descriptor_sink::open(handle_type fd, file_descriptor_flags f)
584{ file_descriptor::open(fd, f); }
585
586#if defined(BOOST_IOSTREAMS_USE_DEPRECATED)
587void file_descriptor_sink::open(handle_type fd, bool close_on_exit)
588{ file_descriptor::open(fd, close_on_exit); }
589#endif
590
591#ifdef BOOST_IOSTREAMS_WINDOWS //---------------------------------------------//
592
593void file_descriptor_sink::open(int fd, file_descriptor_flags f)
594{ file_descriptor::open(fd, f); }
595
596#if defined(BOOST_IOSTREAMS_USE_DEPRECATED)
597void file_descriptor_sink::open(int fd, bool close_on_exit)
598{ file_descriptor::open(fd, close_on_exit); }
599#endif
600
601#endif // #ifdef BOOST_IOSTREAMS_WINDOWS //-----------------------------------//
602
603void file_descriptor_sink::open(
604 const std::string& path, BOOST_IOS::openmode mode)
605{ open(path: detail::path(path), mode); }
606
607void file_descriptor_sink::open(
608 const char* path, BOOST_IOS::openmode mode)
609{ open(path: detail::path(path), mode); }
610
611void file_descriptor_sink::open(
612 const detail::path& path, BOOST_IOS::openmode mode)
613{
614 if (mode & BOOST_IOS::in)
615 boost::throw_exception(BOOST_IOSTREAMS_FAILURE("invalid mode"));
616 file_descriptor::open(path, mode, BOOST_IOS::out);
617}
618
619#include <boost/iostreams/detail/config/enable_warnings.hpp>
620
621} } // End namespaces iostreams, boost.
622

source code of boost/libs/iostreams/src/file_descriptor.cpp