A write() system call can return successfully and even the following
close() syscall may not return an error, even if there was an error like EFBIG (File too large).
if ((fd = creat(name, 0666)) < 0) {
perror(name);
exit(1);
}
while (have_more_data) {
if (write(fd, buffer, count) < 0) {
perror("write");
exit(1);
}
}
if (close(fd) < 0) {
perror("close");
exit(1);
}
This may complete successfully, e.g. when EFBIG occurs in the last
write() syscall before the loop ends.
So what is the best way to check for errors with write()?
A write() system call can return successfully and even the following
close() syscall may not return an error, even if there was an error
like EFBIG (File too large).
if ((fd = creat(name, 0666)) < 0) {
perror(name);
exit(1);
}
while (have_more_data) {
if (write(fd, buffer, count) < 0) {
perror("write");
exit(1);
}
}
if (close(fd) < 0) {
perror("close");
exit(1);
}
This may complete successfully, e.g. when EFBIG occurs in the last
write() syscall before the loop ends.
So what is the best way to check for errors with write()?
Steve
On Thu, 16 Dec 2021 18:58:28 +0100, Steve Keller wrote:
A write() system call can return successfully and even the followingAccording to the Linux write(2) manpage,
close() syscall may not return an error, even if there was an error like
EFBIG (File too large).
if ((fd = creat(name, 0666)) < 0) {
perror(name);
exit(1);
}
while (have_more_data) {
if (write(fd, buffer, count) < 0) {
perror("write");
exit(1);
}
}
if (close(fd) < 0) {
perror("close");
exit(1);
}
This may complete successfully, e.g. when EFBIG occurs in the last
write() syscall before the loop ends.
So what is the best way to check for errors with write()?
A successful return from write() does not make any guarantee that data
has been committed to disk. In fact, on some buggy implementations, it
does not even guarantee that space has successfully been reserved for
the data. The only way to be sure is to call fsync(2) after you are
done writing all your data.
While this may not be true for other Unix and Unix-like systems, an appropriately-placed sync(2)/fsync(2) call wouldn't hurt.
A write() system call can return successfully and even the following
close() syscall may not return an error, even if there was an error
like EFBIG (File too large).
if ((fd = creat(name, 0666)) < 0) {
perror(name);
exit(1);
}
while (have_more_data) {
if (write(fd, buffer, count) < 0) {
perror("write");
exit(1);
}
}
if (close(fd) < 0) {
perror("close");
exit(1);
}
This may complete successfully, e.g. when EFBIG occurs in the last
write() syscall before the loop ends.
So what is the best way to check for errors with write()?
A write() system call can return successfully and even the following
close() syscall may not return an error, even if there was an error
like EFBIG (File too large).
if ((fd = creat(name, 0666)) < 0) {
perror(name);
exit(1);
}
while (have_more_data) {
if (write(fd, buffer, count) < 0) {
perror("write");
exit(1);
}
}
if (close(fd) < 0) {
perror("close");
exit(1);
}
This may complete successfully, e.g. when EFBIG occurs in the last
write() syscall before the loop ends.
So what is the best way to check for errors with write()?
A write() system call can return successfully and even the following
close() syscall may not return an error, even if there was an error
like EFBIG (File too large).
if ((fd = creat(name, 0666)) < 0) {
perror(name);
exit(1);
}
while (have_more_data) {
if (write(fd, buffer, count) < 0) {
perror("write");
exit(1);
}
}
if (close(fd) < 0) {
perror("close");
exit(1);
}
This may complete successfully, e.g. when EFBIG occurs in the last
write() syscall before the loop ends.
So what is the best way to check for errors with write()?
Uh, actually look at the return value and see if it matches the
number of bytes you asked to write: on partial success, write() will
return less than the requested count. Note that a short write won't
change errno; if you need to know why it was unable to write more
than you need to keep calling write() until it completely fails
(usually the next call) and check errno then.
To quote the (next issue) of the POSIX spec's description of write():
If a write( ) requests that more bytes be written than
there is room for (for example, the file size limit of the
process or the physical end of a medium), only as many
bytes as there is room for shall be written. For example,
suppose there is space for 20 bytes more in a file before
reaching a limit. A write of 512 bytes will return 20. The
next write of a non-zero number of bytes would give a
failure return (except as noted below).
If the request would cause the file size to exceed the soft
file size limit for the process and there is no room for
any bytes to be written, the request shall fail and the
implementation shall generate the SIGXFSZ signal for the
thread.
And then in the ERRORS section:
ERRORS
These functions shall fail if:
...
[EFBIG] An attempt was made to write a file that exceeds the
implementation-defined maximum file size and there was
no room for any bytes to be written.
[EFBIG] An attempt was made to write a file that exceeds the
file size limit of the process, and there was no room
for any bytes to be written. A SIGXFSZ signal shall
also be sent to the thread.
The OpenBSD one is similar. Are you talking about other Unix-like
systems, or are you saying the man page is wrong? Because it seems to
say that in your scenario, the fatal write() will return -1 and set
EFBIG.
Until I'm convinced it's wrong: according to the write(2) man page.
(I'm disregarding the fsync(2) angle, covered by others.)
Jorgen Grahn <grahn+nntp@snipabacken.se> writes:
The OpenBSD one is similar. Are you talking about other Unix-like
systems, or are you saying the man page is wrong? Because it seems to
say that in your scenario, the fatal write() will return -1 and set
EFBIG.
I should have written more clearly, that I was talking about a "short
write". I.e. the write() syscall doesn't return -1 and doesn't set
errno, but it could only write data partially.
I wasn't saying the man page is wrong, only that an error can occur
without write() returning -1 to indicate the error. Repeating the
write() with the rest of the data to get the error, as Philip
suggested, was obviously too simple for me to get that idea :-)
Jorgen Grahn <grahn+nntp@snipabacken.se> writes:
The OpenBSD one is similar. Are you talking about other Unix-like
systems, or are you saying the man page is wrong? Because it seems to
say that in your scenario, the fatal write() will return -1 and set
EFBIG.
I should have written more clearly, that I was talking about a "short
write". I.e. the write() syscall doesn't return -1 and doesn't set
errno, but it could only write data partially.
I wasn't saying the man page is wrong, only that an error can occur
without write() returning -1 to indicate the error. Repeating the
write() with the rest of the data to get the error, as Philip
suggested, was obviously too simple for me to get that idea :-)
Until I'm convinced it's wrong: according to the write(2) man page.
(I'm disregarding the fsync(2) angle, covered by others.)
Yes, f*sync() is not what I was looking for.
Philip Guenther <guen...@gmail.com> writes:
Uh, actually look at the return value and see if it matches the
number of bytes you asked to write: on partial success, write() will return less than the requested count. Note that a short write won't
change errno; if you need to know why it was unable to write more
than you need to keep calling write() until it completely fails
(usually the next call) and check errno then.
To quote the (next issue) of the POSIX spec's description of write():
If a write( ) requests that more bytes be written than
there is room for (for example, the file size limit of the
process or the physical end of a medium), only as many
bytes as there is room for shall be written. For example,
suppose there is space for 20 bytes more in a file before
reaching a limit. A write of 512 bytes will return 20. The
next write of a non-zero number of bytes would give a
failure return (except as noted below).
If the request would cause the file size to exceed the soft
file size limit for the process and there is no room for
any bytes to be written, the request shall fail and the
implementation shall generate the SIGXFSZ signal for the
thread.
And then in the ERRORS section:
ERRORS
These functions shall fail if:
...
[EFBIG] An attempt was made to write a file that exceeds the implementation-defined maximum file size and there was
no room for any bytes to be written.
[EFBIG] An attempt was made to write a file that exceeds theAh, thanks. How to handle a short write, i.e. with no error return
file size limit of the process, and there was no room
for any bytes to be written. A SIGXFSZ signal shall
also be sent to the thread.
code, is exactly what I was looking for. This information is not in
the Linux write(2) man page.
BTW, is it possible that after a short write the next write() syscall
for the remaining data will write some more data, possibly even the
whole remaining data successfully? I think of something like a pipe
or a socket where not the whole data can be sent immediately.
On Thursday, December 16, 2021 at 7:35:16 PM UTC-8, Steve Keller wrote:
Philip Guenther <guen...@gmail.com> writes:=20
=20
Uh, actually look at the return value and see if it matches the=20Ah, thanks. How to handle a short write, i.e. with no error return=20
number of bytes you asked to write: on partial success, write() will=20
return less than the requested count. Note that a short write won't=20
change errno; if you need to know why it was unable to write more=20
than you need to keep calling write() until it completely fails=20
(usually the next call) and check errno then.=20
=20
To quote the (next issue) of the POSIX spec's description of write():= >=20
If a write( ) requests that more bytes be written than=20
there is room for (for example, the file size limit of the=20
process or the physical end of a medium), only as many=20
bytes as there is room for shall be written. For example,=20
suppose there is space for 20 bytes more in a file before=20
reaching a limit. A write of 512 bytes will return 20. The=20
next write of a non-zero number of bytes would give a=20
failure return (except as noted below).=20
=20
If the request would cause the file size to exceed the soft=20
file size limit for the process and there is no room for=20
any bytes to be written, the request shall fail and the=20
implementation shall generate the SIGXFSZ signal for the=20
thread.=20
=20
And then in the ERRORS section:=20
ERRORS=20
These functions shall fail if:=20
...=20
[EFBIG] An attempt was made to write a file that exceeds the=20
implementation-defined maximum file size and there was=20
no room for any bytes to be written.=20
=20
[EFBIG] An attempt was made to write a file that exceeds the=20
file size limit of the process, and there was no room=20
for any bytes to be written. A SIGXFSZ signal shall=20
also be sent to the thread.
code, is exactly what I was looking for. This information is not in=20
the Linux write(2) man page.=20
=20
BTW, is it possible that after a short write the next write() syscall=20
for the remaining data will write some more data, possibly even the=20
whole remaining data successfully? I think of something like a pipe=20
or a socket where not the whole data can be sent immediately.=20
If the condition that prevented writing more data has a change of state bet= >ween the two calls, then sure, more data may be written successfully. For = >example, if some other process or thread freed up disk space between the ca= >lls than an ENOSPC or EDQUOT condition that caused a short-write may go awa= >y, permitting more data to be written.
Could the system decide to do short-writes for no good reason and then perm= >it more later, just because? Given the first sentence of the wording I quo= >ted, I think the answer is "no", but also think I'm uninterested in arguing=
about it and would just call such an implementation "low quality" and not =
use it.
One may also catch the SIGXFSZ signal to ensure one detects file
size resource limit violations (see setrlimit(2), signal(7))
Sysop: | Keyop |
---|---|
Location: | Huddersfield, West Yorkshire, UK |
Users: | 296 |
Nodes: | 16 (2 / 14) |
Uptime: | 78:33:31 |
Calls: | 6,658 |
Calls today: | 4 |
Files: | 12,203 |
Messages: | 5,332,979 |
Posted today: | 1 |