このBlogは移転しました。今後は aish.dev を御覧ください。

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

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

import os
try:
    os.lseek(0,0,os.SEEK_CUR)
except OSError:
    print "cannot seek"
else:
    print "seek OK"

lseek()が失敗すると、OSError例外が発生する。

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

import os, stat, sys

def creat(filename, mode):
    return os.open(filename, os.O_WRONLY | os.O_CREAT | os.O_TRUNC, mode)

FILE_MODE = stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IROTH
try:
    fd = creat("file.hole", FILE_MODE)
except Exception:
    sys.exit("create error")

buf1 = "abcdefg"
buf2 = "ABCDEFG"

try:
    os.write(fd, buf1)
except Exception:
    sys.exit("buf1 write error")

try:
    os.lseek(fd, 40, os.SEEK_SET)
except Exception:
    sys.exit("lseek error")

try:
    os.write(fd, buf2)
except Exception:
    sys.exit("buf2 write error")

Pythonではcreat()が提供されていないため、ここでは独自にcreat()を実装した。

わざわざ独立した関数を実装するほどのことでもないのだが、creat()は非常に古く、歴史のある関数であり、かのUnix開発者 Ken Thompson が「もう一度Unixを作り直すとしたら、createを付けたい」と語ったことがあるほど由緒正しい関数であるので、敬意を表して特に独立した関数として定義した。

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

import fcntl, sys, os

O_ACCMODE = os.O_RDONLY | os.O_WRONLY | os.O_RDWR

if len(sys.argv) != 2:
    sys.exit("usage: python scr3-4.py <descriptor#>")
try:
    val = fcntl.fcntl(int(sys.argv[1]), fcntl.F_GETFL, 0)
except Exception:
    sys.exit("fcntl error for fd {0}".format(sys.argv[1]))

accmode = val & O_ACCMODE
if accmode == os.O_RDONLY:
    print "read only",
elif accmode == os.O_WRONLY:
    print "write only",
elif accmode == os.O_RDWR:
    print "read write",

if val & os.O_APPEND:
    print " append",
if val & os.O_NONBLOCK:
   print " nonblocking",
if val & os.O_SYNC:
   print " synchronous write",
print

fcntl()Pythonではfcntlモジュールに定義されている。os.O_ACCMODEが定義されていないため、ここでは独自に定義した。

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

import fcntl, sys

if len(sys.argv) != 3:
    sys.exit("usage: python scr3-5.py <descriptor#> flag")

fd = int(sys.argv[1])
flag = int(sys.argv[2])

try:
    val = fcntl.fcntl(fd, fcntl.F_GETFL, 0)
except Exception:
    sys.exit("fcntl get error for fd {0}".format(fd))

val |= flag

try:
    fcntl.fcntl(fd, fcntl.F_SETFL, val)
except Exception:
    sys.exit("fcntl set error for fd {0}".format(fd))