TL;DR:
There was/is some limit, for example readdir_r()
can't read file names longer than 255 bytes. However Linux does aware of that and modern APIs can read long file names without problem
There's this line in ReiserFS wiki
Max. filename length: 4032 bytes, limited to 255 by Linux VFS
so there may be some real limits in VFS although I don't know enough about Linux VFS to tell. The VFS functions all work on struct dentry
which stores names in the struct qstr d_name;
extern int vfs_create(struct inode *, struct dentry *, umode_t, bool);
extern int vfs_mkdir(struct inode *, struct dentry *, umode_t);
extern int vfs_mknod(struct inode *, struct dentry *, umode_t, dev_t);
extern int vfs_symlink(struct inode *, struct dentry *, const char *);
extern int vfs_link(struct dentry *, struct inode *, struct dentry *, struct inode **);
extern int vfs_rmdir(struct inode *, struct dentry *);
extern int vfs_unlink(struct inode *, struct dentry *, struct inode **);
extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *, struct inode **, unsigned int);
extern int vfs_whiteout(struct inode *, struct dentry *);
The struct qstr
stores hash, length and pointer to the name so I don't think there are any physical limits unless the VFS functions explicitly truncate the name on creating/opening. I didn't check the implementation but I think long names should work fine
Update:
The length check is done in linux/fs/libfs.c and ENAMETOOLONG
will be returned if the name is too long
/*
* Lookup the data. This is trivial - if the dentry didn't already
* exist, we know it is negative. Set d_op to delete negative dentries.
*/
struct dentry *simple_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
{
if (dentry->d_name.len > NAME_MAX)
return ERR_PTR(-ENAMETOOLONG);
if (!dentry->d_sb->s_d_op)
d_set_d_op(dentry, &simple_dentry_operations);
d_add(dentry, NULL);
return NULL;
}
The limit is defined in linux/limits.h
#define NAME_MAX 255 /* # chars in a file name */
But I have no idea how long file names can be opened without that error
However there are a few system calls that do have limits. struct dirent
has the following members
struct dirent {
ino_t d_ino; /* Inode number */
off_t d_off; /* Not an offset; see below */
unsigned short d_reclen; /* Length of this record */
unsigned char d_type; /* Type of file; not supported
by all filesystem types */
char d_name[256]; /* Null-terminated filename */
};
Since d_name
is a fixed array, many functions like readdir_r()
won't ever be able to return names longer than 255 bytes. For example
struct dirent entry;
struct dirent *result;
dir = opendir("/");
int return_code = readdir_r(dir, &entry, &result);
That's why readdir_r()
was deprecated
On some systems, readdir_r()
can't read directory entries with very long names. When the glibc implementation encounters such a name, readdir_r()
fails with the error ENAMETOOLONG
after the final directory entry has been read. On some other systems, readdir_r()
may return a success status, but the returned d_name
field may not be null terminated or may be truncated.
readdir_r(3) — Linux manual page
readdir()
OTOH allocates memory for struct dirent
itself, so the name can actually be longer than 255 bytes and you must not use sizeof(d_name)
and sizeof(struct dirent)
to get the name and struct lengths
Note that while the call
fpathconf(fd, _PC_NAME_MAX)
returns the value 255 for most filesystems, on some filesystems (e.g., CIFS, Windows SMB servers), the null-terminated filename that is (correctly) returned in d_name
can actually exceed this size. In such cases, the d_reclen
field will contain a value that exceeds the size of the glibc dirent
structure shown above.
readdir(3) — Linux manual page
Some other functions like getdents()
use struct linux_dirent
and struct linux_dirent64
which doesn't suffer from the fixed length issue
struct linux_dirent {
unsigned long d_ino; /* Inode number */
unsigned long d_off; /* Offset to next linux_dirent */
unsigned short d_reclen; /* Length of this linux_dirent */
char d_name[]; /* Filename (null-terminated) */
/* length is actually (d_reclen - 2 -
offsetof(struct linux_dirent, d_name)) */
/*
char pad; // Zero padding byte
char d_type; // File type (only since Linux
// 2.6.4); offset is (d_reclen - 1)
*/
}
struct linux_dirent64 {
ino64_t d_ino; /* 64-bit inode number /
off64_t d_off; / 64-bit offset to next structure /
unsigned short d_reclen; / Size of this dirent /
unsigned char d_type; / File type /
char d_name[]; / Filename (null-terminated) */
};
strace ls
shows that ls
uses getdents()
to list files so it can handle file names with arbitrary length