lseek -
ファイルの読み書きオフセットの位置を変える
#include <sys/types.h>
#include <unistd.h>
off_t lseek(int fd, off_t offset, int
whence );
lseek() repositions the file offset of the open file description
associated with the file descriptor
fd to the argument
offset
according to the directive
whence as follows:
- SEEK_SET
- ファイルオフセットは
offset
バイトに設定される。
- SEEK_CUR
- ファイルオフセットは現在位置に
offset
バイトを足した位置になる。
- SEEK_END
- ファイルオフセットはファイルのサイズに
offset
バイトを足した位置になる。
lseek()
は、オフセットをファイルの末尾を越えた位置に設定できる
(但し、これによりファイルのサイズが変わらない)。
もしデータがこのオフセット位置以降に書き込まれた場合、
間の空隙の部分 ("穴
(hole)")
の読み出しがあると、
実際にそこにデータを書き込まれるまではヌルバイト
('\0') の列が返される。
Linux バージョン 3.1
以降では、
whence
に以下の値も指定することができる。
- SEEK_DATA
- ファイルオフセットを
offset
以上で次にデータがある位置に設定する。
offset
がデータを指している場合には、
ファイルオフセットは
offset
に設定される。
- SEEK_HOLE
- ファイルオフセットを、
位置が offset
以上の次のホール (hole)
に設定する。 offset
がホールの内部にある場合は、ファイルシステムは
offset に設定される。
offset
以降にホールがない場合は、
ファイルオフセットはファイル末尾に設定される
(つまり、
どのファイルの末尾にも暗黙のホールが存在するということだ)。
上記のどちらの場合も、
offset
がファイル末尾よりも先を指している場合には
lseek() は失敗する。
これらの操作を使うことで、
アプリケーションが、
まばら (sparse )
にページが割り当てられたファイルでホールをマップすることができる。
この機能はファイルバックアップツールなどのアプリケーションで有用である。
ホールを見つける仕組みがあれば、
ファイルバックアップツールで、
バックアップを作成する際に保存領域を節約し、ホールを保持することができる。
これらの操作の目的としては、
ホールは (通常は)
バックエンドのファイルストレージには割り当てられていない連続する
0 の列である。
しかし、ファイルシステムにはホールを報告する義務はなく、
そのため、
これらの操作は、
ファイルに実際に割り当てられたストレージ領域をマッピングする方法としては確実性のある仕組みではない。
(また、バックエンドのストレージに実際に書き込まれた連続する
0
の列はホールとして報告されないこともある。)
最も単純な実装としては、
SEEK_HOLE
は常にファイル末尾のオフセットを返すようにし、
SEEK_DATA は常に
offset
を返すようにすることで、
ファイルシステムはこれらの操作をサポートすることができる
(
SEEK_DATA は常に
offset
を返すというのは、
offset
が参照する場所がホールであったとしても、
連続する 0
の列のデータで構成されているとみなすということである)。
<unistd.h> から
SEEK_DATA と
SEEK_HOLE
の定義を得るには、
機能検査マクロ
_GNU_SOURCE
を定義しなければならない。
SEEK_HOLE,
SEEK_DATA
操作に対応しているのは以下のファイルシステムである。
- *
- Btrfs (Linux 3.1 以降)
- *
- OCFS (Linux 3.2 以降)
- *
- XFS (Linux 3.5 以降)
- *
- ext4 (Linux 3.8 以降)
- *
-
tmpfs(5) (Linux 3.8 以降)
- *
- NFS (Linux 3.18 以降)
- *
- FUSE (Linux 4.5 以降)
- *
- GFS2 (Linux 4.15 以降)
成功した場合、
lseek()
は結果のファイル位置をファイルの先頭からのバイト数で返す。
エラーの場合、値
(off_t) -1 が返され、
errno
にエラーが指示される。
- EBADF
-
fd
がオープンされたファイルディスクリプターでない。
- EINVAL
-
whence
が有効な値ではない。または、seek
の結果、ファイルオフセットが負に
なってしまうか、 seek
可能なデバイスの末尾を越えてしまう。
- ENXIO
-
whence is SEEK_DATA or SEEK_HOLE, and
offset is beyond the end of the file, or whence is
SEEK_DATA and offset is within a hole at the end of the
file.
- EOVERFLOW
- 結果のファイルオフセットを
off_t
型で表現することができない。
- ESPIPE
-
fd
がパイプ、ソケット、FIFO
を参照している。
POSIX.1-2001, POSIX.1-2008, SVr4, 4.3BSD.
SEEK_DATA と
SEEK_HOLE
は非標準の拡張で、
Solaris, FreeBSD, DragonFly BSD
にも存在する。
これらは POSIX の次の版 (Issue
8)
に入れるよう提案されている。
ファイルディスクリプター、オープンファイル記述、ファイルの関係の説明については
open(2) を参照。
If the
O_APPEND file status flag is set on the open file description,
then a
write(2) always moves the file offset to the end of the
file, regardless of the use of
lseek().
The
off_t data type is a signed integer data type specified by POSIX.1.
いくつかのデバイスでは
seek ができない。 POSIX
はどのデバイスが
lseek()
に対応すべきかは規定していない。
On Linux, using
lseek() on a terminal device fails with the error
ESPIPE.
dup(2),
fallocate(2),
fork(2),
open(2),
fseek(3),
lseek64(3),
posix_fallocate(3)
この man ページは Linux
man-pages
プロジェクトのリリース
5.10
の一部である。プロジェクトの説明とバグ報告に関する情報は
https://www.kernel.org/doc/man-pages/
に書かれている。