Tom: Linux, C und tmpfile(), PHP

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

--
Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
  1. 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

    --
      Schnee :) Skitour gefällig?
      http://harry.ilo.de/projekte/berge/
  2. 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'.  */

    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.

    Gruss
    Thomas

    1. 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 for tempnam' 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

      --
      Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
      1. 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

        --
        Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
      2. 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

        --
        Der Mund ist das Portal zum Unglück.
        1. 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

          --
          Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
          1. 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

            --
            Descartes sagte: 'Ich denke, also bin ich.' Ich hingegen sage: 'Ich denke nicht, also bin ich.'
  3. 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

    --
    Auf der ganzen Welt gibt es nichts Weicheres und Schwaecheres als Wasser. Doch in der Art, wie es dem Harten zusetzt, kommt nichts ihm gleich.
    1. 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 ;-)

      1. 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

        --
        Microsoft: Where do you want to go today?
        Linux: Where do you want to go tomorrow?
        FreeBSD: Are you guys coming, or what?
        1. 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

          --
          Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
          1. 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

            --
            Das Sein entsteht aus dem Nicht-Sein.
            1. 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

              --
              "Habe den Mut, dich deines eigenen Verstandes zu bedienen!" (Immanuel Kant)