ทำความเข้าใจเกี่ยวกับการเข้ารหัสชื่อไฟล์ Unix


25

ฉันมีความเข้าใจยากว่าการเข้ารหัสชื่อไฟล์ทำงานอย่างไร ในยูนิกซ์ฉันพบคำอธิบายที่ขัดแย้ง

ชื่อไฟล์จะถูกเก็บไว้เป็นตัวละคร

เพื่ออ้างอิงคำตอบอื่น: คำถามหลายข้อเกี่ยวกับการเข้ารหัสอักขระระบบไฟล์บน linux

[…] ดังที่คุณพูดถึงคำถามของคุณชื่อไฟล์ UNIX เป็นเพียงลำดับของอักขระ เคอร์เนลไม่รู้อะไรเกี่ยวกับการเข้ารหัสซึ่งเป็นแนวคิดของพื้นที่ผู้ใช้ (เช่นระดับแอปพลิเคชัน)

หากชื่อไฟล์ถูกจัดเก็บเป็นตัวอักษรจะต้องมีการเข้ารหัสบางอย่างเนื่องจากในที่สุดชื่อไฟล์จะต้องลงท้ายด้วยลำดับบิตหรือไบต์บนดิสก์ หากผู้ใช้สามารถเลือกการเข้ารหัสใด ๆเพื่อแมปอักขระกับลำดับไบต์ที่ป้อนไปยังเคอร์เนลเป็นไปได้ที่จะสร้างลำดับไบต์ใด ๆสำหรับชื่อไฟล์ที่ถูกต้อง

สมมติว่าต่อไปนี้: ผู้ใช้ใช้การเข้ารหัสแบบสุ่มXซึ่งแปลไฟล์fooเป็นลำดับไบต์αและบันทึกลงดิสก์ อีกประการหนึ่งการใช้งานของผู้ใช้การเข้ารหัสY ในการเข้ารหัสนี้αแปลเป็น/ซึ่งไม่อนุญาตให้ใช้เป็นชื่อไฟล์ อย่างไรก็ตามสำหรับผู้ใช้คนแรกไฟล์นั้นถูกต้อง

ฉันคิดว่าสถานการณ์นี้ไม่สามารถเกิดขึ้นได้

ชื่อไฟล์จะถูกจัดเก็บเป็นไบนารี blobs

เพื่ออ้างอิงคำตอบอื่น: การ เข้ารหัสชุดอักขระใดที่ใช้สำหรับชื่อไฟล์และเส้นทางบน Linux

ดังที่ผู้อื่นระบุไว้ไม่มีคำตอบสำหรับเรื่องนี้จริงๆ: ชื่อไฟล์และเส้นทางไม่มีการเข้ารหัส ระบบปฏิบัติการเกี่ยวข้องเฉพาะกับลำดับของไบต์เท่านั้น แอปพลิเคชั่นส่วนบุคคลอาจเลือกที่จะตีความว่าเป็นการเข้ารหัสในบางวิธี แต่สิ่งนี้แตกต่างกันไป

หากระบบไม่จัดการกับตัวละครห้ามมีการห้ามเฉพาะอักขระ (เช่น/หรือNULL) ในชื่อไฟล์ได้อย่างไร ไม่มีแนวคิดเกี่ยวกับ/ การเข้ารหัส

คำอธิบายจะเป็นระบบไฟล์ที่สามารถจัดเก็บชื่อไฟล์ที่มี ตัวอักษรใด ๆและเป็นเพียงโปรแกรมผู้ใช้ที่ใช้การเข้ารหัสเข้าบัญชีที่จะทำให้หายใจไม่ออกในชื่อไฟล์ที่มีอักขระที่ไม่ถูกต้อง ซึ่งในที่สุดก็หมายถึงว่าระบบไฟล์และเคอร์เนลกระป๋องไม่มีปัญหาใด ๆ /ชื่อจับไฟล์ที่มี

ฉันก็คิดว่านี่เป็นสิ่งที่ผิด

การเข้ารหัสเกิดขึ้นที่ใดและข้อ จำกัด ถูกวางที่ใดที่ไม่อนุญาตให้ใช้อักขระเฉพาะ


Null เหมือนกัน (0) ในการเข้ารหัสทั้งหมด
เควิน

2
@ เควินไม่ค่อยมาก: ไม่พูดพูด UTF-16 หรือ UCS-4 (= UTF-32) หรือการเข้ารหัสมัลติไบต์อื่น ๆ ส่วนใหญ่ที่ไม่ใช่ส่วนขยายของ ASCII
Gilles 'หยุดความชั่วร้าย' ใน

1
อันที่จริงคำตอบ Riccardo Murri ของควรจะได้กล่าวถึงไบต์และไม่ได้ตัวละครที่มี ระบบไฟล์ส่วนใหญ่เก็บข้อมูลไบต์
Gilles 'หยุดความชั่วร้าย' ใน

@Gilles: อีกครั้งหนึ่งที่ฉันเห็นจริงๆคุณดูสิ่งที่จะเขียน
Incnis Mrsi

คำตอบ:


25

คำตอบสั้น ๆ : ข้อ จำกัด ที่กำหนดในเคอร์เนล Unix / Linux / BSD, namei()ฟังก์ชั่น การเข้ารหัสจะเกิดขึ้นในระดับผู้ใช้โปรแกรมเช่นxterm, หรือfirefoxls

ฉันคิดว่าคุณเริ่มต้นจากสถานที่ที่ไม่ถูกต้อง ชื่อไฟล์ใน Unix เป็นสตริงไบต์ที่มีค่าตามอำเภอใจ ไม่อนุญาตให้ใช้ค่าบางอย่าง 0x0 (ASCII Nul) และ 0x2f (ASCII '/') ไม่ใช่เป็นส่วนหนึ่งของการเข้ารหัสอักขระแบบหลายไบต์ไม่ใช่สิ่งใด ๆ "ไบต์" สามารถมีตัวเลขที่แสดงถึงตัวละคร (ใน ASCII และการเข้ารหัสอื่น ๆ ) แต่ "ตัวอักษร" อาจต้องการมากกว่า 1 ไบต์ (ตัวอย่างเช่นจุดโค้ดเหนือ 0x7f ในการแสดง UTF-8 ของ Unicode)

ข้อ จำกัด เหล่านี้เกิดจากข้อตกลงการพิมพ์ชื่อไฟล์และชุดอักขระ ASCII Unixes ดั้งเดิมใช้ ASCII '/' (ตัวเลข 0x2f) ที่มีค่าไบต์เพื่อแยกส่วนของเส้นทางแบบเต็มบางส่วนหรือที่ผ่านการรับรอง (เช่น '/ usr / bin / cat' มีชิ้น "usr", "bin" และ "cat") . Unixes ดั้งเดิมใช้ NII ASCII เพื่อยกเลิกสตริง นอกเหนือจากค่าสองค่าเหล่านี้ไบต์ในชื่อไฟล์อาจถือว่าเป็นค่าอื่น ๆ คุณสามารถเห็นเสียงสะท้อนนี้ในการเข้ารหัส UTF-8 สำหรับ Unicode อักขระ ASCII ที่พิมพ์ได้รวมถึง '/' ใช้เวลาเพียงหนึ่งไบต์ใน UTF-8 UTF-8 สำหรับจุดโค้ดข้างต้นไม่รวมไบต์ที่มีค่าใด ๆ ยกเว้นอักขระควบคุม Nul UTF-8 ถูกประดิษฐ์ขึ้นสำหรับ Plan-9, The Pretender to the Throne of Unix

Unixes รุ่นเก่า (และดูเหมือนว่า Linux) มีnamei()ฟังก์ชั่นที่ดูเส้นทางในแต่ละครั้งและแบ่งเส้นทางเป็นชิ้น ๆ ที่ 0x2F ซึ่งมีค่าเป็นไบต์หยุดที่ไบต์ที่มีค่าเป็นศูนย์ namei()เป็นส่วนหนึ่งของเคอร์เนล Unix / Linux / BSD ดังนั้นจึงมีการบังคับใช้ค่าไบต์พิเศษ

โปรดสังเกตว่าจนถึงตอนนี้ฉันได้พูดคุยเกี่ยวกับค่าไบต์ไม่ใช่ตัวอักษร namei()ไม่บังคับใช้ความหมายอักขระใด ๆ ในไบต์ ขึ้นอยู่กับโปรแกรมระดับผู้ใช้เช่นlsซึ่งอาจเรียงลำดับชื่อไฟล์ตามค่าไบต์หรือค่าอักขระ xtermตัดสินใจว่าพิกเซลใดที่จะสว่างขึ้นสำหรับชื่อไฟล์ตามการเข้ารหัสอักขระ หากคุณไม่บอกว่าxtermคุณมีชื่อไฟล์ที่เข้ารหัส UTF-8 คุณจะเห็นคำพูดไม่ได้มากมายเมื่อคุณเรียกใช้ หากvimไม่ได้รวบรวมเพื่อตรวจจับการเข้ารหัส UTF-8 (หรืออะไรก็ตาม UTF-16, UTF-32) คุณจะเห็นคำพูดไม่ได้มากมายเมื่อคุณเปิด "ไฟล์ข้อความ" ที่มีอักขระที่เข้ารหัส UTF-8


ถูกต้องnamei()ถูกทอดทิ้งราว ๆ ปี 1986 ระบบ UNIX ที่ใหม่กว่าlookuppn()นั้นใช้VFS
schily

17

เคอร์เนลไม่สนใจว่าแอพพลิเคชั่นจะตีความข้อมูลที่ให้เป็นชื่อไฟล์อย่างไร

ลองนึกภาพฉันมีแอปพลิเคชั่น C ที่เกี่ยวกับสตริง UTF-16 โดยเฉพาะ และฉันป้อนผ่านวิธีการป้อนข้อมูลที่กำหนดค่าอย่างเหมาะสมสัญลักษณ์ ((Unicode 0x222F) ลงในกล่องโต้ตอบ "บันทึกเป็น"

หากแอปพลิเคชันไม่ทำการแปลรูปแบบใด ๆ และส่งสิ่งนั้นในสตริง C แบบเก่า ( char*) ไปยังให้พูดfopenในโหมดเขียนเคอร์เนลจะไม่เห็น∯หรือลองจินตนาการดู มันจะเห็นสองchars หนึ่งหลังด้วยค่า0x22 0x2F(สมมติว่า 8 บิตตัวอักษรและไม่มี funnies ในไลบรารี C )
นั่นคือจากมุมมองของเคอร์เนลถ่านที่ถูกต้อง ( ") ตามด้วย/(ASCII 0x2F) fopenจะกลับมาEISDIR(เช่น "ที่ดูเหมือนไดเรกทอรีและคุณขอโหมดการเขียน!")
ถ้าฉันได้เข้า∮ (Unicode 0x222E) เคอร์เนลจะได้เห็นสองตัวอักษรดีและสร้างไฟล์ซึ่งเท่าที่เห็นผ่านแอปพลิเค ASCII ".ที่พูดจะได้รับการตั้งชื่อ

ถ้าฉันป้อนaแอปพลิเคชันเป็นชื่อไฟล์และแอปพลิเคชันส่งผ่านมันไปใน UTF-16 ไปยังเคอร์เนลเคอร์เนลจะอ่าน0x00 0x61และที่จริงไม่ได้คิดเช่นนั้น0x61เพราะ0x00สตริงยุติแล้วตราบใดที่มันเป็น ที่เกี่ยวข้อง ข้อความแสดงข้อผิดพลาดจะเหมือนกับชื่อไฟล์เปล่า ( ENOENTฉันเชื่อ)

ดังนั้นเคอร์เนลจึงใช้ข้อมูลเป็นหยด มันเป็นกระแสของchars "อักขระ" ที่ไม่ถูกต้องในการเข้ารหัสพื้นที่ผู้ใช้ที่คุณเลือกคือสิ่งที่สร้าง0x00หรือ0x2F("โมฆะ" และ/) ใน Blob (การแสดงไบนารีที่ส่งผ่านไปยังเคอร์เนล)


ถ้าฉันทำให้คุณถูกต้องไม่มีสิ่งนั้นเป็นตัวละครที่ไม่ถูกต้อง มีลำดับไบต์ที่ไม่ถูกต้อง และค่า0x00และ0x2Fถูกเข้ารหัสอย่างหนักในเคอร์เนล ในทางกลับกันหมายความว่าไดเรกทอรีนั้นไม่ได้คั่นด้วย a /แต่จะใช้กับสิ่งที่ตัวละครจับคู่กับ0x2Fการเข้ารหัสที่ใช้งานอยู่
Marco

ใช่นั่นคือความคิดถ้าคุณต้องการที่จะเห็นมันเป็นอย่างนั้น ( แต่ที่อาจจะไม่ถูกต้องเคอร์เนลอาจมี "การเข้ารหัสพื้นเมือง" ซึ่ง. /ไม่ได้ 0x2F - อาจจะไม่ใช้ 8 บิตcharsในความเป็นจริง.) ว่า "ดั้งเดิม" คั่น dir /คือ นั่นคือ 0x27 บน 8bit ไบต์ ASCII (ไม่ใช่ EBCDIC เป็นต้น) ระบบ
Mat

คุณสมมติว่า UTF-16BE ในขณะที่ใน UTF-16LE U + 0061 จะส่งผลให้เกิดaสตริง(สิ้นสุดด้วย null)
Incnis Mrsi

4

การแยกไบต์กับตัวละครเกิดขึ้นมากหลังจาก Unix ได้รับการออกแบบ เมื่อมันถูกออกแบบให้ใช้คำพูดเพียงบางอย่างเกี่ยวกับการตีความบิต 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.