1
1
/*
2
- * Copyright (c) 2018-2020 , Andreas Kling <kling@serenityos.org>
2
+ * Copyright (c) 2018-2022 , Andreas Kling <kling@serenityos.org>
3
3
* Copyright (c) 2021, sin-ack <sin-ack@protonmail.com>
4
4
*
5
5
* SPDX-License-Identifier: BSD-2-Clause
6
6
*/
7
7
8
8
#include < AK/MemoryStream.h>
9
9
#include < Kernel/API/POSIX/errno.h>
10
- #include < Kernel/Debug.h>
11
10
#include < Kernel/Devices/BlockDevice.h>
12
11
#include < Kernel/FileSystem/Custody.h>
13
12
#include < Kernel/FileSystem/FIFO.h>
14
- #include < Kernel/FileSystem/FileSystem.h>
15
13
#include < Kernel/FileSystem/InodeFile.h>
16
14
#include < Kernel/FileSystem/InodeWatcher.h>
17
15
#include < Kernel/FileSystem/OpenFileDescription.h>
@@ -47,14 +45,15 @@ OpenFileDescription::OpenFileDescription(File& file)
47
45
if (file.is_inode ())
48
46
m_inode = static_cast <InodeFile&>(file).inode ();
49
47
50
- m_is_directory = metadata ().is_directory ();
48
+ auto metadata = this ->metadata ();
49
+ m_state.with ([&](auto & state) { state.is_directory = metadata.is_directory (); });
51
50
}
52
51
53
52
OpenFileDescription::~OpenFileDescription ()
54
53
{
55
54
m_file->detach (*this );
56
55
if (is_fifo ())
57
- static_cast <FIFO*>(m_file.ptr ())->detach (m_fifo_direction );
56
+ static_cast <FIFO*>(m_file.ptr ())->detach (fifo_direction () );
58
57
// FIXME: Should this error path be observed somehow?
59
58
(void )m_file->close ();
60
59
if (m_inode)
@@ -99,7 +98,6 @@ Thread::FileBlocker::BlockFlags OpenFileDescription::should_unblock(Thread::File
99
98
100
99
ErrorOr<struct stat > OpenFileDescription::stat ()
101
100
{
102
- MutexLocker locker (m_lock);
103
101
// FIXME: This is due to the Device class not overriding File::stat().
104
102
if (m_inode)
105
103
return m_inode->metadata ().stat ();
@@ -108,43 +106,45 @@ ErrorOr<struct stat> OpenFileDescription::stat()
108
106
109
107
ErrorOr<off_t > OpenFileDescription::seek (off_t offset, int whence)
110
108
{
111
- MutexLocker locker (m_lock);
112
109
if (!m_file->is_seekable ())
113
110
return ESPIPE;
114
111
115
- off_t new_offset ;
112
+ auto metadata = this -> metadata () ;
116
113
117
- switch (whence) {
118
- case SEEK_SET:
119
- new_offset = offset;
120
- break ;
121
- case SEEK_CUR:
122
- if (Checked<off_t >::addition_would_overflow (m_current_offset, offset))
123
- return EOVERFLOW;
124
- new_offset = m_current_offset + offset;
125
- break ;
126
- case SEEK_END:
127
- if (!metadata ().is_valid ())
128
- return EIO;
129
- if (Checked<off_t >::addition_would_overflow (metadata ().size , offset))
130
- return EOVERFLOW;
131
- new_offset = metadata ().size + offset;
132
- break ;
133
- default :
134
- return EINVAL;
135
- }
114
+ auto new_offset = TRY (m_state.with ([&](auto & state) -> ErrorOr<off_t > {
115
+ off_t new_offset;
116
+ switch (whence) {
117
+ case SEEK_SET:
118
+ new_offset = offset;
119
+ break ;
120
+ case SEEK_CUR:
121
+ if (Checked<off_t >::addition_would_overflow (state.current_offset , offset))
122
+ return EOVERFLOW;
123
+ new_offset = state.current_offset + offset;
124
+ break ;
125
+ case SEEK_END:
126
+ if (!metadata.is_valid ())
127
+ return EIO;
128
+ if (Checked<off_t >::addition_would_overflow (metadata.size , offset))
129
+ return EOVERFLOW;
130
+ new_offset = metadata.size + offset;
131
+ break ;
132
+ default :
133
+ return EINVAL;
134
+ }
135
+ if (new_offset < 0 )
136
+ return EINVAL;
137
+ state.current_offset = new_offset;
138
+ return new_offset;
139
+ }));
136
140
137
- if (new_offset < 0 )
138
- return EINVAL;
139
141
// FIXME: Return EINVAL if attempting to seek past the end of a seekable device.
140
142
141
- m_current_offset = new_offset;
142
-
143
143
m_file->did_seek (*this , new_offset);
144
144
if (m_inode)
145
145
m_inode->did_seek (*this , new_offset);
146
146
evaluate_block_conditions ();
147
- return m_current_offset ;
147
+ return new_offset ;
148
148
}
149
149
150
150
ErrorOr<size_t > OpenFileDescription::read (UserOrKernelBuffer& buffer, u64 offset, size_t count)
@@ -163,24 +163,30 @@ ErrorOr<size_t> OpenFileDescription::write(u64 offset, UserOrKernelBuffer const&
163
163
164
164
ErrorOr<size_t > OpenFileDescription::read (UserOrKernelBuffer& buffer, size_t count)
165
165
{
166
- MutexLocker locker (m_lock);
167
- if (Checked<off_t >::addition_would_overflow (m_current_offset, count))
168
- return EOVERFLOW;
169
- auto nread = TRY (m_file->read (*this , offset (), buffer, count));
166
+ auto offset = TRY (m_state.with ([&](auto & state) -> ErrorOr<off_t > {
167
+ if (Checked<off_t >::addition_would_overflow (state.current_offset , count))
168
+ return EOVERFLOW;
169
+ return state.current_offset ;
170
+ }));
171
+ auto nread = TRY (m_file->read (*this , offset, buffer, count));
170
172
if (m_file->is_seekable ())
171
- m_current_offset += nread;
173
+ m_state. with ([&]( auto & state) { state. current_offset = offset + nread; }) ;
172
174
evaluate_block_conditions ();
173
175
return nread;
174
176
}
175
177
176
178
ErrorOr<size_t > OpenFileDescription::write (const UserOrKernelBuffer& data, size_t size)
177
179
{
178
- MutexLocker locker (m_lock);
179
- if (Checked<off_t >::addition_would_overflow (m_current_offset, size))
180
- return EOVERFLOW;
181
- auto nwritten = TRY (m_file->write (*this , offset (), data, size));
180
+ auto offset = TRY (m_state.with ([&](auto & state) -> ErrorOr<off_t > {
181
+ if (Checked<off_t >::addition_would_overflow (state.current_offset , size))
182
+ return EOVERFLOW;
183
+ return state.current_offset ;
184
+ }));
185
+ auto nwritten = TRY (m_file->write (*this , offset, data, size));
186
+
182
187
if (m_file->is_seekable ())
183
- m_current_offset += nwritten;
188
+ m_state.with ([&](auto & state) { state.current_offset = offset + nwritten; });
189
+
184
190
evaluate_block_conditions ();
185
191
return nwritten;
186
192
}
@@ -205,7 +211,6 @@ ErrorOr<NonnullOwnPtr<KBuffer>> OpenFileDescription::read_entire_file()
205
211
206
212
ErrorOr<size_t > OpenFileDescription::get_dir_entries (UserOrKernelBuffer& output_buffer, size_t size)
207
213
{
208
- MutexLocker locker (m_lock, Mutex::Mode::Shared);
209
214
if (!is_directory ())
210
215
return ENOTDIR;
211
216
@@ -371,19 +376,16 @@ InodeMetadata OpenFileDescription::metadata() const
371
376
372
377
ErrorOr<Memory::Region*> OpenFileDescription::mmap (Process& process, Memory::VirtualRange const & range, u64 offset, int prot, bool shared)
373
378
{
374
- MutexLocker locker (m_lock);
375
379
return m_file->mmap (process, *this , range, offset, prot, shared);
376
380
}
377
381
378
382
ErrorOr<void > OpenFileDescription::truncate (u64 length)
379
383
{
380
- MutexLocker locker (m_lock);
381
384
return m_file->truncate (length);
382
385
}
383
386
384
387
ErrorOr<void > OpenFileDescription::sync ()
385
388
{
386
- MutexLocker locker (m_lock);
387
389
return m_file->sync ();
388
390
}
389
391
@@ -420,22 +422,21 @@ const Socket* OpenFileDescription::socket() const
420
422
421
423
void OpenFileDescription::set_file_flags (u32 flags)
422
424
{
423
- MutexLocker locker (m_lock);
424
- m_is_blocking = !(flags & O_NONBLOCK);
425
- m_should_append = flags & O_APPEND;
426
- m_direct = flags & O_DIRECT;
427
- m_file_flags = flags;
425
+ m_state.with ([&](auto & state) {
426
+ state.is_blocking = !(flags & O_NONBLOCK);
427
+ state.should_append = flags & O_APPEND;
428
+ state.direct = flags & O_DIRECT;
429
+ state.file_flags = flags;
430
+ });
428
431
}
429
432
430
433
ErrorOr<void > OpenFileDescription::chmod (mode_t mode)
431
434
{
432
- MutexLocker locker (m_lock);
433
435
return m_file->chmod (*this , mode);
434
436
}
435
437
436
438
ErrorOr<void > OpenFileDescription::chown (UserID uid, GroupID gid)
437
439
{
438
- MutexLocker locker (m_lock);
439
440
return m_file->chown (*this , uid, gid);
440
441
}
441
442
@@ -459,4 +460,82 @@ ErrorOr<void> OpenFileDescription::get_flock(Userspace<flock*> lock) const
459
460
460
461
return m_inode->get_flock (*this , lock);
461
462
}
463
+ bool OpenFileDescription::is_readable () const
464
+ {
465
+ return m_state.with ([](auto & state) { return state.readable ; });
466
+ }
467
+
468
+ bool OpenFileDescription::is_writable () const
469
+ {
470
+ return m_state.with ([](auto & state) { return state.writable ; });
471
+ }
472
+
473
+ void OpenFileDescription::set_readable (bool b)
474
+ {
475
+ m_state.with ([&](auto & state) { state.readable = b; });
476
+ }
477
+
478
+ void OpenFileDescription::set_writable (bool b)
479
+ {
480
+ m_state.with ([&](auto & state) { state.writable = b; });
481
+ }
482
+
483
+ void OpenFileDescription::set_rw_mode (int options)
484
+ {
485
+ m_state.with ([&](auto & state) {
486
+ state.readable = (options & O_RDONLY) == O_RDONLY;
487
+ state.writable = (options & O_WRONLY) == O_WRONLY;
488
+ });
489
+ }
490
+
491
+ bool OpenFileDescription::is_direct () const
492
+ {
493
+ return m_state.with ([](auto & state) { return state.direct ; });
494
+ }
495
+
496
+ bool OpenFileDescription::is_directory () const
497
+ {
498
+ return m_state.with ([](auto & state) { return state.is_directory ; });
499
+ }
500
+
501
+ bool OpenFileDescription::is_blocking () const
502
+ {
503
+ return m_state.with ([](auto & state) { return state.is_blocking ; });
504
+ }
505
+
506
+ void OpenFileDescription::set_blocking (bool b)
507
+ {
508
+ m_state.with ([&](auto & state) { state.is_blocking = b; });
509
+ }
510
+
511
+ bool OpenFileDescription::should_append () const
512
+ {
513
+ return m_state.with ([](auto & state) { return state.should_append ; });
514
+ }
515
+
516
+ u32 OpenFileDescription::file_flags () const
517
+ {
518
+ return m_state.with ([](auto & state) { return state.file_flags ; });
519
+ }
520
+
521
+ FIFO::Direction OpenFileDescription::fifo_direction () const
522
+ {
523
+ return m_state.with ([](auto & state) { return state.fifo_direction ; });
524
+ }
525
+
526
+ void OpenFileDescription::set_fifo_direction (Badge<FIFO>, FIFO::Direction direction)
527
+ {
528
+ m_state.with ([&](auto & state) { state.fifo_direction = direction; });
529
+ }
530
+
531
+ OwnPtr<OpenFileDescriptionData>& OpenFileDescription::data ()
532
+ {
533
+ return m_state.with ([](auto & state) -> OwnPtr<OpenFileDescriptionData>& { return state.data ; });
534
+ }
535
+
536
+ off_t OpenFileDescription::offset () const
537
+ {
538
+ return m_state.with ([](auto & state) { return state.current_offset ; });
539
+ }
540
+
462
541
}
0 commit comments