1//
2// FileStream_POSIX.cpp
3//
4// Library: Foundation
5// Package: Streams
6// Module: FileStream
7//
8// Copyright (c) 2007, Applied Informatics Software Engineering GmbH.
9// and Contributors.
10//
11// SPDX-License-Identifier: BSL-1.0
12//
13
14
15#include "Poco/FileStream.h"
16#include "Poco/File.h"
17#include "Poco/Exception.h"
18#include <sys/types.h>
19#include <sys/stat.h>
20#include <fcntl.h>
21#include <unistd.h>
22
23
24namespace Poco {
25
26
27FileStreamBuf::FileStreamBuf():
28 BufferedBidirectionalStreamBuf(BUFFER_SIZE, std::ios::in | std::ios::out),
29 _fd(-1),
30 _pos(0)
31{
32}
33
34
35FileStreamBuf::~FileStreamBuf()
36{
37 close();
38}
39
40
41void FileStreamBuf::open(const std::string& path, std::ios::openmode mode)
42{
43 poco_assert (_fd == -1);
44
45 _pos = 0;
46 _path = path;
47 setMode(mode);
48 resetBuffers();
49
50 int flags(0);
51 if (mode & std::ios::trunc)
52 flags |= O_TRUNC;
53 if (mode & std::ios::app)
54 flags |= O_APPEND;
55 if (mode & std::ios::out)
56 flags |= O_CREAT;
57 if ((mode & std::ios::in) && (mode & std::ios::out))
58 flags |= O_RDWR;
59 else if (mode & std::ios::in)
60 flags |= O_RDONLY;
61 else
62 flags |= O_WRONLY;
63
64 _fd = ::open(path.c_str(), flags, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
65 if (_fd == -1)
66 File::handleLastError(_path);
67
68 if ((mode & std::ios::app) || (mode & std::ios::ate))
69 seekoff(0, std::ios::end, mode);
70}
71
72
73int FileStreamBuf::readFromDevice(char* buffer, std::streamsize length)
74{
75 if (_fd == -1) return -1;
76
77 if (getMode() & std::ios::out)
78 sync();
79
80 int n = read(_fd, buffer, length);
81 if (n == -1)
82 File::handleLastError(_path);
83 _pos += n;
84 return n;
85}
86
87
88int FileStreamBuf::writeToDevice(const char* buffer, std::streamsize length)
89{
90 if (_fd == -1) return -1;
91
92#if defined(POCO_VXWORKS)
93 int n = write(_fd, const_cast<char*>(buffer), length);
94#else
95 int n = write(_fd, buffer, length);
96#endif
97 if (n == -1)
98 File::handleLastError(_path);
99 _pos += n;
100 return n;
101}
102
103
104bool FileStreamBuf::close()
105{
106 bool success = true;
107 if (_fd != -1)
108 {
109 try
110 {
111 sync();
112 }
113 catch (...)
114 {
115 success = false;
116 }
117 ::close(_fd);
118 _fd = -1;
119 }
120 return success;
121}
122
123
124std::streampos FileStreamBuf::seekoff(std::streamoff off, std::ios::seekdir dir, std::ios::openmode mode)
125{
126 if (_fd == -1 || !(getMode() & mode))
127 return -1;
128
129 if (getMode() & std::ios::out)
130 sync();
131
132 std::streamoff adj;
133 if (mode & std::ios::in)
134 adj = static_cast<std::streamoff>(egptr() - gptr());
135 else
136 adj = 0;
137
138 resetBuffers();
139
140 int whence = SEEK_SET;
141 if (dir == std::ios::cur)
142 {
143 whence = SEEK_CUR;
144 off -= adj;
145 }
146 else if (dir == std::ios::end)
147 {
148 whence = SEEK_END;
149 }
150 _pos = lseek(_fd, off, whence);
151 return _pos;
152}
153
154
155std::streampos FileStreamBuf::seekpos(std::streampos pos, std::ios::openmode mode)
156{
157 if (_fd == -1 || !(getMode() & mode))
158 return -1;
159
160 if (getMode() & std::ios::out)
161 sync();
162
163 resetBuffers();
164
165 _pos = lseek(_fd, pos, SEEK_SET);
166 return _pos;
167}
168
169
170} // namespace Poco
171