ich habe hier (in einer Embedded-Umgebung, die sich teilweise f�r ein
Unix h�lt) einen Filesystem-Stack implementiert. Meine Implementation
von 'write' liefert, wenn der Datentr�ger voll ist, 0. das entspricht
z.B. der Beschreibung in dieser Manpage:
<http://www.freebsd.org/cgi/man.cgi?query=write&apropos=0&sektion=2&manpath=SuSE+Linux%2Fi386+11.0&format=html>
"On success, the number of bytes written is returned (zero indicates
nothing was written)."
Nun haben wir festgestellt, dass die verwendete Implementation von stdio
(nur im Objektcode verf�gbar) 'fwrite' offenbar so implementiert:
int nbytes = size*count;
while (nbytes > 0) {
int written = write(fd, buffer, nbytes);
if (written < 0) return -1;
buffer += written, nbytes -= written;
}
Hei�t: sie geht bei vollem Datentr�ger in eine Endlosschleife.
Nun die Frage: wer hat recht? Beziehungsweise: was ist so �blich? Muss
mein 'write' in diesem Fall z.B. ENOSPC zur�ckgeben, oder darf ich obige
stdio dem Hersteller um die Ohren hauen?
Stefan
Pragmatisch gesehen waere es wohl einfacher, einen Fehler
zurueckzugeben anstatt darauf zu bauen, dass man jemand anderen davon
ueberzeugen kann, dass in seinem Code einer vorhanden sei. Zumal
dieses Verhalten ja durchaus von anderen Kunden benoetigt werden
koennte.
Das ist mir klar, und vermutlich werde ich da auch was umbauen. Dennoch
interessiert mich weiterhin, was andere Systeme an der Stelle tun. SUSv2
schreibt z.B. sogar vor, dass ein SIGXFSZ zu generieren sei, was ich
jetzt noch nirgends gesehen habe und f�r meine Implementation v�llig
ausscheidet (Signale hamwanich).
Stefan
> ich habe hier (in einer Embedded-Umgebung, die sich teilweise für ein
> Unix hält) einen Filesystem-Stack implementiert. Meine Implementation
> von 'write' liefert, wenn der Datenträger voll ist, 0. das entspricht
> z.B. der Beschreibung in dieser Manpage:
> <http://www.freebsd.org/cgi/man.cgi?
query=write&apropos=0&sektion=2&manpath=SuSE+Linux%2Fi386
+11.0&format=html>
> "On success, the number of bytes written is returned (zero indicates
> nothing was written)."
Einen Schreibversuch auf eine volle Platte würde ich nie als erfolgreich
ansehen, d.H. ich erwarte mir hier von einen write den Rückgabewert -1.
> Nun haben wir festgestellt, dass die verwendete Implementation von stdio
> (nur im Objektcode verfügbar) 'fwrite' offenbar so implementiert:
> int nbytes = size*count;
> while (nbytes > 0) {
> int written = write(fd, buffer, nbytes); if (written < 0)
> return -1;
> buffer += written, nbytes -= written;
> }
> Heißt: sie geht bei vollem Datenträger in eine Endlosschleife.
>
> Nun die Frage: wer hat recht? Beziehungsweise: was ist so üblich? Muss
> mein 'write' in diesem Fall z.B. ENOSPC zurückgeben, oder darf ich obige
> stdio dem Hersteller um die Ohren hauen?
Ich hätte erwartet, dass write ENOSPC zurückgibt.
Für eine reguläre Datei erwarte ich nur dann den Rückgabewert 0, wenn
write mit 0 aufgerufen wurde, wobei ich aus der Manpage herauslese,
daß auch wenn 0 byte geschrieben werden sollen und das Dateisystem voll
ist, ein Fehler zurückgeliefert werden könnte.
If count is zero and fd refers to a regular file, then write() may
return a failure status if one of the errors below is detected. If no
errors are detected, 0 will be returned without causing any other
effect. If count is zero and fd refers to a file other than a regular
file, the results are not specified.
Grüße
Erich
--
EFEU 3.2 is released!
Get the open source from http://efeu.cybertec.at.
> Dennoch interessiert mich weiterhin, was andere Systeme an der
> Stelle tun.
write() = -1, errno = ENOSPC.
BSD, mindestens seit UNIX V7 so.
--
Christian "naddy" Weisgerber na...@mips.inka.de
Das kann man sicher so oder so sehen, immerhin liefert 'read' ja
ebenfalls 0 und keinen Fehler, wenn man am Dateiende zu lesen versucht,
und es hat ja auch keine Komponente fehlfunktioniert wie das bei EIO
(kaputte Hardware) oder EINVAL (kaputte Software) der Fall wäre.
Vermutlich war das mein Analogieschluss, als ich das ursprünglich
implementiert habe.
> Ich hätte erwartet, dass write ENOSPC zurückgibt.
Das mache ich nun...
Stefan
Es ist Bestandteil der normalen Funktion von 'read', dass irgendwann
mal ein Dateiende erreicht wurde, aber nicht Bestandteil der normalen
Funktion von 'write', dass die Ausgabeoperation fehlschlug, weil die
Daten nicht mehr auf dem Ausgabemedium untergebracht werden konnten.
Das wird von der betreffenden Norm auch so verlangt:
If a write() requests that more bytes be written than there is
room for (for example, [XSI] [Option Start] the file size
limit of the process or [Option End] 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).
Die einzige relevante Ausnahme fuer 'regular files' ist (meines
Wissens nach):
[XSI] [Option Start] 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. [Option End]
http://www.opengroup.org/onlinepubs/9699919799/functions/write.html
> Nun die Frage: wer hat recht? Beziehungsweise: was ist so �blich?
Beides, 0 und -1 mit errno == ENOSPC. POSIX l��t es unspezifiziert.
Wenigstens der aktuelle UNIX(*)-Standard tut das nicht. Ich hatte den
entsprechenden Passus auch zitiert. Ich tue das allerdings gerne nochmal:
If a write() requests that more bytes be written than there is room
for (for example, [XSI] [Option Start] the file size limit of the
process or [Option End] 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).
Auf Deutsch heisst das:
Wenn ein write-Aufruf verlangt, dass mehr Bytes geschrieben
werden sollen, als Platz dafuer ist (zum Beispiel wegen einer
fuer den Prozess wirksamen Dateigroessenbeschraenkung oder
weil auf einem Speichermedium nicht mehr genuegend Freiraum
zur Verfuegung steht), dann sollen nur soviele Bytes
geschrieben werden, wie momentan geschrieben werden
koennen. Zum Beispiel, angenommen es koennten zwanzig weitere
Bytes geschrieben werden bevor eine solche Grenze erreicht
waere, dann wuerde ein write-Aufruf, der 512 Bytes haette
schreiben sollen, zwanzig zurueckgeben[*]. Ein folgender
write-Aufruf, dessen nbyte-Parameter nicht den Wert Null
haette, gaebe dann eine Fehlerbenachrichtigung zurueck (ausser
insofern im Folgenden anders aufgefuehrt).
[*] und natuerlich auch 20 Byte schreiben
Das einzige, was ich 'im Folgenden' ueber regulaere Dateien finden
konnte, ist
[XSI] [Option Start] 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. [Option End]
Wenn der Aufruf bewirken wuerde, dass eine Datei andernfalls
groesser als die fuer den Prozess wirksame 'weiche'
Dateigroessenbeschraenkung erlaubt werden wuerde und wenn
deswegen nicht einmal ein Byte tatsaechlich geschrieben werden
koennte, dann soll der Aufruf fehlschlagen und die
Implementierung soll dem aufrufenden thread ein SIGXFSZ-Signal
schicken.
Diese Uebersetzung ist sicher mehr als holprig, ich behaupte
allerdings, dass sie inhaltlich korrekt ist. Der Konjunktiv ist ein
sogenannter 'potentialis', dh ein 'Moeglichkeitsfall', kein
'Irrealis', also eine Spekulation ueber etwas, dass noch nicht
stattgefunden hat und von dem bekannt ist, dass es auch nicht
stattfinden wird. Jemand mit ausreichendem Geschick im kreativen
Interpretieren, kann aus diesem Text zweifelsohne auch das
Grundgesatz, den Hoechstwasserstand bei der Flutkatastrophe im Jahre
1634 und die Existenz der Einkommenssteuer ableiten, aber das kann man
immer.
Ueberhaupt hat sich meines Wissen nach noch nie jemand bloss deswegen
von einer Ansicht getrennt, weil diese nachweislich falsch war :->.
Diesen Abschnitt hatte ich auch schon vorher nachgelesen und Florian
sicher auch. "Null" ist erstmal eine g锟絣tige L锟絪ung des Problems "only
as many bytes as there is room". Der Nachsatz dagegen...
> 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).
...klingt jetzt zumindest nicht besonders normativ ("for example..."),
und eine direkte Forderung nach einem ENOSPC steht in all dem Prosatext
nicht.
> Ueberhaupt hat sich meines Wissen nach noch nie jemand bloss deswegen
> von einer Ansicht getrennt, weil diese nachweislich falsch war :->.
Meine Ansicht zum Thema ist schlicht, dass Code, der ein Problem damit
hat, wenn von write() 0 zur锟絚kkommt, deutlich suboptimal ist. Stichwort
Robustness-Prinzip.
Stefan
Die steht dort, wo man sie auch vermuten wuerde, naemlich bei den
Fehlercodes. Im uebrigen gibt es wenig, was ein intendiertes
Verhalten deutlicher zum Ausdruck bringen kann, als ein Beispiel, dass
es beschreibt. Und das, was da beschrieben wurde, beinhaltet 'wenn
write nichts schreiben konnte, ist das ein Fehlerzustand'.
>> Ueberhaupt hat sich meines Wissen nach noch nie jemand bloss deswegen
>> von einer Ansicht getrennt, weil diese nachweislich falsch war :->.
>
> Meine Ansicht zum Thema ist schlicht, dass Code, der ein Problem damit
> hat, wenn von write() 0 zur锟絚kkommt, deutlich suboptimal ist. Stichwort
> Robustness-Prinzip.
Angesichts der Tatsache, dass Leute nachweislich ihnen
nicht genehme Inhalt von Normtexten auch einfach ignorieren, wenn sich
trotz besten Willens keine geeignete Verdrehung einstellen will,
wuerde ich dem zustimmen. Wie ich bereits geschrieben hatte: Jemand,
der hunderte von Geisterfahrern auf einer Autobahn erlebt, wird diese
bestenfalls fuer verblendet halten. Sonst gaebe es naemlich keine.