/* * about sub-second timestamp on FFS * FreeBSD/FFS での timestamp の秒以下分について * by uratan! 2023.5.27 * revised: 2023.12.10 */
各ファイルの timestamp の秒以下分なんですが、 今時はさすがに管理保持しているんだろうなぁとの感触はあるのですが、 man ls にも stat にも strftime にも記述がない、ググっても拾えない…。
というわけで、今回ようやっと自分の手で確認してみました。
以下、FreeBSD 10.2-RELEASE(i386) にての実験的評価結果です、 古くてすいません。
stat system-call の扱う構造体には timestamp の nsec を保持する領域はあるみたい。
/usr/include/sys/stat.h struct stat { : struct timespec st_atim; /* time of last access */ struct timespec st_mtim; /* time of last data modification */ struct timespec st_ctim; /* time of last file status change */ : } /usr/include/sys/_timespec.h struct timespec { time_t tv_sec; /* seconds */ long tv_nsec; /* and nanoseconds */ };
ls コマンドでは、-t での新旧ソートでは 秒以下分も比較対象にしているみたいだけれど、
% cd /usr/src/bin/ls/ % fgrep -e tv_sec -e tv_nsec *.[ch] cmp.c: if (b->fts_statp->st_mtim.tv_sec > cmp.c: a->fts_statp->st_mtim.tv_sec) cmp.c: if (b->fts_statp->st_mtim.tv_sec < cmp.c: a->fts_statp->st_mtim.tv_sec) cmp.c: if (b->fts_statp->st_mtim.tv_nsec > cmp.c: a->fts_statp->st_mtim.tv_nsec) cmp.c: if (b->fts_statp->st_mtim.tv_nsec < cmp.c: a->fts_statp->st_mtim.tv_nsec) cmp.c: if (b->fts_statp->st_atim.tv_sec > ...
秒以下分を表示するという処理はいっさい無いよう。
/usr/src/bin/ls/print.c : if (f_accesstime) printtime(sp->st_atime); else if (f_birthtime) printtime(sp->st_birthtime); else if (f_statustime) printtime(sp->st_ctime); else printtime(sp->st_mtime); : static void printtime(time_t ftime) { : strftime(longstring, sizeof(longstring), format, localtime(&ftime)); fputs(longstring, stdout); fputc(' ', stdout); }
そもそも sys/stat.h には、 秒単位だけ扱う(従来)プログラムのための(後方互換用)マクロまで 用意されているのね。(末尾の'e'有り無しか…、わかりにくい…)
/usr/include/sys/stat.h #define st_atime st_atim.tv_sec #define st_mtime st_mtim.tv_sec #define st_ctime st_ctim.tv_sec
/bin/ls を改造し 秒以下 timestamp も表示するツールを用意します。
オプションは -l (long format) 固定とし、 表示フォーマットは 秒以下 timestamp がつながるように 強制してます。使用例は以下の通り。
/home/uratan/eva % ./my-ls/ls ss-ts.html -rw-r--r-- 1 uratan zinc 7028 2023-0527 13:11.28 ss-ts.html /home/uratan/eva % ./my-ls/ls -l ss-ts.html -rw-r--r-- 1 uratan zinc 7028 2023-0527 13:11.28,510433000 ss-ts.html
修正差分はこんな感じで my-ls-patch.txt (ソースコードは /usr/src/bin/ls/ から)
(【注】以下 実行例ですが不要行は少々削ってあります)サンプルが少ないですが、nsec 表示の下3桁は常時ゼロのようなので 分解能はμsec単位程度のようですね。 touch の結果からも 6桁に制限しているくさいので、常用するなら 6桁表示で十分な感じかな。
- /bin/cp, /bin/mv
…… 秒以下 timestamp は基本保持されるが、filesystem をまたいだ mv では 保持されないよう。(これは 10.4R あたりで修正されてるっぽい)
/home/uratan/eva % touch SAMPLE /home/uratan/eva % ./my-ls/ls -l SAMPLE -rw-r--r-- 1 uratan zinc 0 2023-0527 13:14.35,327202000 SAMPLE /home/uratan/eva % cp -p SAMPLE cpcp /home/uratan/eva % mv SAMPLE mvmv /home/uratan/eva % ./my-ls/ls -l -rw-r--r-- 1 uratan zinc 0 2023-0527 13:14.35,327202000 cpcp -rw-r--r-- 1 uratan zinc 0 2023-0527 13:14.35,327202000 mvmv /home/uratan/eva % touch /tmp/SAMPLE /home/uratan/eva % ./my-ls/ls -l /tmp/SAMPLE -rw-r--r-- 1 uratan wheel 0 2023-0527 13:15.49,247716000 /tmp/SAMPLE /home/uratan/eva % cp -p /tmp/SAMPLE cpcp /home/uratan/eva % mv /tmp/SAMPLE mvmv /home/uratan/eva % ./my-ls/ls -l -rw-r--r-- 1 uratan wheel 0 2023-0527 13:15.49,247716000 cpcp -rw-r--r-- 1 uratan wheel 0 2023-0527 13:15.49,000000000 mvmv
- /usr/bin/tar, /usr/local/bin/zip+unzip, /usr/local/bin/rsync
…… tar, zip/unzip, rsync -av では秒以下 timestamp は保持されないよう。
/home/uratan/eva % touch SAMPLE /home/uratan/eva % ./my-ls/ls -l SAMPLE -rw-r--r-- 1 uratan zinc 0 2023-0527 13:16.53,219662000 SAMPLE /home/uratan/eva % tar cf sample.tar SAMPLE /home/uratan/eva % zip -q sample.zip SAMPLE /home/uratan/eva % mkdir Dtar Dzip Drsync /home/uratan/eva % tar xf sample.tar -C Dtar /home/uratan/eva % unzip -q sample.zip -d Dzip /home/uratan/eva % rsync -av SAMPLE Drsync/ /home/uratan/eva % ./my-ls/ls -lrt -rw-r--r-- 1 uratan zinc 0 2023-0527 13:16.53,219662000 SAMPLE -rw-r--r-- 1 uratan zinc 1536 2023-0527 13:17.10,884790000 sample.tar -rw-r--r-- 1 uratan zinc 162 2023-0527 13:17.18,008650000 sample.zip drwxr-xr-x 2 uratan zinc 512 2023-0527 13:17.38,175962000 Dtar/ drwxr-xr-x 2 uratan zinc 512 2023-0527 13:17.48,556848000 Dzip/ drwxr-xr-x 2 uratan zinc 512 2023-0527 13:17.58,587614000 Drsync/ /home/uratan/eva % ./my-ls/ls -l D* Drsync: -rw-r--r-- 1 uratan zinc 0 2023-0527 13:16.53,000000000 SAMPLE Dtar: -rw-r--r-- 1 uratan zinc 0 2023-0527 13:16.53,000000000 SAMPLE Dzip: -rw-r--r-- 1 uratan zinc 0 2023-0527 13:16.53,000000000 SAMPLE
(tar file や zip file にも仕様がありますから これはまぁ致し方ない)
(rsync は 更新判断の timestamp 比較も秒単位までですね、 まあ整合はしている)
(…しかし tar/zip/rsync で backup OK とか言ってたけど、 厳密には timestamp の細かいところがロストしてるのか…)
- samba による windows との timestamp 共有
…… windows7/NTFS から samba 経由で ffs に書き込んだファイルが それらしい 秒以下 timestamp を示しますので それなりに共有されているように思われます。
u:\eva> cat z.bat touch.exe SAMPLE1 touch.exe SAMPLE2 touch.exe SAMPLE3 SAMPLE4 u:\eva> z.bat u:\eva> xcopy SAM* i:\win\eva U:SAMPLE1 U:SAMPLE2 U:SAMPLE3 U:SAMPLE4 4 個のファイルをコピーしました - * - * - /home/win/eva % /home/uratan/eva/my-ls/ls -lrt -rwxrw-r-- 1 nobody nobody 0 2023-0527 13:09.44,115730000 SAMPLE1* -rwxrw-r-- 1 nobody nobody 0 2023-0527 13:09.44,138230000 SAMPLE2* -rwxrw-r-- 1 nobody nobody 0 2023-0527 13:09.44,150730000 SAMPLE4* -rwxrw-r-- 1 nobody nobody 0 2023-0527 13:09.44,150730000 SAMPLE3*
(往復しても同じ値が保持されてますので間違いなさそう)
- /usr/bin/touch (重要なのを忘れていた)
…… 既に対応してんじゃん!。
/home/uratan/eva % touch -d 2023-06-06T12:34:56 SAMPLE /home/uratan/eva % ./my-ls/ls -l SAMPLE -rw-r--r-- 1 uratan zinc 0 2023-0606 12:34.56,000000000 SAMPLE /home/uratan/eva % touch -d 2023-06-06T12:34:56.123 SAMPLE /home/uratan/eva % ./my-ls/ls -l SAMPLE -rw-r--r-- 1 uratan zinc 0 2023-0606 12:34.56,123000000 SAMPLE /home/uratan/eva % touch -d 2023-06-06T12:34:56.123456 SAMPLE /home/uratan/eva % ./my-ls/ls -l SAMPLE -rw-r--r-- 1 uratan zinc 0 2023-0606 12:34.56,123456000 SAMPLE /home/uratan/eva % touch -d 2023-06-06T12:34:56.123456789 SAMPLE /home/uratan/eva % ./my-ls/ls -l SAMPLE -rw-r--r-- 1 uratan zinc 0 2023-0606 12:34.56,123456000 SAMPLE
以上、とりあえず納得!
- * - * -
[2023.12.10 追記]
FreeBSD 14.0-RELEASE(i386) では /usr/local/bin/rsync だけ 秒以下分まで保持されるよう対応してました。 (タイムスタンプ比較も秒以下でさせるなら --modify-window=NUM, -@ の指定が必要)
また ファイル生成で μsec 単位までなのは 10.2R と同様のようですが、 /usr/bin/touch -d は 1nsec まで 9桁フルに扱えるようになってました。
あと上の 10.2R のテストで漏れてましたけど、ftp も秒以下分は保持しないですね。