|
4. Sisteme
de fisiere. Apeluri sistem si functii de biblioteca pentrulucrul cu fisiere
si directoare
1. Sisteme de fisiere
Fiecare sistem de operare are un mod propriu de organizare si exploatare
a informatiei stocate pe suporturile de memorare fizice. Principiile, regulile
si structurile care realizeaza acest lucru compun sistemul de fisiere
caracteristic sistemului de operare respectiv.
In general, din punctul de vedere al utilizatorului, sistemele de fisiere
prezinta o organizare bazata pe conceptele de fisier si director
(catalog). Fisierele sunt entitati care incapsuleaza informatia de
un anumit tip, iar directoarele grupeaza in interiorul lor fisiere si alte
directoare. Orice fisier sau director poate fi identificat prin numele
sau, indicat in mod absolut, ca
nume de cale sau relativ, fata de directorul curent.
In cazul discurilor fixe (hard-disk-uri) si in cel al dischetelor,
informatia se memoreaza folosind proprietatile magnetice ale acestora.
Hard-disk-ul contine in interior mai multe platane
ce pot memora informatie, iar discheta este formata dintr-un singur
disc flexibil (cu ambele fete magnetizate). O fata a unui disc este impartita
in piste, care sunt cercuri concentrice in care poate fi memorata
informatia. Pistele sunt impartite la randul lor in sectoare, un
sector memorand o cantitate fixa de informatie (de obicei 512 octeti).
Citirea si scrierea informatiei
pe un disc se face la nivel de blocuri de date. Un bloc
(cluster) poate fi format dintr-un singur sector (cum se intampla
la dischete) sau din mai multe (ca la hard-disk-uri).
Un hard-disk poate fi impartit de utilizator in partitii, fiecare
partitie comportandu-se, la nivel utilizator, ca un disc de sine statator.
Partitia memoreaza sistemul de fisiere, de unde
rezulta ca pe acelasi disc fizic pot fi intalnite mai multe sisteme
de fisiere. Pentru calculatoarele personale obisnuite (PC), informatiile
referitoare la partitii se memoreaza la inceputul discului, in asa-numita
tabela
de partitii. Aceasta contine 4 intrari in care memoreaza pozitiile,
dimensiunile si tipurile partitiilor de pe disc. Partitiile memorate tabela
de la inceputul discului se numesc partitii primare, care pot fi,
evident, cel mult 4 la numar. Este posibil, insa, ca in interiorul oricarei
partitii primare sa se creeze cate o noua tabela de partitii, referind
partitii care fizic se afla in interiorul partitiei curente si care se
numesc partitii extinse.
In cele ce urmeaza, vom trece in revista principalele caracteristici
ale sistemelor de fisiere caracteristice pentru doua sisteme de operare:
MS-DOS (Windows) si Unix.
1.1 Sistemul de fisiere in MS-DOS
1.1.1 Organizarea discurilor in MS-DOS
Primul sector al partitiei sau discului care contine sistemul se
numeste
sectorul de boot. Acesta contine urmatoarele informatii:
Offset |
Dimensiune (octeti) |
Continut |
+00h |
3 |
JMP adresa. Salt la rutina de incarcare a sistemului de operare |
+03h |
8 |
Numele producatorului si versiunii |
+0Bh |
2 |
Numarul de octeti pe sector |
+0Dh |
1 |
Numarul de sectoare pe cluster |
+0Eh |
2 |
Numarul de sectoare rezervate (inaintea FAT) |
+10h |
1 |
Numarul de FAT-uri |
+11h |
2 |
Numarul maxim de intrari in directorul radacina |
+13h |
2 |
Numarul total de sectoare |
+15h |
1 |
Media descriptor |
+16h |
2 |
Numarul de sectoare dintr-un FAT |
+18h |
2 |
Numarul de sectoare pe pista |
+1Ah |
2 |
Numarul de capete de citire/scriere |
+1Bh |
2 |
Numarul de sectoare ascunse |
+1Dh |
...
|
Codul de bootare
|
Directoarele sunt memorate ca structuri speciale, ca tabele in care
fiecare intrare reprezinta un fisier. De fapt, un director este memorat
ca un fisier obisnuit, dar care contine informatii despre alte fisiere.
Exista un director radacina, memorat dupa tabela de alocare a fisierelor
(FAT), care are o dimensiune limitata.
Structura unei intrari in director este:
Offset |
Dimensiune |
Continut |
+00h |
8 |
Numele fisierului |
+08h |
3 |
Extensia numelui de fisier |
+0Bh |
1 |
Atribute |
+0Ch |
0Ah |
Rezervat |
+16H |
2 |
Ora ultimei modificari a fisierului |
+18h |
2 |
Data ultimei modificari a fisierului |
+1Ah |
2 |
Numarul primului cluster ocupat de fisier |
+1Ch |
4 |
Dimensiunea fisierului (in octeti) |
Tabela de alocare a fisierelor (File Allocation Table - FAT)
FAT este o structura care este folosita pentru localizarea datelor care
apartin unui fisier. Ea este, de fapt, o structura de tip tablou care memoreaza
in interiorul ei liste inlantuite care indica clustererele ce compun fisierele.
Fiecare locatie din FAT are 12 biti la dischete, 16 biti la partitiile
MS-DOS obisnuite (FAT16) si 32 biti la partitiile FAT32 recunoscute de
catre Windows 95 OSR2 si Windows 98. Primul octet din FAT contine un octet
de identificare numit media descriptor. Urmatorii 5 octeti (FAT12)
sau 7 octeti (FAT16) sau 15 octeti (FAT32) contin valoarea 0FFh.
Celelalte intrari din FAT corespund fiecare unui cluster de pe disc
(clusterele se numara de la spatiul imediat urmator FAT-ului). Astfel,
intrarea 1 din FAT corespunde clusterului 1, intrarea 2 clusterului 2,
s.a.m.d.
Fiecare intrare in FAT memoreaza numarul urmatorului cluster din
fisierul din care face parte clusterul care corespunde intrarii. Numarul
primului cluster al unui fisier este memorat, dupa cum s-a vazut deja,
in intrerea in director corespunzatoare fisierului respectiv. Se vede ca
numarul de biti pe care este reprezentata o intrare in FAT limiteaza, astfel,
numarul maxim de clustere pe disc.
Exemplu: Fie fisierul abc.txt care incepe in clusterul 5 si fisierul
xyz.exe care incepe in clusterul 4. O posibila organizare a spatiului ocupat
de aceste fisiere este prezentata mai jos:
.
1.2 Sistemul de fisiere in UNIX
1.2.1 Organizarea discurilor in Unix
Spatiul fiecarei partitii Unix contine urmatoarele zone:
Bloc
Incarcare |
Super-bloc |
Zona noduri
index |
Swapping |
Continut |
-
Blocul de incarcare (boot block)contine programele care realizeaza
incarcarea partii rezidente a sistemului de operare Unix.
-
Superblocul contine informatii generale despre sistemul de fisiere
de pe disc: inceputul zonelor urmatoare, inceputul zonelor libere de pe
disc.
-
Zona de noduri index are o dimensiune fixata la creareea sistemului
de fisiere si contine cate o intrare pentru fiecare fisier ce poate fi
creat pe acest suport
-
Zona pentru swapping (daca exista) este rezervata pentru pastrarea
imaginilor proceselor atunci cand sunt eliminate temporar din memorie pentru
a face loc altor procese. De obicei, insa, pentru zona de swap se folosesc
partitii distincte.
-
Ultima zona contine blocurile care memoreaza fisierele propriu-zise.
Intrarile in director au o structura foarte simpla, continand doar
doua campuri:
-
numele fisierului
-
numarul nodului index asociat fisierului
1.2.1.1 Structura nodurilor index
Un nod index (i-node) contine informatiile esentiale despre fisierul
caruia ii corespunde. Exista cate un singur nod index pentru fiecare fisier.
Este posibil sa intalnim mai multe intrari in director indicand acelasi
nod index (sistemul de fisiere din Unix accepta crearea de legaturi multiple).
Informatia din nodul index cuprinde:
-
identificatorul utilizatorului: uid (user-id.). Identifica
proprietarul fisierului
-
identificatorul de grup al utilizatorului
-
drepturile de acces la fisier. Drepturile sunt de trei tipuri (r-read,
w-write,
x-execute) si sunt grupate pe trei categorii:
-
user - drepturile proprietarului fisierului
-
group - drepturile utilizatorilor din grupul proprietarului
-
others - drepturile tuturor celorlalti utilizatori
-
timpul ultimului acces la fisier
-
timpul ultimei actualizari a fisierului
-
timpul ultimului acces pentru actualizarea nodului index
-
codul fisierului (tipul fisierului). Fisierele pot fi: fisiere obisnuite
(-), directoare (d), periferice (c) etc.
-
lungimea fisierului (in octeti)
-
contorul de legaturi al fisierului. Reprezinta numarul de legaturi
existente spre acest nod index. Este utilizat la operatia de stergere a
nodului index.
-
lista de blocuri care contin fisierul
Lista de blocuri de pe disc care contin fisierul se realizeaza printr-un
tablou cu 13 intrari. Primele 10 intrari contin direct adresele de bloc
(cluster) pentru primele 10 blocuri ale fisierului. A unsprezecea intrare
din aceasta lista este adresa unui bloc, rezervat fisierului, al carui
continut este, insa, interpretat ca lista de adrese de blocuri. Se spune
ca aceste blocuri sunt adresate prin indirectare simpla. Intrarea
a 12-a contine un bloc al carui continut consta in adrese de blocuri, care
acestea
contin adrese de blocuri de date (indirectare dubla). In mod analog,
intrarea cu numarul 13 determina o indirectare tripla.
1.2.2 Legaturi si fisiere speciale
Sistemul de fisiere din UNIX permite crearea asa-numitelor legaturi la
fisiere. O asemenea legatura (link) este vazuta de catre utilizator
ca un fisier cu un nume propriu, dar care in realitate refera un alt fisier
de pe disc. Orice operatie care se executa asupra fisierului legatura (mai
putin stergerea) isi va avea efectul de fapt asupra fisierului indicat
de legatura. Daca este solicitata stergerea, efectul depinde de tipul
legaturii respective.
Legaturile sunt de doua tipuri:
-
fizice (hard links)
-
simbolice (symbolic links)
Legaturile din prima categorie se realizeaza prin introducerea de intrari
in director care pointeaza spre acelasi nod index, si anume cel al fisierului
indicat. Cand spre fisier este stearsa si ultima intrare in director care
il indica, fisierul in sine va fi sters si el. Legaturile de acest tip
au dezavantajul ca nu pot indica nume de directoare si nici fisiere din
alte partitii decat cea pe care se afla.
Legaturile simbolice sunt de fapt fisiere distincte, marcate cu un cod
special, care au ca si continut numele complet al fisierului indicat. Stergerea
lor nu afecteaza fisierul. Pot referi directoare, precum si fisiere si
directoare din alta partitie sau alt disc, dar au dezavantajul ca pentru
ele (fiind fisiere) trebuie creat un nod index separat si, in plus, ocupa
spatiu pe disc prin continutul lor.
Crearea legaturilor spre fisiere sau directoare se face cu ajutorul
comenzii ln.
ln fisier_indicat nume_legatura - creeaza o legatura "fizica"
ln -s fisier_indicat nume_legatura - creeaza o legatura simbolica
Pe langa legaturi, in Unix exista si alte fisiere speciale. Tipul acestora
poate fi observat citind primul caracter afisat de comanda ls -l
Astfel, avem:
-
Fisiere obisnuite
-
Directoare. Dupa cum am vazut, sunt fisiere care, avand un format special,
grupeaza fisiere
-
Fisiere speciale care corespund unor dispozitive orientate pe caractere
-
Fisiere speciale care corespund unor dispozitive orientate pe blocuri
-
Fisiere FIFO
-
Legaturi simbolice
Fisierele speciale evidentiate la punctele 3 si 4 reprezinta metoda prin
care sistemul Unix abstractizeaza dispozitivele de intrare-iesire si alte
dipozitive din sistemul de calcul. Toate aceste fisiere se gasesc in directorul
/dev.
Spre exemplu, fiecarei unitati de disc ii corespunde cate un fisier
in directorul /dev. In Linux, primei unitati de dischete ii corespunde
fisierul /dev/fd0, celei de-a doua /dev/fd1, s.a.m.d. Primului
hard-disk cu interfata IDE din sistem ii corespunde fisierul special /dev/hda,
iar primei sale partitii fisierul /dev/hda1. A doua partitie de
pe primul disc are ca si
corespondent fisierul /dev/hda2, al doilea hard-disk IDE se
refera cu /dev/hdb, s.a.m.d.
1.2.3 Montarea sistemelor de fisiere
Fisierele speciale care indica unitati de disc sau partitii sunt folosite
in operatia numita montare a sistemelor de fisiere. Sistemul de
operare Unix permite montarea intr-un director a unui sistem de fisiere
aflat pe un disc sau o partitie. Aceasta inseamna ca, dupa montare, in
directorul respectiv se va afla intreaga structura de fisiere si directoare
de pe sistemul de fisiere respectiv. Mecanismul este deosebit de puternic,
deoarece ofera posibilitatea de a avea o structura de directoare unitara,
care grupeaza fisiere de pe mai multe partitii sau discuri. Daca se adauga
si sistemul de fisiere NFS (Network File System), aceasta
structura de directoare va putea contine si sisteme de fisiere montate
de la distanta (de pe alta masina)
Montarea unui sistem de fisiere se face cu comanda mount. Data
fara nici un parametru, ea afiseaza sistemele de fisiere montate in momentul
respectiv in sistem. O alta forma a ei este urmatoarea:
mount fisier-special director
care monteaza un disc sau o partitie intr-un director dat; sau
mount -t tip fisier-special director
cu acelasi efect, doar ca se specifica in clar tipul sistemului de fisiere
care se monteaza. Diferitele variante de Unix cunosc mai multe sau mai
putine tipuri de sisteme de fisiere. Spre exemplu, Linux cunoaste, printre
altele, urmatoarele:
-
minix - sistemul de fisiere al sistemului de operare MINIX
-
ext2 - Second-Extended File System - sistemul caracteristic
Linux
-
msdos - sistemul de fisiere DOS FAT16 sau FAT12
-
vfat - sistemul de fisiere DOS cu extensia pentru nume lungi introdusa
de Windows 95
-
iso9660 - sistem de fisiere pentru CD-ROM (cel mai raspandit)
cu o serie de extensii ale sale
-
proc - un sistem de fisiere virtual ale carui componente furnizeaza
informatii despre starea sistemului
De obicei, montarea de sisteme de fisiere poate fi facuta numai de catre
utilizatorul root (cel mai privilegiat utilizator, administratorul
sistemului), dar se poate permite si utilizatorilor obisnuiti sa monteze
anumite partitii sau unitati de disc.
Exemplu:
Montarea unei dischete introdusa in prima unitate de dischete, care
contine si fisiere cu nume lungi create in Windows se face astfel
mount /dev/fd0 diskA
unde diskA este numele directorului in care se va monta discheta,
aflat in directorul curent.
Important: Orice sistem de fisiere montat de pe
o unitate de disc care permite inlaturarea discului respectiv trebuie demontat
inainte de a scoate discul. De asemenea, inainte de inchiderea sau repornirea
calculatorului, trebuie de-montate si sistemele de fisiere de pe discurile
fixe (in Linux, aceasta din urma operatie se efectueaza automat la restartarea
sistemului prin apasarea simultana a tastelor Ctrl+Alt+Del). De-montarea
fisierelor se face cu comanda
umount fisier-special
sau
umount director
(unde director este numele directorului in care a fost montat sistemul
de fisiere).
2. Apeluri sistem si functii de biblioteca pentru
lucrul cu fisiere
Orice sistem de operare pune la dispozitia programatorilor
o serie de servicii prin intermediul carora acestora li se ofera
acces la resursele hardware si software gestionate de sistem: lucrul cu
tastatura, cu discurile, cu dispozitivul de afisare, gestionarea fisierelor
si directoarelor etc. Aceste servicii se numesc apeluri sistem.
De cele mai multe ori, operatiile pe care ele le pot face asupra resurselor
gestionate sunt operatii simple, cu destul de putine facilitati. De aceea,
frecvent, se pot intalni in bibliotecile specifice limbajelor de programare
colectii de functii mai complicate care gestioneaza resursele respective,
dar oferind programatorului niveluri suplimentare de abstractizare a operatiilor
efectuate, precum si importante facilitati in plus. Acestea sunt functiile
de biblioteca. Trebuie subliniat faptul ca functiile de biblioteca
cu ajutorul carora se poate gestiona o anumita resursa sunt implementate
folosind chiar functiile sistem corespunzatoare, specifice sistemului de
operare.
In acest document vor fi prezentate functiile
sistem pe care le pun la dispozitie sistemele de operare MS-DOS si UNIX
pentru lucrul cu fisiere. Se va presupune in continuare ca limbajul de
programare utilizat este C si ca sunt cunoscute toate caracteristicile
si facilitatile acestui limbaj. Vor fi trecute in revista, de asemenea,
cateva functii de biblioteca C care servesc aceluiasi scop.
2.1 Apeluri sistem pentru lucrul cu fisiere
Apelurile sistem care vor fi discutate aici sunt caracteristice atat sistemului
de operare UNIX cat si MS-DOS. Operatiile care pot fi aplicate fisierelor
folosind aceste functii se refera la deschiderea fisierelor, scrierea si
citirea de blocuri de date in si din fisiere, mutarea si copierea fisierelor
etc.
Pentru a putea actiona asupra unui fisier, este nevoie inainte de toate
de o metoda de a identifica in mod unic fisierul. In cazul functiilor discutate,
identificarea fisierului se face printr-un asa-numit descriptor de fisier
(file descriptor). Acesta este un numar intreg care este asociat fisierului
in momentul deschiderii acestuia.
2.1.1 Functiile open si close
Deschiderea unui fisier este operatia prin care fisierul este pregatit
pentru a putea fi prelucrat in continuare. Aceasta operatie se realizeaza
prin intermediul functiei open:
int open(const char *pathname, int oflag, [, mode_t
mode]);
Functia returneaza -1 in caz de eroare. In caz contrar, ea returneaza descriptorul
de fisier asociat fisierului deschis.
Parametri:
-
pathname - contine numele fisierului
-
oflag - optiunile de deschidere a fisierului. Este, in realitate
un sir de biti, in care fiecare bit sau grupa de biti are o anumita semnificatie.
Pentru fiecare astfel de semnificatie exista definite in fisierul header
C fcntl.h cate o constanta. Constantele se pot combina folosind
operatorul '|' (sau logic pe biti) din C, pentru a seta mai multi
biti (deci a alege mai multe optiuni) in parametrul intreg oflag.
Iata cateva din aceste constante:
-
O_RDONLY - deschidere numai pentru citire
-
O_WRONLY - deschidere numai pentru scriere
-
O_RDWR - deschidere pentru citire si scriere
-
O_APPEND - deschidere pentru adaugare la sfarsitul fisierului
-
O_CREAT - crearea fisierului, daca el nu exista deja; daca e folosita cu
aceasta optiune, functia open trebuie sa primeasca si parametrul
mode.
-
O_EXCL - creare "exclusiva" a fisierului: daca s-a folosit O_CREAT si fisierul
exista deja, functia open va returna eroare
-
O_TRUNC - daca fisierul exista, continutul lui este sters
-
mode - se foloseste numai in cazul in care fisierul este creat si
specifica drepturile de acces asociate fisierului. Acestea se obtin prin
combinarea unor constante folosind operatorul sau ('|'), la fel
ca si la optiunea precedenta. Constantele pot fi:
-
S_IRUSR - drept de citire pentru proprietarul fisierului (user)
-
S_IWUSR - drept de scriere pentru proprietarul fisierului (user)
-
S_IXUSR - drept de executie pentru proprietarul fisierului (user)
-
S_IRGRP - drept de citire pentru grupul proprietar al fisierului
-
S_IWGRP - drept de scriere pentru grupul proprietar al fisierului
-
S_IXGRP - drept de executie pentru grupul proprietar al fisierului
-
S_IROTH - drept de citire pentru ceilalti utilizatori
-
S_IWOTH - drept de scriere pentru ceilalti utilizatori
-
S_IROTH - drept de executie pentru ceilalti utilizatori
Pentru crearea fisierelor poate fi folosita si functia
creat (const char *pathname, mode_t mode)
echivalenta cu specificarea optiunilor O_WRONLY | O_CREAT | O_TRUNC la
functia open.
Dupa utilizarea fisierului, acesta trebuie inchis, folosind functia
int close (int filedes)
in care filedes este descriptorul de fisier obtinut la open.
2.1.2 Functiile read si write
Citirea datelor dintr-un fisier deschis se face cu functia
ssize_t read(int fd, void *buff, size_t nbytes)
Functia citeste un numar de exact nbytes octeti de la pozitia curenta
in fisierul al carui descriptor este fd si ii pune in zona de memorie
indicata de pointerul buff.
Este posibil ca in fisier sa fie de citit la un moment dat mai putin
de nbytes octeti (de exemplu daca s-a ajuns spre sfarsitul fisierului),
astfel ca functia read va pune in buffer doar atatia octeti cati poate
citi. In orice caz, functia returneaza numarul de octeti cititi din
fisier, deci acest lucru poate fi usor observat.
Daca s-a ajuns exact la sfarsitul fisierului, functia returneaza zero,
iar in caz de eroare, -1.
Scrierea datelor se face cu
ssize_t write(int fd, void *buff, size_t nbytes)
Functia scrie in fisier primii nbytes octeti din bufferul indicat
de buff. Returneaza -1 in caz de eroare.
2.1.3 Functia lseek
Operatiile de scriere si citire in si din fisier se fac la o anumita pozitie
in fisier, considerata pozitia curenta. Fiecare operatie de citire, de
exemplu, va actualiza indicatorul pozitiei curente incrementand-o cu numarul
de octeti cititi. Indicatorul pozitiei curente poate fi setat si in mod
explicit, cu ajutorul functiei lseek:
off_t lseek(int fd, off_t offset, int pos)
Functia pozitioneaza indicatorul la deplasamentul offset in fisier,
astfel:
-
daca parametrul pos ia valoarea SEEK_SET, pozitionarea se face relativ
la inceputul fisierului
-
daca parametrul pos ia valoarea SEEK_CUR, pozitionarea se face relativ
la pozitia curenta
-
daca parametrul pos ia valoarea SEEK_END, pozitionarea se face relativ
la sfarsitul fisierului
Parametrul offset poate lua si valori negative si reprezinta deplasamentul,
calculat in octeti.
In caz de eroare, functia returneaza -1.
2.1.4 Alte functii
-
int mkdir(const char *pathname, mode_t mode) - creeaza
un director
-
int rmdir(const char *pathname) - sterge un director
Observatie: La orice folosire
a unei functii sistem este foarte important sa se testeze valoarea returnata
de aceasta. Daca apelul functiei s-a incheiat cu eroare, programul trebuie
sa recunoasca acest caz si sa actioneze in consecinta, de exemplu prin
tiparirea unui mesaj de eroare si eventual terminarea executiei.
2.2 Functii de biblioteca
In biblioteca standard C exista cateva functii pentru gestionarea fisierelor.
Acestea folosesc pentru identificarea fisierelor un descriptor reprezentat
de o structura de date, FILE.
2.2.1 Deschiderea si inchiderea unui fisier
FILE *fopen(const char *filename, const char *mode)
Functia deschide fisierul indicat prin filename, creeaza o structura
FILE continand informatii despre fisier si returneaza un pointer catre
aceasta. Acest pointer va fi elementul care va putea fi folosit in continuare
pentru accesarea fisierului. Parametrul mode este un sir de caractere
care indica modul de deschidere a fisierului. "r" semnifica deschidere
pentru citire, "w" deschidere pentru scriere. Poate fi specificat si tipul
fisierului: "t" pentru fisier text, "b" pentru fisier binar. Optiunile
pot fi combinate, de exemplu sub forma "r+t".
Inchiderea fisierului se face cu
fclose(FILE *stream)
unde stream este pointerul spre structura FILE obtinut la deschiderea
fisierului.
2.2.2 Operatii asupra fisierelor
-
int fprintf(FILE *stream, const char *format, ...); - scriere
in fisier cu formatare; sirul de caractere care specifica formatul este
similar celui de la instructiunea printf.
-
int fscanf(FILE *stream, const char *format, ...); - citire
din fisier, asemanator cu functia scanf.
-
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
- citeste din fisierul indicat de stream un numar de nmemb
elemente, fiecare de dimensiunea size, si le pune in zona de memorie
indicata de ptr.
-
size_t fwrite( void *ptr, size_t size, size_t nmemb, FILE
*stream); - scrie in fisierul indicat de stream un numar
de nmemb elemente, fiecare de dimensiunea size, pe care le
ia din zona de memorie indicata de ptr.
Consultati paginile de manual
corespunzatoare apelurilor sistem si functiilor de biblioteca discutate,
precum si functiilor inrudite cu acestea. Apelurile sistem sunt tratate
in sectiunea 2 a manualului Unix (man 2 nume_functie),
iar functiile de biblioteca in sectiunea 3.
3. Gestionarea directoarelor
Accesul la informatiile memorate in directoare se face cu ajutorul unor
functii speciale, cu ajutorul carora se pot afla numele fisierelor continute
si informatii despre acestea (dimensiune, data crearii, drepturile aferente
etc).
Daca in ceea ce priveste gestionarea fisierelor puteau fi intalnite
aspecte comune in cazurile sistemelor de operare DOS si UNIX, modul in
care se exploateaza directoarele (din perspectiva programatorului) difera
substantial.
3.1 Gestionarea directoarelor in MS-DOS
3.1.1 Functiile findfirst si
findnext
Aceste functii utilizeaza ca intermediar o structura de date numita struct
ffblk, care contine informatii despre un anumit fisier:
struct ffblk {
char ff_reserved[21];
char ff_attrib; /*atributele fisierului*/
int ff_ftime; /*timpul crearii fisierului*/
int ff_fdate; /*data crearii fisierului*/
long ff_fsize; /*dimensiunea fisierului (in
octeti)*/
char ff_fname[13]; /*numele si extensia fisierului
(cu punct)*/
}
-
int findfirst(const char *pathname, struct ffblk *ffblk, int attrib)
-
Gaseste primul fisier care se potriveste tiparului dat in pathname
(tipar care poate contine caracterele * si ?) si initializeaza structurile
de date folosite intern de catre functiile de cautare
de fisiere. Functia va completa o structura ffblk cu
informatii despre primul fisier gasit. Adresa acestei structuri trebuie
data de catre utilizator in parametrul ffblk. Parametrul attrib
specifica atributele de cautare. (Pentru mai multe detalii, consultati
help-urile compilatoarelor de C pentru MS-DOS).
-
int findnext(struct ffblk *ffblk)
-
Primul fisier care corespunde unui anumit tipar poate fi gasit cu findfirst.
Urmatoarele fisiere care corespund aceluiasi tipar pot fi gasite apeland
succesiv functia findnext. Aceasta primeste ca parametru structura
ffblk folosita la findfirst, va gasi fisierul cautat si va
completa structura ffblk cu informatiile specifice fisierului gasit.
3.2. Gestionarea directoarelor in UNIX
3.2.1. Aflarea atributelor fisierelor
int stat(const char *file_name, struct stat *buf);
int fstat(int filedes, struct stat *buf);
int lstat(const char *file_name, struct stat *buf);
Functia stat primeste ca parametru un nume de fisier (cale) si scrie
o structura stat la adresa buf , care contine informatii despre fisierul respectiv.
Structura stat are urmatoarea forma:
struct stat
{
dev_t st_dev; /* device */
ino_t st_ino; /* inode */
umode_t st_mode; /* protection */
nlink_t st_nlink; /* number of hard links */
uid_t st_uid; /* user ID of owner */
gid_t st_gid; /* group ID of owner */
dev_t st_rdev; /* device type (if inode device) */
off_t st_size; /* total size, in bytes */
unsigned long st_blksize; /* blocksize for filesystem I/O */
unsigned long st_blocks; /* number of blocks allocated */
time_t st_atime; /* time of last access */
time_t st_mtime; /* time of last modification */
time_t st_ctime; /* time of last change */
};
Pointerul care indica zona de memorie in care functia stat va
returna aceste informatii trebuie dat ca al doilea parametru al functiei.
Zona de memorie trebuie in prealabil rezervata (prin malloc) pentru
a putea memora structura stat.
Functia fstat are acelasi efect, cu deosebirea ca ea primeste
ca argument un descriptor de fisier, si nu numele acestuia, deci se poate
aplica doar fisierelor in prealabil deschise.
Functia lstat este asemanatoare cu stat, cu diferenta
ca, daca este aplicata unei legaturi simbolice, informatiile returnate
se vor referi la legatura, si nu la fisierul indicat.
3.2.2 Functii de biblioteca pentru citirea directoarelor
Directoarele sunt, in esenta, fisiere cu un format special. Sistemul de
operare UNIX pune la dispozitia programatorului un set de apeluri sistem
care ofera posibilitatea de a citi continutul directoarelor, accesand astfel
informatii despre fisierele si directoarele continute. Folosind aceste
apeluri sistem, biblioteca standard C defineste un set de functii care
se conformeaza standardului POSIX si care ofera aceleasi facilitati. Fiind
recomandabil sa se utilizeze, in locul apelarii directe a functiilor sistem,
functiile de biblioteca , in continuare vor fi prezentate numai acestea
din urma.
DIR *opendir(const char *name);
struct dirent *readdir(DIR *dir);
void rewinddir(DIR *dir);
int closedir(DIR *dir);
Conform specificatiilor POSIX, structura dirent contine un camp
char d_name[];
de dimensiune nespecificata, cu cel mult NAME_MAX charactere
exclusiv caracterul de terminare (NULL). Folosirea altor campuri
existente in aceasta structura dauneaza portabilitatii programului. Campul
d_name contine numele unei intrari in director (nume de fisier,
director etc.).
Structura DIR este o structura utilizata intern de cele patru
functii. Structura va fi returnata (initializata) de opendir si
trebuie transmisa ca parametru celorlalte functii.
Inspectarea fisierelor dintr-un director se face astfel:
-
se "deschide" directorul dorit cu functia opendir.
-
se citeste, pe rand, cate o intrare in director, apeland succesiv functia
readdir. Fiecare apel al aceste functii va returna un pointer la o structura dirent,
in care se vor gasi informatii despre intrarea in director citita. Intrarile
in director vor fi parcurse, astfel, una dupa alta, pana cand se ajunge
la ultima intrare. In momentul in care nu mai exista intrari in director
de citit, functia readdir va returna NULL. De asemenea, in caz de eroare, functia va returna tot NULL, dar atunci va si pozitiona valoarea lui
errno in mod corespunzator.
Dupa cum a fost aratat mai sus, singura informatie care poate fi extrasa
(conform POSIX) din structura dirent este numele intrarii in director.
Toate celelalte informatii despre intrarea citita se pot afla apeland in
continuare functiile stat, fstat sau lstat.
-
in final. directorul este inchis, folosind closedir.
Consultati paginile de manual
corespunzatoare acestor functii.
Anexa: Alte functii pentru lucrul cu directoare si
fisiere
Consultati paginile de manual corespunzatoare urmatoarelor functii,
precum si cele ale functiilor inrudite:
-
int link(const char *oldpath, const char *newpath); - creeaza
legaturi fixe spre fisiere
-
int symlink(const char *oldpath, const char *newpath); -
creeaza legaturi simbolice spre fisiere sau directoare
-
int unlink(const char *pathname); - sterge o intrare
in director (legatura, fisier sau director)
-
int rename(const char *oldpath, const char *newpath); -
redenumire / mutare de fisiere
-
int rmdir(const char *pathname); - stergere de directoare
-
int chdir(const char *path); - schimbarea directorului
curent
-
char *getcwd(char *buf, size_t size); - determinarea directorului
curent
Tema pentru acasa:
Sa se scrie un program C pentru Unix, apelabil din linia de comanda
astfel:
copytree cale1 cale2
care copiaza directorul cale1, cu tot subarborele sau de directoare
in destinatia cale2. Daca exista deja cale2, se va genera
un mesaj de eroare. Daca in sursa sunt intalnite legaturi simbolice,
la destinatie se vor crea legaturi simbolice care refera acelasi
fisier ca originalul (nu se copiaza fisierul indicat!).
Autor: Dan Cosma
|
|