前一陣子利用 NFS 來將使用者上傳上來的檔案儲存在伺服器端的檔案目錄中,但是當使用者想要檢視當前已經上傳上來的檔案並且查看檔案建立的時間時,卻發現無法取得檔案建立時間。雖然可以在設計上稍做調整,例如當檔案上傳上來時,將當前時間紀錄並儲存起來,待後續檢視使用。不過這樣的方法雖然可行,但是缺點就是需要額外成本來維護所儲存的檔案建立時間。因此本篇筆者就希望利用 Linux 檔案系統所儲存的建立時間來提供檢視檔案使用。
在經過筆者一番研究後發現在 Linux 4.11 版本後支援 statx() 方法,參考文件點擊。statx() 方法可以提供呼叫者檔案建立時間,但當前僅可以透過 C 語言進行呼叫,因此我們就需要透過 Golang 呼叫 C 語言,讓 C 語言代替我們去呼叫 statx() 方法,並將結果打包後轉成 Golang 看得懂的語法再將結果輸出。
接下來我們就依序介紹整個程式設計的流程。
步驟
首先我們要先確保當前 linux kernel 版本。
1 2 3
$ uname -a
Linux coredns 5.11.0-051100-generic #202102142330 SMP Sun Feb 14 23:33:21 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux
struct statx { /* 0x00 */ __u32 stx_mask; /* What results were written [uncond] */ __u32 stx_blksize; /* Preferred general I/O size [uncond] */ __u64 stx_attributes; /* Flags conveying information about the file [uncond] */ /* 0x10 */ __u32 stx_nlink; /* Number of hard links */ __u32 stx_uid; /* User ID of owner */ __u32 stx_gid; /* Group ID of owner */ __u16 stx_mode; /* File mode */ __u16 __spare0[1]; /* 0x20 */ __u64 stx_ino; /* Inode number */ __u64 stx_size; /* File size */ __u64 stx_blocks; /* Number of 512-byte blocks allocated */ __u64 stx_attributes_mask; /* Mask to show what's supported in stx_attributes */ /* 0x40 */ struct statx_timestamp stx_atime; /* Last access time */ struct statx_timestamp stx_btime; /* File creation time */ struct statx_timestamp stx_ctime; /* Last attribute change time */ struct statx_timestamp stx_mtime; /* Last data modification time */ /* 0x80 */ __u32 stx_rdev_major; /* Device ID of special file [if bdev/cdev] */ __u32 stx_rdev_minor; __u32 stx_dev_major; /* ID of device containing file [uncond] */ __u32 stx_dev_minor; /* 0x90 */ __u64 __spare2[14]; /* Spare space for future expansion */ /* 0x100 */ };
/* from kernel sources: include/uapi/linux/stat.h */ #define AT_STATX_SYNC_TYPE 0x6000 /* Type of synchronisation required from statx() */ #define AT_STATX_SYNC_AS_STAT 0x0000 /* - Do whatever stat() does */ #define AT_STATX_FORCE_SYNC 0x2000 /* - Force the attributes to be sync'd with the server */ #define AT_STATX_DONT_SYNC 0x4000 /* - Don't sync attributes with the server */
int date(const char *path, char *out);
#endif
上述 int date(const char *path, char *out); 方法,定義檔案路徑(path)與輸出的記憶體空間(out) 兩個參數。