Adresářová struktura
Kolem práce s adresářovou strukturou je spousta problémů. Jde o to, že různé operační systémy používají rozličné způsoby uchovávání dat. Například v Unixech existují ke každému souboru a adresáři přístupová práva, která musíte při vytváření a mazání respektovat, zatímco třeba v DOSu nikoliv. Zde probírané funkce se proto liší systém od systému, překladač od překladače.
Příklad, který najdete na konci kapitoly, byl odladěn v operačním systému Linux, v DOSovém překladači Borland C a windowsovém Dev-C++. Měl by vám být dostatečným návodem k tomu, abyste (s pomocí nápovědy) dokázali vše, co zde bude popisováno.
Jo a ještě jeden problém tu je. Deklarace těch samých funkcí v různých překladačích jsou v různých hlavičkových souborech. Proto je zde nebudu uvádět (hledejte si sami, už jste dost velký :-). V Linuxu hledejte v manuálových stránkách v sekci 2 a 3. Trochu vám může napovědět příklad na konci této kapitoly.
Aktuální adresář
Ke zjištění aktuálního adresáře slouží funkce
getcwd()
.
Aktuální adresář je ten, ve kterém se nacházíte při spouštění
programu, nikoliv ten, ve kterém se nachází spouštěný program.
První argument, buf, je ukazatel na textové
pole, kam se uloží název aktuálního adresáře. Druhý argument,
size, je maximální
velikost, která se do pole může uložit. V případě chyby (např.
jméno aktuálního adresáře je delší než size)
vrátí getcwd()
ukazatel NULL
.
Vytvoření adresáře
K vytvoření adresáře se používá funkce mkdir()
.
Bohužel zde narážíme na již zmíněný problém s kompatibilitou různých operačních
systémů/překladačů. Proto zde uvedu dvě deklarace funkce mkdir()
. První je pro
DOSový překladač Borland C, druhá pro Linuxový překladač gcc.
V Linuxu mají adresáře
(i soubory) přístupová práva.
Ty umožňují, mimo jiné, zabránit
zápisu do adresáře. Jelikož však budeme chtít do vytvořeného
adresáře vstoupit nebo do něj něco zapsat, je třeba mu nastavit
správně práva. Proto má funkce mkdir()
v Linuxu jeden argument navíc. Přístupová práva se navíc kombinují s hodnotou
umask.
Tento problém však přesahuje rámec výuky jazyka C, ale týká se
spíše operačních systémů Unix/Linux. Proto jej zde nebudu řešit a odkážu
vás na dokumentaci. Odkazuji vás na dokumentaci.
Argument pathname je pochopitelně jméno
adresáře, který chcete vytvořit. Může to být například "jmeno", nebo
"../jmeno" atp. Dvě tečky, jak jistě víte, označují
předchozí adresář v adresářové struktuře. Lomítko je oddělovač jmen
adresářů. Ovšem pozor, v DOSu (Windows) je to obrácené
lomítko \
(backslash), kdežto v Unixech obyčejné
/
. Za to, že je to jinak, nenadávejte Unixům, ty tu byli dříve.
Argument mode v deklaraci
mkdir()
pro Unixy určuje
přístupová práva. Přesněji řečeno, přístupová práva k souboru budou
nastavena jako mode & ~umask
.
Návratovou hodnotou je 0 v případě, že vše proběhlo bez chyby. Při chybě -1 a je nastavena globální proměnná errno na číslo chyby.
Přístupová práva
Přístupová práva k souborům a adresářům se nastavují pomocí funkce
chmod()
definované v
hlavičkovém souboru <sys/stat.h>, <io.h>, nebo nějakém
jiném (záleží na prostředí, ve kterém zdrojový kód překládáte).
První argument je cesta k souboru nebo adresáři, jehož práva měníte. Druhý argument nastavuje přístupová práva. Funkce vrací 0 v případě úspěchu, jinak -1 a nastavuje proměnnou errno.
Parametr mode můžete nastavit pomocí
maker definovaných v <sys/stat.h>, ovšem musíte si dát pozor na to,
která makra jsou pro váš systém dostupná. Ve Windows to můžete použít
například S_IREAD | S_IWRITE
pro právo čtení a zápisu. V Linuxu se podívejte do manuálových stránek,
jaká jsou dostupná makra (man 2 chmod
).
Když v programu vytvoříte soubor nebo adresář, nemáte jistotu, jaká jsou na něm
nastavena přístupová práva. A to ani při použití argumentu mode ve funkci
mkdir()
, protože výsledná práva mohou být ovlivněna
nastavením OS, například v Linuxu pomocí umask. Chcete-li mít
jistotu, musíte použít po vytvoření souboru nebo adresáře funkci
chmod()
.
Změna aktuálního adresáře
Aktuální adresář se změní pomocí funkce
chdir()
. Je dobré
vědět, že změna aktuálního adresáře se projeví dozajista jen v
programu, který tuto funkci spustil. Jestli v tomto adresáři
zůstanete i po skončení onoho programu, nebo po skončení programu
budete v adresáři, ze kterého jste program spustili, to už závisí
na jiných věcech (napovím: v DOSu platí to první, v Unixech
nejčastěji to druhé).
Argumentem funkce je adresář, do kterého se chcete přesunout. Návratová hodnota je v případě úspěchu 0, jinak -1 a je nastavena proměnná errno.
Mazání souborů a adresářů
Dle normy ANSI C slouží k mazání souborů a adresářů funkce
remove()
. Leč většinou je tato
funkce nahrazena dvěma jinými funkcemi. Funkcí unlink()
pro mazání souborů a funkcí rmdir()
pro mazání prázdných
adresářů.
Funkce remove()
volá funkci
unlink()
pro soubory a funkci rmdir()
pro adresáře.
Argument pathname je jméno souboru resp. adresáře, který chcete smazat. Návratové hodnoty jsou v případě úspěchu 0, jinak -1 a je nastavena proměnná errno.
Adresář lze smazat pouze pokud je prázdný.
Přejmenování a přesunutí souborů
K přejmenování souboru či adresáře slouží funkce
rename()
. Pokud bude nové
jméno souboru v jiném adresáři než staré jméno, pak se soubor
přesune. K tomu však dojde jedině v případě, že staré a nové jméno
je na jednom disku (diskovém oddíle). Pokud bude nové jméno jméno
již existujícího souboru, bude tento soubor přepsán! Deklarace
funkce vypadá následovně:
Návratová hodnota v případě úspěchu je 0, jinak -1 a je nastavena proměnná errno.
Příklad
Tentokrát bez komentáře.
- /*------------------------------------------------*/
- /* c34/adresar.c */
- #define _CRT_SECURE_NO_WARNINGS
- #include <stdio.h>
- #include <errno.h>
- #ifdef __unix__
- #include <unistd.h>
- #include <sys/stat.h>
- #include <sys/types.h>
- #elif defined _MSC_VER
- #include <direct.h<<?php ?>
- #else
- #include <dir.h>
- #endif
- #define ADRESAR "DATADIR"
- #define SOUBOR "ahoj.txt"
- #ifdef __unix__
- #define GETCWD(X, I) getcwd(X, I)
- #define MKDIR(X) mkdir(X, 0777)
- #define CHDIR(X) chdir(X)
- #define UNLINK(X) unlink(X)
- #define RMDIR(X) rmdir(X)
- #elif defined _MSC_VER
- #define GETCWD(X, I) _getcwd(X, I)
- #define MKDIR(X) _mkdir(X)
- #define CHDIR(X) _chdir(X)
- #define UNLINK(X) _unlink(X)
- #define RMDIR(X) _rmdir(X)
- #else
- #define GETCWD(X, I) getcwd(X, I)
- #define MKDIR(X) mkdir(X)
- #define CHDIR(X) chdir(X)
- #define UNLINK(X) unlink(X)
- #define RMDIR(X) rmdir(X)
- #endif
- {
- return errno;
- }
- {
- FILE *soubor;
- char c;
- }
- }
- }
- /* mazani souboru a adresare */
- }
- /* prechod v adresarove strukture o adresar vyse */
- }
- }
- }
- /*------------------------------------------------*/
Funkce mkdir()
a jí podobné nejsou součástí standardu C89, ani C99.
Jsou součástí standardu POSIX. Standard C++ se rozhodl o něco později tyto funkce zahrnout,
ale aby se nepletli s POSIX normou, pojmenoval je s podtržítkem na začátku: _mkdir()
atp.
Visual Studio nepodporuje funkce bez podtržítka, ale můžete použít funkce z C++ standardu i v jazyku C.
Možný výstup:
Vytvarim v adresari /home/rimmer/public_html/rimmer/c podadresar DATADIR Vstupuji do adresare DATADIR Vytvarim soubor ahoj.txt Mam zase vse smazat? [y/n] y Mazu soubor ahoj.txt Opoustim adresar DATADIR Mazu adresar DATADIR
Za domácí úkol použijte v příkladu funkci
chmod() na nově vytvořený adresář
po volání funkce mkdir()
.