2013-12-16 77 views
3

我正在處理APUE的問題,以便像cp那樣編寫程序來複制文件(第4章問題4.6)。如果文件包含漏洞(或稀疏文件),那麼將不會處理間隙中的'\ 0'。理想的方法是逐塊讀取和寫入,其大小由lseek(fd,current_off,SEEK_HOLE)確定。我以/ bin/ls爲例。但是,如果超時,我會將這個文件(或其他文件)的文件偏移量始終設置爲文件末尾。我檢查了這個post,但似乎沒有令人滿意的答案。這裏是我的代碼:SEEK_HOLE總是指向文件的末尾

#include <stdio.h> 
/* and other headers */ 

int main(void) { 
    int fd; 
    off_t off; 
    fd = open("/bin/ls", O_RDONLY); 
    if ((off = lseek(fd, 0, SEEK_HOLE) == -1) 
     exit(-1); 
    printf("%d\n", off); 
    return 0; 
} 

我的內核是Linux 3.13.0-RC3從最新的穩定樹上摘下我的fs爲EXT4。如果lseek不可用,將任何'\ 0'視爲洞的開始是否合適?感謝您的回答。

+3

我不確定爲什麼問題得不到解決。這似乎很合理。順便說一句,有一些有用的信息在http://lwn.net/Articles/440778/ – NPE

+1

稀疏文件是罕見的野外;你的源文件可能不稀疏。 –

+0

你爲什麼認爲'ls'是一個稀疏文件? 100%這是一個普通的文件。稀疏文件通常是冗長的日誌文件。 – egur

回答

6

從「人lseek的」(man頁面是你的朋友,尋找信息,第一的位置。)

 SEEK_HOLE 
      Adjust the file offset to the next hole in the file greater than 
      or equal to offset. If offset points into the middle of a hole, 
      then the file offset is set to offset. If there is no hole past 
      offset, then the file offset is adjusted to the end of the file 
      (i.e., there is an implicit hole at the end of any file). 

換句話說,你所看到的完全預期的行爲。 ls中沒有任何漏洞,所以你在文件末尾有一個漏洞。

您可以創建一個用於測試的稀疏文件與dd

dd if=/dev/zero of=sparsefile bs=1 count=1 seek=40G 

至於你的最後一個問題:不,這不是合理的。文件完全有可能在其中包含0個字節。這並不表示它們是稀疏文件。

+0

感謝您的所有評論,郵件非常有啓發性。我已經檢查過gnu cp的實現。他們使用最簡單的方法來處理它:遍歷他們讀取的緩衝區中的每個字節。如果緩衝區已清零,則將此緩衝區標記爲不要寫入目標。我犯了一個錯誤,我使用du -s來轉儲文件的大小,並將它與來自ls -l的文件長度進行比較。 du以KB顯示結果,因此我認爲du返回比文件原始長度小得多的尺寸。另外'\ 0'應該是大量的,以便它們可以被識別爲一個洞 – Hypeboyz

+1

@Hypeboyz正確的,稀疏只適用於整個塊被清零的情況。 – glglgl

+0

+1。你是對的! - > RTFM :-) – Kyrol