| ← binární soubory | C/C++ | přímý přístup → |
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íme při vytváření a mazání respektovat,
zatímco například 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,
aby jste (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.
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.
char *getcwd(char *buf,size_t size);
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 větší než size) vrátí getcwd() ukazatel NULL.
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 Linux.
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. Proto jej zde nebudu řešit a odkážu vás na dokumentaci.
int mkdir(const char *pathname); /* DOSová verze */ int mkdir(const char *pathname, mode_t mode); /* LINUXová verze */
Argument pathname je pochopitelně jméno adresáře, který chceme 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 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).
int chmod(const char *path, mode_t mode);
První argument je cesta k souboru nebo adresáři, jehož práva měníme. 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().
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é).
int chdir(const char *path);
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.
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.
int remove(const char *pathname); int unlink(const char *pathname); int rmdir(const char *pathname);
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.
K přejmenování souboru 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ě:
int rename (const char *oldpath, const char *newpath);
Návratová hodnota v případě úspěchu je 0, jinak -1 a je nastavena proměnná errno.
Tentokrát bez komentáře.
1: /*------------------------------------------------*/ 2: /* adresar.c */ 4: #include <stdio.h> 5: #include <errno.h> 6: #ifdef unix 7: #include <unistd.h> 8: #include <sys/stat.h> 9: #include <sys/types.h> 10: #else 11: #include <dir.h> 12: #endif 14: #define ADRESAR "DATADIR" 15: #define SOUBOR "ahoj.txt" 17: #ifdef unix 18: #define MKDIR(X) mkdir(X,0777) 19: #else 20: #define MKDIR(X) mkdir(X) 21: #endif 23: int errkonec(void) 24: { 25: perror("CHYBA"); 26: fprintf(stderr, "Stisknete ENTER pro ukonceni ...\n"); 27: (void) getchar(); 28: return errno; 29: } 31: int main(void) 32: { 33: char text[255]; 34: FILE *soubor; 35: char c; 37: getcwd(text, sizeof(text) / sizeof(text[0])); 38: printf("Vytvarim v adresari %s podadresar %s\n", text, ADRESAR); 41: if (MKDIR(ADRESAR) != 0) { 42: return errkonec(); 43: } 45: printf("Vstupuji do adresare %s\n", ADRESAR); 46: if (chdir(ADRESAR) != 0) { 47: return errkonec(); 48: } 50: printf("Vytvarim soubor %s\n", SOUBOR); 52: if (!(soubor = fopen(SOUBOR, "wr"))) 53: return errkonec(); 55: fprintf(soubor, "Ahoj"); 56: fclose(soubor); 57: printf("Mam zase vse smazat? [y/n] "); 58: c = getchar(); 59: if (c == 'n') { 60: fputs("Koncim.", stdin); 61: return 0; 62: } else if (c != 'y') { 63: fputs("Nechapu, koncim.", stdin); 64: return 0; 65: } 67: /* mazani souboru a adresare */ 68: printf("Mazu soubor %s\n", SOUBOR); 69: if (unlink(SOUBOR) != 0) { 70: return errkonec(); 71: } 73: printf("Opoustim adresar %s\n", ADRESAR); 74: /* prechod v adresarove strukture o adresar vyse */ 75: if (chdir("..") != 0) { 76: return errkonec(); 77: } 79: printf("Mazu adresar %s\n", ADRESAR); 80: if (rmdir(ADRESAR) != 0) { 81: return errkonec(); 82: } 84: return 0; 85: } 87: /*------------------------------------------------*/
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ář funkcí mkdir().
| ← binární soubory | C/C++ | přímý přístup → |
