Alexander (HH): IO bzw. CGI.pm Upload speichern

Beitrag lesen

Moin Moin!

weil sie zwar noch als File existieren, aber kein Verzeichniseintrag mehr auf die Files verweist.

mag ja sein, aber ich will das File nicht kopieren sondern per verschieben. Sprich einen Hardlink anlegen. In perl akzeptiert "link" aber keine Filehandles.

In der darunter liegenden Kernel-Schnittstelle (link(2)) auch nicht.

Und ein shell "mv" kann ich auch nicht ausführen.

Nicht ohne den Namen der Datei, richtig. Würde ich aber ohnehin nicht machen, denn das CGI-Modul ist sehr bestrebt, die Temp-Files wieder zu löschen. Und statt mv aufzurufen, würde ich ganz generell lieber File::Copy::move() benutzen.

Und rate mal, wie das "Betriebssystem" Dateien kopiert. Richtig, blockweise kopieren, nur die Blockgröße variiert je nach Kopiermethode.

jep, ist klar, in meinem FS liegt die Blockgröße bei 4096.

Was aber nichts mit der Puffergröße im kopierenden Programm zu tun haben muß. dd nimmt 512 Bytes, cp macht ohnehin, was es will, und eine Kopierfunktion auf Kernel-Ebene gibt es meines Wissens nicht.

Aber abgesehen davon dass ich ja nicht kopieren möchte, bezweifle ich dass Perl das annähernd so performant macht wie das OS.

Das OS *kann* keine Kopien anfertigen, das machen Hilfsprogramme wie cp und dd. Und die machen abwechselnd read() und write() auf einen einmal angelegten Buffer. Exakt das macht Perl auch, mit unwesentlich mehr overhead. Wenn Du Angst hast, dass die while-Schleife dich ausbremst, erhöhe die Puffergroße. 32K oder 64K RAM hast Du vermutlich noch über. Gegen das Puffern in print hilft syswrite, dabei mußt Du dann allerdings à la C Dich selbst darum kümmern, dass alles geschrieben wurde.

Kennst Du File::Copy::copy()? Das sollte Dir die ganze Kopiererei abnehmen. Und es kopiert in bis zu 2 MB großen Blöcken.

Wie bekomme ich eigentlich den Pfad eines Filehandles wieder raus wenn es zu einem File gehört?

Ein Filehandle hat keinen Pfad. Was möchtest Du? Von einem Handle auf einen Dateinamen schließen? Das geht nicht, u.a. wegen Hardlinks.

stimmt ... leider ... eine FS-Funktion die mir die Pfade aller Hardlinks zu einem Handle ausspuckt wär wirklich nett...schöner Traum...

Aus OS-Sicht wäre das ein Alptraum. Spätestens mit Hardlinks auf Directories.

Stell Dir im folgenden vor, dass die Verzeichnisse mit x und y am Ende jeweils Hardlinks auf das selbe Verzeichnis sind, und alle Dateien der selbe Hardlink:

/home/example/ax/bx/cx/dx/file1
/home/example/ay/by/cy/dy/file2
/home/example/file3

Für dieses blöde Beispiel gäbe es 17 verschiedene Pfade, Symlinks und ähnliche Späße noch gar nicht mit eingerechnet.

Du müßtest eine Funktion aufrufen, die ein Array of Strings zurückliefert. Dummerweise kann C aber weder Arrays zurückliefern noch hat es Strings (jaja, C-Programmierer springen mir jetzt an die Kehle). Strings sind als Array of Characters definiert, und Arrays wiederum als einfacher Zeiger irgendwo in den Speicher.

Also endest Du bei einer kuscheligen Funktion, die einen Zeiger auf einen Speicherblock annimmt, in dem weitere Zeiger auf weitere Speicherblöcke liegen, und befüllt. Damit das Ganze sicher funktioniert, brauchst Du noch eine Zeigerarray-Größe und eine Puffergröße für jeden String. Den Funktionsprototypen mag ich gar nicht aufschreiben.

Oder Du nutzt aus, dass ASCII NUL in Dateinamen nicht erlaubt ist und definierst die Funktion so, dass sie die Dateinamen als langen Puffer voller Namen zurückgibt, die mit ASCII NUL voneinander getrennt und mit einem leeren Namen terminiert sind. Dann mußt Du nur noch über den Buffer iterieren. Auch nicht lustig in C.

Von einem CGI-Upload-Filehandle-Objekt den Namen der Temp-Datei erfahren, sofern "Private Temp Files" abgeschaltet ist? Das steht in der Doku zum CGI-Modul.

ach! wo? ich hab die perldoc zigmal durchforst

Hab ich auch gerade mal gemacht, ist tatsächlich nicht drin. Sorry.

Ohne nachzusehen meine ich mich zu erinnern, dass das Objekt den Strinigfy-Operator überlädt um den Temp-File-Namen zurückzugeben. "".$tempfile oder "$tempfile" müßten es tun.

also sowas?

my  $upload_fh = $query->upload($name);
print h1("[".$upload_fh."]");

das liefert mir den Filenamen auf der Clientseite, nicht das tempfile auf dem Server!

Wie gesagt: "ohne nachzusehen" ;-)

Die Fh-Klasse in CGI.pm gibt sich alle Mühe, den Namen zu verstecken. $query->tmpFileName($upload_fh) sollte den Namen der Temp-Datei ausgeben, wie ich das auf die Schnelle sehe. Die DESTROY-Methode gibt sich aber alle Mühe, Dateien unter Kontrolle von CGI.pm zu löschen, entweder per Handle oder per Namen.

Alexander

--
Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so".