Implement controls for file descriptor inheritance
[libs/core.git] / source / io / file.cpp
1 #include "file.h"
2 #include "handle_private.h"
3
4 using namespace std;
5
6 namespace Msp {
7 namespace IO {
8
9 File::File(const string &fn, Mode m, CreateMode cm)
10 {
11         if(!(m&M_RDWR))
12                 throw invalid_argument("File::File mode");
13         if(cm&~(C_CREATE|C_TRUNCATE|C_EXCLUSIVE))
14                 throw invalid_argument("File::File create");
15         if((cm&C_EXCLUSIVE) && (!(cm&C_CREATE) || (cm&C_TRUNCATE)))
16                 throw invalid_argument("File::File create");
17
18         mode = m;
19
20         platform_init(fn, cm);
21 }
22
23 File::~File()
24 {
25         signal_flush_required.emit();
26         sys_close(handle);
27 }
28
29 void File::set_block(bool b)
30 {
31         adjust_mode(mode, M_NONBLOCK, !b);
32         sys_set_blocking(handle, b);
33 }
34
35 void File::set_inherit(bool i)
36 {
37         adjust_mode(mode, M_INHERIT, i);
38         sys_set_inherit(handle, i);
39 }
40
41 unsigned File::do_write(const char *buf, unsigned size)
42 {
43         check_access(M_WRITE);
44
45         if(size==0)
46                 return 0;
47
48 #ifdef _WIN32
49         if(mode&M_APPEND)
50                 seek(0, S_END);
51 #endif
52
53         return sys_write(handle, buf, size);
54 }
55
56 unsigned File::do_read(char *buf, unsigned size)
57 {
58         check_access(M_READ);
59
60         if(size==0)
61                 return 0;
62
63         unsigned ret = sys_read(handle, buf, size);
64         if(ret==0)
65                 set_eof();
66
67         return ret;
68 }
69
70 SeekOffset File::seek(SeekOffset off, SeekType type)
71 {
72         signal_flush_required.emit();
73         off = sys_seek(handle, off, type);
74         eof_flag = false;
75
76         return off;
77 }
78
79 SeekOffset File::tell() const
80 {
81         return sys_seek(const_cast<Handle &>(handle), 0, S_CUR);
82 }
83
84 const Handle &File::get_handle(Mode m)
85 {
86         check_access(m);
87         return handle;
88 }
89
90
91 BufferedFile::BufferedFile(const string &fn, Mode m, File::CreateMode cm):
92         file(fn, m, cm),
93         buffer(file),
94         position(0)
95 {
96         mode = m;
97         file.signal_end_of_file.connect(sigc::mem_fun(this, &BufferedFile::set_eof));
98 }
99
100 void BufferedFile::set_block(bool b)
101 {
102         file.set_block(b);
103 }
104
105 void BufferedFile::set_inherit(bool)
106 {
107         throw logic_error("BufferedFile::set_inherit");
108 }
109
110 unsigned BufferedFile::do_write(const char *buf, unsigned size)
111 {
112         unsigned ret = buffer.write(buf, size);
113         position += ret;
114         return ret;
115 }
116
117 unsigned BufferedFile::do_read(char *buf, unsigned size)
118 {
119         unsigned ret = buffer.read(buf, size);
120         position += ret;
121         return ret;
122 }
123
124 unsigned BufferedFile::put(char c)
125 {
126         unsigned ret = buffer.put(c);
127         position += ret;
128         return ret;
129 }
130
131 bool BufferedFile::getline(string &line)
132 {
133         bool ret = buffer.getline(line);
134         if(ret)
135                 position += line.size();
136         return ret;
137 }
138
139 int BufferedFile::get()
140 {
141         int ret = buffer.get();
142         if(ret>=0)
143                 ++position;
144         return ret;
145 }
146
147 const Handle &BufferedFile::get_handle(Mode)
148 {
149         throw logic_error("BufferedFile::get_handle");
150 }
151
152 SeekOffset BufferedFile::seek(SeekOffset offset, SeekType type)
153 {
154         if(type==S_CUR)
155         {
156                 offset += position;
157                 type = S_BEG;
158         }
159
160         signal_flush_required.emit();
161         position = file.seek(offset, type);
162         eof_flag = false;
163         return position;
164 }
165
166 } // namespace IO
167 } // namespace Msp