RESTinio
Loading...
Searching...
No Matches
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
19namespace 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///@{
31using file_descriptor_t = int;
33using 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]]
46constexpr file_descriptor_t null_file_descriptor(){ return -1; }
47
48//! Open file.
49[[nodiscard]]
51open_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]]
85open_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.
93template < typename META >
94[[nodiscard]]
95META
96get_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
122 const std::chrono::system_clock::time_point
123 last_modified{
124#if defined( RESTINIO_MACOS_TARGET )
125 std::chrono::seconds( file_stat.st_mtimespec.tv_sec ) +
126 std::chrono::microseconds( file_stat.st_mtimespec.tv_nsec / 1000 )
127#else
128 std::chrono::seconds( file_stat.st_mtim.tv_sec ) +
129 std::chrono::microseconds( file_stat.st_mtim.tv_nsec / 1000 )
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.
137inline void
138close_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.
file_descriptor_t open_file(const char *file_path)
Open file.
std::FILE * file_descriptor_t
file_descriptor_t open_file(const std::filesystem::path &file_path)
Helper function that accepts std::filesystem::path.