Feature #9772
closedIO#statfs and File::Statfs
Added by naruse (Yui NARUSE) over 10 years ago. Updated over 10 years ago.
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のテストなのにやってみて調べるではテストにあまりならない)
Updated by akr (Akira Tanaka) over 10 years ago
ruby-core:62137 で Eric Wong も尋ねていますが、なぜ POSIX で定義されている statvfs じゃなくて、statfs なのか、というのは私も最初に疑問に思いました。
理由を参照できる形で残しておくのは重要だと思うので、説明を書いていただけないでしょうか。
そして、その理由があったとしても、API としては statvfs という名前にして、
statfs が存在する環境ではより多くの情報がなぜか取得できるとした方がいいのではないかという気がします。
(理由がないのであれば、もちろん statvfs にすべきだと思います。)
Updated by znz (Kazuhiro NISHIYAMA) over 10 years ago
- Description updated (diff)
Updated by kosaki (Motohiro KOSAKI) over 10 years 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.
Updated by akr (Akira Tanaka) over 10 years 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). */
仮に proprietary なのは気にしないとしても、NetBSD はどうなのかなぁ。
Updated by kosaki (Motohiro KOSAKI) over 10 years 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). */
仮に proprietary なのは気にしないとしても、NetBSD はどうなのかなぁ。
ああ、statvfsにメンバ追加のほうが世の中で主流なのですね。じゃあ、わたしの主張は取り下げます
Updated by taca (Takahiro Kambe) over 10 years 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] (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 はどうなのかなぁ。
「NetBSD はどうなのかなぁ。」とは、どのような意味でしょう??
--
神戸 隆博 / Takahiro Kambe
Updated by akr (Akira Tanaka) over 10 years ago
Takahiro Kambe wrote:
「NetBSD はどうなのかなぁ。」とは、どのような意味でしょう??
NetBSD で動かないのはよろしくないんじゃないか、という意味です。
Updated by naruse (Yui NARUSE) over 10 years ago
Akira Tanaka wrote:
ruby-core:62137 で Eric Wong も尋ねていますが、なぜ POSIX で定義されている statvfs じゃなくて、statfs なのか、というのは私も最初に疑問に思いました。
理由を参照できる形で残しておくのは重要だと思うので、説明を書いていただけないでしょうか。
statfs では f_type の類がとれないからですね。[ruby-core:62150]
そして、その理由があったとしても、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では動くようにした…はずです。
Updated by ngoto (Naohisa Goto) over 10 years ago
- Related to Bug #9788: TestFile#test_statfs = Bad System Call on Solaris added
Updated by taca (Takahiro Kambe) over 10 years 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
Updated by ngoto (Naohisa Goto) over 10 years 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
Updated by djberg96 (Daniel Berger) over 10 years ago
Also, for reference see the sys-filesystem gem. :)
Updated by ngoto (Naohisa Goto) over 10 years ago
r45790 にて、File::Statfs#fstypename を AIX, HP-UX, Solaris でも使えるようにしてみました。(ただし動作確認は Solaris のみ。)
struct statvfs.f_basetype を struct statfs.f_fstypename の代替として使用しています。
Updated by akr (Akira Tanaka) over 10 years ago
Yui NARUSE wrote:
statfs では f_type の類がとれないからですね。[ruby-core:62150]
なるほど。
では、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
ヘッダファイルが足りないという感じかなぁ
Updated by naruse (Yui NARUSE) over 10 years ago
Akira Tanaka wrote:
Yui NARUSE wrote:
statfs では f_type の類がとれないからですね。[ruby-core:62150]
なるほど。
では、IO#statfs では f_type の類は必須で、
f_type の類が提供されない環境では statvfs があっても
IO#statfs は提供しないということでしょうか?
他の方が互換実装を提供することに反対はしませんが、わたしがわざわざ実装する動機は欠けますね。
なお、NetBSDとOpenBSDでは動くようにした…はずです。
OpenBSD 5.5 が出たので記念にインストールして試してみたところ、コンパイルできない感じです。
ヘッダファイルが足りないという感じかなぁ
r45873で直しました。
Updated by akr (Akira Tanaka) over 10 years 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 が判別できるという利点があるかも? (確認してません)
Updated by naruse (Yui NARUSE) over 10 years 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 とかですかねぇ
Updated by naruse (Yui NARUSE) over 10 years ago
- Status changed from Assigned to Rejected