Feature #9772

IO#statfs and File::Statfs

Added by Yui NARUSE 10 months ago. Updated 10 months ago.

[ruby-dev:48121]
Status:Rejected
Priority:Normal
Assignee:Yukihiro Matsumoto

Description

IO#statfs and File::Statfs を追加しませんか。
(テストで statfs.f_type が必要だったのでとりあえず追加してしまっていますが)

statfs(2) は Unix 系 OS でそこそこ普及している、あるパスが属するファイルシステムについての情報を得るためのシステムコールです。
OS によって多少差がありますが、だいたい以下の様な情報が得られます。

 struct statfs {
 uint32_t f_type;                /* type of filesystem */
 uint64_t f_bsize;               /* filesystem fragment size */
 uint64_t f_blocks;              /* total data blocks in filesystem */
 uint64_t f_bfree;               /* free blocks in filesystem */
 int64_t  f_bavail;              /* free blocks avail to non-superuser */
 uint64_t f_files;               /* total file nodes in filesystem */
 int64_t  f_ffree;               /* free nodes avail to non-superuser */
 char      f_fstypename[MFSNAMELEN]; /* filesystem type name */
 };

f_type の値が OS 依存だったり、Linux 以外だとそもそもどれがどの値かきちんと定義されていないとか
ツッコミどころの多い API ではあるのですが、他では得られない情報が得られます。

たとえば、以前から CRuby で使われている用途としては、あるファイルの乗っているファイルシステムが、
HFS+ かどうかがわかります。言い換えると、ファイル名が正規化されているかどうかがわかります。
ありがちな反論として、書き込めば正規化されるかわかるだろうというのがありえますが、
目当てのファイルと同じディレクトリに書き込めるとは限りません。
違うディレクトリだと別のファイルシステムがマウントされている可能性があります。

なお今回の用途は、SEEK_DATA/SEEK_HOLEができるか否かを、実際にやってみる以外の方法で知りたかった、というものです。
(Rubyのテストなのにやってみて調べるではテストにあまりならない)


Related issues

Related to Ruby trunk - Bug #9788: TestFile#test_statfs = Bad System Call on Solaris Closed 04/30/2014
Related to Ruby trunk - Bug #9789: Error in TestIO#test_seek_symwhence and TestIO#test_seek ... Closed 04/30/2014

Associated revisions

Revision 46042
Added by Yui NARUSE 10 months ago

revert File::Statfs [Feature #9772]

Revision 46042
Added by Yui NARUSE 10 months ago

revert File::Statfs [Feature #9772]

History

#1 Updated by Akira Tanaka 10 months ago

ruby-core:62137 で Eric Wong も尋ねていますが、なぜ POSIX で定義されている statvfs じゃなくて、statfs なのか、というのは私も最初に疑問に思いました。

理由を参照できる形で残しておくのは重要だと思うので、説明を書いていただけないでしょうか。

そして、その理由があったとしても、API としては statvfs という名前にして、
statfs が存在する環境ではより多くの情報がなぜか取得できるとした方がいいのではないかという気がします。
(理由がないのであれば、もちろん statvfs にすべきだと思います。)

#2 Updated by Kazuhiro NISHIYAMA 10 months ago

  • Description updated (diff)

#3 Updated by Motohiro KOSAKI 10 months ago

POSIX的には、statvfsで取れるのは以下のメンバで他はoptional。つまり一番欲しいfs typeが
取れないわけです。
なので、statvfsはmisleadingだと思います。

それよりもstatfsで有益な情報がとれるOSは結局どのぐらいあるのか。が焦点ではないかと思います。
プラットフォーム依存なのは最初からわかっているんだし。

unsigned long f_bsize File system block size.
unsigned long f_frsize Fundamental file system block size.
fsblkcnt_t f_blocks Total number of blocks on file system in units of f_frsize.
fsblkcnt_t f_bfree Total number of free blocks.
fsblkcnt_t f_bavail Number of free blocks available to
non-privileged process.
fsfilcnt_t f_files Total number of file serial numbers.
fsfilcnt_t f_ffree Total number of free file serial numbers.
fsfilcnt_t f_favail Number of file serial numbers available to
non-privileged process.
unsigned long f_fsid File system ID.
unsigned long f_flag Bit mask of f_flag values.
unsigned long f_namemax Maximum filename length.

#4 Updated by Akira Tanaka 10 months ago

こういうときは先人の知恵ということで探してみると coreutils の src/stat.h になにかそれっぽいコメントがありました。

 212 /* Return the type of the specified file system.
 213    Some systems have statfvs.f_basetype[FSTYPSZ] (AIX, HP-UX, and Solaris).
 214    Others have statvfs.f_fstypename[_VFS_NAMELEN] (NetBSD 3.0).
 215    Others have statfs.f_fstypename[MFSNAMELEN] (NetBSD 1.5.2).
 216    Still others have neither and have to get by with f_type (GNU/Linux).
 217    But f_type may only exist in statfs (Cygwin).  */

http://git.savannah.gnu.org/gitweb/?p=coreutils.git;a=blob;f=src/stat.c;h=7d43eb55510372e18cc1129db269586710d28229;hb=HEAD#l212

仮に proprietary なのは気にしないとしても、NetBSD はどうなのかなぁ。

#5 Updated by Motohiro KOSAKI 10 months ago

2014-04-24 19:11 GMT-04:00 akr@fsij.org:

Issue #9772 has been updated by Akira Tanaka.

こういうときは先人の知恵ということで探してみると coreutils の src/stat.h になにかそれっぽいコメントがありました。

 212 /* Return the type of the specified file system.
 213    Some systems have statfvs.f_basetype[FSTYPSZ] (AIX, HP-UX, and Solaris).
 214    Others have statvfs.f_fstypename[_VFS_NAMELEN] (NetBSD 3.0).
 215    Others have statfs.f_fstypename[MFSNAMELEN] (NetBSD 1.5.2).
 216    Still others have neither and have to get by with f_type (GNU/Linux).
 217    But f_type may only exist in statfs (Cygwin).  */

http://git.savannah.gnu.org/gitweb/?p=coreutils.git;a=blob;f=src/stat.c;h=7d43eb55510372e18cc1129db269586710d28229;hb=HEAD#l212

仮に proprietary なのは気にしないとしても、NetBSD はどうなのかなぁ。

ああ、statvfsにメンバ追加のほうが世の中で主流なのですね。じゃあ、わたしの主張は取り下げます

#6 Updated by Takahiro Kambe 10 months ago

In message redmine.journal-46305.20140424231120.f745bb8a50ac0750@ruby-lang.org
on Thu, 24 Apr 2014 23:11:20 +0000,
akr@fsij.org wrote:

214 Others have statvfs.f_fstypename_VFS_NAMELEN.
215 Others have statfs.f_fstypenameMFSNAMELEN.
216 Still others have neither and have to get by with f_type (GNU/Linux).
217 But f_type may only exist in statfs (Cygwin). */
```

http://git.savannah.gnu.org/gitweb/?p=coreutils.git;a=blob;f=src/stat.c;h=7d43eb55510372e18cc1129db269586710d28229;hb=HEAD#l212

仮に proprietary なのは気にしないとしても、NetBSD はどうなのかなぁ。
「NetBSD はどうなのかなぁ。」とは、どのような意味でしょう??

--
神戸 隆博 / Takahiro Kambe

#7 Updated by Akira Tanaka 10 months ago

Takahiro Kambe wrote:

「NetBSD はどうなのかなぁ。」とは、どのような意味でしょう??

NetBSD で動かないのはよろしくないんじゃないか、という意味です。

#8 Updated by Yui NARUSE 10 months ago

Akira Tanaka wrote:

ruby-core:62137 で Eric Wong も尋ねていますが、なぜ POSIX で定義されている statvfs じゃなくて、statfs なのか、というのは私も最初に疑問に思いました。

理由を参照できる形で残しておくのは重要だと思うので、説明を書いていただけないでしょうか。

statfs では f_type の類がとれないからですね。

そして、その理由があったとしても、API としては statvfs という名前にして、
statfs が存在する環境ではより多くの情報がなぜか取得できるとした方がいいのではないかという気がします。
(理由がないのであれば、もちろん statvfs にすべきだと思います。)

うーん、ファイルシステムの情報であって特別VFSの情報ってわけでもないしなぁ、
と思いつつPythonさんを見るとos.statvfsなんですね。
https://docs.python.org/3/library/os.html?highlight=statvfs#os.statvfs

Motohiro KOSAKI wrote:

ああ、statvfsにメンバ追加のほうが世の中で主流なのですね。じゃあ、わたしの主張は取り下げます

statfs は残しつつ、statvfsでは標準のメンバしか出さないLinux, FreeBSD, Darwin, OpenBSDと、
statvfs に寄せた上で独自拡張するプロプライエタリ(と、NetBSD)って読むのが正しいんじゃないですかね。

なお、NetBSDとOpenBSDでは動くようにした…はずです。

#9 Updated by Naohisa Goto 10 months ago

  • Related to Bug #9788: TestFile#test_statfs = Bad System Call on Solaris added

#10 Updated by Takahiro Kambe 10 months ago

In message redmine.journal-46331.20140426142125.1b2e3962cfe9fb0b@ruby-lang.org
on Sat, 26 Apr 2014 14:21:25 +0000,
akr@fsij.org wrote:

Issue #9772 has been updated by Akira Tanaka.

Takahiro Kambe wrote:

「NetBSD はどうなのかなぁ。」とは、どのような意味でしょう??

NetBSD で動かないのはよろしくないんじゃないか、という意味です。
あ、そういう意味でしたか。

NetBSDはstatfs(2)を捨ててstatvfs(2)にしたとき、ソースレベルでは
statfs(2)を完全に捨ててしまいました。

--
神戸 隆博 / Takahiro Kambe

#11 Updated by Naohisa Goto 10 months ago

  • Related to Bug #9789: Error in TestIO#test_seek_symwhence and TestIO#test_seek on systems without File::Statfs#type (e.g. Solaris) added

#12 Updated by Daniel Berger 10 months ago

Also, for reference see the sys-filesystem gem. :)

#13 Updated by Naohisa Goto 10 months ago

r45790 にて、File::Statfs#fstypename を AIX, HP-UX, Solaris でも使えるようにしてみました。(ただし動作確認は Solaris のみ。)
struct statvfs.f_basetype を struct statfs.f_fstypename の代替として使用しています。

#14 Updated by Akira Tanaka 10 months ago

Yui NARUSE wrote:

statfs では f_type の類がとれないからですね。

なるほど。

では、IO#statfs では f_type の類は必須で、
f_type の類が提供されない環境では statvfs があっても
IO#statfs は提供しないということでしょうか?

なお、NetBSDとOpenBSDでは動くようにした…はずです。

OpenBSD 5.5 が出たので記念にインストールして試してみたところ、コンパイルできない感じです。

% uname -mrsv
OpenBSD 5.5 GENERIC#271 amd64
% make up all
Updating '.':
At revision 45793.
./revision.h unchanged
        CC = gcc
        LD = ld
        LDSHARED = gcc -shared 
        CFLAGS = -O0 -fno-fast-math -ggdb3 -Wall -Wextra -Wno-unused-parameter -Wno-parentheses -Wno-long-long -Wno-missing-field-initializers -Wunused-variable -Werror=pointer-arith -Werror=write-strings -Werror=declaration-after-statement -Werror=implicit-function-declaration -Werror=deprecated-declarations -std=iso9899:1999 
        XCFLAGS = -D_FORTIFY_SOURCE=2 -fstack-protector -fno-strict-overflow -fvisibility=hidden -DRUBY_EXPORT -fPIE
        CPPFLAGS = -DRUBY_DEBUG_ENV   -I. -I.ext/include/x86_64-openbsd5.5 -I./include -I.
        DLDFLAGS = -fstack-protector -pie  
        SOLIBS = 
Reading specs from /usr/lib/gcc-lib/amd64-unknown-openbsd5.5/4.2.1/specs
Target: amd64-unknown-openbsd5.5
Configured with: OpenBSD/amd64 system compiler
Thread model: posix
gcc version 4.2.1 20070719 
compiling file.c
file.c: In function 'rb_io_statfs':
file.c:1153: error: storage size of 'st' isn't known
file.c:1161: warning: implicit declaration of function 'fstatvfs'
file.c:1153: warning: unused variable 'st'
file.c: In function 'statfs_memsize':
file.c:5358: error: invalid application of 'sizeof' to incomplete type 'statfs_t' 
file.c: In function 'statfs_new_0':
file.c:5373: error: invalid application of 'sizeof' to incomplete type 'statfs_t' 
file.c:5374: error: dereferencing pointer to incomplete type
file.c:5374: error: dereferencing pointer to incomplete type
file.c: In function 'rb_statfs_init':
file.c:5423: error: storage size of 'st' isn't known
file.c:5428: warning: implicit declaration of function 'statvfs'
file.c:5435: error: invalid application of 'sizeof' to incomplete type 'statfs_t' 
file.c:5436: error: dereferencing pointer to incomplete type
file.c:5423: warning: unused variable 'st'
file.c: In function 'rb_statfs_init_copy':
file.c:5454: error: invalid application of 'sizeof' to incomplete type 'statfs_t' 
file.c:5455: error: dereferencing pointer to incomplete type
file.c:5455: error: dereferencing pointer to incomplete type
file.c: In function 'statfs_bsize':
file.c:5495: error: dereferencing pointer to incomplete type
file.c: In function 'statfs_blocks':
file.c:5509: error: dereferencing pointer to incomplete type
file.c: In function 'statfs_bfree':
file.c:5523: error: dereferencing pointer to incomplete type
file.c: In function 'statfs_bavail':
file.c:5537: error: dereferencing pointer to incomplete type
file.c: In function 'statfs_files':
file.c:5551: error: dereferencing pointer to incomplete type
file.c: In function 'statfs_ffree':
file.c:5565: error: dereferencing pointer to incomplete type
file.c: In function 'statfs_inspect':
file.c:5627: error: dereferencing pointer to incomplete type
file.c:5628: error: dereferencing pointer to incomplete type
file.c:5628: error: dereferencing pointer to incomplete type
file.c:5628: error: dereferencing pointer to incomplete type
file.c:5629: error: dereferencing pointer to incomplete type
file.c:5629: error: dereferencing pointer to incomplete type
*** Error 1 in /home/akr/tst1/ruby (Makefile:330 'file.o': @ gcc -O0 -fno-fast-math -ggdb3 -Wall -Wextra -Wno-unused-parameter -Wno-parenthe...)
zsh: exit 1     make up all
% egrep -i 'statv?fs' .ext/include/x86_64-openbsd5.5/ruby/config.h 
#define HAVE_STRUCT_STATVFS 1
#define HAVE_FSTATFS 1
#define HAVE_FSTATVFS 1

ヘッダファイルが足りないという感じかなぁ

#15 Updated by Yui NARUSE 10 months ago

Akira Tanaka wrote:

Yui NARUSE wrote:

statfs では f_type の類がとれないからですね。

なるほど。

では、IO#statfs では f_type の類は必須で、
f_type の類が提供されない環境では statvfs があっても
IO#statfs は提供しないということでしょうか?

他の方が互換実装を提供することに反対はしませんが、わたしがわざわざ実装する動機は欠けますね。

なお、NetBSDとOpenBSDでは動くようにした…はずです。

OpenBSD 5.5 が出たので記念にインストールして試してみたところ、コンパイルできない感じです。

ヘッダファイルが足りないという感じかなぁ

r45873で直しました。

#16 Updated by Akira Tanaka 10 months ago

Yui NARUSE wrote:

他の方が互換実装を提供することに反対はしませんが、わたしがわざわざ実装する動機は欠けますね。

とすると、statvfs があるときは少なくとも statvfs の情報は提供することになるような気がしますね。
statvfs は POSIX で標準化されているので、結局、提案されているメソッドの実際の動作は
statvfs + 環境依存の様々な情報、ということになりそうな気がします。

そうすると常に提供されると期待できるのは statvfs の部分なわけで、やっぱ名前は statvfs のほうがいい気がするなぁ。
(statfs を使ったときに f_fsid をどう提供するかという問題はあります。)

あるいは、もっと動機に率直なメソッドにしてしまうという手もあって、
ファイルシステムの種類を返すメソッドというように限定してしまうのもいいかもしれません。
そうすると、statfs/statvfs 以外の方法でファイルシステムの種類を得る実装も扱えるようになります。
たとえば、getmntent とか。

実際に statfs/statvfs がなくて getmntent がある環境など、そういう備えが役に立つ環境があるかどうかは知りませんが。

いや、(GNU/Linux の) getmntent は /etc/mtab を読むから、
もしかして ext2/3/4 が判別できるという利点があるかも? (確認してません)

#17 Updated by Yui NARUSE 10 months ago

Akira Tanaka wrote:

Yui NARUSE wrote:

他の方が互換実装を提供することに反対はしませんが、わたしがわざわざ実装する動機は欠けますね。

とすると、statvfs があるときは少なくとも statvfs の情報は提供することになるような気がしますね。
statvfs は POSIX で標準化されているので、結局、提案されているメソッドの実際の動作は
statvfs + 環境依存の様々な情報、ということになりそうな気がします。

そうすると常に提供されると期待できるのは statvfs の部分なわけで、やっぱ名前は statvfs のほうがいい気がするなぁ。
(statfs を使ったときに f_fsid をどう提供するかという問題はあります。)

まぁ採否も含めてまつもとさんに判断頂く際に、名前も決めていただくってことでいいかと。

あるいは、もっと動機に率直なメソッドにしてしまうという手もあって、
ファイルシステムの種類を返すメソッドというように限定してしまうのもいいかもしれません。
そうすると、statfs/statvfs 以外の方法でファイルシステムの種類を得る実装も扱えるようになります。
たとえば、getmntent とか。

実際に statfs/statvfs がなくて getmntent がある環境など、そういう備えが役に立つ環境があるかどうかは知りませんが。

いや、(GNU/Linux の) getmntent は /etc/mtab を読むから、
もしかして ext2/3/4 が判別できるという利点があるかも? (確認してません)

ふむ、確かに今のわたしのユースケースだとこちらのほうが適している気はしますね。
こちらはこちらでいじってみます。
こっちだと Etc.mntinfo とか Etc.df とかですかねぇ

Also available in: Atom PDF