2013-07-03 26 views
5
  • Platforma: Debian Wheezy 3.2.0-4-686-PAE
  • kompilator: GCC (Debian 4.7.2-5) 4.7.2 (Code :: Blocks)

Chcę przenieść plik z jednej lokalizacji do drugiej. Nic skomplikowanego, jak przejście na różne napędy lub różne systemy plików. Wiem, że "standardowym" sposobem na to byłoby po prostu skopiowanie pliku, a następnie usunięcie oryginału. Ale chcę mieć jakiś sposób na zachowanie własności pliku, trybu, ostatniego dostępu/modyfikacji itd. Zakładam, że będę musiał skopiować plik, a następnie edytować jego własność, tryb itd., Ale nie mam pojęcia, jak to zrobić.Przenoszenie plików w systemie Linux w C

Odpowiedz

10

Jeśli nie można użyć rename(2) syscall (na przykład dlatego, źródło i cel są na innym systemie plików), trzeba zapytać rozmiar, pozwolenia i inne metadane pliku źródłowego z stat(2); skopiuj dane przy użyciu read(2), write(2) (przy użyciu bufora o kilku kilobajtach), open(2), close(2) i metadanych przy użyciu chmod(2), chown(2), utime(2). Można również dbają o kopiowanie atrybutów za pomocą getxattr(2), setxattr(2), listxattr(2)

A jeśli źródło i cel znajdują się na różnych systemach plików, nie ma sposobu, aby przenieść atomowej i uniknąć warunków wyścigu (So używając rename(2) korzystne jest, gdy to możliwe, ponieważ jest atomowy zgodnie ze stroną man). Plik źródłowy może być zawsze zmodyfikowane (przez inny proces) podczas operacji move ...

Czytaj Advanced Linux Programming dłużej (a także spróbować strace niektóre polecenia mv zrozumieć, co robi).

+0

Bardzo dziękuję za alternatywną opcję. –

+0

Dla systemu Linux plik [sendfile] (http://man7.org/linux/man-pages/man2/sendfile.2.html) zapewnia metodę kopiowania pomiędzy granicami systemu plików, która jest bardziej wydajna niż "odczyt", "zapis" . Oryginalny 'sendfile' ma limity rozmiaru' 0x7ffff000 (2147479552) 'bajtów, ale Linux dodał także wrapper' sendfile64' z szerszym typem dla argumentu offset. –

11

Jeśli oryginalna i nowa lokalizacja pliku znajduje się w tym samym systemie plików, wówczas "ruch" jest koncepcyjnie identyczny z "rename".

#include <stdio.h> 

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

Niebezpieczny. Ma warunki wyścigowe - tak jak wszystkie operacje na plikach, które opierają się na nazwie, a nie na wskaźniku pliku. Przed wywołaniem funkcji renmae można sprawdzić, czy jest to właściwy plik, ale jest też trochę czasu między sprawdzaniem a rzeczywistą operacją zmiany nazwy. W tym czasie możliwe jest zastąpienie oryginalnego pliku złośliwym plikiem (a takie geny istnieją w rzeczywistych aplikacjach). – atk

+0

Wygląda na to, że nie ma funkcji zmiany nazwy pliku za pomocą wskaźnika pliku, wygląda na to, że będziesz zmuszony ponownie do stat(), zmiany nazwy, a następnie stat(), aby potwierdzić, że plik tak naprawdę nie zmienił się - nowy plik jest wciąż taki sam jak stary plik - zanim go użyjesz – atk

+3

@atk: Dlaczego uważasz, że 'rename (2)' jest niebezpieczne? Wierzę, że jest atomowy, ponieważ jest to system i jego strona "man" wspomina o atomowości! –

Powiązane problemy