# Řetězce, cesty, ‹openat› V této kapitole budeme pracovat se záznamy proměnné délky. Důležitým speciálním případem pak bude práce s řetězci a jejich kódováním. Přestože v praxi je nejběžnější kódování textu UTF-8, jazyk C99 ani POSIX pro práci s ním neposkytují přímou podporu. Zároveň je toto kódování poměrně složité, proto nebudeme v tomto předmětu UTF-8 nijak zpracovávat – omezíme se na situace, kde si vystačíme s PCS (Portable Character Set, viz též první ukázka) – jiné kódové body nebudeme interpretovat. Ukázky: 1. ‹strings› – základy práce s řetězci a textem, 2. ‹dirs› – nalezení / otevření obyčejného souboru, 3. ‹acrostic› – základy práce s UTF-16. Přípravy: 1. ‹long› – nalezení nejdelší nenulové posloupnosti, 2. ‹trunc› – čtení záznamů oddělených specifickým bajtem, 3. ‹cat› – spojení souborů zadaných zřetězeným seznamem, 4. ‹kvsd› – slovníkový server s úložištěm v souborovém systému, 5. ‹kvchk› – ověření přítomnosti klíče a asociované hodnoty, 6. ‹kvget› – dávkové stažení (linked list klíčů na vstupu). Řešené příklady: 1. ‹lines› – počítání řádků, 2. ‹utf16› – počítání výskytů znaku kódovaného v UTF-16, 3. ‹split› – hledání nejdelšího záznamu s dvoubajtovým oddělovačem, 4. ‹guess› – binární hádej na co myslím, 5. ‹cat› – načtení souboru se jmény souborů pro spojení, 6. ‹log› – jednoduchý server pro ukládání logů. ## Systémová volání V této kapitole přidáme systémové volání ‹openat›, které nám umožní získat popisovač pro existující obyčejný soubor, nebo takový soubor i vytvořit. Jinak budeme používat hlavně již dobře známá volání ‹read› a ‹write› (jak ke komunikaci, tak k zápisu a čtení dat z obyčejných souborů). Také budeme samozřejmě potřebovat voláni ‹close›, kterým popisovač uzavřeme (a uvolníme tím alokované zdroje). ### ‹openat› Pro vytvoření popisovače existuje několik systémových volání, ze kterých si tento týden ukážeme to nejdůležitější. Má 3 pevné a 1 volitelný parametr: 1. ‹int fd› je již existující popisovač, který je svázán «se složkou», vůči které budeme uvádět «cestu» – lze použít symbolickou hodnotu ‹AT_FDCWD›, která označuje tzv. pracovní složku, 2. ‹const char *path› je řetězec (ukončený nulou), který udává název, případně cestu (oddělovačem je znak ‹/›) k souboru, se kterým hodláme pracovat, 3. ‹int flags› je bitová kombinace příznaků – budou nás pro tuto chvíli zajímat symbolické hodnoty: ◦ ‹O_RDONLY›, ‹O_WRONLY› a ‹O_RDWR›, které určí jaké operace plánujeme později se souborem provádět, ◦ ‹O_CREAT› která nám umožní vytvořit nový obyčejný soubor, 4. ‹int mode› dodáváme pouze tehdy, když může operací vzniknout nový soubor (zejména obsahuje-li parametr ‹flags› příznak ‹O_CREAT›). ## Knihovní funkce Pro práci s vstupem, který obsahuje záznamy nebo pole předem neznámé délky vymezené oddělovačem, se nám může hodit knihovní podprogram ‹getdelim›. Přestože se jedná o podprogram normy POSIX, nepracuje přímo s popisovačem, ale s přenositelnou abstrakcí ‹FILE› jazyka C. Pravidla pro kombinovanou práci s popisovačem, ke kterému zároveň existuje ‹FILE› jsou relativně složitá, nebudeme proto tyto mechanismy míchat. Pro použití popisovače jej musíme svázat s proudem pomocí knihovního podprogramu ‹fdopen›. Nechceme-li popisovač při ukončení práce se strukturou ‹FILE› zavřít, musíme pro ‹fdopen› vyrobit duplikát použitím systémového volání ‹dup›. Pozor, ‹getdelim› nerozlišuje chybu čtení od konce vstupu. Je tedy nutné jej kombinovat s podprogramy ‹ferror› a ‹feof›. Po ukončení práce je potřeba proud uvolnit podprogramem ‹fclose›. Použití ‹getdelim› je nevhodné v situaci, kdy může být jednotlivý záznam velmi dlouhý, protože ‹getdelim› musí nutně celý záznam uložit do paměti najednou. Je-li to možné, je v těchto případech potřeba zpracovat vstup po částech pevné velikosti. Výjimku tvoří případ, kdy je beztak nutné mít celý záznam k dispozici najednou (např. proto, že se jedná o cestu k souboru).