Issue #15615 has been reported by Glass_saga (Masaki Matsushita).

----------------------------------------
Misc #15615: File.birthtimeがLinux環境で有効なファイル作成時刻を得られなかった場合の挙動について
https://bugs.ruby-lang.org/issues/15615

* Author: Glass_saga (Masaki Matsushita)
* Status: Open
* Priority: Normal
* Assignee: 
----------------------------------------
File.birthtimeはファイルの作成時刻を返すメソッドです。
これまでLinux環境ではこのメソッドは実装されておらず、呼び出すとNotImplementedErrorが発生していましたが、r67088から一部のLinux環境でもFile.birthtimeが動作するようになりました。
Linux環境でのFile.birthtimeは、statx()というLinux 4.11から導入されたシステムコールを使うことで実装されています。

statx()には以下の特徴があります。
1. stat()では取得できなかった情報が取れる
  * ファイル作成時刻
  * 圧縮や暗号化の有無などの属性
2. どの情報に興味があるかをマスクで指定して使う
  * 指定した情報が返されるとは限らず、指定していない情報まで返される場合もある
  * 指定された情報の一部または全部を返せなかった場合でも戻り値は0であり、errnoもセットされない
3. struct statxというstruct statとは異なる構造体を返す
4. 返された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には以下のような部分があります。

```ruby
  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はどのように動作すべきかをこのチケットで議論いただければと思います。



-- 
https://bugs.ruby-lang.org/

Unsubscribe: <mailto:ruby-core-request / ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>