Saya mengalami kesulitan memahami cara kerja pengkodean nama file. Pada unix.SE saya menemukan penjelasan yang bertentangan.
Nama file disimpan sebagai karakter
Mengutip jawaban lain: Beberapa pertanyaan tentang pengkodean karakter sistem file di linux
[...] seperti yang Anda sebutkan dalam pertanyaan Anda, nama file UNIX hanyalah serangkaian karakter; kernel tidak tahu apa-apa tentang pengkodean, yang seluruhnya merupakan konsep ruang pengguna (yaitu, level aplikasi).
Jika nama file disimpan sebagai karakter, harus ada semacam pengkodean, karena akhirnya nama file harus berakhir sebagai urutan bit atau byte pada disk. Jika pengguna dapat memilih pengodean apa pun untuk memetakan karakter ke urutan byte yang diumpankan ke kernel, dimungkinkan untuk membuat urutan byte apa pun untuk nama file yang valid.
Asumsikan sebagai berikut: Pengguna menggunakan pengodean acak X , yang menerjemahkan file foo
ke dalam urutan byte α dan menyimpannya ke disk. Lain penggunaan pengguna encoding Y . Dalam encoding ini α diterjemahkan menjadi /
, yang tidak diizinkan sebagai nama file. Namun, untuk pengguna pertama file tersebut valid.
Saya berasumsi bahwa skenario ini tidak dapat terjadi.
Nama file disimpan sebagai gumpalan biner
Mengutip jawaban lain: Pengkodean charset apa yang digunakan untuk nama file dan jalur di Linux?
Seperti dicatat oleh orang lain, sebenarnya tidak ada jawaban untuk ini: nama file dan jalur tidak memiliki penyandian; OS hanya menangani urutan byte. Aplikasi individual dapat memilih untuk menafsirkannya sebagai dikodekan dalam beberapa cara, tetapi ini bervariasi.
Jika sistem tidak berurusan dengan karakter, bagaimana bisa karakter tertentu (misalnya /
atau NULL
) dilarang dalam nama file? Tidak ada gagasan tentang /
tanpa pengkodean.
Penjelasannya adalah bahwa sistem file dapat menyimpan nama file yang mengandung
karakter apa pun dan hanya program pengguna yang memasukkan pengkodean ke dalam akun yang akan mencekik nama file yang mengandung karakter yang tidak valid. Itu, pada gilirannya, berarti bahwa sistem file dan kernel dapat, tanpa kesulitan, menangani nama file yang mengandung a /
.
Saya juga berasumsi bahwa ini salah.
Di mana pengkodean berlangsung dan di mana batasan yang diajukan tidak mengizinkan karakter tertentu?
Jawaban:
Jawaban singkat: pembatasan diberlakukan di kernel Unix / Linux / BSD,
namei()
berfungsi. Pengkodean berlangsung di program tingkat pengguna sepertixterm
,firefox
atauls
.Saya pikir Anda mulai dari tempat yang salah. Nama file di Unix adalah serangkaian byte dengan nilai arbitrer. Beberapa nilai, 0x0 (ASCII Nul) dan 0x2f (ASCII '/') tidak diperbolehkan, bukan sebagai bagian dari pengkodean karakter multi-byte, bukan sebagai apa pun. "Byte" dapat berisi angka yang mewakili karakter (dalam ASCII dan beberapa pengkodean lainnya) tetapi "karakter" dapat membutuhkan lebih dari 1 byte (misalnya, titik kode di atas 0x7f dalam representasi UTF-8 dari Unicode).
Pembatasan ini muncul dari konvensi pencetakan nama file dan set karakter ASCII. Unix yang asli menggunakan ASCII '/' (numerik 0x2f) yang bernilai byte untuk memisahkan bagian-bagian dari jalur yang sebagian atau sepenuhnya memenuhi syarat (seperti '/ usr / bin / cat' memiliki bagian "usr", "bin" dan "cat") . Unix asli menggunakan ASCII Nul untuk mengakhiri string. Selain kedua nilai tersebut, byte dalam nama file dapat mengasumsikan nilai lainnya. Anda dapat melihat gema ini dalam pengkodean UTF-8 untuk Unicode. Karakter ASCII yang dapat dicetak, termasuk '/', hanya membutuhkan satu byte dalam UTF-8. UTF-8 untuk poin kode di atas tidak termasuk byte bernilai Nol, kecuali untuk karakter kontrol Nul. UTF-8 diciptakan untuk Plan-9, The Pretender to Throne of Unix.
Older Unixes (dan kelihatannya seperti Linux) memiliki
namei()
fungsi yang hanya melihat jalur byte pada satu waktu, dan memecah jalur menjadi potongan-potongan pada 0x2F dihargai byte, berhenti pada byte bernilai nol.namei()
adalah bagian dari kernel Unix / Linux / BSD, jadi di situlah nilai byte yang luar biasa ditegakkan.Perhatikan bahwa sejauh ini, saya sudah bicara tentang nilai byte, bukan karakter.
namei()
tidak menerapkan semantik karakter apa pun pada byte. Terserah program tingkat pengguna, sepertils
, yang mungkin mengurutkan nama file berdasarkan nilai byte, atau nilai karakter.xterm
memutuskan piksel apa yang menyala untuk nama file berdasarkan pengkodean karakter. Jika Anda tidak memberi tahuxterm
Anda memiliki nama file yang disandikan UTF-8, Anda akan melihat banyak omong kosong ketika Anda memintanya. Jikavim
tidak dikompilasi untuk mendeteksi pengkodean UTF-8 (atau apa pun, UTF-16, UTF-32), Anda akan melihat banyak omong kosong ketika Anda membuka "file teks" yang berisi karakter yang dikodekan dari UTF-8.sumber
namei()
ditinggalkan sekitar tahun 1986. Penggunaan sistem UNIX barulookuppn()
berbasis VFS.Masalahnya, kernel tidak peduli sedikitpun bagaimana aplikasi menafsirkan data yang diberikan sebagai nama file.
Mari kita bayangkan saya memiliki aplikasi C yang berhubungan dengan string UTF-16 secara eksklusif. Dan saya masuk, melalui metode input yang dikonfigurasi dengan benar, simbol ∯ (Unicode 0x222F) ke dalam prompt / dialog "Simpan Sebagai".
Jika aplikasi tidak melakukan bentuk terjemahan apa pun dan mengirimkannya, dalam string C lama (
char*
) ke, katakanlah,fopen
dalam mode tulis, kernel tidak akan melihat ∯, atau bahkan mencoba membayangkannya. Ini akan melihat duachar
s, satu demi satu, dengan nilai-nilai0x22 0x2F
(dengan asumsi 8bit karakter dan tidak ada lelucon di perpustakaan C ).Yaitu, dari sudut pandang kernel, karakter yang valid (
"
) diikuti oleh/
(ASCII 0x2F).fopen
akan kembaliEISDIR
(yaitu "yang terlihat seperti direktori dan Anda meminta mode tulis!").Jika saya memasukkan ∮ (Unicode
0x222E
), kernel akan melihat dua karakter yang bagus, dan membuat file yang, seperti terlihat melalui aplikasi yang berbicara ASCII, akan dinamai".
.Jika saya telah memasukkan
a
dalam aplikasi sebagai nama file, dan aplikasi meneruskannya di UTF-16 ke kernel, kernel akan membaca0x00 0x61
, dan sebenarnya bahkan tidak mempertimbangkan itu0x61
, karena0x00
sudah mengakhiri string, sejauh itu prihatin. Pesan kesalahan akan sama dengan nama file kosong (ENOENT
saya percaya).Jadi kernel memang mengambil data sebagai gumpalan. Ini aliran
char
s. "Karakter" yang tidak valid dalam pengkodean ruang-pengguna pilihan Anda adalah yang menghasilkan0x00
atau0x2F
("null" dan/
) di gumpalan mereka (representasi biner yang diteruskan ke kernel).sumber
0x00
dan0x2F
dikodekan dalam kernel. Itu pada gilirannya berarti, bahwa direktori tidak dipisahkan oleh a/
, tetapi untuk karakter apa pun peta ke0x2F
dalam pengkodean yang digunakan./
tidak 0x2F - mungkin tidak menggunakan 8-bitchars
, pada kenyataannya.) Pemisah dir "tradisional" adalah/
. Itu adalah 0x27 pada sistem ASCII 8bit byte (bukan EBCDIC misalnya).a
string (null-dihentikan) .Pemisahan byte vs karakter muncul setelah Unix dirancang. Ketika itu dirancang penggunaan kata-kata hanya menyampaikan sesuatu tentang bagaimana 8 (atau 6, atau 9) bit ditafsirkan tetapi kata penyandian tidak disebutkan.
Nama file adalah urutan byte. Setiap byte kecuali 0x2f "/" diizinkan. Sebuah byte yang berisi 0x00 bahkan tidak dapat menembus kernel karena penggunaannya sebagai terminator string. Suatu aplikasi dapat menginterpretasikan urutan byte menurut suatu encoding yang dipilihnya. Jika itu terdengar berantakan saya kira begitu.
Ada informasi lebih lanjut di http://www.gtk.org/api/2.6/glib/glib-Character-Set-Conversion.html Anda mungkin menemukan berguna.
sumber