FAQ ku C a sluzbam Unix-u Flashcards
Práca s adresárovou štruktúrou a súbormi( readdir, stat, …)
Čo znamená v zadaniach spomínaný termín “plná cesta” ?
Je to cesta z aktuálneho, alebo koreňového adresára ?
Čo je absolútna a relatívna cesta, je asi jasné.
Plnou cestou je myslená celá cesta od zadaného adresára až po nájdený súbor (teda môže to byt aj relatívna aj absolútna cesta - podľa toho, ako je zadaný adresár).
Práca s adresárovou štruktúrou a súbormi( readdir, stat, …)
Pod pojmom obyčajný súbor si mam predstaviť iba txt alebo aj bin ?
Obyčajný súbor = regular file, t.j. nie adresár, nie sym. linka, nie device, …
Práca s adresárovou štruktúrou a súbormi( readdir, stat, …)
V ukážkovom príklade Listdir.c sa robí s funkciou readdir. Tá je síce popísaná aj v manuáli aj na školskom webe (dokumentácia ku knižnici libc) no z toho som nepochopil napríklad čo je to d_namlen a d_name, pripadne či sú nejaké ďalšie premenné, ktoré by mi mohli pomôcť. Môžem dostať nejaké vysvetlenie?
Existuje niekde lepší popis tejto a ostatných funkcii, ktoré potrebujeme?
Keď si pozriete man readdir, tak na konci je sekcia “SEE ALSO”, teda odkazy na manuály, ktoré Vám môžu tiež pomôcť. Medzi nimi je aj odkaz na man dir - je tam celkom slušne popísaná štruktúra adresára.
Ďalšie zaujímavé informácie môžete nájsť aj v hlavičkových súboroch. Na tie Vás zase odporúča sekcia “SYNOPSIS” na začiatku manuálovej stránky.
Príslušné súbory nájdete v adresári /usr/include .
Práca s adresárovou štruktúrou a súbormi( readdir, stat, …)
Kde nájdem popis štruktúry direct ?
(nenašiel som ani v dirent.h, ani v sys/types.h)
Keby ste urobili grep -w direct /usr/include/*/*.h ,
zistili by ste, že v sys/dir.h je:
#define direct dirent
Práca s adresárovou štruktúrou a súbormi( readdir, stat, …)
Čo je to d_ino ?
while ((dir = readdir(dp)) != NULL) {if (dir->d_ino == 0) continue; … }
Je to položka, obsahujúca číslo i-uzlu, na ktorý odkazuje príslušná položka adresára.
Ak je nulová, znamená to, že príslušná položka adresára nie je použitá.
Práca s adresárovou štruktúrou a súbormi( readdir, stat, …)
Prečo mi stat(….) a S_ISREG(..) berie symbolické linky ako regulárne súbory ? Dá sa to nejako spraviť aby ich bral ako linky ?
Ide o to, že keď urobíte stat na symbolickú linku, vráti Vám informácie u súbore, na ktorý daná linka ukazuje. Keď chcete informácie o linke samotnej, použite lstat.
Práca s adresárovou štruktúrou a súbormi( readdir, stat, …)
Ako sa pomocou readdir dozviem, či vypisovaný súbor je súbor, adresár, link a podobne?
Cez readdir sa to nedá spraviť. Treba sa pozrieť na funkciu stat (a lstat, pozrite si “man lstat”) a použiť makro S_IFDIR().
Práca s adresárovou štruktúrou a súbormi( readdir, stat, …)
Aký je rozdiel medzi položkou st_mode v struct stat so statusom S_IFREG a položkou d_type v struct dirent so statusom DT_CHR ?
Položka stat.st_mode obsahuje typ súboru, tak ako ho zistí funkcia stat. Položka dirent.d_type tiež zrejme obsahuje typ súboru a predpokladám, že readdir po načítaní urobí príslušný stat a naplní položku.
Práca s adresárovou štruktúrou a súbormi( readdir, stat, …)
Ako sa dá zistiť, na aký súbor ukazuje daný symbolický link ?
Skúste sa pozrieť na systémové volanie readlink.
Práca s adresárovou štruktúrou a súbormi( readdir, stat, …)
Dá sa nejako zadať veľkosť súboru ? Prípadne, aby sa dynamicky zväčšil súbor a podobne ?
Keď otvoríte súbor a zapisujete doň, tak sa veľkosť automaticky zväčšuje, teda koľko zapíšete, taký je veľký. Keď už súbor existuje a chcete ho zväčšiť, musíte sa buď pred zápisom presunúť na koniec súboru (lseek a potom write) alebo otvoriť súbor na pridávanie (fopen(…, “a”)).
Práca s adresárovou štruktúrou a súbormi( readdir, stat, …)
Prečo mi volanie readlink vždy vráti errno == 0 aj v prípade, že zruším cieľový súbor (kam daná linka ukazuje) ?
Nuž je to veľmi jednoduché, pretože volanie readlink Vám vráti obsah linky, teda konkrétne tu cestu, kam symbolická linka ukazuje (teda nie obsah toho súboru - na to stačí obyčajný read). No a samozrejme keď cieľový súbor zrušíte, tak linka stále existuje a môžete zistiť cestu kam ukazuje.
Práca s adresárovou štruktúrou a súbormi( readdir, stat, …)
Ako mám rekurzívne prehľadávať adresáre, mám ich prehľadávať tak, že budem nasledovať aj linky ? (teda, čí mam použiť stat alebo lstat.)
Je symbolická linka adresár ?
Práca s adresárovou štruktúrou a súbormi( readdir, stat, …)
Ako sa dá predísť (vyhnúť) chybe “Too many open files” pri použití funkcie opendir ?
Tato chyba vzniká, keď vyčerpáte limit na počet súčasne otvorených súborov na proces. Vyhnete sa jej jednoducho - všetky už nepotrebné otvorené súbory (aj adresáre) zatvárajte.
Práca s adresárovou štruktúrou a súbormi( readdir, stat, …)
Robím rekurzívne prehľadávanie adresárov. Inkludujem súbor dir.h a mám s tým problémy. Čo s tým ?
Pri rekurzii treba inkludovať novší súbor dirent.h a nie dir.h. Pozor - súbor dirent.h sa na ose nachádza dva krát. Treba ho inkludnuť zo štandartnej c-čkovskej knižnice, teda:
#include
a nie #include .
Týmto vlastne zamedzíme varovným hláškam pri kompilácii. Ešte jedna zmena pri novom spôsobe: definujeme
“struct dirent *dir”;
a nie
“struct direct *dir”;
ako pri starom.
Práca s adresárovou štruktúrou a súbormi( readdir, stat, …)
Pri rekurzívnom prehľadávaní veľkého adresára (napr. /) mi fork vypisuje chybu, errno = 35, (niekde mi to funguje bez problémov).
Z manuálu som vyčítal, že tento error je “temporary” a že nové volanie forku môže byť úspešné. (Na nájdené súbory ďalej púšťam grep.)
Chyba je asi spôsobená tým, že ste počas behu programu vyčerpali kvótu na počet procesov (32 na ose, 2048 na linux-e). A zrejme sa to stalo tak, že na každý nájdený súbor spúšťate grep, ale zabúdate počkať na jeho ukončenie a prevziať status cez volanie wait. Tak sa stane, že sa Vám nazbiera veľa skončených grep-ov, ktoré už len čakajú na to, aby si ich exit status prevzal ich rodič (sú z nich zombie - živé mŕtvoly - po exit-e).
Práca s adresárovou štruktúrou a súbormi( readdir, stat, …)
int fdr; FILE* fr; …. fdr=open(… fr=fdopen(fdr,… fclose(fr);
Budem mat v tomto okamihu closnuty aj fdr alebo ho mozem dalej pouzivat ?? Predpokladam prvu moznost len si chcem byt na istom
Funkcia fdopen len “prilepi” vrstvu nad deskriptor, takze fclose sa sprava tak, ako keby to bolo otvorene cez fopen (takze zavrie aj deskriptor - urobi close).
Práca s adresárovou štruktúrou a súbormi( readdir, stat, …)
Da sa nejako zistit, ci dany subor existuje bez toho, aby som sa ho pokusal otvarat? WIN/DOS mal findfirst/findnext, ale na ose som zatial ziadny ekvivalent nenasiel.
V Unix-e mate k dispozicii opendir, readdir a closedir. To Vam uplne staci ;-).
Práca s adresárovou štruktúrou a súbormi( readdir, stat, …)
Vo FAQ je otazka ci sa da pomocou funkcie readdir zistit ci vypisovany subor je subor,adresar,link a podobne. Odpoved je ze nie treba pouzit stat.
Lenze: readdir nam vracia pointer na strukturu direct co je ale vlastne struktura dirent:
struct dirent { __uint32_t d_fileno; /* file number of entry */ __uint16_t d_reclen; /* length of this record */ __uint8_t d_type; /* –> file type, see below o trosku dalej su definovane konstanty pre d_type:
/* * File types */ #define DT_UNKNOWN 0 #define DT_FIFO 1 #define DT_CHR 2 #define DT_DIR 4 #define DT_BLK 6 #define DT_REG 8 #define DT_LNK 10 #define DT_SOCK 12 #define DT_WHT 14
ked som to vyskusal funguje to, je chyba vo faq ?
Nie. Nie je to chyba.
Ide o to, ze suborovy system v BSD sa snazi optimalizovat pristup k informaciam o suboroch a preto ma typ suboru skopirovany aj do polozky adresara - tym vlastne odstranuje jedno citanie z disku. Ked sa ale pozriete na strukturu dirent napr. v Linux-e, tak tam polozka d_type nie je (resp. v strukture je, ale nehovori sa o nej v manuali). V Solarise (system zalozeny na System V vetve Unix-ov) nie je ani v strukture. Preto Vam teda odporucam vyhnut sa jej pouzivaniu.
Práca s adresárovou štruktúrou a súbormi( readdir, stat, …)
Ako sa da zistit, ze ci dany spusteny program ma pravo citat/zapisovat/spustat iny subor bez toho aby to skusil a cakal na chybove hlasenie?
Sluzi na to systemove volanie access(const char *path, int mode).
Práca s adresárovou štruktúrou a súbormi( readdir, stat, …)
Vytvorenie suboru s pravami.
fd=open(“aaa.aaa”,O_CREAT|O_WRONLY,0666);
mi vytvori subor s divnymi pravami rw-r–r–
a ja som cakal rw-rw-rw-
Neviete v com to moze byt?
Program zdedil masku nedovolujucu zapisat vacsie prava,
default je S_IWGRP|S_IWOTH (022) (takze write pre grupu a svet urcite nepovoli)
preto najprv pouzi umask:
umask(0);
v tomto pripade by vsak stacilo:
umask(S_IXOTH|S_IXGRP|S_IXUSR);
Volania exec, execlp - spúšťanie externých programov
Môžem používať v C-čkovskom programe awk ? Napríklad potrebujem sa hrať s nejakými stĺpcami a pošlem na ne cez execlp awk.
Pokiaľ to nie je v zadaní explicitne povolené, tak nie.
Systémové volanie exec môžete použiť len v tých zadaniach, v ktorých sa vyžaduje spúšťanie programov. V žiadnom prípade nemôžete časť problému riešiť v C-shelli alebo awk.
Volania exec, execlp - spúšťanie externých programov
Chcel by som spustiť program find pomocou execl, ale neviem nájsť cestu, kde sa find nachádza (v /bin to nie je). Dá sa takto find vôbec spustiť ?
Okrem execl existuje aj volanie execlp, ktoré sa pokúsi vyhľadať spúšťaný program v adresároch uvedených v premennej path.
Keď chcete zistiť, kde sa spúšťaný program nachádza, skúste príkazy whereis, which.
Volania exec, execlp - spúšťanie externých programov
Ako sa v príkazoch execv a execvp zadávajú argumenty programu ?
int execv(const char *path, char *const argv[])
- argument execv je vlastne presne to, čo dostane funkcia main ako 2. argument (argv). Čiže treba vytvoriť pole pointrov na jednotlivé parametre a ukončiť ho nulovým pointrom. (Mimochodom je to veľmi elegantné na riešenie zadaní, kde máte spúšťať programy s parametrami oddelenými bodkočiarkou.)
Volania exec, execlp - spúšťanie externých programov
Treba pri zadaniach, kde sa volá externý program, ošetrovať aj jeho chybový výstup ?
(t.j. či treba jeho chybový výstup vypisovať vo formáte Error:’…’)
Pokiaľ to nie je v zadaní explicitne uvedené, tak nie. Formátovať musíte len svoje vlastné chybové výpisy.