Linux, C und tmpfile(), PHP
Tom
- programmiertechnik
0 Harry0 Thomas W.0 Tom
0 Christian Kruse
Hello,
da es hier auch viele gute C-Programmierer und Linuxer gibt (hoffe ich doch), mal ne Frage zu diesem Thema:
Ich war über einen Thread von nickigraus (oder so ähnlich) gestolpert und da auch was geantwortet, was aber trotz Anzeige "...im Forum lesbar..." im Nirwana verschwunden war (das nur so nebenbei).
Jedenfalls hat mich die Umbenennung der "Temporärdatei" vom Upload sehr gewundert, dass das gehen sollte. Hab ich natürlich gleich recherchiert und auch ausprobiert mangels Treffern. Und was soll ich sagen, man konnte diese "Temporärdatei" umbenennen. Nun habe ich nicht ausprobiert, ob sie mit geändertem Namen trotzdem noch auf dasselbe Handle reagiert... (ist noch nachzuholen).
Aber jedenfalls habe ich dabei festgestellt, dass es sich nicht um eine echte Temporärdatei, sondern um eine persistente Datei handelt, die durch das Runtimesystem bei Scriptende oder -abbruch wieder gelöscht wird.
Auch die Funktion tmpfile() in PHP liefert KEINE echte Temporärdatei, sondern eine persistente.
Ok, rüber zu C und geschaut, was das denn so macht unter Linux. (C ist auf DOS und auf Linux vorhanden, PHP leider nicht)
Na gut, da haben wir dann zu zweit gebastelt, was das Zeug hielt. Aber Linux wollte und wollte keine Datei anzeigen, wenn sie mit tmpfile() in C angelegt wurde. Dabei gabs doch gar keinen Fehler!
Dabei scheint die Datei aber tatsächlich angelegt zu werden und ganz brav am Ende des Programms wieder gelöscht zu werden, so wie sich das gehört. Wer kann mir nun sagen, wo Linux deine temporärdateien anlegt? Nur im Speicher und ggf. im Swapfile?
Und wer von den Windows-PHP-Leuten kann meirt sagen, ob PHP da mit tmpfile() eine echte Temporärdatei auf der Platte anleget oder auch nur eine persistente?
Liebe Grüße aus http://www.braunschweig.de
Tom
Holladiewaldfee,
unabhängig davon, daß ich mit dem Kram nicht wirklich auskenne:
Hast Du schonmal einen Blick in den PHP-Sourcecode geworfen, wie die die temporären Dateien anlegen? Vielleicht erlaubt Dir das ja einige Rückschlüsse auf Dein Problem.
Ciao,
Harry
Hallo,
Dabei scheint die Datei aber tatsächlich angelegt zu werden und ganz brav am Ende des Programms wieder gelöscht zu werden, so wie sich das gehört. Wer kann mir nun sagen, wo Linux deine temporärdateien anlegt? Nur im Speicher und ggf. im Swapfile?
Im Normalfall unter /tmp:
Auszug aus "man tmpfile":
"Die Funktion tmpfile() generiert einen eindeutigen temporären Dateinamen indem sie den Pfad-Prefix P_tmpdir benutzt, welches in <stdio.h>definiert ist.
Auszug aus <stdio.h>:
/* Default path prefix for tempnam' and
tmpnam'. */
Die Anlage von Tempdateien hat auch mit dem Speicher und dem Swap nur mittelbar zu tun (was mache ich, wenn die Datei groesser ist als Speicher und Swap?). Das Puffern der Datei in RAM und Swap laeuft transparent.
Gruss
Thomas
Hello Thomas (W=West...?),
Wer kann mir nun sagen, wo Linux deine temporärdateien anlegt? Nur im Speicher und ggf. im Swapfile?
Im Normalfall unter /tmp:
Auszug aus "man tmpfile":
"Die Funktion tmpfile() generiert einen eindeutigen temporären Dateinamen indem sie den Pfad-Prefix P_tmpdir benutzt, welches in <stdio.h>definiert ist.Auszug aus <stdio.h>:
/* Default path prefix fortempnam' and
tmpnam'. */define P_tmpdir "/tmp"
Die Anlage von Tempdateien hat auch mit dem Speicher und dem Swap nur mittelbar zu tun (was mache ich, wenn die Datei groesser ist als Speicher und Swap?). Das Puffern der Datei in RAM und Swap laeuft transparent.
Danke für die Hinweise. Man Tempfile haben wir schon durch, aber an man tmpfile haben wir nicht gedacht. Es kommt aber trotz funktionstüchtigem Testprogramm in /tmp/ nix an...
Liebe Grüße aus http://www.braunschweig.de
Tom
Hello,
Hello Thomas (W=West...?),
Parodn bitte. Wer lesen kann, ist eindeutig im Vorteil. Hab ich glatt übersehen, dass da eine email stand. Ich dachte nur, vielleicht einen alten Bekannten wiederzutreffen.
Liebe Grüße aus http://www.braunschweig.de
Tom
Hallo Tom,
Danke für die Hinweise. Man Tempfile haben wir schon durch, aber an man tmpfile
haben wir nicht gedacht. Es kommt aber trotz funktionstüchtigem Testprogramm
in /tmp/ nix an...
Natürlich nicht. Durch tmpfile() generierte Dateien werden im _fini-Block
der Standard-C-Bibliothek wieder gelöscht. Aus 'man tmpfile':
The file will be automatically deleted when it is closed or the
program terminates normally.
Dass deine tmpfile()-Dateien nicht gelöscht werden, mag daran liegen, dass PHP
drum herum geschachtelt ist. Läuft es als mod_php? In dem Fall wird der Prozess
nicht beendet, wodurch die tmpfile()-Dateien auch nicht gelöscht werden.
Schliesst du sie wieder korrekt per fclose()? tmpfile() in PHP ist nur
eine Kapselung von der Funktion tmpfile() der Standard-C-Bibliothek.
Grüße,
CK
Hello CK,
Es kommt aber trotz funktionstüchtigem Testprogramm
in /tmp/ nix an...Natürlich nicht. Durch tmpfile() generierte Dateien werden im _fini-Block
Wieso "natürlich nicht"? Solange unsere Programminstanz lebt, müsste doch das Tempfile auch existieren. Ich kann ja schließlich 'was reinschreiben.
der Standard-C-Bibliothek wieder gelöscht. Aus 'man tmpfile':
The file will be automatically deleted when it is closed or the
program terminates normally.Dass deine tmpfile()-Dateien nicht gelöscht werden, mag daran liegen, dass PHP
drum herum geschachtelt ist. Läuft es als mod_php? In dem Fall wird der Prozess
nicht beendet, wodurch die tmpfile()-Dateien auch nicht gelöscht werden.
Schliesst du sie wieder korrekt per fclose()? tmpfile() in PHP ist nur
eine Kapselung von der Funktion tmpfile() der Standard-C-Bibliothek.
Nee, scheinbar nicht. Es scheint tempnam() zu verwenden, soweit wir das jedefalls aus dem Quellcode und Beschreibungen im Internet erkennen konnten.
Besteht immer noch die Frage, wo bleiben die Tempfiles eines C-Programms, das tmpfile() verwendet bei Linux? Bei WinDOS tauchen sie mit Endung *.$$$ im aktiven Verzeichnis auf und verschwinden brav wieder, wenn das Programm endet.
Liebe Grüße aus http://www.braunschweig.de
Tom
Hallo Tom,
Es kommt aber trotz funktionstüchtigem Testprogramm
in /tmp/ nix an...Natürlich nicht. Durch tmpfile() generierte Dateien werden im _fini-Block
Wieso "natürlich nicht"? Solange unsere Programminstanz lebt, müsste doch das
Tempfile auch existieren. Ich kann ja schließlich 'was reinschreiben.
Solange dein Script läuft, ja.
Nee, scheinbar nicht. Es scheint tempnam() zu verwenden, soweit
wir das jedefalls aus dem Quellcode und Beschreibungen im Internet
erkennen konnten.
Hm. Ich habe jetzt gerade im Source nochmal nachgeschaut, und du hast
recht, es wird nicht das tmpfile() aus der C-Lib benutzt. Stattdessen
wird (über Umwege) auf Windows-Systemen GetTempFileName, auf
Netware-Systemen mktemp() verwand. Auf den übrigen Systemen wird,
sollte mkstemp() vorhanden sein, mkstemp() verwandt, ansonsten mktemp().
Das Namensmuster ist:
Windows:
Das Ergebnis von GetTempPath() +
Unizes + Netware:
Der Inhalt der Umgebungsvariablen TMPDIR, ansonsten
die Konstante P_tmpdir, wenn das nicht existiert "/tmp" +
den String "php" + 6 zufällige Zeichen.
Besteht immer noch die Frage, wo bleiben die Tempfiles
eines C-Programms, das tmpfile() verwendet bei Linux?
/tmp
Bei WinDOS tauchen sie mit Endung *.$$$ im aktiven
Verzeichnis auf und verschwinden brav wieder, wenn
das Programm endet.
Bei Windows tauchen sie da auf, wo GetTempPath() es sagt. Wenn
das . ist, dann .. Wenn das c:\tmp ist, dann ist das c:\tmp.
Grüße,
CK
Hallo Tom,
Aber jedenfalls habe ich dabei festgestellt, dass es sich nicht
um eine echte Temporärdatei, sondern um eine persistente Datei handelt,
die durch das Runtimesystem bei Scriptende oder -abbruch wieder gelöscht
wird.
Was soll eine temporäre Datei sonst sein als eine Datei, die nach
einem bestimmten Zeitraum wieder gelöscht wird?
Nur im Speicher und
Nein, es wird eine ganz normale Datei angelegt. Eben eine temporäre Datei.
ggf. im Swapfile?
Es gibt kein 'Swapfile' unter Linux. Da gibt es nur eine Partition, auf
der zu swappende Daten ausgelagert werden.
Grüße,
CK
Tach CK,
Es gibt kein 'Swapfile' unter Linux. Da gibt es nur eine Partition, auf
der zu swappende Daten ausgelagert werden.
Stimmt nicht ganz - es ist auch moeglich, ein File zum Swappen zu verwenden (man mkswap)
Viele Gruesse,
Gero (Neunmalklug ;-)
Tach Gero,
Es gibt kein 'Swapfile' unter Linux. Da gibt es nur eine Partition, auf
der zu swappende Daten ausgelagert werden.Stimmt nicht ganz - es ist auch moeglich, ein File zum Swappen zu
verwenden (man mkswap)
Ui, danke für den Hinweis. War mir neu.
Grüße,
CK
Hello,
Es gibt kein 'Swapfile' unter Linux. Da gibt es nur eine Partition, auf
der zu swappende Daten ausgelagert werden.Stimmt nicht ganz - es ist auch moeglich, ein File zum Swappen zu
verwenden (man mkswap)Ui, danke für den Hinweis. War mir neu.
Na und ich behaupte dann nochmals, dass es eben ein Unterscheid ist, ob das Betriebssystem eine "echte" temporäre Datei zur verfügung stellt, oder eine Applikation/Daemon (PHP, PERL) eine persistente Datei, die nach dem Ende des Prozesesse innerhalb dieses Runtimemoduls wieder gelöscht wird vom Runtimesystem/Daemon.
Alle, die was anderes begaupten, fprdere ich zum Duell. Meine Waffe ist tmpfile() von C *ggg*
Liebe Grüße aus http://www.braunschweig.de
Tom
Hallo Tom,
Na und ich behaupte dann nochmals, dass es eben ein Unterscheid ist, ob
das Betriebssystem eine "echte" temporäre Datei zur verfügung stellt,
Wie definierst du 'echte' temporäre Dateien? Eine temporäre _Datei_(!) ist
eine Datei, die nach einem bestimmten Zeitraum gelöscht wird. Mehr nicht.
oder eine Applikation/Daemon (PHP, PERL) eine persistente Datei, die nach dem
Ende des Prozesesse innerhalb dieses Runtimemoduls wieder gelöscht wird vom
Runtimesystem/Daemon.
Ehm. Du weisst schon, was tmpfile() (abhängig von der libc) macht?
Alle, die was anderes begaupten, fprdere ich zum Duell. Meine Waffe
ist tmpfile() von C *ggg*
Das hier ist tmpfile() bei der glibc:
FILE *
tmpfile (void)
{
error_t err;
file_t file;
int fd;
FILE *f;
/* Get a port to the directory that will contain the file. */
const char *dirname = __secure_getenv ("TMPDIR") ?: P_tmpdir;
file_t dir = __file_name_lookup (dirname, 0, 0);
if (dir == MACH_PORT_NULL)
return NULL;
/* Create an unnamed file in the temporary directory. */
err = __dir_mkfile (dir, O_RDWR, S_IRUSR | S_IWUSR, &file);
__mach_port_deallocate (__mach_task_self (), dir);
if (err)
return __hurd_fail (err), NULL;
/* Get a file descriptor for that port. POSIX.1 requires that streams
returned by tmpfile allocate file descriptors as fopen would. */
fd = _hurd_intern_fd (file, O_RDWR, 1); /* dealloc on error */
if (fd < 0)
return NULL;
/* Open a stream on the unnamed file.
It will cease to exist when this stream is closed. */
if ((f = __fdopen (fd, "w+b")) == NULL)
__close (fd);
return f;
}
Wie du siehst, wird auch hier einfach nur eine Datei angelegt.
Grüße,
CK
Moin!
Ehm. Du weisst schon, was tmpfile() (abhängig von der libc) macht?
Ich habe zwar nur vage Vermutungen, was der _Code_ macht - aber die Kommentare dazwischen sind doch relativ eindeutig:
/* Get a port to the directory that will contain the file. */
/* Create an unnamed file in the temporary directory. */
Aha. Eine unbenannte Datei wird angelegt. Wäre zumindest ein Indiz dafür, dass diese Datei im Verzeichnis nicht auftaucht - so ganz ohne Namen...
/* Get a file descriptor for that port. POSIX.1 requires that streams
returned by tmpfile allocate file descriptors as fopen would. */
/* Open a stream on the unnamed file.
It will cease to exist when this stream is closed. */
Und das ist vermutlich eine Eigenschaft des darunterliegenden Betriebssystems, dass eine temporäre, unbenannte Datei wieder gelöscht wird, wenn der Stream geschlossen wird. Alternativ könnte man die Datei vielleicht "retten", indem man ihr einen Namen und damit einen Directory-Eintrag verpaßt - aber bitte nicht hauen, wenn das total falschvermutet ist :) .
- Sven Rautenberg