Misc #15615
closedFile.birthtimeがLinux環境で有効なファイル作成時刻を得られなかった場合の挙動について
Description
File.birthtime
はファイルの作成時刻を返すメソッドです。
これまでLinux環境ではこのメソッドは実装されておらず、呼び出すとNotImplementedError
が発生していましたが、r67088から一部のLinux環境でもFile.birthtime
が動作するようになりました。
Linux環境でのFile.birthtime
は、statx()
というLinux 4.11から導入されたシステムコールを使うことで実装されています。
statx()
には以下の特徴があります。
-
stat()
では取得できなかった情報が取れる
- ファイル作成時刻
- 圧縮や暗号化の有無などの属性
- どの情報に興味があるかをマスクで指定して使う
- 指定した情報が返されるとは限らず、指定していない情報まで返される場合もある
- 指定された情報の一部または全部を返せなかった場合でも戻り値は0であり、
errno
もセットされない
-
struct statx
というstruct stat
とは異なる構造体を返す - 返された
statx
構造体のうち、どの情報が有効であるかはstx_mask
というメンバに格納される
statx()
でファイルの作成時刻が得られるかどうかはファイルシステム依存であり、有効な値が得られない場合があります。
2.に挙げたように、statx()
はこの場合でも0を返しerrno
もセットされません。
r67088では、stx_mask
を参照して作成時刻が有効であるかどうかを確かめ、無効であった場合はNotImplementedError
をraise
します。
File.birthtime
はTime
を返すことが期待されているので、値が無効だからといってnil
を返す訳にもいかないと考えたからです。
しかし、NotImplementedError
はプラットフォーム依存で機能の実装・未実装が異なる場合に用いられていることが多いようです。
少なくともfile.cの他の部分ではNotImplementedError
はそのように使われています。
また、spec/ruby/core/file/birthtime_spec.rbには以下のような部分があります。
platform_is :linux, :openbsd do
it "raises an NotImplementedError" do
lambda { File.birthtime(@file) }.should raise_error(NotImplementedError)
end
end
このテスト自体の是非はともかく、このようにNotImplementedError
がプラットフォーム依存で発生するものと期待されている面はあるのではないかと思います。
そう考えると、ファイルシステム依存でNotImplementedError
を発生させることは好ましくないかもしれません。
※ r67115ではErrno::ENOSYS
を発生させるよう変更されました。
このような状況で、statx()
で有効なファイル作成時刻が得られなかった場合File.birthtime
はどのように動作すべきかをこのチケットで議論いただければと思います。
Updated by Glass_saga (Masaki Matsushita) almost 6 years ago
- Related to Misc #15614: DevelopersMeeting20190311Japan added
Updated by Glass_saga (Masaki Matsushita) almost 6 years ago
- Related to deleted (Misc #15614: DevelopersMeeting20190311Japan)
Updated by nobu (Nobuyoshi Nakada) almost 6 years ago
- Description updated (diff)
とりあえずNotImplementedError
とも一番近そうなENOSYS
を投げるようにしましたが、本来セットされていないerrno
を装うよりはRuntimeError
あたりのほうがいいのではないかと思います。
もしくは次点でnil
。
Updated by Glass_saga (Masaki Matsushita) almost 6 years ago
- Status changed from Open to Closed
Applied in changeset trunk|r67338.
file.c: raise NotImplementedError instread of Errno::ENOSYS
[Misc #15615]