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
24 namespace Poco {
25
26
FileStreamBuf()27 FileStreamBuf::FileStreamBuf():
28 BufferedBidirectionalStreamBuf(BUFFER_SIZE, std::ios::in | std::ios::out),
29 _fd(-1),
30 _pos(0)
31 {
32 }
33
34
~FileStreamBuf()35 FileStreamBuf::~FileStreamBuf()
36 {
37 close();
38 }
39
40
open(const std::string & path,std::ios::openmode mode)41 void 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
readFromDevice(char * buffer,std::streamsize length)73 int 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
writeToDevice(const char * buffer,std::streamsize length)88 int 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
close()104 bool 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
seekoff(std::streamoff off,std::ios::seekdir dir,std::ios::openmode mode)124 std::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
seekpos(std::streampos pos,std::ios::openmode mode)155 std::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