2016-03-27 19 views
1

Ich mag wiePOSIX Möglichkeiten zur Erzeugung einer temporären Datei mit einem schönen Dateinamen

my-app-Mar27-120357-Qf3K0a.html

eine temporäre Datei mit einem „schönen“ Namen erzeugen, während im Anschluss an der Best Practices für die security.

POSIX bietet mir mkstemp(3), die eine Dateinamenvorlage nimmt (in der Regel so etwas wie /tmp/my-app-XXXXXX), aber es hat zwei Probleme:

  1. Ich brauche mir das Ausgabeverzeichnis zu wählen. When I see glibc tempnam(3) (which is deprecated for a security reason) considers many factors, möchte ich die Bibliothek Funktion wählen lassen.
  2. Es gibt keine Erweiterung im Dateinamen

Der zweite Punkt kann durch mkstemps(3) adressiert werden, die eine Anzahl von Zeichen nimmt als benutzerdefinierte Erweiterung zu halten. In meinem Fall kann ich my-app-Mar27-120357-XXXXXX.html und 5 passieren, aber es hat seine eigenen Probleme:

  1. Ich brauche noch das Ausgabeverzeichnis
  2. Es ist nicht perfekt tragbar zu wählen. NetBSD scheint es zu vermissen.

So bedenkt, dass ich bin die veraltete tempnam(3) zu verwenden, um einen Dateinamen mit dem Ausgangsverzeichnispfad zu erzeugen, überschrieben mit X und ihn an mkstemp(3), und benennen Sie die Datei auf meinem bevorzugten Format den Dateinamen Teil. Das Problem liegt also im letzten Schritt, Umbenennen ohne Überschreiben; ist es in POSIX möglich?

Oder könnte es bessere Alternativen geben?

+0

Die Antwort von Alex ist, was ich auch empfehlen würde, aber es gibt eine Standard-C-Funktion ['tmpnam'] (http://en.cppreference.com/w/c/io/tmpnam), die Sie verwenden könnten, wenn Sie Ich möchte wirklich einen Namen. –

+0

@JoachimPileborg 'tmpnam (3)' ist weniger flexibel als 'tempnam (3)' was ich bereits in meinem Beitrag erwähnt habe. – nodakai

+0

[NetBSD 7.0] (http://netbsd.gw.com/cgi-bin/man-cgi?mkstemps++NetBSD-7.0) und neuer haben 'mkstemps'. Allerdings ist es derzeit nicht in Minix3 libc vorhanden. – kdhp

Antwort

1

Lassen Sie mkstemp machen die Datei, die es machen will, in der POSIX-kompatiblen Weise, die es will. Verwenden Sie symlink, um eine symbolische Verknüpfung von einer Quelldatei und einem Pfad Ihrer Wahl zu einem Ziel herzustellen, das dem entspricht, was von mkstemp stammt. Entfernen Sie den symbolischen Link, wenn Sie fertig sind.

+1

Hmm, ich kann nicht sagen, dass ich diese Lösung liebe ... "Entferne den symbolischen Link, wenn du fertig bist." Stellen Sie sich vor, ich arbeite an einem Crash-Dump, den mein Programm vom Benutzer per E-Mail oder Web-Upload an unseren Server sendet. Aber ja, das könnte meiner Absicht am nächsten kommen. – nodakai

+0

Wenn Sie eine Ausnahme auslösen, die einen schwerwiegenden Fehler verursacht, könnten Sie sich mit der Bereinigung im Handler dieser Ausnahme befassen. –

+0

Ich meine, dass temporäre Dateien ihr Produzentenprogramm in einigen recht üblichen Anwendungsfällen recht gut überstehen können. – nodakai

0

Ein anderer Ansatz besteht darin, die Vorlage einfach zu verschieben und Ihren Pfad hinzuzufügen. Wir beschreiben eine solche Funktion in der BEDOPS Toolkit hier durch die sort-bed Anwendung verwendet, um die Benutzerende festlegen zu können, in dem temporäre Zwischendateien gespeichert sind: https://github.com/bedops/bedops/blob/6da835468565dfc30a3fcb65807e91fcf133ea2b/applications/bed/sort-bed/src/SortDetails.cpp#L115

FILE * 
createTmpFile(char const* path, char** fileName) 
{ 
    FILE* fp; 
    int fd; 
    char* tmpl; 

    if (path == NULL) 
     { 
      fileName = NULL; 
      return tmpfile(); 
     } 

    tmpl = static_cast<char*>(malloc(1 + strlen(path) + L_tmpnam)); 
    strcpy(tmpl, path); 
    strcpy(tmpl+strlen(path), "/sb.XXXXXX"); 
    fd = mkstemp(tmpl); 
    if(fd == -1) 
     { 
      fprintf(stderr, "unable to create temp file!\n"); 
      return NULL; 
     } 
    fp = fdopen(fd, "wb+"); 
    *fileName = static_cast<char*>(malloc(strlen(tmpl) + 1)); 
    strcpy(*fileName, tmpl); 
    free(tmpl); 
    return fp; 
} 

Dies verwendet die L_tmpnam Makro, ein Teil der stdio Bibliothek, um die Anzahl der Zeichen festzulegen, die die Variable tmpl (der Dateiname, letztendlich) speichern kann.

Dies kompiliert und arbeitet unter Linux und OS X (BSD) Hosts und verwendet auch POSIX-Routinen.

Es ist komplexer als meine andere Lösung, aber es könnte besser für Ihren Anwendungsfall funktionieren.

+0

Danke, dass Sie ein aktuelles Beispiel teilen. Du arbeitest an einem interessanten Projekt, übrigens – nodakai