sendfile(2)

โœจ sendfile(2) โ€” System Calls Manual โœจ

okay bestie, welcome to sendfile ๐Ÿ’– it's a system call, it lives in section 2, and honestly it's the moment when you stop doing the whole read-then-write two-step and just let the kernel handle it. icon behaviour only.


๐ŸŒธ NAME ๐ŸŒธ

sendfile โ€” transfer data between file descriptors. yes literally that's it, that's the whole job, slay ๐ŸŽ€


๐Ÿ’… LIBRARY ๐Ÿ’…

Standard C library (libc, -lc). so like, link it and go ๐Ÿ’–


๐Ÿฆ‹ SYNOPSIS ๐Ÿฆ‹

#include <sys/sendfile.h>

ssize_t sendfile(int out_fd, int in_fd, off_t *_Nullable offset,
                 size_t count);

๐Ÿ‘‘ DESCRIPTION ๐Ÿ‘‘

sendfile() copies data between one file descriptor and another. and here's the tea: because this copying happens inside the kernel, sendfile() is way more efficient than gluing together read(2) and write(2), which would make you shuttle all the data back and forth through user space. not me doing extra work for no reason ๐Ÿ™ˆ

in_fd should be a file descriptor opened for reading and out_fd should be a descriptor opened for writing. that's the vibe check.

If offset is not NULL, then it points to a variable holding the file offset from which sendfile() will start reading data from in_fd. and when sendfile() returns, that variable gets set to the offset of the byte following the last byte that was read. also: if offset is not NULL, then sendfile() does not touch the file offset of in_fd. but if offset is NULL, the file offset gets adjusted to reflect the number of bytes read from in_fd. periodt.

If offset is NULL, then data will be read from in_fd starting at the file offset, and the file offset will be updated by the call. yes, that's the same thing said twice, no, we're not skipping anything, every detail stays ๐Ÿ˜ค

count is the number of bytes to copy between the file descriptors.

The in_fd argument must correspond to a file which supports mmap(2)-like operations โ€” meaning it cannot be a socket. huge. except, since Linux 5.12 and if out_fd is a pipe, in which case sendfile() desugars to a splice(2) and its restrictions apply. plot twist ๐ŸŒ€

Before Linux 2.6.33, out_fd must refer to a socket. Since Linux 2.6.33 it can be any file. If it's seekable, then sendfile() changes the file offset appropriately. glow up fr fr โœจ


๐Ÿ’– RETURN VALUE ๐Ÿ’–

If the transfer was successful, the number of bytes written to out_fd is returned.

โš ๏ธ but bestie, listen โ€” a successful call to sendfile() may still write fewer bytes than requested. the caller should be prepared to retry the call if there were unsent bytes. see also NOTES. this is not a drill ๐Ÿ˜ญ

On error, -1 is returned, and errno is set to indicate the error.


๐ŸŒˆ ERRORS ๐ŸŒˆ

  • EAGAIN โ€” Nonblocking I/O has been selected using O_NONBLOCK and the write would block. it's giving "not right now" ๐Ÿ’€
  • EBADF โ€” The input file was not opened for reading or the output file was not opened for writing. one of them didn't have the right permissions, embarrassing.
  • EFAULT โ€” Bad address.
  • EINVAL โ€” Descriptor is not valid or locked, or an mmap(2)-like operation is not available for in_fd, or count is negative.
  • EINVAL โ€” out_fd has the O_APPEND flag set. This is not currently supported by sendfile(). so don't do that ๐Ÿซถ
  • EIO โ€” Unspecified error while reading from in_fd.
  • ENOMEM โ€” Insufficient memory to read from in_fd. brain empty, no thoughts, no memory ๐Ÿ˜ญ
  • EOVERFLOW โ€” count is too large, the operation would result in exceeding the maximum size of either the input file or the output file.
  • ESPIPE โ€” offset is not NULL but the input file is not seekable.

๐Ÿงš VERSIONS ๐Ÿงš

Other UNIX systems implement sendfile() with different semantics and prototypes. It should not be used in portable programs. that's the fine print and we respect it ๐Ÿ’œ


โญ STANDARDS โญ

None. literally none. it's built different, no standard to its name ๐Ÿ’…


๐ŸŽ€ HISTORY ๐ŸŽ€

Linux 2.2, glibc 2.1.

In Linux 2.4 and earlier, out_fd could also refer to a regular file; this possibility went away in the Linux 2.6.x kernel series, but was restored in Linux 2.6.33. the comeback era ๐Ÿ‘‘

The original Linux sendfile() system call was not designed to handle large file offsets. Consequently, Linux 2.4 added sendfile64(), with a wider type for the offset argument. The glibc sendfile() wrapper function transparently deals with the kernel differences. so you don't have to think about it, you're welcome ๐Ÿซถ


๐Ÿ”ฅ NOTES ๐Ÿ”ฅ

sendfile() will transfer at most 0x7ffff000 (2,147,479,552) bytes, returning the number of bytes actually transferred. (This is true on both 32-bit and 64-bit systems.) same cap everywhere, no exceptions.

If you plan to use sendfile() for sending files to a TCP socket, but need to send some header data in front of the file contents, you will find it useful to employ the TCP_CORK option, described in tcp(7), to minimize the number of packets and to tune performance. chef's kiss optimisation ๐Ÿ“

Applications may wish to fall back to read(2) and write(2) in the case where sendfile() fails with EINVAL or ENOSYS. always have a plan B bestie.

If out_fd refers to a socket or pipe with zero-copy support, callers must ensure the transferred portions of the file referred to by in_fd remain unmodified until the reader on the other end of out_fd has consumed the transferred data. > โš ๏ธ do not touch that file mid-flight, i am begging you ๐Ÿ˜ญ

The Linux-specific splice(2) call supports transferring data between arbitrary file descriptors provided one (or both) of them is a pipe. it's giving sendfile's cooler cousin ๐ŸŒˆ


๐Ÿ’œ SEE ALSO ๐Ÿ’œ

copy_file_range(2), mmap(2), open(2), socket(2), splice(2)


and that's the whole page bestie, no cap ๐Ÿฆ‹ this was sendfile(2) from Linux man-pages 6.20, dated 2026-02-08. go forth and copy bytes inside the kernel, mwah ๐Ÿ’–โœจ

๐Ÿ“ฆ where this page comes from
  • arch rolling: man-pages 6.20-1 ยท BSD-2-Clause AND BSD-3-Clause AND BSD-4.3TAHOE AND BSD-4-Clause-UC AND GPL-1.0-or-later AND GPL-2.0-only AND GPL-2.0-or-later AND GPL-3.0-or-later AND LGPL-3.0-linking-exception AND LGPL-3.0-or-later AND LicenseRef-Public-Domain AND LicenseRef-UltraPermissive AND Linux-man-pages-1-para AND Linux-man-pages-copyleft AND Linux-man-pages-copyleft-2-para AND Linux-man-pages-copyleft-var AND MIT AND Spencer-94
  • nixpkgs unstable: man-pages 6.20
  • ๐Ÿ“œ the page's license: Linux-man-pages-1-para
  • ๐Ÿ’– girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms