RESTinio
sendfile_defs_posix.hpp
Go to the documentation of this file.
1 /*
2  restinio
3 */
4 
5 /*!
6  Sendfile routine definitions (posix implementation).
7 
8  @since v.0.4.3
9 */
10 
11 #pragma once
12 
13 #include <sys/types.h>
14 #include <sys/stat.h>
15 #include <fcntl.h>
16 
17 #include <iostream>
18 
19 namespace restinio
20 {
21 
22 #if defined( __FreeBSD__ )
23  #define RESTINIO_FREEBSD_TARGET
24 #elif defined(__APPLE__) && defined( __MACH__ )
25  #define RESTINIO_MACOS_TARGET
26 #endif
27 
28 /** @name Aliases for sendfile operation.
29  */
30 ///@{
31 using file_descriptor_t = int;
32 using file_offset_t = std::int64_t;
33 using file_size_t = std::uint64_t;
34 ///@}
35 
36 /** @name File operations.
37  * @brief A minimal set of file operations.
38  *
39  * Incapsulates details of native API for a set of file operations neccessary
40  * for sendfile_t class implementation.
41  */
42 ///@{
43 
44 //! Get file descriptor which stands for null.
45 [[nodiscard]]
46 constexpr file_descriptor_t null_file_descriptor(){ return -1; }
47 
48 //! Open file.
49 [[nodiscard]]
50 inline file_descriptor_t
51 open_file( const char * file_path)
52 {
53 #if defined( RESTINIO_FREEBSD_TARGET ) || defined( RESTINIO_MACOS_TARGET )
54  file_descriptor_t file_descriptor = ::open( file_path, O_RDONLY );
55 #else
56  file_descriptor_t file_descriptor = ::open( file_path, O_RDONLY | O_LARGEFILE );
57 #endif
58  if( null_file_descriptor() == file_descriptor )
59  {
60  throw exception_t{
61  fmt::format(
62  RESTINIO_FMT_FORMAT_STRING( "unable to openfile '{}': {}" ),
63  file_path,
64  strerror( errno ) )
65  };
66  }
67  return file_descriptor;
68 }
69 
70 /*!
71  * @brief Helper function that accepts std::filesystem::path.
72  *
73  * Just delegates all real work to open_file(const char *).
74  *
75  * @attention
76  * Uses std::filesystem::path::c_str() to get file name and pass it
77  * to the actual open_file implementation. It means that we assume
78  * that file systems on POSIX uses UTF-8 natively and that
79  * @a file_path is specified in UTF-8.
80  *
81  * @since v.0.7.1
82  */
83 [[nodiscard]]
84 inline file_descriptor_t
85 open_file( const std::filesystem::path & file_path )
86 {
87  // Use c_str() on POSIX, because it's assumed that
88  // filesystem uses UTF-8.
89  return open_file( file_path.c_str() );
90 }
91 
92 //! Get file meta.
93 template < typename META >
94 [[nodiscard]]
95 META
96 get_file_meta( file_descriptor_t fd )
97 {
98  if( null_file_descriptor() == fd )
99  {
100  throw exception_t{ "invalid file descriptor" };
101  }
102 
103 #if defined( RESTINIO_FREEBSD_TARGET ) || defined( RESTINIO_MACOS_TARGET )
104  struct stat file_stat;
105 
106  const auto fstat_rc = ::fstat( fd, &file_stat );
107 #else
108  struct stat64 file_stat;
109 
110  const auto fstat_rc = fstat64( fd, &file_stat );
111 #endif
112 
113  if( 0 != fstat_rc )
114  {
115  throw exception_t{
116  fmt::format(
117  RESTINIO_FMT_FORMAT_STRING( "unable to get file stat : {}" ),
118  strerror( errno ) )
119  };
120  }
121 
124 #if defined( RESTINIO_MACOS_TARGET )
127 #else
130 #endif
131  };
132 
133  return META{ static_cast< file_size_t >( file_stat.st_size ), last_modified };
134 }
135 
136 //! Close file by its descriptor.
137 inline void
138 close_file( file_descriptor_t fd )
139 {
140  ::close( fd );
141 }
142 ///@}
143 
144 } /* namespace restinio */
constexpr file_descriptor_t null_file_descriptor()
Get file descriptor which stands for null.
std::enable_if< std::is_same< Parameter_Container, query_string_params_t >::value||std::is_same< Parameter_Container, router::route_params_t >::value, std::optional< Value_Type > >::type opt_value(const Parameter_Container &params, string_view_t key)
Gets the value of a parameter specified by key wrapped in std::optional<Value_Type> if parameter exis...
Definition: value_or.hpp:64
file_descriptor_t open_file(const std::filesystem::path &file_path)
Helper function that accepts std::filesystem::path.
void close_file(file_descriptor_t fd)
Close file by its descriptor.
META get_file_meta(file_descriptor_t fd)
Get file size.
file_descriptor_t open_file(const char *file_path)
Open file.