Perlで学ぶ「詳解 UNIXプログラミング」(その3) 第3章 ファイル入出力

はじめに

「詳解 UNIXプログラミング」の第三章を示します。

3-1標準入力ファイルがシーク可能で有るかどうかを調べる

POSIX::lseekが使えます。

#!/usr/bin/env perl
use strict;
use warnings;

use POSIX;

# 標準入力ファイルがシーク可能であるかどうかを調べる

my $off_t = POSIX::lseek(&POSIX::STDIN_FILENO, 0, &POSIX::SEEK_CUR);
if (defined $off_t) {
    print "seek OK\n";
} else {
    print "cannot seek\n";
}

3-2lseek()でファイル内部に間隙を作成する

POSIXモジュールの各種関数を使っています。
日常的にはこのような低レベルな関数を使う必要はまずないと思います。

#!/usr/bin/env perl
use strict;
use warnings;

use POSIX qw(:fcntl_h);

# lseek()でファイル内部に間隙を作成する
my $mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
my $fd = POSIX::creat("file.hole", $mode);
die "Can't create file\n" unless defined $fd;

my $buf1 = 'abcdefg';
my $buf2 = 'ABCDEFG';

my $retval;
$retval = POSIX::write($fd, $buf1, length $buf1);
die "Can't write buf1 to file\n" unless defined $retval;

POSIX::lseek($fd, 40, &POSIX::SEEK_SET);

$retval = POSIX::write($fd, $buf2, length $buf2);
die "Can't write buf2 to file\n" unless defined $retval;

POSIX::close($fd) or die "Can't close file\n";

odコマンドでちゃんと確認してみましょう。

  % od -c file.hole
  0000000   a   b   c   d   e   f   g  \0  \0  \0  \0  \0  \0  \0  \0  \0
  0000020  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0
  0000040  \0  \0  \0  \0  \0  \0  \0  \0   A   B   C   D   E   F   G
  0000057

隙間ができたことが確認できます。

3.4 指定したファイルの記述子のファイルフラグを出力する

プログラムの意味合いが変わっていますが、openの開き方を変えたら
出力結果が変わってくるのでいろいろ確認してみてください。

#!/usr/bin/env perl
use strict;
use warnings;

use Fcntl;
use POSIX;

# 指定したファイルの記述子のファイルフラグを出力する
my $file = shift or die "Usage: $0 file\n";
open my $fh, ">>", $file or die "Can't open $file: $!";
my $flag = fcntl $fh, F_GETFL, 0 or die "Can't fcntl $file: $!";

my $accmode = $flag & O_ACCMODE;
if ($accmode == O_RDONLY) {
    print "read only\n"
} elsif ($accmode == O_WRONLY) {
    print "write only\n";
} elsif ($accmode == O_RDWR) {
    print "read write\n";
}

if ($flag & O_APPEND) {
    print "append\n";
}
if ($flag & O_NONBLOCK) {
    print "nonblocking\n";
}
if ($flag & O_SYNC) {
    print "synchronous write";
}
close $fh;

3-5記述子のファイル状態フラグの複数ビットをオンにする

正しくセットできるかを確認するための処理を追加しました。
あとから変えるということはあまりないと思うので、フラグを
立てるのであれば、openするときに立てるのがいいでしょう。

#!/usr/bin/env perl
use strict;
use warnings;

use Fcntl;

# 指定したファイルの記述子のファイルフラグを出力する

my $file = shift or die "Usage: $0 file [flag]\n";
my $flag = shift || O_NONBLOCK;

open my $fh, "<", $file or die "Can't open $file: $!";
my $val = fcntl $fh, F_GETFL, 0;
die "Can't get file flag: $file\n" unless defined $val;

die "FLAG is already set\n" if ($val & $flag);

$val |= $flag;

my $retval = fcntl $fh, F_SETFL, $val;
die "Can't set file flag: $file\n" unless defined $retval;

my $check = fcntl $fh, F_GETFL, 0;
die "Can't get file flag: $file\n" unless defined $check;

print "OK set flag\n" if ($check & $flag);

close $fh;

まとめ

「詳解 UNIXプログラミング」の第三章を示しました。