truncate(2)

โœจ truncate(2) โœจ โ€” the System Calls Manual girlies know ๐Ÿ’…

okay so bestie, welcome to truncate(2), straight out of the System Calls Manual ๐Ÿ’– this one is so useful and honestly kind of iconic, no cap.


๐Ÿ“› NAME

truncate, ftruncate โ€” truncate a file to a specified length. that's it, that's the whole gig ๐ŸŽ€


๐Ÿ“š LIBRARY

Standard C library โ€” that's libc, link it with -lc ๐Ÿซถ


๐Ÿงพ SYNOPSIS

#include <unistd.h>

int truncate(const char *path, off_t length);
int ftruncate(int fd, off_t length);

๐Ÿงš Feature Test Macro Requirements for glibc (see feature_test_macros(7)):

lowkey don't forget these bestie, or your compiler will ghost you ๐Ÿ˜ญ

truncate():

_XOPEN_SOURCE >= 500
    || /* Since glibc 2.12: */ _POSIX_C_SOURCE >= 200809L
    || /* glibc <= 2.19: */ _BSD_SOURCE

ftruncate():

_XOPEN_SOURCE >= 500
    || /* Since glibc 2.3.5: */ _POSIX_C_SOURCE >= 200112L
    || /* glibc <= 2.19: */ _BSD_SOURCE

๐Ÿ’– DESCRIPTION

so what do these two do?? literally exactly what it says on the tin, bestie. truncate() and ftruncate() cause the regular file named by path, or referenced by fd, to be truncated to a size of precisely length bytes. periodt โœจ

if the file was previously larger than that size โ€” the extra data is gone, bestie, lost to the void ๐Ÿ’€

if the file was previously shorter โ€” it gets extended, and the extended part reads as null bytes ('\0'). it's giving "stretch but hollow" ๐Ÿฆ‹

the file offset is not changed. say it with me. not. changed. ๐ŸŽ€

if the size actually changed, then the st_ctime and st_mtime fields get updated โ€” that's time of last status change and time of last modification respectively, and yes you should go read inode(7) if you wanna know more โ€” and heads up, the set-user-ID and set-group-ID mode bits may be cleared ๐Ÿ‘‘

with ftruncate(), the file must be open for writing. with truncate(), the file must be writable. non-negotiable ๐ŸŒธ


๐ŸŽฏ RETURN VALUE

on success, zero is returned ๐Ÿ˜Œ on error, -1 is returned, and errno is set to tell you what went wrong. vibe check failed, basically ๐Ÿซ 


๐Ÿ”ฅ ERRORS

๐ŸŒˆ For truncate():

  • EACCES โ€” search permission is denied for a component of the path prefix, or the named file isn't writable by the user. (also see path_resolution(7)) ๐Ÿšซ
  • EFAULT โ€” the argument path points outside the process's allocated address space. it's pointing at nothing, bestie ๐Ÿ˜ญ
  • EFBIG โ€” the argument length is larger than the maximum file size. (XSI)
  • ENOSPC โ€” there is not enough space left on the device for extending the file size to the given length. the disk said no ๐Ÿ’€
  • EINTR โ€” while blocked waiting to complete, the call was interrupted by a signal handler; see fcntl(2) and signal(7). rude interruption fr
  • EINVAL โ€” the argument length is negative or larger than the maximum file size.
  • EIO โ€” an I/O error occurred updating the inode. yikes ๐Ÿซ 
  • EISDIR โ€” the named file is a directory. no ma'am, directories are not for truncating ๐Ÿ™ˆ
  • ELOOP โ€” too many symbolic links were encountered in translating the pathname. symlink rabbit hole ๐ŸŒ€
  • ENAMETOOLONG โ€” a component of a pathname exceeded 255 characters, or an entire pathname exceeded 1023 characters. brevity is a virtue bestie โœ‚๏ธ
  • ENOENT โ€” the named file does not exist. ghosted ๐Ÿ‘ป
  • ENOTDIR โ€” a component of the path prefix is not a directory.
  • EPERM โ€” the underlying filesystem does not support extending a file beyond its current size.
  • EPERM โ€” the operation was prevented by a file seal; see fcntl(2). sealed, like a limited-edition drop ๐Ÿ”’
  • EROFS โ€” the named file resides on a read-only filesystem.
  • ETXTBSY โ€” the file is an executable file that is being executed. it's busy being the main character, do not touch ๐Ÿ‘‘

๐Ÿ’œ For ftruncate():

the same errors apply, except now instead of things that can be wrong with path, we have things that can be wrong with the file descriptor, fd ๐ŸŽ€

  • EBADF โ€” fd is not a valid file descriptor.
  • EBADF or EINVAL โ€” fd is not open for writing.
  • EINVAL โ€” fd does not reference a regular file or a POSIX shared memory object.
  • EINVAL or EBADF โ€” the file descriptor fd is not open for writing. POSIX permits, and portable applications should handle, either error for this case. (Linux produces EINVAL.) so write your code for both, bestie, that's the assignment ๐Ÿ“

๐Ÿ•ฐ๏ธ VERSIONS

the deets in DESCRIPTION are for XSI-compliant systems โœจ for non-XSI-compliant systems, the POSIX standard allows two behaviors for ftruncate() when length exceeds the file length โ€” and btw, truncate() isn't specified at all in such an environment, so jot that down ๐Ÿ™ˆ those two behaviors are: either returning an error, or extending the file. like most UNIX implementations, Linux follows the XSI requirement when dealing with native filesystems ๐ŸŒˆ however โ€” some nonnative filesystems do not permit truncate() and ftruncate() to be used to extend a file beyond its current length: a notable example on Linux is VFAT. so if VFAT is being weird to you, now you know why ๐Ÿ’…

also, on some 32-bit architectures, the calling signature for these system calls differs, for the reasons described in syscall(2). iykyk ๐Ÿง 


๐Ÿ“ STANDARDS

POSIX.1-2024. certified slay โœ…


๐Ÿ“œ HISTORY

POSIX.1-2001, SVr4, 4.2BSD. ancient lore, we love an origin story ๐Ÿ›๏ธ

the original Linux truncate() and ftruncate() system calls were not designed to handle large file offsets, which is genuinely so embarrassing for them ๐Ÿ˜ญ consequently, Linux 2.4 added truncate64() and ftruncate64() system calls that do handle large files. however โ€” applications using glibc can literally ignore all of this, because glibc's wrapper functions transparently employ the more recent system calls where they're available. transparent glow-up, we love to see it ๐Ÿ’–


๐Ÿ—’๏ธ NOTES

ftruncate() can also be used to set the size of a POSIX shared memory object; see shm_open(3) ๐Ÿซถ multi-purpose icon behavior


๐Ÿ› BUGS

a header file bug in glibc 2.12 meant that the minimum value of _POSIX_C_SOURCE required to expose the declaration of ftruncate() was 200809L instead of 200112L. ๐Ÿ˜ญ this has been fixed in later glibc versions, so if you're on 2.12 specifically... girl. upgrade ๐Ÿซ 


๐Ÿ‘€ SEE ALSO


and that's the whole page, bestie!! ๐ŸŒธ this one came from Linux man-pages 6.20, dated 2026-04-12 โ€” go forth and truncate responsibly, 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: BSD-4-Clause-UC
  • ๐Ÿ’– girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms