目次
背景最近、全然書かなくなってきたので、復習?というかいま(2007-03-13)どんな感じの書き方が 自分のトレンドなのかを残しておいて、あとで一人ニヤニヤwするためにmkfileを書いてみました。 元々の動機は Solarisにある mkfile(1)が Linuxになかったので、 きっと類するのはあるかなと思いつつ、perlで書いてみようということでできた産物ですw
win/linux/solarisでは動くことを確認してます。 ただ win/unixのどちらにも対応する為に関数のreferenceを使っているので、 perlのversionは 5.6以上必須です。 ちなみにsolarisのmkfileの実装をパクってます。
解説TBD
コード#!/usr/bin/env perl use strict; use Fcntl qw(:seek); use Config; $::size; @::files; $::cmd = "mkfile.pl"; $::debug = 0; $::nobytes = 0; $::verbose = 0; $::onekbuf; $::onekb = 1024; $::devnull; $::devnullpath = "/dev/null"; $::osname = $Config{osname}; &parseArgs(@ARGV); &init(); &mainloop(); $::init; $::generateBuffer; sub mainloop { my $f; foreach $f ( @::files ) { &validateFile($f); &doIt($f); } } sub init { &_init(); &$::init(); } sub doIt { my $file = $_[0]; my ($fd, $loop, $wbuf); $loop = 1; if ( $::size > $::onekb ) { my $loopSp = $::size % $::onekb; $loop = ( ($::size - $::loopSp) / $::onekb ); } open(WR, ">$file") or die "$!\n"; $fd = \*WR; if ( $::nobytes ) { my $sentinel = pack("C", 0x0); seek($fd, $::size-1, SEEK_SET) or die "$!\n"; print $fd "$sentinel"; } else { printf("loop : %d\n", $loop) if ( $::debug ); my ($alreadyWrite, $requestLength); # init $alreadyWrite = 0; do { $requestLength = $loop > 1 ? $::onekb : ($::size - $alreadyWrite); $wbuf = &$::generateBuffer($requestLength); print $fd "$wbuf"; $alreadyWrite += $requestLength; $loop -= 1; } while ( $loop > 0 ); } close($fd); if ( $::verbose ) { printf("%s %d bytes\n", $file, $::size); } } sub validateSize { my $eflag = 0; my $backup = $_; my ($s); printf("\$::size = %s\n", $::size) if ( $::debug ); if ( $::size =~ /([0-9]{1,})([a-zA-Z])/ ) { $s = $1; $_ = $2; VALIDATESIZE_SW:{ /m/ && do { $::size = $s * 1024 * 1024; last VALIDATESIZE_SW; }; /k/ && do { $::size = $s * 1024; last VALIDATESIZE_SW; }; /.*/ && do { printf STDERR ("%s is NOT match suffix\n", $_); exit(1); last VALIDATESIZE_SW; }; };# end of VALIDATESIZE_SW } elsif ( $::size =~ /[0-9]{1,}/ ) { # do nothing } else { $eflag = 1; } if ( $::size < 1 ) { printf STDERR ("%d is lower than 0\n", $::size); $eflag = 1; } &usage() if ( $eflag == 1 ); $_ = $backup; } sub validateFile { my $file = $_[0]; # windows is NOT suppoted printf("\$file = %s\n", $file) if ( $::debug ); my @_p = split(/\//, $file); my ($i, $pp); foreach $i ( 0 .. $#_p-1 ) { $pp .= "$_p[$i]/"; } if ( defined($pp) && !(-e $pp) ) { printf STDERR ("Directory %s is NOT exist\n", $pp); exit(1); } } sub usage { print <<"EOF"; Usage: $::cmd [-nv] <size>[k|m] <name1> [<name2>] ... -n : specified size. suffix 'k' or 'm' can be parsed. -v : verbose. Report the names and size of craeted file. EOF exit(1); } sub parseArgs { my @argv = @_; my $backup = $_; my ($i, $st); my @flags = (); if ( $argv[0] =~ /^\-.*$/ ) { @flags = split(//, $argv[0]); foreach ( (@flags)[1 .. $#flags] ) { GETOPT_SW:{ /n/ && do { $::nobytes = 1; last GETOPT_SW; }; /v/ && do { $::verbose = 1; last GETOPT_SW; }; /.*/ && do { printf("illegal option %s\n", $_); &usage(); last GETOPT_SW; }; };# end of GETOPT_SW } } $st = ( $#flags == -1 ) ? 0 : 1; $::size = $argv[$st]; &validateSize(); foreach $i ( $st+1 .. $#argv ) { push(@::files, $argv[$i]); } &usage() if ( !defined($::size) || $#::files < 0 ); printf("-n : %d -v : %d\n", $::nobytes, $::verbose) if ( $::debug ); $_ = $backup; } # default impl /w /dev/null sub init_unix { my $rbuf; open(ZERO, "/dev/null") or die "$!\n"; $::devnull = \*ZERO; read(ZERO, $rbuf, 1024); $::onekbuf = pack("C1024", $rbuf); } sub generateBuffer_unix { my $rbuf; my $buflen = $_[0]; my $pstr = sprintf("C%d", $buflen); printf("alloc $buflen PACK str = %s\n", $pstr) if ( $::debug ); if ( $buflen == $::onekb ) { $rbuf = $::onekbuf; } else { my $t; read($::devnull, $t, $buflen); $rbuf = pack($pstr, $t); } return $rbuf; } # alternate impl if /dev/null does NOT exist. sub init_win { my @bzeros = ( 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, ); my $i = 8; my @zeros; do { push(@zeros, @bzeros); $i -= 1; } while ( $i > 0 ); $::onekbuf = pack("C1024", @zeros); } sub generateBuffer_win { my $buf; my $buflen = $_[0]; my $pstr = sprintf("C%d", $buflen); my $zero = pack("C", 0x0); my @zeros = (); printf("alloc $buflen PACK str = %s\n", $pstr) if ( $::debug ); if ( $buflen == $::onekb ) { $buf = $::onekbuf; } else { while ( $buflen > 0 ) { push(@zeros, $zero); $buflen -= 1; } $buf = pack($pstr, @zeros); } return $buf; } sub _init { printf("osname = %s\n", $::osname) if ( $::debug ); if ( $::osname =~ /.*windows.*/i ) { $::init = \&init_win; $::generateBuffer = \&generateBuffer_win; } else { $::init = \&init_unix; $::generateBuffer = \&generateBuffer_unix; } } |