2013-07-03 10 views
5
  • Piattaforma: Debian Wheezy 3.2.0-4-686-pae
  • compilatore: GCC (Debian 4.7.2-5) 4.7.2 (Code :: Blocks)

Desidero spostare un file da una posizione a un'altra. Nulla di complesso come il passaggio a dischi diversi o a diversi file system. So che il modo "standard" per farlo sarebbe semplicemente copiare il file e quindi rimuovere l'originale. Ma voglio un modo per preservare la proprietà del file, la modalità, l'ultimo accesso/modifica, ecc. Suppongo che dovrò copiare il file e successivamente modificare la proprietà, la modalità, ecc. Del nuovo file, ma non ho idea di come farlo.Spostamento di un file su Linux in C

risposta

10

Se non è possibile utilizzare il rename(2) syscall (ad esempio a causa di origine e di destinazione sono su diversi file system), è necessario interrogare il formato, permesso e altri metadati del file sorgente con stat(2); copiare i dati utilizzando read(2), write(2) (utilizzando un buffer di diversi kilobyte), open(2), close(2) e i metadati utilizzando chmod(2), chown(2), utime(2). Si potrebbe anche preoccupate per la copia degli attributi utilizzando getxattr(2), setxattr(2), listxattr(2)

E se l'origine e la destinazione sono su filesystem diversi, non c'è modo di fare la mossa atomica e di evitare condizioni di gara (in modo da utilizzare rename(2) è preferibile, quando possibile, perché è atomico secondo la sua pagina man). Il file sorgente può sempre essere modificato (da un altro processo) durante le operazioni di spostamento ...

Advanced Linux Programming Read per di più (e anche cercare di strace qualche comando mv per capire che cosa sta facendo).

+0

Grazie mille per l'opzione alternativa. –

+0

Per Linux, [sendfile] (http://man7.org/linux/man-pages/man2/sendfile.2.html) fornisce un metodo per copiare oltre i limiti del filesystem che è più efficiente di 'read',' write' . L'originale 'sendfile' ha limiti di dimensione' 0x7ffff000 (2.147.479.552) 'byte, ma Linux ha anche aggiunto il wrapper' sendfile64' con un tipo più largo per l'argomento offset. –

11

Se la posizione originale e nuova del file si trova sullo stesso file system, una "traslazione" è concettualmente identica a "rename".

#include <stdio.h> 

int rename (const char *oldname, const char *newname) 
+1

Pericoloso. Ha condizioni di gara - come tutte le operazioni sui file che si basano sul nome, non su un puntatore di file. Puoi verificare che sia il file giusto prima di chiamare renmae, ma poi c'è un po 'di tempo tra il controllo e l'effettiva operazione di rinomina. A quel tempo, è possibile che il file originale possa essere sostituito con un file dannoso (e tali vulns sono esistiti in applicazioni reali). – atk

+0

Visto che non sembra esserci una funzione di rinomina di file usando un puntatore di file, sembra che sarete costretti a stat(), rinominare, quindi stat() di nuovo, per confermare che il file non è davvero cambiato - il nuovo file è ancora uguale al vecchio file - prima che tu lo usi mai – atk

+3

@atk: perché credi che 'rinominare (2)' sia pericoloso? Credo che sia atomico, dal momento che è un syscall e la sua pagina 'man' menziona l'atomicità! –

Problemi correlati