> For the complete documentation index, see [llms.txt](https://man.bsdcn.org/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://man.bsdcn.org/sys/lseek.2.md).

# lseek(2)

`lseek` — 重新定位读/写文件偏移量

## 名称

`lseek`

## 库

Lb libc

## 概要

`#include <unistd.h>`

```c
off_t
lseek(int fildes, off_t offset, int whence);
```

## 描述

`lseek()` 系统调用根据 `whence` 指令将文件描述符 `fildes` 的偏移量重新定位到参数 `offset`。参数 `fildes` 必须是已打开的文件描述符。`lseek()` 系统调用按以下方式重新定位与文件描述符 `fildes` 关联的文件位置指针：

* 如果 `whence` 为 `SEEK_SET`，偏移量设置为 `offset` 字节。
* 如果 `whence` 为 `SEEK_CUR`，偏移量设置为其当前位置加上 `offset` 字节。
* 如果 `whence` 为 `SEEK_END`，偏移量设置为文件大小加上 `offset` 字节。
* 如果 `whence` 为 `SEEK_HOLE`，偏移量设置为大于或等于所提供 `offset` 的下一个空洞的起始位置。空洞的定义见下文。
* 如果 `whence` 为 `SEEK_DATA`，偏移量设置为大于或等于所提供 `offset` 的下一个非空洞文件区域的起始位置。

`lseek()` 系统调用允许将文件偏移量设置到超出文件现有末尾的位置。如果随后在此位置写入数据，则对间隙中数据的后续读取将返回零字节（直到实际有数据写入间隙）。然而，`lseek()` 系统调用本身不会扩展文件大小。

“hole”（空洞）定义为文件中连续的零值字节范围，但文件中的所有零值不保证都会被表示为 `SEEK_HOLE` 返回的空洞。文件系统可以选择用 `SEEK_HOLE` 暴露零值范围，但不强制要求。应用程序可以使用 `SEEK_HOLE` 来优化对零值范围的处理行为，但不能依赖它来找到文件中所有这样的范围。每个文件在文件末尾都被视为具有一个零大小的虚拟空洞。每个数据区域末尾存在空洞使得编程更加简单，同时也与 Solaris 中的原始实现保持兼容。这还使得当前文件大小（即文件末尾偏移量）会被返回，以表示在提供的 `offset` 之后没有更多空洞。应用程序应使用 `fpathconf(_PC_MIN_HOLE_SIZE)` 或 `pathconf(_PC_MIN_HOLE_SIZE)` 来确定文件系统是否支持 `SEEK_HOLE`。参见 [pathconf(2)](/sys/pathconf.2.md)。

对于不提供空洞信息的文件系统，文件将被表示为一个完整的数据区域。

## 返回值

成功完成后，`lseek()` 返回从文件开头计算的偏移量位置（以字节为单位）。否则，返回值 -1，并设置 `errno` 以指示错误。

## 错误

`lseek()` 系统调用在以下情况下会失败，且文件位置指针保持不变：

**\[`EBADF`]** `fildes` 参数不是已打开的文件描述符。

**\[`EINVAL`]** `whence` 参数不是有效值，或者对于非字符特殊文件，结果文件偏移量为负值。

**\[`ENXIO`]** 对于 `SEEK_DATA`，在提供的偏移量之后没有更多数据区域。由于文件末尾存在空洞，对于 `SEEK_HOLE`，仅当 `offset` 已经指向文件末尾位置时才返回此错误。

**\[`EOVERFLOW`]** 结果文件偏移量无法在 `off_t` 类型的对象中正确表示。

**\[`ESPIPE`]** `fildes` 参数与管道、socket 或 FIFO 相关联。

## 参见

[dup(2)](/sys/dup.2.md), [open(2)](/sys/open.2.md), [pathconf(2)](/sys/pathconf.2.md)

## 标准

`lseek()` 系统调用预期遵循 IEEE Std 1003.1-2008 ("POSIX.1")。

`SEEK_HOLE` 和 `SEEK_DATA` 指令以及 `ENXIO` 错误预期遵循 IEEE Std 1003.1-2024 ("POSIX.1")。

## 历史

`lseek()` 函数出现于 Version 7 AT\&T UNIX。

## 缺陷

如果 `lseek()` 系统调用在无法寻址的设备上操作，它仍会请求寻址操作并成功返回，即使没有执行任何寻址。由于 `offset` 参数会无条件地存储在该设备的文件描述符中，因此无法确认寻址操作是否成功（例如使用 `ftell()` 函数）。已知无法寻址的设备类型包括磁带机。

`lseek()` 系统调用不会检测可更换介质设备（如 DVD 或蓝光设备）中是否存在介质。因此，当没有介质存在时，请求的寻址操作仍会成功返回。

本文档对 `whence` 的使用在英语语法上是不正确的，但出于历史原因予以保留。
