Linux는 255 바이트보다 긴 파일 이름을 어느 정도까지 지원합니까?

Nov 14 2020

나는 리눅스의 255 바이트의 파일 이름 제한에 대해 질문 어제와 답은 / 쉽게 변경되지 않습니다 수없는 한계입니다이었다. 그러나 대부분의 Linux는 최대 파일 이름 길이가 255 UTF-16 문자 인 NTFS를 지원한다는 것을 기억했습니다.

그래서 저는 NTFS 파티션을 만들고 UTF-8의 바이트가 480 인 160 자 일본어 문자열로 파일 이름을 지정하려고했습니다. 작동하지 않을 것이라고 예상했지만 아래와 같이 작동했습니다. 파일 이름이 480 바이트 였는데 어떻게 작동합니까? 255 바이트 제한은 특정 파일 시스템에만 적용되며 Linux 자체가 255 바이트보다 긴 파일 이름을 처리 할 수 ​​있습니까?

----추신-----

이 문자열은 "方丈 記"이라는 이름의 유명한 일본 에세이 의 시작 부분입니다 . 여기에 문자열이 있습니다.

ゆ く 河 の 流 れ は 絶 え ず し て 、 し か も も と の 水 に あ ら ず。 よ ど み に 浮 か ぶ う た か た は 、 か つ 消 え か つ 結 び て 、 久 し く と ど ま り た る た め か な し。 世 の し か。 た ま し き の 都 の う ち に 、 棟 を 並 べ 、 甍 を 争 へ る 、 高 き 、 卑 し き 、 人 の 住 ま ひ は 、 世 々 を 経 て 尽 き せ ぬ も の な れ ど 、 昔 ま こ と 尋 ぬ れ ばし 家 は ま れ な り。

이 웹 응용 프로그램 을 사용 하여 UTF-8 바이트를 계산했습니다.

답변

26 StephenKitt Nov 14 2020 at 19:00

대답은 종종 "상황에 따라 다릅니다"입니다.

특히 NTFS 구현을 살펴보면 statvfs호출자 에게 최대 파일 이름 길이 255를보고 하므로이를 255 바이트 제한으로 해석하는 호출자는 NTFS에서 유효한 파일 이름을 선제 적으로 피할 수 있습니다. 그러나 대부분의 프로그램은 이것을 NAME_MAX미리 확인하지 않으며 (또는 심지어 ) ENAMETOOLONG오류를 포착하기 위해 오류 에 의존 합니다. 대부분의 경우, 중요한 제한이 PATH_MAX아니라 NAME_MAX; 파일 이름을 조작 할 때 일반적으로 버퍼를 할당하는 데 사용됩니다 ( 임의의 제한이없는 Hurd 와 같은 OS에서 예상하는대로 경로 버퍼를 동적으로 할당하지 않는 프로그램의 경우 ).

NTFS 구현 자체는 파일 이름 길이를 바이트 단위로 확인하지 않고 항상 2 바이트 문자로 확인합니다. 255 개의 2 바이트 요소 배열로 표현할 수없는 파일 이름은 ENAMETOOLONG오류를 발생시킵니다.

NTFS는 일반적으로 Linux에서 FUSE 드라이버에 의해 처리됩니다. 커널 드라이버는 현재 UCS-2 문자 만 지원하지만 FUSE 드라이버 는 UTF-16 서로 게이트 쌍을 지원합니다 (문자 길이가 감소됨).

12 Ned64 Nov 14 2020 at 17:19

파일명의 길이에 대한 제한은 실제로 예를 들어, 파일 시스템 내부의 부호화 ext4에서,https://en.wikipedia.org/wiki/Ext4 :

맥스. 파일 이름 길이 255 바이트

에서 https://en.wikipedia.org/wiki/XFS :

맥스. 파일 이름 길이 255 바이트

에서 https://en.wikipedia.org/wiki/Btrfs :

맥스. 파일 이름 길이 255 ASCII 문자 (유니 코드와 같은 멀티 바이트 문자 인코딩의 경우 더 적음)

에서 https://en.wikipedia.org/wiki/NTFS :

맥스. 파일 이름 길이 255 UTF-16 코드 단위

여러 파일 시스템에 대한 이러한 제한에 대한 개요는 https://en.wikipedia.org/wiki/Comparison_of_file_systems#Limits. ReiserFS가 더 높은 제한 (거의 4K)을 가지고 있지만 커널 자체 (VFS 내부, 커널 가상 파일 시스템)의 제한은 255 바이트라는 것을 볼 수 있습니다.

텍스트는 NTFS에서 사용되는 160 개의 UTF-16 문자를 사용합니다.

echo ゆく河の流れは絶えずして、しかももとの水にあらず。よどみに浮かぶうたかたは、かつ消えかつ結びて、久しくとどまりたるためしなし。世の中にある人とすみかと、またかくのごとし。たましきの都のうちに、棟を並べ、甍を争へる、高き、卑しき、人の住まひは、世々を経て尽きせぬものなれど、これをまことかと尋ぬれば、昔ありし家はまれなり。 > jp.txt
iconv -f utf-8 -t utf-16 jp.txt > jp16.txt
ls -ld jp*.txt
cat jp16.txt | hexdump -C

이것은 0x140 = 320 바이트 (사용 된 경우 2 바이트 앞에 붙은 바이트 순서 표시 (BOM) 추가)를 표시합니다. 즉, 160 개의 UTF-16 문자이므로 NTFS의 255 UTF-16 문자 제한 미만이지만 255 바이트 이상입니다.

(여기서 개행 문자 무시)

8 ArtemS.Tashkinov Nov 14 2020 at 17:25

그래서, 제가 알아 낸 것이 있습니다.

Coreutils 는 파일 이름 길이에 특별히 신경 쓰지 않고 길이에 관계없이 사용자 입력으로 작업합니다. 즉, 검사가 없습니다.

즉 이것은 작동합니다 (파일 이름 길이는 462 바이트입니다!).

name="和総坂裁精座回資国定裁出観産大掲記労。基利婚岡第員連聞余枚転屋内分。妹販得野取戦名力共重懲好海。要中心和権瓦教雪外間代円題気変知。貴金長情質思毎標豊装欺期権自馬。訓発宮汚祈子報議広組歴職囲世階沙飲。賞携映麻署来掲給見囲優治落取池塚賀残除捜。三売師定短部北自景訴層海全子相表。著漫寺対表前始稿殺法際込五新店広。"
cd /mnt/ntfs
touch "$name"

이것도 작동합니다

echo 123 > "$name"
cat "$name"
123

그러나 해당 파일을 기존 Linux 파일 시스템에 복사하려고하면 작업이 실패합니다.

cp "$name" /tmp
cp: cannot stat '/tmp/和総坂裁精座回資国定裁出観産大掲記労。基利婚岡第員連聞余枚転屋内分。妹販得野取戦名力共重懲好海。要中心和権瓦教雪外間代円題気変知。貴金長情質思毎標豊装欺期権自馬。訓発宮汚祈子報議広組歴職囲世階沙飲。賞携映麻署来掲給見囲優治落取池塚賀残除捜。三売師定短部北自景訴層海全子相表。著漫寺対表前始稿殺法際込五新店広。': File name too long

IE는 cp사실에서이 파일을 작성하려고했다 /tmp하지만 /tmp파일 이름이 255 바이트보다 허용하지 않습니다.

또한 마우스 패드 (GTK 응용 프로그램)에서이 파일을 열고 편집하고 저장했습니다. 모두 작동하여 특정 Linux 파일 시스템에만 255 바이트 제한이 적용됩니다.

그렇다고 모든 것이 작동한다는 의미는 아닙니다. 예를 나의 마음에 드는 콘솔 파일 관리자, 자정 사령관, 노턴 사령관의 복제 용 - 수없는 목록 (0으로 표시 파일 크기), 개방, 또는이 파일을 아무것도 할 :

Error
No such file or directory (2)
3 phuclv Nov 16 2020 at 11:15

TL; DR :

예를 들어 readdir_r()255 바이트보다 긴 파일 이름을 읽을 수 없습니다. 그러나 Linux는이를 인식하고 최신 API는 문제없이 긴 파일 이름을 읽을 수 있습니다.


ReiserFS 위키 에이 줄이 있습니다.

맥스. 파일 이름 길이 : 4032 바이트, Linux VFS에서 255로 제한

따라서 Linux VFS에 대해 충분히 알지 못하더라도 VFS에 실제 제한이있을 수 있습니다. VFS 기능 모든 작업에 struct dentry어느에 저장 이름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 *);

struct qstrVFS에 기능이 명시 적으로 생성 / 개방에 이름을 절단하지 않는 이름으로 저장 해시, 길이, 포인터 나는 어떤 물리적 한계가 있다고 생각하지 않도록. 구현을 확인하지 않았지만 긴 이름이 제대로 작동해야한다고 생각합니다.

최신 정보:

길이 검사가 이루어집니다 리눅스 / FS / libfs.cENAMETOOLONG이름이 너무 긴 경우 반환됩니다

/*
 * 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;
}

제한은 linux / limits.h에 정의되어 있습니다.

#define NAME_MAX         255    /* # chars in a file name */

하지만 그 오류없이 파일 이름을 얼마나 오래 열 수 있는지 모르겠습니다.


그러나 제한이있는 몇 가지 시스템 호출이 있습니다. struct dirent다음 회원이 있습니다

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 */
};

d_name고정 배열 이기 때문에 같은 많은 함수 readdir_r()는 255 바이트보다 긴 이름을 반환 할 수 없습니다. 예를 들면

struct dirent entry;
struct dirent *result;
dir = opendir("/");
int return_code = readdir_r(dir, &entry, &result);

그게 더 이상 사용되지 않는 이유입니다.readdir_r()

일부 시스템에서는 readdir_r()이름이 매우 긴 디렉토리 항목을 읽을 수 없습니다. glibc 구현에서 이러한 이름을 발견 하면 최종 디렉토리 항목을 읽은 후 readdir_r()오류와 함께 실패합니다 ENAMETOOLONG. 일부 다른 시스템에서는 readdir_r()성공 상태를 리턴 d_name할 수 있지만 리턴 된 필드는 널로 종료되지 않거나 잘릴 수 있습니다.

readdir_r (3) — Linux 매뉴얼 페이지

readdir()대한 OTOH 할당 메모리 struct dirent자체, 이름은 실제로 255 바이트보다 수 있습니다 당신은 그래서 사용 sizeof(d_name)하고 sizeof(struct dirent)이름과 구조체의 길이를 얻을 수

통화하는 동안

fpathconf(fd, _PC_NAME_MAX)

대부분의 파일 시스템에 대해 값 255를 반환합니다. 일부 파일 시스템 (예 : CIFS, Windows SMB 서버)에서 (올바르게) 반환 된 null로 끝나는 파일 이름 d_name은 실제로이 크기를 초과 할 수 있습니다. 이러한 경우 d_reclen필드에는 dirent위에 표시된 glibc 구조 의 크기를 초과하는 값이 포함됩니다 .

readdir (3) — Linux 매뉴얼 페이지

getdents()사용 struct linux_dirent과 같은 일부 다른 기능 struct linux_dirent64은 고정 길이 문제로 어려움을 겪지 않습니다.

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파일을 나열 하는 ls데 사용 getdents()하여 임의의 길이로 파일 이름을 처리 할 수 있음을 보여줍니다.