lördag 3 oktober 2009

Unison, unicode och kompatibilitetsproblem

Jag har försökt att få synkroniseringsprogrammet unison att fungera i mac os x.
Min server använder utf-8 som teckenkodning på filsystemet. Vad mac använder verkar vara normaliserad utf-8 (se här för intressant läsning).
Unison funkar inte alls särskilt bra för mig på sökvägar som innehåller icke-ascii-tecken. En katalog som heter "företag" dupliceras till originalet och en kopia som renderas likadant med en annorlunda representation. Dvs filnamnet är binärt olika men bokstäverna är samma. Det är just detta som unicode-normalisering strävar efter att lösa.
Först trodde jag att det är unison som är boven i dramat, men det är snarare Apples fel! Citerat ur manualsidan för convmv:
Filesystem issues

Almost all POSIX filesystems do not care about how filenames are encoded, here are some exceptions:

HFS+ on OS X / Darwin

Linux and (most?) other Unix-like operating systems use the so called normalization form C (NFC) for its UTF-8 encoding by default
but do not enforce this. Darwin, the base of the Macintosh OS enforces normalization form D (NFD), where a few characters are
encoded in a different way. On OS X it’s not possible to create NFC UTF-8 filenames because this is prevented at filesystem layer.
On HFS+ filenames are internally stored in UTF-16 and when converted back to UTF-8, for the underlying BSD system to be handable,
NFD is created. See http://developer.apple.com/qa/qa2001/qa1173.html for defails. I think it was a very bad idea and breaks many
things under OS X which expect a normal POSIX conforming system. Anywhere else convmv is able to convert files from NFC to NFD or
vice versa which makes interoperability with such systems a lot easier.



Nog med inledning, detta fick mig att läsa på lite om unicode.
Jag använder mitt katalognamn "företag" som exempel.
Det kodas i utf-8 som
66 c3 b6 72 65 74 61 67

ö-et blir alltså hex c3-b6 eller binärt 11000011 10110110 där jag markerat utf-8-prefixen med fetstil. Payload är alltså 11 konkatenerat med 110110 villket är F6 hex som är "direktformen" för ö, eller "Latin Small Letter O with diaeresis" som det heter. Låter snarare som en sjukdom....

Om jag nu kollar vad som hänt på servern ser jag att det finns två mappar som heter företag.
$ls |grep retag
företag
företag
en undersökning av representationen (genom att pipa till hexdump -C) ger (jag har tagit bort newline 0a manuellt):
66 6f cc 88 72 65 74 61 67
66 c3 b6 72 65 74 61 67
ö-et kodas alltså som 6f cc 88 i det första fallet och c3 b6 i det andra (som jag förväntat mig.)
En avkodning enligt ovan ger att 6f är bokstaven o, och prickarna kommer till i efterhand genom cc 88 som binärt är 11001100 10001000 och lasten därmed 0x308 som betyder två prickar(leta efter rad med 0300 i vänstra kolumnen och kolumn med huvud "8").
Det som behövs för att unison ska förstå att dessa två filnamn egentligen är samma är normalisering.
Det är verkligen inte trivialt att hantera teckenkodning korrekt!

3 kommentarer:

Albin Rangefelt sa...

Hade precis samma problem :) Se http://stayinsync.net/2009/04/enable-unicode-normalization-in-unison/

I senaste unison trunken är dock detta fixat! Se: http://stayinsync.net/2010/01/native-unison-unicode-support/

Paul Dreik sa...

Tack Albin för tipset!
Jag lyckades också att få det att fungera, genom att kompilera trunken både på servern (Debian) och lokala värden (Mac Os X) och peka ut sökvägen i unisons profil.
Det får blir ett separat inlägg om detta!

Anonym sa...

lart mycket