AquilaOS documentation
How it works, and its code
Toggle main menu visibility
Loading...
Searching...
No Matches
write.c
Go to the documentation of this file.
1
5
6
#include <
core/system.h
>
7
8
#include <
fs/vfs.h
>
9
#include <
fs/iobuf.h
>
10
11
#include <aquila/fcntl.h>
12
#include <aquila/errno.h>
13
25
ssize_t
posix_file_write
(
struct
file
*
file
,
struct
iobuf
*io)
26
{
27
if
(!(
file
->
flags
& (O_WRONLY | O_RDWR)))
/* not open for writing */
28
return
-EBADF;
29
30
/* appending: each write goes at the end, wherever the offset was
31
* (POSIX: as if by an lseek() to the end, then the write) */
32
if
((
file
->
flags
& O_APPEND) && S_ISREG(
file
->vnode->mode))
33
file
->
offset
=
file
->vnode->size;
34
35
if
(
file
->
flags
& O_NONBLOCK) {
36
if
(
vfs_file_can_write
(
file
, io->
resid
)) {
37
ssize_t
retval =
vfs_write_io
(
file
->vnode,
file
->
offset
, io);
38
39
if
(retval < 0)
40
return
retval;
41
42
file
->
offset
+= retval;
43
44
/* there's data now: wake up the readers waiting for some */
45
if
(
file
->vnode->read_queue)
46
waitq_wakeup
(
file
->vnode->read_queue);
47
48
return
retval;
49
}
else
{
50
/* the write would have to wait */
51
return
-EAGAIN;
52
}
53
}
else
{
54
size_t
size = io->
resid
;
55
56
while
(io->
resid
) {
57
ssize_t
r =
vfs_write_io
(
file
->vnode,
file
->
offset
+ (size - io->
resid
), io);
58
59
if
(r < 0) {
60
/* report the error only if nothing was written */
61
if
(io->
resid
== size)
62
return
r;
63
break
;
64
}
65
66
/* done: everything is written, the user buffer faulted, or the
67
* end of the file was reached */
68
if
(!io->
resid
|| io->
fault
||
vfs_file_eof
(
file
))
69
break
;
70
71
/* readers may be asleep waiting for what was just written
72
* (a pipe's ring holds less than one stdio buffer) */
73
if
(
file
->vnode->read_queue)
74
waitq_wakeup
(
file
->vnode->read_queue);
75
76
/* nothing would wake a waiting writer up: no more fits */
77
if
(!
file
->vnode->write_queue)
78
break
;
79
80
/* wait for room; a signal ends the call, which returns what
81
* was written so far, or the error if nothing was */
82
int
err =
waitq_sleep
(
file
->vnode->write_queue);
83
84
if
(err) {
85
if
(io->
resid
== size)
86
return
err;
87
break
;
88
}
89
}
90
91
ssize_t
retval = size - io->
resid
;
92
93
file
->
offset
+= retval;
94
95
/* there's data now: wake up the readers waiting for some */
96
if
(
file
->vnode->read_queue)
97
waitq_wakeup
(
file
->vnode->read_queue);
98
99
return
retval;
100
}
101
}
vfs_file_eof
int vfs_file_eof(struct file *file)
Says whether an open file is at its end, so that a read returns 0 rather than waiting.
Definition
fops.c:325
vfs_file_can_write
int vfs_file_can_write(struct file *file, size_t size)
Says whether a write to an open file would go on without waiting, for poll(), select() and non-blocki...
Definition
fops.c:295
system.h
iobuf.h
posix_file_write
ssize_t posix_file_write(struct file *file, struct iobuf *io)
Writes to an open file at its offset, and moves the offset past what was written.
Definition
write.c:25
file
An open file (POSIX's "open file description", fs/file.c).
Definition
vfs.h:157
file::offset
off_t offset
Definition
vfs.h:163
file::flags
int flags
Definition
vfs.h:164
iobuf
An iobuf.
Definition
iobuf.h:35
iobuf::fault
int fault
Definition
iobuf.h:40
iobuf::resid
size_t resid
Definition
iobuf.h:38
ssize_t
long int ssize_t
Definition
types.h:12
vfs.h
waitq_wakeup
void waitq_wakeup(struct waitq *waitq)
Wakes up every thread sleeping on a wait queue, and every thread polling it.
Definition
waitq.c:178
waitq_sleep
int waitq_sleep(struct waitq *waitq)
Puts the current thread to sleep on a wait queue until it is woken up.
Definition
waitq.c:50
vfs_write_io
ssize_t vfs_write_io(struct vnode *vnode, off_t off, struct iobuf *io)
Writes to a vnode from an iobuf (user or kernel memory).
Definition
write.c:22
kernel
fs
posix
write.c
Generated by
1.18.0