天天看點

linux 檔案長度 檔案截斷 rename renameat

檔案長度

stat結構成員st_size表示以位元組為機關的檔案的長度。此字段隻對普通檔案、目錄檔案和符号連結檔案有意義。

對于普通檔案,其檔案長度可以是0,在開始讀這種檔案時,将得到檔案結束訓示。

對于目錄,檔案長度通常是一個數的整倍數。

對于符号連結,檔案長度是在檔案名中的實際位元組數。例如,在下面的例子中,檔案長度15就是路徑名/usr/lib的長度:

lrwxrwxrwx  1 root root      15 2014-05-12 17:00 libz.so.1 -> libz.so.1.2.3.3
           

(注意,因為符号連結檔案長度總是由st_size訓示,是以它并不包含通常C語言做名字結尾的null位元組)

現今,大多數現代的UNIX系統提供字段st_blksize和st_blocks,其中,第一個是對檔案I/O較合适的快長度,第二個是所配置設定的資料512位元組塊數。為了提高效率,标準I/O庫也試圖一次讀、寫st_blksize個位元組。

檔案截斷

有時我們需要在檔案尾端處截取一些資料以縮短檔案。将一個檔案的長度截斷為0是一個特例,在打開檔案時使用O_TRUNC标志可以做到這一點。為了截斷檔案可以調用函數truncate和ftruncate。

#include <unistd.h>
int truncate(const char *pathname, off_t length);
int ftruncate(int fd, off_t length);
                                                                連個函數的傳回值:若成功,傳回0;若出錯,傳回-1
           

這兩個函數将一個現有檔案長度截斷為length。如果該檔案以前的長度大于length,則超過length以外的資料就不再能通路。如果以前的長度小于length,檔案長度将增加,在以前的檔案尾端和新檔案的尾端之間的資料将作為0。

函數rename和renameat

檔案或目錄可以用rename函數或者renameat函數進行重命名。

#include <stdio.h>
int rename(const char *oldname, const char *newname);
int renameat(int oldfd,const char *oldname, int newfd, const char *newname);
                                                                              兩個函數的傳回值:若成功,傳回0;若出錯,傳回-1
           

根據oldname是指檔案、目錄還是符号連結,有幾種情況需要加以說明。

(1)如果oldname指的是一個檔案而不是目錄,那麼為該檔案或符号連結重命名。在這種情況下,如果newname已存在,則它不能引用一個目錄。如果newname已存在,而且不是一個目錄,則先将目錄項删除然後将oldname重命名為newname。對包含oldname的目錄以及包含newname的目錄,調用程序必須具有寫權限,因為将更改這兩個目錄。

(2)如若oldname指的是一個目錄,那麼為該目錄重命名。如果newname已存在,則它必須引用一個目錄,而且該目錄應當是空目錄(空目錄指隻有.和..項)。如果newname存在(而且是一個新目錄),則先将其删除,然後将oldname重命名為newname。另外,當為一個目錄重命名時,newname不能包含oldname作為其路徑名字的路徑字首。例如,不能将/usr/foo重命名為/usr/foo/testdir,因為舊名字(/usr/foo)是新名字的路徑字首,因而不能将其删除。

(3)如若oldname或newname引用符号連結,則處理的是符号連結本身,而不是它所引用的檔案。

(4)不能對.和..重命名。更确切的說,.和..都不能出現在oldname和newname的最後部分。

(5)作為一個特例,如果oldname和newname引用同一檔案,則函數不做任何更改而成功傳回。

如若newname已經存在,則調用程序對它需要有寫權限。另外,調用程序将删除oldname目錄項,并可能要建立newname目錄項,是以它需要對包含的oldname及包含newname的目錄具有寫和執行權限。

除了當oldname或newname指向相對路徑名時,其他情況下renameat函數與rename函數功能相同。如果oldname參數指定了相對路徑,就相對于oldfd參數引用的目錄來計算oldname。類似的,如果oldname參數指定了相對路徑,就相對于newfd引用的目錄來計算newname。oldfd或newfd參數都能設定成AT_FDCWD,此時相對于目前目錄來計算相應的路徑名。

繼續閱讀