파일 이름 인코딩이 어떻게 작동하는지 이해하는 데 어려움을 겪고 있습니다. unix.SE에서 상충되는 설명을 발견했습니다.
문자로 저장된 파일 이름
다른 답변을 인용하려면 다음을 수행하십시오. Linux의 파일 시스템 문자 인코딩에 대한 몇 가지 질문
[...] 귀하의 질문에서 언급했듯이 UNIX 파일 이름은 단지 문자 시퀀스일 뿐이며 커널은 인코딩에 대해 전혀 알지 못하며 전적으로 사용자 공간(예: 응용 프로그램 수준) 개념입니다.
파일 이름이 문자로 저장되면 최종 파일 이름이 디스크에 비트 또는 바이트의 시퀀스로 나타나야 하므로 일부 인코딩이 포함되어야 합니다. 사용자가 선택할 수 있는 경우어느인코딩은 문자를 커널에 공급되는 바이트 시퀀스에 매핑하고 생성될 수 있습니다.어느유효한 파일 이름에 대한 일련의 바이트입니다.
다음을 가정합니다. 사용자가 무작위 인코딩을 사용합니다.엑스, 파일을 foo
일련의 바이트로 변환합니다.α그리고 디스크에 저장합니다. 다른 사용자가 인코딩을 사용합니다.예. 이 인코딩에서는α로 변환합니다 /
. 파일 이름으로 허용되지 않습니다. 그러나 첫 번째 사용자의 경우 파일이 유효합니다.
나는 이것이 일어날 것이라고 생각하지 않습니다.
바이너리 blob으로 저장된 파일 이름
다른 답변을 인용하려면 다음을 수행하십시오. Linux에서는 파일 이름과 경로에 어떤 문자 세트 인코딩이 사용됩니까?
다른 사람들이 지적했듯이 이에 대한 실제 대답은 없습니다. 파일 이름과 경로는 인코딩되지 않습니다. 운영 체제는 바이트 시퀀스만 처리합니다. 개별 응용 프로그램은 특정 방식으로 인코딩된 것으로 해석하도록 선택할 수 있지만 이는 다양합니다.
시스템이 문자를 처리하지 않는 경우 파일 이름에서 특정 문자(예: /
또는 ) 를 억제하려면 어떻게 해야 합니까? 코딩이 없으면 NULL
a의 개념도 없습니다./
한 가지 설명은 파일 시스템이 다음을 포함하는 파일 이름을 저장할 수 있다는 것입니다.어느
문자가 있는 경우 인코딩을 고려하는 사용자 프로그램만 잘못된 문자가 포함된 파일 이름을 차단합니다. 이는 결국 파일 시스템과 커널이 어려움 없이 포함을 처리할 수 있음을 의미합니다 /
.
나 역시 이것이 잘못된 것이라고 생각한다.
인코딩은 어디서 이루어지며 특정 문자를 허용하지 않는 제한 사항은 어디에 있습니까?
답변1
짧은 대답: namei()
Unix/Linux/BSD 커널 기능에 부과된 제한 사항입니다. 인코딩 은 또는 같은 사용자 수준 프로그램에서 발생합니다 xterm
.firefox
ls
나는 당신이 잘못된 전제에서 시작하고 있다고 생각합니다. Unix의 파일 이름은 임의의 값을 가진 바이트 문자열입니다. 일부 값, 0x0(ASCII Nul) 및 0x2f(ASCII '/')는 멀티바이트 문자 인코딩의 일부로 허용되지 않습니다. "바이트"에는 문자를 나타내는 숫자(ASCII 및 기타 인코딩)가 포함될 수 있지만 "문자"에는 1바이트 이상이 필요할 수 있습니다(예: 유니코드의 UTF-8 표현에서 0x7f 이상의 코드 포인트).
이러한 제한은 파일 이름 인쇄 규칙과 ASCII 문자 집합으로 인해 발생합니다. 원래 Unix에서는 ASCII '/'(숫자 0x2f) 값 바이트를 사용하여 부분 또는 전체 경로의 조각을 분리했습니다(예: '/usr/bin/cat'에는 'usr', 'bin' 및 'cat' 조각이 있음). 원래 Unix에서는 문자열을 종료하기 위해 ASCII Nul을 사용했습니다. 이 두 값 외에도 파일 이름의 바이트는 다른 값을 가질 수 있습니다. 유니코드의 UTF-8 인코딩에서 이를 확인할 수 있습니다. 인쇄 가능한 ASCII 문자("/" 포함)는 UTF-8에서 1바이트만 차지합니다. 위 코드 포인트의 UTF-8에는 Nul 제어 문자를 제외하고 값이 0인 바이트가 포함되어 있지 않습니다. UTF-8은 유닉스 왕좌를 노리는 Plan-9을 위해 발명되었습니다.
이전 Unix(Linux처럼 보임)에는 namei()
경로를 한 번에 한 바이트씩 살펴보고 0x2F 값 바이트에서 경로를 조각으로 나누고 값이 0인 바이트에서 중지하는 기능이 있었습니다. namei()
Unix/Linux/BSD 커널의 일부이므로 예외 바이트 값이 적용되는 곳입니다.
지금까지 문자가 아닌 바이트 값에 대해 논의했습니다. namei()
바이트에는 문자 의미 체계가 적용되지 않습니다. 이는 ls
예를 들어 바이트 값이나 문자 값을 기준으로 파일 이름을 정렬할 수 있는 사용자 수준 프로그램에 따라 다릅니다 . xterm
파일 이름으로 켜지는 픽셀은 문자 인코딩에 따라 결정됩니다. UTF-8로 인코딩된 파일 이름이 있다는 것을 알려주지 않으면 xterm
호출할 때 횡설수설하는 말을 많이 보게 될 것입니다. UTF-8(또는 모든 UTF-16, UTF-32) 인코딩을 감지하도록 컴파일되지 않은 경우 vim
UTF-8로 인코딩된 문자가 포함된 "텍스트 파일"을 열 때 많은 횡설수설을 보게 됩니다.
답변2
문제는 커널이 응용 프로그램이 파일 이름으로 제공된 데이터를 어떻게 해석하는지 전혀 신경 쓰지 않는다는 것입니다.
UTF-16 문자열을 특별히 다루는 C 애플리케이션이 있다고 가정해 보겠습니다. 적절하게 구성된 입력 방법을 통해 "다른 이름으로 저장" 프롬프트/대화 상자에 ∯ 기호(유니코드 0x222F)를 입력했습니다.
응용 프로그램이 어떤 종류의 변환도 수행하지 않고 이를 일반 C 문자열(예: 쓰기 모드에서)로 char*
보내는 경우 fopen
커널은 ∯를 볼 수 없으며 심지어 그것을 상상하려고 시도할 수도 없습니다. char
값이 포함된 두 개의 s가 차례로 표시됩니다 0x22 0x2F
(8비트 문자 및C 라이브러리에는 재미있는 콘텐츠가 없습니다).
즉, 커널 관점에서 볼 때 유효한 문자( "
) 뒤에는 /
(ASCII 0x2F)가 옵니다. fopen
반환됩니다 EISDIR
(예: "디렉토리처럼 보이는데 쓰기 모드를 요청했습니다!").
∮ (Unicode )를 입력하면 0x222E
커널은 두 개의 멋진 문자를 확인하고 ASCII 언어 응용 프로그램에서 볼 수 있듯이 이름이 ".
.
내 응용 프로그램에 파일 이름을 입력 a
하고 응용 프로그램이 이를 UTF-16으로 커널에 전달하면 커널은 이를 읽고 실제로 는 문자열이 이미 종료되었기 때문에 고려 0x00 0x61
조차 하지 않습니다 . 오류 메시지는 빈 파일 이름과 동일합니다( 제 생각에는).0x61
0x00
ENOENT
따라서 커널은 데이터를 얼룩으로 처리합니다. 이것은 스트림입니다 char
. 선택한 사용자 공간 인코딩에서 잘못된 "문자"는 blob(커널에 전달된 이진 표현)에서 0x00
또는 ("null" 및 )을 생성하는 문자입니다.0x2F
/
답변3
바이트와 문자의 분리는 Unix가 설계된 지 오랜 후에 이루어졌습니다. 설계 당시 이러한 단어의 사용은 8(또는 6 또는 9) 비트를 해석하는 방법에 대한 정보만 전달했지만코딩언급되지 않은.
파일 이름은 바이트의 시퀀스입니다. 0x2f "/"를 제외한 모든 바이트가 허용됩니다. 0x00을 포함하는 바이트는 문자열 종결자로 사용되기 때문에 커널에 도달할 수도 없습니다. 애플리케이션은 선택한 인코딩에 따라 바이트 시퀀스를 해석할 수 있습니다. 이것이 혼란스럽게 들린다면 그럴 것 같습니다.
자세한 내용은 다음에서 확인할 수 있습니다.http://www.gtk.org/api/2.6/glib/glib-Character-Set-Conversion.html유용하다고 생각할 수도 있습니다.