参考のために。
/usr/local/bin/HDLraid.pm(変更後)
# # HDLraid.pm: RAID 制御 # # $Id: HDLraid.pm 2856 2006-09-15 06:45:18Z imai $ # package HDLraid; use integer; use HDLsystem; use HDLdisk; use HDLusbmap; use HDLdefines; sub debug { my $form = shift; my (undef, $filename, $line) = caller; printf STDERR "$filename: $line: $form", @_; } %raid_part = ( 'HDL-GW' => { 'md1' => { 'hda1' => 1, 'hdb1' => 1, }, 'md2' => { 'hda2' => 1, 'hdb2' => 1, }, 'md5' => { 'hda5' => 1, 'hdb5' => 1, }, 'md6' => { 'hda6' => 1, 'hdb6' => 1, }, }, 'HDL-GZ' => { 'md1' => { 'hda1' => 1, 'hdb1' => 1, 'hdc1' => 1, 'hdd1' => 1, }, 'md2' => { 'hda2' => 1, 'hdb2' => 1, 'hdc2' => 1, 'hdd2' => 1, }, 'md5' => { 'hda5' => 1, 'hdb5' => 1, 'hdc5' => 1, 'hdd5' => 1, }, 'md6' => { 'hda6' => 1, 'hdb6' => 1, 'hdc6' => 1, 'hdd6' => 1, }, }, 'HDL-GL' => { 'md1' => { 'sda1' => 1, 'sdb1' => 1, }, 'md2' => { 'sda2' => 1, 'sdb2' => 1, }, 'md5' => { 'sda5' => 1, 'sdb5' => 1, }, 'md6' => { 'sda6' => 1, 'sdb6' => 1, }, }, 'HDL-GXR' => { 'md1' => { 'sda1' => 1, 'sdb1' => 1, }, 'md2' => { 'sda2' => 1, 'sdb2' => 1, }, 'md5' => { 'sda5' => 1, 'sdb5' => 1, }, 'md6' => { 'sda6' => 1, 'sdb6' => 1, }, }, ); # # コンストラクタ # # $raid = HDLraid->new ( [write => 1], [force_write => 1] ); # sub new { my $class = shift; my %param = @_; my $self = {}; $self->{model} = &$HDLdefines::model_name(); ( !exists $raid_part{$self->{model}} ) and # RAID 非サポートモデル return undef; $self->{write} = ( $param{write}||$param{force_write} ) ? 1 : 0; $self->{change} = ( $param{force_write} ) ? 1 : 0; $self->{conf} = HDLconffile->new ( file => $HDLdefines::raid_config, write => $self->{write}, force_write => $param{force_write}, ); return undef if !defined $self->{conf}; $self->{raid2part} = $raid_part{$sys{model}}; # 逆引きテーブルの作成 while ( my ( $r, $h ) = each %{$self->{raid2part}} ) { foreach ( keys %$h ) { $self->{part2raid}->{$_} = $r; } } # 物理パーティション名 -> 仮想パーティション名の変換 my $map = HDLusbmap->new( model => $sys{model} ); ( !defined $map ) and return undef; my %map2 = $map->get(); ( !defined %map2 ) and return undef; while ( my ( $v, $p ) = each %map2 ) { next if $v =~ /hd[bcd]/; next if $v eq 'esata0'; next if !defined $p; $self->{map}->{$p} = $v; } return bless $self; } sub set { my $self = shift; my $param = shift; $self->{conf}->set ( 'raid', $param ); $self->{change} = 1; 1; } sub get { my $self = shift; $self->{conf}->get ( 'raid' ), } sub commit { my $self = shift; $self->{conf}->commit() if $self->{write} && $self->{change}; $self->{write} = $self->{change} = 0; 1; } sub DESTROY { my $self = shift; commit ( $self ) if $self->{write} && $self->{change}; 1; } # # パーティション名から,正常時に属する RAID 名を引く # # $name = $raid->part2raid ( part => 'hda1' ); # sub part2raid { my $self = shift; my %param = @_; my $part = $param{part}; !defined $part and return undef; !exists $self->{part2raid}->{$part} and return undef; $self->{part2raid}->{$part}; } # # RAID 名に対し,正常時に属するパーティションの一覧を返す # # $hash = $raid->raid2part ( [raid => 'md1'] ); # sub raid2part { my $self = shift; my %param = @_; my $raid = $param{raid}; ( !defined $raid || !exists $self->{raid2part}->{$raid} ) and return $self->{raid2part}; # ハッシュ全体 $self->{raid2part}->{$raid}; } # # spot repair 進捗 # 返り値は (スキャン開始日時, 終了日時, 修復可否フラグ) # # 修復可否フラグは # 0: 修復不要 # 1: 修復必要 # 2: 修復不可 # sub __get_scan_progress { my $self = shift; my $raid = shift; my $defect_file = "/etc/landisk/defectlist.$raid"; my ($begin, $end, $fixable ) = ( undef, undef, undef ); my %defect_list = (); ( ! -f $defect_file ) and goto end0; open my $fh, $defect_file or goto end0; my $line = <$fh>; ( $line =~ /^BEGIN:([0-9]+)/ ) or goto end1; $begin = 0 + $1; $line = <$fh>; ( $line =~ /^ABORT:/ ) and $fixable = 'aborted', goto end1; ( $line =~ /^END:([0-9]+)/ ) or goto end1; $end = 0 + $1; $line = <$fh>; ( $line =~ /^STATUS:([0-9]+)/ ) or goto end1; my $dev; my $num; while ( <$fh> ) { chomp; /^DEV:(.*)/ and $dev = $1, $defect_list{$dev} = {}, next; /^([0-9+])/ and $num = 0 + $1, $defect_list{$dev}->{$num} = 1, next; } $fixable = 'not need'; foreach my $d ( keys %defect_list ) { foreach my $b ( keys %{$defect_list{$d}} ) { $fixable = 'need fix'; my $f = 0; foreach my $d2 ( keys %defect_list ) { ( !exists $defect_list{$d2}->{$b} ) and $f = 1, last; } ( $f == 0 ) and $fixable = 'cannot fix', goto end1; } } end1: close ( $fh ); end0: return ( $begin, $end, $fixable ); } # # RAID 状態の取得 # # %status = $raid->status ( raid => 'md1' ); # sub status { my $self = shift; my %param = @_; my %ret = (); my $raid = $param{raid}; my $stt = `sudo /sbin/mdadm --detail /dev/$raid 2>/dev/null`; $? and return undef; ( $stt =~ /Raid Level : (.*)\n/ ) and $ret{level} = $1; ( $stt =~ /Array Size : ([0-9]*)/ ) and $ret{size} = sprintf('%lu',2*$1); # 512 byte 単位 if ( $stt =~ /State : (.*)\n/ ) { $ret{state} = $1; if ( $ret{state} =~ /recovering/ || $ret{state} =~ /resyncing/ ) { $ret{jstate} = '再構築中'; } elsif ( $ret{state} =~ /degraded/ ) { $ret{jstate} = '単体動作'; } elsif ( $ret{state} =~ /clean/ || $ret{state} =~ /active/ ) { $ret{jstate} = '通常動作'; } else { $ret{jstate} = '不明'; }; } ( $stt =~ /Rebuild Status : (.*) complete/ ) and $ret{rebuild_status} = $1; $ret{raid} = {}; my @lines = split ( /\n/, $stt ); foreach ( @lines ) { if ( m|(\S+ \S+) +/dev/(.*)| || m|(\S+) +/dev/(.*)| ) { my $state = $1; my $dev = $2; $dev =~ s/[0-9]+$//; $dev = $self->{map}->{$dev}; $ret{raid}->{$dev} = $state; $state =~ /active sync/ and $ret{jraid}->{$dev} = '正常', next; $state =~ /faulty/ and $ret{jraid}->{$dev} = '故障', next; $state =~ /spare rebuilding/ and $ret{jraid}->{$dev} = '再構築中', next; $ret{jraid}->{$dev} = '不明'; } } ( $ret{scan_begin}, $ret{scan_end}, $ret{scan_fixable} ) = __get_scan_progress ( $self, $param{raid} ); %ret; } # # スキャン結果のクリア # # $raid->clear_scan ( raid => 'md6' ); # sub clear_scan { my $self = shift; my %param = @_; my $defect_file = "/etc/landisk/defectlist.$param{raid}"; `sudo rm -f $defect_file 2>/dev/null`; 1; } __END__ =head1 名前 HDLraid.pm -- RAID 管理 =head2 使いかた use HDLraid; $raid = HDLraid->new (); %list = $raid->status ( raid => 'md6' ); =head1 説明 =head2 $raid = HDLraid->new (); コンストラクタです. =head2 %list = $raid->status ( raid => 'md6' ); RAID デバイスのステータスを返します. キー 値の例 説明 ------------------------------------------------------------------------------ 'raid' RAID 構成デバイスの状態 'esata1' => 'active sync' 'hda' => 'active sync' 'jraid' raid キーの日本語訳 'esata1' => '正常' 'hda' => '正常' 'state' 'clean' RAID 状態 'jstate' '通常動作' 'size' 31262208 RAID 容量.単位はセクタ数. 'level' 'raid1' 'scan_begin' 1135838361 spot repair スキャン開始時刻. UNIX 標準時 1970/01/01 00:00:00 UTCからの 経過秒数 スキャンしていない時は undef 'scan_end' 1135838673 spot repair スキャン終了時刻. UNIX 標準時. 'scan_fixable' 'cannot fix' spot repair の可否 undef: スキャン未終了 not need: 異常無し need fix: 異常あり・修復可 cannot fix: 異常あり・修復不可 aborted: スキャン中断 =head2 $raid->clear_scan ( raid => 'md6' ); spot repair スキャン結果をクリアします. =cut
/usr/local/bin/HDLdrive.pm(変更後)
# # HDLdrive.pm:: ドライブ操作 # # $Id: HDLdrive.pm 2842 2006-09-15 01:20:13Z imai $ # package HDLdrive; use integer; sub debug { my $form = shift; my (undef, $filename, $line) = caller; printf STDERR "$filename: $line: $form", @_; } # # ファイルの読み込み # sub __cat { my @file = @_; my $f; my @ret = (); foreach $f ( @file ) { ( !open ( FILE, $f ) ) and #print STDERR "fail to open $f\n"; return @ret; my @lines = <FILE>; debug ( "lines = %s", join ( '+', @lines ) ); push @ret, @lines; close ( FILE ); } @ret; } # # パーティションリスト # sub __partition_list { my $device = shift; # 引数がパーティションの場合は親デバイスのパーティションを返す $device =~ s/[0-9]+$//; my $part = `echo /sys/block/$device/${device}*`; chomp $part; $part =~ s|/sys/block/$device/||g; split ( /\s+/, $part ); } # # ベンダ・モデル名 # sub __modelname { my ( $device ) = @_; $device =~ s/[0-9]+$// if $device !~ /^sr/; my $model; ( $device =~ /^hd/ ) and # IDE ドライブ #debug("IDE\n"); ( $model ) = __cat( "/proc/ide/$device/model" ), chomp $model, return $model; # USB(SCSI) ドライブ debug("USB\n"); my ( @model ) = __cat ( "/sys/block/$device/device/vendor", "/sys/block/$device/device/model", ); chomp @model; return join ( ' ', @model ); } # # ドライブ or パーティションの容量 # sub __capacity { my $device = shift; my ($size, $path, $drive ); if ( $device !~ /^sr[0-9]+/ && $device !~ /^md[0-9]+/ && $device =~ /(.*)[0-9]+$/ ) { # パーティション名 $drive = $1; $path = "/sys/block/$drive/device/rescan"; system ( "sudo echo 1 >$path >& /dev/null" ) if -f $path; ( $size ) = __cat ( "/sys/block/$drive/$device/size" ); chomp $size; return $size; } # ドライブ名 $path = "/sys/block/$device/device/rescan"; system ( "sudo echo 1 > $path >& /dev/null" ) if -f $path; ( $size ) = __cat ( "/sys/block/$device/size" ); return $size; } @guesstable = ( [ 'ext2' => 'ext2',], [ 'ext3'=> 'ext3', ], [ 'swap file' => 'swap',], [ 'XFS' => 'xfs', ], ['ISO 9660 CD-ROM' => 'iso9660' ], ['FAT \(12 bit\)' => 'FAT12',], ['FAT \(16 bit\)' => 'FAT16',], ['FAT \(32 bit\)' => 'FAT32',], ['OEM-ID.*NTFS' => 'NTFS',], ['Minix filesystem' => 'minix' ], ['partition table' => 'partitioned',], # 怪しい.FAT かも ['x86 boot sector' => 'partitioned',], # 怪しい.FAT かも ['Claris clip art?' => 'partitioned',], # 怪しい.FAT かも ); # # ファイルシステムの推定 # sub __guess_fs { my $self = shift; my $device = shift; my $tmpfile = "/tmp/guessfs.$$"; my $fs = 'none'; system ( "sudo dd if=/dev/$device of=$tmpfile bs=64k count=1 >& /dev/null" ) and $fs = 'none', goto finish; my $guess = `file $tmpfile`; debug ( "file = $guess" ); my $p; foreach $p ( @guesstable ) { ( $guess =~ /$$p[0]/ ) and $fs = $$p[1], last; } goto finish if $fs ne 'partitioned'; # partitioned の場合 if ( 0 ) { if ( $self->{model} eq 'HDL-GL' || $self->{model} eq 'HDL-GXR' ) { # RAID ペアかどうかチェック my $root = `sudo sfdisk -d /dev/sda 2>/dev/null`; my $target = `sudo sfdisk -d /dev/$device 2> /dev/null`; $root =~ s|/dev/[a-z0-9]*||g; $target =~ s|/dev/[a-z0-9]*||g; if ( $root eq $target ) { # RAID の片割れ $fs = 'RAID'; # active かどうかチェック my $mdadm = ` sudo mdadm -D /dev/md1 2>/dev/null; \ sudo mdadm -D /dev/md2 2>/dev/null; \ sudo mdadm -D /dev/md5 2>/dev/null; \ sudo mdadm -D /dev/md6 2>/dev/null; `; $fs = ( $mdadm =~ /$device/ ) ? 'RAID_LIVE': 'RAID_DEAD'; } } } # FAT パーティションが x86 boot sector と認識される場合がある my $magic1 = `dd if=$tmpfile bs=1 skip=55 count=5 2>/dev/null`; chomp $magic1; my $magic11 = `dd if=$tmpfile bs=1 skip=54 count=5 2>/dev/null`; chomp $magic11; if ( ($magic1 eq 'FAT12')||($magic11 eq 'FAT12') ){ $fs = 'FAT12'; } elsif ( ($magic1 eq 'FAT16')||($magic11 eq 'FAT16') ) { $fs = 'FAT16'; } else { my $magic2 = `dd if=$tmpfile bs=1 skip=84 count=5 2>/dev/null`; chomp $magic2; $fs = 'FAT32' if ( $magic2 eq 'FAT32' ); } finish: system ( "sudo rm -f $tmpfile >& /dev/null" ); return $fs; } # # ファイルシステム容量・使用量・空き容量 # sub __fs_usage { my $device = shift; my $tmpname = undef; my %cap = undef; # 既に mount されているかどうか my $line; $cap{mounted} = 0; foreach $line ( __cat ( "/proc/mounts" ) ) { ( $line =~ m|/dev/$device| ) and $cap{mounted} = 1, goto mounted; } # mount されていない # 一時的に mount.まずは mount point の作成 $tmpname = "/tmp/$device.$$"; ( !mkdir $tmpname, 000 ) and #print STDERR "fail to make mount point.\n"; goto err0; system ( "sudo mount -o ro,noatime /dev/$device $tmpname" ) and # mount 失敗 #printf STDERR "fail to mount $device.\n"; goto err1; # df を実行 mounted: open ( DF, "LANG=C df --block-size=512|" ) or #print STDERR "fail to df.\n"; goto err2; while ( <DF> ) { my ( $all, $used, $free ); ( m|^/dev/$device| ) and # filesystem all used free use% mount-point\n" ( undef, $all, $used, $free ) = split ( /\s+/, $_ ), $cap{fs_all} = $all, $cap{fs_used} = $used, $cap{fs_free} = $free, debug ( "all = $all, used = $used, free = $free\n" ), last; } close DF; # ファイルシステムの推定 # reiserfs と UDF は mount してみないとわからんようだ open ( MOUNTS, "cat /proc/mounts|" ) or #print STDERR "fail to df.\n"; goto err2; while ( <MOUNTS> ) { my ( $d, $mp, $fs, $rw ) = split ( / / ); ( $d eq "/dev/$device" ) and $cap{filesystem} = $fs, last; } close MOUNTS; err2: system ( "sudo umount $tmpname" ) if ( -d $tmpname ); err1: rmdir $tmpname if ( -d $tmpname ); err0: return %cap; } # # ext2/ext3 情報 # sub __get_ext23info { my $part = shift; my %info = (); my $lines = `sudo tune2fs -l /dev/$part 2>/dev/null`; return () if $?; my $l; foreach $l ( split /[\r\n]+/, $lines ) { ( $l =~ s/^Filesystem UUID:\s+// ) and $info{filesystem_id} = $l, next; ( $l =~ s/^Last write time:\s+// ) and $info{last_mount} = $l, $info{last_write} = $l, next; ( $l = s/^Filesystem volume name:\s+// ) and $info{volume_name} = ($l ne '<none>') ? $l : '', next } %info; } # # FAT 情報 # sub __get_fatinfo { my $part = shift; my %info = (); my $tmpfile = "/tmp/tmpfile.$$"; my $lines = `sudo dd if=/dev/$part of=$tmpfile bs=64k count=1 2>/dev/null && file $tmpfile 2>/dev/null && sudo rm -f $tmpfile 2>/dev/null`; return () if $?; ( $l =~ /serial number (\S+),/ ) and $info{filesystem_id} = $1; ( $l =~ /label: \"(.+)\"/ ) and $info{volume_name} = $1; %info; } # # ディスクラベリング # %disklabel_offset = ( disklabel_magic => 0x0200, disklabel_version => 0x0204, disklabel_usage => 0x0208, disklabel_model => 0x0210, disklabel_name => 0x0300, ); %disklabel_length = ( disklabel_magic => 4, disklabel_version => 4, disklabel_usage => 4, disklabel_model => 16, disklabel_name => 256, ); sub __read_disklabel { my $self = shift; my $disk = shift; my ( $length, $result ); my %ret = (); while ( my ( $key, $offset ) = each %disklabel_offset ) { $length = 0 + $disklabel_length{$key}; $result = `sudo dd if=/dev/$disk bs=1 skip=$offset count=$length 2>/dev/null`; $result =~ s/\0+$//; $ret{$key} = $result; } return () if $ret{disklabel_magic} ne 'HDLG'; %ret; } sub __write_disklabel { my $self = shift; my $disk = shift; my %param = @_; my ( $length, $val, $fh ); $fh = undef; $param{disklabel_magic} = 'HDLG'; $param{disklabel_version} = '0001'; while ( my ( $key, $offset ) = each %disklabel_offset ) { next if !exists $param{$key}; $length = 0 + $disklabel_length{$key}; #$val = "\0" x $length; #substr ( $val, 0 ) = $param{$key}; $val = $param{$key} . ( "\0" x ( $length - length($param{$key}) ) ); open ( $fh, "|sudo dd of=/dev/$disk bs=1 seek=$offset count=$length 2>/dev/null" ) or return undef; print $fh $val; close $fh; } 1; } # # コンストラクタ # # $drive = HDLdrive->new( [write => 1], [model => 'HDL-GL'] ); # sub new { my $class = shift; my %param = @_; my $self = {}; $self->{write} = $param{write}; $self->{model} = $param{model}; $self->{change} = 0; return bless $self, $class; } # # キャッシュ情報のクリア # # $drive->uncache ( 'hda' ); # sub uncache { my $self = shift; my $drive = shift; while ( my ($k, $v) = each %{$self->{guess_fs}} ) { ( $k =~ /^$drive/ ) and delete $self->{guess_fs}->{$k} } 1; } # # %hda = $drive->get ( 'hda' ); # sub get { my $self = shift; my $name = shift; my %drive = (); return undef if !defined $name; if ( $name !~ /^sr[0-9]+/ && $name !~ /^md[0-9]+/ && $name =~ /^(.+)[0-9]+$/ ) { # パーティション my $d = $1; return () if ! -d "/sys/block/$d/$name"; } else { # ドライブ return () if ! -d "/sys/block/$name"; %drive = __read_disklabel ( $self, $name ); } $drive{device} = $name; $drive{mounted} = 0; $drive{device_list} = join ( ',', __partition_list ( $name ) ) . ','; debug ( "=== %s\n", $drive{device} ); $drive{model} = __modelname ( $drive{device} ); ( !defined $drive{model} ) and #printf STDERR "fail to get model name.\n"; return (); debug ( "=== %s\n", $drive{model} ); $drive{capacity} = __capacity ( $name ); ( !defined $drive{capacity} ) and #printf STDERR "fail to get capacity.\n"; return (); debug ( "=== %u\n", $drive{capacity} ); $drive{filesystem} = ( exists $self->{guess_fs}->{$name} ) ? $self->{guess_fs}->{$name} : ( $self->{guess_fs}->{$name} = __guess_fs ( $self, $name ) ); #( !defined $drive{filesystem} ) and #printf STDERR "warning: cannot guess filesystem.\n"; debug ( "=== %s\n", $drive{filesystem} ); #if ( ( $drive{filesystem} ne 'none' ) #&& ( $drive{filesystem} ne 'partitioned' ) ) { if ( $drive{filesystem} ne 'partitioned' ) { # ファイルシステム使用量を得る my %fs; if ( exists $self->{fs_usage}->{$name} ) { %fs = %{$self->{fs_usage}->{$name}}; } else { %fs = __fs_usage ( $name ); $self->{fs_usage} = { %fs }; } if ( !exists $fs{fs_all} ) { printf STDERR "warning: cannot get filesystem usage.\n"; } else { $drive{fs_all} = $fs{fs_all}; $drive{fs_used} = $fs{fs_used}; $drive{fs_free} = $fs{fs_free}; $drive{mounted} = $fs{mounted}; ( $drive{filesystem} eq 'none' && $fs{filesystem} ) and $drive{filesystem} = $fs{filesystem}; } if ( $drive{filesystem} =~ /^ext/ ) { my %info = __get_ext23info ( $name ); while ( my ( $k, $v ) = each %info ) { $drive{$k} = $v; } } elsif ( $drive{filesystem} =~ /^FAT/ ) { my %info = __get_fatinfo ( $name ); while ( my ( $k, $v ) = each %info ) { $drive{$k} = $v; } } } %drive; } # # $drive->set ( disk => 'hda', magic => 'HDLG', version => '0001', ... ); # sub set { my $self = shift; my %param = @_; my $disk = $param{disk}; my %p = (); delete $param{disk}; return undef if !defined $disk; ( !exists $self->{disklabel}->{$disk} ) and %p = __read_disklabel ( $self, $disk ), $self->{disklabel}->{$disk} = \%p; while ( my ( $k, $v ) = each %param ) { $self->{disklabel}->{$disk}->{$k} = $v; } $self->{change} = 1; 1; } sub commit { my $self = shift; if ( $self->{write} && $self->{change} ) { foreach ( keys %{$self->{disklabel}} ) { __write_disklabel ( $self, $_, %{$self->{disklabel}->{$_}} ); } $self->{write} = $self->{change} = 0; } 1; } sub DESTROY { my $self = shift; commit ( $self ); 1; } 1; __END__ $drive = HDLdrive->new (); foreach $j ( 'hda', 'hda1', 'hda2', 'hda3', 'hda4', 'hda5' ) { %hash = $drive->get($j); foreach $i ( keys %hash ) { printf "$j:$i = %s\n", $hash{$i}; } } __END__ =head1 名前 HDLdrive.pm -- ドライブ情報を得る =head1 使いかた use HDLdrive; $drive = HDLdrive->new(); %info = $drive->get( 'hda' ); =head1 説明 ドライブもしくはパーティションの情報を取得します. =head2 $drive = HDLdrive->new( [model => 'HDL-GL']); コンストラクタです. =head2 %info = $drive->get( 'hda' ); ドライブ情報を返します. ドライブ(例:hda)とパーティション(例:hda1)を指定した場合で,返される値が異なります. 項目 ドライブ全体 パーティション 説明 ---------------------------------------- device o o デバイス名(指定したもの) filesystem o o デバイスのファイルシステム device_list o * パーティションリスト model o * ドライブのモデル名 capacity o o ドライブorパーティションの全容量 fs_all - o ファイルシステム全容量 fs_used - o ファイルシステム使用量 fs_free - o ファイルシステム空き容量 * については,親ドライブ(例えば hda1 に対する hda)の情報です. =head3 filesystem 指定されたドライブorパーティションのファイルシステム. 値は ext2 | ext3 | xfs | minix | udf | iso9660 | FAT12 | FAT | FAT32 | NTFS | partitioned | none. =head3 capacity, fs_all, fs_used, fs_free 単位は 512 バイトです. =head1 関連ファイル 特に無し.