2013-07-03 30 views
5
  • Platformu: Debian Hışıltılı 3.2.0-4-686-pae
  • Uyan: GCC (Debian 4.7.2-5) 4.7.2 (Code :: Blocks)

Bir dosyayı bir konumdan diğerine taşımak istiyorum. Farklı sürücülere veya farklı dosya sistemlerine geçmek gibi karmaşık bir şey yoktur. Bunu yapmanın "standart" yolunu biliyorum, sadece dosyayı kopyalayıp orijinali kaldıracağım. Ama dosyanın sahipliğini, modunu, son erişimini/modifikasyonunu vb. Korumanın bir yolunu istiyorum. Dosyayı kopyalamak ve daha sonra yeni dosyanın sahipliğini, modunu vb. Düzenlemek zorunda olduğumu farz ediyorum, fakat bunun nasıl yapılacağına dair hiçbir fikrim yok. Dosya için özgün ve yeni konum aynı dosya sisteminde iseLinux üzerinde c bir dosya taşındığında

cevap

10

Eğer rename(2) syscall kullanamıyorsanız (örneğin, kaynak ve hedef farklı bir dosya sisteminde olduğu için), boyut, izin ve stat(2) ile kaynak dosyasının diğer meta verileri sorgulamak için var; read(2), write(2) (birkaç kilobayttan oluşan bir arabellek kullanarak), open(2), close(2) ve chmod(2), chown(2), utime(2) kullanarak meta verileri kullanarak verileri kopyalayın. Ayrıca kopyalama getxattr(2), setxattr(2) kullanarak nitelikleri hakkında, listxattr(2)

bakım Ve kaynak ve hedef farklı dosya sistemleri üzerinde ise, yarış koşulları atom hamle yapmak ve önlemek için bir yolu yoktur olabilir (Yani, rename(2) mümkün olduğunda tercih edilir kullanarak çünkü insan sayfasına göre atomiktir). Daha fazla bilgi için (ve aynı zamanda ne yaptığını anlamak için strace bazı mv komut çalışın)

Oku Advanced Linux Programming kaynak dosyası her zaman ... taşıma işlemleri sırasında (başka bir işlem tarafından) değiştirilebilir.

+0

Alternatif seçenek için çok teşekkürler. –

+0

Linux için, [sendfile] (http://man7.org/linux/man-pages/man2/sendfile.2.html) 'read', 'write' 'den daha verimli dosya sistemi sınırları arasında kopyalama için bir yöntem sağlar. . Orijinal 'sendfile'' 0x7ffff000 (2,147,479,552) baytlık boyut sınırlarına sahiptir, ancak Linux ayrıca 'sendfile64' sarmalayıcısını ofset argümanı için daha geniş bir türe ekledi. –

11

daha sonra bir "hareket" bir kavramsal olarak aynıdır "rename."

#include <stdio.h> 

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

Tehlikeli. Yarış koşullarına sahiptir - bir dosya tanıtıcısı değil, isme dayalı tüm dosya işlemleri gibi. Renamayı aramadan önce doğru dosya olduğunu kontrol edebilirsin, ancak kontrol ve gerçek yeniden isimlendirme işlemi arasında biraz zaman var. O zaman, orijinal dosyanın kötü niyetli bir dosya ile değiştirilmesi mümkün olabilir (ve bu tür vatansalar gerçek uygulamalarda mevcuttu). – atk

+0

Bir dosya tanıtıcısı kullanılarak bir dosya yeniden adlandır işlevi göründüğü gibi görünmüyor, dosyanın gerçekten değişmediğini onaylamak için stat(), yeniden adlandırın, sonra stat() öğesine zorlanacaksınız gibi görünüyor - Yeni dosya hala eski dosya ile aynıdır - hiç kullanmadan önce – atk

+3

@atk: Neden bu 'yeniden adlandırmak (2) 'tehlikeli olduğuna inanıyor musunuz? Atom olduğuna inanıyorum, çünkü bu bir syscall ve onun “man” sayfası atomiklikten bahsediyor! –

İlgili konular