유닉스 파일 이름 인코딩 이해


25

파일 이름 인코딩이 어떻게 작동하는지 이해하기가 어렵습니다. 유닉스 SE에서 모순되는 설명을 발견했습니다.

파일 이름은 문자로 저장됩니다

다른 대답을 인용하려면 : Linux의 파일 시스템 문자 인코딩에 대한 몇 가지 질문

[…] 질문에서 언급했듯이 UNIX 파일 이름은 일련의 문자 일뿐입니다. 커널은 인코딩에 대해 전혀 알지 못하며 이는 완전히 사용자 공간 개념입니다.

파일 이름이 문자로 저장되는 경우 마지막으로 파일 이름이 디스크에서 비트 또는 바이트 시퀀스로 끝나야하므로 일종의 인코딩이 필요합니다. 사용자가 선택할 수 있다면 어떤 커널에 공급되는 바이트 순서로 문자를 매핑하는 인코딩을, 그것을 만들 수 있는 유효한 파일 이름에 대한 바이트 순서를.

다음을 가정하십시오. 사용자는 랜덤 인코딩 X를 사용 하여 파일 foo을 바이트 시퀀스 α 로 변환하여 디스크에 저장합니다. 다른 사용자는 Y 인코딩을 사용합니다 . 이 인코딩에서 α는로 변환되며 /파일 이름으로 허용되지 않습니다. 그러나 첫 번째 사용자에게는 파일이 유효합니다.

이 시나리오는 발생할 수 없다고 가정합니다.

파일 이름은 이진 Blob으로 저장됩니다

다른 대답을 인용하자면 : Linux에서 파일 이름과 경로에 어떤 문자 세트 인코딩이 사용됩니까?

다른 사람들이 지적했듯이 실제로 이에 대한 대답은 없습니다. 파일 이름과 경로에는 인코딩이 없습니다. OS는 일련의 바이트 만 처리합니다. 개별 응용 프로그램은 어떤 식 으로든 인코딩 된 것으로 해석하도록 선택할 수 있지만 이는 다양합니다.

시스템이 문자를 처리하지 않는 경우 파일 이름에서 특정 문자 (예 : /또는 NULL)를 어떻게 금지 할 수 있습니까? / 인코딩 이없는의 개념은 없습니다 .

파일 시스템은 임의의 문자를 포함 하는 파일 이름을 저장할 수 있으며 유효하지 않은 문자를 포함하는 파일 이름을 질식시키는 인코딩을 고려하는 사용자 프로그램 일뿐입니다. 이는 파일 시스템과 커널이 어려움없이을 포함하는 파일 이름을 처리 할 수 ​​있음을 의미합니다 /.

또한 이것이 잘못되었다고 가정합니다.

인코딩은 어디에서 발생하며 특정 문자를 허용하지 않는 제한은 어디에 있습니까?


모든 인코딩에서 Null은 같습니다 (0).
케빈

2
@Kevin : UTF-16, UCS-4 (= UTF-32) 또는 ASCII 확장이 아닌 대부분의 다른 멀티 바이트 인코딩은 아닙니다.
Gilles 'SO- 악마 그만'

1
실제로 Riccardo Murri의 대답문자 가 아닌 바이트를 언급해야합니다 . 대부분의 파일 시스템은 바이트를 저장합니다.
Gilles 'SO- 악마 그만'

@Gilles : 또 다른 시간 나는 당신이 정말로 무엇 지켜 볼 작성 .
Incnis Mrsi

답변:


25

짧은 대답 : Unix / Linux / BSD 커널에 적용되는 제한 사항, namei()기능. 인코딩과 같은 사용자 수준의 프로그램에서 발생 xterm, firefox또는 ls.

나는 당신이 잘못된 구내에서 시작하고 있다고 생각합니다. Unix의 파일 이름은 임의의 값을 가진 바이트 문자열입니다. 0x0 (ASCII Nul) 및 0x2f (ASCII '/') 값은 멀티 바이트 문자 인코딩의 일부가 아닌 허용되지 않습니다. "바이트"는 문자를 나타내는 숫자 (ASCII 및 기타 인코딩)를 포함 할 수 있지만 "문자"는 1 바이트를 초과 할 수 있습니다 (예를 들어, UTF-8 유니 코드의 표현에서 0x7f 이상의 코드 포인트).

이러한 제한은 파일 이름 인쇄 규칙과 ASCII 문자 집합에서 발생합니다. 원래 유닉스는 ASCII '/'(숫자 0x2f) 값 바이트를 사용하여 부분적으로 또는 완전한 경로의 조각을 분리합니다 (예 : '/ usr / bin / cat'에는 "usr", "bin"및 "cat"조각이 있음) . 원래 유닉스는 ASCII Nul을 사용하여 문자열을 종료했습니다. 이 두 값 이외의 파일 이름의 바이트는 다른 값을 가정 할 수 있습니다. 유니 코드에 대한 UTF-8 인코딩에서이 에코를 볼 수 있습니다. '/'를 포함하여 인쇄 가능한 ASCII 문자는 UTF-8에서 1 바이트 만 사용합니다. 위의 코드 포인트에 대한 UTF-8에는 Nul 제어 문자를 제외하고 0 값 바이트가 포함되지 않습니다. UTF-8은 Unix의 왕좌에 대한 계획자인 Plan-9를 위해 발명되었습니다.

구 유닉스 (그리고 리눅스처럼 보인다)는 한 namei()번에 한 바이트 씩 경로를보고 0x2F 값 바이트에서 경로를 조각으로 나누고 0 값 바이트에서 멈추는 기능을했습니다. namei()유닉스 / 리눅스 / BSD 커널의 일부이므로 예외적 인 바이트 값이 적용됩니다.

지금까지 문자가 아닌 바이트 값에 대해 이야기했습니다. namei()바이트에 문자 의미를 강요하지 않습니다. ls바이트 값 또는 문자 값을 기준으로 파일 이름을 정렬 할 수 있는 사용자 수준 프로그램에 따라 다릅니다. xterm문자 인코딩을 기반으로 파일 이름에 어떤 픽셀을 밝힐 지 결정합니다. xtermUTF-8로 인코딩 된 파일 이름을 가지고 있지 않다면 호출 할 때 많은 횡설수설이 나타납니다. vimUTF-8 (또는 UTF-16, UTF-32) 인코딩을 감지하도록 컴파일되지 않은 경우 UTF-8 인코딩 문자가 포함 된 "텍스트 파일"을 열면 많은 횡설수설이 나타납니다.


맞습니다 namei(). 1986 년경에 포기되었습니다. 최신 UNIX 시스템 lookuppn()은 VFS 기반입니다.
schily

17

문제는 커널이 응용 프로그램이 파일 이름으로 제공된 데이터를 해석하는 방식을 조금 신경 쓰지 않는다는 것입니다.

UTF-16 문자열만을 처리하는 C 응용 프로그램이 있다고 가정 해 봅시다. 그리고 올바르게 구성된 입력 방법을 통해 "다른 이름으로 저장"프롬프트 / 대화 상자에 ∯ 기호 (유니 코드 0x222F)를 입력합니다.

응용 프로그램이 어떤 변환 형식도 수행하지 않고 일반 오래된 C 문자열 ( char*)로 fopen쓰기 모드로 보내면 커널은 ∯를 보지 못하거나 심지어 상상하려고 시도합니다. 두 개의 볼 char값, S, 하나씩 0x22 0x2F(가정 8 비트 문자 및 C 라이브러리 funnies 없음 ).
즉, 커널의 관점에서 유효한 문자 ( ") 다음에 /(ASCII 0x2F)가 옵니다 . fopen반환합니다 EISDIR(예 : "디렉토리와 같은 그 외모와는 쓰기 모드를 요청!").
내가 ∮ (유니 코드 0x222E)를 입력했다면 , 커널은 두 개의 문자를보고 ASCII를 사용하는 응용 프로그램을 통해 볼 수있는 파일을 만들었습니다 "..

내가 입력 한 경우 a파일 이름과 응용 프로그램 및 응용 프로그램이 커널에 UTF-16를 따라 통과, 커널은 읽을 것 0x00 0x61, 실제로조차 고려하지 0x61(가) 때문에, 0x00이미 지금까지 그대로 문자열을 종료 걱정. 오류 메시지는 빈 파일 이름과 같습니다 ( ENOENT믿습니다).

따라서 커널은 실제로 데이터를 한방울로 취합니다. 의 스트림입니다 char. 선택한 사용자 공간 인코딩에서 유효하지 않은 "문자"는 Blob (커널에 전달되는 이진 표현)에서 0x00또는 0x2F( "null"및 /) 을 생성하는 문자 입니다.


내가 당신을 올바르게 찾으면 유효하지 않은 문자는 없습니다. 유효하지 않은 바이트 시퀀스가 ​​있습니다. 그리고 값 0x000x2F커널에 하드 코딩되어 있습니다. 이는 디렉토리가로 분리되지 않고 사용중인 인코딩에서 /문자가 매핑되는 모든 것을 의미 0x2F합니다.
Marco

네, 그런 식으로보고 싶다면 아이디어입니다. (그러나 올바르지 않을 수 있습니다. 커널은 /0x2F가 아닌 "네이티브 인코딩"을 가질 수 있습니다 chars. 실제로 8 비트를 사용하지 않을 수도 있습니다 .) "전통적인"dir 구분자는 /입니다. 8 비트 바이트 ASCII (예 : EBCDIC 아님) 시스템에서는 0x27입니다.
Mat

UTF-16BE를 가정하지만 UTF-16LE에서는 U + 0061이 (널 종료) a문자열이됩니다.
Incnis Mrsi

4

바이트와 ​​문자의 분리는 유닉스가 디자인 된 이후 많은 부분을 차지했습니다. 그것이 디자인되었을 때 단어의 사용은 8 비트 (또는 6 비트 또는 9 비트)가 어떻게 해석 되었는 지에 관한 것만을 전달했지만 단어 인코딩 은 언급되지 않았습니다.

파일 이름은 바이트 시퀀스입니다. 0x2f "/"를 제외한 모든 바이트가 허용됩니다. 0x00을 포함하는 바이트는 문자열 터미네이터로 사용되어 커널을 통과 할 수 없습니다. 응용 프로그램은 선택한 인코딩에 따라 바이트 시퀀스를 해석 할 수 있습니다. 그것이 지저분하게 들린다 고 생각합니다.

http://www.gtk.org/api/2.6/glib/glib-Character-Set-Conversion.html에 유용한 정보가 더 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.